2011-01-08 09:58:41 +00:00
|
|
|
#include <snes/snes.hpp>
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
#define OBC1_CPP
|
|
|
|
namespace SNES {
|
|
|
|
|
|
|
|
OBC1 obc1;
|
|
|
|
|
|
|
|
#include "serialization.cpp"
|
|
|
|
|
|
|
|
void OBC1::init() {
|
|
|
|
}
|
|
|
|
|
Update to v075 release.
byuu says:
This release brings improved Super Game Boy emulation, the final SHA256
hashes for the DSP-(1,1B,2,3,4) and ST-(0010,0011) coprocessors, user
interface improvements, and major internal code restructuring.
Changelog (since v074):
- completely rewrote memory sub-system to support 1-byte granularity in
XML mapping
- removed Memory inheritance and MMIO class completely, any address can
be mapped to any function now
- SuperFX: removed SuperFXBus : Bus, now implemented manually
- SA-1: removed SA1Bus : Bus, now implemented manually
- entire bus mapping is now static, happens once on cartridge load
- as a result, read/write handlers now handle MMC mapping; slower
average case, far faster worst case
- namespace memory is no more, RAM arrays are stored inside the chips
they are owned by now
- GameBoy: improved CPU HALT emulation, fixes Zelda: Link's Awakening
scrolling
- GameBoy: added serial emulation (cannot connect to another GB yet),
fixes Shin Megami Tensei - Devichil
- GameBoy: improved LCD STAT emulation, fixes Sagaia
- ui: added fullscreen support (F11 key), video settings allows for
three scale settings
- ui: fixed brightness, contrast, gamma, audio volume, input frequency
values on program startup
- ui: since Qt is dead, config file becomes bsnes.cfg once again
- Super Game Boy: you can now load the BIOS without a game inserted to
see a pretty white box
- ui-gameboy: can be built without SNES components now
- libsnes: now a UI target, compile with 'make ui=ui-libsnes'
- libsnes: added WRAM, APURAM, VRAM, OAM, CGRAM access (cheat search,
etc)
- source: removed launcher/, as the Qt port is now gone
- source: Makefile restructuring to better support new ui targets
- source: lots of other internal code cleanup work
2011-01-27 08:52:34 +00:00
|
|
|
void OBC1::load() {
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBC1::unload() {
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OBC1::power() {
|
|
|
|
reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBC1::reset() {
|
|
|
|
for(unsigned i = 0x0000; i <= 0x1fff; i++) ram_write(i, 0xff);
|
|
|
|
|
|
|
|
status.baseptr = (ram_read(0x1ff5) & 1) ? 0x1800 : 0x1c00;
|
|
|
|
status.address = (ram_read(0x1ff6) & 0x7f);
|
|
|
|
status.shift = (ram_read(0x1ff6) & 3) << 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8 OBC1::read(unsigned addr) {
|
|
|
|
addr &= 0x1fff;
|
|
|
|
if((addr & 0x1ff8) != 0x1ff0) return ram_read(addr);
|
|
|
|
|
|
|
|
switch(addr) { default: //never used, avoids compiler warning
|
|
|
|
case 0x1ff0: return ram_read(status.baseptr + (status.address << 2) + 0);
|
|
|
|
case 0x1ff1: return ram_read(status.baseptr + (status.address << 2) + 1);
|
|
|
|
case 0x1ff2: return ram_read(status.baseptr + (status.address << 2) + 2);
|
|
|
|
case 0x1ff3: return ram_read(status.baseptr + (status.address << 2) + 3);
|
|
|
|
case 0x1ff4: return ram_read(status.baseptr + (status.address >> 2) + 0x200);
|
|
|
|
case 0x1ff5: case 0x1ff6: case 0x1ff7: return ram_read(addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBC1::write(unsigned addr, uint8 data) {
|
|
|
|
addr &= 0x1fff;
|
|
|
|
if((addr & 0x1ff8) != 0x1ff0) return ram_write(addr, data);
|
|
|
|
|
|
|
|
switch(addr) {
|
|
|
|
case 0x1ff0: ram_write(status.baseptr + (status.address << 2) + 0, data); break;
|
|
|
|
case 0x1ff1: ram_write(status.baseptr + (status.address << 2) + 1, data); break;
|
|
|
|
case 0x1ff2: ram_write(status.baseptr + (status.address << 2) + 2, data); break;
|
|
|
|
case 0x1ff3: ram_write(status.baseptr + (status.address << 2) + 3, data); break;
|
|
|
|
case 0x1ff4: {
|
|
|
|
uint8 temp = ram_read(status.baseptr + (status.address >> 2) + 0x200);
|
|
|
|
temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift);
|
|
|
|
ram_write(status.baseptr + (status.address >> 2) + 0x200, temp);
|
|
|
|
} break;
|
|
|
|
case 0x1ff5: {
|
|
|
|
status.baseptr = (data & 1) ? 0x1800 : 0x1c00;
|
|
|
|
ram_write(addr, data);
|
|
|
|
} break;
|
|
|
|
case 0x1ff6: {
|
|
|
|
status.address = (data & 0x7f);
|
|
|
|
status.shift = (data & 3) << 1;
|
|
|
|
ram_write(addr, data);
|
|
|
|
} break;
|
|
|
|
case 0x1ff7: {
|
|
|
|
ram_write(addr, data);
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8 OBC1::ram_read(unsigned addr) {
|
Update to v074r10 release.
byuu says:
Major WIP, countless changes. I really went to town on cleaning up the
source today with all kinds of new ideas. I'll post the ones I remember,
use diff -ru to get the rest.
What I like the most is my new within template:
template<unsigned lo, unsigned hi>
alwaysinline bool within(unsigned addr) {
static const unsigned mask = ~(hi ^ lo);
return (addr & mask) == lo;
}
Before, you would see code like this:
if((addr & 0xe0e000) == 0x206000) { //$20-3f:6000-7fff
The comment is basically necessary, and you have to trust that the mask
is right, or do the math yourself.
Now, it looks like this:
if(within<0x20, 0x3f, 0x6000, 0x7fff>(addr)) {
That's the same as within<0x206000, 0x3f7fff>, I just made an
SNES-variant to more closely simulate my XML mapping style:
20-3f:6000-7fff.
Now obviously this has limitations, it only works in base-2 and it can't
manage some tricky edge cases like (addr & 0x408000) == 0x008000 for
00-3f|80-bf:8000-ffff. But for the most part, I'll be using this where
I can. The Game Boy is fully ported over to it (via the MBCs), but the
SNES only has the BS-X town cartridge moved over so far. SuperFX and
SA-1 at the very least could benefit.
Next up, since the memory map is now static, there's really no reason to
remap the entire thing at power-on and reset. So it is now set up at
cartridge load and that's it. I moved the CPU/PPU/WRAM mapping out of
memory.cpp and into their respective processors. A bit of duplication
only because there are multiple processor cores for the different
profiles, but I'm not worried about that. This is also going to be
necessary to fix the debugger.
Next, Coprocessor::enable() actually does what I initially intended it
to now: it is called once to turn a chip on after cartridge load. It's
not called on power cycle anymore. This should help fix power-cycle on
my serial simulation code, and was needed to map the bus exactly one
time. Although most stuff is mapped through XML, some chips still need
some manual hooks for monitoring and such (eg S-DD1.)
Next, I've started killing off memory::, it was initially an
over-reaction to the question of where to put APURAM (in the SMP or
DSP?). The idea was to have this namespace that contained all memory for
everything. But it was very annoying and tedious, and various chips
ignored the convention anyway like ST-0011 RAM, which couldn't work
anyway since it is natively uint16 and not uint8. Cx4 will need 24-bit
RAM eventually, too. There's 8->24-bit functions in there now, because
the HLE code is hideous.
So far, all the cartridge.cpp memory:: types have been destroyed.
memory::cartrom, memory::cartram become cartridge.rom and cartridge.ram.
memory::cartrtc was moved into the SRTC and SPC7110 classes directly.
memory::bsxflash was moved into BSXFlash. memory::bsxram and
memory::bsxpram were moved into BSXCartridge (the town cartridge).
memory::st[AB](rom|ram) were moved into a new area,
snes/chip/sufamiturbo. The snes/chip moniker really doesn't work so
well, since it also has base units, and the serial communications stuff
which is through the controller port, but oh well, now it also has the
base structure for the Sufami Turbo cartridge too. So now we have
sufamiturbo.slotA.rom, sufamiturbo.slotB.ram, etc.
Next, the ST-0010/ST-0011 actually save the data RAM to disk. This
wasn't at all compatible with my old system, and I didn't want to keep
adding memory types to check inside the main UI cartridge RAM loading
and saving routines.
So I built a NonVolatileRAM vector inside SNES::Cartridge, and any chip
that has memory it wants to save and load from disk can append onto it
: data, size, id ("srm", "rtc", "nec", etc) and slot (0 = cartridge,
1 = slot A, 2 = slot B)
To load and save memory, we just do a simple: foreach(memory,
SNES::cartridge.nvram) load/saveMemory(memory).
As a result, you can now keep your save games in F1 Race of Champions II
and Hayazashi Nidan Morita Shougi. Technically I think Metal Combat
should work this way as well, having the RAM being part of the chip
itself, but for now that chip just writes directly into cartridge.ram,
so it also technically saves to disk for now.
To avoid a potential conflict with a manipulated memory map, BS-X SRAM
and PSRAM are now .bss and .bsp, and not .srm and .psr. Honestly I don't
like .srm as an extension either, but it doesn't bother me enough to
break save RAM compatibility with other emulators, so don't worry about
that changing.
I finally killed off MappedRAM initializing size to ~0 (-1U). A size of
zero means there is no memory there just the same. This was an old
holdover for handling MMIO mapping, if I recall correctly. Something
about a size of zero on MMIO-Memory objects causing it to wrap the
address, so ~0 would let it map direct addresses ... or something.
Whatever, that's not needed at all anymore.
BSXBase becomes BSXSatellaview, and I've defaulted the device to being
attached since it won't affect non-BSX games anyway. Eventually the GUI
needs to make that an option. BSXCart becomes BSXCartridge. BSXFlash
remains unchanged.
I probably need to make Coprocessor::disable() functions now to free up
memory on unload, but it shouldn't hurt anything the way it is.
libsnes is most definitely broken to all hell and back now, and the
debugger is still shot. I suppose we'll need some tricky code to work
with the old ID system, and we'll need to add some more IDs for the new
memory types.
2011-01-24 08:59:45 +00:00
|
|
|
return cartridge.ram.read(addr & 0x1fff);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void OBC1::ram_write(unsigned addr, uint8 data) {
|
Update to v074r10 release.
byuu says:
Major WIP, countless changes. I really went to town on cleaning up the
source today with all kinds of new ideas. I'll post the ones I remember,
use diff -ru to get the rest.
What I like the most is my new within template:
template<unsigned lo, unsigned hi>
alwaysinline bool within(unsigned addr) {
static const unsigned mask = ~(hi ^ lo);
return (addr & mask) == lo;
}
Before, you would see code like this:
if((addr & 0xe0e000) == 0x206000) { //$20-3f:6000-7fff
The comment is basically necessary, and you have to trust that the mask
is right, or do the math yourself.
Now, it looks like this:
if(within<0x20, 0x3f, 0x6000, 0x7fff>(addr)) {
That's the same as within<0x206000, 0x3f7fff>, I just made an
SNES-variant to more closely simulate my XML mapping style:
20-3f:6000-7fff.
Now obviously this has limitations, it only works in base-2 and it can't
manage some tricky edge cases like (addr & 0x408000) == 0x008000 for
00-3f|80-bf:8000-ffff. But for the most part, I'll be using this where
I can. The Game Boy is fully ported over to it (via the MBCs), but the
SNES only has the BS-X town cartridge moved over so far. SuperFX and
SA-1 at the very least could benefit.
Next up, since the memory map is now static, there's really no reason to
remap the entire thing at power-on and reset. So it is now set up at
cartridge load and that's it. I moved the CPU/PPU/WRAM mapping out of
memory.cpp and into their respective processors. A bit of duplication
only because there are multiple processor cores for the different
profiles, but I'm not worried about that. This is also going to be
necessary to fix the debugger.
Next, Coprocessor::enable() actually does what I initially intended it
to now: it is called once to turn a chip on after cartridge load. It's
not called on power cycle anymore. This should help fix power-cycle on
my serial simulation code, and was needed to map the bus exactly one
time. Although most stuff is mapped through XML, some chips still need
some manual hooks for monitoring and such (eg S-DD1.)
Next, I've started killing off memory::, it was initially an
over-reaction to the question of where to put APURAM (in the SMP or
DSP?). The idea was to have this namespace that contained all memory for
everything. But it was very annoying and tedious, and various chips
ignored the convention anyway like ST-0011 RAM, which couldn't work
anyway since it is natively uint16 and not uint8. Cx4 will need 24-bit
RAM eventually, too. There's 8->24-bit functions in there now, because
the HLE code is hideous.
So far, all the cartridge.cpp memory:: types have been destroyed.
memory::cartrom, memory::cartram become cartridge.rom and cartridge.ram.
memory::cartrtc was moved into the SRTC and SPC7110 classes directly.
memory::bsxflash was moved into BSXFlash. memory::bsxram and
memory::bsxpram were moved into BSXCartridge (the town cartridge).
memory::st[AB](rom|ram) were moved into a new area,
snes/chip/sufamiturbo. The snes/chip moniker really doesn't work so
well, since it also has base units, and the serial communications stuff
which is through the controller port, but oh well, now it also has the
base structure for the Sufami Turbo cartridge too. So now we have
sufamiturbo.slotA.rom, sufamiturbo.slotB.ram, etc.
Next, the ST-0010/ST-0011 actually save the data RAM to disk. This
wasn't at all compatible with my old system, and I didn't want to keep
adding memory types to check inside the main UI cartridge RAM loading
and saving routines.
So I built a NonVolatileRAM vector inside SNES::Cartridge, and any chip
that has memory it wants to save and load from disk can append onto it
: data, size, id ("srm", "rtc", "nec", etc) and slot (0 = cartridge,
1 = slot A, 2 = slot B)
To load and save memory, we just do a simple: foreach(memory,
SNES::cartridge.nvram) load/saveMemory(memory).
As a result, you can now keep your save games in F1 Race of Champions II
and Hayazashi Nidan Morita Shougi. Technically I think Metal Combat
should work this way as well, having the RAM being part of the chip
itself, but for now that chip just writes directly into cartridge.ram,
so it also technically saves to disk for now.
To avoid a potential conflict with a manipulated memory map, BS-X SRAM
and PSRAM are now .bss and .bsp, and not .srm and .psr. Honestly I don't
like .srm as an extension either, but it doesn't bother me enough to
break save RAM compatibility with other emulators, so don't worry about
that changing.
I finally killed off MappedRAM initializing size to ~0 (-1U). A size of
zero means there is no memory there just the same. This was an old
holdover for handling MMIO mapping, if I recall correctly. Something
about a size of zero on MMIO-Memory objects causing it to wrap the
address, so ~0 would let it map direct addresses ... or something.
Whatever, that's not needed at all anymore.
BSXBase becomes BSXSatellaview, and I've defaulted the device to being
attached since it won't affect non-BSX games anyway. Eventually the GUI
needs to make that an option. BSXCart becomes BSXCartridge. BSXFlash
remains unchanged.
I probably need to make Coprocessor::disable() functions now to free up
memory on unload, but it shouldn't hurt anything the way it is.
libsnes is most definitely broken to all hell and back now, and the
debugger is still shot. I suppose we'll need some tricky code to work
with the old ID system, and we'll need to add some more IDs for the new
memory types.
2011-01-24 08:59:45 +00:00
|
|
|
cartridge.ram.write(addr & 0x1fff, data);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
OBC1::OBC1() {}
|
|
|
|
OBC1::~OBC1() {}
|
|
|
|
|
|
|
|
}
|