diff --git a/CMakeLists.txt b/CMakeLists.txt
index ffc9c23e6..dabf14e1f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -819,10 +819,14 @@ target_sources(${PROJECT_NAME} PRIVATE
core/hw/bba/bba.cpp
core/hw/bba/rtl8139c.h
core/hw/bba/rtl8139c.cpp
+ core/hw/flashrom/at93cxx.cpp
+ core/hw/flashrom/at93cxx.h
core/hw/flashrom/flashrom.cpp
core/hw/flashrom/flashrom.h
core/hw/flashrom/nvmem.cpp
core/hw/flashrom/nvmem.h
+ core/hw/flashrom/x76f100.cpp
+ core/hw/flashrom/x76f100.h
core/hw/gdrom/gdrom_if.h
core/hw/gdrom/gdrom_response.cpp
core/hw/gdrom/gdromv3.cpp
diff --git a/core/hw/flashrom/at93cxx.cpp b/core/hw/flashrom/at93cxx.cpp
new file mode 100644
index 000000000..442b23d31
--- /dev/null
+++ b/core/hw/flashrom/at93cxx.cpp
@@ -0,0 +1,152 @@
+/*
+ Copyright 2023 flyinghead
+
+ This file is part of Flycast.
+
+ Flycast is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ Flycast is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Flycast. If not, see .
+ */
+#include "at93cxx.h"
+
+//#define DEBUG_EEPROM 1
+
+#ifdef DEBUG_EEPROM
+#define EEPROM_LOG(...) DEBUG_LOG(FLASHROM, __VA_ARGS__)
+#else
+#define EEPROM_LOG(...)
+#endif
+
+void AT93CxxSerialEeprom::writeCLK(bool state)
+{
+ // CS asserted and CLK rising
+ if (!clk && state && cs)
+ {
+ if (dataOutBits > 0)
+ dataOutBits--;
+ if (dataOutBits == 0)
+ {
+ if (command.empty() && !di)
+ INFO_LOG(NAOMI, "serial eeprom: Ignoring bit 0 (start bit must be 1)");
+ else
+ {
+ command.push_back(di);
+ if (command.size() == 9)
+ {
+ int opCode = (int)command[1] * 2 + (int)command[2];
+ switch (opCode)
+ {
+ case 0: // write enable/disable, erase all, write all
+ {
+ int subCode = (int)command[3] * 2 + (int)command[4];
+ switch (subCode)
+ {
+ case 0: // disable write
+ EEPROM_LOG("serial eeprom: EWDS");
+ writeEnable = false;
+ command.clear();
+ break;
+ case 1: // write all
+ expected = 3 + 6 + 16; // 6 bits of address, 16 bits of data
+ break;
+ case 2: // erase all
+ EEPROM_LOG("serial eeprom: ERAL");
+ if (writeEnable)
+ memset(data, 0xff, size);
+ command.clear();
+ break;
+ case 3: // enable write
+ EEPROM_LOG("serial eeprom: EWEN");
+ writeEnable = true;
+ command.clear();
+ break;
+ }
+ }
+ break;
+ case 1: // write
+ expected = 3 + 6 + 16; // 6 bits of address, 16 bits of data
+ break;
+ case 2: // read
+ dataOut = Read(getCommandAddress() * 2, 2);
+ dataOutBits = 17; // actually 16 but 0 means no data
+ EEPROM_LOG("serial eeprom: READ %x: %x", getCommandAddress(), dataOut);
+ command.clear();
+ break;
+ case 3: // erase
+ EEPROM_LOG("serial eeprom: ERASE %x", getCommandAddress());
+ if (writeEnable)
+ *(u16 *)&data[(getCommandAddress() * 2) & mask] = 0xffff;
+ command.clear();
+ break;
+ }
+ }
+ else if (expected > 0 && (int)command.size() == expected)
+ {
+ int opCode = (int)command[1] * 2 + (int)command[2];
+ switch (opCode)
+ {
+ case 0: // write all
+ {
+ u16 v = getCommandData();
+ EEPROM_LOG("serial eeprom: WRAL = %x", v);
+ if (writeEnable)
+ for (u32 i = 0; i < size; i += 2)
+ *(u16 *)&data[i & mask] = v;
+ }
+ break;
+ case 1: // write
+ EEPROM_LOG("serial eeprom: WRITE %x = %x", getCommandAddress(), getCommandData());
+ if (writeEnable)
+ *(u16 *)&data[(getCommandAddress() * 2) & mask] = getCommandData();
+ break;
+ }
+ command.clear();
+ expected = 0;
+ }
+ }
+ }
+ }
+ clk = state;
+}
+
+void AT93CxxSerialEeprom::Serialize(Serializer& ser) const
+{
+ ser << cs;
+ ser << clk;
+ ser << di;
+ ser << (u32)command.size();
+ for (bool b : command)
+ ser << b;
+ ser << expected;
+ ser << writeEnable;
+ ser << dataOut;
+ ser << dataOutBits;
+}
+
+void AT93CxxSerialEeprom::Deserialize(Deserializer& deser)
+{
+ deser >> cs;
+ deser >> clk;
+ deser >> di;
+ u32 size;
+ deser >> size;
+ command.resize(size);
+ for (u32 i = 0; i < size; i++) {
+ bool b;
+ deser >> b;
+ command[i] = b;
+ }
+ deser >> expected;
+ deser >> writeEnable;
+ deser >> dataOut;
+ deser >> dataOutBits;
+}
diff --git a/core/hw/flashrom/at93cxx.h b/core/hw/flashrom/at93cxx.h
new file mode 100644
index 000000000..803345ed7
--- /dev/null
+++ b/core/hw/flashrom/at93cxx.h
@@ -0,0 +1,106 @@
+/*
+ Copyright 2023 flyinghead
+
+ This file is part of Flycast.
+
+ Flycast is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ Flycast is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Flycast. If not, see .
+ */
+#pragma once
+#include "flashrom.h"
+#include
+
+//
+// Three-wire Serial EEPROM
+//
+class AT93CxxSerialEeprom : public WritableChip
+{
+public:
+ AT93CxxSerialEeprom(u32 size) : WritableChip(size) {
+ memset(data, 0xff, size);
+ }
+
+ // combined DO + READY/BUSY
+ bool readDO()
+ {
+ if (dataOutBits > 0)
+ // DO
+ return (dataOut >> (dataOutBits - 1)) & 1;
+ else
+ // Ready
+ return true;
+ }
+
+ // chip select (active high)
+ void writeCS(bool state) {
+ cs = state;
+ }
+
+ // clock
+ void writeCLK(bool state);
+
+ // data in
+ void writeDI(bool state) {
+ di = state;
+ }
+
+ void Write(u32 addr, u32 data, u32 size) override {
+ die("Unsupported");
+ }
+
+ void Serialize(Serializer& ser) const override;
+ void Deserialize(Deserializer& deser) override;
+
+private:
+ u8 getCommandAddress() const
+ {
+ verify(command.size() >= 9);
+ u8 addr = 0;
+ for (int i = 3; i < 9; i++) {
+ addr <<= 1;
+ addr |= command[i];
+ }
+ return addr;
+ }
+
+ u16 getCommandData() const
+ {
+ verify(command.size() >= 25);
+ u16 v = 0;
+ for (int i = 9; i < 25; i++) {
+ v <<= 1;
+ v |= command[i];
+ }
+ return v;
+ }
+
+ bool cs = false;
+ bool clk = false;
+ bool di = false;
+ std::vector command;
+ int expected = 0;
+ bool writeEnable = false;
+ u16 dataOut = 0;
+ u8 dataOutBits = 0;
+};
+
+//
+// Three-wire Serial EEPROM
+// 1 Kb (128 x 8)
+//
+class AT93C46SerialEeprom : public AT93CxxSerialEeprom
+{
+public:
+ AT93C46SerialEeprom() : AT93CxxSerialEeprom(128) {}
+};
+
diff --git a/core/hw/flashrom/x76f100.cpp b/core/hw/flashrom/x76f100.cpp
new file mode 100644
index 000000000..d5edda833
--- /dev/null
+++ b/core/hw/flashrom/x76f100.cpp
@@ -0,0 +1,282 @@
+// Derived from mame src/devices/machine/x76f100.{h,cpp}
+// license:BSD-3-Clause
+// copyright-holders:smf
+#include "x76f100.h"
+#include "serialize.h"
+
+void X76F100SerialFlash::writeSCL(bool v)
+{
+ if (!lastCS)
+ {
+ switch (state)
+ {
+ case State::STOP:
+ break;
+
+ case State::RESPONSE_TO_RESET:
+ if (lastSCL && !v)
+ {
+ if (bit == 0)
+ shift = responseToReset[byteOffset];
+
+ sda = shift & 1;
+ shift >>= 1;
+ bit++;
+
+ if (bit == 8)
+ {
+ bit = 0;
+ byteOffset++;
+ if (byteOffset == sizeof(responseToReset))
+ byteOffset = 0;
+ }
+ }
+ break;
+
+ case State::LOAD_COMMAND:
+ case State::LOAD_PASSWORD:
+ case State::VERIFY_PASSWORD:
+ case State::WRITE_DATA:
+ if (!lastSCL && v)
+ {
+ if (bit < 8)
+ {
+ shift <<= 1;
+
+ if (lastSDA)
+ shift |= 1;
+ bit++;
+ }
+ else
+ {
+ sda = false;
+
+ switch (state)
+ {
+ case State::LOAD_COMMAND:
+ command = shift;
+ DEBUG_LOG(FLASHROM, "-> command: %02x", command);
+ state = State::LOAD_PASSWORD;
+ break;
+
+ case State::LOAD_PASSWORD:
+ DEBUG_LOG(FLASHROM, "-> password: %02x", shift);
+ writeBuffer[byteOffset++] = shift;
+
+ if (byteOffset == sizeof(writeBuffer))
+ {
+ state = State::VERIFY_PASSWORD;
+
+ // We don't check the password
+ u8 *password;
+ if ((command & 0xe1) == (int)Command::READ)
+ password = readPassword;
+ else
+ password = writePassword;
+ DEBUG_LOG(FLASHROM, "Password accepted: %d", memcmp(password, writeBuffer, sizeof(writeBuffer)) == 0);
+ }
+ break;
+
+ case State::VERIFY_PASSWORD:
+ DEBUG_LOG(FLASHROM, "-> verify password: %02x", shift);
+
+ if (shift == (int)Command::ACK_PASSWORD)
+ {
+ if (true) // password accepted
+ {
+ if ((command & 0x81) == (int)Command::READ)
+ state = State::READ_DATA;
+ else if ((command & 0x81) == (int)Command::WRITE)
+ state = State::WRITE_DATA;
+ }
+ else
+ sda = true;
+ }
+ break;
+
+ case State::WRITE_DATA:
+ DEBUG_LOG(FLASHROM, "-> data: %02x", shift );
+ writeBuffer[byteOffset++] = shift;
+
+ if (byteOffset == sizeof(writeBuffer))
+ {
+ if (command == (int)Command::CHANGE_WRITE_PASSWORD)
+ {
+ memcpy(writeBuffer, writePassword, sizeof(writePassword));
+ }
+ else if (command == (int)Command::CHANGE_READ_PASSWORD)
+ {
+ memcpy(writeBuffer, readPassword, sizeof(readPassword));
+ }
+ else
+ {
+ for (byteOffset = 0; byteOffset < sizeof(writeBuffer); byteOffset++)
+ {
+ int offset = dataOffset();
+
+ if (offset != -1)
+ data[offset] = writeBuffer[byteOffset];
+ else
+ break;
+ }
+ }
+ byteOffset = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ bit = 0;
+ shift = 0;
+ }
+ }
+ break;
+
+ case State::READ_DATA:
+ if (!lastSCL && v)
+ {
+ if (bit < 8)
+ {
+ if (bit == 0)
+ {
+ int offset = dataOffset();
+
+ if (offset != -1)
+ shift = data[offset];
+ else
+ shift = 0;
+ }
+
+ sda = (shift >> 7) & 1;
+ shift <<= 1;
+ bit++;
+ }
+ else
+ {
+ bit = 0;
+ sda = false;
+
+ if (!lastSDA)
+ {
+ DEBUG_LOG(FLASHROM, "ack <-");
+ byteOffset++;
+ }
+ else
+ {
+ DEBUG_LOG(FLASHROM, "nak <-");
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ SCLChanged = (lastSCL != v);
+ lastSCL = v;
+}
+
+void X76F100SerialFlash::writeSDA(bool v)
+{
+ if (lastSCL && !SCLChanged && !lastCS)
+ {
+ if (!lastSDA && v)
+ {
+ DEBUG_LOG(FLASHROM, "goto stop");
+ state = State::STOP;
+ sda = false;
+ }
+
+ if (lastSDA && !v)
+ {
+ switch (state)
+ {
+ case State::STOP:
+ DEBUG_LOG(FLASHROM, "goto start");
+ state = State::LOAD_COMMAND;
+ break;
+
+ case State::LOAD_PASSWORD:
+ DEBUG_LOG(FLASHROM, "goto start");
+ break;
+
+ case State::READ_DATA:
+ DEBUG_LOG(FLASHROM, "reading");
+ break;
+
+ default:
+ DEBUG_LOG(FLASHROM, "skipped start (default)");
+ break;
+ }
+
+ bit = 0;
+ byteOffset = 0;
+ shift = 0;
+ sda = false;
+ }
+ }
+ lastSDA = v;
+}
+
+void X76F100SerialFlash::reset()
+{
+ lastSCL = false;
+ SCLChanged = false;
+ lastSDA = false;
+ sda = false;
+ lastRST = false;
+ lastCS = false;
+ state = State::STOP;
+ bit = 0;
+ byteOffset = 0;
+ command = 0;
+ shift = 0;
+ memset(writeBuffer, 0, sizeof(writeBuffer));
+}
+
+int X76F100SerialFlash::dataOffset()
+{
+ int block_offset = (command >> 1) & 0x0f;
+ int offset = (block_offset * 8) + byteOffset;
+
+ // Technically there are 4 bits assigned to sector values but since the data array is only 112 bytes,
+ // it will try reading out of bounds when the sector is 14 (= starts at 112) or 15 (= starts at 120).
+ if (offset >= (int)sizeof(data))
+ return -1;
+
+ return offset;
+}
+
+void X76F100SerialFlash::serialize(Serializer& ser) const
+{
+ ser << writeBuffer;
+ ser << lastSCL;
+ ser << SCLChanged;
+ ser << lastSDA;
+ ser << sda;
+ ser << lastRST;
+ ser << lastCS;
+ ser << state;
+ ser << command;
+ ser << byteOffset;
+ ser << bit;
+ ser << shift;
+}
+
+void X76F100SerialFlash::deserialize(Deserializer& deser)
+{
+ deser >> writeBuffer;
+ deser >> lastSCL;
+ deser >> SCLChanged;
+ deser >> lastSDA;
+ deser >> sda;
+ deser >> lastRST;
+ deser >> lastCS;
+ deser >> state;
+ deser >> command;
+ deser >> byteOffset;
+ deser >> bit;
+ deser >> shift;
+}
+
diff --git a/core/hw/flashrom/x76f100.h b/core/hw/flashrom/x76f100.h
new file mode 100644
index 000000000..bb8496a02
--- /dev/null
+++ b/core/hw/flashrom/x76f100.h
@@ -0,0 +1,107 @@
+// Derived from mame src/devices/machine/x76f100.{h,cpp}
+// license:BSD-3-Clause
+// copyright-holders:smf
+/*
+ * The X76F100 is a Password Access Security Supervisor, containing one 896-bit Secure SerialFlash array.
+ * Access to the memory array can be controlled by two 64-bit passwords. These passwords protect read and
+ * write operations of the memory array.
+ */
+#pragma once
+#include "types.h"
+#include
+
+class X76F100SerialFlash
+{
+public:
+ void reset();
+
+ // Clock
+ void writeSCL(bool v);
+
+ // Data I/O
+ void writeSDA(bool v);
+
+ bool readSDA() {
+ return lastCS ? 1 : sda;
+ }
+
+ // Chip select
+ void writeCS(bool v)
+ {
+ if (lastCS && !v)
+ state = State::STOP;
+ else if (!lastCS && v) {
+ state = State::STOP;
+ sda = false;
+ }
+ lastCS = v;
+ }
+
+ // Reset
+ void writeRST(bool v)
+ {
+ if (v && !lastRST && !lastCS)
+ {
+ DEBUG_LOG(FLASHROM, "reset");
+ state = State::RESPONSE_TO_RESET;
+ bit = 0;
+ byteOffset = 0;
+ }
+ lastRST = v;
+ }
+
+ void setData(const u8 *data)
+ {
+ size_t index = 0;
+ memcpy(responseToReset, &data[index], sizeof(responseToReset));
+ index += sizeof(responseToReset);
+ memcpy(writePassword, &data[index], sizeof(writePassword));
+ index += sizeof(writePassword);
+ memcpy(readPassword, &data[index], sizeof(readPassword));
+ index += sizeof(readPassword);
+ memcpy(this->data, &data[index], sizeof(this->data));
+ }
+
+ void serialize(Serializer& ser) const;
+ void deserialize(Deserializer& deser);
+
+private:
+ enum class Command
+ {
+ WRITE = 0x80,
+ READ = 0x81,
+ CHANGE_WRITE_PASSWORD = 0xfc,
+ CHANGE_READ_PASSWORD = 0xfe,
+ ACK_PASSWORD = 0x55
+ };
+
+ enum class State
+ {
+ STOP,
+ RESPONSE_TO_RESET,
+ LOAD_COMMAND,
+ LOAD_PASSWORD,
+ VERIFY_PASSWORD,
+ READ_DATA,
+ WRITE_DATA
+ };
+
+ int dataOffset();
+
+ u8 data[112] {};
+ u8 readPassword[8] {};
+ u8 writePassword[8] {};
+ u8 responseToReset[4] { 0x19, 0x00, 0xaa, 0x55 };
+ u8 writeBuffer[8] {};
+ bool lastSCL = false;
+ bool lastSDA = false;
+ bool sda = false;
+ bool lastRST = false;
+ bool lastCS = false;
+ bool SCLChanged = false;
+ State state = State::STOP;
+ u8 command = 0;
+ u8 byteOffset = 0;
+ u8 bit = 0;
+ u8 shift = 0;
+};
diff --git a/core/hw/naomi/naomi.cpp b/core/hw/naomi/naomi.cpp
index e53fd5699..cf64577cd 100644
--- a/core/hw/naomi/naomi.cpp
+++ b/core/hw/naomi/naomi.cpp
@@ -19,21 +19,15 @@
#include "hw/sh4/modules/modules.h"
#include "rend/gui.h"
#include "printer.h"
+#include "hw/flashrom/x76f100.h"
#include
static NaomiM3Comm m3comm;
Multiboard *multiboard;
-static const u32 BoardID = 0x980055AA;
-static u32 GSerialBuffer, BSerialBuffer;
-static int GBufPos, BBufPos;
-static int GState, BState;
-static int GOldClk, BOldClk;
-static int BControl, BCmd, BLastCmd;
-static int GControl, GCmd, GLastCmd;
-static int SerStep, SerStep2;
-
+static X76F100SerialFlash mainSerialId;
+static X76F100SerialFlash romSerialId;
/*
El numero de serie solo puede contener:
0-9 (0x30-0x39)
@@ -41,294 +35,44 @@ A-H (0x41-0x48)
J-N (0x4A-0x4E)
P-Z (0x50-0x5A)
*/
-static u8 BSerial[]="\xB7"/*CRC1*/"\x19"/*CRC2*/"0123234437897584372973927387463782196719782697849162342198671923649";
+//static u8 BSerial[]="\xB7"/*CRC1*/"\x19"/*CRC2*/"0123234437897584372973927387463782196719782697849162342198671923649";
//static u8 BSerial[]="\x09\xa1 0000000000000000\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; // default from mame
-static u8 GSerial[]="\xB7"/*CRC1*/"\x19"/*CRC2*/"0123234437897584372973927387463782196719782697849162342198671923649";
+//static u8 GSerial[]="\xB7"/*CRC1*/"\x19"/*CRC2*/"0123234437897584372973927387463782196719782697849162342198671923649";
static u8 midiTxBuf[4];
static u32 midiTxBufIndex;
-static unsigned int ShiftCRC(unsigned int CRC,unsigned int rounds)
+void NaomiBoardIDWrite(const u16 data)
{
- const unsigned int Magic=0x10210000;
- unsigned int i;
- for(i=0;i>16);
-}
-
-void NaomiInit()
-{
- u16 CRC;
- CRC=CRCSerial(BSerial+2,0x2E);
- BSerial[0]=(u8)(CRC>>8);
- BSerial[1]=(u8)(CRC);
-
- CRC=CRCSerial(GSerial+2,0x2E);
- GSerial[0]=(u8)(CRC>>8);
- GSerial[1]=(u8)(CRC);
-}
-
-void NaomiBoardIDWrite(const u16 Data)
-{
- int Dat=Data&8;
- int Clk=Data&4;
- int Rst=Data&0x20;
- int Sta=Data&0x10;
-
- if(Rst)
- {
- BState=0;
- BBufPos=0;
- }
-
- if(Clk!=BOldClk && !Clk) //Falling Edge clock
- {
- //State change
- if(BState==0 && Sta)
- BState=1;
- if(BState==1 && !Sta)
- BState=2;
-
- if((BControl&0xfff)==0xFF0) //Command mode
- {
- BCmd<<=1;
- if(Dat)
- BCmd|=1;
- else
- BCmd&=0xfffffffe;
- }
-
- //State processing
- if(BState==1) //LoadBoardID
- {
- BSerialBuffer=BoardID;
- BBufPos=0; //??
- }
- if(BState==2) //ShiftBoardID
- {
- BBufPos++;
- }
- }
- BOldClk=Clk;
+ // bit 2: clock
+ // bit 3: data
+ // bit 4: reset (x76f100 only)
+ // bit 5: chip select
+ mainSerialId.writeCS(data & 0x20);
+ mainSerialId.writeRST(data & 0x10);
+ mainSerialId.writeSCL(data & 4);
+ mainSerialId.writeSDA(data & 8);
}
u16 NaomiBoardIDRead()
{
- if((BControl&0xff)==0xFE)
- return 0xffff;
- return (BSerialBuffer&(1<<(31-BBufPos)))?8:0;
+ // bit 0 indicates the eeprom is a X76F100, otherwise the BIOS expects a AT93C46
+ // bit 3 is xf76f100 SDA
+ // bit 4 is at93c46 DO
+ return (mainSerialId.readSDA() << 3) | 1;
}
-static u32 AdaptByte(u8 val)
+void NaomiGameIDWrite(const u16 data)
{
- return val<<24;
-}
-
-void NaomiBoardIDWriteControl(const u16 Data)
-{
- if((Data&0xfff)==0xF30 && BCmd!=BLastCmd)
- {
- if((BCmd&0x81)==0x81)
- {
- SerStep2=(BCmd>>1)&0x3f;
-
- BSerialBuffer=0x00000000; //First block contains CRC
- BBufPos=0;
- }
- if((BCmd&0xff)==0x55) //Load Offset 0
- {
- BState=2;
- BBufPos=0;
- BSerialBuffer=AdaptByte(BSerial[8*SerStep2])>>1;
- }
- if((BCmd&0xff)==0xAA) //Load Offset 1
- {
- BState=2;
- BBufPos=0;
- BSerialBuffer=AdaptByte(BSerial[8*SerStep2+1]);
- }
- if((BCmd&0xff)==0x54)
- {
- BState=2;
- BBufPos=0;
- BSerialBuffer=AdaptByte(BSerial[8*SerStep2+2]);
- }
- if((BCmd&0xff)==0xA8)
- {
- BState=2;
- BBufPos=0;
- BSerialBuffer=AdaptByte(BSerial[8*SerStep2+3]);
- }
- if((BCmd&0xff)==0x50)
- {
- BState=2;
- BBufPos=0;
- BSerialBuffer=AdaptByte(BSerial[8*SerStep2+4]);
- }
- if((BCmd&0xff)==0xA0)
- {
- BState=2;
- BBufPos=0;
- BSerialBuffer=AdaptByte(BSerial[8*SerStep2+5]);
- }
- if((BCmd&0xff)==0x40)
- {
- BState=2;
- BBufPos=0;
- BSerialBuffer=AdaptByte(BSerial[8*SerStep2+6]);
- }
- if((BCmd&0xff)==0x80)
- {
- BState=2;
- BBufPos=0;
- BSerialBuffer=AdaptByte(BSerial[8*SerStep2+7]);
- }
- BLastCmd=BCmd;
- }
- BControl=Data;
-}
-
-static void NaomiGameIDProcessCmd()
-{
- if(GCmd!=GLastCmd)
- {
- if((GCmd&0x81)==0x81)
- {
- SerStep=(GCmd>>1)&0x3f;
-
- GSerialBuffer=0x00000000; //First block contains CRC
- GBufPos=0;
- }
- if((GCmd&0xff)==0x55) //Load Offset 0
- {
- GState=2;
- GBufPos=0;
- GSerialBuffer=AdaptByte(GSerial[8*SerStep])>>0;
- }
- if((GCmd&0xff)==0xAA) //Load Offset 1
- {
- GState=2;
- GBufPos=0;
- GSerialBuffer=AdaptByte(GSerial[8*SerStep+1]);
- }
- if((GCmd&0xff)==0x54)
- {
- GState=2;
- GBufPos=0;
- GSerialBuffer=AdaptByte(GSerial[8*SerStep+2]);
- }
- if((GCmd&0xff)==0xA8)
- {
- GState=2;
- GBufPos=0;
- GSerialBuffer=AdaptByte(GSerial[8*SerStep+3]);
- }
- if((GCmd&0xff)==0x50)
- {
- GState=2;
- GBufPos=0;
- GSerialBuffer=AdaptByte(GSerial[8*SerStep+4]);
- }
- if((GCmd&0xff)==0xA0)
- {
- GState=2;
- GBufPos=0;
- GSerialBuffer=AdaptByte(GSerial[8*SerStep+5]);
- }
- if((GCmd&0xff)==0x40)
- {
- GState=2;
- GBufPos=0;
- GSerialBuffer=AdaptByte(GSerial[8*SerStep+6]);
- }
- if((GCmd&0xff)==0x80)
- {
- GState=2;
- GBufPos=0;
- GSerialBuffer=AdaptByte(GSerial[8*SerStep+7]);
- }
- GLastCmd=GCmd;
- }
-}
-
-
-void NaomiGameIDWrite(const u16 Data)
-{
- int Dat=Data&0x01; // mame: SDA
- int Clk=Data&0x02; // mame: SCL
- int Rst=Data&0x04; // mame: CS
- int Sta=Data&0x08; // mame: RST
- int Cmd=Data&0x10; // mame: unused...
-
- if(Rst)
- {
- GState=0;
- GBufPos=0;
- }
-
- if(Clk!=GOldClk && !Clk) //Falling Edge clock
- {
- //State change
- if(GState==0 && Sta)
- GState=1;
- if(GState==1 && !Sta)
- GState=2;
-
- //State processing
- if(GState==1) //LoadBoardID
- {
- GSerialBuffer=BoardID;
- GBufPos=0; //??
- }
- if(GState==2) //ShiftBoardID
- GBufPos++;
-
- if(GControl!=Cmd && !Cmd)
- {
- NaomiGameIDProcessCmd();
- }
- GControl=Cmd;
- }
- if(Clk!=GOldClk && Clk) //Rising Edge clock
- {
- if(Cmd) //Command mode
- {
- GCmd<<=1;
- if(Dat)
- GCmd|=1;
- else
- GCmd&=0xfffffffe;
- GControl=Cmd;
- }
- }
- GOldClk=Clk;
+ romSerialId.writeCS(data & 4);
+ romSerialId.writeRST(data & 8);
+ romSerialId.writeSCL(data & 2);
+ romSerialId.writeSDA(data & 1);
}
u16 NaomiGameIDRead()
{
- return (GSerialBuffer&(1<<(31-GBufPos)))?1:0;
+ return romSerialId.readSDA() << 15;
}
static bool aw_ram_test_skipped = false;
@@ -421,8 +165,23 @@ static void Naomi_DmaEnable(u32 addr, u32 data)
void naomi_reg_Init()
{
- NaomiInit();
networkOutput.init();
+
+ static const u8 romSerialData[0x84] = {
+ 0x19, 0x00, 0xaa, 0x55,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x69, 0x79, 0x68, 0x6b, 0x74, 0x6d, 0x68, 0x6d,
+ 0xa1, 0x09, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'
+ };
+ romSerialId.setData(romSerialData);
+ mainSerialId.setData(romSerialData);
+}
+
+void setGameSerialId(const u8 *data)
+{
+ romSerialId.setData(data);
}
void naomi_reg_Term()
@@ -442,22 +201,7 @@ void naomi_reg_Reset(bool hard)
SB_GDEN = 0;
aw_ram_test_skipped = false;
- GSerialBuffer = 0;
- BSerialBuffer = 0;
- GBufPos = 0;
- BBufPos = 0;
- GState = 0;
- BState = 0;
- GOldClk = 0;
- BOldClk = 0;
- BControl = 0;
- BCmd = 0;
- BLastCmd = 0;
- GControl = 0;
- GCmd = 0;
- GLastCmd = 0;
- SerStep = 0;
- SerStep2 = 0;
+
m3comm.closeNetwork();
if (hard)
{
@@ -470,6 +214,8 @@ void naomi_reg_Reset(bool hard)
if (settings.naomi.multiboard)
multiboard = new Multiboard();
networkOutput.reset();
+ mainSerialId.reset();
+ romSerialId.reset();
}
else if (multiboard != nullptr)
multiboard->reset();
@@ -587,24 +333,8 @@ static bool ffbCalibrating;
void naomi_Serialize(Serializer& ser)
{
- ser << GSerialBuffer;
- ser << BSerialBuffer;
- ser << GBufPos;
- ser << BBufPos;
- ser << GState;
- ser << BState;
- ser << GOldClk;
- ser << BOldClk;
- ser << BControl;
- ser << BCmd;
- ser << BLastCmd;
- ser << GControl;
- ser << GCmd;
- ser << GLastCmd;
- ser << SerStep;
- ser << SerStep2;
- ser.serialize(BSerial, 69);
- ser.serialize(GSerial, 69);
+ mainSerialId.serialize(ser);
+ romSerialId.serialize(ser);
ser << aw_maple_devs;
ser << coin_chute_time;
ser << aw_ram_test_skipped;
@@ -615,24 +345,32 @@ void naomi_Serialize(Serializer& ser)
}
void naomi_Deserialize(Deserializer& deser)
{
- deser >> GSerialBuffer;
- deser >> BSerialBuffer;
- deser >> GBufPos;
- deser >> BBufPos;
- deser >> GState;
- deser >> BState;
- deser >> GOldClk;
- deser >> BOldClk;
- deser >> BControl;
- deser >> BCmd;
- deser >> BLastCmd;
- deser >> GControl;
- deser >> GCmd;
- deser >> GLastCmd;
- deser >> SerStep;
- deser >> SerStep2;
- deser.deserialize(BSerial, 69);
- deser.deserialize(GSerial, 69);
+ if (deser.version() < Deserializer::V40)
+ {
+ deser.skip(); // GSerialBuffer
+ deser.skip(); // BSerialBuffer
+ deser.skip(); // GBufPos
+ deser.skip(); // BBufPos
+ deser.skip(); // GState
+ deser.skip(); // BState
+ deser.skip(); // GOldClk
+ deser.skip(); // BOldClk
+ deser.skip(); // BControl
+ deser.skip(); // BCmd
+ deser.skip(); // BLastCmd
+ deser.skip(); // GControl
+ deser.skip(); // GCmd
+ deser.skip(); // GLastCmd
+ deser.skip(); // SerStep
+ deser.skip(); // SerStep2
+ deser.skip(69); // BSerial
+ deser.skip(69); // GSerial
+ }
+ else
+ {
+ mainSerialId.deserialize(deser);
+ romSerialId.deserialize(deser);
+ }
if (deser.version() < Deserializer::V36)
{
deser.skip(); // reg_dimm_command;
diff --git a/core/hw/naomi/naomi.h b/core/hw/naomi/naomi.h
index 29c2456be..f86bf31d3 100644
--- a/core/hw/naomi/naomi.h
+++ b/core/hw/naomi/naomi.h
@@ -14,11 +14,11 @@ void naomi_Deserialize(Deserializer& deser);
u32 ReadMem_naomi(u32 Addr, u32 size);
void WriteMem_naomi(u32 Addr, u32 data, u32 size);
-void NaomiBoardIDWrite(u16 Data);
-void NaomiBoardIDWriteControl(u16 Data);
+void NaomiBoardIDWrite(u16 data);
u16 NaomiBoardIDRead();
u16 NaomiGameIDRead();
-void NaomiGameIDWrite(u16 Data);
+void NaomiGameIDWrite(u16 data);
+void setGameSerialId(const u8 *data);
void initMidiForceFeedback();
void initDriveSimSerialPipe();
diff --git a/core/hw/naomi/naomi_cart.cpp b/core/hw/naomi/naomi_cart.cpp
index dd6dd1858..1c2c447df 100644
--- a/core/hw/naomi/naomi_cart.cpp
+++ b/core/hw/naomi/naomi_cart.cpp
@@ -388,14 +388,27 @@ static void loadMameRom(const std::string& path, const std::string& fileName, Lo
case Eeprom:
{
- naomi_default_eeprom = (u8 *)malloc(game->blobs[romid].length);
- if (naomi_default_eeprom == nullptr)
- throw NaomiCartException("Memory allocation failed");
+ if (game->blobs[romid].length == 0x84)
+ {
+ // on-cart X76F100 security eeprom
+ u8 data[0x84];
+ u32 read = file->Read(data, sizeof(data));
+ if (config::GGPOEnable)
+ md5.add(data, sizeof(data));
+ setGameSerialId(data);
+ DEBUG_LOG(NAOMI, "Loaded %s: %x bytes rom serial eeprom", game->blobs[romid].filename, read);
+ }
+ else
+ {
+ naomi_default_eeprom = (u8 *)malloc(game->blobs[romid].length);
+ if (naomi_default_eeprom == nullptr)
+ throw NaomiCartException("Memory allocation failed");
- u32 read = file->Read(naomi_default_eeprom, game->blobs[romid].length);
- if (config::GGPOEnable)
- md5.add(naomi_default_eeprom, game->blobs[romid].length);
- DEBUG_LOG(NAOMI, "Loaded %s: %x bytes default eeprom", game->blobs[romid].filename, read);
+ u32 read = file->Read(naomi_default_eeprom, game->blobs[romid].length);
+ if (config::GGPOEnable)
+ md5.add(naomi_default_eeprom, game->blobs[romid].length);
+ DEBUG_LOG(NAOMI, "Loaded %s: %x bytes default eeprom", game->blobs[romid].filename, read);
+ }
}
break;
@@ -774,7 +787,8 @@ int naomi_cart_GetPlatform(const char *path)
else
{
#ifdef NAOMI_MULTIBOARD
- if (game->multiboard > 0)
+ if (game->multiboard > 0
+ && (!strncmp("f355", game->name, 4) || config::MultiboardSlaves == 2))
settings.naomi.multiboard = true;
#endif
return DC_PLATFORM_NAOMI;
@@ -911,7 +925,7 @@ u32 NaomiCartridge::ReadMem(u32 address, u32 size)
return (u16)DmaCount;
case NAOMI_BOARDID_READ_addr:
- return NaomiGameIDRead() ? 0x8000 : 0x0000;
+ return NaomiGameIDRead();
case NAOMI_DMA_OFFSETH_addr:
return DmaOffset >> 16;
@@ -919,7 +933,6 @@ u32 NaomiCartridge::ReadMem(u32 address, u32 size)
return DmaOffset & 0xFFFF;
case NAOMI_BOARDID_WRITE_addr:
- DEBUG_LOG(NAOMI, "naomi ReadBoardId: %X, %d", address, size);
return 1;
default:
@@ -999,9 +1012,7 @@ void NaomiCartridge::WriteMem(u32 address, u32 data, u32 size)
NaomiGameIDWrite((u16)data);
return;
- //This should be valid
case NAOMI_BOARDID_READ_addr:
- DEBUG_LOG(NAOMI, "naomi WriteMem: %X <= %X, %d", address, data, size);
return;
case NAOMI_LED_addr:
diff --git a/core/hw/naomi/naomi_roms.cpp b/core/hw/naomi/naomi_roms.cpp
index e2f08c000..abdfe0c83 100644
--- a/core/hw/naomi/naomi_roms.cpp
+++ b/core/hw/naomi/naomi_roms.cpp
@@ -947,14 +947,12 @@ const Game Games[] =
{ "mpr-21738.ic11", 0x5800000, 0x800000 },
// on-cart X76F100 eeprom contents
- //ROM_REGION( 0x84, "naomibd_eeprom", 0 )
- //ROM_LOAD( "airlinepdx.sf", 0x000000, 0x000084, CRC(404b2add) SHA1(540c8474806775646ace111a2993397b1419fee3) )
-
- { NULL, 0, 0 },
+ { "airlinepdx.sf", 0x000000, 0x000084, 0x404b2add, Eeprom },
},
NULL,
&alpilot_inputs,
- alpilot_eeprom_dump
+ alpilot_eeprom_dump,
+ 2,
},
// Airline Pilots (Japan, Rev A)
{
@@ -983,7 +981,8 @@ const Game Games[] =
},
NULL,
&alpilot_inputs,
- alpilot_eeprom_dump
+ alpilot_eeprom_dump,
+ 2,
},
// Alien Front (Rev T)
{
@@ -1387,7 +1386,11 @@ const Game Games[] =
{ "mpr-22237.ic15s", 0x7800000, 0x800000 },
{ "mpr-22238.ic16s", 0x8000000, 0x800000 },
{ NULL, 0, 0 },
- }
+ },
+ nullptr,
+ nullptr,
+ nullptr,
+ 1,
},
// Derby Owners Club (JPN, USA, EXP, KOR, AUS) (Rev B)
{
@@ -1416,7 +1419,11 @@ const Game Games[] =
{ "mpr-22097.ic13s", 0x6800000, 0x0800000 },
{ "mpr-22098.ic14s", 0x7000000, 0x0800000 },
{ NULL, 0, 0 },
- }
+ },
+ nullptr,
+ nullptr,
+ nullptr,
+ 1,
},
// Derby Owners Club II (JPN, USA, EXP, KOR, AUS) (Rev B)
{
@@ -1442,7 +1449,11 @@ const Game Games[] =
{ "mpr-22304.ic10", 0x9800000, 0x1000000 },
{ "mpr-22305.ic11", 0xa800000, 0x1000000 },
{ NULL, 0, 0 },
- }
+ },
+ nullptr,
+ nullptr,
+ nullptr,
+ 1,
},
// Derby Owners Club World Edition (JPN, USA, EXP, KOR, AUS) (Rev D)
{
@@ -1465,6 +1476,10 @@ const Game Games[] =
{ "mpr-22338.ic7", 0x6800000, 0x1000000, 0x4bda7303 },
{ NULL, 0, 0, 0x00000000 },
},
+ nullptr,
+ nullptr,
+ nullptr,
+ 1,
},
// Derby Owners Club World Edition (Rev A)
{
@@ -1486,7 +1501,11 @@ const Game Games[] =
{ "mpr-22333.ic6", 0x5800000, 0x1000000, 0x96f324aa },
{ "mpr-22334.ic7", 0x6800000, 0x1000000, 0x5389b05a },
{ NULL, 0, 0, 0x00000000 },
- }
+ },
+ nullptr,
+ nullptr,
+ nullptr,
+ 1,
},
// Derby Owners Club World Edition (Rev B)
{
@@ -1508,7 +1527,11 @@ const Game Games[] =
{ "mpr-22333.ic6", 0x5800000, 0x1000000, 0x96f324aa },
{ "mpr-22334.ic7", 0x6800000, 0x1000000, 0x5389b05a },
{ NULL, 0, 0, 0x00000000 },
- }
+ },
+ nullptr,
+ nullptr,
+ nullptr,
+ 1,
},
// Derby Owners Club World Edition (Rev C)
{
@@ -1530,7 +1553,11 @@ const Game Games[] =
{ "mpr-22333.ic6", 0x5800000, 0x1000000, 0x96f324aa },
{ "mpr-22334.ic7", 0x6800000, 0x1000000, 0x5389b05a },
{ NULL, 0, 0, 0x00000000 },
- }
+ },
+ nullptr,
+ nullptr,
+ nullptr,
+ 1,
},
// Derby Owners Club World Edition (Rev T)
{
@@ -1552,6 +1579,10 @@ const Game Games[] =
{ "mpr-22333.ic6", 0x5800000, 0x1000000, 0x96f324aa },
{ "mpr-22334.ic7", 0x6800000, 0x1000000, 0x5389b05a },
},
+ nullptr,
+ nullptr,
+ nullptr,
+ 1,
},
// Dead or Alive 2 (JPN, USA, EXP, KOR, AUS)
{
@@ -3464,6 +3495,8 @@ const Game Games[] =
},
nullptr,
&sstrkfgt_inputs,
+ nullptr,
+ 2,
},
// Sega Strike Fighter (Rev A, no training mode)
{
@@ -3501,6 +3534,8 @@ const Game Games[] =
},
nullptr,
&sstrkfgt_inputs,
+ nullptr,
+ 2,
},
// Idol Janshi Suchie-Pai 3 (JPN)
{
diff --git a/core/hw/naomi/systemsp.cpp b/core/hw/naomi/systemsp.cpp
index 18b739f67..ba07d1fa5 100644
--- a/core/hw/naomi/systemsp.cpp
+++ b/core/hw/naomi/systemsp.cpp
@@ -37,11 +37,6 @@
#include "stdclass.h"
#include
-#ifdef DEBUG_EEPROM
-#define EEPROM_LOG(...) DEBUG_LOG(FLASHROM, __VA_ARGS__)
-#else
-#define EEPROM_LOG(...)
-#endif
#ifdef DEBUG_SERIAL
#define SERIAL_LOG(...) DEBUG_LOG(NAOMI, __VA_ARGS__)
#else
@@ -68,100 +63,6 @@ namespace systemsp
SystemSpCart *SystemSpCart::Instance;
-void SerialEeprom93Cxx::writeCLK(int state)
-{
- // CS asserted and CLK rising
- if (clk == 0 && state == 1 && cs == 1)
- {
- if (dataOutBits > 0)
- dataOutBits--;
- if (dataOutBits == 0)
- {
- if (command.empty() && di == 0)
- INFO_LOG(NAOMI, "serial eeprom: Ignoring bit 0 (start bit must be 1)");
- else
- {
- command.push_back(di);
- if (command.size() == 9)
- {
- int opCode = (int)command[1] * 2 + (int)command[2];
- //EEPROM_LOG("Received command: %d", opCode);
- switch (opCode)
- {
- case 0: // write enable/disable, erase all, write all
- {
- int subCode = (int)command[3] * 2 + (int)command[4];
- switch (subCode)
- {
- case 0: // disable write
- EEPROM_LOG("serial eeprom: EWDS");
- writeEnable = false;
- command.clear();
- break;
- case 1: // write all
- expected = 3 + 6 + 16; // 6 bits of address, 16 bits of data
- break;
- case 2: // erase all
- EEPROM_LOG("serial eeprom: ERAL");
- if (writeEnable)
- memset(data, 0xff, size);
- command.clear();
- break;
- case 3: // enable write
- EEPROM_LOG("serial eeprom: EWEN");
- writeEnable = true;
- command.clear();
- break;
- }
- }
- break;
- case 1: // write
- expected = 3 + 6 + 16; // 6 bits of address, 16 bits of data
- break;
- case 2: // read
- dataOut = Read(getCommandAddress() * 2, 2);
- dataOutBits = 17; // actually 16 but 0 means no data
- EEPROM_LOG("serial eeprom: READ %x: %x", getCommandAddress(), dataOut);
- command.clear();
- break;
- case 3: // erase
- EEPROM_LOG("serial eeprom: ERASE %x", getCommandAddress());
- if (writeEnable)
- *(u16 *)&data[(getCommandAddress() * 2) & mask] = 0xffff;
- command.clear();
- break;
- }
- }
- else if (expected > 0 && (int)command.size() == expected)
- {
- int opCode = (int)command[1] * 2 + (int)command[2];
- //EEPROM_LOG("Executing write command: %d", opCode);
- switch (opCode)
- {
- case 0: // write all
- {
- u16 v = getCommandData();
- EEPROM_LOG("serial eeprom: WRAL = %x", v);
- if (writeEnable)
- for (u32 i = 0; i < size; i += 2)
- *(u16 *)&data[i & mask] = v;
- }
- break;
- case 1: // write
- EEPROM_LOG("serial eeprom: WRITE %x = %x", getCommandAddress(), getCommandData());
- if (writeEnable)
- *(u16 *)&data[(getCommandAddress() * 2) & mask] = getCommandData();
- break;
- }
- command.clear();
- expected = 0;
- }
- }
- }
- }
- clk = state;
-}
-
//
// RS232C I/F board (838-14244) connected to RFID Chip R/W board (838-14243)
//
@@ -1237,10 +1138,25 @@ void SystemSpCart::updateInterrupt(u32 mask)
asic_CancelInterrupt(holly_EXP_PCI);
}
-SystemSpCart::SystemSpCart(u32 size) : M4Cartridge(size), eeprom(128), uart1(this, 1), uart2(this, 2)
+SystemSpCart::SystemSpCart(u32 size) : M4Cartridge(size), uart1(this, 1), uart2(this, 2)
{
schedId = sh4_sched_register(0, schedCallback, this);
Instance = this;
+ // mb_serial.ic57
+ static const u8 eepromData[0x80] = {
+ 0xf5, 0x90, 0x53, 0x45, 0x47, 0x41, 0x20, 0x45, 0x4e, 0x54, 0x45, 0x52,
+ 0x50, 0x52, 0x49, 0x53, 0x45, 0x53, 0x2c, 0x4c, 0x54, 0x44, 0x2e, 0x00,
+ 0x4e, 0x41, 0x4f, 0x4d, 0x49, 0x00, 0x00, 0x00, 0x41, 0x41, 0x46, 0x45,
+ 0x30, 0x31, 0x44, 0x31, 0x35, 0x39, 0x32, 0x34, 0x38, 0x31, 0x36, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+ eeprom.Load(eepromData, sizeof(eepromData));
}
SystemSpCart::~SystemSpCart()
@@ -1507,7 +1423,7 @@ void SystemSpCart::Serialize(Serializer& ser) const
sh4_sched_serialize(ser, schedId);
uart1.serialize(ser);
uart2.serialize(ser);
- eeprom.serialize(ser);
+ eeprom.Serialize(ser);
ser << bank;
ser << ata.features;
ser << ata.cylinder;
@@ -1534,7 +1450,7 @@ void SystemSpCart::Deserialize(Deserializer& deser)
sh4_sched_deserialize(deser, schedId);
uart1.deserialize(deser);
uart2.deserialize(deser);
- eeprom.deserialize(deser);
+ eeprom.Deserialize(deser);
deser >> bank;
deser >> ata.features;
deser >> ata.cylinder;
diff --git a/core/hw/naomi/systemsp.h b/core/hw/naomi/systemsp.h
index 800613681..d41e60f85 100644
--- a/core/hw/naomi/systemsp.h
+++ b/core/hw/naomi/systemsp.h
@@ -21,7 +21,7 @@
#include "emulator.h"
#include "hw/hwreg.h"
#include "hw/naomi/m4cartridge.h"
-#include "hw/flashrom/flashrom.h"
+#include "hw/flashrom/at93cxx.h"
#include "serialize.h"
#include
#include
@@ -36,109 +36,6 @@ T readMemArea0(u32 addr);
template
void writeMemArea0(u32 addr, T v);
-//
-// rom board eeprom
-//
-class SerialEeprom93Cxx : public WritableChip
-{
-public:
- SerialEeprom93Cxx(u32 size) : WritableChip(size) {
- memset(data, 0xff, size);
- }
-
- // combined DO + READY/BUSY
- int readDO()
- {
- if (dataOutBits > 0)
- // DO
- return (dataOut >> (dataOutBits - 1)) & 1;
- else
- // Ready
- return 1;
- }
-
- // chip select (active high)
- void writeCS(int state) {
- cs = state;
- }
-
- // clock
- void writeCLK(int state);
-
- // data in
- void writeDI(int state) {
- di = state;
- }
-
- void Write(u32 addr, u32 data, u32 size) override {
- die("Unsupported");
- }
-
- void serialize(Serializer& ser) const
- {
- ser << cs;
- ser << clk;
- ser << di;
- ser << (u32)command.size();
- for (bool b : command)
- ser << b;
- ser << expected;
- ser << writeEnable;
- ser << dataOut;
- ser << dataOutBits;
- }
- void deserialize(Deserializer& deser)
- {
- deser >> cs;
- deser >> clk;
- deser >> di;
- u32 size;
- deser >> size;
- command.resize(size);
- for (u32 i = 0; i < size; i++) {
- bool b;
- deser >> b;
- command[i] = b;
- }
- deser >> expected;
- deser >> writeEnable;
- deser >> dataOut;
- deser >> dataOutBits;
- }
-
-private:
- u8 getCommandAddress() const
- {
- verify(command.size() >= 9);
- u8 addr = 0;
- for (int i = 3; i < 9; i++) {
- addr <<= 1;
- addr |= command[i];
- }
- return addr;
- }
-
- u16 getCommandData() const
- {
- verify(command.size() >= 25);
- u16 v = 0;
- for (int i = 9; i < 25; i++) {
- v <<= 1;
- v |= command[i];
- }
- return v;
- }
-
- u8 cs = 0;
- u8 clk = 0;
- u8 di = 0;
- std::vector command;
- int expected = 0;
- bool writeEnable = false;
- u16 dataOut = 0;
- u8 dataOutBits = 0;
-};
-
class SystemSpCart;
// rom board custom UART ports
@@ -293,7 +190,7 @@ private:
std::unique_ptr hunkmem;
u32 hunknum = ~0;
- SerialEeprom93Cxx eeprom;
+ AT93C46SerialEeprom eeprom;
SerialPort uart1;
SerialPort uart2;
u16 bank = 0;
diff --git a/core/hw/pvr/elan.cpp b/core/hw/pvr/elan.cpp
index 935b76589..dacd7e98b 100644
--- a/core/hw/pvr/elan.cpp
+++ b/core/hw/pvr/elan.cpp
@@ -252,7 +252,6 @@ static glm::mat4x4 curMatrix;
static int taMVMatrix = -1;
static int taNormalMatrix = -1;
static glm::mat4 projectionMatrix;
-static int taProjMatrix = -1;
static LightModel *curLightModel;
static ElanBase *curLights[MAX_LIGHTS];
static float nearPlane = 0.001f;
@@ -273,7 +272,6 @@ struct State
u32 gmp = Null;
u32 instance = Null;
- u32 projMatrix = Null;
u32 lightModel = Null;
u32 lights[MAX_LIGHTS] = {
Null, Null, Null, Null, Null, Null, Null, Null,
@@ -282,15 +280,17 @@ struct State
bool lightModelUpdated = false;
float envMapUOffset = 0.f;
float envMapVOffset = 0.f;
+ float projMatrix[4] = { 579.411194f, -320.f, -579.411194f, -240.f };
+ int projMatrixIdx = -1;
void reset()
{
gmp = Null;
instance = Null;
- projMatrix = Null;
lightModel = Null;
for (auto& light : lights)
light = Null;
+ projMatrixIdx = -1;
update();
if (isDirectX(config::RendererType))
packColor = packColorBGRA;
@@ -347,30 +347,43 @@ struct State
void setProjectionMatrix(void *p)
{
- projMatrix = elanRamAddress(p);
+ ProjMatrix *pm = (ProjMatrix *)&RAM[elanRamAddress(p)];
+ projMatrix[0] = pm->fx;
+ projMatrix[1] = pm->tx;
+ projMatrix[2] = pm->fy;
+ projMatrix[3] = pm->ty;
+ DEBUG_LOG(PVR, "Proj matrix x: %f %f y: %f %f near %f far %f", pm->fx, pm->tx, pm->fy, pm->ty, nearPlane, farPlane);
updateProjectionMatrix();
}
void updateProjectionMatrix()
{
- if (projMatrix == Null)
- {
- taProjMatrix = -1;
- return;
- }
- ProjMatrix *pm = (ProjMatrix *)&RAM[projMatrix];
- DEBUG_LOG(PVR, "Proj matrix x: %f %f y: %f %f near %f far %f", pm->fx, pm->tx, pm->fy, pm->ty, nearPlane, farPlane);
// fx = -m00 * w/2
// tx = -m20 * w/2 + left + w/2
// fy = -m11 * h/2
// ty = -m21 * h/2 + top + h/2
projectionMatrix = glm::mat4(
- -pm->fx, 0, 0, 0,
- 0, pm->fy, 0, 0,
- -pm->tx, -pm->ty, -1, -1,
- 0, 0, 0, 0
+ -projMatrix[0], 0, 0, 0,
+ 0, projMatrix[2], 0, 0,
+ -projMatrix[1], -projMatrix[3], -1, -1,
+ 0, 0, 0, 0
);
- taProjMatrix = ta_add_matrix(glm::value_ptr(projectionMatrix));
+ projMatrixIdx = ta_add_matrix(glm::value_ptr(projectionMatrix));
+ }
+
+ void resetProjectionMatrix()
+ {
+ projMatrix[0] = 579.411194f;
+ projMatrix[1] = -320.f;
+ projMatrix[2] = -579.411194f;
+ projMatrix[3] = -240.f;
+ }
+
+ int getProjectionMatrixIndex()
+ {
+ if (projMatrixIdx == -1)
+ updateProjectionMatrix();
+ return projMatrixIdx;
}
void setGMP(void *p)
@@ -470,7 +483,6 @@ struct State
void update()
{
updateMatrix();
- updateProjectionMatrix();
updateGMP();
updateLightModel();
for (u32 i = 0; i < MAX_LIGHTS; i++)
@@ -498,9 +510,11 @@ struct State
void deserialize(Deserializer& deser)
{
+ projMatrixIdx = -1;
if (deser.version() < Deserializer::V24)
{
reset();
+ resetProjectionMatrix();
return;
}
ta_parse_reset();
@@ -509,7 +523,14 @@ struct State
ta_set_list_type(listType);
deser >> gmp;
deser >> instance;
- deser >> projMatrix;
+ if (deser.version() < Deserializer::V40)
+ {
+ deser.skip(); // projMatrix address
+ resetProjectionMatrix();
+ }
+ else {
+ deser >> projMatrix;
+ }
u32 tileclip;
deser >> tileclip;
ta_set_tileclip(tileclip);
@@ -1087,7 +1108,7 @@ static void sendMVPolygon(ICHList *list, const T *vtx, bool needClipping)
mvp.isp.VolumeLast = list->pcw.volume;
mvp.isp.DepthMode &= 3;
mvp.mvMatrix = taMVMatrix;
- mvp.projMatrix = taProjMatrix;
+ mvp.projMatrix = state.getProjectionMatrixIndex();
ta_add_poly(list->pcw.listType, mvp);
ModifierVolumeClipper clipper(needClipping);
@@ -1242,7 +1263,7 @@ static void setStateParams(PolyParam& pp, const ICHList *list)
sendLights();
pp.mvMatrix = taMVMatrix;
pp.normalMatrix = taNormalMatrix;
- pp.projMatrix = taProjMatrix;
+ pp.projMatrix = state.getProjectionMatrixIndex();
pp.lightModel = taLightModel;
pp.envMapping[0] = false;
pp.envMapping[1] = false;
@@ -1279,7 +1300,7 @@ static void setStateParams(PolyParam& pp, const ICHList *list)
pp.tsp1.full ^= modelTSP.full;
// projFlip is for left-handed projection matrices (initd rear view mirror)
- bool projFlip = taProjMatrix != -1 && std::signbit(projectionMatrix[0][0]) == std::signbit(projectionMatrix[1][1]);
+ bool projFlip = std::signbit(projectionMatrix[0][0]) == std::signbit(projectionMatrix[1][1]);
pp.isp.CullMode ^= (u32)cullingReversed ^ (u32)projFlip;
pp.pcw.Shadow ^= shadowedVolume;
if (pp.pcw.Shadow == 0 || pp.pcw.Volume == 0)
@@ -1751,6 +1772,7 @@ void reset(bool hard)
{
memset(RAM, 0, ERAM_SIZE);
state.reset();
+ state.resetProjectionMatrix();
}
}
diff --git a/core/hw/pvr/ta_vtx.cpp b/core/hw/pvr/ta_vtx.cpp
index 0d7d87d4a..41dd5f472 100644
--- a/core/hw/pvr/ta_vtx.cpp
+++ b/core/hw/pvr/ta_vtx.cpp
@@ -1319,24 +1319,13 @@ const float identityMat[] {
0.f, 0.f, 0.f, 1.f
};
-const float defaultProjMat[] {
- 579.411194f, 0.f, 0.f, 0.f,
- 0.f, -579.411194f, 0.f, 0.f,
- -320.f, -240.f, -1.f, -1.f,
- 0.f, 0.f, 0.f, 0.f
-};
-
constexpr int IdentityMatIndex = 0;
-constexpr int DefaultProjMatIndex = 1;
constexpr int NoLightIndex = 0;
static void setDefaultMatrices()
{
if (ta_ctx->rend.matrices.empty())
- {
ta_ctx->rend.matrices.push_back(*(N2Matrix *)identityMat);
- ta_ctx->rend.matrices.push_back(*(N2Matrix *)defaultProjMat);
- }
}
static void setDefaultLight()
@@ -1363,8 +1352,6 @@ void ta_add_poly(const PolyParam& pp)
n2CurrentPP->mvMatrix = IdentityMatIndex;
if (n2CurrentPP->normalMatrix == -1)
n2CurrentPP->normalMatrix = IdentityMatIndex;
- if (n2CurrentPP->projMatrix == -1)
- n2CurrentPP->projMatrix = DefaultProjMatIndex;
setDefaultLight();
if (n2CurrentPP->lightModel == -1)
n2CurrentPP->lightModel = NoLightIndex;
@@ -1397,8 +1384,6 @@ void ta_add_poly(int listType, const ModifierVolumeParam& mvp)
setDefaultMatrices();
if (n2CurrentMVP->mvMatrix == -1)
n2CurrentMVP->mvMatrix = IdentityMatIndex;
- if (n2CurrentMVP->projMatrix == -1)
- n2CurrentMVP->projMatrix = DefaultProjMatIndex;
vd_ctx = nullptr;
}
diff --git a/core/hw/sh4/modules/bsc.cpp b/core/hw/sh4/modules/bsc.cpp
index 9f372b7c0..04ece27ff 100644
--- a/core/hw/sh4/modules/bsc.cpp
+++ b/core/hw/sh4/modules/bsc.cpp
@@ -9,56 +9,46 @@
BSCRegisters bsc;
-template
-static void write_BSC_PCTRA(u32 addr, T data)
+//u32 port_out_data;
+static void write_BSC_PDTRA_arcade(u32 addr, u16 data)
{
- BSC_PCTRA.full = data;
- if (settings.platform.isNaomi())
- NaomiBoardIDWriteControl((u16)data);
- //else
- //printf("C:BSC_PCTRA = %08X\n",data);
+ BSC_PDTRA.full = data;
+ NaomiBoardIDWrite(data);
}
-//u32 port_out_data;
static void write_BSC_PDTRA(u32 addr, u16 data)
{
BSC_PDTRA.full = data;
- //printf("D:BSC_PDTRA = %04x\n", data);
+}
- if (settings.platform.isNaomi())
- NaomiBoardIDWrite(data);
+static u16 read_BSC_PDTRA_arcade(u32 addr)
+{
+ return NaomiBoardIDRead();
}
static u16 read_BSC_PDTRA(u32 addr)
{
- if (settings.platform.isNaomi())
- {
- return NaomiBoardIDRead();
- }
+ /* as seen on chankast */
+ u32 tpctra = BSC_PCTRA.full;
+ u32 tpdtra = BSC_PDTRA.full;
+
+ u16 tfinal = 0;
+ // magic values
+ if ((tpctra & 0xf) == 0x8)
+ tfinal = 3;
+ else if ((tpctra & 0xf) == 0xB)
+ tfinal = 3;
else
- {
- /* as seen on chankast */
- u32 tpctra = BSC_PCTRA.full;
- u32 tpdtra = BSC_PDTRA.full;
+ tfinal = 0;
- u16 tfinal = 0;
- // magic values
- if ((tpctra & 0xf) == 0x8)
- tfinal = 3;
- else if ((tpctra & 0xf) == 0xB)
- tfinal = 3;
- else
- tfinal = 0;
+ if ((tpctra & 0xf) == 0xB && (tpdtra & 0xf) == 2)
+ tfinal = 0;
+ else if ((tpctra & 0xf) == 0xC && (tpdtra & 0xf) == 2)
+ tfinal = 3;
- if ((tpctra & 0xf) == 0xB && (tpdtra & 0xf) == 2)
- tfinal = 0;
- else if ((tpctra & 0xf) == 0xC && (tpdtra & 0xf) == 2)
- tfinal = 3;
+ tfinal |= config::Cable << 8;
- tfinal |= config::Cable << 8;
-
- return tfinal;
- }
+ return tfinal;
}
void BSCRegisters::init()
@@ -101,10 +91,10 @@ void BSCRegisters::init()
//BSC PCTRA 0xFF80002C 0x1F80002C 32 0x00000000 Held Held Held Bclk
// Naomi BIOS writes u16 in this register but ignoring them doesn't seem to hurt
- setWriteHandler(write_BSC_PCTRA);
+ setRW();
//BSC PDTRA 0xFF800030 0x1F800030 16 Undefined Held Held Held Bclk
- setHandlers(read_BSC_PDTRA, write_BSC_PDTRA);
+ setRW();
//BSC PCTRB 0xFF800040 0x1F800040 32 0x00000000 Held Held Held Bclk
setRW();
@@ -149,4 +139,9 @@ void BSCRegisters::reset()
BSC_WCR3.full = 0x07777777;
BSC_RFCR.full = 17;
+
+ if (settings.platform.isNaomi() || settings.platform.isSystemSP())
+ setHandlers(read_BSC_PDTRA_arcade, write_BSC_PDTRA_arcade);
+ else
+ setHandlers(read_BSC_PDTRA, write_BSC_PDTRA);
}
diff --git a/core/hw/sh4/modules/serial.cpp b/core/hw/sh4/modules/serial.cpp
index 0e4f6ee0a..39421b4b8 100644
--- a/core/hw/sh4/modules/serial.cpp
+++ b/core/hw/sh4/modules/serial.cpp
@@ -33,7 +33,7 @@ static void updateInterrupts()
// SCIF SCFTDR2
void SCIFSerialPort::writeData(u32 addr, u8 data)
{
- INFO_LOG(COMMON, "serial out %02x %c", data, data);
+ //DEBUG_LOG(COMMON, "serial out %02x %c", data, data);
if (Instance().pipe != nullptr)
Instance().pipe->write(data);
diff --git a/core/serialize.h b/core/serialize.h
index 5862a8cc2..5f98bd8dc 100644
--- a/core/serialize.h
+++ b/core/serialize.h
@@ -65,7 +65,8 @@ public:
V37,
V38,
V39,
- Current = V39,
+ V40,
+ Current = V40,
Next = Current + 1,
};