From 129fff1c2a3c0ff9dcf3eb92f919ab3e6beb0b9d Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Fri, 25 Aug 2023 17:01:40 +0200 Subject: [PATCH] naomi: x76f100 and at93cxx implementation. naomi2 elan fix proper emulation of x76f100 security eeprom and at93cxx serial eeprom elan: don't reset projection matrix at end of frame. Issue #1177 --- CMakeLists.txt | 4 + core/hw/flashrom/at93cxx.cpp | 152 +++++++++++++ core/hw/flashrom/at93cxx.h | 106 +++++++++ core/hw/flashrom/x76f100.cpp | 282 +++++++++++++++++++++++ core/hw/flashrom/x76f100.h | 107 +++++++++ core/hw/naomi/naomi.cpp | 404 ++++++--------------------------- core/hw/naomi/naomi.h | 6 +- core/hw/naomi/naomi_cart.cpp | 35 ++- core/hw/naomi/naomi_roms.cpp | 59 ++++- core/hw/naomi/systemsp.cpp | 120 ++-------- core/hw/naomi/systemsp.h | 107 +-------- core/hw/pvr/elan.cpp | 64 ++++-- core/hw/pvr/ta_vtx.cpp | 15 -- core/hw/sh4/modules/bsc.cpp | 69 +++--- core/hw/sh4/modules/serial.cpp | 2 +- core/serialize.h | 3 +- 16 files changed, 893 insertions(+), 642 deletions(-) create mode 100644 core/hw/flashrom/at93cxx.cpp create mode 100644 core/hw/flashrom/at93cxx.h create mode 100644 core/hw/flashrom/x76f100.cpp create mode 100644 core/hw/flashrom/x76f100.h 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, };