/* Copyright 1998 Acorn Computers Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*---------------------------------------------------------------------------*/
/* File:    sprite.c                                                         */
/* Purpose: Sprite handling routines                                         */
/* Author:  Richard Leggett                                                  */
/* History: 29-Oct-97: RML: Begun.                                           */
/*                                                                           */
/* Copyright  1997 Acorn Computers Ltd., Cambridge, UK.                     */
/*---------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "swis.h"
#include "Global/Sprite.h"
#include "Interface/HighFSI.h"
#include "toolbox.h"
#include "sprite.h"
#include "main.h"
#include "msgtrans.h"

/* Sprite structures */
typedef struct
{
  int size;
  int number;
  int sproff;
  int freeoff;
} sprite_area;

typedef struct
{
  int  next;
  char name[12];
  int  width;
  int  height;
  int  lbit;
  int  rbit;
  int  image;
  int  mask;
  int  mode;
  int  palette[512];
  char img[4];
} sprite_header;


/* Global variables */
static int prev1;
static int prev2;
static int prev3;
static char* save_area;


/*---------------------------------------------------------------------------*
 * sprite_size_of_spritearea                                                 *
 *                                                                           *
 * Given a sprite's filename, calculate how large a chunk of memory is       *
 * required to hold it.                                                      *
 *                                                                           *
 * In: filename -> filename string.                                          *
 *                                                                           *
 * On exit: areasize -> size of area required.                               *
 *---------------------------------------------------------------------------*/

_kernel_oserror* sprite_size_of_spritearea(char* filename, int* areasize)
{
    _kernel_oserror *e;
    int              type, length;

    e=_swix(OS_File, _INR(0,1)|_OUT(0)|_OUT(4), OSFile_ReadNoPath, filename, &type, &length);
    if (e) return e;
    if ((!type) || (!length)) return msgtrans_errorlookup("TileNotExist");
    *areasize = length+8;
    return NULL;
}


/*---------------------------------------------------------------------------*
 * sprite_init_and_load                                                      *
 *                                                                           *
 * Initialise a sprite area and load a file into it.                         *
 *                                                                           *
 * In: filename -> filename string.                                          *
 *     buffer -> buffer to load file.                                        *
 *     size = size of buffer.                                                *
 *---------------------------------------------------------------------------*/

_kernel_oserror* sprite_init_and_load(char* filename, void* buffer, int size)
{
    _kernel_oserror *e;
    int*             sprite_area = (int*)buffer;

    sprite_area[0] = size;
    sprite_area[1] = 16;

    e = _swix(OS_SpriteOp, _INR(0,1), 256+SpriteReason_ClearSprites, buffer);

    if (!e) e = _swix(OS_SpriteOp, _INR(0,2), 256+SpriteReason_LoadSpriteFile, buffer, filename);

    return e;
}


/*---------------------------------------------------------------------------*
 * sprite_find_address_of                                                    *
 *                                                                           *
 * Find the address in memory of a sprite with a given name.                 *
 *                                                                           *
 * In: buffer -> sprite area which contains the sprite.                      *
 *     sprite_name -> sprite name string.                                    *
 *                                                                           *
 * On exit: address-> address of sprite in memory.                           *
 *---------------------------------------------------------------------------*/

_kernel_oserror* sprite_find_address_of(void* buffer, char* sprite_name, char**address)
{
    _kernel_oserror *e;
    void*            dest;

    e = _swix(OS_SpriteOp, _INR(0,2)|_OUT(2), 256+SpriteReason_SelectSprite, buffer,
                                              sprite_name, &dest);
    *address = dest;

    return e;
}


/*---------------------------------------------------------------------------*
 * sprite_generate_colourtrans                                               *
 *                                                                           *
 * Generate a colourtrans table for a sprite being plotted into a 32bpp      *
 * screen mode.                                                              *
 *                                                                           *
 * In: area -> sprite area containing the sprite                             *
 *     header -> sprite header for the sprite                                *
 *                                                                           *
 * On exit: table -> location of colourtrans table.                          *
 *---------------------------------------------------------------------------*/

_kernel_oserror* sprite_generate_colourtrans32(void* area, void* sprite, char** table)
{
    _kernel_oserror *e;
    char*            ctable;
    int              modespec[] = {1, 640, 480, 5, -1, -1};
    int              size;
    /* void*            palette; */

    /*e = _swix(OS_SpriteOp, _INR(0,3)|_OUT(3), 512 + Sprite_CreatePalette,
                                              area,
                                              sprite,
                                              -1,
                                              &palette);
    if (e) return e;
    if (palette == 0) palette=(void*)-1;
    else palette=sprite; */

    e = _swix(ColourTrans_GenerateTable, _INR(0,5)|_OUT(4),
                                         area,
                                         sprite,
                                         modespec,
                                         0,
                                         0,
                                         1+2+16,
                                         &size);
    if (e) return e;

    ctable = malloc(size);
    if (!ctable) return msgtrans_errorlookup("NoMem");

    e = _swix(ColourTrans_GenerateTable, _INR(0,5),
                                         area,
                                         sprite,
                                         modespec,
                                         0,
                                         ctable,
                                         1+2+16);
    *table = ctable;

    return e;
}


/*---------------------------------------------------------------------------*
 * sprite_output_to_sprite                                                   *
 *                                                                           *
 * Direct vdu output to a sprite.                                            *
 *                                                                           *
 * In: area -> spritearea containing sprite.                                 *
 *     header -> header of sprite.                                           *
 *---------------------------------------------------------------------------*/

_kernel_oserror* sprite_output_to_sprite(void* area, void* header)
{
    _kernel_oserror *e;
    int save_area_size;

    e = _swix(OS_SpriteOp, _INR(0,2)|_OUT(3),
                           512+SpriteReason_ReadSaveAreaSize,
                           area,
                           header,
                           &save_area_size);
    if (e) return e;

    save_area = malloc(save_area_size);
    if (!save_area) return msgtrans_errorlookup("NotEnoughMemory");
    memset(save_area, 0, 4);

    e = _swix(OS_SpriteOp, _INR(0,3)|_OUTR(1,3),
                           512+SpriteReason_SwitchOutputToSprite,
                           area,
                           header,
                           save_area,
                           &prev1,
                           &prev2,
                           &prev3);
    return e;
}


/*---------------------------------------------------------------------------*
 * sprite_output_back_to_screen                                              *
 *                                                                           *
 * Direct vdu output back to screen.                                         *
 *---------------------------------------------------------------------------*/

_kernel_oserror* sprite_output_back_to_screen(void)
{
    _kernel_oserror *e;

    e = _swix(OS_SpriteOp, _INR(0,3),
                           512+SpriteReason_SwitchOutputToSprite,
                           prev1,
                           prev2,
                           prev3);
    free(save_area);

    return e;
}


/*---------------------------------------------------------------------------*
 * sprite_return_size                                                        *
 *                                                                           *
 * Return the width and height of a sprite.                                  *
 *                                                                           *
 * In: area -> sprite area containing sprite.                                *
 *     header -> header of sprite we're interested in.                       *
 *                                                                           *
 * On exit: width -> sprite width.                                           *
 *          height -> sprite_height.                                         *
 *---------------------------------------------------------------------------*/

_kernel_oserror* sprite_return_size(void* area, void* header, int* width, int* height)
{
    _kernel_oserror *e;
    int              x, y;

    e = _swix(OS_SpriteOp, _INR(0,2)|_OUTR(3,4), 512+SpriteReason_ReadSpriteSize,
                                                 area, header, &x, &y);
    *width = x;
    *height = y;

    return e;
}
