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
This commit is contained in:
parent
10b13dfe9c
commit
129fff1c2a
|
@ -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
|
||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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;
|
||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "flashrom.h"
|
||||
#include <vector>
|
||||
|
||||
//
|
||||
// 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<bool> 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) {}
|
||||
};
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 <string.h>
|
||||
|
||||
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;
|
||||
};
|
|
@ -19,21 +19,15 @@
|
|||
#include "hw/sh4/modules/modules.h"
|
||||
#include "rend/gui.h"
|
||||
#include "printer.h"
|
||||
#include "hw/flashrom/x76f100.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
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<rounds;++i)
|
||||
{
|
||||
if(CRC&0x80000000)
|
||||
CRC=(CRC<<1)+Magic;
|
||||
else
|
||||
CRC=(CRC<<1);
|
||||
}
|
||||
return CRC;
|
||||
}
|
||||
|
||||
static unsigned short CRCSerial(const u8 *Serial,unsigned int len)
|
||||
{
|
||||
unsigned int CRC=0xDEBDEB00;
|
||||
unsigned int i;
|
||||
|
||||
for(i=0;i<len;++i)
|
||||
{
|
||||
unsigned char c=Serial[i];
|
||||
//CRC&=0xFFFFFF00;
|
||||
CRC|=c;
|
||||
CRC=ShiftCRC(CRC,8);
|
||||
}
|
||||
CRC=ShiftCRC(CRC,8);
|
||||
return (u16)(CRC>>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<u32>(); // GSerialBuffer
|
||||
deser.skip<u32>(); // BSerialBuffer
|
||||
deser.skip<int>(); // GBufPos
|
||||
deser.skip<int>(); // BBufPos
|
||||
deser.skip<int>(); // GState
|
||||
deser.skip<int>(); // BState
|
||||
deser.skip<int>(); // GOldClk
|
||||
deser.skip<int>(); // BOldClk
|
||||
deser.skip<int>(); // BControl
|
||||
deser.skip<int>(); // BCmd
|
||||
deser.skip<int>(); // BLastCmd
|
||||
deser.skip<int>(); // GControl
|
||||
deser.skip<int>(); // GCmd
|
||||
deser.skip<int>(); // GLastCmd
|
||||
deser.skip<int>(); // SerStep
|
||||
deser.skip<int>(); // SerStep2
|
||||
deser.skip(69); // BSerial
|
||||
deser.skip(69); // GSerial
|
||||
}
|
||||
else
|
||||
{
|
||||
mainSerialId.deserialize(deser);
|
||||
romSerialId.deserialize(deser);
|
||||
}
|
||||
if (deser.version() < Deserializer::V36)
|
||||
{
|
||||
deser.skip<u32>(); // reg_dimm_command;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -37,11 +37,6 @@
|
|||
#include "stdclass.h"
|
||||
#include <errno.h>
|
||||
|
||||
#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;
|
||||
|
|
|
@ -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 <deque>
|
||||
#include <array>
|
||||
|
@ -36,109 +36,6 @@ T readMemArea0(u32 addr);
|
|||
template<typename T>
|
||||
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<bool> 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<u8[]> hunkmem;
|
||||
u32 hunknum = ~0;
|
||||
|
||||
SerialEeprom93Cxx eeprom;
|
||||
AT93C46SerialEeprom eeprom;
|
||||
SerialPort uart1;
|
||||
SerialPort uart2;
|
||||
u16 bank = 0;
|
||||
|
|
|
@ -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<u32>(); // 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,56 +9,46 @@
|
|||
|
||||
BSCRegisters bsc;
|
||||
|
||||
template<typename T>
|
||||
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<BSC_PCTRA_addr>(write_BSC_PCTRA<u32>);
|
||||
setRW<BSC_PCTRA_addr, u32>();
|
||||
|
||||
//BSC PDTRA 0xFF800030 0x1F800030 16 Undefined Held Held Held Bclk
|
||||
setHandlers<BSC_PDTRA_addr>(read_BSC_PDTRA, write_BSC_PDTRA);
|
||||
setRW<BSC_PDTRA_addr, u16>();
|
||||
|
||||
//BSC PCTRB 0xFF800040 0x1F800040 32 0x00000000 Held Held Held Bclk
|
||||
setRW<BSC_PCTRB_addr, u32, 0x000000ff>();
|
||||
|
@ -149,4 +139,9 @@ void BSCRegisters::reset()
|
|||
BSC_WCR3.full = 0x07777777;
|
||||
|
||||
BSC_RFCR.full = 17;
|
||||
|
||||
if (settings.platform.isNaomi() || settings.platform.isSystemSP())
|
||||
setHandlers<BSC_PDTRA_addr>(read_BSC_PDTRA_arcade, write_BSC_PDTRA_arcade);
|
||||
else
|
||||
setHandlers<BSC_PDTRA_addr>(read_BSC_PDTRA, write_BSC_PDTRA);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -65,7 +65,8 @@ public:
|
|||
V37,
|
||||
V38,
|
||||
V39,
|
||||
Current = V39,
|
||||
V40,
|
||||
Current = V40,
|
||||
|
||||
Next = Current + 1,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue