Update to v087r04 release.
byuu says:
Changelog:
- gameboy/ -> gb/
- GameBoy -> GB
- basic memory map for GBA
- enough code to execute the first BIOS instruction (b 0x68)
I have the code resetting r(15) to 0 on an exception just as a test.
Since that flushes the pipeline, that means we're basically executing "b
0x68" at 8MHz, and nothing else.
... and I am getting __6 motherfucking FPS__ at 4.4GHz on an i7.
Something is seriously, horribly, unfuckingbelievably wrong here, and
I can't figure out what it is.
My *fully complete* ARM core on the ST018 is even less efficient and
runs at 21.47MHz, and yet I get 60fps even after emulating the SNES
CPU+PPU @ 10+MHz each as well.
... I'm stuck. I can't proceed until we figure out what in the holy fuck
is going on here. So ... if anyone can help, please do. If we can't fix
this, the GBA emulation is dead.
I was able to profile on Windows, and I've included that in this WIP
under out/log.txt.
But it looks normal to me. But yeah, there's NO. FUCKING. WAY. This code
should be running this slowly.
2012-03-18 12:35:53 +00:00
|
|
|
#include <gb/gb.hpp>
|
2010-12-28 01:53:15 +00:00
|
|
|
|
2012-04-26 10:51:13 +00:00
|
|
|
namespace GameBoy {
|
2010-12-28 01:53:15 +00:00
|
|
|
|
Update to v099r13 release.
byuu says:
Changelog:
- GB core code cleanup completed
- GBA core code cleanup completed
- some more cleanup on missed processor/arm functions/variables
- fixed FC loading icarus bug
- "Load ROM File" icarus functionality restored
- minor code unification efforts all around (not perfect yet)
- MMIO->IO
- mmio.cpp->io.cpp
- read,write->readIO,writeIO
It's been a very long work in progress ... starting all the way back with
v094r09, but the major part of the higan code cleanup is now completed! Of
course, it's very important to note that this is only for the basic style:
- under_score functions and variables are now camelCase
- return-type function-name() are now auto function-name() -> return-type
- Natural<T>/Integer<T> replace (u)intT_n types where possible
- signed/unsigned are now int/uint
- most of the x==true,x==false tests changed to x,!x
A lot of spot improvements to consistency, simplicity and quality have
gone in along the way, of course. But we'll probably never fully finishing
beautifying every last line of code in the entire codebase. Still,
this is a really great start. Going forward, WIP diffs should start
being smaller and of higher quality once again.
I know the joke is, "until my coding style changes again", but ... this
was way too stressful, way too time consuming, and way too risky. I'm
too old and tired now for extreme upheavel like this again. The only
major change I'm slowly mulling over would be renaming the using
Natural<T>/Integer<T> = (u)intT; shorthand to something that isn't as
easily confused with the (u)int_t types ... but we'll see. I'll definitely
continue to change small things all the time, but for the larger picture,
I need to just accept the style I have and live with it.
2016-06-29 11:10:28 +00:00
|
|
|
#include "io.cpp"
|
2012-04-26 10:51:13 +00:00
|
|
|
#include "memory.cpp"
|
|
|
|
#include "timing.cpp"
|
2011-01-07 11:11:56 +00:00
|
|
|
#include "serialization.cpp"
|
2010-12-28 01:53:15 +00:00
|
|
|
CPU cpu;
|
|
|
|
|
2016-02-09 11:51:12 +00:00
|
|
|
auto CPU::Enter() -> void {
|
|
|
|
while(true) scheduler.synchronize(), cpu.main();
|
2010-12-28 06:03:02 +00:00
|
|
|
}
|
|
|
|
|
2015-11-21 07:36:48 +00:00
|
|
|
auto CPU::main() -> void {
|
2016-06-28 10:43:47 +00:00
|
|
|
interruptTest();
|
2016-06-05 22:10:01 +00:00
|
|
|
instruction();
|
2010-12-28 01:53:15 +00:00
|
|
|
}
|
|
|
|
|
2016-06-05 22:10:01 +00:00
|
|
|
auto CPU::raise(CPU::Interrupt id) -> void {
|
2011-01-22 08:15:49 +00:00
|
|
|
if(id == Interrupt::Vblank) {
|
2016-06-28 10:43:47 +00:00
|
|
|
status.interruptRequestVblank = 1;
|
|
|
|
if(status.interruptEnableVblank) r.halt = false;
|
2011-01-22 08:15:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(id == Interrupt::Stat) {
|
2016-06-28 10:43:47 +00:00
|
|
|
status.interruptRequestStat = 1;
|
|
|
|
if(status.interruptEnableStat) r.halt = false;
|
2011-01-22 08:15:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(id == Interrupt::Timer) {
|
2016-06-28 10:43:47 +00:00
|
|
|
status.interruptRequestTimer = 1;
|
|
|
|
if(status.interruptEnableTimer) r.halt = false;
|
2011-01-22 08:15:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(id == Interrupt::Serial) {
|
2016-06-28 10:43:47 +00:00
|
|
|
status.interruptRequestSerial = 1;
|
|
|
|
if(status.interruptEnableSerial) r.halt = false;
|
2011-01-22 08:15:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(id == Interrupt::Joypad) {
|
2016-06-28 10:43:47 +00:00
|
|
|
status.interruptRequestJoypad = 1;
|
|
|
|
if(status.interruptEnableJoypad) r.halt = r.stop = false;
|
2011-01-02 04:46:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-28 10:43:47 +00:00
|
|
|
auto CPU::interruptTest() -> void {
|
2016-06-05 05:03:21 +00:00
|
|
|
if(!r.ime) return;
|
|
|
|
|
2016-06-28 10:43:47 +00:00
|
|
|
if(status.interruptRequestVblank && status.interruptEnableVblank) {
|
|
|
|
status.interruptRequestVblank = 0;
|
2016-06-05 22:10:01 +00:00
|
|
|
return interrupt(0x0040);
|
2016-06-05 05:03:21 +00:00
|
|
|
}
|
|
|
|
|
2016-06-28 10:43:47 +00:00
|
|
|
if(status.interruptRequestStat && status.interruptEnableStat) {
|
|
|
|
status.interruptRequestStat = 0;
|
2016-06-05 22:10:01 +00:00
|
|
|
return interrupt(0x0048);
|
2016-06-05 05:03:21 +00:00
|
|
|
}
|
|
|
|
|
2016-06-28 10:43:47 +00:00
|
|
|
if(status.interruptRequestTimer && status.interruptEnableTimer) {
|
|
|
|
status.interruptRequestTimer = 0;
|
2016-06-05 22:10:01 +00:00
|
|
|
return interrupt(0x0050);
|
2016-06-05 05:03:21 +00:00
|
|
|
}
|
|
|
|
|
2016-06-28 10:43:47 +00:00
|
|
|
if(status.interruptRequestSerial && status.interruptEnableSerial) {
|
|
|
|
status.interruptRequestSerial = 0;
|
2016-06-05 22:10:01 +00:00
|
|
|
return interrupt(0x0058);
|
2016-06-05 05:03:21 +00:00
|
|
|
}
|
|
|
|
|
2016-06-28 10:43:47 +00:00
|
|
|
if(status.interruptRequestJoypad && status.interruptEnableJoypad) {
|
|
|
|
status.interruptRequestJoypad = 0;
|
2016-06-05 22:10:01 +00:00
|
|
|
return interrupt(0x0060);
|
2010-12-30 07:18:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-21 07:36:48 +00:00
|
|
|
auto CPU::stop() -> bool {
|
2016-06-28 10:43:47 +00:00
|
|
|
if(status.speedSwitch) {
|
|
|
|
status.speedSwitch = 0;
|
|
|
|
status.speedDouble ^= 1;
|
|
|
|
if(status.speedDouble == 0) frequency = 4 * 1024 * 1024;
|
|
|
|
if(status.speedDouble == 1) frequency = 8 * 1024 * 1024;
|
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
|
|
|
return true;
|
2012-04-26 10:51:13 +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
|
|
|
return false;
|
2012-04-26 10:51:13 +00:00
|
|
|
}
|
|
|
|
|
2015-11-21 07:36:48 +00:00
|
|
|
auto CPU::power() -> void {
|
2016-02-09 11:51:12 +00:00
|
|
|
create(Enter, 4 * 1024 * 1024);
|
2012-04-26 10:51:13 +00:00
|
|
|
LR35902::power();
|
2011-01-03 04:28:36 +00:00
|
|
|
|
2015-11-21 07:36:48 +00:00
|
|
|
for(uint n = 0xc000; n <= 0xdfff; n++) bus.mmio[n] = this; //WRAM
|
|
|
|
for(uint n = 0xe000; n <= 0xfdff; n++) bus.mmio[n] = this; //WRAM (mirror)
|
|
|
|
for(uint n = 0xff80; n <= 0xfffe; n++) bus.mmio[n] = this; //HRAM
|
2011-10-27 00:00:17 +00:00
|
|
|
|
|
|
|
bus.mmio[0xff00] = this; //JOYP
|
|
|
|
bus.mmio[0xff01] = this; //SB
|
|
|
|
bus.mmio[0xff02] = this; //SC
|
|
|
|
bus.mmio[0xff04] = this; //DIV
|
|
|
|
bus.mmio[0xff05] = this; //TIMA
|
|
|
|
bus.mmio[0xff06] = this; //TMA
|
|
|
|
bus.mmio[0xff07] = this; //TAC
|
|
|
|
bus.mmio[0xff0f] = this; //IF
|
|
|
|
bus.mmio[0xffff] = this; //IE
|
|
|
|
|
|
|
|
if(system.cgb()) {
|
|
|
|
bus.mmio[0xff4d] = this; //KEY1
|
|
|
|
bus.mmio[0xff51] = this; //HDMA1
|
|
|
|
bus.mmio[0xff52] = this; //HDMA2
|
|
|
|
bus.mmio[0xff53] = this; //HDMA3
|
|
|
|
bus.mmio[0xff54] = this; //HDMA4
|
|
|
|
bus.mmio[0xff55] = this; //HDMA5
|
|
|
|
bus.mmio[0xff56] = this; //RP
|
|
|
|
bus.mmio[0xff6c] = this; //???
|
|
|
|
bus.mmio[0xff70] = this; //SVBK
|
|
|
|
bus.mmio[0xff72] = this; //???
|
|
|
|
bus.mmio[0xff73] = this; //???
|
|
|
|
bus.mmio[0xff74] = this; //???
|
|
|
|
bus.mmio[0xff75] = this; //???
|
|
|
|
bus.mmio[0xff76] = this; //???
|
|
|
|
bus.mmio[0xff77] = this; //???
|
|
|
|
}
|
2010-12-30 07:18:47 +00:00
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
for(auto& n : wram) n = 0x00;
|
|
|
|
for(auto& n : hram) n = 0x00;
|
2010-12-29 11:03:42 +00:00
|
|
|
|
2011-01-06 10:16:07 +00:00
|
|
|
r[PC] = 0x0000;
|
|
|
|
r[SP] = 0x0000;
|
|
|
|
r[AF] = 0x0000;
|
2010-12-28 06:03:02 +00:00
|
|
|
r[BC] = 0x0000;
|
|
|
|
r[DE] = 0x0000;
|
|
|
|
r[HL] = 0x0000;
|
|
|
|
|
2016-06-28 10:43:47 +00:00
|
|
|
memory::fill(&status, sizeof(Status));
|
|
|
|
status.dmaCompleted = true;
|
|
|
|
status.wramBank = 1;
|
2010-12-28 06:03:02 +00:00
|
|
|
}
|
|
|
|
|
2010-12-28 01:53:15 +00:00
|
|
|
}
|