From 59c18b3c2ca9379bae7a21e132d89a49b4cca150 Mon Sep 17 00:00:00 2001 From: Bobby Dilley Date: Tue, 12 Dec 2023 14:00:52 +0000 Subject: [PATCH] Add all games --- .vscode/settings.json | 3 +- docs/games.txt | 94 ++++++++++++++++++++++ docs/lindbergh.conf | 41 ++++++---- src/hookcrc32/Makefile | 17 ---- src/hookcrc32/hookcrc32.c | 95 ---------------------- src/hookcrc32/hookcrc32.so | Bin 16900 -> 0 bytes src/lindbergh/config.c | 160 ++++++++++++++++++++++++++----------- src/lindbergh/config.h | 53 ++++++++---- src/lindbergh/graphics.c | 6 +- src/lindbergh/hook.c | 12 +-- src/lindbergh/jvs.c | 14 +++- src/lindbergh/patch.c | 83 +++++++++++-------- 12 files changed, 343 insertions(+), 235 deletions(-) create mode 100644 docs/games.txt delete mode 100644 src/hookcrc32/Makefile delete mode 100644 src/hookcrc32/hookcrc32.c delete mode 100755 src/hookcrc32/hookcrc32.so diff --git a/.vscode/settings.json b/.vscode/settings.json index 71a6611..fdc3f2f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,6 +8,7 @@ "stdarg.h": "c", "ioctl.h": "c", "segaeax.h": "c", - "passthrough.h": "c" + "passthrough.h": "c", + "pthread.h": "c" } } diff --git a/docs/games.txt b/docs/games.txt new file mode 100644 index 0000000..4a99a71 --- /dev/null +++ b/docs/games.txt @@ -0,0 +1,94 @@ + +2SPICY +After Burner +After Burner Climax +After Burner Climax [Rev.A] +After Burner Climax [Rev.B] +After Burner Climax SDX +After Burner Climax SDX [Rev.A] +AMI-GYO +Ami No.3 +Answer x Answer +Answer x Answer 2 +Answer x Answer Live! +Blackjack Nailed Ace +Club Majesty - Extend - Cloud Nine +Club Majesty - Extend - Wheel Maniacs +Club Majesty Formal: Attractive Deck Poker +Club Majesty Formal: Cosmic Challenge +Club Majesty Formal: Cosmic Challenge [Rev.C] +Club Majesty: Gatling Poker +Club Majesty: Where's Wally! +Derby Owners Club 2008 Feel the Rush +Derby Owners Club 2009 Ride for the live +Ghost Squad Evolution +Harley Davidson King of the Road +HOTD4 +HOTD4SP +HOTD EX +Hummer +Hummer Extreme +Hummer Extreme Edition MDX +Info Station 2 [Rev.C] +Initial D Arcade Stage 4 +Initial D Arcade Stage 4 [Rev.A] +Initial D Arcade Stage 4 [Rev.B] +Initial D Arcade Stage 4 [Rev.C] +Initial D Arcade Stage 4 [Rev.D] +Initial D Arcade Stage 4 [Rev.G] +Initial D Arcade Stage 5 +Initial D Arcade Stage 5 Exp 2.0 +Initial D Arcade Stage 5 [Rev.A] +Let's Go Jungle +Let's Go Jungle Special +MJ4 Evolution +Outrun 2 SP SDX +Outrun 2 SP SDX [Rev.A] +Primeval Hunt +Rambo +Rambo (China) +Router Update (for VTF) +R-Tuned +Sangokushi Taisen 2 +Sangokushi Taisen 3 +Sega Network Casino Club STD +Sega Network Casino Club Ver.2 +Sega Network Casino Club Ver.2 [Rev.B] +Sega Network Casino Club Ver.3 +Sega Race TV +Sengokushi Taisen3 War Begins +Star Horse 2 Fifth Expansion [Rev.B] +Star Horse 2 Fifth Expansion [Rev.D] +Star Horse 2 Fifth Expansion [Rev.E] +Star Horse 2 Final Destination +Starhorse 2 Fourth Ambition +Star Horse 2 Fourth Ambition +Star Horse 2 New Generation +Star Horse 2 Second Fusion +Star Horse 2 Third Evolution +Star Horse 2 Third Evolution (Hong Kong) +Taisen Mahjong 4 (1.0) +Taisen Mahjong 4 (2.0) +Taisen Mahjong 4 (3.0) +Taisen Mahjong 4 (4.0) +Taisen Mahjong 4 (5.0) +Taisen Mahjong 4 (6.0) +Taisen Mahjong 4 (7.0) +Taisen Mahjong 4 (8.0) +toAmi-Gyo +to AMI GYO +VBIOS Update (2.0) +VBIOS Update (3.0) +VBIOS Update (for VTF) +Virtua Fighter 5 +Virtua Fighter 5 Final Showdown +Virtua Fighter 5 Final Showdown [Rev.A] +Virtua Fighter 5 R +Virtua Fighter 5 [Rev.A] +Virtua Fighter 5 [Rev.B] +Virtua Fighter 5 [Rev.E] +Virtua Fighter 5 R [Rev.D] +Virtua Tennis 3 +World Club Championship Football 2008-2009 +World Club Championship Football 2009-2010 [ASIA] +World Club Championship Football 2009-2010 [JP] diff --git a/docs/lindbergh.conf b/docs/lindbergh.conf index d88f2a1..4964038 100644 --- a/docs/lindbergh.conf +++ b/docs/lindbergh.conf @@ -22,26 +22,26 @@ WIDTH 640 # Set the requested dip switch height here HEIGHT 480 -# 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 - -# 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 - -# 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 - # Set if the emulator should emulate JVS and use the keyboard/mouse for controls. # 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_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 + +# 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 + +# 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 + # Define the path to pass the JVS packets to # JVS_PATH /dev/ttyUSB0 @@ -54,5 +54,14 @@ EMULATE_JVS 1 # Define the path to pass the motionboard packets to # MOTIONBOARD_PATH /dev/ttyUSB0 +# Define the path to the sram.bin file +# SRAM_PATH sram.bin + +# Define the path to the eeprom.bin file +# 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 diff --git a/src/hookcrc32/Makefile b/src/hookcrc32/Makefile deleted file mode 100644 index 4a2e6f4..0000000 --- a/src/hookcrc32/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -CC=gcc -m32 -CFLAGS = -g -O0 -fPIC -m32 -Wall -Werror -Wno-unused-variable -Wno-unused-function -LD = g++ -m32 -LDFLAGS = -Wl,-z,defs -rdynamic -static-libstdc++ -static-libgcc -lc -ldl -lGL -lglut -lX11 -lm -lpthread -shared -nostdlib - -BUILD = build - -OBJS := $(patsubst %.c,%.o,$(wildcard *.c)) - -all: hookcrc32.so - -hookcrc32.so: $(OBJS) - $(LD) $(OBJS) $(LDFLAGS) $(CFLAGS) -o hookcrc32.so - rm -f *.o - -clean: - rm -f hookcrc32.so diff --git a/src/hookcrc32/hookcrc32.c b/src/hookcrc32/hookcrc32.c deleted file mode 100644 index 9f7e5fc..0000000 --- a/src/hookcrc32/hookcrc32.c +++ /dev/null @@ -1,95 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include - -static struct { - ElfW(Addr) start, end; -} *segments; -static int n; -static int (*real_main)(int argc,char **argv); - -uint32_t __crc32(const char *s,size_t n) { - uint32_t crc=0xFFFFFFFF; - - for(size_t i=0;i>=1; - if(b) crc=crc^0xEDB88320; - ch>>=1; - } - } - return ~crc; -} - -static int callback(struct dl_phdr_info *info, size_t size, void *data) { - /*n = info->dlpi_phnum; - segments = malloc(n * sizeof *segments); - for(int i = 0; i < n; ++i) { - segments[i].start = info->dlpi_addr + info->dlpi_phdr[i].p_vaddr; - segments[i].end = info->dlpi_addr + info->dlpi_phdr[i].p_vaddr + info->dlpi_phdr[i].p_memsz; - } - char *type; - int p_type; - printf("Name: \"%s\" (%d segments)\n", info->dlpi_name, info->dlpi_phnum); - for (int j = 0; j < info->dlpi_phnum; j++) { - p_type = info->dlpi_phdr[j].p_type; - type = (p_type == PT_LOAD) ? "PT_LOAD" : - (p_type == PT_DYNAMIC) ? "PT_DYNAMIC" : - (p_type == PT_INTERP) ? "PT_INTERP" : - (p_type == PT_NOTE) ? "PT_NOTE" : - (p_type == PT_INTERP) ? "PT_INTERP" : - (p_type == PT_PHDR) ? "PT_PHDR" : - (p_type == PT_TLS) ? "PT_TLS" : - (p_type == PT_GNU_EH_FRAME) ? "PT_GNU_EH_FRAME" : - (p_type == PT_GNU_STACK) ? "PT_GNU_STACK" : - (p_type == PT_GNU_RELRO) ? "PT_GNU_RELRO" : NULL; - - printf(" %2d: [%14p; memsz:0x%7x; size:0x%7x] flags: 0x%x; ", j, - (void *) (info->dlpi_addr + info->dlpi_phdr[j].p_vaddr), - info->dlpi_phdr[j].p_memsz, info->dlpi_phdr[j].p_filesz ,info->dlpi_phdr[j].p_flags); - if (type != NULL) - printf("%s\n", type); - else - printf("[other (0x%x)]\n", p_type);*/ - if((info->dlpi_phnum >= 3) && (info->dlpi_phdr[2].p_type == PT_LOAD) && (info->dlpi_phdr[2].p_flags == 5)) - { - // printf("Aca voy a dumpear el codigo:\n"); - //FILE *file = fopen("dump.bin","w+b"); - - //fwrite((void *)(info->dlpi_addr + info->dlpi_phdr[2].p_vaddr)+10,128,1,file); - //fclose(file); - int crc = 0; - crc = __crc32((void *)(info->dlpi_addr + info->dlpi_phdr[2].p_vaddr+10),128); - printf("Crc32: 0x%x\n",crc); - } - //} - return 1; -} - -__attribute__((__constructor__)) -static void setup(void) { - dl_iterate_phdr(callback, NULL); - //real_main = dlsym(RTLD_NEXT, "main"); - //exit(0); -} - -__attribute__((__destructor__)) -static void teardown(void) { - free(segments); -} -/* -__attribute__((__noinline__)) -int main(int argc,char **argv) { - ElfW(Addr) addr = (ElfW(Addr))__builtin_extract_return_addr(__builtin_return_address(0)); - for(int i = 0; i < n; ++i) { - if(addr >= segments[i].start && addr < segments[i].end) { - // Do Nothing - return 0; - } - } - return real_main(argc, argv); -}*/ \ No newline at end of file diff --git a/src/hookcrc32/hookcrc32.so b/src/hookcrc32/hookcrc32.so deleted file mode 100755 index ff67e24d404dd061a664ecd403e913281ddf5ee3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16900 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 KP3?qFi~j=@&`u`+ diff --git a/src/lindbergh/config.c b/src/lindbergh/config.c index 4b70060..0e3452d 100644 --- a/src/lindbergh/config.c +++ b/src/lindbergh/config.c @@ -36,7 +36,7 @@ static int detectGame(uint32_t elf_crc) if (elf_crc == 0x93ea7e11) { config.game = SEGABOOT_2_4; - config.gameStatus = NOT_WORKING; + config.gameStatus = WORKING; return 0; } @@ -56,7 +56,7 @@ static int detectGame(uint32_t elf_crc) if (elf_crc == 0x6d055308) { - config.game = OUTRUN; + config.game = OUTRUN_2_SP_SDX_REVA; config.emulateDriveboard = 1; config.emulateMotionboard = 1; config.gameStatus = WORKING; @@ -65,7 +65,7 @@ static int detectGame(uint32_t elf_crc) if (elf_crc == 0xffdccaaa) { - config.game = OUTRUN_TEST; + config.game = OUTRUN_2_SP_SDX_REVA_TEST; config.emulateDriveboard = 1; config.emulateMotionboard = 1; config.gameStatus = WORKING; @@ -75,7 +75,7 @@ static int detectGame(uint32_t elf_crc) if (elf_crc == 0xd4726d61) { config.game = LETS_GO_JUNGLE; - config.gameStatus = NOT_WORKING; + config.gameStatus = WORKING; return 0; } @@ -88,98 +88,157 @@ static int detectGame(uint32_t elf_crc) if (elf_crc == 0xcc02de7d) { - config.game = ABC_2006; + config.game = AFTER_BURNER_CLIMAX; config.gameStatus = WORKING; return 0; } if (elf_crc == 0x152530dd) { - config.game = ABC_2007; + config.game = AFTER_BURNER_CLIMAX_REVA; config.gameStatus = WORKING; return 0; } if (elf_crc == 0x4e9ccf33) { - config.game = ID4; + config.game = INITIALD_4; config.gameStatus = NOT_WORKING; return 0; } if (elf_crc == 0xfb096f81) { - config.game = SRTV; - config.emulateDriveboard = 1; - config.emulateMotionboard = 1; - config.gameStatus = NOT_WORKING; - return 0; - } - - if (elf_crc == 0xb05d9bbe) - { - config.game = RTUNED; - config.emulateDriveboard = 1; - config.emulateMotionboard = 1; + config.game = SEGA_RACE_TV; config.gameStatus = WORKING; return 0; } - + + if (elf_crc == 0xb05d9bbe) + { + config.game = R_TUNED; + config.gameStatus = WORKING; + return 0; + } + if (elf_crc == 0xc4b7e89) { - config.game = VT3; + config.game = VIRTUA_TENNIS_3; config.gameStatus = NOT_WORKING; return 0; } if (elf_crc == 0x1bf1b627) { - config.game = VF5_REVC; + config.game = VIRTUA_FIGHTER_5_REVC; config.gameStatus = WORKING; return 0; } - + + if (elf_crc == 0x3CC635EE) + { + config.game = SEGABOOT_2_4; + config.gameStatus = WORKING; + return 0; + } + config.game = UNKNOWN; return 1; } char *getGameName() { + char *unknownGameTitle = "Unknown Game"; switch (config.game) { + case AFTER_BURNER_CLIMAX: + return "After Burner Climax"; + case AFTER_BURNER_CLIMAX_REVA: + return "After Burner Climax Rev A"; + case AFTER_BURNER_CLIMAX_REVB: + return "After Burner Climax Rev B"; + case AFTER_BURNER_CLIMAX_SDX: + return "After Burner Climax SDX"; + case AFTER_BURNER_CLIMAX_SDX_REVA: + return "After Burner Climax SDX Rev A"; + case GHOST_SQUAD_EVOLUTION: + return "Ghost Squad Evolution"; + case HARLEY_DAVIDSON: + return "Harley Davidson: King of the Road"; + case HUMMER: + return "Hummer"; + case HUMMER_EXTREME: + return "Hummer Extreme"; + case HUMMER_EXTREME_MDX: + return "Hummer Extreme MDX"; + case INITIALD_4: + return "Initial D Arcade Stage 4"; + case INITIALD_5: + return "Initial D Arcade Stage 5"; + case LETS_GO_JUNGLE: + return "Let's Go Jungle! Lost on the Island of Spice!"; + case LETS_GO_JUNGLE_SPECIAL: + return "Let's Go Jungle! Special!"; + case OUTRUN_2_SP_SDX: + return "Outrun 2 SP SDX"; + case OUTRUN_2_SP_SDX_REVA: + return "Outrun 2 SP SDX Rev A"; + case OUTRUN_2_SP_SDX_REVA_TEST: + return "Outrun 2 SP SDX Rev A Test Mode"; + case OUTRUN_2_SP_SDX_TEST: + return "Outrun 2 SP SDX Test Mode"; + case PRIMEVAL_HUNT: + return "Primeval Hunt"; + case RAMBO: + return "Rambo"; + case RAMBO_CHINA: + return "Rambo China Release"; + case R_TUNED: + return "RTuned"; case SEGABOOT: - return "SEGABOOT"; + return "Segaboot"; case SEGABOOT_2_4: - return "SEGABOOT 2.4"; + return "Segaboot from 2.4 Kernel"; case SEGABOOT_2_6: - return "SEGABOOT 2.6"; - case OUTRUN: - return "Outrun 2 SP"; + return "Segaboot from 2.6 Kernel"; + case SEGA_RACE_TV: + return "SEGA Race TV"; case THE_HOUSE_OF_THE_DEAD_4: return "The House of the Dead 4"; + case THE_HOUSE_OF_THE_DEAD_4_SPECIAL: + return "The House of the Dead 4 Special"; + case THE_HOUSE_OF_THE_DEAD_4_SPECIAL_TEST: + return "The House of the Dead 4 Special Test Mode"; case THE_HOUSE_OF_THE_DEAD_4_TEST: - return "The House of the Dead 4 - Test Menu"; - case LETS_GO_JUNGLE: - return "Let's Go Jungle! Lost on the Island of Spice"; - case LETS_GO_JUNGLE_SPECIAL: - return "Let's Go Jungle Special"; - case ABC_2006: - case ABC_2007: - return "After Burner Climax"; - case ID4: - return "Initial D 4"; - case SRTV: - return "SEGA Race TV"; - case RTUNED: - return "R-Tuned Ultimate Street Racing"; - case VT3: + return "The House of the Dead 4 Test Mode"; + case THE_HOUSE_OF_THE_DEAD_EX: + return "The House of the Dead Ex"; + case TOO_SPICY: + return "2 Step : 2 Spicy"; + case UNKNOWN: + return unknownGameTitle; + case VIRTUA_FIGHTER_5: + return "Virtua Fighter 5"; + case VIRTUA_FIGHTER_5_FINAL_SHOWDOWN: + return "Virtua Fighter 5 Final Showdown"; + case VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVA: + return "Virtua Fighter 5 Final Showdown Rev A"; + case VIRTUA_FIGHTER_5_R: + return " Virtua Fighter 5 R"; + case VIRTUA_FIGHTER_5_REVA: + return "Virtua Fighter 5 Rev A"; + case VIRTUA_FIGHTER_5_REVB: + return "Virtua Fighter 5 Rev B"; + case VIRTUA_FIGHTER_5_REVC: + return "Virtua Fighter 5 Rev C"; + case VIRTUA_FIGHTER_5_R_REVD: + return "Virtua Fighter 5 Rev D"; + case VIRTUA_TENNIS_3: return "Virtua Tennis 3"; - case VF5_REVC: - return "Virtua Fighter 5 - RevC"; default: - return "Unknown Game"; + return unknownGameTitle; } - return "Unknown Game"; + return unknownGameTitle; } int readConfig(FILE *configFile, EmulatorConfig *config) @@ -223,6 +282,9 @@ int readConfig(FILE *configFile, EmulatorConfig *config) else if (strcmp(command, "EMULATE_JVS") == 0) config->emulateJVS = atoi(getNextToken(NULL, " ", &saveptr)); + else if (strcmp(command, "AMD_FIX") == 0) + config->amdFix = atoi(getNextToken(NULL, " ", &saveptr)); + else if (strcmp(command, "JVS_PATH") == 0) strcpy(config->jvsPath, getNextToken(NULL, " ", &saveptr)); @@ -246,6 +308,7 @@ int initConfig() config.emulateDriveboard = 0; config.emulateMotionboard = 0; config.emulateJVS = 1; + config.amdFix = 0; config.fullscreen = 0; config.lindberghColour = YELLOW; strcpy(config.eepromPath, "eeprom.bin"); @@ -257,9 +320,10 @@ int initConfig() config.width = 1024; config.height = 768; config.crc32 = elf_crc; + if (detectGame(config.crc32) != 0) { - printf("Warning: Unsure what game this is, using default configuration values.\n"); + 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); } configFile = fopen(CONFIG_PATH, "r"); diff --git a/src/lindbergh/config.h b/src/lindbergh/config.h index b0f2c7c..09af474 100644 --- a/src/lindbergh/config.h +++ b/src/lindbergh/config.h @@ -4,23 +4,48 @@ typedef enum { - UNKNOWN, + AFTER_BURNER_CLIMAX, + AFTER_BURNER_CLIMAX_REVA, + AFTER_BURNER_CLIMAX_REVB, + AFTER_BURNER_CLIMAX_SDX, + AFTER_BURNER_CLIMAX_SDX_REVA, + GHOST_SQUAD_EVOLUTION, + HARLEY_DAVIDSON, + HUMMER, + HUMMER_EXTREME, + HUMMER_EXTREME_MDX, + INITIALD_4, + INITIALD_5, + LETS_GO_JUNGLE, + LETS_GO_JUNGLE_SPECIAL, + OUTRUN_2_SP_SDX, + OUTRUN_2_SP_SDX_REVA, + OUTRUN_2_SP_SDX_REVA_TEST, + OUTRUN_2_SP_SDX_TEST, + PRIMEVAL_HUNT, + RAMBO, + RAMBO_CHINA, + R_TUNED, SEGABOOT, SEGABOOT_2_4, SEGABOOT_2_6, + SEGA_RACE_TV, THE_HOUSE_OF_THE_DEAD_4, + THE_HOUSE_OF_THE_DEAD_4_SPECIAL, + THE_HOUSE_OF_THE_DEAD_4_SPECIAL_TEST, THE_HOUSE_OF_THE_DEAD_4_TEST, - OUTRUN, - OUTRUN_TEST, - LETS_GO_JUNGLE, - LETS_GO_JUNGLE_SPECIAL, - ABC_2006, - ABC_2007, - ID4, - SRTV, - RTUNED, - VT3, - VF5_REVC + THE_HOUSE_OF_THE_DEAD_EX, + TOO_SPICY, + UNKNOWN, + VIRTUA_FIGHTER_5, + VIRTUA_FIGHTER_5_FINAL_SHOWDOWN, + VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVA, + VIRTUA_FIGHTER_5_R, + VIRTUA_FIGHTER_5_REVA, + VIRTUA_FIGHTER_5_REVB, + VIRTUA_FIGHTER_5_REVC, + VIRTUA_FIGHTER_5_R_REVD, + VIRTUA_TENNIS_3 } Game; typedef enum @@ -33,7 +58,7 @@ typedef enum { WORKING, NOT_WORKING -}GameStatus; +} GameStatus; typedef struct { @@ -50,11 +75,11 @@ typedef struct char driveboardPath[MAX_PATH_LENGTH]; int width; int height; + int amdFix; Game game; Colour lindberghColour; GameStatus gameStatus; uint32_t crc32; - } EmulatorConfig; int initConfig(); diff --git a/src/lindbergh/graphics.c b/src/lindbergh/graphics.c index bb7c369..53ea574 100644 --- a/src/lindbergh/graphics.c +++ b/src/lindbergh/graphics.c @@ -30,7 +30,8 @@ FGAPI int FGAPIENTRY glutEnterGameMode() glutCreateWindow(gameTitle); // Outrun doesn't run the glutMainLoop through, so we'll do that here - if (getConfig()->game == OUTRUN || getConfig()->game == OUTRUN_TEST) + Game game = getConfig()->game; + if (game == OUTRUN_2_SP_SDX || game == OUTRUN_2_SP_SDX_TEST || game == OUTRUN_2_SP_SDX_REVA || game == OUTRUN_2_SP_SDX_REVA_TEST) { pthread_t glutMainLoopID; pthread_create(&glutMainLoopID, NULL, &glutMainLoopThread, NULL); @@ -163,7 +164,6 @@ int XNextEvent(Display *display, XEvent *event_return) { case 28: setSwitch(SYSTEM, BUTTON_TEST, event_return->type == KeyPress); - //securityBoardSetSwitch(BUTTON_TEST, 1); break; case 39: setSwitch(PLAYER_1, BUTTON_SERVICE, event_return->type == KeyPress); @@ -286,4 +286,4 @@ void glGenFencesNV(int n, uint *fences) void glDeleteFencesNV(int a, const uint *b) { return; -} \ No newline at end of file +} diff --git a/src/lindbergh/hook.c b/src/lindbergh/hook.c index 0202d09..8b9831f 100644 --- a/src/lindbergh/hook.c +++ b/src/lindbergh/hook.c @@ -64,7 +64,6 @@ static void handleSegfault(int signal, siginfo_t *info, void *ptr) // Get the address of the instruction causing the segfault uint8_t *code = (uint8_t *)ctx->uc_mcontext.gregs[REG_EIP]; - printf("Code: 0x%08x - Port: 0x%08x\n", *code, (ctx->uc_mcontext.gregs[REG_EDX] & 0xFFFF) - basePortAddress); switch (*code) { case 0xED: @@ -134,17 +133,14 @@ static void handleSegfault(int signal, siginfo_t *info, void *ptr) void __attribute__((constructor)) hook_init() { - printf("SEGA Lindbergh Loader\nRobert Dilley 2022\nNot for public consumption\n\n"); + printf("SEGA Lindbergh Loader\nRobert Dilley 2023\nNot for public consumption\n\n"); + // Get offsets of the Game's ELF and calculate CRC32. dl_iterate_phdr(callback, NULL); + // Get CPU ID getCPUID(); - FILE *file = fopen("dump_unpatched.bin","w+b"); - - fwrite((void *)0x08048000,0x630fac,1,file); - fclose(file); - // Implement SIGSEGV handler struct sigaction act; act.sa_sigaction = handleSegfault; @@ -634,4 +630,4 @@ int unsetenv(const char *name) } return _unsetenv(name); -} \ No newline at end of file +} diff --git a/src/lindbergh/jvs.c b/src/lindbergh/jvs.c index bdd8208..3756c9c 100644 --- a/src/lindbergh/jvs.c +++ b/src/lindbergh/jvs.c @@ -3,6 +3,7 @@ #include #include #include +#include /* POSIX threads API to create and manage threads in the program */ /* The in and out packets used to read and write to and from*/ JVSPacket inputPacket, outputPacket; @@ -13,6 +14,8 @@ unsigned char outputBuffer[JVS_MAX_PACKET_SIZE], inputBuffer[JVS_MAX_PACKET_SIZE /* Holds the status of the sense line */ int senseLine = 3; +pthread_mutex_t jvsMutex = PTHREAD_MUTEX_INITIALIZER; + JVSIO io = {0}; /** @@ -177,6 +180,8 @@ JVSStatus processPacket() /* Set the entire packet success line */ outputPacket.data[outputPacket.length++] = STATUS_SUCCESS; + pthread_mutex_lock(&jvsMutex); + while (index < inputPacket.length - 1) { int size = 1; @@ -470,6 +475,8 @@ JVSStatus processPacket() index += size; } + pthread_mutex_unlock(&jvsMutex); + writePacket(&outputPacket); return JVS_STATUS_SUCCESS; @@ -559,6 +566,8 @@ JVSStatus readPacket(JVSPacket *packet) */ JVSStatus writePacket(JVSPacket *packet) { + + /* Get pointer to raw data in packet */ unsigned char *packetPointer = (unsigned char *)packet; @@ -600,7 +609,7 @@ JVSStatus writePacket(JVSPacket *packet) /** * Gets the sense line value - * + * * Values are: * 3 = no device, after a RESET * 1 = address assigned @@ -638,7 +647,10 @@ int incrementCoin(JVSPlayer player, int amount) int setAnalogue(JVSInput channel, int value) { + pthread_mutex_lock(&jvsMutex); io.state.analogueChannel[channel] = value; + pthread_mutex_unlock(&jvsMutex); + return 1; } diff --git a/src/lindbergh/patch.c b/src/lindbergh/patch.c index ce2328c..633b177 100644 --- a/src/lindbergh/patch.c +++ b/src/lindbergh/patch.c @@ -24,7 +24,6 @@ static void setVariable(uint32_t address, uint32_t value) printf("Error: Cannot unprotect memory region to change variable (%d)\n", prot); return; } - // printf("Variable: %8X , Value: %8X\n",(uint32_t)variable, value); *variable = value; } @@ -42,7 +41,6 @@ static void setMem(uint32_t address, uint32_t value, int size) printf("Error: Cannot unprotect memory region to change variable (%d)\n", prot); return; } - // printf("Variable: %8X , Value: %8X\n",(uint32_t)variable, value); memccpy((void *)variable, (void *)value, 1, size); } @@ -115,7 +113,7 @@ void _putConsole(const char *format, ...) } else if (*format == '0') { - format ++; + format++; if (*format == '2') { format++; @@ -144,11 +142,11 @@ void _putConsole(const char *format, ...) int initPatch() { - Game game = getConfig()->game; + EmulatorConfig *config = getConfig(); - switch (game) + switch (config->game) { - case RTUNED: + case R_TUNED: { detourFunction(0x08366846, amDongleInit); detourFunction(0x08365301, amDongleIsAvailable); @@ -156,14 +154,14 @@ int initPatch() } break; - case SRTV: + case SEGA_RACE_TV: { detourFunction(0x084d5b40, amDongleInit); detourFunction(0x084d45f9, amDongleIsAvailable); detourFunction(0x084d4fef, amDongleUpdate); } break; - case ABC_2006: + case AFTER_BURNER_CLIMAX_REVA: { setVariable(0x0a0a37e4, 2); // amBackupDebugLevel setVariable(0x0a0a3800, 2); // amCreditDebugLevel @@ -177,12 +175,13 @@ int initPatch() setVariable(0x0a0a3a74, 2); // amOsinfoDebugLevel setVariable(0x0a0a3a78, 2); // amSysDataDebugLevel setVariable(0x0a0a3a80, 2); // bcLibDebugLevel + detourFunction(0x081e4980, amDongleInit); detourFunction(0x081e4cce, amDongleIsAvailable); detourFunction(0x081e4bfa, amDongleUpdate); } break; - case ABC_2007: + case AFTER_BURNER_CLIMAX_REVB: { setVariable(0x0a0a0d24, 2); // amBackupDebugLevel setVariable(0x0a0a0d40, 2); // amCreditDebugLevel @@ -196,13 +195,14 @@ int initPatch() setVariable(0x0a0a0fb4, 2); // amOsinfoDebugLevel setVariable(0x0a0a0fb8, 2); // amSysDataDebugLevel setVariable(0x0a0a0fc0, 2); // bcLibDebugLevel + detourFunction(0x081e3424, amDongleInit); detourFunction(0x081e3772, amDongleIsAvailable); detourFunction(0x081e369e, amDongleUpdate); - setVariable(0x081e7945, 0x00000001); //Test + setVariable(0x081e7945, 0x00000001); // Test } break; - case OUTRUN: + case OUTRUN_2_SP_SDX_REVA: { setVariable(0x0893a24c, 2); // amBackupDebugLevel setVariable(0x0893a260, 2); // amCreditDebugLevel @@ -216,6 +216,7 @@ int initPatch() setVariable(0x0893a4d4, 2); // amOsinfoDebugLevel setVariable(0x0893a4d8, 2); // amSysDataDebugLevel setVariable(0x0893a4e0, 2); // bcLibDebugLevel + detourFunction(0x08190e80, amDongleInit); detourFunction(0x08191201, amDongleIsAvailable); detourFunction(0x08191125, amDongleUpdate); @@ -238,12 +239,17 @@ int initPatch() setVariable(0x0a737f1c, 2); // amSysDataDebugLevel setVariable(0x0a737f20, 2); // bcLibDebugLevel setVariable(0x0a737f24, 0x0FFFFFFF); // s_logMask + detourFunction(0x08320178, amDongleInit); detourFunction(0x08320459, amDongleIsAvailable); detourFunction(0x083203c0, amDongleUpdate); - setVariable(0x0837d6aa, cpu_vendor.ebx); - setVariable(0x0837d6ba, cpu_vendor.edx); - setVariable(0x0837d6c5, cpu_vendor.ecx); + + if (config->amdFix) + { + setVariable(0x0837d6aa, cpu_vendor.ebx); + setVariable(0x0837d6ba, cpu_vendor.edx); + setVariable(0x0837d6c5, cpu_vendor.ecx); + } } break; case THE_HOUSE_OF_THE_DEAD_4_TEST: @@ -251,24 +257,29 @@ int initPatch() detourFunction(0x080677a0, amDongleInit); detourFunction(0x08067a81, amDongleIsAvailable); detourFunction(0x080679e8, amDongleUpdate); - setVariable(0x0807217a, cpu_vendor.ebx); - setVariable(0x0807218a, cpu_vendor.edx); - setVariable(0x08072195, cpu_vendor.ecx); + + if (config->amdFix) + { + setVariable(0x0807217a, cpu_vendor.ebx); + setVariable(0x0807218a, cpu_vendor.edx); + setVariable(0x08072195, cpu_vendor.ecx); + } } break; - case VF5_REVC: + case VIRTUA_FIGHTER_5_REVC: { detourFunction(0x085c6010, amDongleInit); detourFunction(0x085c63cc, amDongleIsAvailable); detourFunction(0x085c62f0, amDongleUpdate); - detourFunction(0x080b3426, stub0); // Stub returns 0 - detourFunction(0x080cb6d4, stub0); // Stub returns 0 - detourFunction(0x0840889e, stub0); // Stub returns 0 - detourFunction(0x0840ab90, stub0); // Stub returns 0 + detourFunction(0x080b3426, stub0); // Stub returns 0 + detourFunction(0x080cb6d4, stub0); // Stub returns 0 + detourFunction(0x0840889e, stub0); // Stub returns 0 + detourFunction(0x0840ab90, stub0); // Stub returns 0 setVariable(0x080e17af, 0x000000b8); // Patch IDK what setVariable(0x080e17b3, 0x01e88300); // Patch IDK what } break; + case LETS_GO_JUNGLE: { setVariable(0x08c083a4, 2); // amBackupDebugLevel @@ -291,20 +302,25 @@ int initPatch() 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 detourFunction(0x084e5086, stub0); // Stub amDipswSetLed detourFunction(0x084e4f98, stub0); // Stub amDipswExit + setVariable(0x0840d858, 0x1c899090); // No more Full Screen from the Game - //From Teknoparrot - setVariable(0x083ef701, 0x00036ee9); // AMDFIX - setVariable(0x084032e0, 0x8b90c933); // fix shader compilation with AMD GPUs - setVariable(0x08523950, 0x000000c3); // Remove ADXM_SetupFramework (Not necessary) + + if (config->amdFix) + { + setVariable(0x083ef701, 0x00036ee9); // AMDFIX + setVariable(0x084032e0, 0x8b90c933); // fix shader compilation with AMD GPUs + setVariable(0x08523950, 0x000000c3); // Remove ADXM_SetupFramework (Not necessary) + } } break; + case LETS_GO_JUNGLE_SPECIAL: { setVariable(0x08c453e4, 2); // amBackupDebugLevel @@ -324,8 +340,8 @@ int initPatch() detourFunction(0x085106dc, amDongleIsAvailable); detourFunction(0x08510600, amDongleUpdate); detourFunction(0x08075012, _putConsole); - //setVariable(0x08303C4B, 0x00000780); // Set ResX - //setVariable(0x08303C58, 0x00000438); // Set ResY + // setVariable(0x08303C4B, 0x00000780); // Set ResX + // setVariable(0x08303C58, 0x00000438); // Set ResY setVariable(0x080dad63, 0x90909090); // Patch acpSystem::checkDongle setVariable(0x080dad67, 0xE8C3C990); // Patch acpSystem::checkDongle setVariable(0x0807e609, 0x90909090); // Patch initializeArcadeBackup @@ -334,7 +350,8 @@ int initPatch() setVariable(0x08438954, 0x1c899090); // No more Full Screen from the Game } break; - case ID4: + + case INITIALD_4: { setVariable(0x08d71750, 2); // amBackupDebugLevel setVariable(0x08d71760, 2); // amCreditDebugLevel @@ -349,10 +366,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(0x0808f9a8, _putConsole); + setVariable(0x080dad63, 0x90909090); // Patch acpSystem::checkDongle setVariable(0x080dad67, 0xE8C3C990); // Patch acpSystem::checkDongle setVariable(0x0807e609, 0x90909090); // Patch initializeArcadeBackup @@ -363,4 +382,4 @@ int initPatch() break; } return 0; -} \ No newline at end of file +}