// Z80 (Zed Eight-Ty) Interface
#include "burnint.h"

#define EMU_DOZE // Use my 'Doze' Assembler Z80 emulator

unsigned char (*ZetRead)(unsigned short a)=NULL;		 // Mem read
void (*ZetWrite)(unsigned short a,unsigned char d)=NULL; // Mem Write
unsigned char (*ZetIn)(unsigned short a)=NULL;			 // Port read
void (*ZetOut)(unsigned short a,unsigned char d)=NULL;	 // Port Write

#ifdef EMU_DOZE
extern "C" unsigned char __cdecl DozeRead(unsigned short a) { return ZetRead(a);}
extern "C" void __cdecl DozeWrite(unsigned short a, unsigned char d) { ZetWrite(a,d);}
extern "C" unsigned char __cdecl DozeIn(unsigned short a) { return ZetIn(a);}
extern "C" void __cdecl DozeOut(unsigned short a, unsigned char d) { ZetOut(a,d);}

int nDozeRunTotal=0; // While inside ZetRun(), the total cycles we should be doing

// the following code is required when compiling with gcc using the -fvtable-thunks flag
 #ifdef DOZE_USE_JUMPTABLE

struct DozeInter {
	unsigned char (*pDozeRead) (unsigned short a);
	void (*pDozeWrite) (unsigned short a, unsigned char d);
	unsigned char (*pDozeIn) (unsigned short a);
	void (*pDozeOut) (unsigned short a, unsigned char d);
};

extern "C" struct DozeInter doze_memory_intf;
struct DozeInter doze_memory_intf = {
	DozeRead,
	DozeWrite,
	DozeIn,
	DozeOut,
};

 #endif // DOZE_USE_JUMPTABLE
#endif // EMU_DOZE

static unsigned char DummyZetRead(unsigned short) {return 0;}
static void DummyZetWrite(unsigned short, unsigned char) {}
static unsigned char DummyZetIn(unsigned short) {return 0;}
static void DummyZetOut(unsigned short, unsigned char) {}

int ZetInit()
{
	if (ZetRead == NULL) {
		ZetRead = DummyZetRead;
	}
	if (ZetWrite == NULL) {
		ZetWrite = DummyZetWrite;
	}
	if (ZetIn == NULL) {
		ZetIn = DummyZetIn;
	}
	if (ZetOut == NULL) {
		ZetOut = DummyZetOut;
	}

	for (int i = 0; i < 0x0100; i++) {
		DozeMemRead[i] = 0;
		DozeMemWrite[i] = 0;
		DozeMemFetch[i] = 0;
		DozeMemFetchData[i] = 0;
	}

	return 0;
}

// This function will make an area callback ZetRead/ZetWrite
int ZetMemCallback(int nStart, int nEnd, int nMode)
{
#ifdef EMU_DOZE
	int i;
	nStart >>= 8;
	nEnd += 0xff;
	nEnd >>= 8;

	// Leave the section out of the memory map, so the Doze* callback with be used
	for (i = nStart; i < nEnd; i++) {
		switch (nMode) {
			case 0:
				DozeMemRead[i] = 0;
				break;
			case 1:
				DozeMemWrite[i] = 0;
				break;
			case 2:
				DozeMemFetch[i] = 0;
				break;
		}
	}
	return 0;
#endif
}

int ZetMemEnd()
{
	return 0;
}

int ZetExit()
{
	ZetRead = NULL;
	ZetWrite = NULL;
	ZetIn = NULL;
	ZetOut = NULL;

	return 0;
}


int ZetMapArea(int nStart, int nEnd, int nMode, unsigned char *Mem)
{
#ifdef EMU_DOZE
	int i, s, e;
	s = nStart >> 8;
	e = (nEnd + 0xFF) >> 8;

	// Put this section in the memory map, giving the offset from Z80 memory to PC memory
	for (i = s; i < e; i++) {
		switch (nMode) {
			case 0:
				DozeMemRead[i] = (unsigned int)(Mem - nStart);
				break;
			case 1:
				DozeMemWrite[i] = (unsigned int)(Mem - nStart);
				break;
			case 2:
				DozeMemFetch[i] = (unsigned int)(Mem - nStart);
				DozeMemFetchData[i] = (unsigned int)(Mem - nStart);
				break;
		}
	}
	return 0;
#endif
}

int ZetMapArea(int nStart, int nEnd, int nMode, unsigned char *Mem01, unsigned char *Mem02)
{
#ifdef EMU_DOZE
	int i, s, e;

	if (nMode != 2) {
		return 1;
	}

	s = nStart >> 8;
	e = (nEnd + 0xFF) >> 8;

	// Put this section in the memory map, giving the offset from Z80 memory to PC memory
	for (i = s; i < e; i++) {
		DozeMemFetch[i] = (unsigned int)(Mem01 - nStart);
		DozeMemFetchData[i] = (unsigned int)(Mem02 - nStart);
	}
	return 0;
#endif
}

int ZetReset()
{
#ifdef EMU_DOZE
	DozeReset();
#endif
	return 0;
}

int ZetPc()
{
#ifdef EMU_DOZE
	return Doze.pc;
#endif
}

int ZetScan(int)	// int nAction
{
#ifdef EMU_DOZE
	SCAN_VAR(Doze)
	return 0;
#endif
}
