/*

This program permits to load ROM generated by LCD-Game-Shrinker.

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.

__author__ = "bzhxx"
__contact__ = "https://github.com/bzhxx"
__license__ = "GPLv3"

*/

#ifndef _GW_ROMLOADER_H_
#define _GW_ROMLOADER_H_


#define  ZLIB_MAGIC "ZLIB"
#define  LZMA_MAGIC "LZMA"

/* Different CPU 4bits from SHARP */
#define  ROM_CPU_SM5A        "SM5A_"
#define  ROM_CPU_SM500       "SM500"
#define  ROM_CPU_SM510       "SM510"
#define  ROM_CPU_SM511       "SM511"
#define  ROM_CPU_SM512       "SM512"
#define  ROM_CPU_SM520       "SM520"
#define  ROM_CPU_SM530       "SM530"

/* flags in ROM file */
// use to check 'flag_rendering_lcd_inverted' bit0 in rom_head.flags
// use to check 'flag_segments_4bits'         bit4 in rom_head.flags
// use to check 'flag_background_jpeg'        bit5 in rom_head.flags
// use to check 'flag_segments_2bits'         bit8 in rom_head.flags
#define FLAG_RENDERING_LCD_INVERTED 0x01
#define FLAG_SEGMENTS_4BITS         0x10
#define FLAG_SEGMENTS_2BITS         0x100
#define FLAG_BACKGROUND_JPEG        0x20

// use to determine the piezo buzzer mode bits1..3 in rom_head.flags

#define FLAG_SOUND_MASK 0xE

#define FLAG_SOUND_R1_PIEZO   1 << 1
#define FLAG_SOUND_R2_PIEZO   2 << 1
#define FLAG_SOUND_R1R2_PIEZO 3 << 1
#define FLAG_SOUND_R1S1_PIEZO 4 << 1
#define FLAG_SOUND_S1R1_PIEZO 5 << 1

// use to determine the LCD deflicker mode bits6.7 in rom_head.flags
#define FLAG_LCD_DEFLICKER_MASK 0xC0

#define FLAG_LCD_DEFLICKER_OFF 0x00
#define FLAG_LCD_DEFLICKER_1   0x40
#define FLAG_LCD_DEFLICKER_2   0x80
#define FLAG_LCD_DEFLICKER_3   0xC0

#define GW_ROM_SIZE_MAX 400000U

/* ROM header */
typedef struct gwromheader_s
{
   /* Name of the sharp microcomputers to emulate */
   char cpu_name[8]                ;

   /* Signature of the original ROM name (8 last characters) */
   /* used to check coherency with save */

   char rom_signature[8]           ;

   /* Address counter time used by the program to manage it RTC */
   unsigned char time_hour_address_msb;
   unsigned char time_hour_address_lsb;
   unsigned char time_min_address_msb ;
   unsigned char time_min_address_lsb ;
   unsigned char time_sec_address_msb ;
   unsigned char time_sec_address_lsb ;
   unsigned char time_hour_msb_pm;

   /* spare reserved for futur used */
   unsigned char byte_spare1       ;

   /* Flags to describe hardware : buzzer and lcd deflicker filter */
   unsigned int flags                  ;

   /* Background pixels 320x240 RGB565 */
   unsigned int background_pixel       ;
   unsigned int background_pixel_size  ;

   /* Segments pixels packed Maximum size 320x240 RGB565 */
   unsigned int segments_pixel         ;
   unsigned int segments_pixel_size    ;

   /* Segments offset and dimensions : x,y,height,width */
   unsigned int segments_offset        ;
   unsigned int segments_offset_size   ;
   unsigned int segments_x             ;
   unsigned int segments_x_size        ;
   unsigned int segments_y             ;
   unsigned int segments_y_size        ;
   unsigned int segments_height        ;
   unsigned int segments_height_size   ;
   unsigned int segments_width         ;
   unsigned int segments_width_size    ;

   /* Melody */
   unsigned int melody         ;
   unsigned int melody_size    ;

   /* CPU program */
   unsigned int program       ;
   unsigned int program_size  ;

   /* CPU keyboard mapping */
   unsigned int keyboard      ;
   unsigned int keyboard_size ;

   /* TODO Add support for dual vertical screen */
   // hook on segments to monitor
   // 2nd background set when the hook select the upper screen
   // 2nd segments set when the hook select the upper screen

} gwromheader_t;

typedef struct
{
   gwromheader_t header;
   unsigned char data[GW_ROM_SIZE_MAX];
   unsigned char  *rom_base;
   unsigned short *background;
   unsigned char  *segments;
   unsigned short *segments_x;
   unsigned short *segments_y;
   unsigned short *segments_width;
   unsigned short *segments_height;
   unsigned int   *segments_offset;
   unsigned char  *program;
   unsigned char  *melody;
   unsigned int   *keyboard;
} gwrom_t;

extern gwrom_t *gwrom;
#define gw_head gwrom->header
#define GW_ROM gwrom->data
#define gw_rom_base gwrom->rom_base
#define gw_background gwrom->background
#define gw_segments gwrom->segments
#define gw_segments_x gwrom->segments_x
#define gw_segments_y gwrom->segments_y
#define gw_segments_width gwrom->segments_width
#define gw_segments_height gwrom->segments_height
#define gw_segments_offset gwrom->segments_offset
#define gw_program gwrom->program
#define gw_melody gwrom->melody
#define gw_keyboard gwrom->keyboard

bool gw_romloader();

#endif /* _GW_ROMLOADER_H_ */
