machine/micomxe1a.cpp: Fudged timings to work with buggy CRI games.

CSK Research Institute games on FM Towns don't follow the same sequence
as other games when reading inputs.  They depend on the data lines not
being updated for some time after /Ack goes high, and can miss
transitions if the timing is too tight (ironic that 16MHz '386 software
has these issues when the 7MHz 6502 in the PC Engine gets by fine).
This fudges the timings to work with the these buggy games without
breaking the other use cases.

Also for some reason, these games expect an XE-1AP in MD mode with a
Sega controller adapter - they won't work wth an XE-1AP in Personal
Computer mode, and they won't work with the XE-1AJ or its NEC-branded
relative.  In MAME you can flip the Interface setting to MD in the
Machine Configuration options without needing to use an adapter device.
This commit is contained in:
Vas Crabb 2022-12-19 05:57:34 +11:00
parent 742ef9cdd6
commit 03b85db840
3 changed files with 42 additions and 49 deletions

View file

@ -2092,7 +2092,7 @@ User/save disks that can be created from the game itself are not included.
<info name="serial" value="HMD-119 / T2061-206"/>
<info name="alt_title" value="アフターバーナーIII" />
<info name="release" value="199206xx" />
<info name="usage" value="Requires 2 MB RAM"/>
<info name="usage" value="Requires 2 MB RAM. Supports XE-1AP analog pad in analog MD mode on second controller port. Use a Towns Pad on first port to navigate menus." />
<part name="cdrom" interface="fmt_cdrom">
<diskarea name="cdrom">
<disk name="after burner iii (japan)" sha1="fe11d382c3efef8ed4a698f6a9832fb6bcd09167" />
@ -4549,7 +4549,7 @@ User/save disks that can be created from the game itself are not included.
<info name="serial" value="HMC-142"/>
<info name="alt_title" value="TAITO チェイスHQ" />
<info name="release" value="199108xx" />
<info name="usage" value="Requires 2 MB RAM"/>
<info name="usage" value="Requires 2 MB RAM. Supports analog joystick on second controller port (Personal Computer mode). Use a Towns Pad on first port to navigate menus." />
<part name="cdrom" interface="fmt_cdrom">
<diskarea name="cdrom">
<disk name="taito chase h.q. (japan)" sha1="8ec3b12763866865ace239e717297b2defcaba43" />
@ -9645,7 +9645,7 @@ User/save disks that can be created from the game itself are not included.
<info name="serial" value="HMB-168 / T2034-104"/>
<info name="alt_title" value="ギャラクシーフォースII" />
<info name="release" value="199103xx" />
<info name="usage" value="Requires 2 MB RAM"/>
<info name="usage" value="Requires 2 MB RAM. Supports XE-1AP analog pad in analog MD mode on second controller port. Use a Towns Pad on first port to navigate menus." />
<part name="cdrom" interface="fmt_cdrom">
<diskarea name="cdrom">
<disk name="galaxy force ii (japan)" sha1="90c869b43bc7f846251f35ef5e5b741f641c6184" />

View file

@ -779,6 +779,7 @@ Most info on release dates and Jpn titles come from the following (wonderful) re
<publisher>電波新聞社 (Dempa Shinbunsha)</publisher>
<info name="alt_title" value="アフターバーナーII" />
<info name="release" value="19890426" />
<info name="usage" value="Supports analog joystick." />
<part name="flop1" interface="floppy_5_25">
<feature name="part_id" value="Disk 1" />
<dataarea name="flop" size="1261824">
@ -13530,6 +13531,7 @@ Typing "CD PACMAN" and enter key, Typing "PAC" (or "PAC.BAT") and enter key. The
<publisher>Sharp</publisher>
<info name="alt_title" value="スーパーハングオン" />
<info name="release" value="19891225" />
<info name="usage" value="Supports analog joystick." />
<part name="flop1" interface="floppy_5_25">
<feature name="part_id" value="Disk A" />
<dataarea name="flop" size="1261824">

View file

@ -15,14 +15,14 @@
In analog mode, data is shifted out as eleven nybbles:
_ ____________________________________________
Req \_________/
____ __ __ __ __ __ __ __ __
Ack \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/
_____ _____ _____ _____
L/H XX\____/ \_____/ \_____/ \_____/ \_____/
____ _____ _____ _____ _____ _____ _____ _____ _____
D XXX____X_____X_____X_____X_____X_____X_____X_____X_____X
_ ____________________________________________
Req \_________/
____ __ __ __ __ __ __ __ __
Ack \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/
_____ _____ _____ _____
L/H XX\____/ \_____/ \_____/ \_____/ \_____/
____ _____ _____ _____ _____ _____ _____ _____ _____
D XXX____X_____X_____X_____X_____X_____X_____X_____X_____X
The falling edge on Req causes data output to start. The host
can't control the speed, it just polls the L/H and Ack lines to
@ -58,6 +58,10 @@
Start appears as simultaneous Left/Right
Select appears as simultaneous Up/Down
This mode is almost compatible with a 6-button Towns Pad (on a
real 6-button Towns Pad, buttons A and B can be read in either
state, they bypass the multiplexer).
Digital MD mode emulates a 3-button Mega Drive pad:
Req 0 1
@ -68,13 +72,10 @@
L/H A B
Ack Start C
This mode is almost compatible with a 6-button Towns Pad (on a
real 6-button Towns Pad, buttons A and B can be read in either
state, they bypass the multiplexer).
TODO:
* Dump MB88513 microcontroller from original controller.
* Measure timings.
- Timings currently fudged for CRI games in FM Towns.
* Latch data at beginning of packet.
* Confirm button mapping in digital mode.
* Estimate thresholds in digital modes.
@ -235,7 +236,7 @@ WRITE_LINE_MEMBER(micom_xe_1a_device::req_w)
m_data[5] = BIT(buttons, 8, 8) & ((BIT(buttons, 6, 2) << 2) | 0xf3);
// takes a while to respond
m_output_timer->adjust(attotime::from_nsec(46'600), 0);
m_output_timer->adjust(attotime::from_nsec(50), 0);
}
}
else
@ -293,47 +294,37 @@ void micom_xe_1a_device::device_start()
TIMER_CALLBACK_MEMBER(micom_xe_1a_device::step_output)
{
auto const step = param >> 2;
auto const phase = param & 0x03;
switch (phase)
auto const step = param >> 1;
if (!BIT(param, 0))
{
case 0:
m_out = (m_out & 0x0f) | (BIT(step, 0) ? 0x30 : 0x20);
LOG(
"Set nybble %u data = 0x%X, L/H = %u, /Ack = %u\n",
step,
BIT(m_out, 0, 4),
BIT(m_out, 4),
BIT(m_out, 5));
if ((std::size(m_data) * 2) > step)
{
m_output_timer->adjust(attotime::from_nsec(20'000), param + 1);
}
}
else
{
if ((std::size(m_data) * 2) > step)
{
auto const nybble = step ^ m_interface;
if ((std::size(m_data) * 2) > step)
m_out = BIT(m_data[nybble >> 1], BIT(nybble, 0) ? 4 : 0, 4);
m_out = BIT(m_data[nybble >> 1], BIT(nybble, 0) ? 4 : 0, 4) | (m_out & 0x10);
else
m_out = 0x0f;
m_out |= BIT(step, 0) ? 0x30 : 0x20;
m_out = 0x0f | (m_out & 0x10);
LOG(
"Set nybble %u data = 0x%X, L/H = %d, /Ack = 1\n",
"Set nybble %u data = 0x%X, L/H = %u, /Ack = %u\n",
step,
BIT(m_out, 0, 4),
BIT(m_out, 4));
if ((std::size(m_data) * 2) > step)
{
m_output_timer->adjust(
attotime::from_nsec(BIT(step, 0) ? 3'800 : 18'000),
param + 1);
}
BIT(m_out, 4),
BIT(m_out, 5));
m_output_timer->adjust(attotime::from_nsec(10'000), param + 1);
}
break;
case 1:
if ((std::size(m_data) * 2) > step)
{
m_out &= 0x1f;
LOG("Set nybble %u /Ack = 0\n", step);
m_output_timer->adjust(
attotime::from_nsec(12'100),
param + (BIT(step, 0) ? 1 : 3));
}
break;
case 2:
m_out |= 0x20;
LOG("Set nybble %u /Ack = 1\n", step);
m_output_timer->adjust(attotime::from_nsec(3'800), param + 2);
break;
}
}