rendered paste body// Z80_Dump.c
/*
* MDZ file dump handler
*
* by UNKNOWNFILE, 2007
* certifiedunknownfile AT gmail DAWT com
*
* Version 1: Initial release for Gens32.
*
* Todos:
* - Make emulator authors write their own goddamn frontend code!
*
*/
#include <stdio.h>
#include "Z80_Dump.h"
#include "Mem_M68k.h"
#include "Mem_Z80.h"
#include "Z80.h"
// *** Dump output section
// Generates Z80 registers. Mostly copied and modified from save.cpp in Gens32.
int Generate_Dump_Z80_Regs (FILE * dump) {
unsigned char dumpMe[0x60];
char * src; int i;
if (!dump) return 1;
memset(dumpMe,0,0x60);
// magic word.
dumpMe[0] = 'Z';
dumpMe[1] = '8';
dumpMe[2] = '0';
dumpMe[0x04] = (unsigned char) (z80_Get_AF(&M_Z80) & 0xFF);
dumpMe[0x05] = (unsigned char) (z80_Get_AF(&M_Z80) >> 8);
dumpMe[0x08] = (unsigned char) (M_Z80.BC.w.BC & 0xFF);
dumpMe[0x09] = (unsigned char) (M_Z80.BC.w.BC >> 8);
dumpMe[0x0C] = (unsigned char) (M_Z80.DE.w.DE & 0xFF);
dumpMe[0x0D] = (unsigned char) (M_Z80.DE.w.DE >> 8);
dumpMe[0x10] = (unsigned char) (M_Z80.HL.w.HL & 0xFF);
dumpMe[0x11] = (unsigned char) (M_Z80.HL.w.HL >> 8);
dumpMe[0x14] = (unsigned char) (M_Z80.IX.w.IX & 0xFF);
dumpMe[0x15] = (unsigned char) (M_Z80.IX.w.IX >> 8);
dumpMe[0x18] = (unsigned char) (M_Z80.IY.w.IY & 0xFF);
dumpMe[0x19] = (unsigned char) (M_Z80.IY.w.IY >> 8);
dumpMe[0x1C] = (unsigned char) (z80_Get_PC(&M_Z80) & 0xFF);
dumpMe[0x1D] = (unsigned char) (z80_Get_PC(&M_Z80) >> 8);
dumpMe[0x20] = (unsigned char) (M_Z80.SP.w.SP & 0xFF);
dumpMe[0x21] = (unsigned char) (M_Z80.SP.w.SP >> 8);
dumpMe[0x24] = (unsigned char) (z80_Get_AF2(&M_Z80) & 0xFF);
dumpMe[0x25] = (unsigned char) (z80_Get_AF2(&M_Z80) >> 8);
dumpMe[0x28] = (unsigned char) (M_Z80.BC2.w.BC2 & 0xFF);
dumpMe[0x29] = (unsigned char) (M_Z80.BC2.w.BC2 >> 8);
dumpMe[0x2C] = (unsigned char) (M_Z80.DE2.w.DE2 & 0xFF);
dumpMe[0x2D] = (unsigned char) (M_Z80.DE2.w.DE2 >> 8);
dumpMe[0x30] = (unsigned char) (M_Z80.HL2.w.HL2 & 0xFF);
dumpMe[0x31] = (unsigned char) (M_Z80.HL2.w.HL2 >> 8);
dumpMe[0x34] = (unsigned char) (M_Z80.I);
dumpMe[0x36] = (unsigned char) (M_Z80.IFF.b.IFF1 >> 2);
dumpMe[0x38] = (unsigned char) (((Z80_State & 4) >> 2) ^ 1);
dumpMe[0x39] = (unsigned char) (((Z80_State & 2) >> 1) ^ 1);
src = (unsigned char *) &Bank_Z80;
for(i = 0; i < 4; i++) dumpMe[0x3A + i] = *src++;
// The rest of this section is reserved.
// Dump the file buffer.
fwrite(dumpMe,1,0x60,dump);
return 0;
}
// Generates a dump of the Z80 program section.
int Generate_Dump_PRG_Z80 (FILE * data) {
if (!data) return 1;
// Header format:
// 3 bytes: "PRG"
// 1 byte: CPU region (Main 68000 will use DAT to load data)
// where 0 = Z80, 1 = Sega CD 68000, 2 = 32X Master, 3 = 32X Slave
fputc('P', data); fputc('R', data); fputc('G', data); fputc(0, data);
fputc(0,data); fputc(0x20,data); fputc(0,data); fputc(0,data);
fwrite(Ram_Z80,1,0x2000,data);
return 0;
}
// Dumps a memory bank in main 68000 memory.
int Generate_Dump_Bank_Z80 (FILE * data) {
int i;
if (!data) return 1;
fputc('D', data); fputc('A', data); fputc('T', data);
// The Genesis only has 24 bits of addressing space.
fputc ( (Bank_Z80 & 0xFF), data);
fputc ( ((Bank_Z80 >> 8) & 0xFF), data);
fputc ( (Bank_Z80 >> 16), data);
fputc (0, data);
// Size
fputc (0xFF, data); fputc (0x7F, data); fputc (0, data); fputc(0, data);
// The data itself
for (i=0;i<0x8000;i++)
fputc( M68K_RB(Bank_Z80+i) , data);
return 0;
}
// Generates a dump. Specific dumping functions split into different routines for easier reading.
int Generate_Dump_Main (char * fn) {
FILE * dump;
int i;
// if it fails stop here.
dump = fopen(fn,"wb");
if (!dump) return 1;
fputc('M',dump); fputc('D',dump); fputc('Z',dump); fputc(1,dump);
// Generate our dumped sections one by one. If any fail, so does the dump.
if (Generate_Dump_Z80_Regs (dump) == 1) return 1;
if (Generate_Dump_PRG_Z80 (dump) == 1) return 2;
if (Generate_Dump_Bank_Z80 (dump) == 1) return 3;
fclose (dump);
// temporarily here to test some stuff.
dump = fopen ("ROM_Sect.bin","wb");
// The data itself
fseek(dump,Bank_Z80,SEEK_SET);
for (i=0;i<0x8000;i++)
fputc( M68K_RB(Bank_Z80+i) , dump);
fclose(dump);
return 0;
}
// Loads a MDZ snapshot.
int Import_Dump (char * fn) {
FILE * dump;
int Version_Id=0, Z80_Sect=0, i=0;
char Sect_Header[4];
char * src;
unsigned int Prg_Size, Prg_Target;
unsigned int Dat_Size, Dat_Target;
unsigned char Z80_Regs[0x60];
Rom_Size=0; // for main 68K processor.
dump=fopen(fn,"rb");
if (!dump) return 1;
while (1) {
memset(Sect_Header,0,4);
fread(Sect_Header,1,3,dump);
if (!strcmp(Sect_Header,"MDZ")) {
// Header initialization crap!
fread(&Version_Id,1,1,dump);
Version_Id=1;
} else if (!strcmp(Sect_Header,"Z80")) {
// Load Z80 register dump and run with it.
// This section is ALWAYS 0x60 bytes.
memset(Z80_Regs,0,0x60);
fread(Z80_Regs,0,0x60,dump);
// Yoinked and modified from Save.cpp.
z80_Set_AF(&M_Z80, Z80_Regs[0x00] + (Z80_Regs[0x01] << 8));
M_Z80.BC.w.BC = Z80_Regs[0x05] + (Z80_Regs[0x06] << 8);
M_Z80.DE.w.DE = Z80_Regs[0x09] + (Z80_Regs[0x0A] << 8);
M_Z80.HL.w.HL = Z80_Regs[0x0D] + (Z80_Regs[0x0E] << 8);
M_Z80.IX.w.IX = Z80_Regs[0x11] + (Z80_Regs[0x12] << 8);
M_Z80.IY.w.IY = Z80_Regs[0x15] + (Z80_Regs[0x16] << 8);
z80_Set_PC(&M_Z80, Z80_Regs[0x19] + (Z80_Regs[0x1A] << 8));
M_Z80.SP.w.SP = Z80_Regs[0x1D] + (Z80_Regs[0x1E] << 8);
z80_Set_AF2(&M_Z80, Z80_Regs[0x21] + (Z80_Regs[0x22] << 8));
M_Z80.BC2.w.BC2 = Z80_Regs[0x25] + (Z80_Regs[0x26] << 8);
M_Z80.DE2.w.DE2 = Z80_Regs[0x29] + (Z80_Regs[0x2A] << 8);
M_Z80.HL2.w.HL2 = Z80_Regs[0x2D] + (Z80_Regs[0x2E] << 8);
M_Z80.I = Z80_Regs[0x31] & 0xFF;
M_Z80.IM = 1;
M_Z80.IFF.b.IFF1 = (Z80_Regs[0x433] & 1) << 2;
M_Z80.IFF.b.IFF2 = (Z80_Regs[0x433] & 1) << 2;
Z80_State &= ~6;
Z80_State |= ((Z80_Regs[0x436] & 1) ^ 1) << 1;
Z80_State |= ((Z80_Regs[0x435] & 1) ^ 1) << 2;
src = (unsigned char *) &Bank_Z80;
for(i = 0; i < 4; i++) *src++ = Z80_Regs[i + 0x37];
} else if (!strcmp(Sect_Header,"PRG")) {
// Program sections. Only one program may be defined per CPU, otherwise it will fail.
// The 68000 loads its program in the DAT section, so we will not be caring about it here.
fread(&Prg_Target,1,1,dump);
switch (Prg_Target) {
case 0:
if (Z80_Sect==1) return 1; // more than one Z80 section defined you silly person
fread(&Prg_Size,1,4,dump);
fread(Ram_Z80,1,Prg_Size,dump);
Z80_Sect=1;
default:
// If we can't handle it, ignore it. An error handler will handle this later later.
break;
}
} else if (!strcmp(Sect_Header,"DAT")) {
// Data bank, etc.
fread(&Dat_Target,1,4,dump);
fread(&Dat_Size,1,4,dump);
if (Dat_Target > Rom_Size) Rom_Size = Dat_Target + Dat_Size;
fread((Rom_Data+Dat_Target),1,Dat_Size,dump);
} else {
// We can't handle anything more. Therefore we end here.
fclose(dump);
if ((!Version_Id) || (!Z80_Sect)) return 1;
return 0;
}
}
return 0;
}