From 79e7e6ab9e37a344278dbcc7df2d6d80bd927e9d Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Thu, 10 Mar 2016 21:35:48 +1100 Subject: [PATCH] Update to v097r23 release. byuu says: Changelog: - emulated SuperDisc $21e1 basic interface (NEC 4-bit MCU); all hardware tests pass now (but they don't test much) - WS/V30MZ: fixed inc/dec reg flag calculation - WS/V30MZ: fixed lds/les instructions WS/C compatibility should be way up now. SuperDisc BIOS passes all tests now (but they only test for the presence of the interface, nothing more.) --- higan/emulator/emulator.hpp | 2 +- higan/processor/r65816/disassembler.cpp | 20 +- higan/processor/v30mz/instructions-alu.cpp | 4 +- higan/processor/v30mz/instructions-move.cpp | 5 +- higan/sfc/expansion/superdisc/nec.cpp | 202 ++++++++++++++++++++ higan/sfc/expansion/superdisc/sony.cpp | 143 ++++++++++++++ higan/sfc/expansion/superdisc/superdisc.cpp | 56 +++--- higan/sfc/expansion/superdisc/superdisc.hpp | 32 +++- higan/ws/cpu/io.cpp | 2 +- 9 files changed, 418 insertions(+), 48 deletions(-) create mode 100644 higan/sfc/expansion/superdisc/nec.cpp create mode 100644 higan/sfc/expansion/superdisc/sony.cpp diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index cb8a833e..cf1fa004 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -6,7 +6,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "097.22"; + static const string Version = "097.23"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/processor/r65816/disassembler.cpp b/higan/processor/r65816/disassembler.cpp index b48c8c7c..5c551273 100644 --- a/higan/processor/r65816/disassembler.cpp +++ b/higan/processor/r65816/disassembler.cpp @@ -148,7 +148,7 @@ auto R65816::disassemble_opcode(char* output, uint32 addr, bool e, bool m, bool case 0x0d: sprintf(t, "ora $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; case 0x0e: sprintf(t, "asl $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; case 0x0f: sprintf(t, "ora $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0x10: sprintf(t, "bpl $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0x10: sprintf(t, "bpl $%.4x [%.6x]", uint16_t(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; case 0x11: sprintf(t, "ora ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break; case 0x12: sprintf(t, "ora ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break; case 0x13: sprintf(t, "ora ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break; @@ -181,7 +181,7 @@ auto R65816::disassemble_opcode(char* output, uint32 addr, bool e, bool m, bool case 0x2d: sprintf(t, "and $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; case 0x2e: sprintf(t, "rol $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; case 0x2f: sprintf(t, "and $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0x30: sprintf(t, "bmi $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0x30: sprintf(t, "bmi $%.4x [%.6x]", uint16_t(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; case 0x31: sprintf(t, "and ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break; case 0x32: sprintf(t, "and ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break; case 0x33: sprintf(t, "and ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break; @@ -214,7 +214,7 @@ auto R65816::disassemble_opcode(char* output, uint32 addr, bool e, bool m, bool case 0x4d: sprintf(t, "eor $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; case 0x4e: sprintf(t, "lsr $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; case 0x4f: sprintf(t, "eor $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0x50: sprintf(t, "bvc $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0x50: sprintf(t, "bvc $%.4x [%.6x]", uint16_t(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; case 0x51: sprintf(t, "eor ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break; case 0x52: sprintf(t, "eor ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break; case 0x53: sprintf(t, "eor ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break; @@ -247,7 +247,7 @@ auto R65816::disassemble_opcode(char* output, uint32 addr, bool e, bool m, bool case 0x6d: sprintf(t, "adc $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; case 0x6e: sprintf(t, "ror $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; case 0x6f: sprintf(t, "adc $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0x70: sprintf(t, "bvs $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0x70: sprintf(t, "bvs $%.4x [%.6x]", uint16_t(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; case 0x71: sprintf(t, "adc ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break; case 0x72: sprintf(t, "adc ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break; case 0x73: sprintf(t, "adc ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break; @@ -263,9 +263,9 @@ auto R65816::disassemble_opcode(char* output, uint32 addr, bool e, bool m, bool case 0x7d: sprintf(t, "adc $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; case 0x7e: sprintf(t, "ror $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break; case 0x7f: sprintf(t, "adc $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break; - case 0x80: sprintf(t, "bra $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0x80: sprintf(t, "bra $%.4x [%.6x]", uint16_t(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; case 0x81: sprintf(t, "sta ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break; - case 0x82: sprintf(t, "brl $%.4x [%.6x]", uint16(decode(OPTYPE_RELW, op16)), decode(OPTYPE_RELW, op16)); break; + case 0x82: sprintf(t, "brl $%.4x [%.6x]", uint16_t(decode(OPTYPE_RELW, op16)), decode(OPTYPE_RELW, op16)); break; case 0x83: sprintf(t, "sta $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break; case 0x84: sprintf(t, "sty $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; case 0x85: sprintf(t, "sta $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break; @@ -280,7 +280,7 @@ auto R65816::disassemble_opcode(char* output, uint32 addr, bool e, bool m, bool case 0x8d: sprintf(t, "sta $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; case 0x8e: sprintf(t, "stx $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; case 0x8f: sprintf(t, "sta $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0x90: sprintf(t, "bcc $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0x90: sprintf(t, "bcc $%.4x [%.6x]", uint16_t(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; case 0x91: sprintf(t, "sta ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break; case 0x92: sprintf(t, "sta ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break; case 0x93: sprintf(t, "sta ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break; @@ -315,7 +315,7 @@ auto R65816::disassemble_opcode(char* output, uint32 addr, bool e, bool m, bool case 0xad: sprintf(t, "lda $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; case 0xae: sprintf(t, "ldx $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; case 0xaf: sprintf(t, "lda $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0xb0: sprintf(t, "bcs $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0xb0: sprintf(t, "bcs $%.4x [%.6x]", uint16_t(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; case 0xb1: sprintf(t, "lda ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break; case 0xb2: sprintf(t, "lda ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break; case 0xb3: sprintf(t, "lda ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break; @@ -349,7 +349,7 @@ auto R65816::disassemble_opcode(char* output, uint32 addr, bool e, bool m, bool case 0xcd: sprintf(t, "cmp $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; case 0xce: sprintf(t, "dec $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; case 0xcf: sprintf(t, "cmp $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0xd0: sprintf(t, "bne $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0xd0: sprintf(t, "bne $%.4x [%.6x]", uint16_t(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; case 0xd1: sprintf(t, "cmp ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break; case 0xd2: sprintf(t, "cmp ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break; case 0xd3: sprintf(t, "cmp ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break; @@ -383,7 +383,7 @@ auto R65816::disassemble_opcode(char* output, uint32 addr, bool e, bool m, bool case 0xed: sprintf(t, "sbc $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; case 0xee: sprintf(t, "inc $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break; case 0xef: sprintf(t, "sbc $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break; - case 0xf0: sprintf(t, "beq $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; + case 0xf0: sprintf(t, "beq $%.4x [%.6x]", uint16_t(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break; case 0xf1: sprintf(t, "sbc ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break; case 0xf2: sprintf(t, "sbc ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break; case 0xf3: sprintf(t, "sbc ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break; diff --git a/higan/processor/v30mz/instructions-alu.cpp b/higan/processor/v30mz/instructions-alu.cpp index b90c1c99..1ed3255b 100644 --- a/higan/processor/v30mz/instructions-alu.cpp +++ b/higan/processor/v30mz/instructions-alu.cpp @@ -146,7 +146,7 @@ auto V30MZ::opMultiplySignedRegMemImm(Size size) { //46 inc si //47 inc di auto V30MZ::opIncReg(uint16_t& reg) { - reg++; + reg = alInc(Word, reg); } //48 dec ax @@ -158,7 +158,7 @@ auto V30MZ::opIncReg(uint16_t& reg) { //4e dec si //4f dec di auto V30MZ::opDecReg(uint16_t& reg) { - reg--; + reg = alDec(Word, reg); } //98 cbw diff --git a/higan/processor/v30mz/instructions-move.cpp b/higan/processor/v30mz/instructions-move.cpp index b51bf663..f62db604 100644 --- a/higan/processor/v30mz/instructions-move.cpp +++ b/higan/processor/v30mz/instructions-move.cpp @@ -65,8 +65,9 @@ auto V30MZ::opLoadEffectiveAddressRegMem() { setReg(Word, modrm.address); } -auto V30MZ::opLoadSegmentMem(uint16_t& reg) { +auto V30MZ::opLoadSegmentMem(uint16_t& segment) { wait(5); modRM(); - reg = getMem(Word); + setReg(Word, getMem(Word)); + segment = getMem(Word, 2); } diff --git a/higan/sfc/expansion/superdisc/nec.cpp b/higan/sfc/expansion/superdisc/nec.cpp new file mode 100644 index 00000000..fd68215e --- /dev/null +++ b/higan/sfc/expansion/superdisc/nec.cpp @@ -0,0 +1,202 @@ +//NEC D75P308GF +//4-bit microcontroller +//CD-player interface + +auto SuperDisc::necPollIRQ() -> uint8 { + auto match = [&](const string& compare) -> bool { + if(nec.command.size() != compare.size()) return false; + for(auto n : range(nec.command)) { + char c = compare[n]; + if(c == '?') continue; + if(c >= '0' && c <= '9') c -= '0'; + if(c >= 'a' && c <= 'f') c -= 'a' - 10; + if(nec.command[n] != c) return false; + } + return true; + }; + + //access ??/??/?? + if(match("b" )) return 0x8f; + if(match("b?" )) return 0x8f; + if(match("b??" )) return 0x8f; + if(match("b???" )) return 0x8f; + if(match("b????" )) return 0x8f; + if(match("b?????" )) return 0x8f; + if(match("b??????" )) return 0x8f; + if(match("b??????f")) { + nec.command.reset(); + return 0x8f; + } + + //access t??/i?? + if(match("c" )) return 0x8f; + if(match("c?" )) return 0x8f; + if(match("c??" )) return 0x8f; + if(match("c???" )) return 0x8f; + if(match("c????" )) return 0x8f; + if(match("c????f")) { + nec.command.reset(); + return 0x8f; + } + + //d-prefixes + if(match("d" )) return 0x8f; + if(match("d0")) return 0x8f; + if(match("d1")) return 0x8f; + if(match("d4")) return 0x8f; + if(match("d5")) return 0x8f; + + //stop + if(match("d01" )) return 0x8f; + if(match("d01f")) { + nec.command.reset(); + return 0x8f; + } + + //play + if(match("d02" )) return 0x8f; + if(match("d02f")) { + nec.command.reset(); + return 0x8f; + } + + //pause + if(match("d03" )) return 0x8f; + if(match("d03f")) { + nec.command.reset(); + return 0x8f; + } + + //open / close + if(match("d04" )) return 0x8f; + if(match("d04f")) { + nec.command.reset(); + return 0x8f; + } + + //fast forward + if(match("d10" )) return 0x8f; + if(match("d10f")) { + nec.command.reset(); + return 0x8f; + } + + //fast reverse + if(match("d11" )) return 0x8f; + if(match("d11f")) { + nec.command.reset(); + return 0x8f; + } + + //forward + if(match("d12" )) return 0x8f; + if(match("d12f")) { + nec.command.reset(); + return 0x8f; + } + + //reverse + if(match("d13" )) return 0x8f; + if(match("d13f")) { + nec.command.reset(); + return 0x8f; + } + + //key direct + if(match("d40" )) return 0x8f; + if(match("d40f")) { + nec.command.reset(); + return 0x8f; + } + + //key ignore + if(match("d41" )) return 0x8f; + if(match("d41f")) { + nec.command.reset(); + return 0x8f; + } + + //continuous play + if(match("d42" )) return 0x8f; + if(match("d42f")) { + nec.command.reset(); + return 0x8f; + } + + //auto track pause + if(match("d43" )) return 0x8f; + if(match("d43f")) { + nec.command.reset(); + return 0x8f; + } + + //auto index pause + if(match("d44" )) return 0x8f; + if(match("d44f")) { + nec.command.reset(); + return 0x8f; + } + + //normal speed + if(match("d45" )) return 0x8f; + if(match("d45f")) { + nec.command.reset(); + return 0x8f; + } + + //double speed + if(match("d46" )) return 0x8f; + if(match("d46f")) { + nec.command.reset(); + return 0x8f; + } + + //q-data request + if(match("d50" )) return 0x8f; + if(match("d50f" )) return 0x8f; + if(match("d50f?" )) return 0x80; + if(match("d50f??" )) return 0x80; + if(match("d50f???" )) return 0x80; + if(match("d50f????" )) return 0x80; + if(match("d50f?????" )) return 0x80; + if(match("d50f??????" )) return 0x80; + if(match("d50f???????" )) return 0x80; + if(match("d50f????????" )) return 0x80; + if(match("d50f?????????" )) return 0x80; + if(match("d50f??????????" )) return 0x80; + if(match("d50f???????????" )) return 0x80; + if(match("d50f????????????" )) return 0x80; + if(match("d50f?????????????" )) return 0x80; + if(match("d50f??????????????" )) return 0x80; + if(match("d50f???????????????" )) return 0x80; + if(match("d50f????????????????" )) return 0x80; + if(match("d50f????????????????f")) { + nec.command.reset(); + return 0x8f; + } + + //status request + if(match("d51" )) return 0x8f; + if(match("d51f" )) return 0x8f; + if(match("d51f0" )) return 0x81; + if(match("d51f01" )) return 0x80; + if(match("d51f012" )) return 0x81; + if(match("d51f0123" )) return 0x80; + if(match("d51f01234" )) return 0x80; + if(match("d51f01234f")) { + nec.command.reset(); + return 0x8f; + } + + nec.command.reset(); + return 0x00; +} + +auto SuperDisc::necReadData() -> uint8 { + return nec.data; +} + +auto SuperDisc::necWriteCommand(uint4 data) -> void { + if(nec.command.size() >= 32) return; + nec.command.append(data); +} diff --git a/higan/sfc/expansion/superdisc/sony.cpp b/higan/sfc/expansion/superdisc/sony.cpp new file mode 100644 index 00000000..b32949c6 --- /dev/null +++ b/higan/sfc/expansion/superdisc/sony.cpp @@ -0,0 +1,143 @@ +//Sony CXD1800Q +//CD-ROM decoder + +auto SuperDisc::sonyPollIRQ() -> uint8 { + return 0x00; +} + +auto SuperDisc::sonyReadData() -> uint8 { + uint8 command = sony.command++; + + auto match = [&](const string& compare) -> bool { + char hi = compare[0]; + if(hi == '?') hi = 0; + if(hi >= '0' && hi <= '9') hi -= '0'; + if(hi >= 'a' && hi <= 'f') hi -= 'a' - 10; + if(hi != '?' && hi != command.bits(4,7)) return false; + + char lo = compare[1]; + if(lo == '?') lo = 0; + if(lo >= '0' && lo <= '9') lo -= '0'; + if(lo >= 'a' && lo <= 'f') lo -= 'a' - 10; + if(lo != '?' && lo != command.bits(0,3)) return false; + + return true; + }; + + //DMA + if(match("00")) return 0x00; + + //INST + if(match("01")) return 0x10; + + //STS + if(match("02")) return 0x00; + + //HFLG + if(match("03")) return 0x00; + + //HMIN + if(match("?4")) return 0x00; + + //HSEC + if(match("?5")) return 0x00; + + //HBLK + if(match("?6")) return 0x00; + + //HMOD + if(match("?7")) return 0x00; + + //SFIL + if(match("08")) return 0x00; + + //SCH + if(match("09")) return 0x00; + + //SMOD + if(match("0a")) return 0x00; + + //SCI + if(match("0b")) return 0x00; + + //CMAD + if(match("0c")) return 0x00; + if(match("0d")) return 0x00; + + //MDFM + if(match("?e")) return 0x00; + + //ADPC + if(match("?f")) return 0x00; + + //DMXF + if(match("18")) return 0x00; + if(match("19")) return 0x00; + + //DMAD + if(match("1a")) return 0x00; + if(match("1b")) return 0x00; + + //DRAD + if(match("1c")) return 0x00; + if(match("1d")) return 0x00; + + return 0x00; +} + +auto SuperDisc::sonyWriteCommand(uint8 data) -> void { + sony.command = data; +} + +auto SuperDisc::sonyWriteData(uint8 data) -> void { + uint8 command = sony.command++; + + auto match = [&](const string& compare) -> bool { + char hi = compare[0]; + if(hi == '?') hi = 0; + if(hi >= '0' && hi <= '9') hi -= '0'; + if(hi >= 'a' && hi <= 'f') hi -= 'a' - 10; + if(hi != '?' && hi != command.bits(4,7)) return false; + + char lo = compare[1]; + if(lo == '?') lo = 0; + if(lo >= '0' && lo <= '9') lo -= '0'; + if(lo >= 'a' && lo <= 'f') lo -= 'a' - 10; + if(lo != '?' && lo != command.bits(0,3)) return false; + + return true; + }; + + //DRIF + if(match("?1")) return; + + //CHCT + if(match("?2")) return; + + //DECT + if(match("?3")) return; + + //INMS + if(match("?4")) return; + + //INCL + if(match("?5")) return; + + //CI + if(match("?6")) return; + + //DMAD + if(match("?7")) return; + if(match("?8")) return; + + //DMXF + if(match("?9")) return; + if(match("?a")) return; + + //DRAD + if(match("?b")) return; + if(match("?c")) return; + + //PLBA + if(match("0d")) return; +} diff --git a/higan/sfc/expansion/superdisc/superdisc.cpp b/higan/sfc/expansion/superdisc/superdisc.cpp index 6a89bb92..2d8a71f7 100644 --- a/higan/sfc/expansion/superdisc/superdisc.cpp +++ b/higan/sfc/expansion/superdisc/superdisc.cpp @@ -3,18 +3,24 @@ namespace SuperFamicom { SuperDisc superdisc; +#include "nec.cpp" +#include "sony.cpp" auto SuperDisc::Enter() -> void { while(true) scheduler.synchronize(), superdisc.main(); } auto SuperDisc::main() -> void { - if(r21e4 & 0x04) { + cpu.regs.irq = 0; + + if(r.irqEnable.bit(3)) { cpu.regs.irq = 1; - r21e1 = 0x81; - } else { - cpu.regs.irq = 0; - r21e1 = 0x00; + nec.data = necPollIRQ(); + } + + if(r.irqEnable.bit(2)) { + cpu.regs.irq = 1; + sony.data = sonyPollIRQ(); } step(1); @@ -37,41 +43,42 @@ auto SuperDisc::power() -> void { } auto SuperDisc::reset() -> void { - r21e0 = 0x00; - r21e1 = 0x00; - r21e2 = 0x00; - r21e3 = 0x00; - r21e4 = 0x00; - r21e5 = 0x00; + r.irqEnable = 0x00; + + nec.command.reset(); + nec.data = 0x00; + + sony.command = 0x00; + sony.data = 0x00; } auto SuperDisc::read(uint24 addr, uint8 data) -> uint8 { addr = 0x21e0 | (addr & 7); if(addr == 0x21e0) { - data = r21e0; + data = 0x00; } if(addr == 0x21e1) { - data = r21e1; + cpu.regs.irq = 0; + data = necReadData(); } if(addr == 0x21e2) { - data = r21e2; + data = 0x00; } if(addr == 0x21e3) { - if(r21e2 == 0x01) data = 0x10; - else data = 0x00; - r21e2++; + cpu.regs.irq = 0; + data = sonyReadData(); } if(addr == 0x21e4) { - data = r21e4; + data = r.irqEnable; } if(addr == 0x21e5) { - data = r21e5; + data = 0x00; } return data; @@ -81,28 +88,25 @@ auto SuperDisc::write(uint24 addr, uint8 data) -> void { addr = 0x21e0 | (addr & 7); if(addr == 0x21e0) { - r21e0 = data; } if(addr == 0x21e1) { - r21e1 = data; + necWriteCommand(data.bits(0,3)); } if(addr == 0x21e2) { - r21e2 = data; + sonyWriteCommand(data); } if(addr == 0x21e3) { - r21e2++; - r21e3 = data; + sonyWriteData(data); } if(addr == 0x21e4) { - r21e4 = data; + r.irqEnable = data; } if(addr == 0x21e5) { - r21e5 = data; } } diff --git a/higan/sfc/expansion/superdisc/superdisc.hpp b/higan/sfc/expansion/superdisc/superdisc.hpp index 2665fddb..1275321c 100644 --- a/higan/sfc/expansion/superdisc/superdisc.hpp +++ b/higan/sfc/expansion/superdisc/superdisc.hpp @@ -11,13 +11,33 @@ struct SuperDisc : Coprocessor, Memory { auto read(uint24 addr, uint8 data) -> uint8; auto write(uint24 addr, uint8 data) -> void; + //nec.cpp + auto necPollIRQ() -> uint8; + auto necReadData() -> uint8; + auto necWriteCommand(uint4 data) -> void; + + //sony.cpp + auto sonyPollIRQ() -> uint8; + auto sonyReadData() -> uint8; + auto sonyWriteCommand(uint8 data) -> void; + auto sonyWriteData(uint8 data) -> void; + private: - uint8 r21e0; - uint8 r21e1; - uint8 r21e2; - uint8 r21e3; - uint8 r21e4; - uint8 r21e5; + struct Registers { + uint8 irqEnable; + } r; + + //NEC + struct NEC { + vector command; + uint8 data; + } nec; + + //Sony + struct Sony { + uint8 command; + uint8 data; + } sony; }; extern SuperDisc superdisc; diff --git a/higan/ws/cpu/io.cpp b/higan/ws/cpu/io.cpp index 4cf779c2..21df93c8 100644 --- a/higan/ws/cpu/io.cpp +++ b/higan/ws/cpu/io.cpp @@ -1,5 +1,5 @@ auto CPU::keypadRead() -> uint4 { - uint1 orientation = 1; + uint1 orientation = 0; uint4 data = 0; if(r.ypadEnable) {