Yet Another SEGA GAME GEAR Emulator その7

DONKEY.ROMのRAMのアドレスを修正(7000H → C000H)すれば、BIOSのパッチ当てである程度は動きます。

f:id:tanam:20140604214407p:image:w360

f:id:tanam:20140604214405p:image:w360

さすがにDONKEY.ROMは公開出来ないので、eSC-3000を改造して、メモリーマップとI/Oポートにパッチを当てるようにしました。yaGAME GEARを改造しないのは、以前のCOLECOVISION対応のソースが残っているためです。

http://www.geocities.jp/parallel_computer_inc/android.html

memory.cpp

/*
	SEGA SC-3000 Emulator 'eSC-3000'

	Author : Takeda.Toshiya
	Date   : 2010.08.17-

	[ memory ]
*/

#include "memory.h"
#include "../../fileio.h"

void MEMORY::sms_mapper_w(uint32 addr, uint32 data)
{
	/* Calculate ROM page index */
	uint8 page = (data % pages);

	/* Save frame control register data */
	fcr[addr] = data;

	switch (addr) {
	case 0:
		if (data & 8) {
			save = 1;
			/* Page in ROM */
			cpu_readmap[4]  = &sram[(data & 4) ? 0x4000 : 0x0000];
			cpu_readmap[5]  = &sram[(data & 4) ? 0x6000 : 0x2000];
			cpu_writemap[4] = &sram[(data & 4) ? 0x4000 : 0x0000];
			cpu_writemap[5] = &sram[(data & 4) ? 0x6000 : 0x2000];
		} else {
			/* Page in RAM */
			cpu_readmap[4]  = &cart[((fcr[3] % pages) << 14) + 0x0000];
			cpu_readmap[5]  = &cart[((fcr[3] % pages) << 14) + 0x2000];
			cpu_writemap[4] = ram + 0x8000;
			cpu_writemap[5] = ram + 0xA000;
		}
		break;
	case 1:
		cpu_readmap[0] = &cart[(page << 14) + 0x0000];
		cpu_readmap[1] = &cart[(page << 14) + 0x2000];
		break;
	case 2:
		cpu_readmap[2] = &cart[(page << 14) + 0x0000];
		cpu_readmap[3] = &cart[(page << 14) + 0x2000];
		break;
	case 3:
		if (!(fcr[0] & 0x08)) {
			cpu_readmap[4] = &cart[(page << 14) + 0x0000];
			cpu_readmap[5] = &cart[(page << 14) + 0x2000];
		}
		break;
	}
}

void MEMORY::initialize()
{
	cart=NULL;
	coleco=0;

	memset(ipl, 0, sizeof(ipl));
	memset(ram, 0, sizeof(ram));
	memset(rdmy, 0xff, sizeof(rdmy));
	memset(sram, 0, sizeof(sram));

	// set memory map
	cpu_readmap[0] = ram;
	cpu_readmap[1] = ram + 0x2000;
	cpu_readmap[2] = ram + 0x4000;
	cpu_readmap[3] = ram + 0x6000;
	cpu_readmap[4] = ram + 0x8000;
	cpu_readmap[5] = ram + 0xA000;
	cpu_readmap[6] = ram + 0xC000;
	cpu_readmap[7] = ram + 0xE000;

	cpu_writemap[0] = ram;
	cpu_writemap[1] = ram + 0x2000;
	cpu_writemap[2] = ram + 0x4000;
	cpu_writemap[3] = ram + 0x6000;
	cpu_writemap[4] = ram + 0x8000;
	cpu_writemap[5] = ram + 0xA000;
	cpu_writemap[6] = ram + 0xC000;
	cpu_writemap[7] = ram + 0xE000;

	fcr[0] = 0x00;
	fcr[1] = 0x00;
	fcr[2] = 0x01;
	fcr[3] = 0x00;

	// load ipl
	FILEIO* fio = new FILEIO();
	if(fio->Fopen(emu->bios_path(_T("COLECO.ROM")), FILEIO_READ_BINARY)) {
		fio->Fread(ipl, sizeof(ipl), 1);
		fio->Fclose();
		cpu_readmap[0] = ipl;
		cpu_readmap[1] = ipl+0x2000;
		coleco=1;
	}
	delete fio;

	inserted = false;
}

void MEMORY::write_data8(uint32 addr, uint32 data)
{
	if (coleco==2 && addr>=0x7000 && addr<=0x73ff)
		addr+=0x5000;
	cpu_writemap[(addr >> 13)][(addr & 0x1FFF)] = data;
	if (pages < 4) return;
	if (addr >= 0xFFFC) sms_mapper_w(addr & 3, data);
}

uint32 MEMORY::read_data8(uint32 addr)
{
	if (coleco==2 && addr>=0x7000 && addr<=0x73ff)
		addr+=0x5000;
	return cpu_readmap[(addr >> 13)][(addr & 0x1FFF)];
}

void MEMORY::write_signal(int id, uint32 data, uint32 mask)
{
	// from PIO-P6
	if(data & mask) {
		cpu_readmap[0] = ram;
		cpu_readmap[1] = ram + 0x2000;
		cpu_readmap[2] = ram + 0x4000;
		cpu_readmap[3] = ram + 0x6000;
		cpu_readmap[4] = ram + 0x8000;
		cpu_writemap[0] = ram;
		cpu_writemap[1] = ram + 0x2000;
		cpu_writemap[2] = ram + 0x4000;
		cpu_writemap[3] = ram + 0x6000;
		cpu_writemap[4] = ram + 0x8000;
	} else {
		// ROM
		cpu_readmap[0] = cart;
		cpu_readmap[1] = rdmy;
		cpu_readmap[2] = ram + 0x4000;
		cpu_readmap[3] = ram + 0x6000;
		cpu_readmap[4] = ram + 0x8000;
		cpu_writemap[0] = ram;
		cpu_writemap[1] = ram + 0x2000;
		cpu_writemap[2] = ram + 0x4000;
		cpu_writemap[3] = ram + 0x6000;
		cpu_writemap[4] = ram + 0x8000;
	}
}

