diff --git a/BizHawk.Emulation.Cores/Computers/MSX/LibMSX.cs b/BizHawk.Emulation.Cores/Computers/MSX/LibMSX.cs index c78a0b8971..715c9787fa 100644 --- a/BizHawk.Emulation.Cores/Computers/MSX/LibMSX.cs +++ b/BizHawk.Emulation.Cores/Computers/MSX/LibMSX.cs @@ -53,7 +53,7 @@ namespace BizHawk.Emulation.Cores.Computers.MSX /// Mapper number to load core with /// 0 on success, negative value on failure. [DllImport("MSXHawk.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern bool MSX_frame_advance(IntPtr core, byte ctrl1, byte ctrl2, bool render, bool sound); + public static extern bool MSX_frame_advance(IntPtr core, byte ctrl1, byte ctrl2, byte[] kbrows, bool render, bool sound); /// /// Get Video data @@ -112,6 +112,13 @@ namespace BizHawk.Emulation.Cores.Computers.MSX [DllImport("MSXHawk.dll", CallingConvention = CallingConvention.Cdecl)] public static extern byte MSX_getvram(IntPtr core, int addr); + /// + /// Read the RAM + /// + /// opaque state pointer + /// ram address + [DllImport("MSXHawk.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern byte MSX_getram(IntPtr core, int addr); #endregion diff --git a/BizHawk.Emulation.Cores/Computers/MSX/MSX.IEmulator.cs b/BizHawk.Emulation.Cores/Computers/MSX/MSX.IEmulator.cs index 92121c4735..25f3e04d7e 100644 --- a/BizHawk.Emulation.Cores/Computers/MSX/MSX.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Computers/MSX/MSX.IEmulator.cs @@ -16,7 +16,7 @@ namespace BizHawk.Emulation.Cores.Computers.MSX } public bool FrameAdvance(IController controller, bool render, bool rendersound) - { + { _controller = controller; byte ctrl1_byte = 0xFF; @@ -28,12 +28,14 @@ namespace BizHawk.Emulation.Cores.Computers.MSX if (_controller.IsPressed("P1 B2")) ctrl1_byte -= 0x20; byte ctrl2_byte = 0xFF; - if (_controller.IsPressed("P2 Up")) ctrl1_byte -= 0x01; - if (_controller.IsPressed("P2 Down")) ctrl1_byte -= 0x02; - if (_controller.IsPressed("P2 Left")) ctrl1_byte -= 0x04; - if (_controller.IsPressed("P2 Right")) ctrl1_byte -= 0x08; - if (_controller.IsPressed("P2 B1")) ctrl1_byte -= 0x10; - if (_controller.IsPressed("P2 B2")) ctrl1_byte -= 0x20; + if (_controller.IsPressed("P2 Up")) ctrl2_byte -= 0x01; + if (_controller.IsPressed("P2 Down")) ctrl2_byte -= 0x02; + if (_controller.IsPressed("P2 Left")) ctrl2_byte -= 0x04; + if (_controller.IsPressed("P2 Right")) ctrl2_byte -= 0x08; + if (_controller.IsPressed("P2 B1")) ctrl2_byte -= 0x10; + if (_controller.IsPressed("P2 B2")) ctrl2_byte -= 0x20; + + kb_rows_check(controller); _frame++; @@ -45,14 +47,102 @@ namespace BizHawk.Emulation.Cores.Computers.MSX { tracecb = null; } - + LibMSX.MSX_settracecallback(MSX_Pntr, tracecb); - - LibMSX.MSX_frame_advance(MSX_Pntr, ctrl1_byte, ctrl2_byte, true, true); - + + LibMSX.MSX_frame_advance(MSX_Pntr, ctrl1_byte, ctrl2_byte, kb_rows, true, true); + return true; } + public byte[] kb_rows = new byte[16]; + + public void kb_rows_check(IController controller) + { + for(int i = 0; i < 9; i++) { kb_rows[i] = 0; } + + if (controller.IsPressed("7")) { kb_rows[0] |= 0x80; } + if (controller.IsPressed("6")) { kb_rows[0] |= 0x40; } + if (controller.IsPressed("5")) { kb_rows[0] |= 0x20; } + if (controller.IsPressed("4")) { kb_rows[0] |= 0x10; } + if (controller.IsPressed("3")) { kb_rows[0] |= 0x08; } + if (controller.IsPressed("2")) { kb_rows[0] |= 0x04; } + if (controller.IsPressed("1")) { kb_rows[0] |= 0x02; } + if (controller.IsPressed("0")) { kb_rows[0] |= 0x01; } + + if (controller.IsPressed(";")) { kb_rows[1] |= 0x80; } + if (controller.IsPressed("[")) { kb_rows[1] |= 0x40; } + if (controller.IsPressed("@")) { kb_rows[1] |= 0x20; } + if (controller.IsPressed("$")) { kb_rows[1] |= 0x10; } + if (controller.IsPressed("^")) { kb_rows[1] |= 0x08; } + if (controller.IsPressed("-")) { kb_rows[1] |= 0x04; } + if (controller.IsPressed("9")) { kb_rows[1] |= 0x02; } + if (controller.IsPressed("8")) { kb_rows[1] |= 0x01; } + + if (controller.IsPressed("B")) { kb_rows[2] |= 0x80; } + if (controller.IsPressed("A")) { kb_rows[2] |= 0x40; } + + if (controller.IsPressed("/")) { kb_rows[2] |= 0x10; } + if (controller.IsPressed(".")) { kb_rows[2] |= 0x08; } + if (controller.IsPressed(",")) { kb_rows[2] |= 0x04; } + if (controller.IsPressed("]")) { kb_rows[2] |= 0x02; } + if (controller.IsPressed(":")) { kb_rows[2] |= 0x01; } + + if (controller.IsPressed("J")) { kb_rows[3] |= 0x80; } + if (controller.IsPressed("I")) { kb_rows[3] |= 0x40; } + if (controller.IsPressed("H")) { kb_rows[3] |= 0x20; } + if (controller.IsPressed("G")) { kb_rows[3] |= 0x10; } + if (controller.IsPressed("F")) { kb_rows[3] |= 0x08; } + if (controller.IsPressed("E")) { kb_rows[3] |= 0x04; } + if (controller.IsPressed("D")) { kb_rows[3] |= 0x02; } + if (controller.IsPressed("C")) { kb_rows[3] |= 0x01; } + + if (controller.IsPressed("R")) { kb_rows[4] |= 0x80; } + if (controller.IsPressed("Q")) { kb_rows[4] |= 0x40; } + if (controller.IsPressed("P")) { kb_rows[4] |= 0x20; } + if (controller.IsPressed("O")) { kb_rows[4] |= 0x10; } + if (controller.IsPressed("N")) { kb_rows[4] |= 0x08; } + if (controller.IsPressed("M")) { kb_rows[4] |= 0x04; } + if (controller.IsPressed("L")) { kb_rows[4] |= 0x02; } + if (controller.IsPressed("K")) { kb_rows[4] |= 0x01; } + + if (controller.IsPressed("Z")) { kb_rows[5] |= 0x80; } + if (controller.IsPressed("Y")) { kb_rows[5] |= 0x40; } + if (controller.IsPressed("X")) { kb_rows[5] |= 0x20; } + if (controller.IsPressed("W")) { kb_rows[5] |= 0x10; } + if (controller.IsPressed("V")) { kb_rows[5] |= 0x08; } + if (controller.IsPressed("U")) { kb_rows[5] |= 0x04; } + if (controller.IsPressed("T")) { kb_rows[5] |= 0x02; } + if (controller.IsPressed("S")) { kb_rows[5] |= 0x01; } + + if (controller.IsPressed("F3")) { kb_rows[6] |= 0x80; } + if (controller.IsPressed("F2")) { kb_rows[6] |= 0x40; } + if (controller.IsPressed("F1")) { kb_rows[6] |= 0x20; } + if (controller.IsPressed("KANA")) { kb_rows[6] |= 0x10; } + if (controller.IsPressed("CAP")) { kb_rows[6] |= 0x08; } + if (controller.IsPressed("GRAPH")) { kb_rows[6] |= 0x04; } + if (controller.IsPressed("CTRL")) { kb_rows[6] |= 0x02; } + if (controller.IsPressed("SHIFT")) { kb_rows[6] |= 0x01; } + + if (controller.IsPressed("RET")) { kb_rows[7] |= 0x80; } + if (controller.IsPressed("SEL")) { kb_rows[7] |= 0x40; } + if (controller.IsPressed("BACK")) { kb_rows[7] |= 0x20; } + if (controller.IsPressed("STOP")) { kb_rows[7] |= 0x10; } + if (controller.IsPressed("TAB")) { kb_rows[7] |= 0x08; } + if (controller.IsPressed("ESC")) { kb_rows[7] |= 0x04; } + if (controller.IsPressed("F5")) { kb_rows[7] |= 0x02; } + if (controller.IsPressed("F4")) { kb_rows[7] |= 0x01; } + + if (controller.IsPressed("RIGHT")) { kb_rows[8] |= 0x80; } + if (controller.IsPressed("DOWN")) { kb_rows[8] |= 0x40; } + if (controller.IsPressed("UP")) { kb_rows[8] |= 0x20; } + if (controller.IsPressed("LEFT")) { kb_rows[8] |= 0x10; } + if (controller.IsPressed("DEL")) { kb_rows[8] |= 0x08; } + if (controller.IsPressed("INS")) { kb_rows[8] |= 0x04; } + if (controller.IsPressed("HOME")) { kb_rows[8] |= 0x02; } + if (controller.IsPressed("SPACE")) { kb_rows[8] |= 0x01; } + } + public int Frame => _frame; public string SystemId => "MSX"; @@ -151,6 +241,7 @@ namespace BizHawk.Emulation.Cores.Computers.MSX public int VirtualHeight => 192; public int BufferWidth => 256; public int BufferHeight => 192; + public int BackgroundColor => unchecked((int)0xFF000000); public int VsyncNumerator => _frameHz; public int VsyncDenominator => 1; diff --git a/BizHawk.Emulation.Cores/Computers/MSX/MSX.IMemoryDomains.cs b/BizHawk.Emulation.Cores/Computers/MSX/MSX.IMemoryDomains.cs index 7866cf4203..321e15070f 100644 --- a/BizHawk.Emulation.Cores/Computers/MSX/MSX.IMemoryDomains.cs +++ b/BizHawk.Emulation.Cores/Computers/MSX/MSX.IMemoryDomains.cs @@ -30,6 +30,13 @@ namespace BizHawk.Emulation.Cores.Computers.MSX (addr) => LibMSX.MSX_getvram(MSX_Pntr, (int)(addr & 0x3FFF)), (addr, value) => { }, 1), + new MemoryDomainDelegate( + "RAM", + 0x10000, + MemoryDomain.Endian.Little, + (addr) => LibMSX.MSX_getram(MSX_Pntr, (int)(addr & 0xFFFF)), + (addr, value) => { }, + 1) }; if (SaveRAM != null) diff --git a/BizHawk.Emulation.Cores/Computers/MSX/MSX.Input.cs b/BizHawk.Emulation.Cores/Computers/MSX/MSX.Input.cs index 01f59e88c2..1dfa9a7e00 100644 --- a/BizHawk.Emulation.Cores/Computers/MSX/MSX.Input.cs +++ b/BizHawk.Emulation.Cores/Computers/MSX/MSX.Input.cs @@ -14,7 +14,16 @@ namespace BizHawk.Emulation.Cores.Computers.MSX { "Reset", "P1 Up", "P1 Down", "P1 Left", "P1 Right", "P1 B1", "P1 B2", - "P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 B1", "P2 B2" + "P2 Up", "P2 Down", "P2 Left", "P2 Right", "P2 B1", "P2 B2", + "7", "6", "5", "4", "3", "2", "1", "0", + ";", "[", "@", "$", "^", "-", "9", "8", + "B", "A", "/", ".", ",", "]", ":", + "J", "I", "H", "G", "F", "E", "D", "C", + "R", "Q", "P", "O", "N", "M", "L", "K", + "Z", "Y", "X", "W", "V", "U", "T", "S", + "F3", "F2", "F1", "KANA", "CAP", "GRAPH", "CTRL", "SHIFT", + "RET", "SEL", "BACK", "STOP", "TAB", "ESC", "F5", "F4", + "RIGHT", "DOWN", "UP", "LEFT", "DEL", "INS", "HOME", "SPACE" } }; } diff --git a/libHawk/MSXHawk/MSXHawk/Core.h b/libHawk/MSXHawk/MSXHawk/Core.h index 669708b0cc..36afb5bda0 100644 --- a/libHawk/MSXHawk/MSXHawk/Core.h +++ b/libHawk/MSXHawk/MSXHawk/Core.h @@ -39,7 +39,7 @@ namespace MSXHawk MemMap.Load_ROM(ext_rom_1, ext_rom_size_1, ext_rom_mapper_1, ext_rom_2, ext_rom_size_2, ext_rom_mapper_2); } - bool FrameAdvance(uint8_t controller_1, uint8_t controller_2, bool render, bool rendersound) + bool FrameAdvance(uint8_t controller_1, uint8_t controller_2, uint8_t* kb_rows_ptr, bool render, bool rendersound) { if ((MemMap.psg_pntr->Register[0xF] & 0x40) > 0) { @@ -52,6 +52,7 @@ namespace MSXHawk MemMap.controller_byte_1 = controller_1; MemMap.controller_byte_2 = controller_2; + MemMap.kb_rows = kb_rows_ptr; MemMap.start_pressed = (controller_1 & 0x80) > 0; MemMap.lagged = true; @@ -91,7 +92,8 @@ namespace MSXHawk return MemMap.lagged; } - void GetVideo(uint32_t* dest) { + void GetVideo(uint32_t* dest) + { uint32_t* src = vdp.FrameBuffer; uint32_t* dst = dest; @@ -145,6 +147,11 @@ namespace MSXHawk return vdp.VRAM[addr & 0x3FFF]; } + uint8_t GetRAM(uint32_t addr) + { + return MemMap.ram[addr & 0xFFFF]; + } + #pragma endregion #pragma region Tracer diff --git a/libHawk/MSXHawk/MSXHawk/MSXHawk.cpp b/libHawk/MSXHawk/MSXHawk/MSXHawk.cpp index 528b44c032..34c6809a5b 100644 --- a/libHawk/MSXHawk/MSXHawk/MSXHawk.cpp +++ b/libHawk/MSXHawk/MSXHawk/MSXHawk.cpp @@ -41,10 +41,9 @@ MSXHawk_EXPORT void MSX_load(MSXCore* p, uint8_t* rom_1, uint32_t size_1, uint32 } // advance a frame -MSXHawk_EXPORT bool MSX_frame_advance(MSXCore* p, uint8_t ctrl1, uint8_t ctrl2, bool render, bool sound) +MSXHawk_EXPORT bool MSX_frame_advance(MSXCore* p, uint8_t ctrl1, uint8_t ctrl2, uint8_t* kbrows, bool render, bool sound) { - p->FrameAdvance(ctrl1, ctrl2, render, sound); - return p->vdp.EnableInterrupts(); + return p->FrameAdvance(ctrl1, ctrl2, kbrows, render, sound); } // send video data to external video provider @@ -84,6 +83,11 @@ MSXHawk_EXPORT uint8_t MSX_getsysbus(MSXCore* p, uint32_t addr) { MSXHawk_EXPORT uint8_t MSX_getvram(MSXCore* p, uint32_t addr) { return p->GetVRAM(addr); } + +MSXHawk_EXPORT uint8_t MSX_getram(MSXCore* p, uint32_t addr) { + return p->GetRAM(addr); +} + #pragma endregion diff --git a/libHawk/MSXHawk/MSXHawk/Memory.cpp b/libHawk/MSXHawk/MSXHawk/Memory.cpp index ec89c9e5b3..62b67c3dd2 100644 --- a/libHawk/MSXHawk/MSXHawk/Memory.cpp +++ b/libHawk/MSXHawk/MSXHawk/Memory.cpp @@ -26,6 +26,7 @@ namespace MSXHawk } else if (port == 0xA2) { + if (psg_pntr->port_sel == 0xE) { lagged = false; } return psg_pntr->ReadReg(); } else if (port == 0xA8) @@ -34,7 +35,13 @@ namespace MSXHawk } else if (port == 0xA9) { - return 0xFF; + lagged = false; + return ~kb_rows[kb_rows_sel]; + } + else if (port == 0xAA) + { + // TODO: casette, caps lamp, keyboard sound click + return kb_rows_sel; } return 0xFF; @@ -78,6 +85,11 @@ namespace MSXHawk PortA8 = value; remap(); } + else if (port == 0xAA) + { + kb_rows_sel = value & 0xF; + remap(); + } } void MemoryManager::remap() diff --git a/libHawk/MSXHawk/MSXHawk/Memory.h b/libHawk/MSXHawk/MSXHawk/Memory.h index d9c60d36e4..c3d864b04e 100644 --- a/libHawk/MSXHawk/MSXHawk/Memory.h +++ b/libHawk/MSXHawk/MSXHawk/Memory.h @@ -29,12 +29,16 @@ namespace MSXHawk uint32_t rom_size_2; uint32_t rom_mapper_2; + // controls are not stated + uint8_t controller_byte_1, controller_byte_2; + uint8_t* kb_rows; + // State bool PortDEEnabled = false; bool lagged; bool start_pressed; - uint8_t controller_byte_1, controller_byte_2; + uint8_t kb_rows_sel; uint8_t PortA8 = 0x00; uint8_t reg_FFFC, reg_FFFD, reg_FFFE, reg_FFFF; uint8_t ram[0x10000] = {}; @@ -87,40 +91,6 @@ namespace MSXHawk } - uint8_t ReadPort0() - { - lagged = false; - - uint8_t value = 0xFF; - if (start_pressed) - { - value ^= 0x80; - } - - return value; - } - - uint8_t ReadControls1() - { - lagged = false; - uint8_t value = 0xFF; - - value &= ~(controller_byte_1 & 0x3F); - value &= ~(controller_byte_2 & 0xC0); - - return value; - } - - uint8_t ReadControls2() - { - lagged = false; - uint8_t value = 0xFF; - - value &= ~(controller_byte_2 & 0xF); - - return value; - } - #pragma region State Save / Load uint8_t* SaveState(uint8_t* saver) @@ -129,8 +99,7 @@ namespace MSXHawk *saver = (uint8_t)(lagged ? 1 : 0); saver++; *saver = (uint8_t)(start_pressed ? 1 : 0); saver++; - *saver = controller_byte_1; saver++; - *saver = controller_byte_2; saver++; + *saver = kb_rows_sel; saver++; *saver = PortA8; saver++; *saver = reg_FFFC; saver++; *saver = reg_FFFD; saver++; @@ -149,8 +118,7 @@ namespace MSXHawk lagged = *loader == 1; loader++; start_pressed = *loader == 1; loader++; - controller_byte_1 = *loader; loader++; - controller_byte_2 = *loader; loader++; + kb_rows_sel = *loader; loader++; PortA8 = *loader; loader++; reg_FFFC = *loader; loader++; reg_FFFD = *loader; loader++; diff --git a/libHawk/MSXHawk/MSXHawk/TMS9918A.h b/libHawk/MSXHawk/MSXHawk/TMS9918A.h index 298a0c4428..c31b76be4a 100644 --- a/libHawk/MSXHawk/MSXHawk/TMS9918A.h +++ b/libHawk/MSXHawk/MSXHawk/TMS9918A.h @@ -32,12 +32,12 @@ namespace MSXHawk uint8_t StatusByte; uint8_t VdpLatch; uint8_t VdpBuffer; + uint8_t TmsMode; uint8_t Registers[8] = {}; uint8_t VRAM[0x4000]; //16kb video RAM int32_t ScanLine; uint32_t VdpAddress; - uint32_t TmsMode; uint32_t ColorTableBase; uint32_t PatternGeneratorBase; uint32_t SpritePatternGeneratorBase; @@ -373,7 +373,7 @@ namespace MSXHawk } } - void RenderTmsSprites(int32_t scanLine) + inline void RenderTmsSprites(int32_t scanLine) { if (EnableDoubledSprites() == false) { @@ -537,6 +537,7 @@ namespace MSXHawk *saver = StatusByte; saver++; *saver = VdpLatch; saver++; *saver = VdpBuffer; saver++; + *saver = TmsMode; saver++; std::memcpy(saver, &Registers, 8); saver += 8; std::memcpy(saver, &VRAM, 0x4000); saver += 0x4000; @@ -547,9 +548,6 @@ namespace MSXHawk *saver = (uint8_t)(VdpAddress & 0xFF); saver++; *saver = (uint8_t)((VdpAddress >> 8) & 0xFF); saver++; *saver = (uint8_t)((VdpAddress >> 16) & 0xFF); saver++; *saver = (uint8_t)((VdpAddress >> 24) & 0xFF); saver++; - *saver = (uint8_t)(TmsMode & 0xFF); saver++; *saver = (uint8_t)((TmsMode >> 8) & 0xFF); saver++; - *saver = (uint8_t)((TmsMode >> 16) & 0xFF); saver++; *saver = (uint8_t)((TmsMode >> 24) & 0xFF); saver++; - *saver = (uint8_t)(ColorTableBase & 0xFF); saver++; *saver = (uint8_t)((ColorTableBase >> 8) & 0xFF); saver++; *saver = (uint8_t)((ColorTableBase >> 16) & 0xFF); saver++; *saver = (uint8_t)((ColorTableBase >> 24) & 0xFF); saver++; @@ -578,6 +576,7 @@ namespace MSXHawk StatusByte = *loader; loader++; VdpLatch = *loader; loader++; VdpBuffer = *loader; loader++; + TmsMode = *loader; loader++; std::memcpy(&Registers, loader, 8); loader += 8; std::memcpy(&VRAM, loader, 0x4000); loader += 0x4000; @@ -588,9 +587,6 @@ namespace MSXHawk VdpAddress = *loader; loader++; VdpAddress |= (*loader << 8); loader++; VdpAddress |= (*loader << 16); loader++; VdpAddress |= (*loader << 24); loader++; - TmsMode = *loader; loader++; TmsMode |= (*loader << 8); loader++; - TmsMode |= (*loader << 16); loader++; TmsMode |= (*loader << 24); loader++; - ColorTableBase = *loader; loader++; ColorTableBase |= (*loader << 8); loader++; ColorTableBase |= (*loader << 16); loader++; ColorTableBase |= (*loader << 24); loader++;