diff --git a/src/lindbergh/baseboard.c b/src/lindbergh/baseboard.c index 81cf5a1..a88e6eb 100644 --- a/src/lindbergh/baseboard.c +++ b/src/lindbergh/baseboard.c @@ -154,14 +154,14 @@ int baseboardIoctl(int fd, unsigned int request, void *data) switch (_data[0]) { - case BASEBOARD_GET_SERIAL: + case BASEBOARD_GET_SERIAL: // bcCmdSysInfoGetReq { serialCommand.destAddress = _data[1]; serialCommand.destSize = _data[2]; } break; - case BASEBOARD_WRITE_FLASH: + case BASEBOARD_WRITE_FLASH: // bcCmdSysFlashWrite { printf("Warning: The game attempted to write to the baseboard flash\n"); } @@ -173,8 +173,8 @@ int baseboardIoctl(int fd, unsigned int request, void *data) jvsCommand.srcSize = _data[2]; jvsCommand.destAddress = _data[3]; jvsCommand.destSize = _data[4]; - // memcpy(inputBuffer, &shm[jvsCommand.srcAddress], jvsCommand.srcSize); - // processPacket(&io); + memcpy(inputBuffer, &sharedMemory[jvsCommand.srcAddress], jvsCommand.srcSize); + processPacket(); } break; @@ -207,16 +207,15 @@ int baseboardIoctl(int fd, unsigned int request, void *data) case BASEBOARD_GET_SENSE_LINE: { - // _data[2] = getSenseLine(); - _data[2] = 3; + _data[2] = getSenseLine(); } break; case BASEBOARD_PROCESS_JVS: { - // memcpy(&sharedMemory[jvsCommand.destAddress], outputBuffer, outputPacket.length + 3); + memcpy(&sharedMemory[jvsCommand.destAddress], outputBuffer, outputPacket.length + 3); _data[2] = jvsCommand.destAddress; - // dp[3] = outputPacket.length + 3; + _data[3] = outputPacket.length + 3; } break; diff --git a/src/lindbergh/hook.c b/src/lindbergh/hook.c index c79c83c..f5603f6 100644 --- a/src/lindbergh/hook.c +++ b/src/lindbergh/hook.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "hook.h" @@ -14,6 +15,7 @@ #include "rideboard.h" #include "eeprom.h" #include "jvs.h" +#include "securityboard.h" #define HOOK_FILE_NAME "/dev/zero" @@ -24,6 +26,8 @@ int hooks[4] = {-1, -1, -1, -1}; +uint16_t basePortAddress = 0xFFFF; + void __attribute__((constructor)) hook_init() { printf("SEGA Lindbergh Loader\nRobert Dilley 2022\nNot for public consumption\n\n"); @@ -37,6 +41,11 @@ void __attribute__((constructor)) hook_init() if (initJVS() != 0) exit(1); + + if(initSecurityBoard() != 0) + exit(1); + + printf("Loader init success\n"); } int open(const char *pathname, int flags) @@ -179,9 +188,26 @@ int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set return _select(nfds, readfds, writefds, exceptfds, timeout); } -#include +int system(const char *command) +{ + int (*_system)(const char *command) = dlsym(RTLD_NEXT, "system"); -static void exceptionTrampoline(int signum, siginfo_t *info, void *ptr) + if (strcmp(command, "lsmod | grep basebd > /dev/null") == 0) + return 0; + /* + if (strcmp(command, "lspci | grep \"Multimedia audio controller: %Creative\" > /dev/null") == 0) + return 0; + + if (strcmp(command, "lsmod | grep ctaud") == 0) + return 0; + + if (strcmp(command, "lspci | grep MPC8272 > /dev/null") == 0) + return 0; + */ + return _system(command); +} + +static void handleSegfault(int signal, siginfo_t *info, void *ptr) { ucontext_t *ctx = ptr; @@ -193,15 +219,14 @@ static void exceptionTrampoline(int signum, siginfo_t *info, void *ptr) { uint16_t port = ctx->uc_mcontext.gregs[REG_EDX] & 0xFFFF; - switch (port) - { - case 0x38: - ctx->uc_mcontext.gregs[REG_EAX] = 0xFFFFFFFF; - break; - default: - break; - } - // printf("Warning: IO READ Port %X\n", port); + if(basePortAddress == 0xFFFF) + basePortAddress = port; + + if(port > 0x38) + port = port - basePortAddress; + + securityBoardIn(port, (uint32_t *) &(ctx->uc_mcontext.gregs[REG_EAX])); + ctx->uc_mcontext.gregs[REG_EIP]++; return; } @@ -209,7 +234,7 @@ static void exceptionTrampoline(int signum, siginfo_t *info, void *ptr) case 0xE7: { - //printf("Warning: IO WRITE IMMIDIATE %X\n", code[1]); + // printf("Warning: IO WRITE IMMIDIATE %X\n", code[1]); ctx->uc_mcontext.gregs[REG_EIP] += 2; return; } @@ -217,7 +242,7 @@ static void exceptionTrampoline(int signum, siginfo_t *info, void *ptr) case 0xE6: { - //printf("Warning: IO WRITE IMMIDIATE %X\n", code[1]); + // printf("Warning: IO WRITE IMMIDIATE %X\n", code[1]); ctx->uc_mcontext.gregs[REG_EIP] += 2; return; } @@ -227,7 +252,7 @@ static void exceptionTrampoline(int signum, siginfo_t *info, void *ptr) { 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); + // printf("Warning: IO WRITE Port %X Data %X\n", port, data); ctx->uc_mcontext.gregs[REG_EIP]++; return; } @@ -236,7 +261,7 @@ static void exceptionTrampoline(int signum, siginfo_t *info, void *ptr) case 0xEF: { uint16_t port = ctx->uc_mcontext.gregs[REG_EDX] & 0xFFFF; - //printf("Warning: IO WRITE Port %X\n", port); + // printf("Warning: IO WRITE Port %X\n", port); ctx->uc_mcontext.gregs[REG_EIP]++; return; } @@ -250,19 +275,12 @@ static void exceptionTrampoline(int signum, siginfo_t *info, void *ptr) int iopl(int level) { - static int hasRunAlready = 0; + struct sigaction act; - if (hasRunAlready == 0) - { - struct sigaction act; + act.sa_sigaction = handleSegfault; + act.sa_flags = SA_SIGINFO; - act.sa_sigaction = exceptionTrampoline; - act.sa_flags = SA_SIGINFO; - - sigaction(SIGSEGV, &act, NULL); - - hasRunAlready = 1; - } + sigaction(SIGSEGV, &act, NULL); return 0; } diff --git a/src/lindbergh/jvs.c b/src/lindbergh/jvs.c index 9673c8e..5d3d2fb 100644 --- a/src/lindbergh/jvs.c +++ b/src/lindbergh/jvs.c @@ -160,12 +160,12 @@ void writeFeatures(JVSPacket *outputPacket, JVSCapabilities *capabilities) * * @returns The status of the entire operation */ -JVSStatus processPacket(JVSIO *jvsIO) +JVSStatus processPacket() { readPacket(&inputPacket); /* Check if the packet is for us */ - if (inputPacket.destination != BROADCAST && inputPacket.destination != jvsIO->deviceID) + if (inputPacket.destination != BROADCAST && inputPacket.destination != io.deviceID) return JVS_STATUS_NOT_FOR_US; /* Setup the output packet */ @@ -209,8 +209,8 @@ JVSStatus processPacket(JVSIO *jvsIO) { // printf("CMD_REQUEST_ID\n"); outputPacket.data[outputPacket.length] = REPORT_SUCCESS; - memcpy(&outputPacket.data[outputPacket.length + 1], jvsIO->capabilities.name, strlen(jvsIO->capabilities.name) + 1); - outputPacket.length += strlen(jvsIO->capabilities.name) + 2; + memcpy(&outputPacket.data[outputPacket.length + 1], io.capabilities.name, strlen(io.capabilities.name) + 1); + outputPacket.length += strlen(io.capabilities.name) + 2; } break; @@ -219,7 +219,7 @@ JVSStatus processPacket(JVSIO *jvsIO) { // printf("CMD_COMMAND_VERSION\n"); outputPacket.data[outputPacket.length] = REPORT_SUCCESS; - outputPacket.data[outputPacket.length + 1] = jvsIO->capabilities.commandVersion; + outputPacket.data[outputPacket.length + 1] = io.capabilities.commandVersion; outputPacket.length += 2; } break; @@ -227,9 +227,9 @@ JVSStatus processPacket(JVSIO *jvsIO) /* Asks for version information */ case CMD_JVS_VERSION: { - ////printf("CMD_JVS_VERSION\n"); + // printf("CMD_JVS_VERSION\n"); outputPacket.data[outputPacket.length] = REPORT_SUCCESS; - outputPacket.data[outputPacket.length + 1] = jvsIO->capabilities.jvsVersion; + outputPacket.data[outputPacket.length + 1] = io.capabilities.jvsVersion; outputPacket.length += 2; } break; @@ -237,9 +237,9 @@ JVSStatus processPacket(JVSIO *jvsIO) /* Asks for version information */ case CMD_COMMS_VERSION: { - ////printf("CMD_COMMS_VERSION\n"); + // printf("CMD_COMMS_VERSION\n"); outputPacket.data[outputPacket.length] = REPORT_SUCCESS; - outputPacket.data[outputPacket.length + 1] = jvsIO->capabilities.commsVersion; + outputPacket.data[outputPacket.length + 1] = io.capabilities.commsVersion; outputPacket.length += 2; } break; @@ -248,7 +248,7 @@ JVSStatus processPacket(JVSIO *jvsIO) case CMD_CAPABILITIES: { // printf("CMD_CAPABILITIES\n"); - writeFeatures(&outputPacket, &jvsIO->capabilities); + writeFeatures(&outputPacket, &io.capabilities); } break; @@ -258,13 +258,13 @@ JVSStatus processPacket(JVSIO *jvsIO) // printf("CMD_READ_SWITCHES\n"); size = 3; outputPacket.data[outputPacket.length] = REPORT_SUCCESS; - outputPacket.data[outputPacket.length + 1] = jvsIO->state.inputSwitch[0]; + outputPacket.data[outputPacket.length + 1] = io.state.inputSwitch[0]; outputPacket.length += 2; for (int i = 0; i < inputPacket.data[index + 1]; i++) { for (int j = 0; j < inputPacket.data[index + 2]; j++) { - outputPacket.data[outputPacket.length++] = jvsIO->state.inputSwitch[i + 1] >> (8 - (j * 8)); + outputPacket.data[outputPacket.length++] = io.state.inputSwitch[i + 1] >> (8 - (j * 8)); } } } @@ -279,8 +279,8 @@ JVSStatus processPacket(JVSIO *jvsIO) for (int i = 0; i < numberCoinSlots; i++) { - outputPacket.data[outputPacket.length] = (jvsIO->state.coinCount[i] << 8) & 0x1F; - outputPacket.data[outputPacket.length + 1] = jvsIO->state.coinCount[i] & 0xFF; + outputPacket.data[outputPacket.length] = (io.state.coinCount[i] << 8) & 0x1F; + outputPacket.data[outputPacket.length + 1] = io.state.coinCount[i] & 0xFF; outputPacket.length += 2; } } @@ -296,7 +296,7 @@ JVSStatus processPacket(JVSIO *jvsIO) for (int i = 0; i < inputPacket.data[index + 1]; i++) { /* By default left align the data */ - int analogueData = jvsIO->state.analogueChannel[i] << jvsIO->analogueRestBits; + int analogueData = io.state.analogueChannel[i] << io.analogueRestBits; outputPacket.data[outputPacket.length] = analogueData >> 8; outputPacket.data[outputPacket.length + 1] = analogueData; outputPacket.length += 2; @@ -313,8 +313,8 @@ JVSStatus processPacket(JVSIO *jvsIO) for (int i = 0; i < inputPacket.data[index + 1]; i++) { - outputPacket.data[outputPacket.length] = jvsIO->state.rotaryChannel[i] >> 8; - outputPacket.data[outputPacket.length + 1] = jvsIO->state.rotaryChannel[i]; + outputPacket.data[outputPacket.length] = io.state.rotaryChannel[i] >> 8; + outputPacket.data[outputPacket.length + 1] = io.state.rotaryChannel[i]; outputPacket.length += 2; } } @@ -414,9 +414,9 @@ JVSStatus processPacket(JVSIO *jvsIO) outputPacket.data[outputPacket.length++] = REPORT_SUCCESS; /* Prevent overflow of coins */ - if (coin_increment + jvsIO->state.coinCount[slot_index] > 16383) - coin_increment = 16383 - jvsIO->state.coinCount[slot_index]; - jvsIO->state.coinCount[slot_index] += coin_increment; + if (coin_increment + io.state.coinCount[slot_index] > 16383) + coin_increment = 16383 - io.state.coinCount[slot_index]; + io.state.coinCount[slot_index] += coin_increment; } break; @@ -439,9 +439,9 @@ JVSStatus processPacket(JVSIO *jvsIO) outputPacket.data[outputPacket.length++] = REPORT_SUCCESS; /* Prevent underflow of coins */ - if (coin_decrement > jvsIO->state.coinCount[slot_index]) - coin_decrement = jvsIO->state.coinCount[slot_index]; - jvsIO->state.coinCount[slot_index] -= coin_decrement; + if (coin_decrement > io.state.coinCount[slot_index]) + coin_decrement = io.state.coinCount[slot_index]; + io.state.coinCount[slot_index] -= coin_decrement; } break; @@ -462,23 +462,6 @@ JVSStatus processPacket(JVSIO *jvsIO) } break; - /* The touch screen and light gun input, simply using analogue channels */ - case CMD_READ_LIGHTGUN: - { - ////printf("CMD_READ_LIGHTGUN\n"); - size = 2; - - int analogueXData = jvsIO->state.gunChannel[0] << jvsIO->gunXRestBits; - int analogueYData = jvsIO->state.gunChannel[1] << jvsIO->gunYRestBits; - outputPacket.data[outputPacket.length] = REPORT_SUCCESS; - outputPacket.data[outputPacket.length + 1] = analogueXData >> 8; - outputPacket.data[outputPacket.length + 2] = analogueXData; - outputPacket.data[outputPacket.length + 3] = analogueYData >> 8; - outputPacket.data[outputPacket.length + 4] = analogueYData; - outputPacket.length += 5; - } - break; - default: { printf("Error: JVS command not supported [0x%02hhX]\n", inputPacket.data[index]); @@ -624,34 +607,34 @@ int getSenseLine() return senseLine; } -int setSwitch(JVSIO *io, JVSPlayer player, JVSInput switchNumber, int value) +int setSwitch(JVSPlayer player, JVSInput switchNumber, int value) { - if (player > io->capabilities.players) + if (player > io.capabilities.players) return 0; if (value) { - io->state.inputSwitch[player] |= switchNumber; + io.state.inputSwitch[player] |= switchNumber; } else { - io->state.inputSwitch[player] &= ~switchNumber; + io.state.inputSwitch[player] &= ~switchNumber; } return 1; } -int incrementCoin(JVSIO *io, JVSPlayer player, int amount) +int incrementCoin(JVSPlayer player, int amount) { if (player == SYSTEM) return 0; - io->state.coinCount[player - 1] = io->state.coinCount[player - 1] + amount; + io.state.coinCount[player - 1] = io.state.coinCount[player - 1] + amount; return 1; } -int setAnalogue(JVSIO *io, JVSInput channel, int value) +int setAnalogue(JVSInput channel, int value) { - io->state.analogueChannel[channel] = value; + io.state.analogueChannel[channel] = value; return 1; } diff --git a/src/lindbergh/jvs.h b/src/lindbergh/jvs.h index 664c1dd..bab7acc 100644 --- a/src/lindbergh/jvs.h +++ b/src/lindbergh/jvs.h @@ -223,7 +223,7 @@ typedef enum int initJVS(); -JVSStatus processPacket(JVSIO *jvsIO); +JVSStatus processPacket(); JVSStatus readPacket(JVSPacket *packet); JVSStatus writePacket(JVSPacket *packet); @@ -239,9 +239,9 @@ int getSenseLine(); JVSCapabilities *getCapabilities(); JVSState *getState(); -int initIO(JVSIO *io); -int setSwitch(JVSIO *io, JVSPlayer player, JVSInput switchNumber, int value); -int incrementCoin(JVSIO *io, JVSPlayer player, int amount); -int setAnalogue(JVSIO *io, JVSInput channel, int value); +int initIO(); +int setSwitch(JVSPlayer player, JVSInput switchNumber, int value); +int incrementCoin(JVSPlayer player, int amount); +int setAnalogue(JVSInput channel, int value); #endif // JVS_H_ diff --git a/src/lindbergh/securityboard.c b/src/lindbergh/securityboard.c new file mode 100644 index 0000000..58e9b41 --- /dev/null +++ b/src/lindbergh/securityboard.c @@ -0,0 +1,91 @@ +#include +#include + +#include "securityboard.h" + +#define SECURITY_BOARD_FRONT_PANEL 0x38 +#define SECURITY_BOARD_KEYCHIP 0xFF + +#define DIP_SWITCH_ROTATION 2 + +typedef struct +{ + int serviceSwitch; + int testSwitch; + int dipSwitch[8]; + int led[2]; +} SecurityBoard; + +SecurityBoard securityBoard = {0}; + +int initSecurityBoard() +{ + securityBoard.dipSwitch[DIP_SWITCH_ROTATION] = 0; + return 0; +} + +int securityBoardSetRotation(int rotation) +{ + securityBoard.dipSwitch[DIP_SWITCH_ROTATION] = rotation; + return 0; +} + +int securityBoardSetSwitch(JVSInput switchNumber, int value) +{ + switch (switchNumber) + { + case BUTTON_TEST: + securityBoard.testSwitch = value; + break; + case BUTTON_SERVICE: + securityBoard.serviceSwitch = value; + break; + default: + printf("Error: Attempted to set a security board switch incorrectly"); + return -1; + } + + return 0; +} + +int securityBoardOut(uint16_t port, uint32_t *data) +{ + return 0; +} + +int securityBoardIn(uint16_t port, uint32_t *data) +{ + switch (port) + { + case SECURITY_BOARD_FRONT_PANEL: + uint32_t result = 0xFFFFFFFF; + + if (securityBoard.serviceSwitch) + 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 &= ~0x10; + + *data = result; + break; + default: + break; + } + + return 0; +} diff --git a/src/lindbergh/securityboard.h b/src/lindbergh/securityboard.h new file mode 100644 index 0000000..b2d4a64 --- /dev/null +++ b/src/lindbergh/securityboard.h @@ -0,0 +1,10 @@ +#include + +#include "jvs.h" + +int initSecurityBoard(); +int securityBoardOut(uint16_t port, uint32_t *data); +int securityBoardIn(uint16_t port, uint32_t *data); +int securityBoardSetSwitch(JVSInput switchNumber, int value); +int securityBoardSetRotation(int rotation); +int securityBoardSetDipSwitch(int switchNumber, int value);