// 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 #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; }