/*******************************************************
 ** mem.h                                             **
 ** Memory-Handler                                    **
 ** Speicherzugriffe, RAM,ROM,Hardware                **
 *******************************************************/

#ifndef MEM_H

#ifndef __ATARI__
#include "atari.h"
#endif


typedef unsigned char mtype;
typedef int ATPtr;

#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef NULL
#define NULL 0L
#endif


typedef mtype (*MemGet)(void);
typedef int (*MemPut)(mtype byte);

struct Cart {
    int type;
    int active;
    int num_secs;     /* Number of discrete sections that can be mapped into
			 currently limited to four */
    struct {
	ATPtr lo,hi;   /* address ranges of the sections in memory */
	int offset;   /* offset of this section from the start of the image */
	int active;   /* whether this section is enabled */
    } secs[4];

    mtype *image;     /* keeps the image itself */
    mtype *saveback;  /* keeps the RAM under the image */
};


/* Cart-Types */

extern mtype memory[65536];
extern MemGet mget[65536];
extern MemPut mput[65536];


/* Lo-level memory access. Must be redefined if memory type changes */

/* These are strictly for the CPU module */

#ifdef DEBUG
#define GetByte(addr)      (mget[addr]?mget[(regPC=PC)?(addr):(0)]():memory[addr])
#define PutByte(addr,byte) if (mput[addr]) {                          \
				 regPC=PC;                            \
				 if (mput[addr](byte)) goto halt_cpu; \
			   } else memory[addr]=byte;             

#else
#define GetByte(addr)      (mget[addr]?mget[addr]():memory[addr])
#define PutByte(addr,byte) if (mput[addr]) {                             \
				 if (mput[addr](byte)) goto halt_cpu;    \
			   } else memory[addr]=byte;             
#endif

/* This is for all the remaining stuff. */

#define IsRAM(addr)        (mput[addr]!=NULL)

#define Peek(addr)         ((int)((mget[addr]?mget[addr]():memory[addr])&0xff))
#define DPeek(addr)        ((Peek(addr))|(((Peek(addr+1))<<8)))
#define Poke(addr,byte)    if (mput[addr]) {                     \
				 mput[addr](byte);               \
			   } else memory[addr]=byte;         

/* The same for the ANTIC module. Might differ in the future if the XE 
   simulation is setup properly... */

#define APeek(addr)        ((int)((mget[addr]?mget[addr]():memory[addr])&0xff))
#define DAPeek(addr)       ((Peek(addr))|(((Peek(addr+1))<<8)))

void SetRAM(int lower,int upper);
void SetROM(int lower,int upper);
void SetHW(int address,int mask,MemGet read,MemPut write);
void SetBlank(int lower,int upper);
int LoadMem(int fd,int addr,int size);
int load_image (char *filename, int addr, int nbytes);
void EnablePILL (void);
void CopyFromMem(ATPtr to,UBYTE *,int size);
void CopyToMem(UBYTE *,ATPtr from,int size);

void TurnOffCart(void);
void TurnOnCart(void);
void RemoveCart(void);
void InsertCart(struct Cart *ct);
void EnableBasic(void);
void DisableBasic(void);
int CartInserted(void);
void EnableOs(void);
void DisableOs(void);
void EnableSelftest(void);
void DisableSelftest(void);
void RemoveCurrent(void);
void ChangeMapping(int map0,int map1,int map2, int map3);
int CartType(void);

int Read5200Rom(char *filename,int fd);
int ReadOSABRom(char *filename,int fd);
int ReadXLRom(char *filename,int fd);
int ReadBasic(char *filename,int fd);
int Insert_8K_ROM (char *filename,int fd);
int Insert_16K_ROM (char *filename,int fd);
int Insert_OSS_ROM (char *filename,int fd);
int Insert_DB_ROM (char *filename,int fd);
int Insert_32K_5200ROM (char *filename,int fd);
int Insert_16K_5200ROM (char *filename,int fd);

void SelectXEBank(int bank);
int Free_XE_Banks(void);
int Build_XE_Banks(void);
void FreeCarts(void);

int RomGet(ATPtr ad);
int RomDGet(ATPtr ad);
void RomSet(ATPtr ad,int v);

#endif
