jvs: fix crackin'dj inputs. serialize coin count

crackin'dj: map vertical mouse axis to right turntable. Invert fader.
Simulate turntable motor. Embed eeproms with calibration done.
Fix coin being inserted after loading a savestate.
This commit is contained in:
Flyinghead 2024-01-24 19:39:20 +01:00
parent cbd01fba38
commit 10d3ffdf09
4 changed files with 113 additions and 20 deletions

View File

@ -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<u32, 32> cur_mapping;
std::array<u32, 32> p1_mapping;
std::array<u32, 32> 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<jvs_837_13938_shootout>(1, this));
else if (gameId == "KICK '4' CASH")
io_boards.push_back(std::make_unique<jvs_837_13938_kick4cash>(1, this));
else if (gameId.substr(0, 10) == "CRACKIN'DJ")
io_boards.push_back(std::make_unique<jvs_837_13938_crackindj>(1, this));
else
io_boards.push_back(std::make_unique<jvs_837_13938>(1, this));
io_boards.push_back(std::make_unique<jvs_837_13551>(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));
}

View File

@ -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
{

View File

@ -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
};

View File

@ -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 },
},
};