From 6d7d49496e782e86aee658a230bfa41a213011f3 Mon Sep 17 00:00:00 2001 From: Bobby Dilley Date: Tue, 19 Jul 2022 12:17:50 +0100 Subject: [PATCH] Add stuff --- src/lindbergh/config.c | 2 + src/lindbergh/config.h | 2 + src/lindbergh/graphics.c | 113 +++++++++++++++++++++++++++++++++- src/lindbergh/hook.c | 61 +++++++++++++----- src/lindbergh/motionboard.c | 9 +++ src/lindbergh/motionboard.h | 4 ++ src/lindbergh/securityboard.c | 77 ++++++++++++++++++----- src/lindbergh/securityboard.h | 1 + 8 files changed, 236 insertions(+), 33 deletions(-) diff --git a/src/lindbergh/config.c b/src/lindbergh/config.c index 000fbf8..4d2a9a2 100644 --- a/src/lindbergh/config.c +++ b/src/lindbergh/config.c @@ -8,6 +8,8 @@ int initConfig() { config.emulateRideboard = 0; strcpy(config.eepromPath, "eeprom.bin"); strcpy(config.sramPath, "sram.bin"); + config.width = 1024; + config.height = 768; return 0; } diff --git a/src/lindbergh/config.h b/src/lindbergh/config.h index b602d44..8eb6187 100644 --- a/src/lindbergh/config.h +++ b/src/lindbergh/config.h @@ -7,6 +7,8 @@ typedef struct int emulateRideboard; char eepromPath[MAX_PATH_LENGTH]; char sramPath[MAX_PATH_LENGTH]; + int width; + int height; } EmulatorConfig; int initConfig(); diff --git a/src/lindbergh/graphics.c b/src/lindbergh/graphics.c index 764bda3..3096df8 100644 --- a/src/lindbergh/graphics.c +++ b/src/lindbergh/graphics.c @@ -1,9 +1,18 @@ #include #include +#include +#include + +#include "config.h" +#include "jvs.h" +#include "securityboard.h" + +int gameModeWidth = -1; +int gameModeHeight = -1; FGAPI int FGAPIENTRY glutEnterGameMode() { - glutCreateWindow("SEGA Lindbergh"); + glutCreateWindow("SEGA Lindbergh (GLUT)"); return 1; } @@ -12,3 +21,105 @@ FGAPI void FGAPIENTRY glutLeaveGameMode() glutDestroyWindow(glutGetWindow()); return; } + +FGAPI void FGAPIENTRY glutSetCursor(int cursor) +{ + return; +} + +FGAPI void FGAPIENTRY glutGameModeString(const char *string) +{ + printf("glutGameModeString: %s\n", string); + + char gameModeString[1024]; + strcpy(gameModeString, string); + + char *widthString = gameModeString; + char *heightString = NULL; + + for (int i = 0; i < 1024; i++) + { + if (gameModeString[i] == 'x') + { + gameModeString[i] = 0; + heightString = &gameModeString[i + 1]; + } + + if (gameModeString[i] == ':') + { + gameModeString[i] = 0; + break; + } + } + + int width = atoi(widthString); + int height = atoi(heightString); + + if (getConfig()->width != width || getConfig()->height != height) + { + printf("Warning: Game is overriding resolution settings to %dX%d\n", width, height); + getConfig()->width = width; + getConfig()->height = height; + } +} + +Window XCreateWindow(Display *display, Window parent, int x, int y, unsigned int width, unsigned int height, unsigned int border_width, int depth, unsigned int class, Visual *visual, unsigned long valueMask, XSetWindowAttributes *attributes) +{ + + Window (*_XCreateWindow)(Display * display, Window parent, int x, int y, unsigned int width, unsigned int height, unsigned int border_width, int depth, unsigned int class, Visual *visual, unsigned long valueMask, XSetWindowAttributes *attributes) = dlsym(RTLD_NEXT, "XCreateWindow"); + + width = getConfig()->width; + height = getConfig()->height; + + // Ensure that the windows will respond with keyboard and mouse events + attributes->event_mask = attributes->event_mask | KeyPressMask | KeyReleaseMask | PointerMotionMask; + + Window window = _XCreateWindow(display, parent, x, y, width, height, border_width, depth, class, visual, valueMask, attributes); + + return window; +} + +int XNextEvent(Display *display, XEvent *event_return) +{ + + int (*_XNextEvent)(Display * display, XEvent * event_return) = dlsym(RTLD_NEXT, "XNextEvent"); + int returnValue = _XNextEvent(display, event_return); + + switch (event_return->type) + { + case KeyPress: + switch (event_return->xkey.keycode) + { + case 28: + securityBoardSetSwitch(BUTTON_TEST, 1); + break; + case 39: + securityBoardSetSwitch(BUTTON_SERVICE, 1); + break; + default: + break; + } + break; + case KeyRelease: + switch (event_return->xkey.keycode) + { + case 28: + securityBoardSetSwitch(BUTTON_TEST, 0); + break; + case 39: + securityBoardSetSwitch(BUTTON_SERVICE, 0); + 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"); + return _XSetStandardProperties(display, window, "SEGA Lindbergh (X11)", icon_name, icon_pixmap, argv, argc, hints); +} diff --git a/src/lindbergh/hook.c b/src/lindbergh/hook.c index f5603f6..1bab18e 100644 --- a/src/lindbergh/hook.c +++ b/src/lindbergh/hook.c @@ -1,11 +1,13 @@ #include +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include +#include +#include #include #include "hook.h" @@ -42,9 +44,11 @@ void __attribute__((constructor)) hook_init() if (initJVS() != 0) exit(1); - if(initSecurityBoard() != 0) + if (initSecurityBoard() != 0) exit(1); + securityBoardSetDipResolution(getConfig()->width, getConfig()->height); + printf("Loader init success\n"); } @@ -76,9 +80,27 @@ int open(const char *pathname, int flags) return hooks[SERIAL1]; } + if (strncmp(pathname, "/tmp/", 5) == 0) + { + mkdir("tmp", 0777); + return _open(pathname + 1, flags); + } + return _open(pathname, flags); } +FILE *fopen(const char *restrict pathname, const char *restrict mode) +{ + FILE *(*_fopen)(const char *restrict pathname, const char *restrict mode) = dlsym(RTLD_NEXT, "fopen"); + + if (strcmp(pathname, "/root/lindbergrc") == 0) + { + return _fopen("lindbergrc", mode); + } + + return _fopen(pathname, mode); +} + int openat(int dirfd, const char *pathname, int flags) { int (*_openat)(int dirfd, const char *pathname, int flags) = dlsym(RTLD_NEXT, "openat"); @@ -194,6 +216,13 @@ int system(const char *command) if (strcmp(command, "lsmod | grep basebd > /dev/null") == 0) return 0; + + if (strcmp(command, "cd /tmp/segaboot > /dev/null") == 0) + return system("cd tmp/segaboot > /dev/null"); + + if (strcmp(command, "mkdir /tmp/segaboot > /dev/null") == 0) + return system("mkdir tmp/segaboot > /dev/null"); + /* if (strcmp(command, "lspci | grep \"Multimedia audio controller: %Creative\" > /dev/null") == 0) return 0; @@ -219,49 +248,49 @@ static void handleSegfault(int signal, siginfo_t *info, void *ptr) { uint16_t port = ctx->uc_mcontext.gregs[REG_EDX] & 0xFFFF; - if(basePortAddress == 0xFFFF) + // The first port called is usually random, but everything after that + // is a constant offset, so this is a hack to fix that. + // When run as sudo it works fine!? + + if (basePortAddress == 0xFFFF) basePortAddress = port; - if(port > 0x38) + if (port > 0x38) port = port - basePortAddress; - securityBoardIn(port, (uint32_t *) &(ctx->uc_mcontext.gregs[REG_EAX])); + securityBoardIn(port, (uint32_t *)&(ctx->uc_mcontext.gregs[REG_EAX])); ctx->uc_mcontext.gregs[REG_EIP]++; return; } break; - case 0xE7: + case 0xE7: // OUT IMMIDIATE { - // printf("Warning: IO WRITE IMMIDIATE %X\n", code[1]); ctx->uc_mcontext.gregs[REG_EIP] += 2; return; } break; - case 0xE6: + case 0xE6: // OUT IMMIDIATE { - // printf("Warning: IO WRITE IMMIDIATE %X\n", code[1]); ctx->uc_mcontext.gregs[REG_EIP] += 2; return; } break; - case 0xEE: + case 0xEE: // OUT { uint16_t port = ctx->uc_mcontext.gregs[REG_EDX] & 0xFFFF; uint8_t data = ctx->uc_mcontext.gregs[REG_EAX] & 0xFF; - // printf("Warning: IO WRITE Port %X Data %X\n", port, data); ctx->uc_mcontext.gregs[REG_EIP]++; return; } break; - case 0xEF: + case 0xEF: // OUT { uint16_t port = ctx->uc_mcontext.gregs[REG_EDX] & 0xFFFF; - // printf("Warning: IO WRITE Port %X\n", port); ctx->uc_mcontext.gregs[REG_EIP]++; return; } diff --git a/src/lindbergh/motionboard.c b/src/lindbergh/motionboard.c index e69de29..7b410cc 100644 --- a/src/lindbergh/motionboard.c +++ b/src/lindbergh/motionboard.c @@ -0,0 +1,9 @@ +#include "motionboard.h" + +ssize_t motionboardRead(int fd, void *buf, size_t count) { + return 0; +} + +ssize_t motionboardWrite(int fd, const void *buf, size_t count) { + return 0; +} diff --git a/src/lindbergh/motionboard.h b/src/lindbergh/motionboard.h index e69de29..2fa2200 100644 --- a/src/lindbergh/motionboard.h +++ b/src/lindbergh/motionboard.h @@ -0,0 +1,4 @@ +#include + +ssize_t motionboardRead(int fd, void *buf, size_t count); +ssize_t motionboardWrite(int fd, const void *buf, size_t count); diff --git a/src/lindbergh/securityboard.c b/src/lindbergh/securityboard.c index 58e9b41..c085566 100644 --- a/src/lindbergh/securityboard.c +++ b/src/lindbergh/securityboard.c @@ -2,17 +2,18 @@ #include #include "securityboard.h" +#include "config.h" #define SECURITY_BOARD_FRONT_PANEL 0x38 #define SECURITY_BOARD_KEYCHIP 0xFF -#define DIP_SWITCH_ROTATION 2 +#define DIP_SWITCH_ROTATION 3 typedef struct { int serviceSwitch; int testSwitch; - int dipSwitch[8]; + int dipSwitch[8 + 1]; // Start index at 1 int led[2]; } SecurityBoard; @@ -21,6 +22,38 @@ SecurityBoard securityBoard = {0}; int initSecurityBoard() { securityBoard.dipSwitch[DIP_SWITCH_ROTATION] = 0; + + return 0; +} + +static void setResolutionDips(int dip4, int dip5, int dip6) +{ + securityBoard.dipSwitch[4] = dip4; + securityBoard.dipSwitch[5] = dip5; + securityBoard.dipSwitch[6] = dip6; +} + +int securityBoardSetDipResolution(int width, int height) +{ + if (width == 640 && height == 480) + setResolutionDips(0, 0, 0); + else if (width == 800 && height == 600) + setResolutionDips(0, 0, 1); + else if (width == 1024 && height == 768) + setResolutionDips(0, 1, 0); + else if (width == 1280 && height == 1024) + setResolutionDips(0, 1, 1); + else if (width == 800 && height == 480) + setResolutionDips(1, 0, 0); + else if (width == 1024 && height == 600) + setResolutionDips(1, 0, 1); + else if (width == 1280 && height == 768) + setResolutionDips(1, 1, 0); + else if (width == 1360 && height == 768) + setResolutionDips(1, 1, 1); + else + printf("Warning: Resolution not compatible, using 640 x 480\n"); + return 0; } @@ -30,6 +63,17 @@ int securityBoardSetRotation(int rotation) return 0; } +int securityBoardSetDipSwitch(int switchNumber, int value) +{ + if (switchNumber == 0) + { + printf("Error: Dip Switch index starts at 1\n"); + return 1; + } + securityBoard.dipSwitch[switchNumber] = value; + return 0; +} + int securityBoardSetSwitch(JVSInput switchNumber, int value) { switch (switchNumber) @@ -64,21 +108,22 @@ int securityBoardIn(uint16_t port, uint32_t *data) result &= ~0x08; if (securityBoard.testSwitch) result &= ~0x04; - if (securityBoard.dipSwitch[7]) - result &= ~0x800; - if (securityBoard.dipSwitch[0]) - result &= ~0x400; - if (securityBoard.dipSwitch[1]) - result &= ~0x200; - if (securityBoard.dipSwitch[2]) - result &= ~0x100; - if (securityBoard.dipSwitch[3]) - result &= ~0x80; - if (securityBoard.dipSwitch[4]) - result &= ~0x40; - if (securityBoard.dipSwitch[5]) - result &= ~0x20; + if (securityBoard.dipSwitch[6]) + result &= ~0x800; // DIP 6 + if (securityBoard.dipSwitch[5]) + result &= ~0x400; // DIP 5 + if (securityBoard.dipSwitch[4]) + result &= ~0x200; // DIP 4 + if (securityBoard.dipSwitch[3]) + result &= ~0x100; // DIP 3 + if (securityBoard.dipSwitch[2]) + result &= ~0x80; // DIP 2 + if (securityBoard.dipSwitch[1]) + result &= ~0x40; // DIP 1 + if (securityBoard.dipSwitch[8]) + result &= ~0x20; + if (securityBoard.dipSwitch[7]) result &= ~0x10; *data = result; diff --git a/src/lindbergh/securityboard.h b/src/lindbergh/securityboard.h index b2d4a64..9661bf2 100644 --- a/src/lindbergh/securityboard.h +++ b/src/lindbergh/securityboard.h @@ -8,3 +8,4 @@ int securityBoardIn(uint16_t port, uint32_t *data); int securityBoardSetSwitch(JVSInput switchNumber, int value); int securityBoardSetRotation(int rotation); int securityBoardSetDipSwitch(int switchNumber, int value); +int securityBoardSetDipResolution(int width, int height);