diff --git a/core/hw/naomi/netdimm.h b/core/hw/naomi/netdimm.h index fd7b26385..c0329a7c4 100644 --- a/core/hw/naomi/netdimm.h +++ b/core/hw/naomi/netdimm.h @@ -166,5 +166,4 @@ private: u32 dimmBufferOffset = 0x0f000000; static constexpr int POLL_CYCLES = SH4_MAIN_CLOCK / 60; - static NetDimm *Instance; }; diff --git a/core/hw/naomi/systemsp.cpp b/core/hw/naomi/systemsp.cpp index 4ac2bd832..e2840dd60 100644 --- a/core/hw/naomi/systemsp.cpp +++ b/core/hw/naomi/systemsp.cpp @@ -651,7 +651,7 @@ private: } else { - bool button = (input[0].kcode & DC_BTN_B) == 0; // FIXME use button A instead + bool button = (input[0].kcode & DC_BTN_A) == 0; if (button != lastButton || x != lastPosX || y != lastPosY) { // bit 6 is touch down @@ -810,6 +810,169 @@ void SerialPort::updateStatus() cart->updateInterrupt(index == 1 ? SystemSpCart::INT_UART1 : SystemSpCart::INT_UART2); } +class DefaultInPortManager : public InPortManager +{ +public: + // IN_PORT0 + u8 getCN9_17_24() override + { + MapleInputState mapleInputState[4]; + ggpo::getInput(mapleInputState); + + u8 v = 0xff; + // 0: P1 start + // 1: P2 start + // 2: P1 right + // 3: P2 right + // 4: P1 left + // 5: P2 left + // 6: P1 up + // 7: P2 up + if (!(mapleInputState[0].kcode & DC_BTN_START)) + v &= ~0x01; + if (!(mapleInputState[1].kcode & DC_BTN_START)) + v &= ~0x02; + if (!(mapleInputState[0].kcode & DC_DPAD_RIGHT)) + v &= ~0x04; + if (!(mapleInputState[1].kcode & DC_DPAD_RIGHT)) + v &= ~0x08; + if (!(mapleInputState[0].kcode & DC_DPAD_LEFT)) + v &= ~0x10; + if (!(mapleInputState[1].kcode & DC_DPAD_LEFT)) + v &= ~0x20; + if (!(mapleInputState[0].kcode & DC_DPAD_UP)) + v &= ~0x40; + if (!(mapleInputState[1].kcode & DC_DPAD_UP)) + v &= ~0x80; + IO_LOG("systemsp::read IN_PORT0 %x", v); + return v; + } + + // IN_PORT3 + u8 getCN9_25_32() override + { + u8 v = 0xff; + // 0: P1 down + // 1: P2 down + // 2: P1 button 1 + // 3: P2 button 1 + // 4: P1 button 2 + // 5: P2 button 2 + // 6: P1 button 3 + // 7: P2 button 3 + MapleInputState mapleInputState[4]; + ggpo::getInput(mapleInputState); + if (!(mapleInputState[0].kcode & DC_DPAD_DOWN)) + v &= ~0x01; + if (!(mapleInputState[1].kcode & DC_DPAD_DOWN)) + v &= ~0x02; + if (!(mapleInputState[0].kcode & DC_BTN_A)) + v &= ~0x04; + if (!(mapleInputState[1].kcode & DC_BTN_A)) + v &= ~0x08; + if (!(mapleInputState[0].kcode & DC_BTN_B)) + v &= ~0x10; + if (!(mapleInputState[1].kcode & DC_BTN_B)) + v &= ~0x20; + if (!(mapleInputState[0].kcode & DC_BTN_C)) + v &= ~0x40; + if (!(mapleInputState[1].kcode & DC_BTN_C)) + v &= ~0x80; + IO_LOG("systemsp::read IN_PORT3 %x", v); + return v; + } + + u8 getCN9_33_40() override + { + IO_LOG("systemsp::read IN CN9 33-40"); + return 0xff; + } + + // IN_PORT1 + u8 getCN9_41_48() override + { + u8 v = 0xff; + // 0: P1 service + // 2: P1 test + // 4: P1 coin + // 5: P2 coin + MapleInputState mapleInputState[4]; + ggpo::getInput(mapleInputState); + if (!(mapleInputState[0].kcode & DC_DPAD2_UP)) // service + v &= ~0x01; + if (!(mapleInputState[0].kcode & DC_DPAD2_DOWN)) // test + v &= ~0x04; + if (!(mapleInputState[0].kcode & DC_BTN_D)) // coin + v &= ~0x10; + if (!(mapleInputState[1].kcode & DC_BTN_D)) + v &= ~0x20; + IO_LOG("systemsp::read IN_PORT1 %x", v); + return v; + } + + // IN_PORT4 + u8 getCN9_49_56() override + { + u8 v = 0; + // FIXME these are outputs?? + // 0: P1 coin meter + // 1: P2 coin meter + MapleInputState mapleInputState[4]; + ggpo::getInput(mapleInputState); + if (!(mapleInputState[0].kcode & DC_BTN_D)) // coin + v |= 1; + if (!(mapleInputState[1].kcode & DC_BTN_D)) + v |= 2; + IO_LOG("systemsp::read IN_PORT4 %x", v); + return v; + } +}; + +class CardReaderInPortManager : public DefaultInPortManager +{ +public: + u8 getCN9_17_24() override + { + MapleInputState mapleInputState[4]; + ggpo::getInput(mapleInputState); + for (size_t i = 0; i < 2; i++) + { + if ((mapleInputState[i].kcode & DC_BTN_INSERT_CARD) == 0 + && (last_kcode[i] & DC_BTN_INSERT_CARD) != 0) + card_reader::insertCard(i); + last_kcode[i] = mapleInputState[i].kcode; + } + return DefaultInPortManager::getCN9_17_24(); + } + + virtual u8 getCN9_33_40() + { + IO_LOG("systemsp::read IN CN9 33-40"); + // dinosaur king, love & berry: + // 0: P1 card set (not used) + // 2: CD1 input ok (active low) + // 4: CD1 card jam (active low) + // 6: CD1 empty (active low) + return 0xfb; + } + +private: + u32 last_kcode[2] = {}; +}; + +class IsshoniInPortManager : public CardReaderInPortManager +{ +public: + u8 getCN9_17_24() override { + CardReaderInPortManager::getCN9_17_24(); + return 0xff; + } + + u8 getCN9_25_32() override { + return 0xff; + } +}; + template T readMemArea0(u32 addr) { @@ -992,118 +1155,20 @@ T SystemSpCart::readMemArea0(u32 addr) switch (addr - 0x10100) { case 0x0: // IN_PORT0 (CN9 17-24) - { - MapleInputState mapleInputState[4]; - ggpo::getInput(mapleInputState); - for (size_t i = 0; i < 2; i++) - { - if ((mapleInputState[i].kcode & DC_BTN_INSERT_CARD) == 0 - && (last_kcode[i] & DC_BTN_INSERT_CARD) != 0) - card_reader::insertCard(i); - last_kcode[i] = mapleInputState[i].kcode; - } - u8 v = 0xff; - // 0: P1 start - // 1: P2 start - // 2: P1 right - // 3: P2 right - // 4: P1 left - // 5: P2 left - // 6: P1 up - // 7: P2 up - if (!(mapleInputState[0].kcode & DC_BTN_START)) - v &= ~0x01; - if (!(mapleInputState[1].kcode & DC_BTN_START)) - v &= ~0x02; - if (!(mapleInputState[0].kcode & DC_DPAD_RIGHT)) - v &= ~0x04; - if (!(mapleInputState[1].kcode & DC_DPAD_RIGHT)) - v &= ~0x08; - if (!(mapleInputState[0].kcode & DC_DPAD_LEFT)) - v &= ~0x10; - if (!(mapleInputState[1].kcode & DC_DPAD_LEFT)) - v &= ~0x20; - if (!(mapleInputState[0].kcode & DC_DPAD_UP)) - v &= ~0x40; - if (!(mapleInputState[1].kcode & DC_DPAD_UP)) - v &= ~0x80; - IO_LOG("systemsp::read(%x) IN_PORT0 %x", addr, v); - return v; - } + return inPortManager->getCN9_17_24(); + case 0x4: // IN_PORT1 (CN9 41-48) - { - u8 v = 0xff; - // 0: P1 service - // 2: P1 test - // 4: P1 coin - // 5: P2 coin - MapleInputState mapleInputState[4]; - ggpo::getInput(mapleInputState); - if (!(mapleInputState[0].kcode & DC_DPAD2_UP)) // service - v &= ~0x01; - if (!(mapleInputState[0].kcode & DC_DPAD2_DOWN)) // test - v &= ~0x04; - if (!(mapleInputState[0].kcode & DC_BTN_D)) // coin - v &= ~0x10; - if (!(mapleInputState[1].kcode & DC_BTN_D)) - v &= ~0x20; - IO_LOG("systemsp::read(%x) IN_PORT1 %x", addr, v); - return v; - } + return inPortManager->getCN9_41_48(); + case 0x8: // IN_PORT3 (CN9 25-32) - { - u8 v = 0xff; - // 0: P1 down - // 1: P2 down - // 2: P1 button 1 - // 3: P2 button 1 - // 4: P1 button 2 - // 5: P2 button 2 - // 6: P1 button 3 - // 7: P2 button 3 - MapleInputState mapleInputState[4]; - ggpo::getInput(mapleInputState); - if (!(mapleInputState[0].kcode & DC_DPAD_DOWN)) - v &= ~0x01; - if (!(mapleInputState[1].kcode & DC_DPAD_DOWN)) - v &= ~0x02; - if (!(mapleInputState[0].kcode & DC_BTN_A)) - v &= ~0x04; - if (!(mapleInputState[1].kcode & DC_BTN_A)) - v &= ~0x08; - if (!(mapleInputState[0].kcode & DC_BTN_B)) - v &= ~0x10; - if (!(mapleInputState[1].kcode & DC_BTN_B)) - v &= ~0x20; - if (!(mapleInputState[0].kcode & DC_BTN_C)) - v &= ~0x40; - if (!(mapleInputState[1].kcode & DC_BTN_C)) - v &= ~0x80; - IO_LOG("systemsp::read(%x) IN_PORT3 %x", addr, v); - return v; - } + return inPortManager->getCN9_25_32(); + case 0xc: // IN CN9 33-40 - IO_LOG("systemsp::read(%x) IN CN9 33-40", addr); - // dinosaur king, love & berry: - // 0: P1 card set (not used) - // 2: CD1 input ok (active low) - // 4: CD1 card jam (active low) - // 6: CD1 empty (active low) - return 0xfb; + return inPortManager->getCN9_33_40(); + case 0x10: // IN_PORT4 (CN9 49-56) - { - u8 v = 0; - // 0: P1 coin meter - // 1: P2 coin meter - MapleInputState mapleInputState[4]; - ggpo::getInput(mapleInputState); - if (!(mapleInputState[0].kcode & DC_BTN_D)) // coin - v |= 1; - if (!(mapleInputState[1].kcode & DC_BTN_D)) - v |= 2; - IO_LOG("systemsp::read(%x) IN_PORT4 %x", addr, v); - return v; - } + return inPortManager->getCN9_49_56(); + case 0x18: // IN_PORT2 (DIP switches and jumpers, and P1 service for older pcb rev) { // DIP switches @@ -1735,7 +1800,12 @@ void SystemSpCart::Init(LoadProgress *progress, std::vector *digest) else if (!strcmp(game->name, "isshoni")) { new Touchscreen(&uart1); + inPortManager = std::make_unique(); } + if (!strncmp(game->name, "dinoki", 6) || !strncmp(game->name, "loveber", 7)) + inPortManager = std::make_unique(); + if (!inPortManager) + inPortManager = std::make_unique(); EventManager::listen(Event::Pause, handleEvent, this); } diff --git a/core/hw/naomi/systemsp.h b/core/hw/naomi/systemsp.h index 76ea664b1..a23ee5191 100644 --- a/core/hw/naomi/systemsp.h +++ b/core/hw/naomi/systemsp.h @@ -132,6 +132,17 @@ union AtaDevCtrlRegister }; }; +class InPortManager +{ +public: + virtual u8 getCN9_17_24() = 0; + virtual u8 getCN9_25_32() = 0; + virtual u8 getCN9_33_40() = 0; + virtual u8 getCN9_41_48() = 0; + virtual u8 getCN9_49_56() = 0; + virtual ~InPortManager() = default; +}; + class SystemSpCart : public M4Cartridge { public: @@ -197,7 +208,7 @@ private: SerialPort uart2; u16 bank = 0; int region = 0; - u32 last_kcode[2] = {}; + std::unique_ptr inPortManager; static constexpr u32 SECTOR_SIZE = 512; diff --git a/shell/libretro/libretro.cpp b/shell/libretro/libretro.cpp index 963b6343e..00c21eb1c 100644 --- a/shell/libretro/libretro.cpp +++ b/shell/libretro/libretro.cpp @@ -1311,6 +1311,26 @@ static uint32_t map_gamepad_button(unsigned device, unsigned id) /* LIGHTGUN_RIGHT */ NAOMI_RIGHT_KEY, }; + static const uint32_t systemsp_joymap[] = + { + /* JOYPAD_B */ DC_BTN_A, + /* JOYPAD_Y */ DC_BTN_C, + /* JOYPAD_SELECT */ DC_BTN_D, // coin + /* JOYPAD_START */ DC_BTN_START, + /* JOYPAD_UP */ DC_DPAD_UP, + /* JOYPAD_DOWN */ DC_DPAD_DOWN, + /* JOYPAD_LEFT */ DC_DPAD_LEFT, + /* JOYPAD_RIGHT */ DC_DPAD_RIGHT, + /* JOYPAD_A */ DC_BTN_B, + /* JOYPAD_X */ 0, + /* JOYPAD_L */ 0, + /* JOYPAD_R */ 0, + /* JOYPAD_L2 */ 0, + /* JOYPAD_R2 */ 0, + /* JOYPAD_L3 */ DC_DPAD2_DOWN, // test + /* JOYPAD_R3 */ DC_DPAD2_UP, // service + }; + const uint32_t *joymap; size_t joymap_size; @@ -1369,6 +1389,11 @@ static uint32_t map_gamepad_button(unsigned device, unsigned id) } break; + case DC_PLATFORM_SYSTEMSP: + joymap = systemsp_joymap; + joymap_size = std::size(systemsp_joymap); + break; + default: return 0; }