All pastes #808785 Raw Edit

Z80 dump loader - recent version

public text v1 · immutable
·published 2007-12-07 22:23 UTC
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;

}