mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 13:55: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)
|
ifeq ($(strip $(BITS)),64)
|
||||||
SDL_LIBPATH = /mingw64/lib64
|
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
|
else
|
||||||
SDL_LIBPATH = /mingw/lib
|
SDL_LIBPATH = /mingw/lib
|
||||||
SDL_INCLUDEPATH = /mingw/include/SDL
|
SDL_INCLUDEPATH = /mingw/include/SDL
|
||||||
|
@ -68,6 +69,7 @@ endif
|
||||||
#
|
#
|
||||||
ifeq ($(strip $(BITS)),64)
|
ifeq ($(strip $(BITS)),64)
|
||||||
WINSDK_LIBPATH = /Program\ Files/Microsoft\ SDKs/Windows/v7.0/Lib/x64
|
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
|
else
|
||||||
WINSDK_LIBPATH = /Program\ Files/Microsoft\ SDKs/Windows/v7.0/Lib
|
WINSDK_LIBPATH = /Program\ Files/Microsoft\ SDKs/Windows/v7.0/Lib
|
||||||
endif
|
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
|
COMPILER_FLAGS = -I$(SDL_INCLUDEPATH) -ISrc/ -ISrc/OSD/ -ISrc/OSD/SDL/ -ISrc/OSD/Windows/ -c -Wall -DSUPERMODEL_WIN32 -DGLEW_STATIC -O3
|
||||||
CFLAGS = $(COMPILER_FLAGS)
|
CFLAGS = $(COMPILER_FLAGS)
|
||||||
CPPFLAGS = $(COMPILER_FLAGS) -I$(BOOST_INCLUDEPATH) -std=c++11
|
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...
|
# 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)/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_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_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
|
# 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
|
$(OBJ_DIR)/%.o: Src/Pkgs/%.c
|
||||||
$(CC) $< $(CFLAGS) -o $(OBJ_DIR)/$(*F).o
|
$(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
|
# 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
|
** Supermodel
|
||||||
** A Sega Model 3 Arcade Emulator.
|
** 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.
|
** This file is part of Supermodel.
|
||||||
**
|
**
|
||||||
|
@ -27,8 +27,9 @@
|
||||||
* To-Do List
|
* To-Do List
|
||||||
* ----------
|
* ----------
|
||||||
* - Save state format has changed slightly. No longer need dmaUnknownRegister
|
* - Save state format has changed slightly. No longer need dmaUnknownRegister
|
||||||
* in Real3D.cpp. PowerPC timing variables have changed. Before 0.3a
|
* in Real3D.cpp and security board-related variable was added to Model 3
|
||||||
* release, important to change format version #.
|
* 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
|
* - ROM sets should probably be handled with a class that manages ROM
|
||||||
* loading, the game list, as well as ROM patching
|
* loading, the game list, as well as ROM patching
|
||||||
* - Wrap up CPU emulation inside a class.
|
* - Wrap up CPU emulation inside a class.
|
||||||
|
@ -184,6 +185,16 @@
|
||||||
* G32 ---
|
* G32 ---
|
||||||
* G31 Right Turbo
|
* G31 Right Turbo
|
||||||
* G30 Right Shot Trigger
|
* 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>
|
#include <new>
|
||||||
|
@ -191,6 +202,10 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "Supermodel.h"
|
#include "Supermodel.h"
|
||||||
|
#include "Util/Format.h"
|
||||||
|
#include <functional>
|
||||||
|
#include <set>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
Model 3 Inputs
|
Model 3 Inputs
|
||||||
|
@ -636,130 +651,30 @@ void CModel3::WriteInputs(unsigned reg, UINT8 data)
|
||||||
seems to help avoid this.
|
seems to help avoid this.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
static const UINT16 spikeoutSecurity[] =
|
uint16_t CModel3::ReadSecurityRAM(uint32_t addr)
|
||||||
{
|
{
|
||||||
0x0000,
|
if (addr < 0x8000)
|
||||||
0x4f4d, 0x4544, 0x2d4c, 0x2033, 0x7953, 0x7473, 0x6d65, 0x5020,
|
return (*(uint32_t *) &securityRAM[addr * 4]) >> 16;
|
||||||
0x6f72, 0x7267, 0x6d61, 0x4320, 0x706f, 0x7279, 0x6769, 0x7468,
|
return 0;
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
UINT32 CModel3::ReadSecurity(unsigned reg)
|
UINT32 CModel3::ReadSecurity(unsigned reg)
|
||||||
{
|
{
|
||||||
UINT32 data;
|
|
||||||
|
|
||||||
switch (reg)
|
switch (reg)
|
||||||
{
|
{
|
||||||
case 0x00: // Status
|
case 0x00: // Status
|
||||||
return 0;
|
return 0;
|
||||||
case 0x1C: // Data
|
case 0x1C: // Data
|
||||||
if (!strcmp(Game->id, "spikeout") || !strcmp(Game->id, "spikeofe"))
|
if (m_securityFirstRead)
|
||||||
{
|
{
|
||||||
data = (spikeoutSecurity[securityPtr++] << 16);
|
m_securityFirstRead = false;
|
||||||
securityPtr %= (sizeof(spikeoutSecurity)/sizeof(UINT16));
|
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
|
else
|
||||||
{
|
{
|
||||||
data = 0xFFFFFFFF;
|
uint8_t *base_ptr;
|
||||||
DebugLog("Security read: reg=%X, PC=%08X, LR=%08X\n", reg, ppc_get_pc(), ppc_get_lr());
|
return m_cryptoDevice.Decrypt(&base_ptr) << 16;
|
||||||
}
|
}
|
||||||
return data;
|
|
||||||
default:
|
default:
|
||||||
DebugLog("Security read: reg=%X\n", reg);
|
DebugLog("Security read: reg=%X\n", reg);
|
||||||
break;
|
break;
|
||||||
|
@ -770,7 +685,25 @@ UINT32 CModel3::ReadSecurity(unsigned reg)
|
||||||
|
|
||||||
void CModel3::WriteSecurity(unsigned reg, UINT32 data)
|
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());
|
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;
|
idx = (~idx) & 0xF;
|
||||||
cromBank = &crom[0x800000 + (idx*0x800000)];
|
cromBank = &crom[0x800000 + (idx*0x800000)];
|
||||||
DebugLog("CROM bank setting: %d (%02X), PC=%08X, LR=%08X\n", idx, cromBankReg, ppc_get_pc(), ppc_get_lr());
|
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)
|
UINT8 CModel3::ReadSystemRegister(unsigned reg)
|
||||||
|
@ -965,7 +897,7 @@ UINT8 CModel3::Read8(UINT32 addr)
|
||||||
|
|
||||||
// 53C810 SCSI
|
// 53C810 SCSI
|
||||||
case 0xC0: // only on Step 1.0
|
case 0xC0: // only on Step 1.0
|
||||||
if (Game->step != 0x10) // check for Step 1.0
|
if (Game->step != 0x10)
|
||||||
break;
|
break;
|
||||||
case 0xF9:
|
case 0xF9:
|
||||||
case 0xC1:
|
case 0xC1:
|
||||||
|
@ -1499,6 +1431,7 @@ void CModel3::Write32(UINT32 addr, UINT32 data)
|
||||||
|
|
||||||
// Security board RAM
|
// Security board RAM
|
||||||
case 0x18:
|
case 0x18:
|
||||||
|
case 0x19:
|
||||||
*(UINT32 *) &securityRAM[(addr&0x1FFFF)] = data;
|
*(UINT32 *) &securityRAM[(addr&0x1FFFF)] = data;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1903,7 +1836,6 @@ void CModel3::Write64(UINT32 addr, UINT64 data)
|
||||||
Write32(addr+4, (UINT32) data);
|
Write32(addr+4, (UINT32) data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -1926,6 +1858,8 @@ void CModel3::SaveState(CBlockFile *SaveState)
|
||||||
SaveState->Write(backupRAM, 0x20000);
|
SaveState->Write(backupRAM, 0x20000);
|
||||||
SaveState->Write(securityRAM, 0x20000);
|
SaveState->Write(securityRAM, 0x20000);
|
||||||
SaveState->Write(&midiCtrlPort, sizeof(midiCtrlPort));
|
SaveState->Write(&midiCtrlPort, sizeof(midiCtrlPort));
|
||||||
|
int32_t securityFirstRead = m_securityFirstRead;
|
||||||
|
SaveState->Write(&securityFirstRead, sizeof(securityFirstRead));
|
||||||
|
|
||||||
// All devices...
|
// All devices...
|
||||||
ppc_save_state(SaveState);
|
ppc_save_state(SaveState);
|
||||||
|
@ -1937,6 +1871,7 @@ void CModel3::SaveState(CBlockFile *SaveState)
|
||||||
GPU.SaveState(SaveState);
|
GPU.SaveState(SaveState);
|
||||||
SoundBoard.SaveState(SaveState); // also saves DSB state
|
SoundBoard.SaveState(SaveState); // also saves DSB state
|
||||||
DriveBoard.SaveState(SaveState);
|
DriveBoard.SaveState(SaveState);
|
||||||
|
m_cryptoDevice.SaveState(SaveState);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModel3::LoadState(CBlockFile *SaveState)
|
void CModel3::LoadState(CBlockFile *SaveState)
|
||||||
|
@ -1960,6 +1895,9 @@ void CModel3::LoadState(CBlockFile *SaveState)
|
||||||
SaveState->Read(backupRAM, 0x20000);
|
SaveState->Read(backupRAM, 0x20000);
|
||||||
SaveState->Read(securityRAM, 0x20000);
|
SaveState->Read(securityRAM, 0x20000);
|
||||||
SaveState->Read(&midiCtrlPort, sizeof(midiCtrlPort));
|
SaveState->Read(&midiCtrlPort, sizeof(midiCtrlPort));
|
||||||
|
int32_t securityFirstRead;
|
||||||
|
SaveState->Write(&securityFirstRead, sizeof(securityFirstRead));
|
||||||
|
m_securityFirstRead = securityFirstRead;
|
||||||
|
|
||||||
// All devices...
|
// All devices...
|
||||||
GPU.LoadState(SaveState);
|
GPU.LoadState(SaveState);
|
||||||
|
@ -1971,6 +1909,7 @@ void CModel3::LoadState(CBlockFile *SaveState)
|
||||||
ppc_load_state(SaveState);
|
ppc_load_state(SaveState);
|
||||||
SoundBoard.LoadState(SaveState);
|
SoundBoard.LoadState(SaveState);
|
||||||
DriveBoard.LoadState(SaveState);
|
DriveBoard.LoadState(SaveState);
|
||||||
|
m_cryptoDevice.LoadState(SaveState);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModel3::SaveNVRAM(CBlockFile *NVRAM)
|
void CModel3::SaveNVRAM(CBlockFile *NVRAM)
|
||||||
|
@ -2015,9 +1954,9 @@ void CModel3::RunFrame(void)
|
||||||
goto ThreadError;
|
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
|
// 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() ||
|
if ((g_Config.gpuMultiThreaded && !ppcBrdThreadSync->Post()) ||
|
||||||
syncSndBrdThread && !sndBrdThreadSync->Post() ||
|
(syncSndBrdThread && !sndBrdThreadSync->Post()) ||
|
||||||
DriveBoard.IsAttached() && !drvBrdThreadSync->Post())
|
(DriveBoard.IsAttached() && !drvBrdThreadSync->Post()))
|
||||||
goto ThreadError;
|
goto ThreadError;
|
||||||
|
|
||||||
// If not multi-threading GPU, then run PPC main board for a frame and sync GPUs now in this thread
|
// 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;
|
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)
|
// 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 ||
|
while ((g_Config.gpuMultiThreaded && !ppcBrdThreadDone) ||
|
||||||
syncSndBrdThread && !sndBrdThreadDone ||
|
(syncSndBrdThread && !sndBrdThreadDone) ||
|
||||||
DriveBoard.IsAttached() && !drvBrdThreadDone)
|
(DriveBoard.IsAttached() && !drvBrdThreadDone))
|
||||||
{
|
{
|
||||||
if (!notifySync->Wait(notifyLock))
|
if (!notifySync->Wait(notifyLock))
|
||||||
goto ThreadError;
|
goto ThreadError;
|
||||||
|
@ -2199,20 +2138,15 @@ void CModel3::RenderFrame(void)
|
||||||
bool CModel3::RunSoundBoardFrame(void)
|
bool CModel3::RunSoundBoardFrame(void)
|
||||||
{
|
{
|
||||||
UINT32 start = CThread::GetTicks();
|
UINT32 start = CThread::GetTicks();
|
||||||
|
|
||||||
bool bufferFull = SoundBoard.RunFrame();
|
bool bufferFull = SoundBoard.RunFrame();
|
||||||
|
|
||||||
timings.sndTicks = CThread::GetTicks() - start;
|
timings.sndTicks = CThread::GetTicks() - start;
|
||||||
|
|
||||||
return bufferFull;
|
return bufferFull;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CModel3::RunDriveBoardFrame(void)
|
void CModel3::RunDriveBoardFrame(void)
|
||||||
{
|
{
|
||||||
UINT32 start = CThread::GetTicks();
|
UINT32 start = CThread::GetTicks();
|
||||||
|
|
||||||
DriveBoard.RunFrame();
|
DriveBoard.RunFrame();
|
||||||
|
|
||||||
timings.drvTicks = CThread::GetTicks() - start;
|
timings.drvTicks = CThread::GetTicks() - start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2816,6 +2750,7 @@ void CModel3::Reset(void)
|
||||||
|
|
||||||
// Reset security device
|
// Reset security device
|
||||||
securityPtr = 0;
|
securityPtr = 0;
|
||||||
|
m_securityFirstRead = true;
|
||||||
|
|
||||||
// Reset inputs
|
// Reset inputs
|
||||||
inputBank = 0;
|
inputBank = 0;
|
||||||
|
@ -2841,6 +2776,8 @@ void CModel3::Reset(void)
|
||||||
if (DriveBoard.IsAttached())
|
if (DriveBoard.IsAttached())
|
||||||
DriveBoard.Reset();
|
DriveBoard.Reset();
|
||||||
|
|
||||||
|
m_cryptoDevice.Reset();
|
||||||
|
|
||||||
gpusReady = false;
|
gpusReady = false;
|
||||||
|
|
||||||
timings.ppcTicks = 0;
|
timings.ppcTicks = 0;
|
||||||
|
@ -2875,8 +2812,7 @@ void CModel3::Patch(void)
|
||||||
{
|
{
|
||||||
*(UINT32 *) &crom[0x7374f4] = 0x38840004; // an actual bug in the game code
|
*(UINT32 *) &crom[0x7374f4] = 0x38840004; // an actual bug in the game code
|
||||||
}
|
}
|
||||||
else if (!strcmp(Game->id, "vs215") ||
|
else if (!strcmp(Game->id, "vs215") || !strcmp(Game->id, "vs215o") || !strcmp(Game->id, "vs29815"))
|
||||||
!strcmp(Game->id, "vs215o") || !strcmp(Game->id, "vs29815"))
|
|
||||||
{
|
{
|
||||||
// VS215 is a modification of VS2 that runs on Step 1.5 hardware. I
|
// 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
|
// 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[0x7C0C8] = 0x60000000;
|
||||||
*(UINT32 *) &crom[0x7C0CC] = 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"))
|
else if (!strcmp(Game->id, "harley"))
|
||||||
{
|
{
|
||||||
*(UINT32 *) &crom[0x50E8D4] = 0x60000000;
|
*(UINT32 *) &crom[0x50E8D4] = 0x60000000;
|
||||||
|
@ -2941,35 +2860,29 @@ void CModel3::Patch(void)
|
||||||
else if (!strcmp(Game->id, "eca") || !strcmp(Game->id, "ecax"))
|
else if (!strcmp(Game->id, "eca") || !strcmp(Game->id, "ecax"))
|
||||||
{
|
{
|
||||||
*(UINT32 *) &crom[0x535580] = 0x60000000;
|
*(UINT32 *) &crom[0x535580] = 0x60000000;
|
||||||
*(UINT32 *) &crom[0x5023B4] = 0x60000000;
|
//*(UINT32 *) &crom[0x5023B4] = 0x60000000;
|
||||||
*(UINT32 *) &crom[0x5023D4] = 0x60000000;
|
//*(UINT32 *) &crom[0x5023D4] = 0x60000000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverses all aligned 16-bit words, thereby switching their endianness (assumes buffer size is divisible by 2)
|
// 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;
|
for (size_t i = 0; i < size; i += 2)
|
||||||
UINT8 tmp;
|
|
||||||
|
|
||||||
for (i = 0; i < size; i += 2)
|
|
||||||
{
|
{
|
||||||
tmp = buf[i+0];
|
uint8_t tmp = buf[i+0];
|
||||||
buf[i+0] = buf[i+1];
|
buf[i+0] = buf[i+1];
|
||||||
buf[i+1] = tmp;
|
buf[i+1] = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverses all aligned 32-bit words, thereby switching their endianness (assumes buffer size is divisible by 4)
|
// 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;
|
for (size_t i = 0; i < size; i += 4)
|
||||||
UINT8 tmp1, tmp2;
|
|
||||||
|
|
||||||
for (i = 0; i < size; i += 4)
|
|
||||||
{
|
{
|
||||||
tmp1 = buf[i+0];
|
uint8_t tmp1 = buf[i+0];
|
||||||
tmp2 = buf[i+1];
|
uint8_t tmp2 = buf[i+1];
|
||||||
buf[i+0] = buf[i+3];
|
buf[i+0] = buf[i+3];
|
||||||
buf[i+1] = buf[i+2];
|
buf[i+1] = buf[i+2];
|
||||||
buf[i+2] = tmp2;
|
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
|
// Offsets of memory regions within Model 3's pool
|
||||||
#define OFFSET_RAM 0 // 8 MB
|
#define OFFSET_RAM 0 // 8 MB
|
||||||
#define OFFSET_CROM 0x800000 // 8 MB (fixed CROM)
|
#define OFFSET_CROM 0x800000 // 8 MB (fixed CROM)
|
||||||
|
@ -3181,29 +3037,27 @@ bool CModel3::LoadROMSet(const struct GameInfo *GameList, const char *zipFile)
|
||||||
else
|
else
|
||||||
DriveBoard.Init(NULL); // disable
|
DriveBoard.Init(NULL); // disable
|
||||||
|
|
||||||
|
// Security board encryption device
|
||||||
|
m_cryptoDevice.Init(Game->encryptionKey, std::bind(&CModel3::ReadSecurityRAM, this, std::placeholders::_1));
|
||||||
|
|
||||||
// Apply ROM patches
|
// Apply ROM patches
|
||||||
Patch();
|
Patch();
|
||||||
|
|
||||||
// Print game information
|
// 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(" Title: %s\n", Game->title);
|
||||||
printf(" ROM Set: %s\n", Game->id);
|
printf(" ROM Set: %s\n", Game->id);
|
||||||
printf(" Developer: %s\n", Game->mfgName);
|
printf(" Developer: %s\n", Game->mfgName);
|
||||||
printf(" Year: %d\n", Game->year);
|
printf(" Year: %d\n", Game->year);
|
||||||
printf(" Step: %d.%d\n", (Game->step>>4)&0xF, Game->step&0xF);
|
printf(" Step: %d.%d\n", (Game->step>>4)&0xF, Game->step&0xF);
|
||||||
if (Game->mpegBoard)
|
printf(" Extra Hardware: %s\n", Util::Format(", ").Join(extraHw).str().c_str());
|
||||||
{
|
|
||||||
printf(" Extra Hardware: Digital Sound Board (Type %d)", Game->mpegBoard);
|
|
||||||
if (Game->driveBoard)
|
|
||||||
printf(", Drive Board");
|
|
||||||
printf("\n");
|
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;
|
return OKAY;
|
||||||
}
|
}
|
||||||
|
@ -3259,7 +3113,7 @@ bool CModel3::Init(void)
|
||||||
driveROM = &memoryPool[OFFSET_DRIVEROM];
|
driveROM = &memoryPool[OFFSET_DRIVEROM];
|
||||||
SetCROMBank(0xFF);
|
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();
|
IRQ.Init();
|
||||||
PCIBridge.Init();
|
PCIBridge.Init();
|
||||||
PCIBus.Init();
|
PCIBus.Init();
|
||||||
|
@ -3339,17 +3193,37 @@ CModel3::CModel3(void)
|
||||||
DebugLog("Built Model 3\n");
|
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)
|
CModel3::~CModel3(void)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
// Debug: dump some files
|
// Debug: dump some files
|
||||||
#if 0
|
|
||||||
//Dump("ram", ram, 0x800000, true, false);
|
//Dump("ram", ram, 0x800000, true, false);
|
||||||
//Dump("vrom", vrom, 0x4000000, true, false);
|
//Dump("vrom", vrom, 0x4000000, true, false);
|
||||||
Dump("crom", crom, 0x800000, true, false);
|
Dump("crom", crom, 0x800000, true, false);
|
||||||
//Dump("bankedCrom", &crom[0x800000], 0x7000000, true, false);
|
//Dump("bankedCrom", &crom[0x800000], 0x7000000, true, false);
|
||||||
//Dump("soundROM", soundROM, 0x80000, false, true);
|
//Dump("soundROM", soundROM, 0x80000, false, true);
|
||||||
//Dump("sampleROM", sampleROM, 0x800000, false, true);
|
//Dump("sampleROM", sampleROM, 0x800000, false, true);
|
||||||
#endif
|
*/
|
||||||
|
|
||||||
// Stop all threads
|
// Stop all threads
|
||||||
StopThreads();
|
StopThreads();
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#ifndef INCLUDED_MODEL3_H
|
#ifndef INCLUDED_MODEL3_H
|
||||||
#define INCLUDED_MODEL3_H
|
#define INCLUDED_MODEL3_H
|
||||||
|
|
||||||
|
#include "Model3/Crypto.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FrameTimings
|
* FrameTimings
|
||||||
|
@ -370,6 +371,7 @@ private:
|
||||||
// Private member functions
|
// Private member functions
|
||||||
UINT8 ReadInputs(unsigned reg);
|
UINT8 ReadInputs(unsigned reg);
|
||||||
void WriteInputs(unsigned reg, UINT8 data);
|
void WriteInputs(unsigned reg, UINT8 data);
|
||||||
|
uint16_t ReadSecurityRAM(uint32_t addr);
|
||||||
UINT32 ReadSecurity(unsigned reg);
|
UINT32 ReadSecurity(unsigned reg);
|
||||||
void WriteSecurity(unsigned reg, UINT32 data);
|
void WriteSecurity(unsigned reg, UINT32 data);
|
||||||
void SetCROMBank(unsigned idx);
|
void SetCROMBank(unsigned idx);
|
||||||
|
@ -403,10 +405,8 @@ private:
|
||||||
// Game and hardware information
|
// Game and hardware information
|
||||||
const struct GameInfo *Game;
|
const struct GameInfo *Game;
|
||||||
|
|
||||||
// Game inputs
|
// Game inputs and outputs
|
||||||
CInputs *Inputs;
|
CInputs *Inputs;
|
||||||
|
|
||||||
// Game outputs
|
|
||||||
COutputs *Outputs;
|
COutputs *Outputs;
|
||||||
|
|
||||||
// Input registers (game controls)
|
// Input registers (game controls)
|
||||||
|
@ -436,6 +436,7 @@ private:
|
||||||
unsigned cromBankReg; // the CROM bank register
|
unsigned cromBankReg; // the CROM bank register
|
||||||
|
|
||||||
// Security device
|
// Security device
|
||||||
|
bool m_securityFirstRead = true;
|
||||||
unsigned securityPtr; // pointer to current offset in security data
|
unsigned securityPtr; // pointer to current offset in security data
|
||||||
|
|
||||||
// PowerPC
|
// PowerPC
|
||||||
|
@ -482,6 +483,7 @@ private:
|
||||||
CSoundBoard SoundBoard; // Sound board
|
CSoundBoard SoundBoard; // Sound board
|
||||||
CDSB *DSB; // Digital Sound Board (type determined dynamically at load time)
|
CDSB *DSB; // Digital Sound Board (type determined dynamically at load time)
|
||||||
CDriveBoard DriveBoard; // Drive board
|
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