mirror of https://github.com/bsnes-emu/bsnes.git
Update to v087r28 release.
byuu says: Be sure to run make install, and move required images to their appropriate system profile folders. I still have no warnings in place if those images aren't present. Changelog: - OBJ mosaic should hopefully be emulated correctly now (thanks to krom and Cydrak for testing the hardware behavior) - emulated dummy serial registers, fixes Sonic Advance (you may still need to specify 512KB FlashROM with an appropriate ID, I used Panaonic's) - GBA core exits scheduler (PPU thread) and calls interface->videoRefresh() from main thread (not required, just nice) - SRAM, FRAM, EEPROM and FlashROM initialized to 0xFF if it does not exist (probably not needed, but FlashROM likes to reset to 0xFF anyway) - GBA manifest.xml for file-mode will now use "gamename.xml" instead of "gamename.gba.xml" - started renaming "NES" to "Famicom" and "SNES" to "Super Famicom" in the GUI (may or may not change source code in the long-term) - removed target-libsnes/ - added profile/ Profiles are the major new feature. So far we have: Famicom.sys/{nothing (yet?)} Super Famicom.sys/{ipl.rom} Game Boy.sys/{boot.rom} Game Boy Color.sys/{boot.rom} Game Boy Advance.sys/{bios.rom[not included]} Super Game Boy.sfc/{boot.rom,program.rom[not included]} BS-X Satellaview.sfc/{program.rom,bsx.ram,bsx.pram} Sufami Turbo.sfc/{program.rom} The SGB, BSX and ST cartridges ask you to load GB, BS or ST cartridges directly now. No slot loader for them. So the obvious downsides: you can't quickly pick between different SGB BIOSes, but why would you want to? Just use SGB2/JP. It's still possible, so I'll sacrifice a little complexity for a rare case to make it a lot easier for the more common case. ST cartridges currently won't let you load the secondary slot. BS-X Town cart is the only useful game to load with nothing in the slot, but only barely, since games are all seeded on flash and not on PSRAM images. We can revisit a way to boot the BIOS directly if and when we get the satellite uplink emulated and data can be downloaded onto the PSRAM :P BS-X slotted cartridges still require the secondary slot. My plan for BS-X slotted cartridges is to require a manifest.xml to specify that it has the BS-X slot present. Otherwise, we have to load the ROM into the SNES cartridge class, and parse its header before we can find out if it has one. Screw that. If it's in the XML, I can tell before loading the ROM if I need to present you with an optional slot loading dialog. I will probably do something similar for Sufami Turbo. Not all games even work with a secondary slot, so why ask you to load a second slot for them? Let the XML request a second slot. A complete Sufami Turbo ROM set will be trivial anyway. Not sure how I want to do the sub dialog yet. We want basic file loading, but we don't want it to look like the dialog 'didn't do anything' if it pops back open immediately again. Maybe change the background color of the dialog to a darker gray? Tacky, but it'd give you the visual cue without the need for some subtle text changes.
This commit is contained in:
parent
d2241f1931
commit
a454e9d927
|
@ -1,7 +1,7 @@
|
|||
#ifndef BASE_HPP
|
||||
#define BASE_HPP
|
||||
|
||||
static const char Version[] = "087.27";
|
||||
static const char Version[] = "087.28";
|
||||
|
||||
#include <nall/platform.hpp>
|
||||
#include <nall/algorithm.hpp>
|
||||
|
|
|
@ -103,9 +103,9 @@ uint8 Cartridge::mmio_read(uint16 addr) {
|
|||
if(bootrom_enable) {
|
||||
const uint8 *data = nullptr;
|
||||
switch(system.revision()) { default:
|
||||
case System::Revision::GameBoy: data = System::BootROM::dmg; break;
|
||||
case System::Revision::SuperGameBoy: data = System::BootROM::sgb; break;
|
||||
case System::Revision::GameBoyColor: data = System::BootROM::cgb; break;
|
||||
case System::Revision::GameBoy: data = system.bootROM.dmg; break;
|
||||
case System::Revision::SuperGameBoy: data = system.bootROM.sgb; break;
|
||||
case System::Revision::GameBoyColor: data = system.bootROM.cgb; break;
|
||||
}
|
||||
if(addr >= 0x0000 && addr <= 0x00ff) return data[addr];
|
||||
if(addr >= 0x0200 && addr <= 0x08ff && system.cgb()) return data[addr - 256];
|
||||
|
|
|
@ -1,135 +0,0 @@
|
|||
#ifdef SYSTEM_CPP
|
||||
|
||||
//SHA256 = 4bf5021be357ce523a59ac5f4efff5d6371ae50112a6db0adf4a75916ad760a9
|
||||
const uint8_t System::BootROM::cgb[2048] = {
|
||||
0x31,0xfe,0xff,0x3e,0x02,0xc3,0x7c,0x00,0xd3,0x00,0x98,0xa0,0x12,0xd3,0x00,0x80,
|
||||
0x00,0x40,0x1e,0x53,0xd0,0x00,0x1f,0x42,0x1c,0x00,0x14,0x2a,0x4d,0x19,0x8c,0x7e,
|
||||
0x00,0x7c,0x31,0x6e,0x4a,0x45,0x52,0x4a,0x00,0x00,0xff,0x53,0x1f,0x7c,0xff,0x03,
|
||||
0x1f,0x00,0xff,0x1f,0xa7,0x00,0xef,0x1b,0x1f,0x00,0xef,0x1b,0x00,0x7c,0x00,0x00,
|
||||
0xff,0x03,0xce,0xed,0x66,0x66,0xcc,0x0d,0x00,0x0b,0x03,0x73,0x00,0x83,0x00,0x0c,
|
||||
0x00,0x0d,0x00,0x08,0x11,0x1f,0x88,0x89,0x00,0x0e,0xdc,0xcc,0x6e,0xe6,0xdd,0xdd,
|
||||
0xd9,0x99,0xbb,0xbb,0x67,0x63,0x6e,0x0e,0xec,0xcc,0xdd,0xdc,0x99,0x9f,0xbb,0xb9,
|
||||
0x33,0x3e,0x3c,0x42,0xb9,0xa5,0xb9,0xa5,0x42,0x3c,0x58,0x43,0xe0,0x70,0x3e,0xfc,
|
||||
0xe0,0x47,0xcd,0x75,0x02,0xcd,0x00,0x02,0x26,0xd0,0xcd,0x03,0x02,0x21,0x00,0xfe,
|
||||
0x0e,0xa0,0xaf,0x22,0x0d,0x20,0xfc,0x11,0x04,0x01,0x21,0x10,0x80,0x4c,0x1a,0xe2,
|
||||
0x0c,0xcd,0xc6,0x03,0xcd,0xc7,0x03,0x13,0x7b,0xfe,0x34,0x20,0xf1,0x11,0x72,0x00,
|
||||
0x06,0x08,0x1a,0x13,0x22,0x23,0x05,0x20,0xf9,0xcd,0xf0,0x03,0x3e,0x01,0xe0,0x4f,
|
||||
0x3e,0x91,0xe0,0x40,0x21,0xb2,0x98,0x06,0x4e,0x0e,0x44,0xcd,0x91,0x02,0xaf,0xe0,
|
||||
0x4f,0x0e,0x80,0x21,0x42,0x00,0x06,0x18,0xf2,0x0c,0xbe,0x20,0xfe,0x23,0x05,0x20,
|
||||
0xf7,0x21,0x34,0x01,0x06,0x19,0x78,0x86,0x2c,0x05,0x20,0xfb,0x86,0x20,0xfe,0xcd,
|
||||
0x1c,0x03,0x18,0x02,0x00,0x00,0xcd,0xd0,0x05,0xaf,0xe0,0x70,0x3e,0x11,0xe0,0x50,
|
||||
0x21,0x00,0x80,0xaf,0x22,0xcb,0x6c,0x28,0xfb,0xc9,0x2a,0x12,0x13,0x0d,0x20,0xfa,
|
||||
0xc9,0xe5,0x21,0x0f,0xff,0xcb,0x86,0xcb,0x46,0x28,0xfc,0xe1,0xc9,0x11,0x00,0xff,
|
||||
0x21,0x03,0xd0,0x0e,0x0f,0x3e,0x30,0x12,0x3e,0x20,0x12,0x1a,0x2f,0xa1,0xcb,0x37,
|
||||
0x47,0x3e,0x10,0x12,0x1a,0x2f,0xa1,0xb0,0x4f,0x7e,0xa9,0xe6,0xf0,0x47,0x2a,0xa9,
|
||||
0xa1,0xb0,0x32,0x47,0x79,0x77,0x3e,0x30,0x12,0xc9,0x3e,0x80,0xe0,0x68,0xe0,0x6a,
|
||||
0x0e,0x6b,0x2a,0xe2,0x05,0x20,0xfb,0x4a,0x09,0x43,0x0e,0x69,0x2a,0xe2,0x05,0x20,
|
||||
0xfb,0xc9,0xc5,0xd5,0xe5,0x21,0x00,0xd8,0x06,0x01,0x16,0x3f,0x1e,0x40,0xcd,0x4a,
|
||||
0x02,0xe1,0xd1,0xc1,0xc9,0x3e,0x80,0xe0,0x26,0xe0,0x11,0x3e,0xf3,0xe0,0x12,0xe0,
|
||||
0x25,0x3e,0x77,0xe0,0x24,0x21,0x30,0xff,0xaf,0x0e,0x10,0x22,0x2f,0x0d,0x20,0xfb,
|
||||
0xc9,0xcd,0x11,0x02,0xcd,0x62,0x02,0x79,0xfe,0x38,0x20,0x14,0xe5,0xaf,0xe0,0x4f,
|
||||
0x21,0xa7,0x99,0x3e,0x38,0x22,0x3c,0xfe,0x3f,0x20,0xfa,0x3e,0x01,0xe0,0x4f,0xe1,
|
||||
0xc5,0xe5,0x21,0x43,0x01,0xcb,0x7e,0xcc,0x89,0x05,0xe1,0xc1,0xcd,0x11,0x02,0x79,
|
||||
0xd6,0x30,0xd2,0x06,0x03,0x79,0xfe,0x01,0xca,0x06,0x03,0x7d,0xfe,0xd1,0x28,0x21,
|
||||
0xc5,0x06,0x03,0x0e,0x01,0x16,0x03,0x7e,0xe6,0xf8,0xb1,0x22,0x15,0x20,0xf8,0x0c,
|
||||
0x79,0xfe,0x06,0x20,0xf0,0x11,0x11,0x00,0x19,0x05,0x20,0xe7,0x11,0xa1,0xff,0x19,
|
||||
0xc1,0x04,0x78,0x1e,0x83,0xfe,0x62,0x28,0x06,0x1e,0xc1,0xfe,0x64,0x20,0x07,0x7b,
|
||||
0xe0,0x13,0x3e,0x87,0xe0,0x14,0xfa,0x02,0xd0,0xfe,0x00,0x28,0x0a,0x3d,0xea,0x02,
|
||||
0xd0,0x79,0xfe,0x01,0xca,0x91,0x02,0x0d,0xc2,0x91,0x02,0xc9,0x0e,0x26,0xcd,0x4a,
|
||||
0x03,0xcd,0x11,0x02,0xcd,0x62,0x02,0x0d,0x20,0xf4,0xcd,0x11,0x02,0x3e,0x01,0xe0,
|
||||
0x4f,0xcd,0x3e,0x03,0xcd,0x41,0x03,0xaf,0xe0,0x4f,0xcd,0x3e,0x03,0xc9,0x21,0x08,
|
||||
0x00,0x11,0x51,0xff,0x0e,0x05,0xcd,0x0a,0x02,0xc9,0xc5,0xd5,0xe5,0x21,0x40,0xd8,
|
||||
0x0e,0x20,0x7e,0xe6,0x1f,0xfe,0x1f,0x28,0x01,0x3c,0x57,0x2a,0x07,0x07,0x07,0xe6,
|
||||
0x07,0x47,0x3a,0x07,0x07,0x07,0xe6,0x18,0xb0,0xfe,0x1f,0x28,0x01,0x3c,0x0f,0x0f,
|
||||
0x0f,0x47,0xe6,0xe0,0xb2,0x22,0x78,0xe6,0x03,0x5f,0x7e,0x0f,0x0f,0xe6,0x1f,0xfe,
|
||||
0x1f,0x28,0x01,0x3c,0x07,0x07,0xb3,0x22,0x0d,0x20,0xc7,0xe1,0xd1,0xc1,0xc9,0x0e,
|
||||
0x00,0x1a,0xe6,0xf0,0xcb,0x49,0x28,0x02,0xcb,0x37,0x47,0x23,0x7e,0xb0,0x22,0x1a,
|
||||
0xe6,0x0f,0xcb,0x49,0x20,0x02,0xcb,0x37,0x47,0x23,0x7e,0xb0,0x22,0x13,0xcb,0x41,
|
||||
0x28,0x0d,0xd5,0x11,0xf8,0xff,0xcb,0x49,0x28,0x03,0x11,0x08,0x00,0x19,0xd1,0x0c,
|
||||
0x79,0xfe,0x18,0x20,0xcc,0xc9,0x47,0xd5,0x16,0x04,0x58,0xcb,0x10,0x17,0xcb,0x13,
|
||||
0x17,0x15,0x20,0xf6,0xd1,0x22,0x23,0x22,0x23,0xc9,0x3e,0x19,0xea,0x10,0x99,0x21,
|
||||
0x2f,0x99,0x0e,0x0c,0x3d,0x28,0x08,0x32,0x0d,0x20,0xf9,0x2e,0x0f,0x18,0xf3,0xc9,
|
||||
0x3e,0x01,0xe0,0x4f,0xcd,0x00,0x02,0x11,0x07,0x06,0x21,0x80,0x80,0x0e,0xc0,0x1a,
|
||||
0x22,0x23,0x22,0x23,0x13,0x0d,0x20,0xf7,0x11,0x04,0x01,0xcd,0x8f,0x03,0x01,0xa8,
|
||||
0xff,0x09,0xcd,0x8f,0x03,0x01,0xf8,0xff,0x09,0x11,0x72,0x00,0x0e,0x08,0x23,0x1a,
|
||||
0x22,0x13,0x0d,0x20,0xf9,0x21,0xc2,0x98,0x06,0x08,0x3e,0x08,0x0e,0x10,0x22,0x0d,
|
||||
0x20,0xfc,0x11,0x10,0x00,0x19,0x05,0x20,0xf3,0xaf,0xe0,0x4f,0x21,0xc2,0x98,0x3e,
|
||||
0x08,0x22,0x3c,0xfe,0x18,0x20,0x02,0x2e,0xe2,0xfe,0x28,0x20,0x03,0x21,0x02,0x99,
|
||||
0xfe,0x38,0x20,0xed,0x21,0xd8,0x08,0x11,0x40,0xd8,0x06,0x08,0x3e,0xff,0x12,0x13,
|
||||
0x12,0x13,0x0e,0x02,0xcd,0x0a,0x02,0x3e,0x00,0x12,0x13,0x12,0x13,0x13,0x13,0x05,
|
||||
0x20,0xea,0xcd,0x62,0x02,0x21,0x4b,0x01,0x7e,0xfe,0x33,0x20,0x0b,0x2e,0x44,0x1e,
|
||||
0x30,0x2a,0xbb,0x20,0x49,0x1c,0x18,0x04,0x2e,0x4b,0x1e,0x01,0x2a,0xbb,0x20,0x3e,
|
||||
0x2e,0x34,0x01,0x10,0x00,0x2a,0x80,0x47,0x0d,0x20,0xfa,0xea,0x00,0xd0,0x21,0xc7,
|
||||
0x06,0x0e,0x00,0x2a,0xb8,0x28,0x08,0x0c,0x79,0xfe,0x4f,0x20,0xf6,0x18,0x1f,0x79,
|
||||
0xd6,0x41,0x38,0x1c,0x21,0x16,0x07,0x16,0x00,0x5f,0x19,0xfa,0x37,0x01,0x57,0x7e,
|
||||
0xba,0x28,0x0d,0x11,0x0e,0x00,0x19,0x79,0x83,0x4f,0xd6,0x5e,0x38,0xed,0x0e,0x00,
|
||||
0x21,0x33,0x07,0x06,0x00,0x09,0x7e,0xe6,0x1f,0xea,0x08,0xd0,0x7e,0xe6,0xe0,0x07,
|
||||
0x07,0x07,0xea,0x0b,0xd0,0xcd,0xe9,0x04,0xc9,0x11,0x91,0x07,0x21,0x00,0xd9,0xfa,
|
||||
0x0b,0xd0,0x47,0x0e,0x1e,0xcb,0x40,0x20,0x02,0x13,0x13,0x1a,0x22,0x20,0x02,0x1b,
|
||||
0x1b,0xcb,0x48,0x20,0x02,0x13,0x13,0x1a,0x22,0x13,0x13,0x20,0x02,0x1b,0x1b,0xcb,
|
||||
0x50,0x28,0x05,0x1b,0x2b,0x1a,0x22,0x13,0x1a,0x22,0x13,0x0d,0x20,0xd7,0x21,0x00,
|
||||
0xd9,0x11,0x00,0xda,0xcd,0x64,0x05,0xc9,0x21,0x12,0x00,0xfa,0x05,0xd0,0x07,0x07,
|
||||
0x06,0x00,0x4f,0x09,0x11,0x40,0xd8,0x06,0x08,0xe5,0x0e,0x02,0xcd,0x0a,0x02,0x13,
|
||||
0x13,0x13,0x13,0x13,0x13,0xe1,0x05,0x20,0xf0,0x11,0x42,0xd8,0x0e,0x02,0xcd,0x0a,
|
||||
0x02,0x11,0x4a,0xd8,0x0e,0x02,0xcd,0x0a,0x02,0x2b,0x2b,0x11,0x44,0xd8,0x0e,0x02,
|
||||
0xcd,0x0a,0x02,0xc9,0x0e,0x60,0x2a,0xe5,0xc5,0x21,0xe8,0x07,0x06,0x00,0x4f,0x09,
|
||||
0x0e,0x08,0xcd,0x0a,0x02,0xc1,0xe1,0x0d,0x20,0xec,0xc9,0xfa,0x08,0xd0,0x11,0x18,
|
||||
0x00,0x3c,0x3d,0x28,0x03,0x19,0x20,0xfa,0xc9,0xcd,0x1d,0x02,0x78,0xe6,0xff,0x28,
|
||||
0x0f,0x21,0xe4,0x08,0x06,0x00,0x2a,0xb9,0x28,0x08,0x04,0x78,0xfe,0x0c,0x20,0xf6,
|
||||
0x18,0x2d,0x78,0xea,0x05,0xd0,0x3e,0x1e,0xea,0x02,0xd0,0x11,0x0b,0x00,0x19,0x56,
|
||||
0x7a,0xe6,0x1f,0x5f,0x21,0x08,0xd0,0x3a,0x22,0x7b,0x77,0x7a,0xe6,0xe0,0x07,0x07,
|
||||
0x07,0x5f,0x21,0x0b,0xd0,0x3a,0x22,0x7b,0x77,0xcd,0xe9,0x04,0xcd,0x28,0x05,0xc9,
|
||||
0xcd,0x11,0x02,0xfa,0x43,0x01,0xcb,0x7f,0x28,0x04,0xe0,0x4c,0x18,0x28,0x3e,0x04,
|
||||
0xe0,0x4c,0x3e,0x01,0xe0,0x6c,0x21,0x00,0xda,0xcd,0x7b,0x05,0x06,0x10,0x16,0x00,
|
||||
0x1e,0x08,0xcd,0x4a,0x02,0x21,0x7a,0x00,0xfa,0x00,0xd0,0x47,0x0e,0x02,0x2a,0xb8,
|
||||
0xcc,0xda,0x03,0x0d,0x20,0xf8,0xc9,0x01,0x0f,0x3f,0x7e,0xff,0xff,0xc0,0x00,0xc0,
|
||||
0xf0,0xf1,0x03,0x7c,0xfc,0xfe,0xfe,0x03,0x07,0x07,0x0f,0xe0,0xe0,0xf0,0xf0,0x1e,
|
||||
0x3e,0x7e,0xfe,0x0f,0x0f,0x1f,0x1f,0xff,0xff,0x00,0x00,0x01,0x01,0x01,0x03,0xff,
|
||||
0xff,0xe1,0xe0,0xc0,0xf0,0xf9,0xfb,0x1f,0x7f,0xf8,0xe0,0xf3,0xfd,0x3e,0x1e,0xe0,
|
||||
0xf0,0xf9,0x7f,0x3e,0x7c,0xf8,0xe0,0xf8,0xf0,0xf0,0xf8,0x00,0x00,0x7f,0x7f,0x07,
|
||||
0x0f,0x9f,0xbf,0x9e,0x1f,0xff,0xff,0x0f,0x1e,0x3e,0x3c,0xf1,0xfb,0x7f,0x7f,0xfe,
|
||||
0xde,0xdf,0x9f,0x1f,0x3f,0x3e,0x3c,0xf8,0xf8,0x00,0x00,0x03,0x03,0x07,0x07,0xff,
|
||||
0xff,0xc1,0xc0,0xf3,0xe7,0xf7,0xf3,0xc0,0xc0,0xc0,0xc0,0x1f,0x1f,0x1e,0x3e,0x3f,
|
||||
0x1f,0x3e,0x3e,0x80,0x00,0x00,0x00,0x7c,0x1f,0x07,0x00,0x0f,0xff,0xfe,0x00,0x7c,
|
||||
0xf8,0xf0,0x00,0x1f,0x0f,0x0f,0x00,0x7c,0xf8,0xf8,0x00,0x3f,0x3e,0x1c,0x00,0x0f,
|
||||
0x0f,0x0f,0x00,0x7c,0xff,0xff,0x00,0x00,0xf8,0xf8,0x00,0x07,0x0f,0x0f,0x00,0x81,
|
||||
0xff,0xff,0x00,0xf3,0xe1,0x80,0x00,0xe0,0xff,0x7f,0x00,0xfc,0xf0,0xc0,0x00,0x3e,
|
||||
0x7c,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x16,0x36,0xd1,0xdb,0xf2,0x3c,0x8c,
|
||||
0x92,0x3d,0x5c,0x58,0xc9,0x3e,0x70,0x1d,0x59,0x69,0x19,0x35,0xa8,0x14,0xaa,0x75,
|
||||
0x95,0x99,0x34,0x6f,0x15,0xff,0x97,0x4b,0x90,0x17,0x10,0x39,0xf7,0xf6,0xa2,0x49,
|
||||
0x4e,0x43,0x68,0xe0,0x8b,0xf0,0xce,0x0c,0x29,0xe8,0xb7,0x86,0x9a,0x52,0x01,0x9d,
|
||||
0x71,0x9c,0xbd,0x5d,0x6d,0x67,0x3f,0x6b,0xb3,0x46,0x28,0xa5,0xc6,0xd3,0x27,0x61,
|
||||
0x18,0x66,0x6a,0xbf,0x0d,0xf4,0x42,0x45,0x46,0x41,0x41,0x52,0x42,0x45,0x4b,0x45,
|
||||
0x4b,0x20,0x52,0x2d,0x55,0x52,0x41,0x52,0x20,0x49,0x4e,0x41,0x49,0x4c,0x49,0x43,
|
||||
0x45,0x20,0x52,0x7c,0x08,0x12,0xa3,0xa2,0x07,0x87,0x4b,0x20,0x12,0x65,0xa8,0x16,
|
||||
0xa9,0x86,0xb1,0x68,0xa0,0x87,0x66,0x12,0xa1,0x30,0x3c,0x12,0x85,0x12,0x64,0x1b,
|
||||
0x07,0x06,0x6f,0x6e,0x6e,0xae,0xaf,0x6f,0xb2,0xaf,0xb2,0xa8,0xab,0x6f,0xaf,0x86,
|
||||
0xae,0xa2,0xa2,0x12,0xaf,0x13,0x12,0xa1,0x6e,0xaf,0xaf,0xad,0x06,0x4c,0x6e,0xaf,
|
||||
0xaf,0x12,0x7c,0xac,0xa8,0x6a,0x6e,0x13,0xa0,0x2d,0xa8,0x2b,0xac,0x64,0xac,0x6d,
|
||||
0x87,0xbc,0x60,0xb4,0x13,0x72,0x7c,0xb5,0xae,0xae,0x7c,0x7c,0x65,0xa2,0x6c,0x64,
|
||||
0x85,0x80,0xb0,0x40,0x88,0x20,0x68,0xde,0x00,0x70,0xde,0x20,0x78,0x20,0x20,0x38,
|
||||
0x20,0xb0,0x90,0x20,0xb0,0xa0,0xe0,0xb0,0xc0,0x98,0xb6,0x48,0x80,0xe0,0x50,0x1e,
|
||||
0x1e,0x58,0x20,0xb8,0xe0,0x88,0xb0,0x10,0x20,0x00,0x10,0x20,0xe0,0x18,0xe0,0x18,
|
||||
0x00,0x18,0xe0,0x20,0xa8,0xe0,0x20,0x18,0xe0,0x00,0x20,0x18,0xd8,0xc8,0x18,0xe0,
|
||||
0x00,0xe0,0x40,0x28,0x28,0x28,0x18,0xe0,0x60,0x20,0x18,0xe0,0x00,0x00,0x08,0xe0,
|
||||
0x18,0x30,0xd0,0xd0,0xd0,0x20,0xe0,0xe8,0xff,0x7f,0xbf,0x32,0xd0,0x00,0x00,0x00,
|
||||
0x9f,0x63,0x79,0x42,0xb0,0x15,0xcb,0x04,0xff,0x7f,0x31,0x6e,0x4a,0x45,0x00,0x00,
|
||||
0xff,0x7f,0xef,0x1b,0x00,0x02,0x00,0x00,0xff,0x7f,0x1f,0x42,0xf2,0x1c,0x00,0x00,
|
||||
0xff,0x7f,0x94,0x52,0x4a,0x29,0x00,0x00,0xff,0x7f,0xff,0x03,0x2f,0x01,0x00,0x00,
|
||||
0xff,0x7f,0xef,0x03,0xd6,0x01,0x00,0x00,0xff,0x7f,0xb5,0x42,0xc8,0x3d,0x00,0x00,
|
||||
0x74,0x7e,0xff,0x03,0x80,0x01,0x00,0x00,0xff,0x67,0xac,0x77,0x13,0x1a,0x6b,0x2d,
|
||||
0xd6,0x7e,0xff,0x4b,0x75,0x21,0x00,0x00,0xff,0x53,0x5f,0x4a,0x52,0x7e,0x00,0x00,
|
||||
0xff,0x4f,0xd2,0x7e,0x4c,0x3a,0xe0,0x1c,0xed,0x03,0xff,0x7f,0x5f,0x25,0x00,0x00,
|
||||
0x6a,0x03,0x1f,0x02,0xff,0x03,0xff,0x7f,0xff,0x7f,0xdf,0x01,0x12,0x01,0x00,0x00,
|
||||
0x1f,0x23,0x5f,0x03,0xf2,0x00,0x09,0x00,0xff,0x7f,0xea,0x03,0x1f,0x01,0x00,0x00,
|
||||
0x9f,0x29,0x1a,0x00,0x0c,0x00,0x00,0x00,0xff,0x7f,0x7f,0x02,0x1f,0x00,0x00,0x00,
|
||||
0xff,0x7f,0xe0,0x03,0x06,0x02,0x20,0x01,0xff,0x7f,0xeb,0x7e,0x1f,0x00,0x00,0x7c,
|
||||
0xff,0x7f,0xff,0x3f,0x00,0x7e,0x1f,0x00,0xff,0x7f,0xff,0x03,0x1f,0x00,0x00,0x00,
|
||||
0xff,0x03,0x1f,0x00,0x0c,0x00,0x00,0x00,0xff,0x7f,0x3f,0x03,0x93,0x01,0x00,0x00,
|
||||
0x00,0x00,0x00,0x42,0x7f,0x03,0xff,0x7f,0xff,0x7f,0x8c,0x7e,0x00,0x7c,0x00,0x00,
|
||||
0xff,0x7f,0xef,0x1b,0x80,0x61,0x00,0x00,0xff,0x7f,0x00,0x7c,0xe0,0x03,0x1f,0x7c,
|
||||
0x1f,0x00,0xff,0x03,0x40,0x41,0x42,0x20,0x21,0x22,0x80,0x81,0x82,0x10,0x11,0x12,
|
||||
0x12,0xb0,0x79,0xb8,0xad,0x16,0x17,0x07,0xba,0x05,0x7c,0x13,0x00,0x00,0x00,0x00,
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,23 +0,0 @@
|
|||
#ifdef SYSTEM_CPP
|
||||
|
||||
//SHA256 = cf053eccb4ccafff9e67339d4e78e98dce7d1ed59be819d2a1ba2232c6fce1c7
|
||||
const uint8_t System::BootROM::dmg[256] = {
|
||||
0x31,0xfe,0xff,0xaf,0x21,0xff,0x9f,0x32,0xcb,0x7c,0x20,0xfb,0x21,0x26,0xff,0x0e,
|
||||
0x11,0x3e,0x80,0x32,0xe2,0x0c,0x3e,0xf3,0xe2,0x32,0x3e,0x77,0x77,0x3e,0xfc,0xe0,
|
||||
0x47,0x11,0x04,0x01,0x21,0x10,0x80,0x1a,0xcd,0x95,0x00,0xcd,0x96,0x00,0x13,0x7b,
|
||||
0xfe,0x34,0x20,0xf3,0x11,0xd8,0x00,0x06,0x08,0x1a,0x13,0x22,0x23,0x05,0x20,0xf9,
|
||||
0x3e,0x19,0xea,0x10,0x99,0x21,0x2f,0x99,0x0e,0x0c,0x3d,0x28,0x08,0x32,0x0d,0x20,
|
||||
0xf9,0x2e,0x0f,0x18,0xf3,0x67,0x3e,0x64,0x57,0xe0,0x42,0x3e,0x91,0xe0,0x40,0x04,
|
||||
0x1e,0x02,0x0e,0x0c,0xf0,0x44,0xfe,0x90,0x20,0xfa,0x0d,0x20,0xf7,0x1d,0x20,0xf2,
|
||||
0x0e,0x13,0x24,0x7c,0x1e,0x83,0xfe,0x62,0x28,0x06,0x1e,0xc1,0xfe,0x64,0x20,0x06,
|
||||
0x7b,0xe2,0x0c,0x3e,0x87,0xe2,0xf0,0x42,0x90,0xe0,0x42,0x15,0x20,0xd2,0x05,0x20,
|
||||
0x4f,0x16,0x20,0x18,0xcb,0x4f,0x06,0x04,0xc5,0xcb,0x11,0x17,0xc1,0xcb,0x11,0x17,
|
||||
0x05,0x20,0xf5,0x22,0x23,0x22,0x23,0xc9,0xce,0xed,0x66,0x66,0xcc,0x0d,0x00,0x0b,
|
||||
0x03,0x73,0x00,0x83,0x00,0x0c,0x00,0x0d,0x00,0x08,0x11,0x1f,0x88,0x89,0x00,0x0e,
|
||||
0xdc,0xcc,0x6e,0xe6,0xdd,0xdd,0xd9,0x99,0xbb,0xbb,0x67,0x63,0x6e,0x0e,0xec,0xcc,
|
||||
0xdd,0xdc,0x99,0x9f,0xbb,0xb9,0x33,0x3e,0x3c,0x42,0xb9,0xa5,0xb9,0xa5,0x42,0x3c,
|
||||
0x21,0x04,0x01,0x11,0xa8,0x00,0x1a,0x13,0xbe,0x20,0xfe,0x23,0x7d,0xfe,0x34,0x20,
|
||||
0xf5,0x06,0x19,0x78,0x86,0x23,0x05,0x20,0xfb,0x86,0x20,0xfe,0x3e,0x01,0xe0,0x50,
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,23 +0,0 @@
|
|||
#ifdef SYSTEM_CPP
|
||||
|
||||
//SHA256 = 0e4ddff32fc9d1eeaae812a157dd246459b00c9e14f2f61751f661f32361e360
|
||||
const uint8_t System::BootROM::sgb[256] = {
|
||||
0x31,0xfe,0xff,0x3e,0x30,0xe0,0x00,0xaf,0x21,0xff,0x9f,0x32,0xcb,0x7c,0x20,0xfb,
|
||||
0x21,0x26,0xff,0x0e,0x11,0x3e,0x80,0x32,0xe2,0x0c,0x3e,0xf3,0xe2,0x32,0x3e,0x77,
|
||||
0x77,0x3e,0xfc,0xe0,0x47,0x21,0x5f,0xc0,0x0e,0x08,0xaf,0x32,0x0d,0x20,0xfc,0x11,
|
||||
0x4f,0x01,0x3e,0xfb,0x0e,0x06,0xf5,0x06,0x00,0x1a,0x1b,0x32,0x80,0x47,0x0d,0x20,
|
||||
0xf8,0x32,0xf1,0x32,0x0e,0x0e,0xd6,0x02,0xfe,0xef,0x20,0xea,0x11,0x04,0x01,0x21,
|
||||
0x10,0x80,0x1a,0xcd,0xd3,0x00,0xcd,0xd4,0x00,0x13,0x7b,0xfe,0x34,0x20,0xf3,0x11,
|
||||
0xe6,0x00,0x06,0x08,0x1a,0x13,0x22,0x23,0x05,0x20,0xf9,0x3e,0x19,0xea,0x10,0x99,
|
||||
0x21,0x2f,0x99,0x0e,0x0c,0x3d,0x28,0x08,0x32,0x0d,0x20,0xf9,0x2e,0x0f,0x18,0xf3,
|
||||
0x3e,0x91,0xe0,0x40,0x21,0x00,0xc0,0x0e,0x00,0x3e,0x00,0xe2,0x3e,0x30,0xe2,0x06,
|
||||
0x10,0x1e,0x08,0x2a,0x57,0xcb,0x42,0x3e,0x10,0x20,0x02,0x3e,0x20,0xe2,0x3e,0x30,
|
||||
0xe2,0xcb,0x1a,0x1d,0x20,0xef,0x05,0x20,0xe8,0x3e,0x20,0xe2,0x3e,0x30,0xe2,0xcd,
|
||||
0xc2,0x00,0x7d,0xfe,0x60,0x20,0xd2,0x0e,0x13,0x3e,0xc1,0xe2,0x0c,0x3e,0x07,0xe2,
|
||||
0x18,0x3a,0x16,0x04,0xf0,0x44,0xfe,0x90,0x20,0xfa,0x1e,0x00,0x1d,0x20,0xfd,0x15,
|
||||
0x20,0xf2,0xc9,0x4f,0x06,0x04,0xc5,0xcb,0x11,0x17,0xc1,0xcb,0x11,0x17,0x05,0x20,
|
||||
0xf5,0x22,0x23,0x22,0x23,0xc9,0x3c,0x42,0xb9,0xa5,0xb9,0xa5,0x42,0x3c,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x01,0xe0,0x50,
|
||||
};
|
||||
|
||||
#endif
|
|
@ -3,9 +3,6 @@
|
|||
#define SYSTEM_CPP
|
||||
namespace GB {
|
||||
|
||||
#include "bootrom-dmg.cpp"
|
||||
#include "bootrom-sgb.cpp"
|
||||
#include "bootrom-cgb.cpp"
|
||||
#include "serialization.cpp"
|
||||
System system;
|
||||
|
||||
|
@ -42,6 +39,11 @@ void System::runthreadtosave() {
|
|||
}
|
||||
|
||||
void System::init() {
|
||||
file fp;
|
||||
fp.open("/home/byuu/Desktop/boot.rom", file::mode::write);
|
||||
fp.write(bootROM.sgb, 256);
|
||||
fp.close();
|
||||
|
||||
assert(interface != 0);
|
||||
}
|
||||
|
||||
|
@ -61,4 +63,10 @@ void System::power() {
|
|||
clocks_executed = 0;
|
||||
}
|
||||
|
||||
System::System() {
|
||||
for(auto &byte : bootROM.dmg) byte = 0;
|
||||
for(auto &byte : bootROM.sgb) byte = 0;
|
||||
for(auto &byte : bootROM.cgb) byte = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,9 +16,9 @@ struct System : property<System> {
|
|||
inline bool cgb() const { return revision == Revision::GameBoyColor; }
|
||||
|
||||
struct BootROM {
|
||||
static const uint8 dmg[ 256];
|
||||
static const uint8 sgb[ 256];
|
||||
static const uint8 cgb[2048];
|
||||
uint8 dmg[ 256];
|
||||
uint8 sgb[ 256];
|
||||
uint8 cgb[2048];
|
||||
} bootROM;
|
||||
|
||||
void run();
|
||||
|
@ -40,6 +40,8 @@ struct System : property<System> {
|
|||
void serialize(serializer&);
|
||||
void serialize_all(serializer&);
|
||||
void serialize_init();
|
||||
|
||||
System();
|
||||
};
|
||||
|
||||
#include <gb/interface/interface.hpp>
|
||||
|
|
|
@ -25,7 +25,7 @@ bool Cartridge::load(const string &markup, const uint8_t *data, unsigned size) {
|
|||
has_sram = true;
|
||||
ram.size = numeral(info["size"].data);
|
||||
ram.mask = ram.size - 1;
|
||||
for(unsigned n = 0; n < ram.size; n++) ram.data[n] = 0;
|
||||
for(unsigned n = 0; n < ram.size; n++) ram.data[n] = 0xff;
|
||||
}
|
||||
|
||||
if(info["type"].data == "EEPROM") {
|
||||
|
@ -33,14 +33,14 @@ bool Cartridge::load(const string &markup, const uint8_t *data, unsigned size) {
|
|||
eeprom.size = numeral(info["size"].data);
|
||||
eeprom.mask = size > 16 * 1024 * 1024 ? 0x0fffff00 : 0x0f000000;
|
||||
eeprom.test = size > 16 * 1024 * 1024 ? 0x0dffff00 : 0x0d000000;
|
||||
for(unsigned n = 0; n < eeprom.size; n++) eeprom.data[n] = 0;
|
||||
for(unsigned n = 0; n < eeprom.size; n++) eeprom.data[n] = 0xff;
|
||||
}
|
||||
|
||||
if(info["type"].data == "FlashROM") {
|
||||
has_flashrom = true;
|
||||
flashrom.id = numeral(info["id"].data);
|
||||
flashrom.size = numeral(info["size"].data);
|
||||
for(unsigned n = 0; n < flashrom.size; n++) flashrom.data[n] = 0;
|
||||
for(unsigned n = 0; n < flashrom.size; n++) flashrom.data[n] = 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,9 +78,6 @@ void Cartridge::FlashROM::write(uint16 addr, uint8 byte) {
|
|||
}
|
||||
|
||||
void Cartridge::FlashROM::power() {
|
||||
id = 0x09c2;
|
||||
size = 128 * 1024;
|
||||
|
||||
unlockhi = false;
|
||||
unlocklo = false;
|
||||
idmode = false;
|
||||
|
|
|
@ -132,7 +132,9 @@ void CPU::power() {
|
|||
|
||||
for(unsigned n = 0x0b0; n <= 0x0df; n++) bus.mmio[n] = this; //DMA
|
||||
for(unsigned n = 0x100; n <= 0x10f; n++) bus.mmio[n] = this; //Timers
|
||||
for(unsigned n = 0x120; n <= 0x12b; n++) bus.mmio[n] = this; //Serial
|
||||
for(unsigned n = 0x130; n <= 0x133; n++) bus.mmio[n] = this; //Keypad
|
||||
for(unsigned n = 0x134; n <= 0x159; n++) bus.mmio[n] = this; //Serial
|
||||
for(unsigned n = 0x200; n <= 0x209; n++) bus.mmio[n] = this; //System
|
||||
for(unsigned n = 0x300; n <= 0x301; n++) bus.mmio[n] = this; //System
|
||||
//0x080-0x083 mirrored via gba/memory/memory.cpp //System
|
||||
|
|
|
@ -39,6 +39,27 @@ uint8 CPU::read(uint32 addr) {
|
|||
return timer.control >> shift;
|
||||
}
|
||||
|
||||
//SIOMULTI0 (SIODATA32_L)
|
||||
//SIOMULTI1 (SIODATA32_H)
|
||||
//SIOMULTI2
|
||||
//SIOMULTI3
|
||||
case 0x04000120: case 0x04000121:
|
||||
case 0x04000122: case 0x04000123:
|
||||
case 0x04000124: case 0x04000125:
|
||||
case 0x04000126: case 0x04000127: {
|
||||
auto &data = regs.serial.data[(addr >> 1) & 3];
|
||||
unsigned shift = (addr & 1) * 8;
|
||||
return data >> shift;
|
||||
}
|
||||
|
||||
//SIOCNT
|
||||
case 0x04000128: return regs.serial.control >> 0;
|
||||
case 0x04000129: return regs.serial.control >> 8;
|
||||
|
||||
//SIOMLT_SEND (SIODATA8)
|
||||
case 0x0400012a: return regs.serial.data8;
|
||||
case 0x0400012b: return 0u;
|
||||
|
||||
//KEYINPUT
|
||||
case 0x04000130:
|
||||
for(unsigned n = 0; n < 8; n++) result |= interface->inputPoll(n) << n;
|
||||
|
@ -54,6 +75,32 @@ uint8 CPU::read(uint32 addr) {
|
|||
case 0x04000132: return regs.keypad.control >> 0;
|
||||
case 0x04000133: return regs.keypad.control >> 8;
|
||||
|
||||
//RCNT
|
||||
case 0x04000134: return regs.joybus.settings >> 0;
|
||||
case 0x04000135: return regs.joybus.settings >> 8;
|
||||
|
||||
//JOYCNT
|
||||
case 0x04000140: return regs.joybus.control >> 0;
|
||||
case 0x04000141: return regs.joybus.control >> 8;
|
||||
|
||||
//JOY_RECV_L
|
||||
//JOY_RECV_H
|
||||
case 0x04000150: return regs.joybus.receive >> 0;
|
||||
case 0x04000151: return regs.joybus.receive >> 8;
|
||||
case 0x04000152: return regs.joybus.receive >> 16;
|
||||
case 0x04000153: return regs.joybus.receive >> 24;
|
||||
|
||||
//JOY_TRANS_L
|
||||
//JOY_TRANS_H
|
||||
case 0x04000154: return regs.joybus.transmit >> 0;
|
||||
case 0x04000155: return regs.joybus.transmit >> 8;
|
||||
case 0x04000156: return regs.joybus.transmit >> 16;
|
||||
case 0x04000157: return regs.joybus.transmit >> 24;
|
||||
|
||||
//JOYSTAT
|
||||
case 0x04000158: return regs.joybus.status >> 0;
|
||||
case 0x04000159: return regs.joybus.status >> 8;
|
||||
|
||||
//IE
|
||||
case 0x04000200: return regs.irq.enable >> 0;
|
||||
case 0x04000201: return regs.irq.enable >> 8;
|
||||
|
@ -183,10 +230,58 @@ void CPU::write(uint32 addr, uint8 byte) {
|
|||
return;
|
||||
}
|
||||
|
||||
//SIOMULTI0 (SIODATA32_L)
|
||||
//SIOMULTI1 (SIODATA32_H)
|
||||
//SIOMULTI2
|
||||
//SIOMULTI3
|
||||
case 0x04000120: case 0x04000121:
|
||||
case 0x04000122: case 0x04000123:
|
||||
case 0x04000124: case 0x04000125:
|
||||
case 0x04000126: case 0x04000127: {
|
||||
auto &data = regs.serial.data[(addr >> 1) & 3];
|
||||
unsigned shift = (addr & 1) * 8;
|
||||
data = (data & ~(255 << shift)) | (byte << shift);
|
||||
return;
|
||||
}
|
||||
|
||||
//SIOCNT
|
||||
case 0x04000128: regs.serial.control = (regs.serial.control & 0xff00) | (byte << 0); return;
|
||||
case 0x04000129: regs.serial.control = (regs.serial.control & 0x00ff) | (byte << 8); return;
|
||||
|
||||
//SIOMLT_SEND (SIODATA8)
|
||||
case 0x0400012a: regs.serial.data8 = byte; return;
|
||||
case 0x0400012b: return;
|
||||
|
||||
//KEYCNT
|
||||
case 0x04000132: regs.keypad.control = (regs.keypad.control & 0xff00) | (byte << 0); return;
|
||||
case 0x04000133: regs.keypad.control = (regs.keypad.control & 0x00ff) | (byte << 8); return;
|
||||
|
||||
//RCNT
|
||||
case 0x04000134: regs.joybus.settings = (regs.joybus.settings & 0xff00) | (byte << 0); return;
|
||||
case 0x04000135: regs.joybus.settings = (regs.joybus.settings & 0x00ff) | (byte << 8); return;
|
||||
|
||||
//JOYCNT
|
||||
case 0x04000140: regs.joybus.control = (regs.joybus.control & 0xff00) | (byte << 0); return;
|
||||
case 0x04000141: regs.joybus.control = (regs.joybus.control & 0x00ff) | (byte << 8); return;
|
||||
|
||||
//JOY_RECV_L
|
||||
//JOY_RECV_H
|
||||
case 0x04000150: regs.joybus.receive = (regs.joybus.receive & 0xffffff00) | (byte << 0); return;
|
||||
case 0x04000151: regs.joybus.receive = (regs.joybus.receive & 0xffff00ff) | (byte << 8); return;
|
||||
case 0x04000152: regs.joybus.receive = (regs.joybus.receive & 0xff00ffff) | (byte << 16); return;
|
||||
case 0x04000153: regs.joybus.receive = (regs.joybus.receive & 0x00ffffff) | (byte << 24); return;
|
||||
|
||||
//JOY_TRANS_L
|
||||
//JOY_TRANS_H
|
||||
case 0x04000154: regs.joybus.transmit = (regs.joybus.transmit & 0xffffff00) | (byte << 0); return;
|
||||
case 0x04000155: regs.joybus.transmit = (regs.joybus.transmit & 0xffff00ff) | (byte << 8); return;
|
||||
case 0x04000156: regs.joybus.transmit = (regs.joybus.transmit & 0xff00ffff) | (byte << 16); return;
|
||||
case 0x04000157: regs.joybus.transmit = (regs.joybus.transmit & 0x00ffffff) | (byte << 24); return;
|
||||
|
||||
//JOYSTAT
|
||||
case 0x04000158: regs.joybus.status = (regs.joybus.status & 0xff00) | (byte << 0); return;
|
||||
case 0x04000159: regs.joybus.status = (regs.joybus.status & 0x00ff) | (byte << 8); return;
|
||||
|
||||
//IE
|
||||
case 0x04000200: regs.irq.enable = (regs.irq.enable & 0xff00) | (byte << 0); return;
|
||||
case 0x04000201: regs.irq.enable = (regs.irq.enable & 0x00ff) | (byte << 8); return;
|
||||
|
@ -200,18 +295,17 @@ void CPU::write(uint32 addr, uint8 byte) {
|
|||
case 0x04000205: regs.wait.control = (regs.wait.control & 0x00ff) | ((byte & 0x7f) << 8); return;
|
||||
|
||||
//IME
|
||||
case 0x04000208: regs.ime = byte & 1; return;
|
||||
case 0x04000208: regs.ime = byte >> 0; return;
|
||||
case 0x04000209: return;
|
||||
|
||||
//POSTFLG + HALTCNT
|
||||
case 0x04000300: regs.postboot = byte & 1; return;
|
||||
//POSTFLG, HALTCNT
|
||||
case 0x04000300: regs.postboot |= byte >> 0; return;
|
||||
case 0x04000301: regs.mode = byte & 0x80 ? Registers::Mode::Stop : Registers::Mode::Halt; return;
|
||||
|
||||
//MEMCNT_L
|
||||
//MEMCNT_H
|
||||
case 0x04000800: regs.memory.control = (regs.memory.control & 0xffffff00) | (byte << 0); return;
|
||||
case 0x04000801: regs.memory.control = (regs.memory.control & 0xffff00ff) | (byte << 8); return;
|
||||
|
||||
//MEMCNT_H
|
||||
case 0x04000802: regs.memory.control = (regs.memory.control & 0xff00ffff) | (byte << 16); return;
|
||||
case 0x04000803: regs.memory.control = (regs.memory.control & 0x00ffffff) | (byte << 24); return;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ uint16 CPU::Registers::DMAControl::operator=(uint16 source) {
|
|||
return operator uint16();
|
||||
}
|
||||
|
||||
CPU::Registers::TimerControl::operator uint8() const {
|
||||
CPU::Registers::TimerControl::operator uint16() const {
|
||||
return (
|
||||
(frequency << 0)
|
||||
| (cascade << 2)
|
||||
|
@ -32,12 +32,35 @@ CPU::Registers::TimerControl::operator uint8() const {
|
|||
);
|
||||
}
|
||||
|
||||
uint8 CPU::Registers::TimerControl::operator=(uint8 source) {
|
||||
uint16 CPU::Registers::TimerControl::operator=(uint16 source) {
|
||||
frequency = source >> 0;
|
||||
cascade = source >> 2;
|
||||
irq = source >> 6;
|
||||
enable = source >> 7;
|
||||
return operator uint8();
|
||||
return operator uint16();
|
||||
}
|
||||
|
||||
CPU::Registers::SerialControl::operator uint16() const {
|
||||
return (
|
||||
(shiftclockselect << 0)
|
||||
| (shiftclockfrequency << 1)
|
||||
| (transferenablereceive << 2)
|
||||
| (transferenablesend << 3)
|
||||
| (startbit << 7)
|
||||
| (transferlength << 12)
|
||||
| (irqenable << 14)
|
||||
);
|
||||
}
|
||||
|
||||
uint16 CPU::Registers::SerialControl::operator=(uint16 source) {
|
||||
shiftclockselect = source >> 0;
|
||||
shiftclockfrequency = source >> 1;
|
||||
transferenablereceive = source >> 2;
|
||||
transferenablesend = source >> 3;
|
||||
startbit = source >> 7;
|
||||
transferlength = source >> 12;
|
||||
irqenable = source >> 14;
|
||||
return operator uint16();
|
||||
}
|
||||
|
||||
CPU::Registers::KeypadControl::operator uint16() const {
|
||||
|
@ -73,6 +96,67 @@ uint16 CPU::Registers::KeypadControl::operator=(uint16 source) {
|
|||
return operator uint16();
|
||||
}
|
||||
|
||||
CPU::Registers::JoybusSettings::operator uint16() const {
|
||||
return (
|
||||
(sc << 0)
|
||||
| (sd << 1)
|
||||
| (si << 2)
|
||||
| (so << 3)
|
||||
| (scmode << 4)
|
||||
| (sdmode << 5)
|
||||
| (simode << 6)
|
||||
| (somode << 7)
|
||||
| (irqenable << 8)
|
||||
| (mode << 14)
|
||||
);
|
||||
}
|
||||
|
||||
uint16 CPU::Registers::JoybusSettings::operator=(uint16 source) {
|
||||
sc = source >> 0;
|
||||
sd = source >> 1;
|
||||
si = source >> 2;
|
||||
so = source >> 3;
|
||||
scmode = source >> 4;
|
||||
sdmode = source >> 5;
|
||||
simode = source >> 6;
|
||||
somode = source >> 7;
|
||||
irqenable = source >> 8;
|
||||
mode = source >> 14;
|
||||
return operator uint16();
|
||||
}
|
||||
|
||||
CPU::Registers::JoybusControl::operator uint16() const {
|
||||
return (
|
||||
(resetsignal << 0)
|
||||
| (receivecomplete << 1)
|
||||
| (sendcomplete << 2)
|
||||
| (irqenable << 6)
|
||||
);
|
||||
}
|
||||
|
||||
uint16 CPU::Registers::JoybusControl::operator=(uint16 source) {
|
||||
resetsignal = source >> 0;
|
||||
receivecomplete = source >> 1;
|
||||
sendcomplete = source >> 2;
|
||||
irqenable = source >> 6;
|
||||
return operator uint16();
|
||||
}
|
||||
|
||||
CPU::Registers::JoybusStatus::operator uint16() const {
|
||||
return (
|
||||
(receiveflag << 1)
|
||||
| (sendflag << 3)
|
||||
| (generalflag << 4)
|
||||
);
|
||||
}
|
||||
|
||||
uint16 CPU::Registers::JoybusStatus::operator=(uint16 source) {
|
||||
receiveflag = source >> 1;
|
||||
sendflag = source >> 3;
|
||||
generalflag = source >> 4;
|
||||
return operator uint16();
|
||||
}
|
||||
|
||||
CPU::Registers::Interrupt::operator uint16() const {
|
||||
return (
|
||||
(vblank << 0)
|
||||
|
@ -93,20 +177,20 @@ CPU::Registers::Interrupt::operator uint16() const {
|
|||
}
|
||||
|
||||
uint16 CPU::Registers::Interrupt::operator=(uint16 source) {
|
||||
vblank = source & (1 << 0);
|
||||
hblank = source & (1 << 1);
|
||||
vcoincidence = source & (1 << 2);
|
||||
timer[0] = source & (1 << 3);
|
||||
timer[1] = source & (1 << 4);
|
||||
timer[2] = source & (1 << 5);
|
||||
timer[3] = source & (1 << 6);
|
||||
serial = source & (1 << 7);
|
||||
dma[0] = source & (1 << 8);
|
||||
dma[1] = source & (1 << 9);
|
||||
dma[2] = source & (1 << 10);
|
||||
dma[3] = source & (1 << 11);
|
||||
keypad = source & (1 << 12);
|
||||
cartridge = source & (1 << 13);
|
||||
vblank = source >> 0;
|
||||
hblank = source >> 1;
|
||||
vcoincidence = source >> 2;
|
||||
timer[0] = source >> 3;
|
||||
timer[1] = source >> 4;
|
||||
timer[2] = source >> 5;
|
||||
timer[3] = source >> 6;
|
||||
serial = source >> 7;
|
||||
dma[0] = source >> 8;
|
||||
dma[1] = source >> 9;
|
||||
dma[2] = source >> 10;
|
||||
dma[3] = source >> 11;
|
||||
keypad = source >> 12;
|
||||
cartridge = source >> 13;
|
||||
return operator uint16();
|
||||
}
|
||||
|
||||
|
@ -151,10 +235,10 @@ CPU::Registers::MemoryControl::operator uint32() const {
|
|||
}
|
||||
|
||||
uint32 CPU::Registers::MemoryControl::operator=(uint32 source) {
|
||||
disable = (source >> 0) & 1;
|
||||
unknown1 = (source >> 1) & 7;
|
||||
ewram = (source >> 5) & 1;
|
||||
ewramwait = (source >> 24) & 15;
|
||||
unknown2 = (source >> 28) & 15;
|
||||
disable = source >> 0;
|
||||
unknown1 = source >> 1;
|
||||
ewram = source >> 5;
|
||||
ewramwait = source >> 24;
|
||||
unknown2 = source >> 28;
|
||||
return operator uint32();
|
||||
}
|
||||
|
|
|
@ -34,8 +34,8 @@ struct Registers {
|
|||
uint1 irq;
|
||||
uint1 enable;
|
||||
|
||||
operator uint8() const;
|
||||
uint8 operator=(uint8 source);
|
||||
operator uint16() const;
|
||||
uint16 operator=(uint16 source);
|
||||
TimerControl& operator=(const TimerControl&) = delete;
|
||||
};
|
||||
|
||||
|
@ -45,6 +45,26 @@ struct Registers {
|
|||
TimerControl control;
|
||||
} timer[4];
|
||||
|
||||
struct SerialControl {
|
||||
uint1 shiftclockselect;
|
||||
uint1 shiftclockfrequency;
|
||||
uint1 transferenablereceive;
|
||||
uint1 transferenablesend;
|
||||
uint1 startbit;
|
||||
uint1 transferlength;
|
||||
uint1 irqenable;
|
||||
|
||||
operator uint16() const;
|
||||
uint16 operator=(uint16 source);
|
||||
SerialControl& operator=(const SerialControl&) = delete;
|
||||
};
|
||||
|
||||
struct Serial {
|
||||
uint16 data[4];
|
||||
SerialControl control;
|
||||
uint8 data8;
|
||||
} serial;
|
||||
|
||||
struct KeypadControl {
|
||||
uint1 flag[10];
|
||||
uint1 enable;
|
||||
|
@ -59,17 +79,63 @@ struct Registers {
|
|||
KeypadControl control;
|
||||
} keypad;
|
||||
|
||||
bool ime;
|
||||
struct JoybusSettings {
|
||||
uint1 sc;
|
||||
uint1 sd;
|
||||
uint1 si;
|
||||
uint1 so;
|
||||
uint1 scmode;
|
||||
uint1 sdmode;
|
||||
uint1 simode;
|
||||
uint1 somode;
|
||||
uint1 irqenable;
|
||||
uint2 mode;
|
||||
|
||||
operator uint16() const;
|
||||
uint16 operator=(uint16 source);
|
||||
JoybusSettings& operator=(const JoybusSettings&) = delete;
|
||||
};
|
||||
|
||||
struct JoybusControl {
|
||||
uint1 resetsignal;
|
||||
uint1 receivecomplete;
|
||||
uint1 sendcomplete;
|
||||
uint1 irqenable;
|
||||
|
||||
operator uint16() const;
|
||||
uint16 operator=(uint16 source);
|
||||
JoybusControl& operator=(const JoybusControl&) = delete;
|
||||
};
|
||||
|
||||
struct JoybusStatus {
|
||||
uint1 receiveflag;
|
||||
uint1 sendflag;
|
||||
uint2 generalflag;
|
||||
|
||||
operator uint16() const;
|
||||
uint16 operator=(uint16 source);
|
||||
JoybusStatus& operator=(const JoybusStatus&) = delete;
|
||||
};
|
||||
|
||||
struct Joybus {
|
||||
JoybusSettings settings;
|
||||
JoybusControl control;
|
||||
uint32 receive;
|
||||
uint32 transmit;
|
||||
JoybusStatus status;
|
||||
} joybus;
|
||||
|
||||
uint1 ime;
|
||||
|
||||
struct Interrupt {
|
||||
bool vblank;
|
||||
bool hblank;
|
||||
bool vcoincidence;
|
||||
bool timer[4];
|
||||
bool serial;
|
||||
bool dma[4];
|
||||
bool keypad;
|
||||
bool cartridge;
|
||||
uint1 vblank;
|
||||
uint1 hblank;
|
||||
uint1 vcoincidence;
|
||||
uint1 timer[4];
|
||||
uint1 serial;
|
||||
uint1 dma[4];
|
||||
uint1 keypad;
|
||||
uint1 cartridge;
|
||||
|
||||
operator uint16() const;
|
||||
uint16 operator=(uint16 source);
|
||||
|
@ -98,9 +164,9 @@ struct Registers {
|
|||
} wait;
|
||||
|
||||
struct MemoryControl {
|
||||
bool disable;
|
||||
uint1 disable;
|
||||
uint3 unknown1;
|
||||
bool ewram;
|
||||
uint1 ewram;
|
||||
uint4 ewramwait;
|
||||
uint4 unknown2;
|
||||
|
||||
|
@ -113,7 +179,7 @@ struct Registers {
|
|||
MemoryControl control;
|
||||
} memory;
|
||||
|
||||
bool postboot;
|
||||
uint1 postboot;
|
||||
enum class Mode : unsigned { Normal, Halt, Stop } mode;
|
||||
unsigned clock;
|
||||
} regs;
|
||||
|
|
|
@ -31,10 +31,43 @@ void CPU::serialize(serializer &s) {
|
|||
s.integer(timer.control.enable);
|
||||
}
|
||||
|
||||
for(auto &value : regs.serial.data) s.integer(value);
|
||||
s.integer(regs.serial.control.shiftclockselect);
|
||||
s.integer(regs.serial.control.shiftclockfrequency);
|
||||
s.integer(regs.serial.control.transferenablereceive);
|
||||
s.integer(regs.serial.control.transferenablesend);
|
||||
s.integer(regs.serial.control.startbit);
|
||||
s.integer(regs.serial.control.transferlength);
|
||||
s.integer(regs.serial.control.irqenable);
|
||||
s.integer(regs.serial.data8);
|
||||
|
||||
for(auto &flag : regs.keypad.control.flag) s.integer(flag);
|
||||
s.integer(regs.keypad.control.enable);
|
||||
s.integer(regs.keypad.control.condition);
|
||||
|
||||
s.integer(regs.joybus.settings.sc);
|
||||
s.integer(regs.joybus.settings.sd);
|
||||
s.integer(regs.joybus.settings.si);
|
||||
s.integer(regs.joybus.settings.so);
|
||||
s.integer(regs.joybus.settings.scmode);
|
||||
s.integer(regs.joybus.settings.sdmode);
|
||||
s.integer(regs.joybus.settings.simode);
|
||||
s.integer(regs.joybus.settings.somode);
|
||||
s.integer(regs.joybus.settings.irqenable);
|
||||
s.integer(regs.joybus.settings.mode);
|
||||
|
||||
s.integer(regs.joybus.control.resetsignal);
|
||||
s.integer(regs.joybus.control.receivecomplete);
|
||||
s.integer(regs.joybus.control.sendcomplete);
|
||||
s.integer(regs.joybus.control.irqenable);
|
||||
|
||||
s.integer(regs.joybus.receive);
|
||||
s.integer(regs.joybus.transmit);
|
||||
|
||||
s.integer(regs.joybus.status.receiveflag);
|
||||
s.integer(regs.joybus.status.sendflag);
|
||||
s.integer(regs.joybus.status.generalflag);
|
||||
|
||||
s.integer(regs.ime);
|
||||
|
||||
s.integer(regs.irq.enable.vblank);
|
||||
|
|
|
@ -72,8 +72,8 @@ void PPU::render_background_linear(Registers::Background &bg) {
|
|||
uint8 color = data[px++ ^ (tile.hflip ? 7 : 0)];
|
||||
|
||||
if(color) {
|
||||
if(bg.control.colormode == 0) output[x] = { true, false, bg.control.priority, pram[tile.palette * 16 + color] };
|
||||
if(bg.control.colormode == 1) output[x] = { true, false, bg.control.priority, pram[color] };
|
||||
if(bg.control.colormode == 0) output[x].write(true, bg.control.priority, pram[tile.palette * 16 + color]);
|
||||
if(bg.control.colormode == 1) output[x].write(true, bg.control.priority, pram[color]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ void PPU::render_background_affine(Registers::Background &bg) {
|
|||
if(tx < screensize && ty < screensize) {
|
||||
uint8 character = vram[basemap + ty * screensize + tx];
|
||||
uint8 color = vram[basechr + (character * 64) + py * 8 + px];
|
||||
if(color) output[x] = { true, false, bg.control.priority, pram[color] };
|
||||
if(color) output[x].write(true, bg.control.priority, pram[color]);
|
||||
}
|
||||
|
||||
fx += bg.pa;
|
||||
|
@ -143,7 +143,7 @@ void PPU::render_background_bitmap(Registers::Background &bg) {
|
|||
if(depth || color) { //8bpp color 0 is transparent; 15bpp color is always opaque
|
||||
if(depth == 0) color = pram[color];
|
||||
if(depth == 1) color = color & 0x7fff;
|
||||
output[x] = { true, false, bg.control.priority, color };
|
||||
output[x].write(true, bg.control.priority, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
void PPU::render_mosaic_background(unsigned id) {
|
||||
if(regs.mosaic.bghsize == 0) return;
|
||||
unsigned width = 1 + regs.mosaic.bghsize;
|
||||
auto &buffer = layer[id];
|
||||
|
||||
for(unsigned x = 0; x < 240;) {
|
||||
for(unsigned m = 1; m < width; m++) {
|
||||
if(x + m >= 240) break;
|
||||
buffer[x + m] = buffer[x];
|
||||
}
|
||||
x += width;
|
||||
}
|
||||
}
|
||||
|
||||
void PPU::render_mosaic_object() {
|
||||
if(regs.mosaic.objhsize == 0) return;
|
||||
unsigned width = 1 + regs.mosaic.objhsize;
|
||||
auto &buffer = layer[OBJ];
|
||||
|
||||
Pixel mosaicPixel;
|
||||
mosaicPixel.mosaic = false;
|
||||
unsigned counter = 0;
|
||||
|
||||
for(unsigned x = 0; x < 240; x++) {
|
||||
if(counter == width || mosaicPixel.mosaic == false) {
|
||||
mosaicPixel = buffer[x];
|
||||
if(counter == width) counter = 0;
|
||||
} else {
|
||||
if(buffer[x].mosaic) buffer[x] = mosaicPixel;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
}
|
|
@ -52,10 +52,6 @@ void PPU::render_object(Object &obj) {
|
|||
y = (fy >> 8) + centery;
|
||||
}
|
||||
|
||||
if(obj.mosaic && regs.mosaic.objhsize) {
|
||||
x = (x / (1 + regs.mosaic.objhsize)) * (1 + regs.mosaic.objhsize);
|
||||
}
|
||||
|
||||
uint9 ox = obj.x + px;
|
||||
if(ox < 240 && x < obj.width && y < obj.height) {
|
||||
unsigned offset = (y / 8) * rowsize + (x / 8);
|
||||
|
@ -68,7 +64,7 @@ void PPU::render_object(Object &obj) {
|
|||
windowmask[Obj][ox] = true;
|
||||
} else if(output[ox].enable == false || obj.priority < output[ox].priority) {
|
||||
if(obj.colors == 0) color = obj.palette * 16 + color;
|
||||
output[ox] = { true, obj.mode == 1, obj.priority, pram[256 + color] };
|
||||
output[ox].write(true, obj.priority, pram[256 + color], obj.mode == 1, obj.mosaic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace GBA {
|
|||
#include "registers.cpp"
|
||||
#include "background.cpp"
|
||||
#include "object.cpp"
|
||||
#include "mosaic.cpp"
|
||||
#include "screen.cpp"
|
||||
#include "mmio.cpp"
|
||||
#include "memory.cpp"
|
||||
|
@ -119,12 +120,12 @@ void PPU::scanline() {
|
|||
windowmask[0][x] = false;
|
||||
windowmask[1][x] = false;
|
||||
windowmask[2][x] = false;
|
||||
layer[OBJ][x].enable = false;
|
||||
layer[BG0][x].enable = false;
|
||||
layer[BG1][x].enable = false;
|
||||
layer[BG2][x].enable = false;
|
||||
layer[BG3][x].enable = false;
|
||||
layer[SFX][x] = { true, false, 3, pram[0] };
|
||||
layer[OBJ][x].write(false);
|
||||
layer[BG0][x].write(false);
|
||||
layer[BG1][x].write(false);
|
||||
layer[BG2][x].write(false);
|
||||
layer[BG3][x].write(false);
|
||||
layer[SFX][x].write(true, 3, pram[0]);
|
||||
}
|
||||
render_window(0);
|
||||
render_window(1);
|
||||
|
@ -148,7 +149,6 @@ void PPU::scanline() {
|
|||
}
|
||||
|
||||
void PPU::frame() {
|
||||
interface->videoRefresh(output);
|
||||
scheduler.exit(Scheduler::ExitReason::FrameEvent);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,9 +34,11 @@ struct PPU : Thread, MMIO {
|
|||
void render_objects();
|
||||
void render_object(Object&);
|
||||
|
||||
void render_mosaic_background(unsigned id);
|
||||
void render_mosaic_object();
|
||||
|
||||
void render_forceblank();
|
||||
void render_screen();
|
||||
void render_mosaic(unsigned id, unsigned width);
|
||||
void render_window(unsigned window);
|
||||
unsigned blend(unsigned above, unsigned eva, unsigned below, unsigned evb);
|
||||
|
||||
|
|
|
@ -11,10 +11,11 @@ void PPU::render_screen() {
|
|||
uint16 *line = output + regs.vcounter * 240;
|
||||
uint16 *last = blur + regs.vcounter * 240;
|
||||
|
||||
if(regs.bg[0].control.mosaic) render_mosaic(BG0, regs.mosaic.bghsize);
|
||||
if(regs.bg[1].control.mosaic) render_mosaic(BG1, regs.mosaic.bghsize);
|
||||
if(regs.bg[2].control.mosaic) render_mosaic(BG2, regs.mosaic.bghsize);
|
||||
if(regs.bg[3].control.mosaic) render_mosaic(BG3, regs.mosaic.bghsize);
|
||||
if(regs.bg[0].control.mosaic) render_mosaic_background(BG0);
|
||||
if(regs.bg[1].control.mosaic) render_mosaic_background(BG1);
|
||||
if(regs.bg[2].control.mosaic) render_mosaic_background(BG2);
|
||||
if(regs.bg[3].control.mosaic) render_mosaic_background(BG3);
|
||||
render_mosaic_object();
|
||||
|
||||
for(unsigned x = 0; x < 240; x++) {
|
||||
Registers::WindowFlags flags;
|
||||
|
@ -63,19 +64,6 @@ void PPU::render_screen() {
|
|||
}
|
||||
}
|
||||
|
||||
void PPU::render_mosaic(unsigned id, unsigned width) {
|
||||
if(++width == 1) return;
|
||||
auto &buffer = layer[id];
|
||||
|
||||
for(unsigned x = 0; x < 240;) {
|
||||
for(unsigned m = 1; m < width; m++) {
|
||||
if(x + m >= 240) break;
|
||||
buffer[x + m] = buffer[x];
|
||||
}
|
||||
x += width;
|
||||
}
|
||||
}
|
||||
|
||||
void PPU::render_window(unsigned w) {
|
||||
unsigned y = regs.vcounter;
|
||||
|
||||
|
|
|
@ -75,9 +75,10 @@ void PPU::serialize(serializer &s) {
|
|||
for(unsigned p = 0; p < 240; p++) {
|
||||
auto &pixel = layer[l][p];
|
||||
s.integer(pixel.enable);
|
||||
s.integer(pixel.translucent);
|
||||
s.integer(pixel.priority);
|
||||
s.integer(pixel.color);
|
||||
s.integer(pixel.translucent);
|
||||
s.integer(pixel.mosaic);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
struct Pixel {
|
||||
bool enable;
|
||||
bool translucent;
|
||||
unsigned priority;
|
||||
unsigned color;
|
||||
|
||||
//objects only
|
||||
bool translucent;
|
||||
bool mosaic;
|
||||
|
||||
alwaysinline void write(bool e) { enable = e; }
|
||||
alwaysinline void write(bool e, unsigned p, unsigned c) { enable = e; priority = p; color = c; }
|
||||
alwaysinline void write(bool e, unsigned p, unsigned c, bool t, bool m) { enable = e; priority = p; color = c; translucent = t; mosaic = m; }
|
||||
} layer[6][240];
|
||||
|
||||
bool windowmask[3][240];
|
||||
|
|
|
@ -1,12 +1,3 @@
|
|||
void BIOS::load(const uint8 *biosdata, unsigned biossize) {
|
||||
memcpy(data, biosdata, min(size, biossize));
|
||||
|
||||
string sha256 = nall::sha256(data, size);
|
||||
if(sha256 != "fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570") {
|
||||
interface->message("Warning: Game Boy Advance BIOS SHA256 sum is incorrect.");
|
||||
}
|
||||
}
|
||||
|
||||
uint32 BIOS::read(uint32 addr, uint32 size) {
|
||||
//GBA BIOS is read-protected; only the BIOS itself can read its own memory
|
||||
//when accessed elsewhere; this returns the last value read by the BIOS program
|
||||
|
|
|
@ -27,7 +27,11 @@ void System::load() {
|
|||
}
|
||||
|
||||
void System::run() {
|
||||
scheduler.enter();
|
||||
while(true) {
|
||||
scheduler.enter();
|
||||
if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) break;
|
||||
}
|
||||
interface->videoRefresh(ppu.output);
|
||||
}
|
||||
|
||||
void System::runtosave() {
|
||||
|
@ -49,7 +53,7 @@ void System::runthreadtosave() {
|
|||
while(true) {
|
||||
scheduler.enter();
|
||||
if(scheduler.exit_reason() == Scheduler::ExitReason::SynchronizeEvent) break;
|
||||
if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent);
|
||||
if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) interface->videoRefresh(ppu.output);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ struct BIOS : Memory {
|
|||
unsigned size;
|
||||
uint32 mdr;
|
||||
|
||||
void load(const uint8 *data, unsigned size);
|
||||
uint32 read(uint32 addr, uint32 size);
|
||||
void write(uint32 addr, uint32 size, uint32 word);
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<cartridge region="NTSC">
|
||||
<bsx>
|
||||
<mcu>
|
||||
<map address="00-3f:8000-ffff"/>
|
||||
<map address="80-bf:8000-ffff"/>
|
||||
<map address="40-7f:0000-ffff"/>
|
||||
<map address="c0-ff:0000-ffff"/>
|
||||
<map address="20-3f:6000-7fff"/>
|
||||
</mcu>
|
||||
<mmio>
|
||||
<map address="00-3f:5000-5fff"/>
|
||||
<map address="80-bf:5000-5fff"/>
|
||||
</mmio>
|
||||
</bsx>
|
||||
</cartridge>
|
|
@ -0,0 +1,3 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<system type="NES">
|
||||
</system>
|
Binary file not shown.
|
@ -0,0 +1,4 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<system type="GBC">
|
||||
<boot firmware="boot.rom" sha256="4bf5021be357ce523a59ac5f4efff5d6371ae50112a6db0adf4a75916ad760a9"/>
|
||||
</system>
|
Binary file not shown.
|
@ -0,0 +1,4 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<system type="GB">
|
||||
<boot firmware="boot.rom" sha256="cf053eccb4ccafff9e67339d4e78e98dce7d1ed59be819d2a1ba2232c6fce1c7"/>
|
||||
</system>
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<cartridge region="NTSC">
|
||||
<rom>
|
||||
<map mode="linear" address="00-1f:8000-ffff"/>
|
||||
<map mode="linear" address="80-9f:8000-ffff"/>
|
||||
</rom>
|
||||
<sufamiturbo>
|
||||
<slot id="A">
|
||||
<rom>
|
||||
<map mode="linear" address="20-3f:8000-ffff"/>
|
||||
<map mode="linear" address="a0-bf:8000-ffff"/>
|
||||
</rom>
|
||||
<ram size="131072">
|
||||
<map mode="linear" address="60-63:8000-ffff"/>
|
||||
<map mode="linear" address="e0-e3:8000-ffff"/>
|
||||
</ram>
|
||||
</slot>
|
||||
<slot id="B">
|
||||
<rom>
|
||||
<map mode="linear" address="40-5f:8000-ffff"/>
|
||||
<map mode="linear" address="c0-df:8000-ffff"/>
|
||||
</rom>
|
||||
<ram size="131072">
|
||||
<map mode="linear" address="70-73:8000-ffff"/>
|
||||
<map mode="linear" address="f0-f3:8000-ffff"/>
|
||||
</ram>
|
||||
</slot>
|
||||
</sufamiturbo>
|
||||
</cartridge>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<system type="SNES">
|
||||
<smp firmware="spc700.rom" sha256="c95f88b299030d5afa55b1031e2b5ef2dff650c4b4e6bb6f8b1359436521278f"/>
|
||||
</system>
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<cartridge region="NTSC">
|
||||
<boot firmware="boot.rom" sha256="0e4ddff32fc9d1eeaae812a157dd246459b00c9e14f2f61751f661f32361e360"/>
|
||||
<rom>
|
||||
<map mode="linear" address="00-7f:8000-ffff"/>
|
||||
<map mode="linear" address="80-ff:8000-ffff"/>
|
||||
</rom>
|
||||
<icd2 revision="1">
|
||||
<map address="00-3f:6000-7fff"/>
|
||||
<map address="80-bf:6000-7fff"/>
|
||||
</icd2>
|
||||
</cartridge>
|
|
@ -1,44 +0,0 @@
|
|||
#ifdef SMP_CPP
|
||||
|
||||
//this is the IPLROM for the S-SMP coprocessor.
|
||||
//the S-SMP does not allow writing to the IPLROM.
|
||||
//all writes are instead mapped to the extended
|
||||
//RAM region, accessible when $f1.d7 is clear.
|
||||
|
||||
const uint8 SMP::iplrom[64] = {
|
||||
/*ffc0*/ 0xcd, 0xef, //mov x,#$ef
|
||||
/*ffc2*/ 0xbd, //mov sp,x
|
||||
/*ffc3*/ 0xe8, 0x00, //mov a,#$00
|
||||
/*ffc5*/ 0xc6, //mov (x),a
|
||||
/*ffc6*/ 0x1d, //dec x
|
||||
/*ffc7*/ 0xd0, 0xfc, //bne $ffc5
|
||||
/*ffc9*/ 0x8f, 0xaa, 0xf4, //mov $f4,#$aa
|
||||
/*ffcc*/ 0x8f, 0xbb, 0xf5, //mov $f5,#$bb
|
||||
/*ffcf*/ 0x78, 0xcc, 0xf4, //cmp $f4,#$cc
|
||||
/*ffd2*/ 0xd0, 0xfb, //bne $ffcf
|
||||
/*ffd4*/ 0x2f, 0x19, //bra $ffef
|
||||
/*ffd6*/ 0xeb, 0xf4, //mov y,$f4
|
||||
/*ffd8*/ 0xd0, 0xfc, //bne $ffd6
|
||||
/*ffda*/ 0x7e, 0xf4, //cmp y,$f4
|
||||
/*ffdc*/ 0xd0, 0x0b, //bne $ffe9
|
||||
/*ffde*/ 0xe4, 0xf5, //mov a,$f5
|
||||
/*ffe0*/ 0xcb, 0xf4, //mov $f4,y
|
||||
/*ffe2*/ 0xd7, 0x00, //mov ($00)+y,a
|
||||
/*ffe4*/ 0xfc, //inc y
|
||||
/*ffe5*/ 0xd0, 0xf3, //bne $ffda
|
||||
/*ffe7*/ 0xab, 0x01, //inc $01
|
||||
/*ffe9*/ 0x10, 0xef, //bpl $ffda
|
||||
/*ffeb*/ 0x7e, 0xf4, //cmp y,$f4
|
||||
/*ffed*/ 0x10, 0xeb, //bpl $ffda
|
||||
/*ffef*/ 0xba, 0xf6, //movw ya,$f6
|
||||
/*fff1*/ 0xda, 0x00, //movw $00,ya
|
||||
/*fff3*/ 0xba, 0xf4, //movw ya,$f4
|
||||
/*fff5*/ 0xc4, 0xf4, //mov $f4,a
|
||||
/*fff7*/ 0xdd, //mov a,y
|
||||
/*fff8*/ 0x5d, //mov x,a
|
||||
/*fff9*/ 0xd0, 0xdb, //bne $ffd6
|
||||
/*fffb*/ 0x1f, 0x00, 0x00, //jmp ($0000+x)
|
||||
/*fffe*/ 0xc0, 0xff //reset vector location ($ffc0)
|
||||
};
|
||||
|
||||
#endif
|
|
@ -9,7 +9,6 @@ SMP smp;
|
|||
|
||||
#include "algorithms.cpp"
|
||||
#include "core.cpp"
|
||||
#include "iplrom.cpp"
|
||||
#include "memory.cpp"
|
||||
#include "timing.cpp"
|
||||
|
||||
|
@ -140,6 +139,7 @@ void SMP::serialize(serializer &s) {
|
|||
|
||||
SMP::SMP() {
|
||||
apuram = new uint8[64 * 1024];
|
||||
for(auto &byte : iplrom) byte = 0;
|
||||
}
|
||||
|
||||
SMP::~SMP() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
struct SMP : Thread {
|
||||
static const uint8 iplrom[64];
|
||||
uint8 iplrom[64];
|
||||
uint8 *apuram;
|
||||
|
||||
enum : bool { Threaded = false };
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
#ifdef SMP_CPP
|
||||
|
||||
//this is the IPLROM for the S-SMP coprocessor.
|
||||
//the S-SMP does not allow writing to the IPLROM.
|
||||
//all writes are instead mapped to the extended
|
||||
//RAM region, accessible when $f1.d7 is clear.
|
||||
|
||||
const uint8 SMP::iplrom[64] = {
|
||||
/*ffc0*/ 0xcd, 0xef, //mov x,#$ef
|
||||
/*ffc2*/ 0xbd, //mov sp,x
|
||||
/*ffc3*/ 0xe8, 0x00, //mov a,#$00
|
||||
/*ffc5*/ 0xc6, //mov (x),a
|
||||
/*ffc6*/ 0x1d, //dec x
|
||||
/*ffc7*/ 0xd0, 0xfc, //bne $ffc5
|
||||
/*ffc9*/ 0x8f, 0xaa, 0xf4, //mov $f4,#$aa
|
||||
/*ffcc*/ 0x8f, 0xbb, 0xf5, //mov $f5,#$bb
|
||||
/*ffcf*/ 0x78, 0xcc, 0xf4, //cmp $f4,#$cc
|
||||
/*ffd2*/ 0xd0, 0xfb, //bne $ffcf
|
||||
/*ffd4*/ 0x2f, 0x19, //bra $ffef
|
||||
/*ffd6*/ 0xeb, 0xf4, //mov y,$f4
|
||||
/*ffd8*/ 0xd0, 0xfc, //bne $ffd6
|
||||
/*ffda*/ 0x7e, 0xf4, //cmp y,$f4
|
||||
/*ffdc*/ 0xd0, 0x0b, //bne $ffe9
|
||||
/*ffde*/ 0xe4, 0xf5, //mov a,$f5
|
||||
/*ffe0*/ 0xcb, 0xf4, //mov $f4,y
|
||||
/*ffe2*/ 0xd7, 0x00, //mov ($00)+y,a
|
||||
/*ffe4*/ 0xfc, //inc y
|
||||
/*ffe5*/ 0xd0, 0xf3, //bne $ffda
|
||||
/*ffe7*/ 0xab, 0x01, //inc $01
|
||||
/*ffe9*/ 0x10, 0xef, //bpl $ffda
|
||||
/*ffeb*/ 0x7e, 0xf4, //cmp y,$f4
|
||||
/*ffed*/ 0x10, 0xeb, //bpl $ffda
|
||||
/*ffef*/ 0xba, 0xf6, //movw ya,$f6
|
||||
/*fff1*/ 0xda, 0x00, //movw $00,ya
|
||||
/*fff3*/ 0xba, 0xf4, //movw ya,$f4
|
||||
/*fff5*/ 0xc4, 0xf4, //mov $f4,a
|
||||
/*fff7*/ 0xdd, //mov a,y
|
||||
/*fff8*/ 0x5d, //mov x,a
|
||||
/*fff9*/ 0xd0, 0xdb, //bne $ffd6
|
||||
/*fffb*/ 0x1f, 0x00, 0x00, //jmp ($0000+x)
|
||||
/*fffe*/ 0xc0, 0xff //reset vector location ($ffc0)
|
||||
};
|
||||
|
||||
#endif
|
|
@ -6,7 +6,6 @@ namespace SNES {
|
|||
SMP smp;
|
||||
|
||||
#include "serialization.cpp"
|
||||
#include "iplrom.cpp"
|
||||
#include "memory/memory.cpp"
|
||||
#include "timing/timing.cpp"
|
||||
|
||||
|
@ -115,6 +114,7 @@ void SMP::reset() {
|
|||
}
|
||||
|
||||
SMP::SMP() {
|
||||
for(auto &byte : iplrom) byte = 0;
|
||||
}
|
||||
|
||||
SMP::~SMP() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
struct SMP : Thread, public SMPcore {
|
||||
static const uint8 iplrom[64];
|
||||
uint8 iplrom[64];
|
||||
uint8 apuram[64 * 1024];
|
||||
|
||||
enum : bool { Threaded = true };
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
processor := arm hg51b
|
||||
include processor/Makefile
|
||||
|
||||
include $(snes)/Makefile
|
||||
include $(gb)/Makefile
|
||||
output := libsnes
|
||||
|
||||
ifeq ($(platform),x)
|
||||
flags += -fPIC
|
||||
else ifeq ($(platform),osx)
|
||||
flags += -fPIC
|
||||
else ifeq ($(platform),win)
|
||||
endif
|
||||
|
||||
#rules
|
||||
objects := $(objects) libsnes
|
||||
objects := $(patsubst %,obj/%.o,$(objects))
|
||||
|
||||
obj/libsnes.o: $(ui)/libsnes.cpp $(ui)/*
|
||||
|
||||
#targets
|
||||
build: $(objects)
|
||||
ifeq ($(platform),x)
|
||||
ar rcs out/libsnes.a $(objects)
|
||||
$(cpp) -o out/libsnes.so -shared -Wl,-soname,libsnes.so.1 $(objects)
|
||||
else ifeq ($(platform),osx)
|
||||
ar rcs out/libsnes.a $(objects)
|
||||
$(cpp) -o out/libsnes.dylib -install_name @executable_path/../Libraries/libsnes.dylib -shared -dynamiclib $(objects)
|
||||
else ifeq ($(platform),win)
|
||||
$(cpp) -o out/snes.dll -shared -Wl,--out-implib,libsnes.a $(objects)
|
||||
endif
|
||||
|
||||
install:
|
||||
ifeq ($(platform),x)
|
||||
install -D -m 755 out/libsnes.a $(DESTDIR)$(prefix)/lib/libsnes.a
|
||||
install -D -m 755 out/libsnes.so $(DESTDIR)$(prefix)/lib/libsnes.so
|
||||
ldconfig -n $(DESTDIR)$(prefix)/lib
|
||||
else ifeq ($(platform),osx)
|
||||
cp out/libsnes.dylib /usr/local/lib/libsnes.dylib
|
||||
endif
|
||||
|
||||
uninstall:
|
||||
ifeq ($(platform),x)
|
||||
rm $(DESTDIR)$(prefix)/lib/libsnes.a
|
||||
rm $(DESTDIR)$(prefix)/lib/libsnes.so
|
||||
else ifeq ($(platform),osx)
|
||||
rm /usr/local/lib/libsnes.dylib
|
||||
endif
|
|
@ -1,395 +0,0 @@
|
|||
#include "libsnes.hpp"
|
||||
#include <snes/snes.hpp>
|
||||
|
||||
#include <nall/snes/cartridge.hpp>
|
||||
#include <nall/gameboy/cartridge.hpp>
|
||||
using namespace nall;
|
||||
|
||||
struct Interface : public SNES::Interface {
|
||||
snes_video_refresh_t pvideo_refresh;
|
||||
snes_audio_sample_t paudio_sample;
|
||||
snes_input_poll_t pinput_poll;
|
||||
snes_input_state_t pinput_state;
|
||||
string basename;
|
||||
uint16_t *buffer;
|
||||
uint32_t *palette;
|
||||
|
||||
void videoRefresh(const uint32_t *data, bool hires, bool interlace, bool overscan) {
|
||||
unsigned width = hires ? 512 : 256;
|
||||
unsigned height = overscan ? 239 : 224;
|
||||
unsigned pitch = 1024 >> interlace;
|
||||
if(interlace) height <<= 1;
|
||||
data += 9 * 1024; //skip front porch
|
||||
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
const uint32_t *sp = data + y * pitch;
|
||||
uint16_t *dp = buffer + y * pitch;
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
*dp++ = palette[*sp++];
|
||||
}
|
||||
}
|
||||
|
||||
if(pvideo_refresh) pvideo_refresh(buffer, width, height);
|
||||
if(pinput_poll) pinput_poll();
|
||||
}
|
||||
|
||||
void audioSample(int16_t left, int16_t right) {
|
||||
if(paudio_sample) return paudio_sample(left, right);
|
||||
}
|
||||
|
||||
int16_t inputPoll(bool port, SNES::Input::Device device, unsigned index, unsigned id) {
|
||||
if(pinput_state) return pinput_state(port, (unsigned)device, index, id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void message(const string &text) {
|
||||
print(text, "\n");
|
||||
}
|
||||
|
||||
string path(SNES::Cartridge::Slot slot, const string &hint) {
|
||||
return { basename, hint };
|
||||
}
|
||||
|
||||
Interface() : pvideo_refresh(0), paudio_sample(0), pinput_poll(0), pinput_state(0) {
|
||||
buffer = new uint16_t[512 * 480];
|
||||
palette = new uint32_t[16 * 32768];
|
||||
|
||||
//{llll bbbbb ggggg rrrrr} -> { rrrrr ggggg bbbbb }
|
||||
for(unsigned l = 0; l < 16; l++) {
|
||||
for(unsigned r = 0; r < 32; r++) {
|
||||
for(unsigned g = 0; g < 32; g++) {
|
||||
for(unsigned b = 0; b < 32; b++) {
|
||||
double luma = (double)l / 15.0;
|
||||
unsigned ar = (luma * r + 0.5);
|
||||
unsigned ag = (luma * g + 0.5);
|
||||
unsigned ab = (luma * b + 0.5);
|
||||
palette[(l << 15) + (r << 10) + (g << 5) + (b << 0)] = (ab << 10) + (ag << 5) + (ar << 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~Interface() {
|
||||
delete[] buffer;
|
||||
delete[] palette;
|
||||
}
|
||||
};
|
||||
|
||||
static Interface interface;
|
||||
|
||||
const char* snes_library_id(void) {
|
||||
static string version = {"bsnes v", Version};
|
||||
return version;
|
||||
}
|
||||
|
||||
unsigned snes_library_revision_major(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned snes_library_revision_minor(void) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
void snes_set_video_refresh(snes_video_refresh_t video_refresh) {
|
||||
interface.pvideo_refresh = video_refresh;
|
||||
}
|
||||
|
||||
void snes_set_audio_sample(snes_audio_sample_t audio_sample) {
|
||||
interface.paudio_sample = audio_sample;
|
||||
}
|
||||
|
||||
void snes_set_input_poll(snes_input_poll_t input_poll) {
|
||||
interface.pinput_poll = input_poll;
|
||||
}
|
||||
|
||||
void snes_set_input_state(snes_input_state_t input_state) {
|
||||
interface.pinput_state = input_state;
|
||||
}
|
||||
|
||||
void snes_set_controller_port_device(bool port, unsigned device) {
|
||||
SNES::input.connect(port, (SNES::Input::Device)device);
|
||||
}
|
||||
|
||||
void snes_set_cartridge_basename(const char *basename) {
|
||||
interface.basename = basename;
|
||||
}
|
||||
|
||||
void snes_init(void) {
|
||||
SNES::interface = &interface;
|
||||
SNES::system.init();
|
||||
SNES::input.connect(SNES::Controller::Port1, SNES::Input::Device::Joypad);
|
||||
SNES::input.connect(SNES::Controller::Port2, SNES::Input::Device::Joypad);
|
||||
}
|
||||
|
||||
void snes_term(void) {
|
||||
SNES::system.term();
|
||||
}
|
||||
|
||||
void snes_power(void) {
|
||||
SNES::system.power();
|
||||
}
|
||||
|
||||
void snes_reset(void) {
|
||||
SNES::system.reset();
|
||||
}
|
||||
|
||||
void snes_run(void) {
|
||||
SNES::system.run();
|
||||
}
|
||||
|
||||
unsigned snes_serialize_size(void) {
|
||||
return SNES::system.serialize_size();
|
||||
}
|
||||
|
||||
bool snes_serialize(uint8_t *data, unsigned size) {
|
||||
SNES::system.runtosave();
|
||||
serializer s = SNES::system.serialize();
|
||||
if(s.size() > size) return false;
|
||||
memcpy(data, s.data(), s.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool snes_unserialize(const uint8_t *data, unsigned size) {
|
||||
serializer s(data, size);
|
||||
return SNES::system.unserialize(s);
|
||||
}
|
||||
|
||||
struct CheatList {
|
||||
bool enable;
|
||||
string code;
|
||||
CheatList() : enable(false) {}
|
||||
};
|
||||
|
||||
static linear_vector<CheatList> cheatList;
|
||||
|
||||
void snes_cheat_reset(void) {
|
||||
cheatList.reset();
|
||||
GameBoy::cheat.reset();
|
||||
GameBoy::cheat.synchronize();
|
||||
SNES::cheat.reset();
|
||||
SNES::cheat.synchronize();
|
||||
}
|
||||
|
||||
void snes_cheat_set(unsigned index, bool enable, const char *code) {
|
||||
cheatList[index].enable = enable;
|
||||
cheatList[index].code = code;
|
||||
lstring list;
|
||||
for(unsigned n = 0; n < cheatList.size(); n++) {
|
||||
if(cheatList[n].enable) list.append(cheatList[n].code);
|
||||
}
|
||||
|
||||
if(SNES::cartridge.mode() == SNES::Cartridge::Mode::SuperGameBoy) {
|
||||
GameBoy::cheat.reset();
|
||||
for(auto &code : list) {
|
||||
lstring codelist;
|
||||
codelist.split("+", code);
|
||||
for(auto &part : codelist) {
|
||||
unsigned addr, data, comp;
|
||||
if(GameBoy::Cheat::decode(part, addr, data, comp)) {
|
||||
GameBoy::cheat.append({ addr, data, comp });
|
||||
}
|
||||
}
|
||||
}
|
||||
GameBoy::cheat.synchronize();
|
||||
return;
|
||||
}
|
||||
|
||||
SNES::cheat.reset();
|
||||
for(auto &code : list) {
|
||||
lstring codelist;
|
||||
codelist.split("+", code);
|
||||
for(auto &part : codelist) {
|
||||
unsigned addr, data;
|
||||
if(SNES::Cheat::decode(part, addr, data)) {
|
||||
SNES::cheat.append({ addr, data });
|
||||
}
|
||||
}
|
||||
}
|
||||
SNES::cheat.synchronize();
|
||||
}
|
||||
|
||||
bool snes_load_cartridge_normal(
|
||||
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size
|
||||
) {
|
||||
snes_cheat_reset();
|
||||
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
|
||||
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : SnesCartridge(rom_data, rom_size).markup;
|
||||
SNES::cartridge.load(SNES::Cartridge::Mode::Normal, { xmlrom });
|
||||
SNES::system.power();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool snes_load_cartridge_bsx_slotted(
|
||||
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,
|
||||
const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size
|
||||
) {
|
||||
snes_cheat_reset();
|
||||
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
|
||||
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : SnesCartridge(rom_data, rom_size).markup;
|
||||
if(bsx_data) SNES::bsxflash.memory.copy(bsx_data, bsx_size);
|
||||
string xmlbsx = (bsx_xml && *bsx_xml) ? string(bsx_xml) : SnesCartridge(bsx_data, bsx_size).markup;
|
||||
SNES::cartridge.load(SNES::Cartridge::Mode::BsxSlotted, xmlrom);
|
||||
SNES::system.power();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool snes_load_cartridge_bsx(
|
||||
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,
|
||||
const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size
|
||||
) {
|
||||
snes_cheat_reset();
|
||||
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
|
||||
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : SnesCartridge(rom_data, rom_size).markup;
|
||||
if(bsx_data) SNES::bsxflash.memory.copy(bsx_data, bsx_size);
|
||||
string xmlbsx = (bsx_xml && *bsx_xml) ? string(bsx_xml) : SnesCartridge(bsx_data, bsx_size).markup;
|
||||
SNES::cartridge.load(SNES::Cartridge::Mode::Bsx, xmlrom);
|
||||
SNES::system.power();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool snes_load_cartridge_sufami_turbo(
|
||||
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,
|
||||
const char *sta_xml, const uint8_t *sta_data, unsigned sta_size,
|
||||
const char *stb_xml, const uint8_t *stb_data, unsigned stb_size
|
||||
) {
|
||||
snes_cheat_reset();
|
||||
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
|
||||
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : SnesCartridge(rom_data, rom_size).markup;
|
||||
if(sta_data) SNES::sufamiturbo.slotA.rom.copy(sta_data, sta_size);
|
||||
string xmlsta = (sta_xml && *sta_xml) ? string(sta_xml) : SnesCartridge(sta_data, sta_size).markup;
|
||||
if(stb_data) SNES::sufamiturbo.slotB.rom.copy(stb_data, stb_size);
|
||||
string xmlstb = (stb_xml && *stb_xml) ? string(stb_xml) : SnesCartridge(stb_data, stb_size).markup;
|
||||
SNES::cartridge.load(SNES::Cartridge::Mode::SufamiTurbo, xmlrom);
|
||||
SNES::system.power();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool snes_load_cartridge_super_game_boy(
|
||||
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,
|
||||
const char *dmg_xml, const uint8_t *dmg_data, unsigned dmg_size
|
||||
) {
|
||||
snes_cheat_reset();
|
||||
if(rom_data) SNES::cartridge.rom.copy(rom_data, rom_size);
|
||||
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : SnesCartridge(rom_data, rom_size).markup;
|
||||
if(dmg_data) {
|
||||
//GameBoyCartridge needs to modify dmg_data (for MMM01 emulation); so copy data
|
||||
uint8_t *data = new uint8_t[dmg_size];
|
||||
memcpy(data, dmg_data, dmg_size);
|
||||
string xmldmg = (dmg_xml && *dmg_xml) ? string(dmg_xml) : GameBoyCartridge(data, dmg_size).markup;
|
||||
GameBoy::cartridge.load(GameBoy::System::Revision::SuperGameBoy, xmldmg, data, dmg_size);
|
||||
delete[] data;
|
||||
}
|
||||
SNES::cartridge.load(SNES::Cartridge::Mode::SuperGameBoy, xmlrom);
|
||||
SNES::system.power();
|
||||
return true;
|
||||
}
|
||||
|
||||
void snes_unload_cartridge(void) {
|
||||
SNES::cartridge.unload();
|
||||
}
|
||||
|
||||
bool snes_get_region(void) {
|
||||
return SNES::system.region() == SNES::System::Region::NTSC ? 0 : 1;
|
||||
}
|
||||
|
||||
uint8_t* snes_get_memory_data(unsigned id) {
|
||||
if(SNES::cartridge.loaded() == false) return 0;
|
||||
|
||||
switch(id) {
|
||||
case SNES_MEMORY_CARTRIDGE_RAM:
|
||||
return SNES::cartridge.ram.data();
|
||||
case SNES_MEMORY_CARTRIDGE_RTC:
|
||||
if(SNES::cartridge.has_srtc()) return SNES::srtc.rtc;
|
||||
if(SNES::cartridge.has_spc7110rtc()) return SNES::spc7110.rtc;
|
||||
return 0;
|
||||
case SNES_MEMORY_BSX_RAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;
|
||||
return SNES::bsxcartridge.sram.data();
|
||||
case SNES_MEMORY_BSX_PRAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;
|
||||
return SNES::bsxcartridge.psram.data();
|
||||
case SNES_MEMORY_SUFAMI_TURBO_A_RAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;
|
||||
return SNES::sufamiturbo.slotA.ram.data();
|
||||
case SNES_MEMORY_SUFAMI_TURBO_B_RAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;
|
||||
return SNES::sufamiturbo.slotB.ram.data();
|
||||
case SNES_MEMORY_GAME_BOY_RAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
|
||||
return GameBoy::cartridge.ramdata;
|
||||
//case SNES_MEMORY_GAME_BOY_RTC:
|
||||
// if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
|
||||
// return GameBoy::cartridge.rtcdata;
|
||||
|
||||
case SNES_MEMORY_WRAM:
|
||||
return SNES::cpu.wram;
|
||||
case SNES_MEMORY_APURAM:
|
||||
return SNES::smp.apuram;
|
||||
case SNES_MEMORY_VRAM:
|
||||
return SNES::ppu.vram;
|
||||
case SNES_MEMORY_OAM:
|
||||
return SNES::ppu.oam;
|
||||
case SNES_MEMORY_CGRAM:
|
||||
return SNES::ppu.cgram;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned snes_get_memory_size(unsigned id) {
|
||||
if(SNES::cartridge.loaded() == false) return 0;
|
||||
unsigned size = 0;
|
||||
|
||||
switch(id) {
|
||||
case SNES_MEMORY_CARTRIDGE_RAM:
|
||||
size = SNES::cartridge.ram.size();
|
||||
break;
|
||||
case SNES_MEMORY_CARTRIDGE_RTC:
|
||||
if(SNES::cartridge.has_srtc() || SNES::cartridge.has_spc7110rtc()) size = 20;
|
||||
break;
|
||||
case SNES_MEMORY_BSX_RAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;
|
||||
size = SNES::bsxcartridge.sram.size();
|
||||
break;
|
||||
case SNES_MEMORY_BSX_PRAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::Bsx) break;
|
||||
size = SNES::bsxcartridge.psram.size();
|
||||
break;
|
||||
case SNES_MEMORY_SUFAMI_TURBO_A_RAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;
|
||||
size = SNES::sufamiturbo.slotA.ram.size();
|
||||
break;
|
||||
case SNES_MEMORY_SUFAMI_TURBO_B_RAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SufamiTurbo) break;
|
||||
size = SNES::sufamiturbo.slotB.ram.size();
|
||||
break;
|
||||
case SNES_MEMORY_GAME_BOY_RAM:
|
||||
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
|
||||
size = GameBoy::cartridge.ramsize;
|
||||
break;
|
||||
//case SNES_MEMORY_GAME_BOY_RTC:
|
||||
// if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
|
||||
// size = GameBoy::cartridge.rtcsize;
|
||||
// break;
|
||||
|
||||
case SNES_MEMORY_WRAM:
|
||||
size = 128 * 1024;
|
||||
break;
|
||||
case SNES_MEMORY_APURAM:
|
||||
size = 64 * 1024;
|
||||
break;
|
||||
case SNES_MEMORY_VRAM:
|
||||
size = 64 * 1024;
|
||||
break;
|
||||
case SNES_MEMORY_OAM:
|
||||
size = 544;
|
||||
break;
|
||||
case SNES_MEMORY_CGRAM:
|
||||
size = 512;
|
||||
break;
|
||||
}
|
||||
|
||||
if(size == -1U) size = 0;
|
||||
return size;
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
#ifndef LIBSNES_HPP
|
||||
#define LIBSNES_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SNES_PORT_1 0
|
||||
#define SNES_PORT_2 1
|
||||
|
||||
#define SNES_DEVICE_NONE 0
|
||||
#define SNES_DEVICE_JOYPAD 1
|
||||
#define SNES_DEVICE_MULTITAP 2
|
||||
#define SNES_DEVICE_MOUSE 3
|
||||
#define SNES_DEVICE_SUPER_SCOPE 4
|
||||
#define SNES_DEVICE_JUSTIFIER 5
|
||||
#define SNES_DEVICE_JUSTIFIERS 6
|
||||
#define SNES_DEVICE_SERIAL_CABLE 7
|
||||
|
||||
#define SNES_DEVICE_ID_JOYPAD_B 0
|
||||
#define SNES_DEVICE_ID_JOYPAD_Y 1
|
||||
#define SNES_DEVICE_ID_JOYPAD_SELECT 2
|
||||
#define SNES_DEVICE_ID_JOYPAD_START 3
|
||||
#define SNES_DEVICE_ID_JOYPAD_UP 4
|
||||
#define SNES_DEVICE_ID_JOYPAD_DOWN 5
|
||||
#define SNES_DEVICE_ID_JOYPAD_LEFT 6
|
||||
#define SNES_DEVICE_ID_JOYPAD_RIGHT 7
|
||||
#define SNES_DEVICE_ID_JOYPAD_A 8
|
||||
#define SNES_DEVICE_ID_JOYPAD_X 9
|
||||
#define SNES_DEVICE_ID_JOYPAD_L 10
|
||||
#define SNES_DEVICE_ID_JOYPAD_R 11
|
||||
|
||||
#define SNES_DEVICE_ID_MOUSE_X 0
|
||||
#define SNES_DEVICE_ID_MOUSE_Y 1
|
||||
#define SNES_DEVICE_ID_MOUSE_LEFT 2
|
||||
#define SNES_DEVICE_ID_MOUSE_RIGHT 3
|
||||
|
||||
#define SNES_DEVICE_ID_SUPER_SCOPE_X 0
|
||||
#define SNES_DEVICE_ID_SUPER_SCOPE_Y 1
|
||||
#define SNES_DEVICE_ID_SUPER_SCOPE_TRIGGER 2
|
||||
#define SNES_DEVICE_ID_SUPER_SCOPE_CURSOR 3
|
||||
#define SNES_DEVICE_ID_SUPER_SCOPE_TURBO 4
|
||||
#define SNES_DEVICE_ID_SUPER_SCOPE_PAUSE 5
|
||||
|
||||
#define SNES_DEVICE_ID_JUSTIFIER_X 0
|
||||
#define SNES_DEVICE_ID_JUSTIFIER_Y 1
|
||||
#define SNES_DEVICE_ID_JUSTIFIER_TRIGGER 2
|
||||
#define SNES_DEVICE_ID_JUSTIFIER_START 3
|
||||
|
||||
#define SNES_REGION_NTSC 0
|
||||
#define SNES_REGION_PAL 1
|
||||
|
||||
#define SNES_MEMORY_CARTRIDGE_RAM 0
|
||||
#define SNES_MEMORY_CARTRIDGE_RTC 1
|
||||
#define SNES_MEMORY_BSX_RAM 2
|
||||
#define SNES_MEMORY_BSX_PRAM 3
|
||||
#define SNES_MEMORY_SUFAMI_TURBO_A_RAM 4
|
||||
#define SNES_MEMORY_SUFAMI_TURBO_B_RAM 5
|
||||
#define SNES_MEMORY_GAME_BOY_RAM 6
|
||||
#define SNES_MEMORY_GAME_BOY_RTC 7
|
||||
|
||||
#define SNES_MEMORY_WRAM 100
|
||||
#define SNES_MEMORY_APURAM 101
|
||||
#define SNES_MEMORY_VRAM 102
|
||||
#define SNES_MEMORY_OAM 103
|
||||
#define SNES_MEMORY_CGRAM 104
|
||||
|
||||
typedef void (*snes_video_refresh_t)(const uint16_t *data, unsigned width, unsigned height);
|
||||
typedef void (*snes_audio_sample_t)(uint16_t left, uint16_t right);
|
||||
typedef void (*snes_input_poll_t)(void);
|
||||
typedef int16_t (*snes_input_state_t)(bool port, unsigned device, unsigned index, unsigned id);
|
||||
|
||||
const char* snes_library_id(void);
|
||||
unsigned snes_library_revision_major(void);
|
||||
unsigned snes_library_revision_minor(void);
|
||||
|
||||
void snes_set_video_refresh(snes_video_refresh_t);
|
||||
void snes_set_audio_sample(snes_audio_sample_t);
|
||||
void snes_set_input_poll(snes_input_poll_t);
|
||||
void snes_set_input_state(snes_input_state_t);
|
||||
|
||||
void snes_set_controller_port_device(bool port, unsigned device);
|
||||
void snes_set_cartridge_basename(const char *basename);
|
||||
|
||||
void snes_init(void);
|
||||
void snes_term(void);
|
||||
void snes_power(void);
|
||||
void snes_reset(void);
|
||||
void snes_run(void);
|
||||
|
||||
unsigned snes_serialize_size(void);
|
||||
bool snes_serialize(uint8_t *data, unsigned size);
|
||||
bool snes_unserialize(const uint8_t *data, unsigned size);
|
||||
|
||||
void snes_cheat_reset(void);
|
||||
void snes_cheat_set(unsigned index, bool enable, const char *code);
|
||||
|
||||
bool snes_load_cartridge_normal(
|
||||
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size
|
||||
);
|
||||
|
||||
bool snes_load_cartridge_bsx_slotted(
|
||||
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,
|
||||
const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size
|
||||
);
|
||||
|
||||
bool snes_load_cartridge_bsx(
|
||||
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,
|
||||
const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size
|
||||
);
|
||||
|
||||
bool snes_load_cartridge_sufami_turbo(
|
||||
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,
|
||||
const char *sta_xml, const uint8_t *sta_data, unsigned sta_size,
|
||||
const char *stb_xml, const uint8_t *stb_data, unsigned stb_size
|
||||
);
|
||||
|
||||
bool snes_load_cartridge_super_game_boy(
|
||||
const char *rom_xml, const uint8_t *rom_data, unsigned rom_size,
|
||||
const char *dmg_xml, const uint8_t *dmg_data, unsigned dmg_size
|
||||
);
|
||||
|
||||
void snes_unload_cartridge(void);
|
||||
|
||||
bool snes_get_region(void);
|
||||
uint8_t* snes_get_memory_data(unsigned id);
|
||||
unsigned snes_get_memory_size(unsigned id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -78,8 +78,8 @@ else ifeq ($(platform),x)
|
|||
sudo install -D -m 644 data/$(name).desktop $(DESTDIR)$(prefix)/share/applications/$(name).desktop
|
||||
|
||||
mkdir -p ~/.config/$(name)
|
||||
cp -R profile/* ~/.config/$(name)
|
||||
cp data/cheats.xml ~/.config/$(name)/cheats.xml
|
||||
cp -R "data/Game Boy Advance.system" ~/.config/$(name)
|
||||
chmod -R 777 ~/.config/$(name)
|
||||
endif
|
||||
|
||||
|
|
|
@ -7,13 +7,13 @@ MainWindow::MainWindow() {
|
|||
windowManager->append(this, "MainWindow");
|
||||
|
||||
cartridgeMenu.setText("&Cartridge");
|
||||
cartridgeLoadSNES.setText("Load &SNES Cartridge ...");
|
||||
cartridgeLoadNES.setText("Load &NES Cartridge ...");
|
||||
cartridgeLoadNES.setText("Load &Famicom Cartridge ...");
|
||||
cartridgeLoadSNES.setText("Load &Super Famicom Cartridge ...");
|
||||
cartridgeLoadGameBoy.setText("Load &Game Boy Cartridge ...");
|
||||
cartridgeLoadGameBoyColor.setText("Load Game Boy &Color Cartridge ...");
|
||||
cartridgeLoadGameBoyAdvance.setText("Load Game Boy &Advance Cartridge ...");
|
||||
cartridgeLoadSatellaviewSlotted.setText("Load Satellaview-Slotted Cartridge ...");
|
||||
cartridgeLoadSatellaview.setText("Load Satellaview Cartridge ...");
|
||||
cartridgeLoadSatellaview.setText("Load BS-X Satellaview Cartridge ...");
|
||||
cartridgeLoadSufamiTurbo.setText("Load Sufami Turbo Cartridge ...");
|
||||
cartridgeLoadSuperGameBoy.setText("Load Super Game Boy Cartridge ...");
|
||||
|
||||
|
@ -203,13 +203,13 @@ MainWindow::MainWindow() {
|
|||
onSize = [&] { utility->resizeMainWindow(); };
|
||||
|
||||
cartridgeLoadNES.onActivate = [&] {
|
||||
fileBrowser->open("Load Cartridge - NES", FileBrowser::Mode::NES, [](string filename) {
|
||||
fileBrowser->open("Load Cartridge - Famicom", FileBrowser::Mode::NES, [](string filename) {
|
||||
interface->nes.loadCartridge(filename);
|
||||
});
|
||||
};
|
||||
|
||||
cartridgeLoadSNES.onActivate = [&] {
|
||||
fileBrowser->open("Load Cartridge - SNES", FileBrowser::Mode::SNES, [](string filename) {
|
||||
fileBrowser->open("Load Cartridge - Super Famicom", FileBrowser::Mode::SNES, [](string filename) {
|
||||
interface->snes.loadCartridge(filename);
|
||||
});
|
||||
};
|
||||
|
@ -233,9 +233,24 @@ MainWindow::MainWindow() {
|
|||
};
|
||||
|
||||
cartridgeLoadSatellaviewSlotted.onActivate = [&] { slotLoader->loadSatellaviewSlotted(); };
|
||||
cartridgeLoadSatellaview.onActivate = [&] { slotLoader->loadSatellaview(); };
|
||||
cartridgeLoadSufamiTurbo.onActivate = [&] { slotLoader->loadSufamiTurbo(); };
|
||||
cartridgeLoadSuperGameBoy.onActivate = [&] { slotLoader->loadSuperGameBoy(); };
|
||||
|
||||
cartridgeLoadSatellaview.onActivate = [&] {
|
||||
fileBrowser->open("Load Cartridge - BS-X Satellaview", FileBrowser::Mode::Satellaview, [](string filename) {
|
||||
interface->snes.loadSatellaviewCartridge(application->path("BS-X Satellaview.sfc/"), filename);
|
||||
});
|
||||
};
|
||||
|
||||
cartridgeLoadSufamiTurbo.onActivate = [&] {
|
||||
fileBrowser->open("Load Cartridge - Sufami Turbo", FileBrowser::Mode::SufamiTurbo, [](string filename) {
|
||||
interface->snes.loadSufamiTurboCartridge(application->path("Sufami Turbo.sfc/"), filename, "");
|
||||
});
|
||||
};
|
||||
|
||||
cartridgeLoadSuperGameBoy.onActivate = [&] {
|
||||
fileBrowser->open("Load Cartridge - Super Game Boy", FileBrowser::Mode::GameBoy, [](string filename) {
|
||||
interface->snes.loadSuperGameBoyCartridge(application->path("Super Game Boy.sfc/"), filename);
|
||||
});
|
||||
};
|
||||
|
||||
nesPower.onActivate = { &Interface::power, interface };
|
||||
nesReset.onActivate = { &Interface::reset, interface };
|
||||
|
|
|
@ -55,6 +55,6 @@ NesPort2Input::NesPort2Input() {
|
|||
//
|
||||
|
||||
NesInput::NesInput() {
|
||||
name = "NES";
|
||||
name = "Famicom";
|
||||
append(port1, port2);
|
||||
}
|
||||
|
|
|
@ -179,6 +179,6 @@ justifier2("Justifier - Port 2", false)
|
|||
//
|
||||
|
||||
SnesInput::SnesInput() {
|
||||
name = "SNES";
|
||||
name = "Super Famicom";
|
||||
append(port1, port2);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
bool InterfaceCore::loadFirmware(string filename, string keyname, uint8_t *targetdata, unsigned targetsize) {
|
||||
filename = application->path(filename);
|
||||
string markup;
|
||||
markup.readfile(filename);
|
||||
XML::Document document(markup);
|
||||
lstring keypart = keyname.split<1>(".");
|
||||
|
||||
if(document[keypart[0]][keypart[1]].exists()) {
|
||||
auto &key = document[keypart[0]][keypart[1]];
|
||||
string firmware = key["firmware"].data;
|
||||
string hash = key["sha256"].data;
|
||||
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
if(file::read({dir(filename),firmware}, data, size) == true) {
|
||||
if(nall::sha256(data, size) == hash) {
|
||||
memcpy(targetdata, data, min(targetsize, size));
|
||||
return true;
|
||||
} else {
|
||||
MessageWindow::information(Window::None, {"Warning: Firmware SHA256 sum is incorrect:\n\n", dir(filename), firmware});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -1,4 +1,8 @@
|
|||
void InterfaceGB::initialize() {
|
||||
loadFirmware("Game Boy.sys/manifest.xml", "system.boot", GB::system.bootROM.dmg, 256u);
|
||||
loadFirmware("Super Game Boy.sfc/manifest.xml", "cartridge.boot", GB::system.bootROM.sgb, 256u);
|
||||
loadFirmware("Game Boy Color.sys/manifest.xml", "system.boot", GB::system.bootROM.cgb, 2048u);
|
||||
|
||||
GB::interface = this;
|
||||
GB::system.init();
|
||||
}
|
||||
|
|
|
@ -1,24 +1,5 @@
|
|||
void InterfaceGBA::initialize() {
|
||||
string filename = application->path("Game Boy Advance.system/manifest.xml");
|
||||
string markup;
|
||||
markup.readfile(filename);
|
||||
XML::Document document(markup);
|
||||
|
||||
if(document["system"]["bios"].exists()) {
|
||||
auto &bios = document["system"]["bios"];
|
||||
string firmware = bios["firmware"].data;
|
||||
string hash = bios["sha256"].data;
|
||||
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
if(file::read({dir(filename),firmware}, data, size) == true) {
|
||||
if(nall::sha256(data, size) == hash) {
|
||||
GBA::bios.load(data, size);
|
||||
} else {
|
||||
MessageWindow::information(Window::None, "Warning: GBA BIOS SHA256 sum is incorrect.");
|
||||
}
|
||||
}
|
||||
}
|
||||
loadFirmware("Game Boy Advance.sys/manifest.xml", "system.bios", GBA::bios.data, 16384u);
|
||||
|
||||
GBA::interface = this;
|
||||
GBA::system.init();
|
||||
|
@ -39,7 +20,7 @@ bool InterfaceGBA::loadCartridge(const string &filename) {
|
|||
interface->base = {true, filename};
|
||||
} else {
|
||||
if(file::read(filename, data, size) == false) return false;
|
||||
interface->base = {false, filename};
|
||||
interface->base = {false, nall::basename(filename)};
|
||||
}
|
||||
|
||||
interface->game = interface->base;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "../base.hpp"
|
||||
#include "core.cpp"
|
||||
#include "palette.cpp"
|
||||
#include "nes/nes.cpp"
|
||||
#include "snes/snes.cpp"
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "palette.hpp"
|
||||
|
||||
struct InterfaceCore {
|
||||
bool loadFirmware(string filename, string keyname, uint8_t *targetdata, unsigned targetsize);
|
||||
|
||||
virtual bool cartridgeLoaded() = 0;
|
||||
virtual void unloadCartridge() = 0;
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
void InterfaceSNES::initialize() {
|
||||
loadFirmware("Super Famicom.sys/manifest.xml", "system.smp", SNES::smp.iplrom, 64u);
|
||||
|
||||
SNES::interface = this;
|
||||
SNES::system.init();
|
||||
}
|
||||
|
|
|
@ -53,12 +53,12 @@ AudioSettings::AudioSettings() {
|
|||
frequencyAdjustmentLabel.setFont(application->boldFont);
|
||||
frequencyAdjustmentLabel.setText("Frequency: (lower to reduce audio crackling; raise to reduce video tearing)");
|
||||
|
||||
nes.name.setText("NES:");
|
||||
nes.name.setText("FC:");
|
||||
nes.slider.setLength(2001);
|
||||
nes.base = 1789772;
|
||||
nes.step = 56;
|
||||
|
||||
snes.name.setText("SNES:");
|
||||
snes.name.setText("SFC:");
|
||||
snes.slider.setLength(2001);
|
||||
snes.base = 32000;
|
||||
snes.step = 1;
|
||||
|
|
Loading…
Reference in New Issue