// license:BSD-3-Clause
// copyright-holders:Ville Linde
/*
Hardware info by Guru
Network PCB (Racing Jam and Thrill Drive (NWK-LC))
-----------
GN676-PWB(H)A
MADE IN JAPAN
(C)1998 KONAMI
|------------------------|
| CY7C199 N676H1 |
| |
|CN3 |
| HYC2485S |
| XC5204 XC5210 |
|CN2 |
| CN1 |
|------------------------|
Notes:
CN1 - Connector joining to CPU board CN4
CN2/3 - RCA jacks for network cable
HYC2485S - Hybrid ceramic module for RS485
CY7C199 - 32k x8 SRAM
XC5204 - Xilinx XC5204 FPGA
XC5210 - Xilink XC5210 FPGA
N676H1 - PALCE16V8Q-15 stamped 'N676H1'
Network PCB (Racing Jam 2 and Thrill Drive (NWK-TR))
-----------
GN676-PWB(H)B
MADE IN JAPAN
(C)1998 KONAMI
|------------------------|
| CY7C199 N676H1 |
| 2G|
|CN3 |
| HYC2485S |
| XC5204 XC5210 |
|CN2 |
| CN1 |
|------------------------|
This pcb is the same as the A version but with one added chip:
2G - XICOR X76F041 Secure SerialFlash (SOIC8)
Note: This chip is also present on *some* Hornet games on the GN715 CPU board at location
30C. The chip refreshes game and region specific serial data to the Timekeeper RAM if the
region ID matches the timekeeper. Because Racing Jam 2 and Thrill Drive came in a conversion
kit for Racing Jam, the two former games will first boot with a "backup data error" because
because of the timekeeper used for the incorrect game. Pressing the test switch then sets the
timekeeper back to factory settings for the new kitted game installed. If the region ID in
serialflash and timekeeper do not match, the game boots with a "hardware error" message.
TODO:
- Add X76F041 device when dumps will be available and get rid of the work_ram hack
*/
#include "emu.h"
#include "konami_gn676_lan.h"
//#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(KONAMI_GN676_LAN, konami_gn676_lan_device, "konami_gn676_lan", "Konami GN676 Network PCB")
konami_gn676_lan_device::konami_gn676_lan_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, KONAMI_GN676_LAN, tag, owner, clock),
m_fpga_uploaded(false),
m_lanc2_ram_r(0),
m_lanc2_ram_w(0),
m_lanc2_ram(nullptr),
m_work_ram(*this, finder_base::DUMMY_TAG)
{
std::fill(std::begin(m_lanc2_reg), std::end(m_lanc2_reg), 0);
}
void konami_gn676_lan_device::device_start()
{
m_lanc2_ram = std::make_unique<uint8_t[]>(0x8000);
save_item(NAME(m_fpga_uploaded));
save_item(NAME(m_lanc2_ram_r));
save_item(NAME(m_lanc2_ram_w));
save_item(NAME(m_lanc2_reg));
save_pointer(NAME(m_lanc2_ram), 0x8000);
}
uint32_t konami_gn676_lan_device::lanc1_r(offs_t offset)
{
switch (offset)
{
case 0x40/4:
{
uint32_t r = 0;
r |= (m_fpga_uploaded) ? (1 << 6) : 0;
r |= 1 << 5;
return (r) << 24;
}
default:
{
LOG("lanc1_r: %08X at %08X\n", offset, machine().describe_context());
return 0xffffffff;
}
}
}
void konami_gn676_lan_device::lanc1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
LOG("lanc1_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, machine().describe_context());
}
uint32_t konami_gn676_lan_device::lanc2_r(offs_t offset, uint32_t mem_mask)
{
uint32_t r = 0;
if (offset == 0)
{
if (ACCESSING_BITS_0_7)
{
r |= m_lanc2_ram[m_lanc2_ram_r & 0x7fff];
m_lanc2_ram_r++;
}
else
{
r |= 0xffffff00;
}
}
else if (offset == 1)
{
r |= 0x00005555; // set all other machines as disconnected
}
else if (offset == 3)
{
r |= 0xffffffff;
}
else if (offset == 4)
{
if (ACCESSING_BITS_24_31)
{
r |= 0x00000000;
}
}
LOG("lanc2_r: %08X, %08X at %08X\n", offset, mem_mask, machine().describe_context());
return r;
}
void konami_gn676_lan_device::lanc2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
if (offset == 0)
{
if (ACCESSING_BITS_24_31)
{
uint8_t value = data >> 24;
value = ((value >> 7) & 0x01) |
((value >> 5) & 0x02) |
((value >> 3) & 0x04) |
((value >> 1) & 0x08) |
((value << 1) & 0x10) |
((value << 3) & 0x20) |
((value << 5) & 0x40) |
((value << 7) & 0x80);
m_fpga_uploaded = true;
m_lanc2_reg[0] = (uint8_t)(data >> 24);
LOG("lanc2_fpga_w: %02X at %08X\n", value, machine().describe_context());
}
if (ACCESSING_BITS_8_15)
{
m_lanc2_ram_r = 0;
m_lanc2_ram_w = 0;
m_lanc2_reg[1] = (uint8_t)(data >> 8);
if (data & 0x1000)
{
// send out frame for this machine
}
else
{
// read from other machines
//int machine_id = (m_lanc2_reg[2] >> 4) & 7;
//int self = m_lanc2_reg[2] & 1;
for (auto j = 0; j < 0x110; j++)
{
m_lanc2_ram[j] = 0xff;
}
}
}
if (ACCESSING_BITS_16_23)
{
m_lanc2_reg[2] = (uint8_t)(data >> 16);
}
if (ACCESSING_BITS_0_7)
{
m_lanc2_ram[m_lanc2_ram_w & 0x7fff] = data & 0xff;
m_lanc2_ram_w++;
}
}
if (offset == 4) // only type B has the chip at 2G
{
// TODO: HACK! The data below would normally be present on the serialflash at 2G.
if (strcmp(machine().system().name, "thrilld") == 0 ||
strcmp(machine().system().name, "thrilldb") == 0 ||
strcmp(machine().system().name, "thrilldbe") == 0)
{
m_work_ram[(0x3ffed0/4) + 0] = 0x472a3731; // G*71
m_work_ram[(0x3ffed0/4) + 1] = 0x33202020; // 3
m_work_ram[(0x3ffed0/4) + 2] = 0x2d2d2a2a; // --**
m_work_ram[(0x3ffed0/4) + 3] = 0x2a207878; // *
m_work_ram[(0x3fff40/4) + 0] = 0x47433731; // GC71
m_work_ram[(0x3fff40/4) + 1] = 0x33000000; // 3
m_work_ram[(0x3fff40/4) + 2] = 0x19994a41; // JA
m_work_ram[(0x3fff40/4) + 3] = 0x4100a9b1; // A
}
else if (strcmp(machine().system().name, "racingj2") == 0)
{
m_work_ram[(0x3ffc80/4) + 0] = 0x47453838; // GE88
m_work_ram[(0x3ffc80/4) + 1] = 0x38003030; // 8 00
m_work_ram[(0x3ffc80/4) + 2] = 0x39374541; // 97EA
m_work_ram[(0x3ffc80/4) + 3] = 0x410058da; // A
}
}
LOG("lanc2_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, machine().describe_context());
}