2010-12-29 11:03:42 +00:00
|
|
|
#ifdef CPU_CPP
|
|
|
|
|
2011-10-27 00:00:17 +00:00
|
|
|
unsigned CPU::wram_addr(uint16 addr) const {
|
|
|
|
addr &= 0x1fff;
|
|
|
|
if(addr < 0x1000) return addr;
|
2011-10-27 13:30:19 +00:00
|
|
|
auto bank = status.wram_bank + (status.wram_bank == 0);
|
|
|
|
return (bank * 0x1000) + (addr & 0x0fff);
|
2011-10-27 00:00:17 +00:00
|
|
|
}
|
|
|
|
|
2010-12-31 05:43:47 +00:00
|
|
|
void CPU::mmio_joyp_poll() {
|
|
|
|
unsigned button = 0, dpad = 0;
|
|
|
|
|
Update to v088r08 release.
byuu says:
From this WIP, I'm starting on the impossible task of
a declarative-based GUI, which I'm calling Ethos.
base/ becomes emulator/, and we add emulator/interface.hpp, which is
a base API that all emulation cores must implement in full.
(Right now, it's kind of a hybrid to work with the old GUI and the new
GUI at the same time, of course.)
Unlike the old interfaces, the new base class also provides all general
usability hooks: loading and saving files and states, cheat codes, etc.
The new interface also contains information and vector structs to
describe all possible loading methods, controller bindings, etc; and
gives names for them all.
The actual GUI in fact should not include eg <gba/gba.hpp> anymore.
Should speed up GUI compilation.
So the idea going forward is that ethos will build a list of emulators
right when the application starts up.
Once you've appended an emulator to that list, you're done. No more GUI
changes are needed to support that system.
The GUI will have code to parse the emulator interfaces list, and build
all the requisite GUI options dynamically, declarative style.
Ultimately, once the project is finished, the new GUI should look ~99%
identical to the current GUI. But it'll probably be a whole lot smaller.
2012-04-29 06:29:54 +00:00
|
|
|
button |= interface->inputPoll(0, 0, (unsigned)Input::Start) << 3;
|
|
|
|
button |= interface->inputPoll(0, 0, (unsigned)Input::Select) << 2;
|
|
|
|
button |= interface->inputPoll(0, 0, (unsigned)Input::B) << 1;
|
|
|
|
button |= interface->inputPoll(0, 0, (unsigned)Input::A) << 0;
|
2010-12-31 05:43:47 +00:00
|
|
|
|
Update to v088r08 release.
byuu says:
From this WIP, I'm starting on the impossible task of
a declarative-based GUI, which I'm calling Ethos.
base/ becomes emulator/, and we add emulator/interface.hpp, which is
a base API that all emulation cores must implement in full.
(Right now, it's kind of a hybrid to work with the old GUI and the new
GUI at the same time, of course.)
Unlike the old interfaces, the new base class also provides all general
usability hooks: loading and saving files and states, cheat codes, etc.
The new interface also contains information and vector structs to
describe all possible loading methods, controller bindings, etc; and
gives names for them all.
The actual GUI in fact should not include eg <gba/gba.hpp> anymore.
Should speed up GUI compilation.
So the idea going forward is that ethos will build a list of emulators
right when the application starts up.
Once you've appended an emulator to that list, you're done. No more GUI
changes are needed to support that system.
The GUI will have code to parse the emulator interfaces list, and build
all the requisite GUI options dynamically, declarative style.
Ultimately, once the project is finished, the new GUI should look ~99%
identical to the current GUI. But it'll probably be a whole lot smaller.
2012-04-29 06:29:54 +00:00
|
|
|
dpad |= interface->inputPoll(0, 0, (unsigned)Input::Down) << 3;
|
|
|
|
dpad |= interface->inputPoll(0, 0, (unsigned)Input::Up) << 2;
|
|
|
|
dpad |= interface->inputPoll(0, 0, (unsigned)Input::Left) << 1;
|
|
|
|
dpad |= interface->inputPoll(0, 0, (unsigned)Input::Right) << 0;
|
2010-12-31 05:43:47 +00:00
|
|
|
|
2013-12-07 09:12:37 +00:00
|
|
|
//D-pad pivot makes it impossible to press opposing directions at the same time
|
|
|
|
if(dpad & 4) dpad &= ~8; //disallow up+down
|
|
|
|
if(dpad & 2) dpad &= ~1; //disallow left+right
|
|
|
|
|
2010-12-31 05:43:47 +00:00
|
|
|
status.joyp = 0x0f;
|
2011-01-06 10:16:07 +00:00
|
|
|
if(status.p15 == 1 && status.p14 == 1) status.joyp -= status.mlt_req;
|
2010-12-31 05:43:47 +00:00
|
|
|
if(status.p15 == 0) status.joyp &= button ^ 0x0f;
|
|
|
|
if(status.p14 == 0) status.joyp &= dpad ^ 0x0f;
|
2011-01-02 04:46:54 +00:00
|
|
|
if(status.joyp != 0x0f) interrupt_raise(Interrupt::Joypad);
|
2010-12-31 05:43:47 +00:00
|
|
|
}
|
|
|
|
|
2010-12-29 11:03:42 +00:00
|
|
|
uint8 CPU::mmio_read(uint16 addr) {
|
2011-10-27 00:00:17 +00:00
|
|
|
if(addr >= 0xc000 && addr <= 0xfdff) return wram[wram_addr(addr)];
|
2010-12-29 11:03:42 +00:00
|
|
|
if(addr >= 0xff80 && addr <= 0xfffe) return hram[addr & 0x7f];
|
2010-12-30 07:18:47 +00:00
|
|
|
|
|
|
|
if(addr == 0xff00) { //JOYP
|
2013-12-07 09:12:37 +00:00
|
|
|
mmio_joyp_poll();
|
2010-12-30 07:18:47 +00:00
|
|
|
return (status.p15 << 5)
|
|
|
|
| (status.p14 << 4)
|
2010-12-31 05:43:47 +00:00
|
|
|
| (status.joyp << 0);
|
2010-12-30 07:18:47 +00:00
|
|
|
}
|
|
|
|
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
if(addr == 0xff01) { //SB
|
|
|
|
return 0xff;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff02) { //SC
|
|
|
|
return (status.serial_transfer << 7)
|
|
|
|
| (status.serial_clock << 0);
|
|
|
|
}
|
|
|
|
|
2010-12-30 07:18:47 +00:00
|
|
|
if(addr == 0xff04) { //DIV
|
|
|
|
return status.div;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff05) { //TIMA
|
|
|
|
return status.tima;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff06) { //TMA
|
|
|
|
return status.tma;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff07) { //TAC
|
|
|
|
return (status.timer_enable << 2)
|
|
|
|
| (status.timer_clock << 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff0f) { //IF
|
|
|
|
return (status.interrupt_request_joypad << 4)
|
|
|
|
| (status.interrupt_request_serial << 3)
|
|
|
|
| (status.interrupt_request_timer << 2)
|
|
|
|
| (status.interrupt_request_stat << 1)
|
|
|
|
| (status.interrupt_request_vblank << 0);
|
|
|
|
}
|
|
|
|
|
2011-10-27 00:00:17 +00:00
|
|
|
if(addr == 0xff4d) { //KEY1
|
|
|
|
return (status.speed_double << 7);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff55) { //HDMA5
|
2013-12-10 12:12:54 +00:00
|
|
|
return (status.dma_completed << 7)
|
|
|
|
| (((status.dma_length / 16) - 1) & 0x7f);
|
2011-10-27 00:00:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff56) { //RP
|
|
|
|
return 0x02;
|
|
|
|
}
|
|
|
|
|
2011-10-27 13:30:19 +00:00
|
|
|
if(addr == 0xff6c) { //???
|
|
|
|
return 0xfe | status.ff6c;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff70) { //SVBK
|
|
|
|
return status.wram_bank;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff72) { //???
|
|
|
|
return status.ff72;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff73) { //???
|
|
|
|
return status.ff73;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff74) { //???
|
|
|
|
return status.ff74;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff75) { //???
|
|
|
|
return 0x8f | status.ff75;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff76) { //???
|
|
|
|
return 0x00;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff77) { //???
|
|
|
|
return 0x00;
|
|
|
|
}
|
2011-10-27 00:00:17 +00:00
|
|
|
|
2010-12-30 07:18:47 +00:00
|
|
|
if(addr == 0xffff) { //IE
|
|
|
|
return (status.interrupt_enable_joypad << 4)
|
|
|
|
| (status.interrupt_enable_serial << 3)
|
|
|
|
| (status.interrupt_enable_timer << 2)
|
|
|
|
| (status.interrupt_enable_stat << 1)
|
|
|
|
| (status.interrupt_enable_vblank << 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0x00;
|
2010-12-29 11:03:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CPU::mmio_write(uint16 addr, uint8 data) {
|
2011-10-27 00:00:17 +00:00
|
|
|
if(addr >= 0xc000 && addr <= 0xfdff) { wram[wram_addr(addr)] = data; return; }
|
2010-12-29 11:03:42 +00:00
|
|
|
if(addr >= 0xff80 && addr <= 0xfffe) { hram[addr & 0x7f] = data; return; }
|
2010-12-30 07:18:47 +00:00
|
|
|
|
|
|
|
if(addr == 0xff00) { //JOYP
|
|
|
|
status.p15 = data & 0x20;
|
|
|
|
status.p14 = data & 0x10;
|
2011-09-15 12:41:49 +00:00
|
|
|
interface->joypWrite(status.p15, status.p14);
|
2010-12-30 07:18:47 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff01) { //SB
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
status.serial_data = data;
|
2010-12-30 07:18:47 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff02) { //SC
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
status.serial_transfer = data & 0x80;
|
|
|
|
status.serial_clock = data & 0x01;
|
|
|
|
if(status.serial_transfer) status.serial_bits = 8;
|
2010-12-30 07:18:47 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff04) { //DIV
|
|
|
|
status.div = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff05) { //TIMA
|
|
|
|
status.tima = data;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff06) { //TMA
|
|
|
|
status.tma = data;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff07) { //TAC
|
|
|
|
status.timer_enable = data & 0x04;
|
|
|
|
status.timer_clock = data & 0x03;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff0f) { //IF
|
|
|
|
status.interrupt_request_joypad = data & 0x10;
|
|
|
|
status.interrupt_request_serial = data & 0x08;
|
|
|
|
status.interrupt_request_timer = data & 0x04;
|
|
|
|
status.interrupt_request_stat = data & 0x02;
|
|
|
|
status.interrupt_request_vblank = data & 0x01;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-10-27 00:00:17 +00:00
|
|
|
if(addr == 0xff46) { //DMA
|
|
|
|
for(unsigned n = 0x00; n <= 0x9f; n++) {
|
|
|
|
bus.write(0xfe00 + n, bus.read((data << 8) + n));
|
2011-10-27 13:30:19 +00:00
|
|
|
add_clocks(4);
|
2011-10-27 00:00:17 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff4d) { //KEY1
|
|
|
|
status.speed_switch = data & 0x01;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff51) { //HDMA1
|
|
|
|
status.dma_source = (status.dma_source & 0x00ff) | (data << 8);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff52) { //HDMA2
|
2013-12-10 12:12:54 +00:00
|
|
|
status.dma_source = (status.dma_source & 0xff00) | (data & 0xf0);
|
2011-10-27 00:00:17 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff53) { //HDMA3
|
|
|
|
status.dma_target = (status.dma_target & 0x00ff) | (data << 8);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff54) { //HDMA4
|
2013-12-10 12:12:54 +00:00
|
|
|
status.dma_target = (status.dma_target & 0xff00) | (data & 0xf0);
|
2011-10-27 00:00:17 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff55) { //HDMA5
|
|
|
|
status.dma_mode = data & 0x80;
|
|
|
|
status.dma_length = ((data & 0x7f) + 1) * 16;
|
2013-12-10 12:12:54 +00:00
|
|
|
status.dma_completed = !status.dma_mode;
|
|
|
|
|
|
|
|
if(status.dma_mode == 0) {
|
|
|
|
do {
|
|
|
|
for(unsigned n = 0; n < 16; n++) {
|
|
|
|
dma_write(status.dma_target++, dma_read(status.dma_source++));
|
|
|
|
}
|
|
|
|
add_clocks(8 << status.speed_double);
|
|
|
|
status.dma_length -= 16;
|
|
|
|
} while(status.dma_length);
|
|
|
|
}
|
2011-10-27 00:00:17 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff56) { //RP
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff6c) { //???
|
|
|
|
status.ff6c = data & 0x01;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff72) { //???
|
|
|
|
status.ff72 = data;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff73) { //???
|
|
|
|
status.ff73 = data;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff74) { //???
|
|
|
|
status.ff74 = data;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff75) { //???
|
|
|
|
status.ff75 = data & 0x70;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(addr == 0xff70) { //SVBK
|
|
|
|
status.wram_bank = data & 0x07;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-12-30 07:18:47 +00:00
|
|
|
if(addr == 0xffff) { //IE
|
|
|
|
status.interrupt_enable_joypad = data & 0x10;
|
|
|
|
status.interrupt_enable_serial = data & 0x08;
|
|
|
|
status.interrupt_enable_timer = data & 0x04;
|
|
|
|
status.interrupt_enable_stat = data & 0x02;
|
|
|
|
status.interrupt_enable_vblank = data & 0x01;
|
|
|
|
return;
|
|
|
|
}
|
2010-12-29 11:03:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|