2016-08-17 12:31:22 +00:00
|
|
|
#include <ms/ms.hpp>
|
|
|
|
|
|
|
|
namespace MasterSystem {
|
|
|
|
|
|
|
|
CPU cpu;
|
2017-08-11 16:02:09 +00:00
|
|
|
#include "bus.cpp"
|
Update to v102r10 release.
byuu says:
Changelog:
- removed Emulator::Interface::Capabilities¹
- MS: improved the PSG emulation a bit
- MS: added cheat code support
- MS: added save state support²
- MD: emulated the PSG³
¹: there's really no point to it anymore. I intend to add cheat codes
to the GBA core, as well as both cheat codes and save states to the Mega
Drive core. I no longer intend to emulate any new systems, so these
values will always be true. Further, the GUI doesn't respond to these
values to disable those features anymore ever since the hiro rewrite, so
they're double useless.
²: right now, the Z80 core is using a pointer for HL-\>(IX,IY)
overrides. But I can't reliably serialize pointers, so I need to convert
the Z80 core to use an integer here. The save states still appear to
work fine, but there's the potential for an instruction to execute
incorrectly if you're incredibly unlucky, so this needs to be fixed as
soon as possible. Further, I still need a way to serialize
array<T, Size> objects, and I should also add nall::Boolean
serialization support.
³: I don't have a system in place to share identical sound chips. But
this chip is so incredibly simple that it's not really much trouble to
duplicate it. Further, I can strip out the stereo sound support code
from the Game Gear portion, so it's even tinier.
Note that the Mega Drive only just barely uses the PSG. Not at all in
Altered Beast, and only for a tiny part of the BGM music on Sonic 1,
plus his jump sound effect.
2017-02-22 21:25:01 +00:00
|
|
|
#include "serialization.cpp"
|
2016-08-17 12:31:22 +00:00
|
|
|
|
|
|
|
auto CPU::Enter() -> void {
|
|
|
|
while(true) scheduler.synchronize(), cpu.main();
|
|
|
|
}
|
|
|
|
|
|
|
|
auto CPU::main() -> void {
|
2016-12-26 12:09:56 +00:00
|
|
|
if(state.nmiLine) {
|
|
|
|
state.nmiLine = 0; //edge-sensitive
|
|
|
|
irq(0, 0x0066, 0xff);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(state.intLine) {
|
|
|
|
//level-sensitive
|
|
|
|
irq(1, 0x0038, 0xff);
|
|
|
|
}
|
|
|
|
|
2016-08-19 14:11:26 +00:00
|
|
|
instruction();
|
2016-08-17 12:31:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
auto CPU::step(uint clocks) -> void {
|
|
|
|
Thread::step(clocks);
|
2016-08-19 14:11:26 +00:00
|
|
|
synchronize(vdp);
|
|
|
|
synchronize(psg);
|
Update to v101r28 release.
byuu says:
Changelog:
- SMS: emulated the remaining 240 instructions in the (0xfd, 0xdd)
0xcb (displacement) (opcode) set
- 1/8th of these were "legal" instructions, and apparently games
use them a lot
- SMS: emulated the standard gamepad controllers
- reset button not emulated yet
The reset button is tricky. In every other case, reset is a hardware
thing that instantly reboots the entire machine.
But on the SMS, it's more like a gamepad button that's attached to the
front of the device. When you press it, it fires off a reset vector
interrupt and the gamepad polling routine lets you query the status of
the button.
Just having a reset option in the "Master System" hardware menu is not
sufficient to fully emulate the behavior. Even more annoying is that the
Game Gear doesn't have such a button, yet the core information structs
aren't flexible enough for the Master System to have it, and the Game
Gear to not have it, in the main menu. But that doesn't matter anyway,
since it won't work having it in the menu for the Master System.
So as a result, I'm going to have to have a new "input device" called
"Hardware" that has the "Reset" button listed under there. And for the
sake of consistency, I'm not sure if we should treat the other systems
the same way or not :/
2017-01-08 20:55:02 +00:00
|
|
|
for(auto peripheral : peripherals) synchronize(*peripheral);
|
2016-08-19 14:11:26 +00:00
|
|
|
}
|
|
|
|
|
2017-06-22 06:04:07 +00:00
|
|
|
auto CPU::synchronizing() const -> bool {
|
|
|
|
return scheduler.synchronizing();
|
|
|
|
}
|
|
|
|
|
2017-01-13 23:59:38 +00:00
|
|
|
//called once per frame
|
|
|
|
auto CPU::pollPause() -> void {
|
2017-02-21 11:07:33 +00:00
|
|
|
if(Model::MasterSystem()) {
|
2017-01-13 23:59:38 +00:00
|
|
|
static bool pause = 0;
|
|
|
|
bool state = platform->inputPoll(ID::Port::Hardware, ID::Device::MasterSystemControls, 1);
|
|
|
|
if(!pause && state) setNMI(1);
|
|
|
|
pause = state;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-26 12:09:56 +00:00
|
|
|
auto CPU::setNMI(bool value) -> void {
|
|
|
|
state.nmiLine = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto CPU::setINT(bool value) -> void {
|
|
|
|
state.intLine = value;
|
|
|
|
}
|
|
|
|
|
2016-08-19 14:11:26 +00:00
|
|
|
auto CPU::power() -> void {
|
2017-08-11 16:02:09 +00:00
|
|
|
Z80::bus = this;
|
2016-09-04 13:51:27 +00:00
|
|
|
Z80::power();
|
2016-08-19 14:11:26 +00:00
|
|
|
create(CPU::Enter, system.colorburst());
|
Update to v101r24 release.
byuu says:
Changelog:
- SMS: extended bus mapping of in/out ports: now decoding them fully
inside ms/bus
- SMS: moved Z80 disassembly code from processor/z80 to ms/cpu
(cosmetic)
- SMS: hooked up non-functional silent PSG sample generation, so I can
cap the framerate at 60fps
- SMS: hooked up the VDP main loop: 684 clocks/scanline, 262
scanlines/frame (no PAL support yet)
- SMS: emulated the VDP Vcounter and Hcounter polling ... hopefully
it's right, as it's very bizarre
- SMS: emulated VDP in/out ports (data read, data write, status read,
control write, register write)
- SMS: decoding and caching all VDP register flags (variable names
will probably change)
- nall: \#undef IN on Windows port (prevent compilation warning on
processor/z80)
Watching Sonic the Hedgehog, I can definitely see some VDP register
writes going through, which is a good sign.
Probably the big thing that's needed before I can get enough into the
VDP to start showing graphics is interrupt support. And interrupts are
never fun to figure out :/
What really sucks on this front is I'm flying blind on the Z80 CPU core.
Without a working VDP, I can't run any Z80 test ROMs to look for CPU
bugs. And the CPU is certainly too buggy still to run said test ROM
anyway. I can't find any SMS emulators with trace logging from reset.
Such logs vastly accelerate tracking down CPU logic bugs, so without
them, it's going to take a lot longer.
2016-12-17 11:31:34 +00:00
|
|
|
|
2017-01-13 23:59:38 +00:00
|
|
|
r.pc = 0x0000; //reset vector address
|
|
|
|
|
2016-12-26 12:09:56 +00:00
|
|
|
memory::fill(&state, sizeof(State));
|
2016-08-17 12:31:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|