Refactor
This commit is contained in:
parent
59c18b3c2c
commit
c2e29d9e26
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -9,6 +9,7 @@
|
||||
"ioctl.h": "c",
|
||||
"segaeax.h": "c",
|
||||
"passthrough.h": "c",
|
||||
"pthread.h": "c"
|
||||
}
|
||||
"config.h": "c"
|
||||
},
|
||||
"C_Cpp.errorSquiggles": "disabled"
|
||||
}
|
||||
|
3
Makefile
3
Makefile
@ -26,3 +26,6 @@ libkswapapi.so: src/libkswapapi/libkswapapi.o
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD)
|
||||
rm -f src/lindbergh/*.o
|
||||
rm -f src/libsegaapi/*.o
|
||||
rm -f src/libkswapapi/*.o
|
@ -30,38 +30,44 @@ EMULATE_JVS 1
|
||||
# Set if the emulator should emulate the rideboard used in the special games here
|
||||
# If this is set to 0, then the emulator will route the traffic to the serial device
|
||||
# defined in RIDEBOARD_PATH if it has been defined.
|
||||
# EMULATE_RIDEBOARD 0
|
||||
EMULATE_RIDEBOARD 0
|
||||
|
||||
# Set if the emulator should emulate the driveboard used in driving games here
|
||||
# If this is set to 0, then the emulator will route the traffic to the serial device
|
||||
# defined in DRIVEBOARD_PATH if it has been defined.
|
||||
# EMULATE_DRIVEBOARD 0
|
||||
EMULATE_DRIVEBOARD 0
|
||||
|
||||
# Set if the emulator should emulate the motion board from Outrun 2 SP SDX here
|
||||
# If this is set to 0, then the emulator will route the traffic to the serial device
|
||||
# defined in MOTIONBOARD_PATH if it has been defined.
|
||||
# EMULATE_MOTIONBOARD 0
|
||||
EMULATE_MOTIONBOARD 0
|
||||
|
||||
# Define the path to pass the JVS packets to
|
||||
# JVS_PATH /dev/ttyUSB0
|
||||
JVS_PATH /dev/ttyUSB0
|
||||
|
||||
# Define the path to pass the rideboard packets to
|
||||
# RIDEBOARD_PATH /dev/ttyUSB0
|
||||
RIDEBOARD_PATH /dev/ttyUSB0
|
||||
|
||||
# Define the path to pass the driveboard packets to
|
||||
# DRIVEBOARD_PATH /dev/ttyUSB0
|
||||
DRIVEBOARD_PATH /dev/ttyUSB0
|
||||
|
||||
# Define the path to pass the motionboard packets to
|
||||
# MOTIONBOARD_PATH /dev/ttyUSB0
|
||||
MOTIONBOARD_PATH /dev/ttyUSB0
|
||||
|
||||
# Define the path to the sram.bin file
|
||||
# SRAM_PATH sram.bin
|
||||
SRAM_PATH sram.bin
|
||||
|
||||
# Define the path to the eeprom.bin file
|
||||
# EEPROM_PATH eeprom.bin
|
||||
EEPROM_PATH eeprom.bin
|
||||
|
||||
# Set if the emulator should go full screen
|
||||
# FULLSCREEN 0
|
||||
FULLSCREEN 0
|
||||
|
||||
# Set if you would like to apply AMD CPU / GPU Fixes
|
||||
# AMD_FIX 0
|
||||
AMD_FIX 0
|
||||
|
||||
# Set the Region ( JP/US/EX )
|
||||
REGION EX
|
||||
|
||||
# Set if you want the game to be Free Play
|
||||
FREEPLAY 1
|
||||
|
@ -10,6 +10,7 @@ Working is defined by getting into attract mode and running the game, but not ne
|
||||
- After Burner Climax
|
||||
- Ghost Squad Evolution
|
||||
- Harley Davidson
|
||||
- Let's Go Jungle
|
||||
- Let's Go Jungle Special (boots to ride error)
|
||||
- Outrun 2 SP SDX
|
||||
- R-Tuned
|
||||
@ -19,20 +20,12 @@ Working is defined by getting into attract mode and running the game, but not ne
|
||||
- The House Of The Dead 4 Special
|
||||
- The House Of The Dead Ex
|
||||
- Virtua Fighter 5
|
||||
|
||||
## Games that do not work or haven't been tested
|
||||
|
||||
- Hummer
|
||||
- Initial D 4
|
||||
- Initial D 5
|
||||
- Let's Go Jungle
|
||||
- Primevil
|
||||
- Virtua Tennis 3
|
||||
|
||||
## How to run specific games
|
||||
## Games that current do not work
|
||||
|
||||
### Let's Go Jungle
|
||||
- Hummer
|
||||
- Initial D 5
|
||||
- Primevil
|
||||
|
||||
No, this game will not start.
|
||||
|
||||
```LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. LD_PRELOAD=lindbergh.so TEA_DIR=`pwd` ./lgj_final```
|
||||
|
Binary file not shown.
@ -40,6 +40,13 @@ static int detectGame(uint32_t elf_crc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (elf_crc == 0x3cc635ee)
|
||||
{
|
||||
config.game = SEGABOOT_2_4_SYM;
|
||||
config.gameStatus = WORKING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (elf_crc == 0xbc0c9ffa)
|
||||
{
|
||||
config.game = THE_HOUSE_OF_THE_DEAD_4;
|
||||
@ -124,6 +131,13 @@ static int detectGame(uint32_t elf_crc)
|
||||
if (elf_crc == 0xc4b7e89)
|
||||
{
|
||||
config.game = VIRTUA_TENNIS_3;
|
||||
config.gameStatus = WORKING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (elf_crc == 0xffe3b0fd)
|
||||
{
|
||||
config.game = VIRTUA_TENNIS_3_TEST;
|
||||
config.gameStatus = NOT_WORKING;
|
||||
return 0;
|
||||
}
|
||||
@ -198,9 +212,11 @@ char *getGameName()
|
||||
case SEGABOOT:
|
||||
return "Segaboot";
|
||||
case SEGABOOT_2_4:
|
||||
return "Segaboot from 2.4 Kernel";
|
||||
return "SEGABOOT 2.4";
|
||||
case SEGABOOT_2_4_SYM:
|
||||
return "SEGABOOT 2.4 Symbols";
|
||||
case SEGABOOT_2_6:
|
||||
return "Segaboot from 2.6 Kernel";
|
||||
return "SEGABOOT 2.6";
|
||||
case SEGA_RACE_TV:
|
||||
return "SEGA Race TV";
|
||||
case THE_HOUSE_OF_THE_DEAD_4:
|
||||
@ -235,6 +251,8 @@ char *getGameName()
|
||||
return "Virtua Fighter 5 Rev D";
|
||||
case VIRTUA_TENNIS_3:
|
||||
return "Virtua Tennis 3";
|
||||
case VIRTUA_TENNIS_3_TEST:
|
||||
return "Virtua Tennis 3 - Testmode";
|
||||
default:
|
||||
return unknownGameTitle;
|
||||
}
|
||||
@ -288,6 +306,18 @@ int readConfig(FILE *configFile, EmulatorConfig *config)
|
||||
else if (strcmp(command, "JVS_PATH") == 0)
|
||||
strcpy(config->jvsPath, getNextToken(NULL, " ", &saveptr));
|
||||
|
||||
else if (strcmp(command, "RIDEBOARD_PATH") == 0)
|
||||
strcpy(config->rideboardPath, getNextToken(NULL, " ", &saveptr));
|
||||
|
||||
else if (strcmp(command, "DRIVEBOARD_PATH") == 0)
|
||||
strcpy(config->driveboardPath, getNextToken(NULL, " ", &saveptr));
|
||||
|
||||
else if (strcmp(command, "MOTIONBOARD_PATH") == 0)
|
||||
strcpy(config->motionboardPath, getNextToken(NULL, " ", &saveptr));
|
||||
|
||||
else if (strcmp(command, "FREEPLAY") == 0)
|
||||
config->freeplay = atoi(getNextToken(NULL, " ", &saveptr));
|
||||
|
||||
else if (strcmp(command, "LINDBERGH_COLOUR") == 0)
|
||||
{
|
||||
char colour[256];
|
||||
@ -295,6 +325,19 @@ int readConfig(FILE *configFile, EmulatorConfig *config)
|
||||
if (strcmp(colour, "RED") == 0)
|
||||
config->lindberghColour = RED;
|
||||
}
|
||||
|
||||
else if (strcmp(command, "REGION") == 0)
|
||||
{
|
||||
char region[256];
|
||||
strcpy(region, getNextToken(NULL, " ", &saveptr));
|
||||
if (strcmp(region, "JP") == 0)
|
||||
config->region = JP;
|
||||
else if (strcmp(region, "US") == 0)
|
||||
config->region = US;
|
||||
else
|
||||
config->region = EX;
|
||||
}
|
||||
|
||||
else
|
||||
printf("Error: Unknown settings command %s\n", command);
|
||||
}
|
||||
@ -320,10 +363,11 @@ int initConfig()
|
||||
config.width = 1024;
|
||||
config.height = 768;
|
||||
config.crc32 = elf_crc;
|
||||
|
||||
config.region = US;
|
||||
config.freeplay = 1;
|
||||
if (detectGame(config.crc32) != 0)
|
||||
{
|
||||
printf("Warning: Unsure what game this is. Please submit this new game to the GitHub repository: https://github.com/bobbydilley/lindbergh-loader/issues/new?title=Please+add+new+game+0x%X&body=I+tried+to+launch+the+following+game:\n", config.crc32);
|
||||
printf("Warning: Unsure what game with CRC 0x%X is. Please submit this new game to the GitHub repository: https://github.com/bobbydilley/lindbergh-loader/issues/new?title=Please+add+new+game+0x%X&body=I+tried+to+launch+the+following+game:\n", config.crc32, config.crc32);
|
||||
}
|
||||
|
||||
configFile = fopen(CONFIG_PATH, "r");
|
||||
|
@ -28,6 +28,7 @@ typedef enum
|
||||
R_TUNED,
|
||||
SEGABOOT,
|
||||
SEGABOOT_2_4,
|
||||
SEGABOOT_2_4_SYM,
|
||||
SEGABOOT_2_6,
|
||||
SEGA_RACE_TV,
|
||||
THE_HOUSE_OF_THE_DEAD_4,
|
||||
@ -45,7 +46,8 @@ typedef enum
|
||||
VIRTUA_FIGHTER_5_REVB,
|
||||
VIRTUA_FIGHTER_5_REVC,
|
||||
VIRTUA_FIGHTER_5_R_REVD,
|
||||
VIRTUA_TENNIS_3
|
||||
VIRTUA_TENNIS_3,
|
||||
VIRTUA_TENNIS_3_TEST
|
||||
} Game;
|
||||
|
||||
typedef enum
|
||||
@ -60,6 +62,13 @@ typedef enum
|
||||
NOT_WORKING
|
||||
} GameStatus;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
JP,
|
||||
US,
|
||||
EX
|
||||
} GameRegion;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int emulateRideboard;
|
||||
@ -80,6 +89,8 @@ typedef struct
|
||||
Colour lindberghColour;
|
||||
GameStatus gameStatus;
|
||||
uint32_t crc32;
|
||||
GameRegion region;
|
||||
int freeplay;
|
||||
} EmulatorConfig;
|
||||
|
||||
int initConfig();
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "eeprom.h"
|
||||
#include "eeprom_settings.h"
|
||||
#include "config.h"
|
||||
|
||||
#define I2C_SMBUS_BLOCK_MAX 32
|
||||
@ -46,6 +47,19 @@ int initEeprom()
|
||||
|
||||
eeprom = fopen(eepromPath, "rb+");
|
||||
|
||||
if(eepromSettingsInit(eeprom) !=0)
|
||||
{
|
||||
printf("Error initializing eeprom settings.");
|
||||
fclose(eeprom);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(getRegion() != getConfig()->region)
|
||||
setRegion(eeprom, getConfig()->region);
|
||||
|
||||
if(getFreeplay() != getConfig()->freeplay)
|
||||
setFreeplay(eeprom, getConfig()->freeplay);
|
||||
|
||||
fseek(eeprom, 0, SEEK_SET);
|
||||
|
||||
return 0;
|
||||
|
332
src/lindbergh/eeprom_settings.c
Normal file
332
src/lindbergh/eeprom_settings.c
Normal file
@ -0,0 +1,332 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "eeprom_settings.h"
|
||||
|
||||
uint32_t crc32_table[255];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t offset;
|
||||
uint16_t size;
|
||||
} eepromOffsets;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STATIC,
|
||||
NETWORK_TYPE,
|
||||
ETH0,
|
||||
ETH1,
|
||||
CREDIT,
|
||||
BACKUP
|
||||
} eepromSection;
|
||||
|
||||
eepromOffsets eepromOffsetTable[] = {
|
||||
{0x0000, 0x0020}, // amSysDataRecord_Static
|
||||
{0x00A0, 0x0010}, // amSysDataRecord_NetworkType
|
||||
{0x00B0, 0x0020}, // amSysDataRecord_Eth0
|
||||
{0x00D0, 0x0020}, // amSysDataRecord_Eth1
|
||||
{0x0100, 0x0040}, // amSysDataRecord_Credit
|
||||
{0x0400, 0x0060}}; // amSysDataRecord_Backup
|
||||
|
||||
unsigned char eepromBuffer[512];
|
||||
|
||||
void build_crc32_table()
|
||||
{
|
||||
for (uint32_t i = 0; i < 256; i++)
|
||||
{
|
||||
uint32_t ch = i;
|
||||
uint32_t crc = 0;
|
||||
for (size_t j = 0; j < 8; j++)
|
||||
{
|
||||
uint32_t b = (ch ^ crc) & 1;
|
||||
crc >>= 1;
|
||||
if (b)
|
||||
crc = crc ^ 0xEDB88320;
|
||||
ch >>= 1;
|
||||
}
|
||||
crc32_table[i] = crc;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t gen_crc(int section, size_t n)
|
||||
{
|
||||
unsigned char *buff = &eepromBuffer[eepromOffsetTable[section].offset + 4];
|
||||
unsigned long crc = 0xfffffffful;
|
||||
size_t i;
|
||||
for (i = 0; i < n; i++)
|
||||
crc = crc32_table[*buff++ ^ (crc & 0xff)] ^ (crc >> 8);
|
||||
return (crc);
|
||||
}
|
||||
|
||||
void addCRCtoBuffer(int section)
|
||||
{
|
||||
uint32_t crc = gen_crc(section, eepromOffsetTable[section].size - 4);
|
||||
memcpy(&eepromBuffer[eepromOffsetTable[section].offset], &crc, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
int fillBuffer(FILE *file)
|
||||
{
|
||||
fseek(file, 0, SEEK_SET);
|
||||
int b = fread(eepromBuffer, 1, 512, file);
|
||||
if (b < 512)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int checkCRCinBuffer(int section)
|
||||
{
|
||||
uint32_t crc;
|
||||
memcpy(&crc, &eepromBuffer[eepromOffsetTable[section].offset], 4);
|
||||
if (crc != gen_crc(section, eepromOffsetTable[section].size - 4))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int createStaticSection()
|
||||
{
|
||||
unsigned char *buff = &eepromBuffer[eepromOffsetTable[STATIC].offset];
|
||||
memset(buff, 0, eepromOffsetTable[STATIC].size);
|
||||
buff[14] = 0;
|
||||
memcpy(buff + 15, "AAGX-01A00009999", 16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int createNetworkTypeSection()
|
||||
{
|
||||
memset(&eepromBuffer[eepromOffsetTable[NETWORK_TYPE].offset], 0,
|
||||
eepromOffsetTable[NETWORK_TYPE].size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int createEthSection(int section)
|
||||
{
|
||||
unsigned char *buff = &eepromBuffer[eepromOffsetTable[section].offset];
|
||||
memset(buff, 0, eepromOffsetTable[section].size);
|
||||
uint32_t value = 1;
|
||||
memcpy(buff + 8, &value, sizeof(uint32_t));
|
||||
value = inet_addr("10.0.0.1");
|
||||
if (section == ETH1)
|
||||
value += (1 << 24);
|
||||
memcpy(buff + 12, &value, sizeof(uint32_t));
|
||||
value = inet_addr("255.255.255.0");
|
||||
memcpy(buff + 16, &value, sizeof(uint32_t));
|
||||
value = inet_addr("0.0.0.0");
|
||||
memcpy(buff + 20, &value, sizeof(uint32_t));
|
||||
memcpy(buff + 24, &value, sizeof(uint32_t));
|
||||
memcpy(buff + 28, &value, sizeof(uint32_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int createCreditSection()
|
||||
{
|
||||
unsigned char *buff = &eepromBuffer[eepromOffsetTable[CREDIT].offset];
|
||||
memset(buff, 0, eepromOffsetTable[CREDIT].size);
|
||||
buff[32] = 99;
|
||||
buff[33] = 9;
|
||||
buff[34] = 4;
|
||||
buff[35] = 0; // Coin chute type [COMMON (Default) / INDIVIDUAL]
|
||||
buff[36] = 1; // Service Type [COMMON / INDIVIDUAL (Default)]
|
||||
buff[38] = 1; //
|
||||
buff[39] = 0; // Freeplay set to 1
|
||||
buff[40] = 1; // Credits Chute #1
|
||||
buff[41] = 1; // Credits Chute #1
|
||||
buff[42] = 0; //
|
||||
buff[43] = 1; // Coins
|
||||
for (size_t i = 0; i < 8; i++)
|
||||
{
|
||||
buff[44 + i] = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int writeSectiontoFile(FILE *file, int section)
|
||||
{
|
||||
unsigned char *buff = &eepromBuffer[eepromOffsetTable[section].offset];
|
||||
// Original
|
||||
if (fseek(file, eepromOffsetTable[section].offset, SEEK_SET) != 0)
|
||||
return 1;
|
||||
if (fwrite(buff, eepromOffsetTable[section].size, 1, file) != 1)
|
||||
return 1;
|
||||
|
||||
// Duplicate
|
||||
if (fseek(file, eepromOffsetTable[section].offset + 0x200, SEEK_SET) != 0)
|
||||
return 1;
|
||||
if (fwrite(buff, eepromOffsetTable[section].size, 1, file) != 1)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getRegion()
|
||||
{
|
||||
return eepromBuffer[14];
|
||||
}
|
||||
|
||||
int setRegion(FILE *eeprom, int region)
|
||||
{
|
||||
eepromBuffer[14] = region;
|
||||
addCRCtoBuffer(STATIC);
|
||||
if (writeSectiontoFile(eeprom, STATIC) != 0)
|
||||
{
|
||||
printf("Error setting the .");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getFreeplay()
|
||||
{
|
||||
return eepromBuffer[eepromOffsetTable[CREDIT].offset + 39];
|
||||
}
|
||||
|
||||
int setFreeplay(FILE *eeprom, int freeplay)
|
||||
{
|
||||
if (createCreditSection() != 0)
|
||||
{
|
||||
printf("Error setting Free Play.");
|
||||
return 1;
|
||||
}
|
||||
eepromBuffer[eepromOffsetTable[CREDIT].offset + 39] = freeplay;
|
||||
addCRCtoBuffer(CREDIT);
|
||||
if (writeSectiontoFile(eeprom, CREDIT) != 0)
|
||||
{
|
||||
printf("Error setting Free Play.");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int eepromSettingsInit( FILE *eeprom)
|
||||
{
|
||||
build_crc32_table();
|
||||
|
||||
eeprom = fopen("eeprom.bin", "r+b");
|
||||
if (eeprom == NULL)
|
||||
{
|
||||
printf("eeprom.bin cannot be opened, let's create a new one.\n");
|
||||
eeprom = fopen("eeprom.bin", "w+b");
|
||||
}
|
||||
fseek(eeprom, 0, SEEK_END);
|
||||
int size = ftell(eeprom);
|
||||
fseek(eeprom, 0, SEEK_SET);
|
||||
if (size >= 832) // eeprom initialized at least by SEGABOOT
|
||||
{
|
||||
fillBuffer(eeprom); // Fills buffer with 1st 512 bytes of the eeprom file
|
||||
if (checkCRCinBuffer(STATIC) != 0)
|
||||
{
|
||||
// Create section from scratch
|
||||
if (createStaticSection() != 0)
|
||||
{
|
||||
printf("Error creating Static Section.\n");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
addCRCtoBuffer(STATIC);
|
||||
if (writeSectiontoFile(eeprom, STATIC) != 0)
|
||||
{
|
||||
printf("Error writing to eeprom.bin [STATIC].");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (checkCRCinBuffer(NETWORK_TYPE) != 0)
|
||||
{
|
||||
// Create section from scratch
|
||||
if (createNetworkTypeSection() != 0)
|
||||
{
|
||||
printf("Error creating NetworkType Section.\n");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
addCRCtoBuffer(NETWORK_TYPE);
|
||||
if (writeSectiontoFile(eeprom, NETWORK_TYPE) != 0)
|
||||
{
|
||||
printf("Error writing to eeprom.bin [NETWORK_TYPE].");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (checkCRCinBuffer(ETH0) != 0)
|
||||
{
|
||||
// Create section from scratch
|
||||
if (createEthSection(ETH0) != 0)
|
||||
{
|
||||
printf("Error creating Eth0 Section.\n");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
addCRCtoBuffer(ETH0);
|
||||
if (writeSectiontoFile(eeprom, ETH0) != 0)
|
||||
{
|
||||
printf("Error writing to eeprom.bin [ETH0].");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (checkCRCinBuffer(ETH1) != 0)
|
||||
{
|
||||
// Create section from scratch
|
||||
if (createEthSection(ETH1) != 0)
|
||||
{
|
||||
printf("Error creating Eth0 Section.\n");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
addCRCtoBuffer(ETH1);
|
||||
if (writeSectiontoFile(eeprom, ETH1) != 0)
|
||||
{
|
||||
printf("Error writing to eeprom.bin [ETH1].");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (checkCRCinBuffer(CREDIT) != 0)
|
||||
{
|
||||
// Create section from scratch
|
||||
if (createCreditSection() != 0)
|
||||
{
|
||||
printf("Error creating CREDIT Section.\n");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
addCRCtoBuffer(CREDIT);
|
||||
if (writeSectiontoFile(eeprom, NETWORK_TYPE) != 0)
|
||||
{
|
||||
printf("Error writing to eeprom.bin [CREDIT]].");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create all sections from scratch
|
||||
if ((createStaticSection() != 0) || (createNetworkTypeSection() != 0) ||
|
||||
(createEthSection(ETH0) != 0) || (createEthSection(ETH1) != 0) || (createCreditSection() != 0))
|
||||
{
|
||||
printf("Error creating section from scratch.\n");
|
||||
return 1;
|
||||
}
|
||||
addCRCtoBuffer(STATIC);
|
||||
addCRCtoBuffer(NETWORK_TYPE);
|
||||
addCRCtoBuffer(ETH0);
|
||||
addCRCtoBuffer(ETH1);
|
||||
addCRCtoBuffer(CREDIT);
|
||||
if ((writeSectiontoFile(eeprom, STATIC) != 0) || (writeSectiontoFile(eeprom, NETWORK_TYPE) != 0) ||
|
||||
(writeSectiontoFile(eeprom, ETH0) != 0) || (writeSectiontoFile(eeprom, ETH1) != 0) ||
|
||||
(writeSectiontoFile(eeprom, CREDIT) != 0))
|
||||
{
|
||||
printf("Error writing section from scratch.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
5
src/lindbergh/eeprom_settings.h
Normal file
5
src/lindbergh/eeprom_settings.h
Normal file
@ -0,0 +1,5 @@
|
||||
int eepromSettingsInit(FILE *eeprom);
|
||||
int getRegion();
|
||||
int getFreeplay();
|
||||
int setRegion(FILE *eeprom, int region);
|
||||
int setFreeplay(FILE *eeprom, int freeplay);
|
@ -142,102 +142,6 @@ int XStoreName(Display *display, Window w, const char *window_name)
|
||||
return _XStoreName(display, w, gameTitle);
|
||||
}
|
||||
|
||||
int XNextEvent(Display *display, XEvent *event_return)
|
||||
{
|
||||
|
||||
int (*_XNextEvent)(Display *display, XEvent *event_return) = dlsym(RTLD_NEXT, "XNextEvent");
|
||||
int returnValue = _XNextEvent(display, event_return);
|
||||
|
||||
// Return now if we're not emulating JVS
|
||||
if (!getConfig()->emulateJVS)
|
||||
{
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
switch (event_return->type)
|
||||
{
|
||||
|
||||
case KeyRelease:
|
||||
case KeyPress:
|
||||
{
|
||||
switch (event_return->xkey.keycode)
|
||||
{
|
||||
case 28:
|
||||
setSwitch(SYSTEM, BUTTON_TEST, event_return->type == KeyPress);
|
||||
break;
|
||||
case 39:
|
||||
setSwitch(PLAYER_1, BUTTON_SERVICE, event_return->type == KeyPress);
|
||||
break;
|
||||
case 14:
|
||||
incrementCoin(PLAYER_1, event_return->type == KeyPress);
|
||||
break;
|
||||
case 15:
|
||||
incrementCoin(PLAYER_2, event_return->type == KeyPress);
|
||||
break;
|
||||
case 111:
|
||||
setSwitch(PLAYER_1, BUTTON_UP, event_return->type == KeyPress);
|
||||
break;
|
||||
case 116:
|
||||
setSwitch(PLAYER_1, BUTTON_DOWN, event_return->type == KeyPress);
|
||||
break;
|
||||
case 113:
|
||||
setSwitch(PLAYER_1, BUTTON_LEFT, event_return->type == KeyPress);
|
||||
break;
|
||||
case 114:
|
||||
setSwitch(PLAYER_1, BUTTON_RIGHT, event_return->type == KeyPress);
|
||||
break;
|
||||
case 10:
|
||||
setSwitch(PLAYER_1, BUTTON_START, event_return->type == KeyPress);
|
||||
break;
|
||||
case 24:
|
||||
setSwitch(PLAYER_1, BUTTON_1, event_return->type == KeyPress);
|
||||
break;
|
||||
case 25:
|
||||
setSwitch(PLAYER_1, BUTTON_2, event_return->type == KeyPress);
|
||||
break;
|
||||
case 26:
|
||||
setSwitch(PLAYER_1, BUTTON_3, event_return->type == KeyPress);
|
||||
break;
|
||||
case 27:
|
||||
setSwitch(PLAYER_1, BUTTON_4, event_return->type == KeyPress);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
{
|
||||
setAnalogue(ANALOGUE_1, ((double)event_return->xmotion.x / (double)getConfig()->width) * 255);
|
||||
setAnalogue(ANALOGUE_2, ((double)event_return->xmotion.y / (double)getConfig()->height) * 255);
|
||||
}
|
||||
break;
|
||||
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
{
|
||||
switch (event_return->xbutton.button)
|
||||
{
|
||||
case 1: // Trigger
|
||||
setSwitch(PLAYER_1, BUTTON_1, event_return->type == ButtonPress);
|
||||
break;
|
||||
case 3: // Reload
|
||||
setSwitch(PLAYER_1, BUTTON_2, event_return->type == ButtonPress);
|
||||
break;
|
||||
case 9: // Gun Button
|
||||
setSwitch(PLAYER_1, BUTTON_3, event_return->type == ButtonPress);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
int XSetStandardProperties(Display *display, Window window, const char *window_name, const char *icon_name, Pixmap icon_pixmap, char **argv, int argc, XSizeHints *hints)
|
||||
{
|
||||
int (*_XSetStandardProperties)(Display *display, Window window, const char *window_name, const char *icon_name, Pixmap icon_pixmap, char **argv, int argc, XSizeHints *hints) = dlsym(RTLD_NEXT, "XSetStandardProperties");
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <cpuid.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "hook.h"
|
||||
|
||||
@ -27,6 +28,8 @@
|
||||
#include "rideboard.h"
|
||||
#include "securityboard.h"
|
||||
#include "patch.h"
|
||||
#include "pcidata.h"
|
||||
#include "input.h"
|
||||
|
||||
#define HOOK_FILE_NAME "/dev/zero"
|
||||
|
||||
@ -37,10 +40,12 @@
|
||||
|
||||
#define CPUINFO 0
|
||||
#define OSRELEASE 1
|
||||
#define PCI_CARD_1F0 2
|
||||
|
||||
int hooks[5] = {-1, -1, -1, -1};
|
||||
FILE *fileHooks[2] = {NULL, NULL};
|
||||
int fileRead[2] = {0, 0};
|
||||
FILE *fileHooks[3] = {NULL, NULL, NULL};
|
||||
int fileRead[3] = {0, 0, 0};
|
||||
char envpath[100];
|
||||
uint32_t elf_crc = 0;
|
||||
|
||||
cpuvendor cpu_vendor = {0};
|
||||
@ -59,8 +64,6 @@ static void handleSegfault(int signal, siginfo_t *info, void *ptr)
|
||||
{
|
||||
ucontext_t *ctx = ptr;
|
||||
|
||||
//printf("Caught segfault at address %p\n", info->si_addr);
|
||||
|
||||
// Get the address of the instruction causing the segfault
|
||||
uint8_t *code = (uint8_t *)ctx->uc_mcontext.gregs[REG_EIP];
|
||||
|
||||
@ -130,7 +133,6 @@ static void handleSegfault(int signal, siginfo_t *info, void *ptr)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void __attribute__((constructor)) hook_init()
|
||||
{
|
||||
printf("SEGA Lindbergh Loader\nRobert Dilley 2023\nNot for public consumption\n\n");
|
||||
@ -149,7 +151,7 @@ void __attribute__((constructor)) hook_init()
|
||||
|
||||
initConfig();
|
||||
|
||||
if(initPatch() != 0)
|
||||
if (initPatch() != 0)
|
||||
exit(1);
|
||||
|
||||
if (initEeprom() != 0)
|
||||
@ -176,10 +178,13 @@ void __attribute__((constructor)) hook_init()
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(initInput() != 0)
|
||||
exit(1);
|
||||
|
||||
securityBoardSetDipResolution(getConfig()->width, getConfig()->height);
|
||||
|
||||
printf("Now emulating %s", getGameName());
|
||||
if(getConfig()->gameStatus == WORKING)
|
||||
if (getConfig()->gameStatus == WORKING)
|
||||
{
|
||||
printf((" - Game is in working state.\n"));
|
||||
}
|
||||
@ -198,14 +203,12 @@ int open(const char *pathname, int flags)
|
||||
if (strcmp(pathname, "/dev/lbb") == 0)
|
||||
{
|
||||
hooks[BASEBOARD] = _open(HOOK_FILE_NAME, flags);
|
||||
printf("Baseboard opened %d\n", hooks[BASEBOARD]);
|
||||
return hooks[BASEBOARD];
|
||||
}
|
||||
|
||||
if (strcmp(pathname, "/dev/i2c/0") == 0)
|
||||
{
|
||||
hooks[EEPROM] = _open(HOOK_FILE_NAME, flags);
|
||||
printf("EEPROM opened %d\n", hooks[EEPROM]);
|
||||
return hooks[EEPROM];
|
||||
}
|
||||
|
||||
@ -215,7 +218,7 @@ int open(const char *pathname, int flags)
|
||||
return -1;
|
||||
|
||||
hooks[SERIAL0] = _open(HOOK_FILE_NAME, flags);
|
||||
printf("SERIAL0 Opened %d\n", hooks[SERIAL0]);
|
||||
printf("Warning: SERIAL0 Opened %d\n", hooks[SERIAL0]);
|
||||
return hooks[SERIAL0];
|
||||
}
|
||||
|
||||
@ -225,7 +228,7 @@ int open(const char *pathname, int flags)
|
||||
return -1;
|
||||
|
||||
hooks[SERIAL1] = _open(HOOK_FILE_NAME, flags);
|
||||
printf("SERIAL1 opened %d\n", hooks[SERIAL1]);
|
||||
printf("Warning: SERIAL1 opened %d\n", hooks[SERIAL1]);
|
||||
return hooks[SERIAL1];
|
||||
}
|
||||
|
||||
@ -252,7 +255,7 @@ FILE *fopen(const char *restrict pathname, const char *restrict mode)
|
||||
return _fopen("lindbergrc", mode);
|
||||
}
|
||||
|
||||
if (strcmp(pathname, "/usr/lib/boot/logo.tga") == 0)
|
||||
if ((strcmp(pathname, "/usr/lib/boot/logo.tga") == 0) || (strcmp(pathname, "/usr/lib/boot/logo.tga") == 0))
|
||||
{
|
||||
return _fopen("logo.tga", mode);
|
||||
}
|
||||
@ -274,6 +277,26 @@ FILE *fopen(const char *restrict pathname, const char *restrict mode)
|
||||
return fileHooks[CPUINFO];
|
||||
}
|
||||
|
||||
if (strcmp(pathname, "/usr/lib/boot/logo_red.tga") == 0)
|
||||
{
|
||||
return _fopen("logo_red.tga", mode);
|
||||
}
|
||||
if (strcmp(pathname, "/usr/lib/boot/SEGA_KakuGothic-DB-Roman_12.tga") == 0)
|
||||
{
|
||||
return _fopen("SEGA_KakuGothic-DB-Roman_12.tga", mode);
|
||||
}
|
||||
|
||||
if (strcmp(pathname, "/usr/lib/boot/SEGA_KakuGothic-DB-Roman_12.abc") == 0)
|
||||
{
|
||||
return _fopen("SEGA_KakuGothic-DB-Roman_12.abc", mode);
|
||||
}
|
||||
|
||||
if (strcmp(pathname, "/proc/bus/pci/00/1f.0") == 0)
|
||||
{
|
||||
fileRead[PCI_CARD_1F0] = 0;
|
||||
fileHooks[PCI_CARD_1F0] = _fopen(HOOK_FILE_NAME, mode);
|
||||
return fileHooks[PCI_CARD_1F0];
|
||||
}
|
||||
return _fopen(pathname, mode);
|
||||
}
|
||||
|
||||
@ -313,6 +336,20 @@ FILE *fopen64(const char *pathname, const char *mode)
|
||||
return _fopen64(pathname, mode);
|
||||
}
|
||||
|
||||
int fclose(FILE *stream)
|
||||
{
|
||||
int (*_fclose)(FILE *stream) = dlsym(RTLD_NEXT, "fclose");
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (fileHooks[i] == stream)
|
||||
{
|
||||
int r = _fclose(stream);
|
||||
fileHooks[i] = NULL;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return _fclose(stream);
|
||||
}
|
||||
int openat(int dirfd, const char *pathname, int flags)
|
||||
{
|
||||
int (*_openat)(int dirfd, const char *pathname, int flags) = dlsym(RTLD_NEXT, "openat");
|
||||
@ -404,6 +441,18 @@ ssize_t read(int fd, void *buf, size_t count)
|
||||
return _read(fd, buf, count);
|
||||
}
|
||||
|
||||
size_t fread(void *buf, size_t size, size_t count, FILE *stream)
|
||||
{
|
||||
size_t (*_fread)(void *buf, size_t size, size_t count, FILE *stream) = dlsym(RTLD_NEXT, "fread");
|
||||
|
||||
if (stream == fileHooks[PCI_CARD_1F0])
|
||||
{
|
||||
memcpy(buf, pcidata, 68);
|
||||
return 68;
|
||||
}
|
||||
return _fread(buf, size, count, stream);
|
||||
}
|
||||
|
||||
ssize_t write(int fd, const void *buf, size_t count)
|
||||
{
|
||||
int (*_write)(int fd, const void *buf, size_t count) = dlsym(RTLD_NEXT, "write");
|
||||
@ -565,31 +614,34 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
|
||||
/**
|
||||
* Function to calculate CRC32 checksum in memory.
|
||||
*/
|
||||
uint32_t get_crc32(const char *s,size_t n)
|
||||
*/
|
||||
uint32_t get_crc32(const char *s, size_t n)
|
||||
{
|
||||
uint32_t crc=0xFFFFFFFF;
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
|
||||
for(size_t i=0;i<n;i++) {
|
||||
char ch=s[i];
|
||||
for(size_t j=0;j<8;j++) {
|
||||
uint32_t b=(ch^crc)&1;
|
||||
crc>>=1;
|
||||
if(b) crc=crc^0xEDB88320;
|
||||
ch>>=1;
|
||||
}
|
||||
for (size_t i = 0; i < n; i++)
|
||||
{
|
||||
char ch = s[i];
|
||||
for (size_t j = 0; j < 8; j++)
|
||||
{
|
||||
uint32_t b = (ch ^ crc) & 1;
|
||||
crc >>= 1;
|
||||
if (b)
|
||||
crc = crc ^ 0xEDB88320;
|
||||
ch >>= 1;
|
||||
}
|
||||
}
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function to get the offset and size of the execution program in memory of the ELF we hook to.
|
||||
*/
|
||||
static int callback(struct dl_phdr_info *info, size_t size, void *data)
|
||||
*/
|
||||
static int callback(struct dl_phdr_info *info, size_t size, void *data)
|
||||
{
|
||||
if((info->dlpi_phnum >= 3) && (info->dlpi_phdr[2].p_type == PT_LOAD) && (info->dlpi_phdr[2].p_flags == 5))
|
||||
if ((info->dlpi_phnum >= 3) && (info->dlpi_phdr[2].p_type == PT_LOAD) && (info->dlpi_phdr[2].p_flags == 5))
|
||||
{
|
||||
elf_crc = get_crc32((void *)(info->dlpi_addr + info->dlpi_phdr[2].p_vaddr+10),128);
|
||||
elf_crc = get_crc32((void *)(info->dlpi_addr + info->dlpi_phdr[2].p_vaddr + 10), 128);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -599,7 +651,7 @@ void getCPUID()
|
||||
unsigned eax;
|
||||
eax = 0;
|
||||
__get_cpuid(0, &eax, &cpu_vendor.ebx, &cpu_vendor.ecx, &cpu_vendor.edx);
|
||||
printf("CPU Vendor: %.4s%.4s%.4s\n", (const char*)&cpu_vendor.ebx,(const char*)&cpu_vendor.edx,(const char*)&cpu_vendor.ecx);
|
||||
printf("CPU Vendor: %.4s%.4s%.4s\n", (const char *)&cpu_vendor.ebx, (const char *)&cpu_vendor.edx, (const char *)&cpu_vendor.ecx);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -617,6 +669,33 @@ int setenv(const char *name, const char *value, int overwrite)
|
||||
return _setenv(name, value, overwrite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fake the TEA_DIR environment variable to games that require it to run
|
||||
*/
|
||||
char *getenv(const char *name)
|
||||
{
|
||||
char *(*_getenv)(const char *name) = dlsym(RTLD_NEXT, "getenv");
|
||||
|
||||
if ((strcmp(name, "TEA_DIR") == 0) && getConfig()->game == VIRTUA_TENNIS_3)
|
||||
{
|
||||
if (getcwd(envpath, 100) == NULL)
|
||||
return "";
|
||||
char *ptr = strrchr(envpath, '/');
|
||||
if (ptr == NULL)
|
||||
return "";
|
||||
*ptr = '\0';
|
||||
return envpath;
|
||||
}
|
||||
else if (strcmp(name, "TEA_DIR") == 0)
|
||||
{
|
||||
if (getcwd(envpath, 100) == NULL)
|
||||
return "";
|
||||
return envpath;
|
||||
}
|
||||
|
||||
return _getenv(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the game unsetting the DISPLAY environment variable
|
||||
*/
|
||||
|
117
src/lindbergh/input.c
Normal file
117
src/lindbergh/input.c
Normal file
@ -0,0 +1,117 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "jvs.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <GL/freeglut.h>
|
||||
#include <GL/glx.h>
|
||||
#include <X11/extensions/xf86vmode.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
int initInput()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XNextEvent(Display *display, XEvent *event_return)
|
||||
{
|
||||
|
||||
int (*_XNextEvent)(Display *display, XEvent *event_return) = dlsym(RTLD_NEXT, "XNextEvent");
|
||||
int returnValue = _XNextEvent(display, event_return);
|
||||
|
||||
// Return now if we're not emulating JVS
|
||||
if (!getConfig()->emulateJVS)
|
||||
{
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
switch (event_return->type)
|
||||
{
|
||||
|
||||
case KeyRelease:
|
||||
case KeyPress:
|
||||
{
|
||||
switch (event_return->xkey.keycode)
|
||||
{
|
||||
case 28:
|
||||
setSwitch(SYSTEM, BUTTON_TEST, event_return->type == KeyPress);
|
||||
break;
|
||||
case 39:
|
||||
setSwitch(PLAYER_1, BUTTON_SERVICE, event_return->type == KeyPress);
|
||||
break;
|
||||
case 14:
|
||||
incrementCoin(PLAYER_1, event_return->type == KeyPress);
|
||||
break;
|
||||
case 15:
|
||||
incrementCoin(PLAYER_2, event_return->type == KeyPress);
|
||||
break;
|
||||
case 111:
|
||||
setSwitch(PLAYER_1, BUTTON_UP, event_return->type == KeyPress);
|
||||
break;
|
||||
case 116:
|
||||
setSwitch(PLAYER_1, BUTTON_DOWN, event_return->type == KeyPress);
|
||||
break;
|
||||
case 113:
|
||||
setSwitch(PLAYER_1, BUTTON_LEFT, event_return->type == KeyPress);
|
||||
break;
|
||||
case 114:
|
||||
setSwitch(PLAYER_1, BUTTON_RIGHT, event_return->type == KeyPress);
|
||||
break;
|
||||
case 10:
|
||||
setSwitch(PLAYER_1, BUTTON_START, event_return->type == KeyPress);
|
||||
break;
|
||||
case 24:
|
||||
setSwitch(PLAYER_1, BUTTON_1, event_return->type == KeyPress);
|
||||
break;
|
||||
case 25:
|
||||
setSwitch(PLAYER_1, BUTTON_2, event_return->type == KeyPress);
|
||||
break;
|
||||
case 26:
|
||||
setSwitch(PLAYER_1, BUTTON_3, event_return->type == KeyPress);
|
||||
break;
|
||||
case 27:
|
||||
setSwitch(PLAYER_1, BUTTON_4, event_return->type == KeyPress);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
{
|
||||
setAnalogue(ANALOGUE_1, ((double)event_return->xmotion.x / (double)getConfig()->width) * 255);
|
||||
setAnalogue(ANALOGUE_2, ((double)event_return->xmotion.y / (double)getConfig()->height) * 255);
|
||||
}
|
||||
break;
|
||||
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
{
|
||||
switch (event_return->xbutton.button)
|
||||
{
|
||||
case 1: // Trigger
|
||||
setSwitch(PLAYER_1, BUTTON_1, event_return->type == ButtonPress);
|
||||
break;
|
||||
case 3: // Reload
|
||||
setSwitch(PLAYER_1, BUTTON_2, event_return->type == ButtonPress);
|
||||
break;
|
||||
case 9: // Gun Button
|
||||
setSwitch(PLAYER_1, BUTTON_3, event_return->type == ButtonPress);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
1
src/lindbergh/input.h
Normal file
1
src/lindbergh/input.h
Normal file
@ -0,0 +1 @@
|
||||
int initInput();
|
@ -7,6 +7,7 @@
|
||||
#include "patch.h"
|
||||
#include "config.h"
|
||||
#include "hook.h"
|
||||
#include "securityboard.h"
|
||||
|
||||
extern cpuvendor cpu_vendor;
|
||||
|
||||
@ -89,6 +90,76 @@ int amDongleUpdate()
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amLibInit()
|
||||
{
|
||||
uint32_t *amLibContext = (uint32_t *)0x08dfa2c0; // 0x0809cb00;
|
||||
*amLibContext = 1;
|
||||
uint32_t *amLibInitializad = (uint32_t *)0x08dfa2c4; // 0x0809cb04;
|
||||
uint16_t *amLibPort1 = (uint16_t *)(0x08dfa2c4 + 4); //(0x0809cb04 + 4);
|
||||
uint16_t *amLibPort2 = (uint16_t *)(0x08dfa2c4 + 4); //(0x0809cb04 + 6);
|
||||
uint32_t *bcLibInitialized = (uint32_t *)(0x08dfa2c4 + 8); // 0x0809cb0c;
|
||||
*amLibInitializad = 1;
|
||||
*amLibPort1 = 0xd000;
|
||||
*amLibPort2 = 0x0004;
|
||||
*bcLibInitialized = 0;
|
||||
int res = ((int (*)(void))0x084dedc4)(); // 0x08065d80)();
|
||||
if (res == 1)
|
||||
*bcLibInitialized = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amDipswInit()
|
||||
{
|
||||
uint32_t *amDipswContext = (uint32_t *)0x08df9cec; // 0x0809c12c;
|
||||
uint32_t *amDipswContext1 = (uint32_t *)(0x08df9cec + 4); //(0x0809c12c + 4);
|
||||
uint32_t *amDipswContext2 = (uint32_t *)(0x08df9cec + 8); //(0x0809c12c + 8);
|
||||
uint32_t *amDipswContext3 = (uint32_t *)(0x08df9cec + 12); //(0x0809c12c + 12);
|
||||
// typedef void *(*___constant_c_and_count_memset)(uint32_t *, int, size_t);
|
||||
//___constant_c_and_count_memset func = (___constant_c_and_count_memset)//0x0805c3d5;
|
||||
// func(amDipswContext, 0, 4);
|
||||
*amDipswContext = 1;
|
||||
*amDipswContext1 = 1;
|
||||
*amDipswContext2 = 1;
|
||||
*amDipswContext3 = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_binary(unsigned int number)
|
||||
{
|
||||
if (number >> 1)
|
||||
{
|
||||
print_binary(number >> 1);
|
||||
}
|
||||
putc((number & 1) ? '1' : '0', stdout);
|
||||
}
|
||||
|
||||
int amDipswGetData(uint8_t *dip)
|
||||
{
|
||||
// printf("amDipswGetData Called!!!!!\n");
|
||||
uint8_t result;
|
||||
uint32_t data;
|
||||
|
||||
securityBoardIn(0x38, &data);
|
||||
|
||||
result = (~data & 4) != 0; // Test Button
|
||||
if ((~data & 8) != 0)
|
||||
result |= 2; // Service Button
|
||||
if ((~data & 0x10) != 0)
|
||||
result |= 4; // ??
|
||||
if ((char)data >= 0)
|
||||
result |= 8; // ??
|
||||
if ((~data & 0x100) != 0)
|
||||
result |= 0x10; // Rotation
|
||||
if ((~data & 0x200) != 0)
|
||||
result |= 0x20; // Resolution Dip 4
|
||||
if ((~data & 0x400) != 0)
|
||||
result |= 0x40; // Resolution Dip 5
|
||||
if ((~data & 0x800) != 0)
|
||||
result |= 0x80; // Resolution Dip 6
|
||||
*dip = result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _putConsole(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
@ -159,6 +230,10 @@ int initPatch()
|
||||
detourFunction(0x084d5b40, amDongleInit);
|
||||
detourFunction(0x084d45f9, amDongleIsAvailable);
|
||||
detourFunction(0x084d4fef, amDongleUpdate);
|
||||
detourFunction(0x084d44fc, stub0);
|
||||
detourFunction(0x084d4485, amDipswGetData);
|
||||
detourFunction(0x084d9118, amLibInit);
|
||||
detourFunction(0x084d438c, amDipswInit);
|
||||
}
|
||||
break;
|
||||
case AFTER_BURNER_CLIMAX_REVA:
|
||||
@ -282,28 +357,31 @@ int initPatch()
|
||||
|
||||
case LETS_GO_JUNGLE:
|
||||
{
|
||||
setVariable(0x08c083a4, 2); // amBackupDebugLevel
|
||||
setVariable(0x08c083c0, 2); // amCreditDebugLevel
|
||||
setVariable(0x08c08618, 2); // amDipswDebugLevel
|
||||
setVariable(0x08c0861c, 2); // amDongleDebugLevel
|
||||
setVariable(0x08c08620, 2); // amEepromDebugLevel
|
||||
setVariable(0x08c08624, 2); // amHwmonitorDebugLevel
|
||||
setVariable(0x08c08628, 2); // amJvsDebugLevel
|
||||
setVariable(0x08c0862c, 2); // amLibDebugLevel
|
||||
setVariable(0x08c08630, 2); // amMiscDebugLevel
|
||||
setVariable(0x08c08638, 2); // amSysDataDebugLevel
|
||||
setVariable(0x08c08640, 2); // bcLibDebugLevel
|
||||
setVariable(0x08c08634, 2); // amOsinfoDebugLevel
|
||||
setVariable(0x08c08644, 0x0FFFFFFF); // s_logMask
|
||||
setVariable(0x08c083a4, 2); // amBackupDebugLevel
|
||||
setVariable(0x08c083c0, 2); // amCreditDebugLevel
|
||||
setVariable(0x08c08618, 2); // amDipswDebugLevel
|
||||
setVariable(0x08c0861c, 2); // amDongleDebugLevel
|
||||
setVariable(0x08c08620, 2); // amEepromDebugLevel
|
||||
setVariable(0x08c08624, 2); // amHwmonitorDebugLevel
|
||||
setVariable(0x08c08628, 2); // amJvsDebugLevel
|
||||
setVariable(0x08c0862c, 2); // amLibDebugLevel
|
||||
setVariable(0x08c08630, 2); // amMiscDebugLevel
|
||||
setVariable(0x08c08638, 2); // amSysDataDebugLevel
|
||||
setVariable(0x08c08640, 2); // bcLibDebugLevel
|
||||
setVariable(0x08c08634, 2); // amOsinfoDebugLevel
|
||||
setVariable(0x08c08644, 0x0FFFFFFF); // s_logMask
|
||||
detourFunction(0x08074a8c, _putConsole); // Debug Messages
|
||||
|
||||
detourFunction(0x084e50d8, amDongleInit);
|
||||
detourFunction(0x084e5459, amDongleIsAvailable);
|
||||
detourFunction(0x084e537d, amDongleUpdate);
|
||||
detourFunction(0x08074a8c, _putConsole);
|
||||
detourFunction(0x084e500e, amDipswGetData);
|
||||
|
||||
setVariable(0x080d1f02, 0x90909090); // Patch acpSystem::checkDongle
|
||||
setVariable(0x080d1f06, 0xE8C3C990); // Patch acpSystem::checkDongle
|
||||
setVariable(0x0807b76a, 0xc2839090); // Patch initializeArcadeBackup
|
||||
// setVariable(0x082E006b, 0x00000280); // Set ResX
|
||||
// setVariable(0x082E0078, 0x000001E0); // Set ResY
|
||||
// setVariable(0x082E006b, 0x00000280); // Set ResX
|
||||
// setVariable(0x082E0078, 0x000001E0); // Set ResY
|
||||
|
||||
detourFunction(0x084e4efc, stub0); // Stub amDipswInit
|
||||
detourFunction(0x084e500e, stub0); // Stub amDipswGetData
|
||||
@ -366,10 +444,12 @@ int initPatch()
|
||||
setVariable(0x08d719e0, 2); // bcLibDebugLevel
|
||||
setVariable(0x08d719d4, 2); // amOsinfoDebugLevel
|
||||
setVariable(0x08d719e4, 0x0FFFFFFF); // s_logMask
|
||||
|
||||
|
||||
detourFunction(0x086e2336, amDongleInit);
|
||||
detourFunction(0x086e0d81, amDongleIsAvailable);
|
||||
detourFunction(0x086e17e5, amDongleUpdate);
|
||||
detourFunction(0x086e0c0d, amDipswGetData);
|
||||
detourFunction(0x086e0c84, stub0);
|
||||
detourFunction(0x0808f9a8, _putConsole);
|
||||
|
||||
setVariable(0x080dad63, 0x90909090); // Patch acpSystem::checkDongle
|
||||
@ -377,6 +457,36 @@ int initPatch()
|
||||
setVariable(0x0807e609, 0x90909090); // Patch initializeArcadeBackup
|
||||
setVariable(0x0807e60D, 0xC2839090); // Patch initializeArcadeBackup
|
||||
}
|
||||
break;
|
||||
case SEGABOOT_2_4_SYM:
|
||||
{
|
||||
detourFunction(0x0805e8b0, amDongleInit);
|
||||
detourFunction(0x0805ebc3, amDongleIsAvailable);
|
||||
detourFunction(0x0805eb2a, amDongleUpdate);
|
||||
// detourFunction(0x08062cf8, amLibInit);
|
||||
// detourFunction(0x0805c200, amDipswInit);
|
||||
detourFunction(0x0805c30b, amDipswGetData);
|
||||
}
|
||||
break;
|
||||
case VIRTUA_TENNIS_3:
|
||||
{
|
||||
detourFunction(0x0831c724, amDongleInit);
|
||||
detourFunction(0x0831ca37, amDongleIsAvailable);
|
||||
detourFunction(0x0831c99e, amDongleUpdate);
|
||||
detourFunction(0x0831c5d7, amDipswGetData);
|
||||
detourFunction(0x0831c64f, stub0);
|
||||
setVariable(0x0827ae1b, 0x34891beb); // Disable Fullscreen
|
||||
}
|
||||
case VIRTUA_TENNIS_3_TEST:
|
||||
{
|
||||
detourFunction(0x0815f610, amDongleInit);
|
||||
detourFunction(0x0815f923, amDongleIsAvailable);
|
||||
detourFunction(0x0815f88a, amDongleUpdate);
|
||||
detourFunction(0x0815d06b, amDipswGetData);
|
||||
detourFunction(0x0815d0e3, stub0);
|
||||
// setVariable(0x0827ae1b, 0x34891beb); //Disable Fullscreen
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Don't do any patches for random games
|
||||
break;
|
||||
|
28
src/lindbergh/pcidata.h
Normal file
28
src/lindbergh/pcidata.h
Normal file
@ -0,0 +1,28 @@
|
||||
const char pcidata[256] = {
|
||||
0x86, 0x80, 0x18, 0x29, 0x03, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01,
|
||||
0x06, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xf4, 0x1a, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06,
|
||||
0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x8a, 0x8b,
|
||||
0x8b, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x8a, 0x8b, 0x8b, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0,
|
||||
0xd1, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const int pcidata_length = 256;
|
@ -77,7 +77,6 @@ int securityBoardSetDipSwitch(int switchNumber, int value)
|
||||
|
||||
int securityBoardSetSwitch(JVSInput switchNumber, int value)
|
||||
{
|
||||
printf("Pressed\n");
|
||||
switch (switchNumber)
|
||||
{
|
||||
case BUTTON_TEST:
|
||||
@ -107,26 +106,26 @@ int securityBoardIn(uint16_t port, uint32_t *data)
|
||||
case SECURITY_BOARD_FRONT_PANEL:
|
||||
{
|
||||
uint32_t result = 0xFFFFFFFF;
|
||||
if (securityBoard.serviceSwitch)
|
||||
result &= ~0x08;
|
||||
if (securityBoard.testSwitch)
|
||||
result &= ~0x04;
|
||||
if (securityBoard.dipSwitch[6])
|
||||
if (securityBoard.dipSwitch[6]) // bit12
|
||||
result &= ~0x800; // DIP 6
|
||||
if (securityBoard.dipSwitch[5])
|
||||
if (securityBoard.dipSwitch[5]) // bit11
|
||||
result &= ~0x400; // DIP 5
|
||||
if (securityBoard.dipSwitch[4])
|
||||
if (securityBoard.dipSwitch[4]) // bit10
|
||||
result &= ~0x200; // DIP 4
|
||||
if (securityBoard.dipSwitch[3])
|
||||
if (securityBoard.dipSwitch[3]) // bit9
|
||||
result &= ~0x100; // DIP 3
|
||||
if (securityBoard.dipSwitch[2])
|
||||
if (securityBoard.dipSwitch[2]) // bit8
|
||||
result &= ~0x80; // DIP 2
|
||||
if (securityBoard.dipSwitch[1])
|
||||
if (securityBoard.dipSwitch[1]) // bit7
|
||||
result &= ~0x40; // DIP 1
|
||||
if (securityBoard.dipSwitch[8])
|
||||
if (securityBoard.dipSwitch[8]) // bit6
|
||||
result &= ~0x20;
|
||||
if (securityBoard.dipSwitch[7])
|
||||
if (securityBoard.dipSwitch[7]) // bit5
|
||||
result &= ~0x10;
|
||||
if (securityBoard.serviceSwitch) // bit4
|
||||
result &= ~0x08;
|
||||
if (securityBoard.testSwitch) // bit3
|
||||
result &= ~0x04;
|
||||
*data = result;
|
||||
}
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user