From 569f5abc28e8fc0a860b08d3e112180a9355ef7b Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Fri, 6 Jan 2017 19:11:38 +1100 Subject: [PATCH] Update to v101r27 release. byuu says: Changelog: - SMS: emulated the generic Sega memory mapper (none of the more limited forms of it yet) - (missing ROM shift, ROM write enable emulation -- no commercial games use either, though) - SMS: bus I/O returns 0xff instead of 0x00 so games don't think every key is being pressed at once - (this is a hack until I implement proper controller pad reading) - SMS: very limited protection against reading/writing past the end of ROM/RAM (todo: should mirror) - SMS: VDP background HSCROLL subtracts, rather than adds, to the offset (unlike VSCROLL) - SMS: VDP VSCROLL is 9-bit, modulates voffset+vscroll to 224 in 192-line mode (32x28 tilemap) - SMS: VDP tiledata for backgrounds and sprites use `7-(x&7)` rather than `(x&7)` - SMS: fix output color to be 6-bit rather than 5-bit - SMS: left clip uses register `#7`, not palette color `#7` - (todo: do we want `color[reg7]` or `color[16 + reg7]`?) - SMS: refined handling of 0xcb, 0xed prefixes in the Z80 core and its disassembler - SMS: emulated (0xfd, 0xdd) 0xcb opcodes 0x00-0x0f (still missing 0x10-0xff) - SMS: fixed 0xcb 0b-----110 opcodes to use direct HL and never allow (IX,IY)+d - SMS: fixed major logic bug in (IX,IY)+d displacement - (was using `read(x)` instead of `operand()` for the displacement byte fetch before) - icarus: fake there always being 32KiB of RAM in all SMS cartridges for the time being - (not sure how to detect this stuff yet; although I've read it's not even really possible `>_>`) TODO: remove processor/z80/dissassembler.cpp code block at line 396 (as it's unnecessary.) Lots of commercial games are starting to show trashed graphical output now. --- higan/emulator/emulator.hpp | 2 +- higan/ms/bus/bus.cpp | 11 +-- higan/ms/cartridge/cartridge.cpp | 21 ++++-- higan/ms/cartridge/cartridge.hpp | 28 ++++++- higan/ms/cartridge/mapper.cpp | 92 +++++++++++++++++++++++ higan/ms/vdp/background.cpp | 8 +- higan/ms/vdp/sprite.cpp | 9 ++- higan/ms/vdp/vdp.cpp | 4 +- higan/processor/z80/disassembler.cpp | 56 ++++++++++++-- higan/processor/z80/instruction.cpp | 106 ++++++++++++++++++--------- higan/processor/z80/instructions.cpp | 14 +++- higan/processor/z80/memory.cpp | 2 +- higan/processor/z80/z80.hpp | 8 +- icarus/heuristics/master-system.cpp | 1 + 14 files changed, 288 insertions(+), 74 deletions(-) create mode 100644 higan/ms/cartridge/mapper.cpp diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 2ba64a7a..435c63d8 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -12,7 +12,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "101.26"; + static const string Version = "101.27"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/ms/bus/bus.cpp b/higan/ms/bus/bus.cpp index cd877301..6b5c2aad 100644 --- a/higan/ms/bus/bus.cpp +++ b/higan/ms/bus/bus.cpp @@ -5,13 +5,14 @@ namespace MasterSystem { Bus bus; auto Bus::read(uint16 addr) -> uint8 { - if(addr < 0xc000) return cartridge.read(addr); - return ram[addr & 0x1fff]; + if(auto data = cartridge.read(addr)) return data(); + if(addr >= 0xc000) return ram[addr & 0x1fff]; + return 0x00; } auto Bus::write(uint16 addr, uint8 data) -> void { - if(addr < 0xc000) return cartridge.write(addr, data); - ram[addr & 0x1fff] = data; + if(cartridge.write(addr, data)) return; + if(addr >= 0xc000) ram[addr & 0x1fff] = data; } auto Bus::in(uint8 addr) -> uint8 { @@ -31,7 +32,7 @@ auto Bus::in(uint8 addr) -> uint8 { } - return 0x00; + return 0xff; } auto Bus::out(uint8 addr, uint8 data) -> void { diff --git a/higan/ms/cartridge/cartridge.cpp b/higan/ms/cartridge/cartridge.cpp index 2d5330dd..3616d15f 100644 --- a/higan/ms/cartridge/cartridge.cpp +++ b/higan/ms/cartridge/cartridge.cpp @@ -3,6 +3,7 @@ namespace MasterSystem { Cartridge cartridge; +#include "mapper.cpp" auto Cartridge::load() -> bool { information = {}; @@ -73,17 +74,23 @@ auto Cartridge::unload() -> void { ram = {}; } -auto Cartridge::read(uint16 addr) -> uint8 { - return rom.data[addr & rom.mask]; -} - -auto Cartridge::write(uint16 addr, uint8 data) -> void { -} - auto Cartridge::power() -> void { } auto Cartridge::reset() -> void { + memory::fill(&mapper, sizeof(Mapper)); + mapper.romPage0 = 0; + mapper.romPage1 = 1; + mapper.romPage2 = 2; +} + +auto Cartridge::Memory::read(uint addr) -> uint8 { + if(addr < this->size) return this->data[addr]; + return 0x00; +} + +auto Cartridge::Memory::write(uint addr, uint8 data) -> void { + if(addr < this->size) this->data[addr] = data; } } diff --git a/higan/ms/cartridge/cartridge.hpp b/higan/ms/cartridge/cartridge.hpp index 75cdc6a5..560a574c 100644 --- a/higan/ms/cartridge/cartridge.hpp +++ b/higan/ms/cartridge/cartridge.hpp @@ -8,12 +8,13 @@ struct Cartridge { auto save() -> void; auto unload() -> void; - auto read(uint16 addr) -> uint8; - auto write(uint16 addr, uint8 data) -> void; - auto power() -> void; auto reset() -> void; + //mapper.cpp + auto read(uint16 addr) -> maybe; + auto write(uint16 addr, uint8 data) -> bool; + private: struct Information { uint pathID = 0; @@ -26,10 +27,31 @@ private: uint8* data = nullptr; uint size = 0; uint mask = 0; + + auto read(uint addr) -> uint8; + auto write(uint addr, uint8 data) -> void; }; Memory rom; Memory ram; + + struct Mapper { + //$fffc + uint2 shift; + uint1 ramPage2; + uint1 ramEnablePage2; + uint1 ramEnablePage3; + uint1 romWriteEnable; + + //$fffd + uint8 romPage0; + + //$fffe + uint8 romPage1; + + //$ffff + uint8 romPage2; + } mapper; }; extern Cartridge cartridge; diff --git a/higan/ms/cartridge/mapper.cpp b/higan/ms/cartridge/mapper.cpp new file mode 100644 index 00000000..80c0beca --- /dev/null +++ b/higan/ms/cartridge/mapper.cpp @@ -0,0 +1,92 @@ +auto Cartridge::read(uint16 addr) -> maybe { + uint2 page = addr >> 14; + addr &= 0x3fff; + + switch(page) { + + case 0: { + if(addr <= 0x03ff) return rom.read(addr); + return rom.read(mapper.romPage0 << 14 | addr); + } + + case 1: { + return rom.read(mapper.romPage1 << 14 | addr); + } + + case 2: { + if(mapper.ramEnablePage2) { + return ram.read(mapper.ramPage2 << 14 | addr); + } + + return rom.read(mapper.romPage2 << 14 | addr); + } + + case 3: { + if(mapper.ramEnablePage3) { + return ram.read(addr); + } + + return nothing; + } + + } + + unreachable; +} + +auto Cartridge::write(uint16 addr, uint8 data) -> bool { + if(addr == 0xfffc) { + mapper.shift = data.bits(0,1); + mapper.ramPage2 = data.bit(2); + mapper.ramEnablePage2 = data.bit(3); + mapper.ramEnablePage3 = data.bit(4); + mapper.romWriteEnable = data.bit(7); + } + + if(addr == 0xfffd) { + mapper.romPage0 = data; + } + + if(addr == 0xfffe) { + mapper.romPage1 = data; + } + + if(addr == 0xffff) { + mapper.romPage2 = data; + } + + uint2 page = addr >> 14; + addr &= 0x3fff; + + switch(page) { + + case 0: { + return false; + } + + case 1: { + return false; + } + + case 2: { + if(mapper.ramEnablePage2) { + ram.write(mapper.ramPage2 << 14 | addr, data); + return true; + } + + return false; + } + + case 3: { + if(mapper.ramEnablePage3) { + ram.write(addr, data); + return true; + } + + return false; + } + + } + + unreachable; +} diff --git a/higan/ms/vdp/background.cpp b/higan/ms/vdp/background.cpp index 96a91f2c..b0dc053e 100644 --- a/higan/ms/vdp/background.cpp +++ b/higan/ms/vdp/background.cpp @@ -12,15 +12,17 @@ auto VDP::Background::run() -> void { } uint8 hoffset = state.x; - if(!vdp.io.horizontalScrollLock || hoffset >= 16) hoffset += vdp.io.hscroll; + if(!vdp.io.horizontalScrollLock || hoffset >= 16) hoffset -= vdp.io.hscroll; - uint8 voffset = state.y; + uint9 voffset = state.y; if(!vdp.io.verticalScrollLock || hoffset <= 191) voffset += vdp.io.vscroll; uint14 nameTableAddress; if(vdp.vlines() == 192) { + if(voffset >= 224) voffset -= 224; nameTableAddress = vdp.io.nameTableAddress << 11; } else { + voffset &= 255; nameTableAddress = (vdp.io.nameTableAddress & ~1) << 11 | 0x700; } nameTableAddress += ((voffset >> 3) << 6) + ((hoffset >> 3) << 1); @@ -35,7 +37,7 @@ auto VDP::Background::run() -> void { output.palette = tiledata.bit(11); output.priority = tiledata.bit(12); - auto index = hoffset & 7; + auto index = 7 - (hoffset & 7); patternAddress += (voffset & 7) << 2; output.color.bit(0) = vdp.vram[patternAddress + 0].bit(index); output.color.bit(1) = vdp.vram[patternAddress + 1].bit(index); diff --git a/higan/ms/vdp/sprite.cpp b/higan/ms/vdp/sprite.cpp index cb64beba..b5c2d3e8 100644 --- a/higan/ms/vdp/sprite.cpp +++ b/higan/ms/vdp/sprite.cpp @@ -43,11 +43,12 @@ auto VDP::Sprite::run() -> void { address += o.pattern << 5; address += (y & (large ? 15 : 7)) << 2; + auto index = 7 - (x & 7); uint4 color; - color.bit(0) = vdp.vram[address + 0].bit(x & 7); - color.bit(1) = vdp.vram[address + 1].bit(x & 7); - color.bit(2) = vdp.vram[address + 2].bit(x & 7); - color.bit(3) = vdp.vram[address + 3].bit(x & 7); + color.bit(0) = vdp.vram[address + 0].bit(index); + color.bit(1) = vdp.vram[address + 1].bit(index); + color.bit(2) = vdp.vram[address + 2].bit(index); + color.bit(3) = vdp.vram[address + 3].bit(index); if(color == 0) continue; if(output.color) { diff --git a/higan/ms/vdp/vdp.cpp b/higan/ms/vdp/vdp.cpp index fd5885f1..886d0645 100644 --- a/higan/ms/vdp/vdp.cpp +++ b/higan/ms/vdp/vdp.cpp @@ -34,13 +34,13 @@ auto VDP::main() -> void { sprite.run(); step(2); - uint5 color = cram[16 | io.backdropColor]; + uint6 color = cram[io.backdropColor]; if(background.output.color && (background.output.priority || !sprite.output.color)) { color = cram[background.output.palette << 4 | background.output.color]; } else if(sprite.output.color) { color = cram[16 | sprite.output.color]; } - if(x <= 7 && io.leftClip) color = cram[7]; + if(x <= 7 && io.leftClip) color = cram[io.backdropColor]; if(!io.displayEnable) color = 0; buffer[io.vcounter * 256 + x] = color; } diff --git a/higan/processor/z80/disassembler.cpp b/higan/processor/z80/disassembler.cpp index b58076c7..87afa76b 100644 --- a/higan/processor/z80/disassembler.cpp +++ b/higan/processor/z80/disassembler.cpp @@ -1,5 +1,5 @@ auto Z80::disassemble(uint16 pc) -> string { - string s; + string s, output; s.append(hex(pc, 4L), " "); uint8 prefix = 0x00; @@ -20,7 +20,21 @@ auto Z80::disassemble(uint16 pc) -> string { } } - s.append(pad(disassemble__(pc, prefix, code), -18L, ' ')); + if(code == 0xcb && prefix) { + auto d = (int8)code; + code = bus->read(pc++); + output = disassembleCBd(pc, prefix, d, code); + } else if(code == 0xcb) { + code = bus->read(pc++); + output = disassembleCB(pc, prefix, code); + } else if(code == 0xed) { + code = bus->read(pc++); + output = disassembleED(pc, prefix, code); + } else { + output = disassemble(pc, prefix, code); + } + + s.append(pad(output, -18L, ' ')); finish: s.append(" AF:", hex(r.af.word, 4L)); @@ -76,7 +90,7 @@ auto Z80::disassemble(uint16 pc) -> string { #define IHL string{"(", HL, displace(), ")"} #define ISP "(sp)" -auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string { +auto Z80::disassemble(uint16 pc, uint8 prefix, uint8 code) -> string { auto byte = [&] { return bus->read(pc++); }; @@ -97,9 +111,6 @@ auto Z80::disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string { return d >= 0 ? string{"+$", hex(d, 2L)} : string{"-$", hex(-d, 2L)}; }; - if(code == 0xcb) return code = byte(), disassembleCB(pc, prefix, code); - if(code == 0xed) return code = byte(), disassembleED(pc, prefix, code); - switch(code) { op(0x00, "nop ") op(0x01, "ld ", BC, NN) @@ -382,6 +393,12 @@ auto Z80::disassembleCB(uint16 pc, uint8 prefix, uint8 code) -> string { return d >= 0 ? string{"+$", hex(d, 2L)} : string{"-$", hex(-d, 2L)}; }; + if(prefix) { + auto d = (int8)code; + string ds = d >= 0 ? string{"+$", hex(d, 2L)} : string{"-$", hex(-d, 2L)}; + return {"rlc (", HL, ds, ")"}; + } + switch(code) { op(0x00, "rlc ", B) op(0x01, "rlc ", C) @@ -644,6 +661,33 @@ auto Z80::disassembleCB(uint16 pc, uint8 prefix, uint8 code) -> string { unreachable; } +auto Z80::disassembleCBd(uint16 pc, uint8 prefix, int8 d, uint8 code) -> string { + auto displace = [&] { + return d >= 0 ? string{"+$", hex(d, 2L)} : string{"-$", hex(-d, 2L)}; + }; + + switch(code) { + op(0x00, "rlc ", IHL, B) + op(0x01, "rlc ", IHL, C) + op(0x02, "rlc ", IHL, D) + op(0x03, "rlc ", IHL, E) + op(0x04, "rlc ", IHL, H) + op(0x05, "rlc ", IHL, L) + op(0x06, "rlc ", IHL) + op(0x07, "rlc ", IHL, A) + op(0x08, "rrc ", IHL, B) + op(0x09, "rrc ", IHL, C) + op(0x0a, "rrc ", IHL, D) + op(0x0b, "rrc ", IHL, E) + op(0x0c, "rrc ", IHL, H) + op(0x0d, "rrc ", IHL, L) + op(0x0e, "rrc ", IHL) + op(0x0f, "rrc ", IHL, A) + } + + return {"???"}; +} + auto Z80::disassembleED(uint16 pc, uint8 prefix, uint8 code) -> string { auto byte = [&] { return bus->read(pc++); diff --git a/higan/processor/z80/instruction.cpp b/higan/processor/z80/instruction.cpp index 1368f35a..426bd777 100644 --- a/higan/processor/z80/instruction.cpp +++ b/higan/processor/z80/instruction.cpp @@ -9,13 +9,24 @@ auto Z80::instruction() -> void { r.iff2 = 1; } - instruction__(code); + if(code == 0xcb && r.hlp != &r.hl) { + uint16 addr = HL + (int8)operand(); + wait(1); + instructionCBd(addr, opcode()); + } else if(code == 0xcb) { + instructionCB(opcode()); + } else if(code == 0xed) { + instructionED(opcode()); + } else { + instruction(code); + } + r.hlp = &r.hl; } #define op(id, name, ...) case id: return instruction##name(__VA_ARGS__); -auto Z80::instruction__(uint8 code) -> void { +auto Z80::instruction(uint8 code) -> void { switch(code) { op(0x00, NOP) op(0x01, LD_rr_nn, BC) @@ -220,7 +231,7 @@ auto Z80::instruction__(uint8 code) -> void { op(0xc8, RET_c, ZF == 1) op(0xc9, RET) op(0xca, JP_c_nn, ZF == 1) - op(0xcb, CB, opcode()) +//op(0xcb, cb:) op(0xcc, CALL_c_nn, ZF == 1) op(0xcd, CALL_nn) op(0xce, ADC_a_n) @@ -253,7 +264,7 @@ auto Z80::instruction__(uint8 code) -> void { op(0xea, JP_c_nn, PF == 1) op(0xeb, EX_rr_rr, DE, _HL) op(0xec, CALL_c_nn, PF == 1) - op(0xed, ED, opcode()) +//op(0xed, ed:) op(0xee, XOR_a_n) op(0xef, RST_o, 5) op(0xf0, RET_c, SF == 0) @@ -283,7 +294,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x03, RLC_r, E) op(0x04, RLC_r, H) op(0x05, RLC_r, L) - op(0x06, RLC_irr, HL) + op(0x06, RLC_irr, _HL) op(0x07, RLC_r, A) op(0x08, RRC_r, B) op(0x09, RRC_r, C) @@ -291,7 +302,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x0b, RRC_r, E) op(0x0c, RRC_r, H) op(0x0d, RRC_r, L) - op(0x0e, RRC_irr, HL) + op(0x0e, RRC_irr, _HL) op(0x0f, RRC_r, A) op(0x10, RL_r, B) op(0x11, RL_r, C) @@ -299,7 +310,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x13, RL_r, E) op(0x14, RL_r, H) op(0x15, RL_r, L) - op(0x16, RL_irr, HL) + op(0x16, RL_irr, _HL) op(0x17, RL_r, A) op(0x18, RR_r, B) op(0x19, RR_r, C) @@ -307,7 +318,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x1b, RR_r, E) op(0x1c, RR_r, H) op(0x1d, RR_r, L) - op(0x1e, RR_irr, HL) + op(0x1e, RR_irr, _HL) op(0x1f, RR_r, A) op(0x20, SLA_r, B) op(0x21, SLA_r, C) @@ -315,7 +326,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x23, SLA_r, E) op(0x24, SLA_r, H) op(0x25, SLA_r, L) - op(0x26, SLA_irr, HL) + op(0x26, SLA_irr, _HL) op(0x27, SLA_r, A) op(0x28, SRA_r, B) op(0x29, SRA_r, C) @@ -323,7 +334,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x2b, SRA_r, E) op(0x2c, SRA_r, H) op(0x2d, SRA_r, L) - op(0x2e, SRA_irr, HL) + op(0x2e, SRA_irr, _HL) op(0x2f, SRA_r, A) op(0x30, SLL_r, B) op(0x31, SLL_r, C) @@ -331,7 +342,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x33, SLL_r, E) op(0x34, SLL_r, H) op(0x35, SLL_r, L) - op(0x36, SLL_irr, HL) + op(0x36, SLL_irr, _HL) op(0x37, SLL_r, A) op(0x38, SRL_r, B) op(0x39, SRL_r, C) @@ -339,7 +350,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x3b, SRL_r, E) op(0x3c, SRL_r, H) op(0x3d, SRL_r, L) - op(0x3e, SRL_irr, HL) + op(0x3e, SRL_irr, _HL) op(0x3f, SRL_r, A) op(0x40, BIT_o_r, 0, B) op(0x41, BIT_o_r, 0, C) @@ -347,7 +358,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x43, BIT_o_r, 0, E) op(0x44, BIT_o_r, 0, H) op(0x45, BIT_o_r, 0, L) - op(0x46, BIT_o_irr, 0, HL) + op(0x46, BIT_o_irr, 0, _HL) op(0x47, BIT_o_r, 0, A) op(0x48, BIT_o_r, 1, B) op(0x49, BIT_o_r, 1, C) @@ -355,7 +366,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x4b, BIT_o_r, 1, E) op(0x4c, BIT_o_r, 1, H) op(0x4d, BIT_o_r, 1, L) - op(0x4e, BIT_o_irr, 1, HL) + op(0x4e, BIT_o_irr, 1, _HL) op(0x4f, BIT_o_r, 1, A) op(0x50, BIT_o_r, 2, B) op(0x51, BIT_o_r, 2, C) @@ -363,7 +374,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x53, BIT_o_r, 2, E) op(0x54, BIT_o_r, 2, H) op(0x55, BIT_o_r, 2, L) - op(0x56, BIT_o_irr, 2, HL) + op(0x56, BIT_o_irr, 2, _HL) op(0x57, BIT_o_r, 2, A) op(0x58, BIT_o_r, 3, B) op(0x59, BIT_o_r, 3, C) @@ -371,7 +382,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x5b, BIT_o_r, 3, E) op(0x5c, BIT_o_r, 3, H) op(0x5d, BIT_o_r, 3, L) - op(0x5e, BIT_o_irr, 3, HL) + op(0x5e, BIT_o_irr, 3, _HL) op(0x5f, BIT_o_r, 3, A) op(0x60, BIT_o_r, 4, B) op(0x61, BIT_o_r, 4, C) @@ -379,7 +390,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x63, BIT_o_r, 4, E) op(0x64, BIT_o_r, 4, H) op(0x65, BIT_o_r, 4, L) - op(0x66, BIT_o_irr, 4, HL) + op(0x66, BIT_o_irr, 4, _HL) op(0x67, BIT_o_r, 4, A) op(0x68, BIT_o_r, 5, B) op(0x69, BIT_o_r, 5, C) @@ -387,7 +398,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x6b, BIT_o_r, 5, E) op(0x6c, BIT_o_r, 5, H) op(0x6d, BIT_o_r, 5, L) - op(0x6e, BIT_o_irr, 5, HL) + op(0x6e, BIT_o_irr, 5, _HL) op(0x6f, BIT_o_r, 5, A) op(0x70, BIT_o_r, 6, B) op(0x71, BIT_o_r, 6, C) @@ -395,7 +406,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x73, BIT_o_r, 6, E) op(0x74, BIT_o_r, 6, H) op(0x75, BIT_o_r, 6, L) - op(0x76, BIT_o_irr, 6, HL) + op(0x76, BIT_o_irr, 6, _HL) op(0x77, BIT_o_r, 6, A) op(0x78, BIT_o_r, 7, B) op(0x79, BIT_o_r, 7, C) @@ -403,7 +414,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x7b, BIT_o_r, 7, E) op(0x7c, BIT_o_r, 7, H) op(0x7d, BIT_o_r, 7, L) - op(0x7e, BIT_o_irr, 7, HL) + op(0x7e, BIT_o_irr, 7, _HL) op(0x7f, BIT_o_r, 7, A) op(0x80, RES_o_r, 0, B) op(0x81, RES_o_r, 0, C) @@ -411,7 +422,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x83, RES_o_r, 0, E) op(0x84, RES_o_r, 0, H) op(0x85, RES_o_r, 0, L) - op(0x86, RES_o_irr, 0, HL) + op(0x86, RES_o_irr, 0, _HL) op(0x87, RES_o_r, 0, A) op(0x88, RES_o_r, 1, B) op(0x89, RES_o_r, 1, C) @@ -419,7 +430,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x8b, RES_o_r, 1, E) op(0x8c, RES_o_r, 1, H) op(0x8d, RES_o_r, 1, L) - op(0x8e, RES_o_irr, 1, HL) + op(0x8e, RES_o_irr, 1, _HL) op(0x8f, RES_o_r, 1, A) op(0x90, RES_o_r, 2, B) op(0x91, RES_o_r, 2, C) @@ -427,7 +438,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x93, RES_o_r, 2, E) op(0x94, RES_o_r, 2, H) op(0x95, RES_o_r, 2, L) - op(0x96, RES_o_irr, 2, HL) + op(0x96, RES_o_irr, 2, _HL) op(0x97, RES_o_r, 2, A) op(0x98, RES_o_r, 3, B) op(0x99, RES_o_r, 3, C) @@ -435,7 +446,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0x9b, RES_o_r, 3, E) op(0x9c, RES_o_r, 3, H) op(0x9d, RES_o_r, 3, L) - op(0x9e, RES_o_irr, 3, HL) + op(0x9e, RES_o_irr, 3, _HL) op(0x9f, RES_o_r, 3, A) op(0xa0, RES_o_r, 4, B) op(0xa1, RES_o_r, 4, C) @@ -443,7 +454,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0xa3, RES_o_r, 4, E) op(0xa4, RES_o_r, 4, H) op(0xa5, RES_o_r, 4, L) - op(0xa6, RES_o_irr, 4, HL) + op(0xa6, RES_o_irr, 4, _HL) op(0xa7, RES_o_r, 4, A) op(0xa8, RES_o_r, 5, B) op(0xa9, RES_o_r, 5, C) @@ -451,7 +462,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0xab, RES_o_r, 5, E) op(0xac, RES_o_r, 5, H) op(0xad, RES_o_r, 5, L) - op(0xae, RES_o_irr, 5, HL) + op(0xae, RES_o_irr, 5, _HL) op(0xaf, RES_o_r, 5, A) op(0xb0, RES_o_r, 6, B) op(0xb1, RES_o_r, 6, C) @@ -459,7 +470,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0xb3, RES_o_r, 6, E) op(0xb4, RES_o_r, 6, H) op(0xb5, RES_o_r, 6, L) - op(0xb6, RES_o_irr, 6, HL) + op(0xb6, RES_o_irr, 6, _HL) op(0xb7, RES_o_r, 6, A) op(0xb8, RES_o_r, 7, B) op(0xb9, RES_o_r, 7, C) @@ -467,7 +478,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0xbb, RES_o_r, 7, E) op(0xbc, RES_o_r, 7, H) op(0xbd, RES_o_r, 7, L) - op(0xbe, RES_o_irr, 7, HL) + op(0xbe, RES_o_irr, 7, _HL) op(0xbf, RES_o_r, 7, A) op(0xc0, SET_o_r, 0, B) op(0xc1, SET_o_r, 0, C) @@ -475,7 +486,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0xc3, SET_o_r, 0, E) op(0xc4, SET_o_r, 0, H) op(0xc5, SET_o_r, 0, L) - op(0xc6, SET_o_irr, 0, HL) + op(0xc6, SET_o_irr, 0, _HL) op(0xc7, SET_o_r, 0, A) op(0xc8, SET_o_r, 1, B) op(0xc9, SET_o_r, 1, C) @@ -483,7 +494,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0xcb, SET_o_r, 1, E) op(0xcc, SET_o_r, 1, H) op(0xcd, SET_o_r, 1, L) - op(0xce, SET_o_irr, 1, HL) + op(0xce, SET_o_irr, 1, _HL) op(0xcf, SET_o_r, 1, A) op(0xd0, SET_o_r, 2, B) op(0xd1, SET_o_r, 2, C) @@ -491,7 +502,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0xd3, SET_o_r, 2, E) op(0xd4, SET_o_r, 2, H) op(0xd5, SET_o_r, 2, L) - op(0xd6, SET_o_irr, 2, HL) + op(0xd6, SET_o_irr, 2, _HL) op(0xd7, SET_o_r, 2, A) op(0xd8, SET_o_r, 3, B) op(0xd9, SET_o_r, 3, C) @@ -499,7 +510,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0xdb, SET_o_r, 3, E) op(0xdc, SET_o_r, 3, H) op(0xdd, SET_o_r, 3, L) - op(0xde, SET_o_irr, 3, HL) + op(0xde, SET_o_irr, 3, _HL) op(0xdf, SET_o_r, 3, A) op(0xe0, SET_o_r, 4, B) op(0xe1, SET_o_r, 4, C) @@ -507,7 +518,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0xe3, SET_o_r, 4, E) op(0xe4, SET_o_r, 4, H) op(0xe5, SET_o_r, 4, L) - op(0xe6, SET_o_irr, 4, HL) + op(0xe6, SET_o_irr, 4, _HL) op(0xe7, SET_o_r, 4, A) op(0xe8, SET_o_r, 5, B) op(0xe9, SET_o_r, 5, C) @@ -515,7 +526,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0xeb, SET_o_r, 5, E) op(0xec, SET_o_r, 5, H) op(0xed, SET_o_r, 5, L) - op(0xee, SET_o_irr, 5, HL) + op(0xee, SET_o_irr, 5, _HL) op(0xef, SET_o_r, 5, A) op(0xf0, SET_o_r, 6, B) op(0xf1, SET_o_r, 6, C) @@ -523,7 +534,7 @@ auto Z80::instructionCB(uint8 code) -> void { op(0xf3, SET_o_r, 6, E) op(0xf4, SET_o_r, 6, H) op(0xf5, SET_o_r, 6, L) - op(0xf6, SET_o_irr, 6, HL) + op(0xf6, SET_o_irr, 6, _HL) op(0xf7, SET_o_r, 6, A) op(0xf8, SET_o_r, 7, B) op(0xf9, SET_o_r, 7, C) @@ -531,11 +542,34 @@ auto Z80::instructionCB(uint8 code) -> void { op(0xfb, SET_o_r, 7, E) op(0xfc, SET_o_r, 7, H) op(0xfd, SET_o_r, 7, L) - op(0xfe, SET_o_irr, 7, HL) + op(0xfe, SET_o_irr, 7, _HL) op(0xff, SET_o_r, 7, A) } } +auto Z80::instructionCBd(uint16 addr, uint8 code) -> void { + uint8 _; + + switch(code) { + op(0x00, RLC_irr_r, addr, B) + op(0x01, RLC_irr_r, addr, C) + op(0x02, RLC_irr_r, addr, D) + op(0x03, RLC_irr_r, addr, E) + op(0x04, RLC_irr_r, addr, H) + op(0x05, RLC_irr_r, addr, L) + op(0x06, RLC_irr_r, addr, _) + op(0x07, RLC_irr_r, addr, A) + op(0x08, RRC_irr_r, addr, B) + op(0x09, RRC_irr_r, addr, C) + op(0x0a, RRC_irr_r, addr, D) + op(0x0b, RRC_irr_r, addr, E) + op(0x0c, RRC_irr_r, addr, H) + op(0x0d, RRC_irr_r, addr, L) + op(0x0e, RRC_irr_r, addr, _) + op(0x0f, RRC_irr_r, addr, A) + } +} + auto Z80::instructionED(uint8 code) -> void { switch(code) { op(0x40, IN_r_ic, B) diff --git a/higan/processor/z80/instructions.cpp b/higan/processor/z80/instructions.cpp index 30720c1a..f4f34554 100644 --- a/higan/processor/z80/instructions.cpp +++ b/higan/processor/z80/instructions.cpp @@ -738,11 +738,14 @@ auto Z80::instructionRLA() -> void { YF = A.bit(5); } -auto Z80::instructionRLC_irr(uint16& x) -> void { - auto addr = displace(x); +auto Z80::instructionRLC_irr(uint16& addr) -> void { write(addr, RLC(read(addr))); } +auto Z80::instructionRLC_irr_r(uint16& addr, uint8& x) -> void { + write(addr, x = RLC(read(addr))); +} + auto Z80::instructionRLC_r(uint8& x) -> void { x = RLC(x); } @@ -794,11 +797,14 @@ auto Z80::instructionRRA() -> void { YF = A.bit(5); } -auto Z80::instructionRRC_irr(uint16& x) -> void { - auto addr = displace(x); +auto Z80::instructionRRC_irr(uint16& addr) -> void { write(addr, RRC(read(addr))); } +auto Z80::instructionRRC_irr_r(uint16& addr, uint8& x) -> void { + write(addr, x = RRC(read(addr))); +} + auto Z80::instructionRRC_r(uint8& x) -> void { x = RRC(x); } diff --git a/higan/processor/z80/memory.cpp b/higan/processor/z80/memory.cpp index 9991b413..39c2918a 100644 --- a/higan/processor/z80/memory.cpp +++ b/higan/processor/z80/memory.cpp @@ -29,7 +29,7 @@ auto Z80::pop() -> uint16 { auto Z80::displace(uint16& x) -> uint16 { if(&x != &r.ix.word && &x != &r.iy.word) return x; - auto d = read(x); + auto d = operand(); wait(5); return x + (int8)d; } diff --git a/higan/processor/z80/z80.hpp b/higan/processor/z80/z80.hpp index b5bf0372..ca92fe45 100644 --- a/higan/processor/z80/z80.hpp +++ b/higan/processor/z80/z80.hpp @@ -36,8 +36,9 @@ struct Z80 { //instruction.cpp auto instruction() -> void; - auto instruction__(uint8 code) -> void; + auto instruction(uint8 code) -> void; auto instructionCB(uint8 code) -> void; + auto instructionCBd(uint16 addr, uint8 code) -> void; auto instructionED(uint8 code) -> void; //instructions.cpp @@ -148,6 +149,7 @@ struct Z80 { auto instructionRL_r(uint8&) -> void; auto instructionRLA() -> void; auto instructionRLC_irr(uint16&) -> void; + auto instructionRLC_irr_r(uint16&, uint8&) -> void; auto instructionRLC_r(uint8&) -> void; auto instructionRLCA() -> void; auto instructionRLD() -> void; @@ -155,6 +157,7 @@ struct Z80 { auto instructionRR_r(uint8&) -> void; auto instructionRRA() -> void; auto instructionRRC_irr(uint16&) -> void; + auto instructionRRC_irr_r(uint16&, uint8&) -> void; auto instructionRRC_r(uint8&) -> void; auto instructionRRCA() -> void; auto instructionRRD() -> void; @@ -183,8 +186,9 @@ struct Z80 { //disassembler.cpp auto disassemble(uint16 pc) -> string; - auto disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string; + auto disassemble(uint16 pc, uint8 prefix, uint8 code) -> string; auto disassembleCB(uint16 pc, uint8 prefix, uint8 code) -> string; + auto disassembleCBd(uint16 pc, uint8 prefix, int8 d, uint8 code) -> string; auto disassembleED(uint16 pc, uint8 prefix, uint8 code) -> string; struct Registers { diff --git a/icarus/heuristics/master-system.cpp b/icarus/heuristics/master-system.cpp index 79cee49e..a0e034ed 100644 --- a/icarus/heuristics/master-system.cpp +++ b/icarus/heuristics/master-system.cpp @@ -11,6 +11,7 @@ struct MasterSystemCartridge { MasterSystemCartridge::MasterSystemCartridge(string location, uint8_t* data, uint size) { manifest.append("board\n"); manifest.append(" rom name=program.rom size=0x", hex(size), "\n"); + manifest.append(" ram name=save.ram size=0x8000\n"); manifest.append("\n"); manifest.append("information\n"); manifest.append(" title: ", Location::prefix(location), "\n");