Update to v074r01 release.

byuu says:

Changelog:
- fixed libsnes to compile again, the GB RTC constant is there but
  doesn't do anything just yet (no serialize support in GameBoy core)
- libsnes: added SNES_MEMORY_(WRAM,APURAM,VRAM,OAM,CGRAM) -- really only
  for the first one, it allows libsnes users to implement their own
  cheat search
- you can now load the SGB BIOS without a game!! please be sure to enjoy
  the blinking cartridge icon emulation :D
- necdsp (uPD7725,96050) - simplified code a bit: removed persistent
  regs.idb, simplified jumps, merged exec() with main loop, etc.
- nall::function - fixed an initialization bug when copy-constructing
  objects
- nall::vector - use calloc instead of malloc to help safeguard against
  uninitialized class data (potentially hides errors, but better than
  crashing in production)
This commit is contained in:
Tim Allen 2011-01-13 21:07:04 +11:00
parent 20afa076ef
commit a198e555dc
16 changed files with 200 additions and 158 deletions

View File

@ -1,7 +1,7 @@
include nall/Makefile
snes := snes
gameboy := gameboy
profile := accuracy
profile := compatibility
ui := ui
# compiler
@ -48,8 +48,6 @@ all: build;
obj/libco.o: libco/libco.c libco/*
include $(snes)/Makefile
include $(gameboy)/Makefile
include $(ui)/Makefile
objects := $(patsubst %,obj/%.o,$(objects))
@ -57,15 +55,17 @@ objects := $(patsubst %,obj/%.o,$(objects))
# targets
build: ui_build $(objects)
ifeq ($(platform),osx)
test -d ../bsnes.app || mkdir -p ../bsnes.app/Contents/MacOS
$(strip $(cpp) -o ../bsnes.app/Contents/MacOS/bsnes $(objects) $(link))
test -d ../$(output).app || mkdir -p ../$(output).app/Contents/MacOS
$(strip $(cpp) -o ../$(output).app/Contents/MacOS/$(output) $(objects) $(link))
else
$(strip $(cpp) -o out/bsnes $(objects) $(link))
$(strip $(cpp) -o out/$(output) $(objects) $(link))
endif
install:
ifeq ($(platform),x)
install -D -m 755 out/bsnes $(DESTDIR)$(prefix)/bin/bsnes
install -D -m 755 out/$(output) $(DESTDIR)$(prefix)/bin/$(output)
endif
ifeq ($(output),bsnes)
install -D -m 644 data/bsnes.png $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png
install -D -m 644 data/bsnes.desktop $(DESTDIR)$(prefix)/share/applications/bsnes.desktop
test -d ~/.bsnes || mkdir ~/.bsnes
@ -75,7 +75,9 @@ endif
uninstall:
ifeq ($(platform),x)
rm $(DESTDIR)$(prefix)/bin/bsnes
rm $(DESTDIR)$(prefix)/bin/$(output)
endif
ifeq ($(output),bsnes)
rm $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png
rm $(DESTDIR)$(prefix)/share/applications/bsnes.desktop
endif

View File

@ -16,13 +16,14 @@ namespace GameBoy {
#include "serialization.cpp"
Cartridge cartridge;
void Cartridge::load(const string &xml, uint8_t *data, unsigned size) {
void Cartridge::load(const string &xml, const uint8_t *data, unsigned size) {
if(size == 0) size = 32768;
romdata = new uint8[romsize = size]();
if(data) memcpy(romdata, data, size);
//uint32_t crc = crc32_calculate(data, size);
//print("CRC32 = ", hex<4>(crc), "\n");
romdata = new uint8[romsize = size];
memcpy(romdata, data, size);
info.mapper = Mapper::Unknown;
info.ram = false;
info.battery = false;

View File

@ -41,7 +41,7 @@ struct Cartridge : property<Cartridge> {
uint8_t *ramdata;
unsigned ramsize;
void load(const string &xml, uint8_t *data, unsigned size);
void load(const string &xml, const uint8_t *data, unsigned size);
void unload();
uint8 rom_read(unsigned addr);

View File

@ -27,7 +27,7 @@ namespace nall {
};
template<typename L> struct lambda : container {
L object;
mutable L object;
R operator()(P... p) const { return object(std::forward<P>(p)...); }
container* copy() const { return new lambda(object); }
lambda(const L& object) : object(object) {}
@ -46,7 +46,7 @@ namespace nall {
return *this;
}
function(const function &source) { operator=(source); }
function(const function &source) : callback(0) { operator=(source); }
function() : callback(0) {}
function(void *function) : callback(0) { if(function) callback = new global((R (*)(P...))function); }
function(R (*function)(P...)) { callback = new global(function); }

View File

@ -46,7 +46,7 @@ namespace nall {
void reserve(unsigned newsize) {
newsize = bit::round(newsize); //round to nearest power of two (for amortized growth)
T *poolcopy = (T*)malloc(newsize * sizeof(T));
T *poolcopy = (T*)calloc(newsize, sizeof(T));
for(unsigned i = 0; i < min(objectsize, newsize); i++) new(poolcopy + i) T(pool[i]);
for(unsigned i = 0; i < objectsize; i++) pool[i].~T();
free(pool);

View File

@ -48,46 +48,44 @@ string NECDSP::disassemble(uint14 ip) {
case 1: output << "b"; break;
}
if(1||dst) {
output << "\n mov ";
output << "\n mov ";
switch(src) {
case 0: output << "trb,"; break;
case 1: output << "a,"; break;
case 2: output << "b,"; break;
case 3: output << "tr,"; break;
case 4: output << "dp,"; break;
case 5: output << "rp,"; break;
case 6: output << "ro,"; break;
case 7: output << "sgn,"; break;
case 8: output << "dr,"; break;
case 9: output << "drnf,"; break;
case 10: output << "sr,"; break;
case 11: output << "sim,"; break;
case 12: output << "sil,"; break;
case 13: output << "k,"; break;
case 14: output << "l,"; break;
case 15: output << "mem,"; break;
}
switch(src) {
case 0: output << "trb,"; break;
case 1: output << "a,"; break;
case 2: output << "b,"; break;
case 3: output << "tr,"; break;
case 4: output << "dp,"; break;
case 5: output << "rp,"; break;
case 6: output << "ro,"; break;
case 7: output << "sgn,"; break;
case 8: output << "dr,"; break;
case 9: output << "drnf,"; break;
case 10: output << "sr,"; break;
case 11: output << "sim,"; break;
case 12: output << "sil,"; break;
case 13: output << "k,"; break;
case 14: output << "l,"; break;
case 15: output << "mem,"; break;
}
switch(dst) {
case 0: output << "non"; break;
case 1: output << "a"; break;
case 2: output << "b"; break;
case 3: output << "tr"; break;
case 4: output << "dp"; break;
case 5: output << "rp"; break;
case 6: output << "dr"; break;
case 7: output << "sr"; break;
case 8: output << "sol"; break;
case 9: output << "som"; break;
case 10: output << "k"; break;
case 11: output << "klr"; break;
case 12: output << "klm"; break;
case 13: output << "l"; break;
case 14: output << "trb"; break;
case 15: output << "mem"; break;
}
switch(dst) {
case 0: output << "non"; break;
case 1: output << "a"; break;
case 2: output << "b"; break;
case 3: output << "tr"; break;
case 4: output << "dp"; break;
case 5: output << "rp"; break;
case 6: output << "dr"; break;
case 7: output << "sr"; break;
case 8: output << "sol"; break;
case 9: output << "som"; break;
case 10: output << "k"; break;
case 11: output << "klr"; break;
case 12: output << "klm"; break;
case 13: output << "l"; break;
case 14: output << "trb"; break;
case 15: output << "mem"; break;
}
if(dpl) {
@ -132,9 +130,12 @@ string NECDSP::disassemble(uint14 ip) {
if(type == 2) { //JP
uint9 brch = opcode >> 13;
uint11 na = opcode >> 2;
uint8 bank = opcode >> 0;
uint14 jp = (regs.pc & 0x2000) | (bank << 11) | (na << 0);
switch(brch) {
case 0x000: output << "jmpso "; break;
case 0x000: output << "jmpso "; jp = 0; break;
case 0x080: output << "jnca "; break;
case 0x082: output << "jca "; break;
case 0x084: output << "jncb "; break;
@ -169,14 +170,14 @@ string NECDSP::disassemble(uint14 ip) {
case 0x0ba: output << "jsoak "; break;
case 0x0bc: output << "jnrqm "; break;
case 0x0be: output << "jrqm "; break;
case 0x100: output << "ljmp "; break;
case 0x101: output << "hjmp "; break;
case 0x140: output << "lcall "; break;
case 0x141: output << "hcall "; break;
case 0x100: output << "ljmp "; jp &= ~0x2000; break;
case 0x101: output << "hjmp "; jp |= 0x2000; break;
case 0x140: output << "lcall "; jp &= ~0x2000; break;
case 0x141: output << "hcall "; jp |= 0x2000; break;
default: output << "?????? "; break;
}
output << "$" << hex<4>(na);
output << "$" << hex<4>(jp);
}
if(type == 3) { //LD

View File

@ -16,26 +16,26 @@ void NECDSP::enter() {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
}
exec();
static uint16 lastpc = 0xfff;
if(lastpc != regs.pc) print(disassemble(lastpc = regs.pc), "\n");
uint24 opcode = programROM[regs.pc++];
switch(opcode >> 22) {
case 0: exec_op(opcode); break;
case 1: exec_rt(opcode); break;
case 2: exec_jp(opcode); break;
case 3: exec_ld(opcode); break;
}
int32 result = (int32)regs.k * regs.l; //sign + 30-bit result
regs.m = result >> 15; //store sign + top 15-bits
regs.n = result << 1; //store low 15-bits + zero
step(1);
synchronize_cpu();
}
}
void NECDSP::exec() {
uint24 opcode = programROM[regs.pc++];
switch(opcode >> 22) {
case 0: exec_op(opcode); break;
case 1: exec_rt(opcode); break;
case 2: exec_jp(opcode); break;
case 3: exec_ld(opcode); break;
}
int32 result = (int32)regs.k * regs.l; //sign + 30-bit result
regs.m = result >> 15; //store sign + top 15-bits
regs.n = result << 1; //store low 15-bits + zero
}
void NECDSP::exec_op(uint24 opcode) {
uint2 pselect = opcode >> 20; //P select
uint4 alu = opcode >> 16; //ALU operation mode
@ -46,23 +46,24 @@ void NECDSP::exec_op(uint24 opcode) {
uint4 src = opcode >> 4; //move source
uint4 dst = opcode >> 0; //move destination
uint16 idb;
switch(src) {
case 0: regs.idb = regs.trb; break;
case 1: regs.idb = regs.a; break;
case 2: regs.idb = regs.b; break;
case 3: regs.idb = regs.tr; break;
case 4: regs.idb = regs.dp; break;
case 5: regs.idb = regs.rp; break;
case 6: regs.idb = dataROM[regs.rp]; break;
case 7: regs.idb = 0x8000 - regs.flaga.s1; break;
case 8: regs.idb = regs.dr; regs.sr.rqm = 1; break;
case 9: regs.idb = regs.dr; break;
case 10: regs.idb = regs.sr; break;
case 11: regs.idb = regs.si; break; //MSB
case 12: regs.idb = regs.si; break; //LSB
case 13: regs.idb = regs.k; break;
case 14: regs.idb = regs.l; break;
case 15: regs.idb = dataRAM[regs.dp]; break;
case 0: idb = regs.trb; break;
case 1: idb = regs.a; break;
case 2: idb = regs.b; break;
case 3: idb = regs.tr; break;
case 4: idb = regs.dp; break;
case 5: idb = regs.rp; break;
case 6: idb = dataROM[regs.rp]; break;
case 7: idb = 0x8000 - regs.flaga.s1; break;
case 8: idb = regs.dr; regs.sr.rqm = 1; break;
case 9: idb = regs.dr; break;
case 10: idb = regs.sr; break;
case 11: idb = regs.si; break; //MSB
case 12: idb = regs.si; break; //LSB
case 13: idb = regs.k; break;
case 14: idb = regs.l; break;
case 15: idb = dataRAM[regs.dp]; break;
}
if(alu) {
@ -72,7 +73,7 @@ void NECDSP::exec_op(uint24 opcode) {
switch(pselect) {
case 0: p = dataRAM[regs.dp]; break;
case 1: p = regs.idb; break;
case 1: p = idb; break;
case 2: p = regs.m; break;
case 3: p = regs.n; break;
}
@ -146,7 +147,7 @@ void NECDSP::exec_op(uint24 opcode) {
}
}
exec_ld((regs.idb << 6) + dst);
exec_ld((idb << 6) + dst);
switch(dpl) {
case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC
@ -169,55 +170,54 @@ void NECDSP::exec_jp(uint24 opcode) {
uint11 na = opcode >> 2; //next address
uint2 bank = opcode >> 0; //bank address
uint16 jps = (regs.pc & 0x2000) | (bank << 11) | (na << 0);
uint16 jpl = (bank << 11) | (na << 0);
uint14 jp = (regs.pc & 0x2000) | (bank << 11) | (na << 0);
switch(brch) {
case 0x000: regs.pc = regs.so; return; //JMPSO
case 0x080: if(regs.flaga.c == 0) regs.pc = jps; return; //JNCA
case 0x082: if(regs.flaga.c == 1) regs.pc = jps; return; //JCA
case 0x084: if(regs.flagb.c == 0) regs.pc = jps; return; //JNCB
case 0x086: if(regs.flagb.c == 1) regs.pc = jps; return; //JCB
case 0x080: if(regs.flaga.c == 0) regs.pc = jp; return; //JNCA
case 0x082: if(regs.flaga.c == 1) regs.pc = jp; return; //JCA
case 0x084: if(regs.flagb.c == 0) regs.pc = jp; return; //JNCB
case 0x086: if(regs.flagb.c == 1) regs.pc = jp; return; //JCB
case 0x088: if(regs.flaga.z == 0) regs.pc = jps; return; //JNZA
case 0x08a: if(regs.flaga.z == 1) regs.pc = jps; return; //JZA
case 0x08c: if(regs.flagb.z == 0) regs.pc = jps; return; //JNZB
case 0x08e: if(regs.flagb.z == 1) regs.pc = jps; return; //JZB
case 0x088: if(regs.flaga.z == 0) regs.pc = jp; return; //JNZA
case 0x08a: if(regs.flaga.z == 1) regs.pc = jp; return; //JZA
case 0x08c: if(regs.flagb.z == 0) regs.pc = jp; return; //JNZB
case 0x08e: if(regs.flagb.z == 1) regs.pc = jp; return; //JZB
case 0x090: if(regs.flaga.ov0 == 0) regs.pc = jps; return; //JNOVA0
case 0x092: if(regs.flaga.ov0 == 1) regs.pc = jps; return; //JOVA0
case 0x094: if(regs.flagb.ov0 == 0) regs.pc = jps; return; //JNOVB0
case 0x096: if(regs.flagb.ov0 == 1) regs.pc = jps; return; //JOVB0
case 0x090: if(regs.flaga.ov0 == 0) regs.pc = jp; return; //JNOVA0
case 0x092: if(regs.flaga.ov0 == 1) regs.pc = jp; return; //JOVA0
case 0x094: if(regs.flagb.ov0 == 0) regs.pc = jp; return; //JNOVB0
case 0x096: if(regs.flagb.ov0 == 1) regs.pc = jp; return; //JOVB0
case 0x098: if(regs.flaga.ov1 == 0) regs.pc = jps; return; //JNOVA1
case 0x09a: if(regs.flaga.ov1 == 1) regs.pc = jps; return; //JOVA1
case 0x09c: if(regs.flagb.ov1 == 0) regs.pc = jps; return; //JNOVB1
case 0x09e: if(regs.flagb.ov1 == 1) regs.pc = jps; return; //JOVB1
case 0x098: if(regs.flaga.ov1 == 0) regs.pc = jp; return; //JNOVA1
case 0x09a: if(regs.flaga.ov1 == 1) regs.pc = jp; return; //JOVA1
case 0x09c: if(regs.flagb.ov1 == 0) regs.pc = jp; return; //JNOVB1
case 0x09e: if(regs.flagb.ov1 == 1) regs.pc = jp; return; //JOVB1
case 0x0a0: if(regs.flaga.s0 == 0) regs.pc = jps; return; //JNSA0
case 0x0a2: if(regs.flaga.s0 == 1) regs.pc = jps; return; //JSA0
case 0x0a4: if(regs.flagb.s0 == 0) regs.pc = jps; return; //JNSB0
case 0x0a6: if(regs.flagb.s0 == 1) regs.pc = jps; return; //JSB0
case 0x0a0: if(regs.flaga.s0 == 0) regs.pc = jp; return; //JNSA0
case 0x0a2: if(regs.flaga.s0 == 1) regs.pc = jp; return; //JSA0
case 0x0a4: if(regs.flagb.s0 == 0) regs.pc = jp; return; //JNSB0
case 0x0a6: if(regs.flagb.s0 == 1) regs.pc = jp; return; //JSB0
case 0x0a8: if(regs.flaga.s1 == 0) regs.pc = jps; return; //JNSA1
case 0x0aa: if(regs.flaga.s1 == 1) regs.pc = jps; return; //JSA1
case 0x0ac: if(regs.flagb.s1 == 0) regs.pc = jps; return; //JNSB1
case 0x0ae: if(regs.flagb.s1 == 1) regs.pc = jps; return; //JSB1
case 0x0a8: if(regs.flaga.s1 == 0) regs.pc = jp; return; //JNSA1
case 0x0aa: if(regs.flaga.s1 == 1) regs.pc = jp; return; //JSA1
case 0x0ac: if(regs.flagb.s1 == 0) regs.pc = jp; return; //JNSB1
case 0x0ae: if(regs.flagb.s1 == 1) regs.pc = jp; return; //JSB1
case 0x0b0: if((regs.dp & 0x0f) == 0x00) regs.pc = jps; return; //JDPL0
case 0x0b1: if((regs.dp & 0x0f) != 0x00) regs.pc = jps; return; //JDPLN0
case 0x0b2: if((regs.dp & 0x0f) == 0x0f) regs.pc = jps; return; //JDPLF
case 0x0b3: if((regs.dp & 0x0f) != 0x0f) regs.pc = jps; return; //JDPLNF
case 0x0b0: if((regs.dp & 0x0f) == 0x00) regs.pc = jp; return; //JDPL0
case 0x0b1: if((regs.dp & 0x0f) != 0x00) regs.pc = jp; return; //JDPLN0
case 0x0b2: if((regs.dp & 0x0f) == 0x0f) regs.pc = jp; return; //JDPLF
case 0x0b3: if((regs.dp & 0x0f) != 0x0f) regs.pc = jp; return; //JDPLNF
case 0x0bc: if(regs.sr.rqm == 0) regs.pc = jps; return; //JNRQM
case 0x0be: if(regs.sr.rqm == 1) regs.pc = jps; return; //JRQM
case 0x0bc: if(regs.sr.rqm == 0) regs.pc = jp; return; //JNRQM
case 0x0be: if(regs.sr.rqm == 1) regs.pc = jp; return; //JRQM
case 0x100: regs.pc = 0x0000 | jpl; return; //LJMP
case 0x101: regs.pc = 0x2000 | jpl; return; //HJMP
case 0x100: regs.pc = jp & ~0x2000; return; //LJMP
case 0x101: regs.pc = jp | 0x2000; return; //HJMP
case 0x140: regs.stack[regs.sp++] = regs.pc; regs.pc = 0x0000 | jpl; return; //LCALL
case 0x141: regs.stack[regs.sp++] = regs.pc; regs.pc = 0x2000 | jpl; return; //HCALL
case 0x140: regs.stack[regs.sp++] = regs.pc; regs.pc = jp & ~0x2000; return; //LCALL
case 0x141: regs.stack[regs.sp++] = regs.pc; regs.pc = jp | 0x2000; return; //HCALL
}
}
@ -225,8 +225,6 @@ void NECDSP::exec_ld(uint24 opcode) {
uint16 id = opcode >> 6; //immediate data
uint4 dst = opcode >> 0; //destination
regs.idb = id;
switch(dst) {
case 0: break;
case 1: regs.a = id; break;
@ -292,7 +290,6 @@ void NECDSP::reset() {
regs.dr = 0x0000;
regs.si = 0x0000;
regs.so = 0x0000;
regs.idb = 0x0000;
}
NECDSP::NECDSP() {

View File

@ -19,7 +19,6 @@ public:
static void Enter();
void enter();
void exec();
void exec_op(uint24 opcode);
void exec_rt(uint24 opcode);
void exec_jp(uint24 opcode);

View File

@ -48,5 +48,4 @@ struct Regs {
uint16 dr; //data register
uint16 si;
uint16 so;
uint16 idb;
} regs;

View File

@ -48,7 +48,6 @@ void NECDSP::serialize(serializer &s) {
s.integer(regs.dr);
s.integer(regs.si);
s.integer(regs.so);
s.integer(regs.idb);
}
#endif

View File

@ -1,7 +1,8 @@
#include "libsnes.hpp"
#include <snes.hpp>
#include <snes/snes.hpp>
#include <nall/snes/cartridge.hpp>
#include <nall/gameboy/cartridge.hpp>
using namespace nall;
struct Interface : public SNES::Interface {
@ -38,7 +39,7 @@ unsigned snes_library_revision_major(void) {
}
unsigned snes_library_revision_minor(void) {
return 1;
return 2;
}
void snes_set_video_refresh(snes_video_refresh_t video_refresh) {
@ -178,9 +179,11 @@ bool snes_load_cartridge_super_game_boy(
snes_cheat_reset();
if(rom_data) SNES::memory::cartrom.copy(rom_data, rom_size);
string xmlrom = (rom_xml && *rom_xml) ? string(rom_xml) : SNESCartridge(rom_data, rom_size).xmlMemoryMap;
if(dmg_data) SNES::memory::gbrom.copy(dmg_data, dmg_size);
string xmldmg = (dmg_xml && *dmg_xml) ? string(dmg_xml) : SNESCartridge(dmg_data, dmg_size).xmlMemoryMap;
SNES::cartridge.load(SNES::Cartridge::Mode::SuperGameBoy, { xmlrom, xmldmg });
if(dmg_data) {
string xmldmg = (dmg_xml && *dmg_xml) ? string(dmg_xml) : GameBoyCartridge(dmg_data, dmg_size).xml;
GameBoy::cartridge.load(dmg_xml, dmg_data, dmg_size);
}
SNES::cartridge.load(SNES::Cartridge::Mode::SuperGameBoy, { xmlrom, "" });
SNES::system.power();
return true;
}
@ -215,12 +218,21 @@ uint8_t* snes_get_memory_data(unsigned id) {
return SNES::memory::stBram.data();
case SNES_MEMORY_GAME_BOY_RAM:
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
SNES::supergameboy.save();
return SNES::memory::gbram.data();
case SNES_MEMORY_GAME_BOY_RTC:
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
SNES::supergameboy.save();
return SNES::memory::gbrtc.data();
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::memory::wram.data();
case SNES_MEMORY_APURAM:
return SNES::memory::apuram.data();
case SNES_MEMORY_VRAM:
return SNES::memory::vram.data();
case SNES_MEMORY_OAM:
return SNES::memory::oam.data();
case SNES_MEMORY_CGRAM:
return SNES::memory::cgram.data();
}
return 0;
@ -255,11 +267,27 @@ unsigned snes_get_memory_size(unsigned id) {
break;
case SNES_MEMORY_GAME_BOY_RAM:
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
size = SNES::memory::gbram.size();
size = GameBoy::cartridge.ramsize;
break;
case SNES_MEMORY_GAME_BOY_RTC:
if(SNES::cartridge.mode() != SNES::Cartridge::Mode::SuperGameBoy) break;
size = SNES::memory::gbrtc.size();
//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 = SNES::memory::wram.size();
break;
case SNES_MEMORY_APURAM:
size = SNES::memory::apuram.size();
break;
case SNES_MEMORY_VRAM:
size = SNES::memory::vram.size();
break;
case SNES_MEMORY_OAM:
size = SNES::memory::oam.size();
break;
case SNES_MEMORY_CGRAM:
size = SNES::memory::cgram.size();
break;
}

View File

@ -60,6 +60,12 @@ extern "C" {
#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);

View File

@ -1,8 +1,8 @@
namespace SNES {
namespace Info {
static const char Name[] = "bsnes";
static const char Version[] = "074";
static const unsigned SerializerVersion = 16;
static const char Version[] = "074.01";
static const unsigned SerializerVersion = 17;
}
}

View File

@ -1,3 +1,6 @@
output := bgameboy
include $(gameboy)/Makefile
ui_objects := ui-main ui-utility
ui_objects += ruby phoenix

View File

@ -1,3 +1,7 @@
output := bsnes
include $(snes)/Makefile
include $(gameboy)/Makefile
ui_objects := ui-main ui-general ui-settings ui-tools ui-input ui-utility ui-cartridge ui-debugger
ui_objects += ruby phoenix
ui_objects += $(if $(call streq,$(platform),win),resource)

View File

@ -57,18 +57,21 @@ bool Cartridge::loadSuperGameBoy(const char *basename, const char *slotname) {
unload();
if(loadCartridge(SNES::memory::cartrom, baseXML, basename) == false) return false;
unsigned size = 0;
uint8_t *data = 0;
file fp;
if(fp.open(slotname, file::mode::read)) {
unsigned size = fp.size();
uint8_t *data = new uint8_t[size];
data = new uint8_t[size = fp.size()];
fp.read(data, size);
fp.close();
GameBoyCartridge info(data, size);
GameBoy::cartridge.load(info.xml, data, size);
delete[] data;
}
//note: it is safe to pass below two functions null pointers
GameBoyCartridge info(data, size);
GameBoy::cartridge.load(info.xml, data, size);
if(data) delete[] data;
SNES::cartridge.basename = baseName = nall::basename(basename);
slotAName = nall::basename(slotname);
SNES::cartridge.load(SNES::Cartridge::Mode::SuperGameBoy, { baseXML, "" });