void MEMORY::open_cart(_TCHAR* file_path)
{
	FILEIO* fio = new FILEIO();
	
	if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
		fio->Fseek(0, FILEIO_SEEK_END);
		size=fio->Ftell();
		pages = (size / 0x4000);
		fio->Fseek(0, FILEIO_SEEK_SET);
		if (cart) free(cart);
		cart=(uint8 *)malloc(size);
		fio->Fread(cart, size, 1);
		fio->Fclose();

		inserted = true;
	}
	delete fio;
	if (coleco && (strstr(file_path, ".col") || 
		strstr(file_path, ".COL"))) {
		coleco=2;
		/* $0000-$1FFF mapped to internal ROM (8K) */
		cpu_readmap[0]  = ipl;
		/* $2000-$5FFF mapped to expansion */
		cpu_readmap[1]  = ipl+0x2000;
		/* $6000-$7FFF mapped to RAM (1K mirrored) */
		cpu_readmap[2]  = rdmy;
		cpu_readmap[3]  = rdmy; /// ram + 0x6000;
		/* $8000-$FFFF mapped to Cartridge ROM (max. 32K) */
		cpu_readmap[4] = cart;
		if (size>0x2000) cpu_readmap[5] = cart + 0x2000;
		else cpu_readmap[5] = rdmy;
		/* $C000-$FFFF mapped to RAM */
		cpu_readmap[6] = ram + 0xC000;
		cpu_readmap[7] = ram + 0xE000;
	} else {
		if (coleco) coleco=1;
		// set memory map
		cpu_readmap[0] = cart;
		if (size>0x2000) cpu_readmap[1] = cart + 0x2000;
		else cpu_readmap[1] = rdmy;
		if (size>0x4000) cpu_readmap[2] = cart + 0x4000;
		else cpu_readmap[2] = rdmy;
		if (size>0x6000) cpu_readmap[3] = cart + 0x6000;
		else cpu_readmap[3] = rdmy;
		if (size>0x8000) cpu_readmap[4] = cart + 0x8000;
		else cpu_readmap[4] = ram + 0x8000;
		if (size>0xA000) cpu_readmap[5] = cart + 0xA000;
		else cpu_readmap[5] = ram + 0xA000;
		cpu_readmap[6] = ram + 0xC000;
		cpu_readmap[7] = ram + 0xE000;
		cpu_writemap[0] = ram;
		cpu_writemap[1] = ram + 0x2000;
		cpu_writemap[2] = ram + 0x4000;
		cpu_writemap[3] = ram + 0x6000;
		cpu_writemap[4] = ram + 0x8000;
		cpu_writemap[5] = ram + 0xA000;
		cpu_writemap[6] = ram + 0xC000;
		cpu_writemap[7] = ram + 0xE000;
	}

	fcr[0] = 0x00;
	fcr[1] = 0x00;
	fcr[2] = 0x01;
	fcr[3] = 0x00;
}

void MEMORY::close_cart()
{
	if (cart) free(cart);	
	initialize();	
}

memory.h

/*
	SEGA SC-3000 Emulator 'eSC-3000'

	Author : Takeda.Toshiya
	Date   : 2010.08.17-

	[ memory ]
*/

#ifndef _MEMORY_H_
#define _MEMORY_H_

#include "../vm.h"
#include "../../emu.h"
#include "../device.h"

#define SIG_MEMORY_SEL	0

class MEMORY : public DEVICE
{
private:
	int coleco;
	// memory
	uint8 *cart;
	uint32 size;
	uint8 pages;
	uint8 ipl[0xC000];	// colecovision
	uint8 ram[0x10000];	
	uint8 rdmy[0x2000];
	uint8 sram[0x8000];
	uint8 *cpu_readmap[8];
	uint8 *cpu_writemap[8];
	uint8 fcr[4];
	uint8 save;
	
	bool inserted;
	void sms_mapper_w(uint32 addr, uint32 data);
	
public:
	MEMORY(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) {}
	~MEMORY() {}
	
	// common functions
	void initialize();
	void write_data8(uint32 addr, uint32 data);
	uint32 read_data8(uint32 addr);
	void write_data16(uint32 addr, uint32 data) {
		write_data8(addr, data & 0xff); write_data8(addr + 1, data >> 8);
	}
	uint32 read_data16(uint32 addr) {
		return read_data8(addr) | (read_data8(addr + 1) << 8);
	}
	void write_signal(int id, uint32 data, uint32 mask);
	
	// unique functions
	void open_cart(_TCHAR* file_path);
	void close_cart();
	bool cart_inserted() {
		return inserted;
	}
};
#endif

winmain.cpp

#if defined(_GAMEGEAR)
		_T("Supported Files (*.rom;*.bin;*.gg)\0*.rom;*.bin;*.gg\0All Files (*.*)\0*.*\0\0"),
		_T("Game Cartridge"),
#elif defined(_COLECOVISION)
		_T("Supported Files (*.rom;*.bin;*.sg;*.col)\0*.rom;*.bin;*.sg;*.col\0All Files (*.*)\0*.*\0\0"),
		_T("Game Cartridge"),
#elif defined(_MASTERSYSTEM)
		_T("Supported Files (*.rom;*.bin;*.sms)\0*.rom;*.bin;*.sms\0All Files (*.*)\0*.*\0\0"),
		_T("Game Cartridge"),