mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-10-01 00:26:46 +02:00
Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
88c79e56a0 |
13
higan/emulator/debugger.hpp
Normal file
13
higan/emulator/debugger.hpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Emulator {
|
||||||
|
|
||||||
|
#if defined(DEBUGGER)
|
||||||
|
#define debug(id, ...) if(debugger.id) debugger.id(__VA_ARGS__)
|
||||||
|
#define privileged public
|
||||||
|
#else
|
||||||
|
#define debug(id, ...)
|
||||||
|
#define privileged private
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
@@ -11,7 +11,7 @@ using namespace nall;
|
|||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "higan";
|
static const string Name = "higan";
|
||||||
static const string Version = "100";
|
static const string Version = "100.01";
|
||||||
static const string Author = "byuu";
|
static const string Author = "byuu";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "http://byuu.org/";
|
static const string Website = "http://byuu.org/";
|
||||||
@@ -21,9 +21,4 @@ namespace Emulator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#include "interface.hpp"
|
#include "interface.hpp"
|
||||||
|
#include "debugger.hpp"
|
||||||
#if defined(DEBUGGER)
|
|
||||||
#define privileged public
|
|
||||||
#else
|
|
||||||
#define privileged private
|
|
||||||
#endif
|
|
||||||
|
@@ -53,7 +53,7 @@ auto V30MZ::opGroup3MemImm(Size size) {
|
|||||||
auto mem = getMem(size);
|
auto mem = getMem(size);
|
||||||
switch(modrm.reg) {
|
switch(modrm.reg) {
|
||||||
case 0: alAnd(size, mem, fetch(size)); break;
|
case 0: alAnd(size, mem, fetch(size)); break;
|
||||||
case 1: debug("[V30MZ] GRP3.1"); break;
|
case 1: warning("[V30MZ] GRP3.1"); break;
|
||||||
case 2: wait(2); setMem(size, alNot(size, mem)); break;
|
case 2: wait(2); setMem(size, alNot(size, mem)); break;
|
||||||
case 3: wait(2); setMem(size, alNeg(size, mem)); break;
|
case 3: wait(2); setMem(size, alNeg(size, mem)); break;
|
||||||
case 4: wait(2); setAcc(size * 2, alMul(size, getAcc(size), mem)); break;
|
case 4: wait(2); setAcc(size * 2, alMul(size, getAcc(size), mem)); break;
|
||||||
@@ -77,13 +77,13 @@ auto V30MZ::opGroup4MemImm(Size size) {
|
|||||||
setMem(size, alDec(size, getMem(size)));
|
setMem(size, alDec(size, getMem(size)));
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if(size == Byte) { debug("[V30MZ] GRP4.2"); break; }
|
if(size == Byte) { warning("[V30MZ] GRP4.2"); break; }
|
||||||
wait(5);
|
wait(5);
|
||||||
push(r.ip);
|
push(r.ip);
|
||||||
r.ip = getMem(Word);
|
r.ip = getMem(Word);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if(size == Byte) { debug("[V30MZ] GRP4.3"); break; }
|
if(size == Byte) { warning("[V30MZ] GRP4.3"); break; }
|
||||||
wait(11);
|
wait(11);
|
||||||
push(r.cs);
|
push(r.cs);
|
||||||
push(r.ip);
|
push(r.ip);
|
||||||
@@ -91,23 +91,23 @@ auto V30MZ::opGroup4MemImm(Size size) {
|
|||||||
r.cs = getMem(Word, 2);
|
r.cs = getMem(Word, 2);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if(size == Byte) { debug("[V30MZ] GRP4.4"); break; }
|
if(size == Byte) { warning("[V30MZ] GRP4.4"); break; }
|
||||||
wait(4);
|
wait(4);
|
||||||
r.ip = getMem(Word);
|
r.ip = getMem(Word);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
if(size == Byte) { debug("[V30MZ] GRP4.5"); break; }
|
if(size == Byte) { warning("[V30MZ] GRP4.5"); break; }
|
||||||
wait(9);
|
wait(9);
|
||||||
r.ip = getMem(Word, 0);
|
r.ip = getMem(Word, 0);
|
||||||
r.cs = getMem(Word, 2);
|
r.cs = getMem(Word, 2);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
if(size == Byte) { debug("[V30MZ] GRP4.6"); break; }
|
if(size == Byte) { warning("[V30MZ] GRP4.6"); break; }
|
||||||
wait(1);
|
wait(1);
|
||||||
push(getMem(Word));
|
push(getMem(Word));
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
debug("[V30MZ] GRP4.7");
|
warning("[V30MZ] GRP4.7");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,7 @@ namespace Processor {
|
|||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
#include "disassembler.cpp"
|
#include "disassembler.cpp"
|
||||||
|
|
||||||
auto V30MZ::debug(string text) -> void {
|
auto V30MZ::warning(string text) -> void {
|
||||||
//print(text, "\n");
|
//print(text, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -23,7 +23,7 @@ struct V30MZ {
|
|||||||
virtual auto in(uint16 port) -> uint8 = 0;
|
virtual auto in(uint16 port) -> uint8 = 0;
|
||||||
virtual auto out(uint16 port, uint8 data) -> void = 0;
|
virtual auto out(uint16 port, uint8 data) -> void = 0;
|
||||||
|
|
||||||
auto debug(string text) -> void;
|
auto warning(string text) -> void;
|
||||||
auto power() -> void;
|
auto power() -> void;
|
||||||
auto exec() -> void;
|
auto exec() -> void;
|
||||||
auto interrupt(uint8 vector) -> void;
|
auto interrupt(uint8 vector) -> void;
|
||||||
|
@@ -10,7 +10,7 @@ auto Cartridge::loadCartridge(Markup::Node node) -> void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(board["sufamiturbo"]) {
|
if(board["sufamiturbo"]) {
|
||||||
if(auto pathID = interface->load(ID::SufamiTurboA, "Sufami Turbo - Slot A", "st")) {
|
if(auto pathID = interface->load(ID::SufamiTurboA, "Sufami Turbo", "st")) {
|
||||||
sufamiturboA.pathID = pathID();
|
sufamiturboA.pathID = pathID();
|
||||||
loadSufamiTurboA();
|
loadSufamiTurboA();
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@ auto Cartridge::loadSufamiTurboA(Markup::Node node) -> void {
|
|||||||
loadMemory(sufamiturboA.ram, node["board/ram"], File::Optional, sufamiturboA.pathID);
|
loadMemory(sufamiturboA.ram, node["board/ram"], File::Optional, sufamiturboA.pathID);
|
||||||
|
|
||||||
if(node["board/linkable"]) {
|
if(node["board/linkable"]) {
|
||||||
if(auto pathID = interface->load(ID::SufamiTurboB, "Sufami Turbo - Slot B", "st")) {
|
if(auto pathID = interface->load(ID::SufamiTurboB, "Sufami Turbo", "st")) {
|
||||||
sufamiturboB.pathID = pathID();
|
sufamiturboB.pathID = pathID();
|
||||||
loadSufamiTurboB();
|
loadSufamiTurboB();
|
||||||
}
|
}
|
||||||
|
@@ -50,10 +50,12 @@ auto CPU::main() -> void {
|
|||||||
status.nmiPending = false;
|
status.nmiPending = false;
|
||||||
r.vector = r.e ? 0xfffa : 0xffea;
|
r.vector = r.e ? 0xfffa : 0xffea;
|
||||||
interrupt();
|
interrupt();
|
||||||
|
debug(cpu.nmi);
|
||||||
} else if(status.irqPending) {
|
} else if(status.irqPending) {
|
||||||
status.irqPending = false;
|
status.irqPending = false;
|
||||||
r.vector = r.e ? 0xfffe : 0xffee;
|
r.vector = r.e ? 0xfffe : 0xffee;
|
||||||
interrupt();
|
interrupt();
|
||||||
|
debug(cpu.irq);
|
||||||
} else if(status.resetPending) {
|
} else if(status.resetPending) {
|
||||||
status.resetPending = false;
|
status.resetPending = false;
|
||||||
step(132);
|
step(132);
|
||||||
@@ -67,6 +69,7 @@ auto CPU::main() -> void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug(cpu.execute, r.pc);
|
||||||
instruction();
|
instruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -20,6 +20,7 @@ auto CPU::read(uint24 addr) -> uint8 {
|
|||||||
r.mdr = bus.read(addr, r.mdr);
|
r.mdr = bus.read(addr, r.mdr);
|
||||||
step(4);
|
step(4);
|
||||||
aluEdge();
|
aluEdge();
|
||||||
|
debug(cpu.read, addr, r.mdr);
|
||||||
return r.mdr;
|
return r.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ auto CPU::write(uint24 addr, uint8 data) -> void {
|
|||||||
dmaEdge();
|
dmaEdge();
|
||||||
step(status.clockCount);
|
step(status.clockCount);
|
||||||
bus.write(addr, r.mdr = data);
|
bus.write(addr, r.mdr = data);
|
||||||
|
debug(cpu.write, addr, r.mdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CPU::speed(uint24 addr) const -> uint {
|
auto CPU::speed(uint24 addr) const -> uint {
|
||||||
|
40
higan/sfc/debugger.hpp
Normal file
40
higan/sfc/debugger.hpp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace SuperFamicom {
|
||||||
|
|
||||||
|
struct Debugger {
|
||||||
|
struct CPU {
|
||||||
|
function<void (uint24, uint8)> read;
|
||||||
|
function<void (uint24, uint8)> write;
|
||||||
|
function<void (uint24)> execute;
|
||||||
|
function<void ()> nmi;
|
||||||
|
function<void ()> irq;
|
||||||
|
} cpu;
|
||||||
|
|
||||||
|
struct SMP {
|
||||||
|
function<void (uint16, uint8)> read;
|
||||||
|
function<void (uint16, uint8)> write;
|
||||||
|
function<void (uint16)> execute;
|
||||||
|
} smp;
|
||||||
|
|
||||||
|
struct PPU {
|
||||||
|
struct VRAM {
|
||||||
|
function<void (uint17, uint8)> read;
|
||||||
|
function<void (uint17, uint8)> write;
|
||||||
|
} vram;
|
||||||
|
|
||||||
|
struct OAM {
|
||||||
|
function<void (uint10, uint8)> read;
|
||||||
|
function<void (uint10, uint8)> write;
|
||||||
|
} oam;
|
||||||
|
|
||||||
|
struct CGRAM {
|
||||||
|
function<void (uint9, uint8)> read;
|
||||||
|
function<void (uint9, uint8)> write;
|
||||||
|
} cgram;
|
||||||
|
} ppu;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Debugger debugger;
|
||||||
|
|
||||||
|
}
|
@@ -4,6 +4,7 @@ namespace SuperFamicom {
|
|||||||
|
|
||||||
Interface* interface = nullptr;
|
Interface* interface = nullptr;
|
||||||
Settings settings;
|
Settings settings;
|
||||||
|
Debugger debugger;
|
||||||
|
|
||||||
Interface::Interface() {
|
Interface::Interface() {
|
||||||
interface = this;
|
interface = this;
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#include <sfc/debugger.hpp>
|
||||||
|
|
||||||
namespace SuperFamicom {
|
namespace SuperFamicom {
|
||||||
|
|
||||||
struct ID {
|
struct ID {
|
||||||
|
@@ -11,22 +11,31 @@ auto PPU::addressVRAM() const -> uint16 {
|
|||||||
|
|
||||||
auto PPU::readVRAM() -> uint16 {
|
auto PPU::readVRAM() -> uint16 {
|
||||||
if(!io.displayDisable && vcounter() < vdisp()) return 0x0000;
|
if(!io.displayDisable && vcounter() < vdisp()) return 0x0000;
|
||||||
return vram[addressVRAM()];
|
auto addr = addressVRAM();
|
||||||
|
auto data = vram[addr];
|
||||||
|
debug(ppu.vram.read, addr << 1 | 0, data.byte(0));
|
||||||
|
debug(ppu.vram.read, addr << 1 | 1, data.byte(1));
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PPU::writeVRAM(bool byte, uint8 data) -> void {
|
auto PPU::writeVRAM(bool byte, uint8 data) -> void {
|
||||||
if(!io.displayDisable && vcounter() < vdisp()) return;
|
if(!io.displayDisable && vcounter() < vdisp()) return;
|
||||||
vram[addressVRAM()].byte(byte) = data;
|
auto addr = addressVRAM();
|
||||||
|
vram[addr].byte(byte) = data;
|
||||||
|
debug(ppu.vram.write, addr << 1 | byte, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PPU::readOAM(uint10 addr) -> uint8 {
|
auto PPU::readOAM(uint10 addr) -> uint8 {
|
||||||
if(!io.displayDisable && vcounter() < vdisp()) addr = latch.oamAddress;
|
if(!io.displayDisable && vcounter() < vdisp()) addr = latch.oamAddress;
|
||||||
return obj.oam.read(addr);
|
auto data = obj.oam.read(addr);
|
||||||
|
debug(ppu.oam.read, addr, data);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PPU::writeOAM(uint10 addr, uint8 data) -> void {
|
auto PPU::writeOAM(uint10 addr, uint8 data) -> void {
|
||||||
if(!io.displayDisable && vcounter() < vdisp()) addr = latch.oamAddress;
|
if(!io.displayDisable && vcounter() < vdisp()) addr = latch.oamAddress;
|
||||||
obj.oam.write(addr, data);
|
obj.oam.write(addr, data);
|
||||||
|
debug(ppu.oam.write, addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PPU::readCGRAM(bool byte, uint8 addr) -> uint8 {
|
auto PPU::readCGRAM(bool byte, uint8 addr) -> uint8 {
|
||||||
@@ -34,7 +43,9 @@ auto PPU::readCGRAM(bool byte, uint8 addr) -> uint8 {
|
|||||||
&& vcounter() > 0 && vcounter() < vdisp()
|
&& vcounter() > 0 && vcounter() < vdisp()
|
||||||
&& hcounter() >= 88 && hcounter() < 1096
|
&& hcounter() >= 88 && hcounter() < 1096
|
||||||
) addr = latch.cgramAddress;
|
) addr = latch.cgramAddress;
|
||||||
return screen.cgram[addr].byte(byte);
|
auto data = screen.cgram[addr].byte(byte);
|
||||||
|
debug(ppu.cgram.read, addr << 1 | byte, data);
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PPU::writeCGRAM(uint8 addr, uint15 data) -> void {
|
auto PPU::writeCGRAM(uint8 addr, uint15 data) -> void {
|
||||||
@@ -43,6 +54,8 @@ auto PPU::writeCGRAM(uint8 addr, uint15 data) -> void {
|
|||||||
&& hcounter() >= 88 && hcounter() < 1096
|
&& hcounter() >= 88 && hcounter() < 1096
|
||||||
) addr = latch.cgramAddress;
|
) addr = latch.cgramAddress;
|
||||||
screen.cgram[addr] = data;
|
screen.cgram[addr] = data;
|
||||||
|
debug(ppu.cgram.write, addr << 1 | 0, data.byte(0));
|
||||||
|
debug(ppu.cgram.write, addr << 1 | 1, data.byte(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PPU::readIO(uint24 addr, uint8 data) -> uint8 {
|
auto PPU::readIO(uint24 addr, uint8 data) -> uint8 {
|
||||||
|
@@ -183,6 +183,7 @@ auto SMP::read(uint16 addr) -> uint8 {
|
|||||||
uint8 data = readBus(addr);
|
uint8 data = readBus(addr);
|
||||||
step(12);
|
step(12);
|
||||||
cycleEdge();
|
cycleEdge();
|
||||||
|
debug(smp.read, addr, data);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,6 +191,7 @@ auto SMP::write(uint16 addr, uint8 data) -> void {
|
|||||||
step(24);
|
step(24);
|
||||||
writeBus(addr, data);
|
writeBus(addr, data);
|
||||||
cycleEdge();
|
cycleEdge();
|
||||||
|
debug(smp.write, addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SMP::readDisassembler(uint16 addr) -> uint8 {
|
auto SMP::readDisassembler(uint16 addr) -> uint8 {
|
||||||
|
@@ -21,6 +21,7 @@ auto SMP::Enter() -> void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto SMP::main() -> void {
|
auto SMP::main() -> void {
|
||||||
|
debug(smp.execute, regs.pc);
|
||||||
instruction();
|
instruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -22,9 +22,10 @@ Interface::Interface() {
|
|||||||
media.append({ID::WonderSwan, "WonderSwan", "ws" });
|
media.append({ID::WonderSwan, "WonderSwan", "ws" });
|
||||||
media.append({ID::WonderSwanColor, "WonderSwan Color", "wsc"});
|
media.append({ID::WonderSwanColor, "WonderSwan Color", "wsc"});
|
||||||
|
|
||||||
Port hardwarePort{ID::Port::Hardware, "Hardware"};
|
Port hardwareHorizontalPort{ID::Port::HardwareHorizontal, "Hardware - Horizontal"};
|
||||||
|
Port hardwareVerticalPort{ID::Port::HardwareVertical, "Hardware - Vertical"};
|
||||||
|
|
||||||
{ Device device{ID::Device::HorizontalControls, "Horizontal Controls"};
|
{ Device device{ID::Device::Controls, "Controls"};
|
||||||
device.inputs.append({0, "Y1"});
|
device.inputs.append({0, "Y1"});
|
||||||
device.inputs.append({0, "Y2"});
|
device.inputs.append({0, "Y2"});
|
||||||
device.inputs.append({0, "Y3"});
|
device.inputs.append({0, "Y3"});
|
||||||
@@ -37,26 +38,12 @@ Interface::Interface() {
|
|||||||
device.inputs.append({0, "A"});
|
device.inputs.append({0, "A"});
|
||||||
device.inputs.append({0, "Start"});
|
device.inputs.append({0, "Start"});
|
||||||
device.inputs.append({0, "Rotate"});
|
device.inputs.append({0, "Rotate"});
|
||||||
hardwarePort.devices.append(device);
|
hardwareHorizontalPort.devices.append(device);
|
||||||
|
hardwareVerticalPort.devices.append(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
{ Device device{ID::Device::VerticalControls, "Vertical Controls"};
|
ports.append(move(hardwareHorizontalPort));
|
||||||
device.inputs.append({0, "Y1"});
|
ports.append(move(hardwareVerticalPort));
|
||||||
device.inputs.append({0, "Y2"});
|
|
||||||
device.inputs.append({0, "Y3"});
|
|
||||||
device.inputs.append({0, "Y4"});
|
|
||||||
device.inputs.append({0, "X1"});
|
|
||||||
device.inputs.append({0, "X2"});
|
|
||||||
device.inputs.append({0, "X3"});
|
|
||||||
device.inputs.append({0, "X4"});
|
|
||||||
device.inputs.append({0, "B"});
|
|
||||||
device.inputs.append({0, "A"});
|
|
||||||
device.inputs.append({0, "Start"});
|
|
||||||
device.inputs.append({0, "Rotate"});
|
|
||||||
hardwarePort.devices.append(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
ports.append(move(hardwarePort));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Interface::manifest() -> string {
|
auto Interface::manifest() -> string {
|
||||||
|
@@ -7,13 +7,13 @@ struct ID {
|
|||||||
WonderSwanColor,
|
WonderSwanColor,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Device { enum : uint {
|
struct Port { enum : uint {
|
||||||
HorizontalControls,
|
HardwareHorizontal,
|
||||||
VerticalControls,
|
HardwareVertical,
|
||||||
};};
|
};};
|
||||||
|
|
||||||
struct Port { enum : uint {
|
struct Device { enum : uint {
|
||||||
Hardware,
|
Controls,
|
||||||
};};
|
};};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -98,8 +98,8 @@ auto System::runToSave() -> void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto System::pollKeypad() -> void {
|
auto System::pollKeypad() -> void {
|
||||||
uint port = ID::Port::Hardware;
|
uint port = !_orientation ? ID::Port::HardwareHorizontal : ID::Port::HardwareVertical;
|
||||||
uint device = !_orientation ? ID::Device::HorizontalControls : ID::Device::VerticalControls;
|
uint device = ID::Device::Controls;
|
||||||
bool rotate = keypad.rotate;
|
bool rotate = keypad.rotate;
|
||||||
|
|
||||||
keypad.y1 = interface->inputPoll(port, device, 0);
|
keypad.y1 = interface->inputPoll(port, device, 0);
|
||||||
|
Reference in New Issue
Block a user