diff --git a/core/hw/maple/maple_jvs.cpp b/core/hw/maple/maple_jvs.cpp index 477136bd9..7f18edbb5 100644 --- a/core/hw/maple/maple_jvs.cpp +++ b/core/hw/maple/maple_jvs.cpp @@ -135,7 +135,6 @@ const char *GetCurrentGameAxisName(DreamcastKey axis) * Sega JVS I/O board */ static bool old_coin_chute[4]; -static int coin_count[4]; class jvs_io_board { @@ -153,6 +152,10 @@ public: virtual void serialize(Serializer& ser) const; virtual void deserialize(Deserializer& deser); + u32 getDigitalOutput() const { + return digOutput; + } + bool lightgun_as_analog = false; protected: @@ -258,6 +261,7 @@ protected: u32 light_gun_count = 0; u32 output_count = 0; bool init_in_progress = false; + maple_naomi_jamma *parent; private: void init_mappings() @@ -289,13 +293,13 @@ private: } u8 node_id; - maple_naomi_jamma *parent; u8 first_player; std::array cur_mapping; std::array p1_mapping; std::array p2_mapping; u32 digOutput = 0; + int coin_count[4] {}; }; // Most common JVS board @@ -445,6 +449,52 @@ protected: float rotY = 0.f; }; +class jvs_837_13938_crackindj : public jvs_837_13938 +{ +public: + jvs_837_13938_crackindj(u8 node_id, maple_naomi_jamma *parent, int first_player = 0) + : jvs_837_13938(node_id, parent, first_player) + {} + + void serialize(Serializer& ser) const override + { + jvs_837_13938::serialize(ser); + ser << motorRotation; + } + void deserialize(Deserializer& deser) override + { + jvs_837_13938::deserialize(deser); + if (deser.version() >= Deserializer::V46) + deser >> motorRotation; + } + +protected: + s16 readRotaryEncoders(int channel, s16 relX, s16 relY) override + { + jvs_io_board& outputBoard = *parent->io_boards[1]; + bool turntableOn = outputBoard.getDigitalOutput() & 0x10; + switch (channel) + { + case 0: // Left turntable + if (turntableOn && relX == lastRel[0]) + motorRotation[0] -= 10; + lastRel[0] = relX; + return -relX + motorRotation[0]; + case 2: // Right turntable + if (turntableOn && relY == lastRel[1]) + motorRotation[1] -= 10; + lastRel[1] = relY; + return relY + motorRotation[1]; + default: + return 0; + } + } + +private: + s16 motorRotation[2]{}; + s16 lastRel[2]{}; +}; + // Sega Marine Fishing, 18 Wheeler (TODO) class jvs_837_13844 : public jvs_io_board { @@ -998,10 +1048,8 @@ maple_naomi_jamma::maple_naomi_jamma() settings.input.fourPlayerGames = true; } else if (gameId == "DYNAMIC GOLF" - || gameId == "SHOOTOUT POOL" - || gameId == "SHOOTOUT POOL MEDAL" - || gameId == "CRACKIN'DJ ver JAPAN" - || gameId == "CRACKIN'DJ PART2 ver JAPAN" + || gameId.substr(0, 13) == "SHOOTOUT POOL" + || gameId.substr(0, 10) == "CRACKIN'DJ" || gameId == "KICK '4' CASH") { // Rotary encoders @@ -1010,6 +1058,8 @@ maple_naomi_jamma::maple_naomi_jamma() io_boards.push_back(std::make_unique(1, this)); else if (gameId == "KICK '4' CASH") io_boards.push_back(std::make_unique(1, this)); + else if (gameId.substr(0, 10) == "CRACKIN'DJ") + io_boards.push_back(std::make_unique(1, this)); else io_boards.push_back(std::make_unique(1, this)); io_boards.push_back(std::make_unique(2, this)); @@ -1984,15 +2034,15 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou { coin_chute = true; if (!old_coin_chute[first_player + slot]) - coin_count[first_player + slot] += 1; + coin_count[slot] += 1; } old_coin_chute[first_player + slot] = coin_chute; LOGJVS("%d:%d ", slot + 1 + first_player, coin_count[first_player + slot]); // status (2 highest bits, 0: normal), coin count MSB - JVS_OUT((coin_count[first_player + slot] >> 8) & 0x3F); + JVS_OUT((coin_count[slot] >> 8) & 0x3F); // coin count LSB - JVS_OUT(coin_count[first_player + slot]); + JVS_OUT(coin_count[slot]); } cmdi += 2; } @@ -2141,8 +2191,8 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou break; case 0x30: // substract coin - if (buffer_in[cmdi + 1] > 0 && first_player + buffer_in[cmdi + 1] - 1 < (int)std::size(coin_count)) - coin_count[first_player + buffer_in[cmdi + 1] - 1] -= (buffer_in[cmdi + 2] << 8) + buffer_in[cmdi + 3]; + if (buffer_in[cmdi + 1] > 0 && buffer_in[cmdi + 1] - 1 < (int)std::size(coin_count)) + coin_count[buffer_in[cmdi + 1] - 1] -= (buffer_in[cmdi + 2] << 8) + buffer_in[cmdi + 3]; JVS_STATUS1(); // report byte cmdi += 4; break; @@ -2197,9 +2247,14 @@ void jvs_io_board::serialize(Serializer& ser) const { ser << node_id; ser << lightgun_as_analog; + ser << coin_count; } void jvs_io_board::deserialize(Deserializer& deser) { deser >> node_id; deser >> lightgun_as_analog; + if (deser.version() >= Deserializer::V46) + deser >> coin_count; + else + memset(coin_count, 0, sizeof(coin_count)); } diff --git a/core/hw/naomi/naomi_roms.cpp b/core/hw/naomi/naomi_roms.cpp index bd8d53d38..8c5fd0419 100644 --- a/core/hw/naomi/naomi_roms.cpp +++ b/core/hw/naomi/naomi_roms.cpp @@ -1108,11 +1108,11 @@ const Game Games[] = // Crackin' DJ { "crackndj", - NULL, + nullptr, "Crackin' DJ", 0x0a800000, 0x281c2347, - NULL, + nullptr, M2, ROT0, { @@ -1127,17 +1127,19 @@ const Game Games[] = { "mpr-23532.ic8", 0x7800000, 0x1000000 }, { "mpr-23533.ic9", 0x8800000, 0x1000000 }, { "mpr-23534.ic10", 0x9800000, 0x1000000 }, - { NULL, 0, 0 }, - } + }, + nullptr, + &crackindj_inputs, + crackndj_eeprom_dump, }, // Crackin' DJ Part 2 (Japan) { "crakndj2", - NULL, + nullptr, "Crackin' DJ Part 2", 0x0a800000, 0x28428247, - NULL, + nullptr, M2, ROT0, { @@ -1165,9 +1167,10 @@ const Game Games[] = //ROM_REGION(0x84, "some_eeprom", 0) //ROM_LOAD("sflash.ic37", 0x000000, 0x000084, CRC(08f27149) SHA1(3b8d53dcf2c09035b318022906c444cf8504d7fa) ) - - { NULL, 0, 0 }, - } + }, + nullptr, + &crackindj_inputs, + crakndj2_eeprom_dump, }, // Crazy Taxi { diff --git a/core/hw/naomi/naomi_roms_eeprom.h b/core/hw/naomi/naomi_roms_eeprom.h index 5882c1e2e..2f6c304c5 100644 --- a/core/hw/naomi/naomi_roms_eeprom.h +++ b/core/hw/naomi/naomi_roms_eeprom.h @@ -660,3 +660,28 @@ static u8 manicpnc_eeprom_dump[128] = { 0x22, 0x11, 0x10, 0x42, 0x4d, 0x4b, 0x30, 0x09, 0x10, 0x00, 0x01, 0x01, 0x01, 0x00, 0x12, 0x12, 0x11, 0x11, 0x22, 0x11, 0x10, 0x42, 0x4d, 0x4b, 0x30, 0x09, 0x10, 0x00, 0x01, 0x01, 0x01, 0x00, 0x12, 0x12, 0x11, 0x11, }; + +// calibration done +static u8 crackndj_eeprom_dump[] = { + 0x4e, 0x8b, 0x10, 0x42, 0x43, 0x47, 0x30, 0x09, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x4e, 0x8b, 0x10, 0x42, 0x43, 0x47, 0x30, 0x09, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x5d, 0x2c, 0x24, 0x24, 0x5d, 0x2c, 0x24, 0x24, 0x00, 0x47, 0x43, 0x42, 0x43, 0x52, 0x41, 0x43, 0x4b, 0x49, + 0x4e, 0x44, 0x4a, 0x20, 0x41, 0x4d, 0x33, 0x03, 0x00, 0x00, 0xfe, 0x00, 0x07, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x20, 0x41, 0x00, 0x47, 0x43, 0x42, 0x43, 0x52, 0x41, 0x43, 0x4b, 0x49, + 0x4e, 0x44, 0x4a, 0x20, 0x41, 0x4d, 0x33, 0x03, 0x00, 0x00, 0xfe, 0x00, 0x07, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + +// calibration done +static u8 crakndj2_eeprom_dump[] = { + 0xa1, 0xab, 0x10, 0x42, 0x44, 0x4b, 0x30, 0x09, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x11, 0x11, 0x11, 0x11, + 0xa1, 0xab, 0x10, 0x42, 0x44, 0x4b, 0x30, 0x09, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x11, 0x11, 0x11, 0x11, + 0xb4, 0xdd, 0x24, 0x24, 0xb4, 0xdd, 0x24, 0x24, 0x00, 0x4b, 0x44, 0x42, 0x43, 0x52, 0x41, 0x43, 0x4b, 0x49, + 0x4e, 0x44, 0x4a, 0x20, 0x41, 0x4d, 0x33, 0x03, 0x00, 0x00, 0xfe, 0x00, 0x07, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x20, 0x41, 0x00, 0x4b, 0x44, 0x42, 0x43, 0x52, 0x41, 0x43, 0x4b, 0x49, + 0x4e, 0x44, 0x4a, 0x20, 0x41, 0x4d, 0x33, 0x03, 0x00, 0x00, 0xfe, 0x00, 0x07, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + diff --git a/core/hw/naomi/naomi_roms_input.h b/core/hw/naomi/naomi_roms_input.h index 1f64075e8..55c4640c6 100644 --- a/core/hw/naomi/naomi_roms_input.h +++ b/core/hw/naomi/naomi_roms_input.h @@ -717,3 +717,13 @@ static InputDescriptors drvsim_inputs = { { "Clutch", Full, 1 }, }, }; + +static InputDescriptors crackindj_inputs = { + { + NAO_START_DESC + NAO_BASE_BTN_DESC + }, + { + { "FADER", Full, 0, true }, + }, +};