
#ifdef __cplusplus
extern "C" {
#endif
/******************************************************************************/
/*																			  */
/*		  RAINE (680x0 arcade emulation) v0.28 (C) 1998/99 Raine Team		  */
/*																			  */
/******************************************************************************/

#ifndef __rainedefs__
#define __rainedefs__

#include <stdio.h>
#include <stdlib.h> // Would you believe that this is included by allegro.h
#include <stdarg.h> // this one too by the way (needed by arkanoid.c at least)

#include <string.h>

#include <allegro.h>

#if ALLEGRO_WIP_VERSION >= 38
#define clear(x) clear_bitmap(x) // super broken allegro-3.9.38 !!!
#endif

#ifdef RAINE_WIN32

// remove some MSVC funky warnings...
#if _MSC_VER > 1000
#pragma warning( disable : 4005 4057 4127 4131 4146 4152 4232 4245 4706 4710 4711 4761 )
// C4005 - 'identifier' : macro redefinition
// C4057 - 'operator' : 'identifier1' indirection to slightly different base types from 'identifier2'
// C4127 - conditional expression is constant
// C4131 - 'function' : uses old-style declarator
//		   --- This one is needed since the unzip (zlib) declares using ANSI standard (old style).
// C4146 - unary minus operator applied to unsigned type, result still unsigned
// C4152 - non standard extension, function/data ptr conversion in expression
//		   --- This one is needed for almost all of the files, when MSVC is put on warning level 4,
//			   It complains about almost every hard coded string in the source complaining about typecast
//			   required etc.  It also complains on function pointer assignments that are not typecasted correctly.
// C4232 - nonstandard extension used : 'identifier' : address of dllimport 'dllimport' is not static, identity not guaranteed
// C4245 - 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
// C4706 - assignment within conditional expression
//		   --- For cleanliness these should actually be split out into multiple lines, also makes
//			   debugging these lines a lot easier.	Most occurances of this were testing memory allocation.
// C4710 - function 'function' not inlined
// C4711 - function 'function' selected for inline expansion
// C4761 - integral size mismatch in argument : conversion supplied
//		   --- This one occurs for a few of the libraries that are used due to parameter type mis-match.
//			   The compiler does however straigten these out, but the warning is issued so it can be resolved
//			   correctly and no compiler stupidity can break the program.
#endif // _MSC_VER > 1000

#endif

#ifdef RAINE_UNIX
// Well sorry : these are defined only in allegro dos...
#define GFX_DRIVER_VGA
#define GFX_DRIVER_MODEX
#endif // RAINE_UNIX

#ifdef GFX_DRIVER_MODEX
#define GFX_ARCMON				 AL_ID('A','R','C','M')
#endif

#ifdef MEMORY_DEBUG
#include "newmem.h"     // This must be placed before other includes
#endif

#include "deftypes.h"       // Raine data types
#include "68020.h"      // UAE 68020 engine (ripped)
#include "confile.h"
#include "debug.h" // if needed

// Compilation Options

#define FASTF3MEM		// Use Faster (no bad address checking) memory access in F3-System
#define F3SINGLE		// Directly use F3-System memory access in 68020 engine

#define BGAMES			// Beta/Unreleased games included

#define RDTSC_PROFILE		// Rdtsc profiling included

#define TRIPLE_BUFFER		// Triple buffer support included

#define HAVE_6502

// Useful String Constants

#define HANDLE	"Raine Team"    // Credit string
#ifdef RAINE_DOS
#define EMUNAME "Raine"     // Dos Name
#else
#ifdef RAINE_WIN32
#define EMUNAME "Raine32"       // Win32/DirectX Name
#else
#define EMUNAME "RaineX"    // Linux Name
// In fact I kept raine as the name for the emulator :
// It is shorter, and more usual...
// I will have to choose one day : it gives me rainex.cfg for raine exe...
// anyway... (rainex.cfg is better : it allows to have the same dir for
// the 3 versions, which is quite convinient for developpement !)
#endif
#endif

#ifdef RAINE_UNIX
   #define SLASH "/"
#else
   #define SLASH "\\"
#endif

UINT8 *R24[0x100];		// Memory Addresses for UAE020 Read
UINT8 *W24[0x100];		// Memory Addresses for UAE020 Read
UINT8 *ROM; 		// Pointer for ROM memory
UINT8 *RAM; 		// Pointer for RAM memory
UINT8 *GFX; 		// Pointer for Graphics memory
UINT8 *SMP; 		// Pointer for Sample memory
UINT8 *EEPROM;			// Pointer for EEPROM memory
UINT8 *Z80ROM;			// Pointer for Z80ROM memory
extern int MC68020;  // 68020 running ???
#ifdef RAINE_UNIX
extern int x_display;			// Running in XFree ???
#endif

#ifdef HAVE_6502
UINT8 *M6502ROM;		// Pointer for Z80ROM memory
#endif

/*

x86 memory access

*/

#define ReadByte(a) (*(UINT8  *)(a))
#define ReadWord(a) (*(UINT16 *)(a))
#define ReadLong(a) (*(UINT32 *)(a))

#define WriteByte(a,d)	(*(UINT8  *)(a) = (d))
#define WriteWord(a,d)	(*(UINT16 *)(a) = (d))
#define WriteLong(a,d)	(*(UINT32 *)(a) = (d))

/*

680x0 memory access

*/

static DEF_INLINE UINT32 m680x0_get_word(UINT16 *a)
{
#if 0 // !defined(RAINE_DOS) && !defined(RAINE_UNIX)
   return (((UINT8 *) a)[0] << 8) | (((UINT8 *) a)[1] << 0);
#else
   UINT32 retval;
   asm("xorl %k0,%k0\n\tmovw %w1,%w0\n\trolw $8,%w0" : "=&r" (retval) : "m" (*a) : "cc");
	return retval;
#endif
}

static DEF_INLINE UINT32 m680x0_get_long(UINT32 *a)
{
#if 0 // !defined(RAINE_DOS) && !defined(RAINE_UNIX)
   return (((UINT8 *) a)[0] << 24) | (((UINT8 *) a)[1] << 16) | (((UINT8 *) a)[2] << 8) | (((UINT8 *) a)[3] << 0);
#else
   UINT32 retval;
   asm("bswapl %0" : "=r" (retval) : "0" (*a) : "cc");
   return retval;
#endif
}

#define ReadByte68k(a)	(*(UINT8 *)(a))
#define ReadWord68k(a)	m680x0_get_word((UINT16 *)(a))
#define ReadLong68k(a)	m680x0_get_long((UINT32 *)(a))

static DEF_INLINE void m680x0_put_word(UINT16 *a, UINT32 v)
{
#if 0 // !defined(RAINE_DOS) && !defined(RAINE_UNIX)
   ((UINT8 *) a)[0] = (v >> 8) & 0xFF;
   ((UINT8 *) a)[1] = (v >> 0) & 0xFF;
#else
   asm("rolw $8,%w0" : "=r" (v) : "0" (v) : "cc");
   *a = v;
#endif
}
static DEF_INLINE void m680x0_put_long(UINT32 *a, UINT32 v)
{
#if 0 // !defined(RAINE_DOS) && !defined(RAINE_UNIX)
   ((UINT8 *) a)[0] = (v >>24) & 0xFF;
   ((UINT8 *) a)[1] = (v >>16) & 0xFF;
   ((UINT8 *) a)[2] = (v >> 8) & 0xFF;
   ((UINT8 *) a)[3] = (v >> 0) & 0xFF;
#else
   asm("bswapl %0" : "=r" (v) : "0" (v) : "cc");
   *a = v;
#endif
}

#define WriteByte68k(a,d)	(*(UINT8 *)(a) = (d))
#define WriteWord68k(a,d)	m680x0_put_word((UINT16 *)(a), (d))
#define WriteLong68k(a,d)	m680x0_put_long((UINT32 *)(a), (d))

// UAE 68020 Read Pointers
// -----------------------

UINT8  (*ByteRead)(UINT32 address);
UINT16 (*WordRead)(UINT32 address);
UINT32 (*LongRead)(UINT32 address);

// UAE 68020 Write Pointers
// ------------------------

void (*ByteWrite)(UINT32 address, UINT8  data);
void (*WordWrite)(UINT32 address, UINT16 data);
void (*LongWrite)(UINT32 address, UINT32 data);

void (*F3SystemEEPROMAccess)(UINT8 data);

#ifdef F3SINGLE

static DEF_INLINE UINT8 ReadF3SystemByte(UINT32 i)
{
   return(R24[(i>>16)&0xFF][i&0xFFFF]);
}

static DEF_INLINE UINT16 ReadF3SystemWord(UINT32 i)
{
   return(ReadWord68k(&R24[(i>>16)&0xFF][i&0xFFFF]));
}

static DEF_INLINE UINT32 ReadF3SystemLong(UINT32 i)
{
   return(ReadLong68k(&R24[(i>>16)&0xFF][i&0xFFFF]));
}

static DEF_INLINE void WriteF3SystemByte(UINT32 i, UINT8 data)
{
   W24[(i>>16)&0xFF][i&0xFFFF]=data;
}

static DEF_INLINE void WriteF3SystemWord(UINT32 i, UINT16 data)
{
   WriteWord68k(&W24[(i>>16)&0xFF][i&0xFFFF],data);
}

static DEF_INLINE void WriteF3SystemLong(UINT32 i, UINT32 data)
{
   WriteLong68k(&W24[(i>>16)&0xFF][i&0xFFFF],data);
}

// Define UAE 680x0 Read routines
// ------------------------------

#define cpu_readmem24(address)			ReadF3SystemByte(address)
#define cpu_readmem24_word(address) 	ReadF3SystemWord(address)
#define cpu_readmem24_dword(address)		ReadF3SystemLong(address)

// Define UAE 680x0 Write routines
// -------------------------------

#define cpu_writemem24(address,data)		WriteF3SystemByte(address,data)
#define cpu_writemem24_word(address,data)	WriteF3SystemWord(address,data)
#define cpu_writemem24_dword(address,data)	WriteF3SystemLong(address,data)

#else

// Define UAE 680x0 Read routines
// ------------------------------

#define cpu_readmem24(address)			ByteRead(address)
#define cpu_readmem24_word(address) 	WordRead(address)
#define cpu_readmem24_dword(address)		LongRead(address)

// Define UAE 680x0 Write routines
// -------------------------------

#define cpu_writemem24(address,data)		ByteWrite(address,data)
#define cpu_writemem24_word(address,data)	WordWrite(address,data)
#define cpu_writemem24_dword(address,data)	LongWrite(address,data)

#endif

#define CPU_FRAME_MHz(speed,slice) ((speed*1000000)/slice)

void (*ExecuteSoundFrame)();	// Pointer to ExecuteSoundFrame rountine (sound cpu work for 1 frame), used for pausegame + playsound

// Load Error Report

#define LOAD_FATAL_ERROR (0x0001)
#define LOAD_WARNING	 (0x0002)
int load_error;
char *load_debug;

// Sound

int GameSound;			// 1 if game supports sound
int SoundEnabled;		// 1 if user wants sound emulation

// Misc Stuff

int GameMouse;			// 1 if game wants to use mouse driver

// Game Screen

BITMAP *GameBitmap; 	// *Full* Bitmap for generating the game screen (eg. 0,0 to 320+32,240+32)

PALETTE pal;			// 256 Colour palette for the game

BITMAP *GameViewBitmap; 	// *Viewable* Bitmap for saving (pcx) the game screen (eg. 16,16 to 320+16,240+16)
DATAFILE *RaineData;		// Resource datafile

int StarScreamEngine;		// Number of M68000's in use
int MZ80Engine; 		// Number of Z80's in use

#ifdef HAVE_6502
int M6502Engine;		// Number of M6502's in use
#endif

int RAMSize;			// Size of RAM[] block

UINT8 *SpriteGun1;		// Raw data for player 1 mouse target
UINT8 *SpriteGun2;		// Raw data for player 2 mouse target
UINT8 *ingame_font; 	// Raw data for ingame font


int RefreshBuffers;

/*

general configuration

*/

typedef struct RAINE_CFG
{
   UINT32 show_fps_mode;			// type of fps output
   UINT32 no_gui;			// gui is disabled
   UINT32 req_load_game;			// request to load game (from the command line)
   UINT32 req_game_index;		// game number for req_load_game
   UINT32 version_no;			// what version of raine is running
   UINT32 run_count;			// how many times raine has run
   UINT32 wibble;			// wibble the screen
   UINT32 extra_games;			// extra games enable (currently unused)
   UINT32 save_game_screen_settings;	// save display config for each game
   UINT32 hide;
   UINT32 req_pause_game;
   UINT32 req_save_screen;
   UINT32 req_pause_scroll;
   UINT32 auto_save; // Auto-save/load current game
} RAINE_CFG;

struct RAINE_CFG raine_cfg;

// flags for auto_save

#define FLAG_AUTO_SAVE 1
#define FLAG_AUTO_LOAD 2

/*

display configuration

*/

typedef struct DISPLAY_CFG
{
   UINT32 screen_type;			// pc screen display type {..MODX,VB2L,VBAF..}
	INT32 screen_x; 		// pc screen display width
	INT32 screen_y; 		// pc screen display height
   UINT32 scanlines;			// scanlines mode {0,1,2}
   UINT32 vsync;			// vsync mode {0,1}
   UINT32 triple_buffer;		// triple buffer mode {0,1}
   UINT32 eagle_fx; 		// use eagle effect {0,1}
   UINT16 stretch;

   UINT32 fast_set_pal; 		// fast or slow(compatable) set pal {0,1}
   UINT32 screenshot_png;
   UINT32 pixel_double; 		// double pixels effect {0,1,2}
   UINT32 limit_speed;			// don't exceed 60 fps {0,1}
   UINT32 frame_skip;			// skip frames number {0..9} (0=auto frame skip)
#if defined(RAINE_DOS) || defined(RAINE_UNIX)
   UINT32 arcade_h_timing;		// arcade monitor mode
   UINT32 arcade_v_timing;
   UINT32 arcade_center_x;
   UINT32 arcade_center_y;
#endif
   UINT32 rotate;			// real rotation setting {0,1,2,3}
   UINT32 flip; 			// real flipping setting {0,1,2,3}
   UINT32 user_rotate;			// user preferred rotation {0,1,2,3}
   UINT32 user_flip;			// user preferred flipping {0,1,2,3}
   UINT32 no_rotate;			// ignore default rotation in game drivers
   UINT32 no_flip;			// ignore default rotation in game drivers
  UINT32 auto_mode_change; // Mode change allowed when loading a game ?
   UINT32 bpp;							// colour depth {8,15,16,24,32}
} DISPLAY_CFG;

struct DISPLAY_CFG display_cfg, game_display_cfg, prev_display_cfg;

int use_custom_screen;

/*

file & directory configuration

*/

typedef struct DIR_CFG
{
   char exe_path[256]; 		// current path of raine.exe
   char share_path[256];		// location of data files
   char language_file[256];		// language translation file (no path)
   char screen_dir[256];		// screenshot path
   char rom_dir[4][256];		// rom paths
   char cheat_file[256];		// cheat file (no path)
   char config_file[256];		// config file (no path)
   UINT32 long_file_names;		// enable long file name support
   UINT32 last_screenshot_num;		// counter for last screenshot
} DIR_CFG;

struct DIR_CFG dir_cfg;

#endif

#ifdef __cplusplus
}
#endif
