mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 05:45:38 +00:00
Encryption device emulation (thanks to MAME), fixed warnings in Model3.cpp, added a string formatter helper, and updated Win32 GCC Makefile.
This commit is contained in:
parent
c0f679479a
commit
6e5c301de8
|
@ -57,7 +57,8 @@ BOOST_INCLUDEPATH = /mingw64/boost_1_55_0
|
|||
#
|
||||
ifeq ($(strip $(BITS)),64)
|
||||
SDL_LIBPATH = /mingw64/lib64
|
||||
SDL_INCLUDEPATH = /mingw64/x86_64-w64-mingw32/include/SDL
|
||||
#SDL_INCLUDEPATH = /mingw64/x86_64-w64-mingw32/include/SDL
|
||||
SDL_INCLUDEPATH = /mingw64/SDL-1.2.15/include
|
||||
else
|
||||
SDL_LIBPATH = /mingw/lib
|
||||
SDL_INCLUDEPATH = /mingw/include/SDL
|
||||
|
@ -68,6 +69,7 @@ endif
|
|||
#
|
||||
ifeq ($(strip $(BITS)),64)
|
||||
WINSDK_LIBPATH = /Program\ Files/Microsoft\ SDKs/Windows/v7.0/Lib/x64
|
||||
#WINSDK_LIBPATH = /Program\ Files\ (x86)/Windows\ Kits/10/Lib/10.0.10586.0/um/x64
|
||||
else
|
||||
WINSDK_LIBPATH = /Program\ Files/Microsoft\ SDKs/Windows/v7.0/Lib
|
||||
endif
|
||||
|
@ -98,7 +100,7 @@ LD = g++
|
|||
COMPILER_FLAGS = -I$(SDL_INCLUDEPATH) -ISrc/ -ISrc/OSD/ -ISrc/OSD/SDL/ -ISrc/OSD/Windows/ -c -Wall -DSUPERMODEL_WIN32 -DGLEW_STATIC -O3
|
||||
CFLAGS = $(COMPILER_FLAGS)
|
||||
CPPFLAGS = $(COMPILER_FLAGS) -I$(BOOST_INCLUDEPATH) -std=c++11
|
||||
LFLAGS = -o $(OUTFILE) $(OBJ) -L$(SDL_LIBPATH) -lmingw32 -lSDLmain -lSDL -lopengl32 -lglu32 -ldinput8 -ldxguid -lole32 -loleaut32 -lz -l:$(WINSDK_LIBPATH)/WbemUuid.lib -s
|
||||
LFLAGS = -o $(OUTFILE) $(OBJ) -L$(SDL_LIBPATH) -lmingw32 -lSDLmain -lSDL -lopengl32 -lglu32 -ldinput8 -ldxguid -lole32 -loleaut32 -lwbemuuid -lz -s #-l:$(WINSDK_LIBPATH)/WbemUuid.lib -s
|
||||
|
||||
#
|
||||
# Build options...
|
||||
|
@ -131,7 +133,9 @@ OBJ = $(OBJ_DIR)/PPCDisasm.o $(OBJ_DIR)/Games.o $(OBJ_DIR)/Config.o $(OBJ_DIR)/I
|
|||
$(OBJ_DIR)/Outputs.o $(OBJ_DIR)/WinOutputs.o \
|
||||
$(OBJ_DIR)/amp_audio.o $(OBJ_DIR)/amp_dump.o $(OBJ_DIR)/amp_getbits.o $(OBJ_DIR)/amp_getdata.o $(OBJ_DIR)/amp_huffman.o \
|
||||
$(OBJ_DIR)/amp_layer2.o $(OBJ_DIR)/amp_layer3.o $(OBJ_DIR)/amp_misc2.o $(OBJ_DIR)/amp_position.o $(OBJ_DIR)/amp_transform.o \
|
||||
$(OBJ_DIR)/amp_util.o
|
||||
$(OBJ_DIR)/amp_util.o \
|
||||
$(OBJ_DIR)/Crypto.o \
|
||||
$(OBJ_DIR)/Format.o
|
||||
|
||||
|
||||
# If built-in debugger enabled, include all debugging classes
|
||||
|
@ -250,6 +254,9 @@ $(OBJ_DIR)/%.o: Src/OSD/Windows/%.cpp
|
|||
$(OBJ_DIR)/%.o: Src/Pkgs/%.c
|
||||
$(CC) $< $(CFLAGS) -o $(OBJ_DIR)/$(*F).o
|
||||
|
||||
$(OBJ_DIR)/%.o: Src/Util/%.cpp Src/Util/%.h
|
||||
$(CC) $< $(CPPFLAGS) -o $(OBJ_DIR)/$(*F).o
|
||||
|
||||
#
|
||||
# AMP MPEG decoder library
|
||||
#
|
||||
|
|
1031
Src/Model3/Crypto.cpp
Normal file
1031
Src/Model3/Crypto.cpp
Normal file
File diff suppressed because it is too large
Load diff
123
Src/Model3/Crypto.h
Normal file
123
Src/Model3/Crypto.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
** Supermodel
|
||||
** A Sega Model 3 Arcade Emulator.
|
||||
** Copyright 2011-2016 Bart Trzynadlowski, Nik Henson
|
||||
**
|
||||
** This file is part of Supermodel.
|
||||
**
|
||||
** Supermodel 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 3 of the License, or (at your option)
|
||||
** any later version.
|
||||
**
|
||||
** Supermodel 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 Supermodel. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
|
||||
/*
|
||||
* Crypto.h
|
||||
*
|
||||
* Header file for security board encryption device. This code was taken from
|
||||
* MAME (http://mamedev.org).
|
||||
*/
|
||||
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __SEGA315_5881_CRYPT__
|
||||
#define __SEGA315_5881_CRYPT__
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
class CBlockFile;
|
||||
|
||||
class CCrypto
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
CCrypto();
|
||||
|
||||
void SaveState(CBlockFile *SaveState);
|
||||
void LoadState(CBlockFile *SaveState);
|
||||
void Init(uint32_t encryptionKey, std::function<uint16_t(uint32_t)> ReadRAMCallback);
|
||||
void Reset();
|
||||
|
||||
|
||||
uint16_t Decrypt(uint8_t **base);
|
||||
void SetAddressLow(uint16_t data);
|
||||
void SetAddressHigh(uint16_t data);
|
||||
void SetSubKey(uint16_t data);
|
||||
|
||||
std::function<uint16_t(uint32_t)> m_read;
|
||||
|
||||
/*
|
||||
static void set_read_cb(device_t &device,sega_m2_read_delegate readcb)
|
||||
{
|
||||
sega_315_5881_crypt_device &dev = downcast<sega_315_5881_crypt_device &>(device);
|
||||
dev.m_read = readcb;
|
||||
}
|
||||
*/
|
||||
|
||||
private:
|
||||
|
||||
uint32_t key;
|
||||
|
||||
std::unique_ptr<uint8_t[]> buffer;
|
||||
std::unique_ptr<uint8_t[]> line_buffer;
|
||||
std::unique_ptr<uint8_t[]> line_buffer_prev;
|
||||
uint32_t prot_cur_address;
|
||||
uint16_t subkey, dec_hist;
|
||||
uint32_t dec_header;
|
||||
|
||||
bool enc_ready;
|
||||
|
||||
int buffer_pos, line_buffer_pos, line_buffer_size, buffer_bit, buffer_bit2;
|
||||
uint8_t buffer2[2];
|
||||
uint16_t buffer2a;
|
||||
|
||||
int block_size;
|
||||
int block_pos;
|
||||
int block_numlines;
|
||||
int done_compression;
|
||||
|
||||
struct sbox {
|
||||
uint8_t table[64];
|
||||
int inputs[6]; // positions of the inputs bits, -1 means no input except from key
|
||||
int outputs[2]; // positions of the output bits
|
||||
};
|
||||
|
||||
static const sbox fn1_sboxes[4][4];
|
||||
static const sbox fn2_sboxes[4][4];
|
||||
|
||||
static const int FN1GK = 38;
|
||||
static const int FN2GK = 32;
|
||||
static const int fn1_game_key_scheduling[FN1GK][2];
|
||||
static const int fn2_game_key_scheduling[FN2GK][2];
|
||||
static const int fn1_sequence_key_scheduling[20][2];
|
||||
static const int fn2_sequence_key_scheduling[16];
|
||||
static const int fn2_middle_result_scheduling[16];
|
||||
|
||||
static const uint8_t trees[9][2][32];
|
||||
|
||||
int feistel_function(int input, const struct sbox *sboxes, uint32_t subkeys);
|
||||
uint16_t block_decrypt(uint32_t game_key, uint16_t sequence_key, uint16_t counter, uint16_t data);
|
||||
|
||||
uint16_t get_decrypted_16();
|
||||
int get_compressed_bit();
|
||||
|
||||
void enc_start();
|
||||
void enc_fill();
|
||||
void line_fill();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
** Supermodel
|
||||
** A Sega Model 3 Arcade Emulator.
|
||||
** Copyright 2011 Bart Trzynadlowski, Nik Henson
|
||||
** Copyright 2011-2016 Bart Trzynadlowski, Nik Henson
|
||||
**
|
||||
** This file is part of Supermodel.
|
||||
**
|
||||
|
@ -27,8 +27,9 @@
|
|||
* To-Do List
|
||||
* ----------
|
||||
* - Save state format has changed slightly. No longer need dmaUnknownRegister
|
||||
* in Real3D.cpp. PowerPC timing variables have changed. Before 0.3a
|
||||
* release, important to change format version #.
|
||||
* in Real3D.cpp and security board-related variable was added to Model 3
|
||||
* state. PowerPC timing variables have changed. Before 0.3a release,
|
||||
* important to change format version #.
|
||||
* - ROM sets should probably be handled with a class that manages ROM
|
||||
* loading, the game list, as well as ROM patching
|
||||
* - Wrap up CPU emulation inside a class.
|
||||
|
@ -184,6 +185,16 @@
|
|||
* G32 ---
|
||||
* G31 Right Turbo
|
||||
* G30 Right Shot Trigger
|
||||
*
|
||||
* Misc. Notes
|
||||
* -----------
|
||||
*
|
||||
* daytona2:
|
||||
* - Base address of program in CROM: 0x600000
|
||||
* - 0x10019E is the location in RAM which contains link type.
|
||||
* - Region menu can be accessed by entering test mode, holding start, and
|
||||
* pressing: green, green, blue, yellow, red, yellow, blue
|
||||
* (VR4,4,2,3,1,3,2).
|
||||
*/
|
||||
|
||||
#include <new>
|
||||
|
@ -191,6 +202,10 @@
|
|||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include "Supermodel.h"
|
||||
#include "Util/Format.h"
|
||||
#include <functional>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
/******************************************************************************
|
||||
Model 3 Inputs
|
||||
|
@ -636,130 +651,30 @@ void CModel3::WriteInputs(unsigned reg, UINT8 data)
|
|||
seems to help avoid this.
|
||||
******************************************************************************/
|
||||
|
||||
static const UINT16 spikeoutSecurity[] =
|
||||
uint16_t CModel3::ReadSecurityRAM(uint32_t addr)
|
||||
{
|
||||
0x0000,
|
||||
0x4f4d, 0x4544, 0x2d4c, 0x2033, 0x7953, 0x7473, 0x6d65, 0x5020,
|
||||
0x6f72, 0x7267, 0x6d61, 0x4320, 0x706f, 0x7279, 0x6769, 0x7468,
|
||||
0x2820, 0x2943, 0x3120, 0x3939, 0x2035, 0x4553, 0x4147, 0x4520,
|
||||
0x746e, 0x7265, 0x7270, 0x7369, 0x7365, 0x4c2c, 0x4454, 0x202e,
|
||||
0x6c41, 0x206c, 0x6972, 0x6867, 0x2074, 0x6572, 0x6573, 0x7672,
|
||||
0x6465, 0x202e, 0x2020, 0x0020
|
||||
};
|
||||
|
||||
static const UINT16 vs298Security[] =
|
||||
{
|
||||
0x0000, // dummy read
|
||||
0x4A20, 0x5041, 0x4E41, 0x4920, 0x4154, 0x594C, 0x4220, 0x4152, 0x4953, 0x204C,
|
||||
0x5241, 0x4547, 0x544E, 0x4E49, 0x2041, 0x4547, 0x4D52, 0x4E41, 0x2059, 0x4E45,
|
||||
0x4C47, 0x4E41, 0x2044, 0x454E, 0x4854, 0x5245, 0x414C, 0x444E, 0x2053, 0x5246,
|
||||
0x4E41, 0x4543, 0x4320, 0x4C4F, 0x4D4F, 0x4942, 0x2041, 0x4150, 0x4152, 0x5547,
|
||||
0x5941, 0x4220, 0x4C55, 0x4147, 0x4952, 0x2041, 0x5053, 0x4941, 0x204E, 0x5243,
|
||||
0x414F, 0x4954, 0x2041, 0x4542, 0x474C, 0x5549, 0x204D, 0x494E, 0x4547, 0x4952,
|
||||
0x2041, 0x4153, 0x4455, 0x2049, 0x4F4B, 0x4552, 0x2041, 0x4544, 0x4D4E, 0x5241,
|
||||
0x204B, 0x4F52, 0x414D, 0x494E, 0x2041, 0x4353, 0x544F, 0x414C, 0x444E, 0x5520,
|
||||
0x4153, 0x5320, 0x554F, 0x4854, 0x4641, 0x4952, 0x4143, 0x4D20, 0x5845, 0x4349,
|
||||
0x204F, 0x5559, 0x4F47, 0x4C53, 0x5641, 0x4149, 0x4620, 0x5F43, 0x4553, 0x4147
|
||||
};
|
||||
|
||||
static const UINT16 ecaSecurity[] =
|
||||
{
|
||||
0x0000,
|
||||
0x2d2f, 0x202d, 0x4d45, 0x5245, 0x4547, 0x434e, 0x2059, 0x4143,
|
||||
0x4c4c, 0x4120, 0x424d, 0x4c55, 0x4e41, 0x4543, 0x2d20, 0x0a2d,
|
||||
0x6f43, 0x7970, 0x6952, 0x6867, 0x2074, 0x4553, 0x4147, 0x4520,
|
||||
0x746e, 0x7265, 0x7270, 0x7369, 0x7365, 0x202c, 0x744c, 0x2e64,
|
||||
0x530a, 0x666f, 0x7774, 0x7261, 0x2065, 0x2652, 0x2044, 0x6544,
|
||||
0x7470, 0x202e, 0x3123, 0x660a, 0x726f, 0x7420, 0x7365, 0x0a74,
|
||||
};
|
||||
|
||||
static const UINT16 oceanhunSecurity[57] =
|
||||
{
|
||||
0x0000, // dummy read
|
||||
|
||||
0x3d3d, 0x203d, 0x434f, 0x4145, 0x204e, 0x5548, 0x544e, 0x5245,
|
||||
0x3d20, 0x3d3d, 0x430a, 0x706f, 0x5279, 0x6769, 0x7468, 0x5320,
|
||||
0x4745, 0x2041, 0x6e45, 0x6574, 0x7072, 0x6972, 0x6573, 0x2c73,
|
||||
0x4c20, 0x6474, 0x0a2e, 0x6d41, 0x7375, 0x6d65, 0x6e65, 0x2074,
|
||||
0x2652, 0x2044, 0x6544, 0x7470, 0x202e, 0x3123, 0x4b0a, 0x7a61,
|
||||
0x6e75, 0x7261, 0x2069, 0x7354, 0x6b75, 0x6d61, 0x746f, 0x206f,
|
||||
0x6553, 0x7463, 0x6f69, 0x206e, 0x614d, 0x616e, 0x6567, 0x0a72
|
||||
};
|
||||
|
||||
static const UINT16 swtrilgySecurity[57] =
|
||||
{
|
||||
0xffff,
|
||||
0x3d3d, 0x3d3d, 0x203d, 0x5453, 0x5241, 0x5720, 0x5241, 0x2053,
|
||||
0x3d3d, 0x3d3d, 0x0a3d, 0x6f43, 0x7970, 0x6952, 0x6867, 0x2074,
|
||||
0x4553, 0x4147, 0x4520, 0x746e, 0x7265, 0x7270, 0x7369, 0x7365,
|
||||
0x202c, 0x744c, 0x2e64, 0x410a, 0x756d, 0x6573, 0x656d, 0x746e,
|
||||
0x5220, 0x4426, 0x4420, 0x7065, 0x2e74, 0x2320, 0x3231, 0x4b0a,
|
||||
0x7461, 0x7573, 0x6179, 0x7573, 0x4120, 0x646e, 0x206f, 0x2026,
|
||||
0x614b, 0x6f79, 0x6f6b, 0x5920, 0x6d61, 0x6d61, 0x746f, 0x0a6f
|
||||
};
|
||||
|
||||
static const UINT16 fvipers2Security[65] =
|
||||
{
|
||||
0x2a2a,
|
||||
0x2a2a, 0x2a2a, 0x2a2a, 0x2a2a, 0x2a2a, 0x2a2a, 0x202a, 0x5b5b,
|
||||
0x4620, 0x6769, 0x7468, 0x6e69, 0x2067, 0x6956, 0x6570, 0x7372,
|
||||
0x3220, 0x5d20, 0x205d, 0x6e69, 0x3c20, 0x4d3c, 0x444f, 0x4c45,
|
||||
0x332d, 0x3e3e, 0x4320, 0x706f, 0x7279, 0x6769, 0x7468, 0x2820,
|
||||
0x2943, 0x3931, 0x3839, 0x5320, 0x4745, 0x2041, 0x6e45, 0x6574,
|
||||
0x7072, 0x6972, 0x6573, 0x2c73, 0x544c, 0x2e44, 0x2020, 0x4120,
|
||||
0x6c6c, 0x7220, 0x6769, 0x7468, 0x7220, 0x7365, 0x7265, 0x6576,
|
||||
0x2e64, 0x2a20, 0x2a2a, 0x2a2a, 0x2a2a, 0x2a2a, 0x2a2a, 0x2a2a
|
||||
};
|
||||
if (addr < 0x8000)
|
||||
return (*(uint32_t *) &securityRAM[addr * 4]) >> 16;
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT32 CModel3::ReadSecurity(unsigned reg)
|
||||
{
|
||||
UINT32 data;
|
||||
|
||||
switch (reg)
|
||||
{
|
||||
case 0x00: // Status
|
||||
return 0;
|
||||
case 0x1C: // Data
|
||||
if (!strcmp(Game->id, "spikeout") || !strcmp(Game->id, "spikeofe"))
|
||||
if (m_securityFirstRead)
|
||||
{
|
||||
data = (spikeoutSecurity[securityPtr++] << 16);
|
||||
securityPtr %= (sizeof(spikeoutSecurity)/sizeof(UINT16));
|
||||
m_securityFirstRead = false;
|
||||
return 0xFFFF0000;
|
||||
}
|
||||
else if (!strcmp(Game->id, "vs298") ||
|
||||
!strcmp(Game->id, "vs2v991") || !strcmp(Game->id, "vs299") ||
|
||||
!strcmp(Game->id, "vs299a") || !strcmp(Game->id, "vs299b"))
|
||||
{
|
||||
data = (vs298Security[securityPtr++] << 16);
|
||||
securityPtr %= (sizeof(vs298Security)/sizeof(UINT16));
|
||||
}
|
||||
else if (!strcmp(Game->id, "eca") || !strcmp(Game->id, "ecax"))
|
||||
{
|
||||
data = (ecaSecurity[securityPtr++] << 16);
|
||||
securityPtr %= (sizeof(ecaSecurity)/sizeof(UINT16));
|
||||
}
|
||||
else if (!strcmp(Game->id, "oceanhun"))
|
||||
{
|
||||
data = (oceanhunSecurity[securityPtr++] << 16);
|
||||
securityPtr %= (sizeof(oceanhunSecurity)/sizeof(UINT16));
|
||||
}
|
||||
else if (!strcmp(Game->id, "swtrilgy") || !strcmp(Game->id, "swtrilgya"))
|
||||
{
|
||||
data = (swtrilgySecurity[securityPtr++] << 16);
|
||||
securityPtr %= (sizeof(swtrilgySecurity)/sizeof(UINT16));
|
||||
}
|
||||
else if (!strcmp(Game->id, "fvipers2"))
|
||||
{
|
||||
data = (fvipers2Security[securityPtr++] << 16);
|
||||
securityPtr %= (sizeof(fvipers2Security)/sizeof(UINT16));
|
||||
}
|
||||
else if (!strcmp(Game->id, "von2"))
|
||||
data = 0xFFFFFFFF;
|
||||
else
|
||||
{
|
||||
data = 0xFFFFFFFF;
|
||||
DebugLog("Security read: reg=%X, PC=%08X, LR=%08X\n", reg, ppc_get_pc(), ppc_get_lr());
|
||||
uint8_t *base_ptr;
|
||||
return m_cryptoDevice.Decrypt(&base_ptr) << 16;
|
||||
}
|
||||
return data;
|
||||
default:
|
||||
DebugLog("Security read: reg=%X\n", reg);
|
||||
break;
|
||||
|
@ -770,7 +685,25 @@ UINT32 CModel3::ReadSecurity(unsigned reg)
|
|||
|
||||
void CModel3::WriteSecurity(unsigned reg, UINT32 data)
|
||||
{
|
||||
switch (reg)
|
||||
{
|
||||
case 0x10:
|
||||
case 0x14:
|
||||
m_cryptoDevice.SetAddressLow(0);
|
||||
m_cryptoDevice.SetAddressHigh(0);
|
||||
m_securityFirstRead = true;
|
||||
break;
|
||||
case 0x18:
|
||||
{
|
||||
uint16_t subKey = data >> 16;
|
||||
subKey = ((subKey & 0xFF00) >> 8) | ((subKey & 0x00FF) << 8);
|
||||
m_cryptoDevice.SetSubKey(subKey);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
DebugLog("Security write: reg=%X, data=%08X (PC=%08X, LR=%08X)\n", reg, data, ppc_get_pc(), ppc_get_lr());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -831,7 +764,6 @@ void CModel3::SetCROMBank(unsigned idx)
|
|||
idx = (~idx) & 0xF;
|
||||
cromBank = &crom[0x800000 + (idx*0x800000)];
|
||||
DebugLog("CROM bank setting: %d (%02X), PC=%08X, LR=%08X\n", idx, cromBankReg, ppc_get_pc(), ppc_get_lr());
|
||||
//printf("CROM bank setting: %d (%02X), PC=%08X, LR=%08X\n", idx, cromBankReg, ppc_get_pc(), ppc_get_lr());
|
||||
}
|
||||
|
||||
UINT8 CModel3::ReadSystemRegister(unsigned reg)
|
||||
|
@ -965,7 +897,7 @@ UINT8 CModel3::Read8(UINT32 addr)
|
|||
|
||||
// 53C810 SCSI
|
||||
case 0xC0: // only on Step 1.0
|
||||
if (Game->step != 0x10) // check for Step 1.0
|
||||
if (Game->step != 0x10)
|
||||
break;
|
||||
case 0xF9:
|
||||
case 0xC1:
|
||||
|
@ -1499,6 +1431,7 @@ void CModel3::Write32(UINT32 addr, UINT32 data)
|
|||
|
||||
// Security board RAM
|
||||
case 0x18:
|
||||
case 0x19:
|
||||
*(UINT32 *) &securityRAM[(addr&0x1FFFF)] = data;
|
||||
break;
|
||||
|
||||
|
@ -1903,7 +1836,6 @@ void CModel3::Write64(UINT32 addr, UINT64 data)
|
|||
Write32(addr+4, (UINT32) data);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -1926,6 +1858,8 @@ void CModel3::SaveState(CBlockFile *SaveState)
|
|||
SaveState->Write(backupRAM, 0x20000);
|
||||
SaveState->Write(securityRAM, 0x20000);
|
||||
SaveState->Write(&midiCtrlPort, sizeof(midiCtrlPort));
|
||||
int32_t securityFirstRead = m_securityFirstRead;
|
||||
SaveState->Write(&securityFirstRead, sizeof(securityFirstRead));
|
||||
|
||||
// All devices...
|
||||
ppc_save_state(SaveState);
|
||||
|
@ -1937,6 +1871,7 @@ void CModel3::SaveState(CBlockFile *SaveState)
|
|||
GPU.SaveState(SaveState);
|
||||
SoundBoard.SaveState(SaveState); // also saves DSB state
|
||||
DriveBoard.SaveState(SaveState);
|
||||
m_cryptoDevice.SaveState(SaveState);
|
||||
}
|
||||
|
||||
void CModel3::LoadState(CBlockFile *SaveState)
|
||||
|
@ -1960,6 +1895,9 @@ void CModel3::LoadState(CBlockFile *SaveState)
|
|||
SaveState->Read(backupRAM, 0x20000);
|
||||
SaveState->Read(securityRAM, 0x20000);
|
||||
SaveState->Read(&midiCtrlPort, sizeof(midiCtrlPort));
|
||||
int32_t securityFirstRead;
|
||||
SaveState->Write(&securityFirstRead, sizeof(securityFirstRead));
|
||||
m_securityFirstRead = securityFirstRead;
|
||||
|
||||
// All devices...
|
||||
GPU.LoadState(SaveState);
|
||||
|
@ -1971,6 +1909,7 @@ void CModel3::LoadState(CBlockFile *SaveState)
|
|||
ppc_load_state(SaveState);
|
||||
SoundBoard.LoadState(SaveState);
|
||||
DriveBoard.LoadState(SaveState);
|
||||
m_cryptoDevice.LoadState(SaveState);
|
||||
}
|
||||
|
||||
void CModel3::SaveNVRAM(CBlockFile *NVRAM)
|
||||
|
@ -2015,9 +1954,9 @@ void CModel3::RunFrame(void)
|
|||
goto ThreadError;
|
||||
|
||||
// Wake threads for PPC main board (if multi-threading GPU), sound board (if sync'd) and drive board (if attached) so they can process a frame
|
||||
if (g_Config.gpuMultiThreaded && !ppcBrdThreadSync->Post() ||
|
||||
syncSndBrdThread && !sndBrdThreadSync->Post() ||
|
||||
DriveBoard.IsAttached() && !drvBrdThreadSync->Post())
|
||||
if ((g_Config.gpuMultiThreaded && !ppcBrdThreadSync->Post()) ||
|
||||
(syncSndBrdThread && !sndBrdThreadSync->Post()) ||
|
||||
(DriveBoard.IsAttached() && !drvBrdThreadSync->Post()))
|
||||
goto ThreadError;
|
||||
|
||||
// If not multi-threading GPU, then run PPC main board for a frame and sync GPUs now in this thread
|
||||
|
@ -2035,9 +1974,9 @@ void CModel3::RunFrame(void)
|
|||
goto ThreadError;
|
||||
|
||||
// Wait for PPC main board, sound board and drive board threads to finish their work (if they are running and haven't finished already)
|
||||
while (g_Config.gpuMultiThreaded && !ppcBrdThreadDone ||
|
||||
syncSndBrdThread && !sndBrdThreadDone ||
|
||||
DriveBoard.IsAttached() && !drvBrdThreadDone)
|
||||
while ((g_Config.gpuMultiThreaded && !ppcBrdThreadDone) ||
|
||||
(syncSndBrdThread && !sndBrdThreadDone) ||
|
||||
(DriveBoard.IsAttached() && !drvBrdThreadDone))
|
||||
{
|
||||
if (!notifySync->Wait(notifyLock))
|
||||
goto ThreadError;
|
||||
|
@ -2199,20 +2138,15 @@ void CModel3::RenderFrame(void)
|
|||
bool CModel3::RunSoundBoardFrame(void)
|
||||
{
|
||||
UINT32 start = CThread::GetTicks();
|
||||
|
||||
bool bufferFull = SoundBoard.RunFrame();
|
||||
|
||||
timings.sndTicks = CThread::GetTicks() - start;
|
||||
|
||||
return bufferFull;
|
||||
}
|
||||
|
||||
void CModel3::RunDriveBoardFrame(void)
|
||||
{
|
||||
UINT32 start = CThread::GetTicks();
|
||||
|
||||
DriveBoard.RunFrame();
|
||||
|
||||
timings.drvTicks = CThread::GetTicks() - start;
|
||||
}
|
||||
|
||||
|
@ -2816,6 +2750,7 @@ void CModel3::Reset(void)
|
|||
|
||||
// Reset security device
|
||||
securityPtr = 0;
|
||||
m_securityFirstRead = true;
|
||||
|
||||
// Reset inputs
|
||||
inputBank = 0;
|
||||
|
@ -2841,6 +2776,8 @@ void CModel3::Reset(void)
|
|||
if (DriveBoard.IsAttached())
|
||||
DriveBoard.Reset();
|
||||
|
||||
m_cryptoDevice.Reset();
|
||||
|
||||
gpusReady = false;
|
||||
|
||||
timings.ppcTicks = 0;
|
||||
|
@ -2875,8 +2812,7 @@ void CModel3::Patch(void)
|
|||
{
|
||||
*(UINT32 *) &crom[0x7374f4] = 0x38840004; // an actual bug in the game code
|
||||
}
|
||||
else if (!strcmp(Game->id, "vs215") ||
|
||||
!strcmp(Game->id, "vs215o") || !strcmp(Game->id, "vs29815"))
|
||||
else if (!strcmp(Game->id, "vs215") || !strcmp(Game->id, "vs215o") || !strcmp(Game->id, "vs29815"))
|
||||
{
|
||||
// VS215 is a modification of VS2 that runs on Step 1.5 hardware. I
|
||||
// suspect the code here is trying to detect the system type but am too
|
||||
|
@ -2898,23 +2834,6 @@ void CModel3::Patch(void)
|
|||
*(UINT32 *) &crom[0x7C0C8] = 0x60000000;
|
||||
*(UINT32 *) &crom[0x7C0CC] = 0x60000000;
|
||||
}
|
||||
else if (!strcmp(Game->id, "daytona2"))
|
||||
{
|
||||
// Base address of program in CROM: 0x600000
|
||||
// 0x10019E is the location in RAM which contains link type.
|
||||
// Region menu can be accessed by entering test mode, holding start,
|
||||
// and pressing: green, green, blue, yellow, red, yellow, blue (VR4,4,2,3,1,3,2)
|
||||
*(UINT32 *) &crom[0x68468c] = 0x60000000; // protection device
|
||||
*(UINT32 *) &crom[0x6063c4] = 0x60000000; // needed to allow levels to load
|
||||
*(UINT32 *) &crom[0x616434] = 0x60000000; // prevents PPC from executing invalid code (MMU?)
|
||||
*(UINT32 *) &crom[0x69f4e4] = 0x60000000; // ""
|
||||
}
|
||||
else if (!strcmp(Game->id, "dayto2pe"))
|
||||
{
|
||||
//*(UINT32 *) &crom[0x606784] = 0x60000000;
|
||||
*(UINT32 *) &crom[0x69A3FC] = 0x60000000; // MAME says: jump to encrypted code
|
||||
*(UINT32 *) &crom[0x618B28] = 0x60000000; // MAME says: jump to encrypted code
|
||||
}
|
||||
else if (!strcmp(Game->id, "harley"))
|
||||
{
|
||||
*(UINT32 *) &crom[0x50E8D4] = 0x60000000;
|
||||
|
@ -2941,35 +2860,29 @@ void CModel3::Patch(void)
|
|||
else if (!strcmp(Game->id, "eca") || !strcmp(Game->id, "ecax"))
|
||||
{
|
||||
*(UINT32 *) &crom[0x535580] = 0x60000000;
|
||||
*(UINT32 *) &crom[0x5023B4] = 0x60000000;
|
||||
*(UINT32 *) &crom[0x5023D4] = 0x60000000;
|
||||
//*(UINT32 *) &crom[0x5023B4] = 0x60000000;
|
||||
//*(UINT32 *) &crom[0x5023D4] = 0x60000000;
|
||||
}
|
||||
}
|
||||
|
||||
// Reverses all aligned 16-bit words, thereby switching their endianness (assumes buffer size is divisible by 2)
|
||||
static void Reverse16(UINT8 *buf, unsigned size)
|
||||
static void Reverse16(uint8_t *buf, size_t size)
|
||||
{
|
||||
unsigned i;
|
||||
UINT8 tmp;
|
||||
|
||||
for (i = 0; i < size; i += 2)
|
||||
for (size_t i = 0; i < size; i += 2)
|
||||
{
|
||||
tmp = buf[i+0];
|
||||
uint8_t tmp = buf[i+0];
|
||||
buf[i+0] = buf[i+1];
|
||||
buf[i+1] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// Reverses all aligned 32-bit words, thereby switching their endianness (assumes buffer size is divisible by 4)
|
||||
static void Reverse32(UINT8 *buf, unsigned size)
|
||||
static void Reverse32(uint8_t *buf, size_t size)
|
||||
{
|
||||
unsigned i;
|
||||
UINT8 tmp1, tmp2;
|
||||
|
||||
for (i = 0; i < size; i += 4)
|
||||
for (size_t i = 0; i < size; i += 4)
|
||||
{
|
||||
tmp1 = buf[i+0];
|
||||
tmp2 = buf[i+1];
|
||||
uint8_t tmp1 = buf[i+0];
|
||||
uint8_t tmp2 = buf[i+1];
|
||||
buf[i+0] = buf[i+3];
|
||||
buf[i+1] = buf[i+2];
|
||||
buf[i+2] = tmp2;
|
||||
|
@ -2977,63 +2890,6 @@ static void Reverse32(UINT8 *buf, unsigned size)
|
|||
}
|
||||
}
|
||||
|
||||
// Reads in CROMs directly (for debugging purposes only)
|
||||
static void ReadCROMDirectly(UINT8 *crom, char *fileName[4], unsigned combinedSize)
|
||||
{
|
||||
FILE *fp[4] = { NULL, NULL, NULL, NULL };
|
||||
|
||||
// Open all files
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
fp[i] = fopen(fileName[i],"rb");
|
||||
if (NULL == fp[i])
|
||||
{
|
||||
ErrorLog("Unable to open file for reading: %s.", fileName[i]);
|
||||
goto ReadCleanup;
|
||||
}
|
||||
}
|
||||
|
||||
// Read and interleave 2 bytes at a time
|
||||
for (unsigned i = 0; i < combinedSize; i += 8)
|
||||
{
|
||||
fread(&crom[i+0], 1, 2, fp[0]);
|
||||
fread(&crom[i+2], 1, 2, fp[1]);
|
||||
fread(&crom[i+4], 1, 2, fp[2]);
|
||||
fread(&crom[i+6], 1, 2, fp[3]);
|
||||
}
|
||||
Reverse16(crom, combinedSize); // byte reverse ROMs
|
||||
|
||||
// Reverse 32 bit words for Supermodel
|
||||
Reverse32(crom, combinedSize);
|
||||
|
||||
ReadCleanup:
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (fp[i] != NULL)
|
||||
fclose(fp[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Dumps a memory region to a file for debugging purposes
|
||||
static void Dump(const char *file, UINT8 *buf, unsigned size, bool reverse32, bool reverse16)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(file, "wb");
|
||||
if (NULL != fp)
|
||||
{
|
||||
if (reverse32)
|
||||
Reverse32(buf, size);
|
||||
else if (reverse16)
|
||||
Reverse16(buf, size);
|
||||
fwrite(buf, sizeof(UINT8), size, fp);
|
||||
fclose(fp);
|
||||
printf("dumped %s\n", file);
|
||||
}
|
||||
else
|
||||
printf("unable to dump %s\n", file);
|
||||
}
|
||||
|
||||
// Offsets of memory regions within Model 3's pool
|
||||
#define OFFSET_RAM 0 // 8 MB
|
||||
#define OFFSET_CROM 0x800000 // 8 MB (fixed CROM)
|
||||
|
@ -3181,29 +3037,27 @@ bool CModel3::LoadROMSet(const struct GameInfo *GameList, const char *zipFile)
|
|||
else
|
||||
DriveBoard.Init(NULL); // disable
|
||||
|
||||
// Security board encryption device
|
||||
m_cryptoDevice.Init(Game->encryptionKey, std::bind(&CModel3::ReadSecurityRAM, this, std::placeholders::_1));
|
||||
|
||||
// Apply ROM patches
|
||||
Patch();
|
||||
|
||||
// Print game information
|
||||
std::set<std::string> extraHw;
|
||||
if (Game->mpegBoard)
|
||||
extraHw.insert(Util::Format() << "Digital Sound Board (Type " << Game->mpegBoard << ")");
|
||||
if (Game->driveBoard)
|
||||
extraHw.insert("Drive Board");
|
||||
if (Game->encryptionKey)
|
||||
extraHw.insert("Security Board");
|
||||
printf(" Title: %s\n", Game->title);
|
||||
printf(" ROM Set: %s\n", Game->id);
|
||||
printf(" Developer: %s\n", Game->mfgName);
|
||||
printf(" Year: %d\n", Game->year);
|
||||
printf(" Step: %d.%d\n", (Game->step>>4)&0xF, Game->step&0xF);
|
||||
if (Game->mpegBoard)
|
||||
{
|
||||
printf(" Extra Hardware: Digital Sound Board (Type %d)", Game->mpegBoard);
|
||||
if (Game->driveBoard)
|
||||
printf(", Drive Board");
|
||||
printf(" Extra Hardware: %s\n", Util::Format(", ").Join(extraHw).str().c_str());
|
||||
printf("\n");
|
||||
}
|
||||
else if (Game->driveBoard)
|
||||
printf(" Extra Hardware: Drive Board\n");
|
||||
printf("\n");
|
||||
|
||||
// Load patched CROM directly (for testing out ROM patches)
|
||||
//char *fileName[4] = { "epr-20599a.patched.20","epr-20598a.patched.19","epr-20597a.patched.18","epr-20596a.patched.17" };
|
||||
//ReadCROMDirectly(crom, fileName, 0x800000);
|
||||
|
||||
return OKAY;
|
||||
}
|
||||
|
@ -3259,7 +3113,7 @@ bool CModel3::Init(void)
|
|||
driveROM = &memoryPool[OFFSET_DRIVEROM];
|
||||
SetCROMBank(0xFF);
|
||||
|
||||
// Initialize other devices (PowerPC and DSB initialized after ROMs loaded)
|
||||
// Initialize other devices (PowerPC, DSB, and security board initialized after ROMs loaded)
|
||||
IRQ.Init();
|
||||
PCIBridge.Init();
|
||||
PCIBus.Init();
|
||||
|
@ -3339,17 +3193,37 @@ CModel3::CModel3(void)
|
|||
DebugLog("Built Model 3\n");
|
||||
}
|
||||
|
||||
/*
|
||||
// Dumps a memory region to a file for debugging purposes
|
||||
static void Dump(const char *file, uint8_t *buf, size_t size, bool reverse32, bool reverse16)
|
||||
{
|
||||
FILE *fp = fopen(file, "wb");
|
||||
if (NULL != fp)
|
||||
{
|
||||
if (reverse32)
|
||||
Reverse32(buf, size);
|
||||
else if (reverse16)
|
||||
Reverse16(buf, size);
|
||||
fwrite(buf, sizeof(UINT8), size, fp);
|
||||
fclose(fp);
|
||||
printf("dumped %s\n", file);
|
||||
}
|
||||
else
|
||||
printf("unable to dump %s\n", file);
|
||||
}
|
||||
*/
|
||||
|
||||
CModel3::~CModel3(void)
|
||||
{
|
||||
/*
|
||||
// Debug: dump some files
|
||||
#if 0
|
||||
//Dump("ram", ram, 0x800000, true, false);
|
||||
//Dump("vrom", vrom, 0x4000000, true, false);
|
||||
Dump("crom", crom, 0x800000, true, false);
|
||||
//Dump("bankedCrom", &crom[0x800000], 0x7000000, true, false);
|
||||
//Dump("soundROM", soundROM, 0x80000, false, true);
|
||||
//Dump("sampleROM", sampleROM, 0x800000, false, true);
|
||||
#endif
|
||||
*/
|
||||
|
||||
// Stop all threads
|
||||
StopThreads();
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#ifndef INCLUDED_MODEL3_H
|
||||
#define INCLUDED_MODEL3_H
|
||||
|
||||
#include "Model3/Crypto.h"
|
||||
|
||||
/*
|
||||
* FrameTimings
|
||||
|
@ -370,6 +371,7 @@ private:
|
|||
// Private member functions
|
||||
UINT8 ReadInputs(unsigned reg);
|
||||
void WriteInputs(unsigned reg, UINT8 data);
|
||||
uint16_t ReadSecurityRAM(uint32_t addr);
|
||||
UINT32 ReadSecurity(unsigned reg);
|
||||
void WriteSecurity(unsigned reg, UINT32 data);
|
||||
void SetCROMBank(unsigned idx);
|
||||
|
@ -403,10 +405,8 @@ private:
|
|||
// Game and hardware information
|
||||
const struct GameInfo *Game;
|
||||
|
||||
// Game inputs
|
||||
// Game inputs and outputs
|
||||
CInputs *Inputs;
|
||||
|
||||
// Game outputs
|
||||
COutputs *Outputs;
|
||||
|
||||
// Input registers (game controls)
|
||||
|
@ -436,6 +436,7 @@ private:
|
|||
unsigned cromBankReg; // the CROM bank register
|
||||
|
||||
// Security device
|
||||
bool m_securityFirstRead = true;
|
||||
unsigned securityPtr; // pointer to current offset in security data
|
||||
|
||||
// PowerPC
|
||||
|
@ -482,6 +483,7 @@ private:
|
|||
CSoundBoard SoundBoard; // Sound board
|
||||
CDSB *DSB; // Digital Sound Board (type determined dynamically at load time)
|
||||
CDriveBoard DriveBoard; // Drive board
|
||||
CCrypto m_cryptoDevice; // Encryption device
|
||||
};
|
||||
|
||||
|
||||
|
|
33
Src/Util/Format.cpp
Normal file
33
Src/Util/Format.cpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include "Util/Format.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
static const char hex_digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||
|
||||
const std::string Hex(uint32_t n, size_t num_digits)
|
||||
{
|
||||
Util::Format f;
|
||||
f << "0x";
|
||||
for (size_t b = num_digits * 4; b; )
|
||||
{
|
||||
b -= 4;
|
||||
f << hex_digits[(n >> b) & 0xf];
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
const std::string Hex(uint32_t n)
|
||||
{
|
||||
return Hex(n, 8);
|
||||
}
|
||||
|
||||
const std::string Hex(uint16_t n)
|
||||
{
|
||||
return Hex(n, 4);
|
||||
}
|
||||
|
||||
const std::string Hex(uint8_t n)
|
||||
{
|
||||
return Hex(n, 2);
|
||||
}
|
||||
} // Util
|
68
Src/Util/Format.h
Normal file
68
Src/Util/Format.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
#ifndef INCLUDED_FORMAT_H
|
||||
#define INCLUDED_FORMAT_H
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace Util
|
||||
{
|
||||
class Format
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
Format &operator<<(const T &data)
|
||||
{
|
||||
m_stream << data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator std::string() const
|
||||
{
|
||||
return str();
|
||||
}
|
||||
|
||||
std::string str() const
|
||||
{
|
||||
return m_stream.str();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Format &Join(const T &collection)
|
||||
{
|
||||
std::string separator = m_stream.str();
|
||||
clear();
|
||||
for (auto it = collection.begin(); it != collection.end(); )
|
||||
{
|
||||
m_stream << *it;
|
||||
++it;
|
||||
if (it != collection.end())
|
||||
m_stream << separator;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Format(const std::string &str)
|
||||
: m_stream(str)
|
||||
{
|
||||
}
|
||||
|
||||
Format()
|
||||
{
|
||||
}
|
||||
private:
|
||||
std::stringstream m_stream;
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_stream.str(std::string());
|
||||
}
|
||||
};
|
||||
|
||||
const std::string Hex(uint32_t n, size_t num_digits);
|
||||
const std::string Hex(uint32_t n);
|
||||
const std::string Hex(uint16_t n);
|
||||
const std::string Hex(uint8_t n);
|
||||
} // Util
|
||||
|
||||
#endif // INCLUDED_FORMAT_H
|
Loading…
Reference in a new issue