diff --git a/src/mame/drivers/segas18.cpp b/src/mame/drivers/segas18.cpp index 67f94791302..59ac551ae03 100644 --- a/src/mame/drivers/segas18.cpp +++ b/src/mame/drivers/segas18.cpp @@ -394,22 +394,159 @@ READ16_MEMBER( segas18_state::lghost_custom_io_r ) WRITE16_MEMBER( segas18_state::lghost_custom_io_w ) { + UINT8 pos_value_x, pos_value_y; + switch (offset) { + // Player 1, Y axis case 0x3010/2: - m_lghost_value = 255 - ioport("GUNY1")->read(); + + pos_value_x = ioport("GUNX1")->read(); + pos_value_y = 255 - ioport("GUNY1")->read(); + + // Depending of the position on the X axis, we need to calculate the Y offset accordingly + if (pos_value_x >= 50 && pos_value_x <= 99) + { + // Linear function (decreasing) + if (pos_value_y >= 130 && pos_value_y <= 225) + m_lghost_value = round(pos_value_y * 0.94 + 0.80); + // Keep real value as no offset is needed + else + m_lghost_value = pos_value_y; + } + else if (pos_value_x >= 100 && pos_value_x <= 199) + { + // Linear function (decreasing) + if (pos_value_y >= 100 && pos_value_y <= 225) + m_lghost_value = round(pos_value_y * 0.89 + 6.00); + // Keep real value as no offset is needed + else + m_lghost_value = pos_value_y; + } + else if (pos_value_x >= 200 && pos_value_x <= 249) + { + // Linear function (decreasing) #1 + if (pos_value_y >= 30 && pos_value_y <= 55) + m_lghost_value = round(pos_value_y * 0.78 + 18.28); + + // Linear function (decreasing) #2 + else if (pos_value_y >= 100 && pos_value_y <= 205) + m_lghost_value = round(pos_value_y * 0.70 + 28.00); + // Linear function (decreasing) #2 + else if (pos_value_y >= 206 && pos_value_y <= 225) + m_lghost_value = round(pos_value_y * 1.58 - 151.48); + // Keep real value as no offset is needed + else + m_lghost_value = pos_value_y; + } + // if crosshair is near the left edge, keep real value as no offset is needed + else + m_lghost_value = pos_value_y; break; + // Player 1, X axis case 0x3012/2: - m_lghost_value = ioport("GUNX1")->read(); + + pos_value_x = ioport("GUNX1")->read(); + + // Here, linear functions (increasing) are used + // The line is divided in two parts to get more precise results + + // Linear function (increasing) #1 + if (pos_value_x >= 26 && pos_value_x <= 85) + m_lghost_value = round(pos_value_x * 1.13 + 0.95); + + // Linear function (increasing) #2 + else if (pos_value_x >= 86 && pos_value_x <= 140) + m_lghost_value = round(pos_value_x * 1.10 + 4.00); + + // Here, linear functions (decreasing) are used + // The line is divided in two parts to get more precise results + + // Linear function (decreasing) #1 + else if (pos_value_x >= 141 && pos_value_x <= 190) + m_lghost_value = round(pos_value_x * 1.02 + 11.20); + + // Linear function (decreasing) #2 + else if (pos_value_x >= 191 && pos_value_x <= 240) + m_lghost_value = round(pos_value_x * 0.76 + 62.60); + + // if crosshair is near the edges, keep real value as no offset is needed + else + m_lghost_value = pos_value_x; break; + // Player 2 and 3, Y axis case 0x3014/2: - m_lghost_value = 255 - ioport(m_lghost_select ? "GUNY3" : "GUNY2")->read(); + + // Player 3, Y axis + if (m_lghost_select) + { + pos_value_x = ioport("GUNX3")->read(); + pos_value_y = 255 - ioport("GUNY3")->read(); + + // Depending of the position on the X axis, we need to calculate the Y offset accordingly + if (pos_value_x >= 128 && pos_value_x <= 255) + { + // Linear function (increasing) + if (pos_value_y >= 30 && pos_value_y <= 125) + m_lghost_value = round(pos_value_y * 1.01 + 11.82); + // Linear function (decreasing) + else if (pos_value_y >= 126 && pos_value_y <= 235) + m_lghost_value = round(pos_value_y * 0.94 + 21.90); + // Keep real value as no offset is needed + else + m_lghost_value = pos_value_y; + } + else if (pos_value_x >= 17 && pos_value_x <= 127) + { + // Linear function (increasing) + if (pos_value_y >= 40 && pos_value_y <= 145) + m_lghost_value = round(pos_value_y * 0.82 + 31.80); + // Linear function (decreasing) + else if (pos_value_y >= 200 && pos_value_y <= 225) + m_lghost_value = round(pos_value_y * 0.83 + 29.95); + // Keep real value as no offset is needed + else + m_lghost_value = pos_value_y; + } + // Keep real value as no offset is needed + else + m_lghost_value = pos_value_y; + } + // Player 2, Y axis. It doesn't need any offset adjustement. + else + m_lghost_value = 255 - ioport("GUNY2")->read(); break; + // Player 2 and 3, X axis case 0x3016/2: - m_lghost_value = ioport(m_lghost_select ? "GUNX3" : "GUNX2")->read(); + + // Player 3, X axis + if (m_lghost_select) + { + pos_value_x = ioport("GUNX3")->read(); + + // Right edge of screen, constant value + if (pos_value_x >= 17 && pos_value_x <= 34) + m_lghost_value = pos_value_x - 17; + + // Linear function (increasing) + else if (pos_value_x >= 35 && pos_value_x <= 110) + m_lghost_value = round(pos_value_x * 0.94 - 14.08); + + // Linear function (decreasing) #1 + else if (pos_value_x >= 111 && pos_value_x <= 225) + m_lghost_value = round(pos_value_x * 1.15 - 35.65); + + // if crosshair is near the edges, keep real value as no offset is needed*/ + else + m_lghost_value = pos_value_x; + break; + } + // Player 2, X axis. It doesn't need any offset adjustement. + else + m_lghost_value = ioport("GUNX2")->read(); break; case 0x3020/2: