diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0a3c183..ecdd584 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,6 +16,7 @@ on: - '**.md' - '.github/ISSUE_TEMPLATE/*' - '.docs/changelog' + - '.github/workflows/*' jobs: linux-build: @@ -32,29 +33,69 @@ jobs: name: 📤 Create Release needs: [linux-build, linux-flatpak, linux-appimage] runs-on: ubuntu-22.04 - if: github.ref == 'refs/heads/master' + if: github.event_name == 'push' && github.ref == 'refs/heads/master' steps: + # Step 1: Checkout the code to access Git history and tags + - name: Checkout code + uses: actions/checkout@v4 + with: + # Fetch all history and tags, necessary for git tag command + fetch-depth: 0 + + # Step 2: Download artifacts from previous build jobs - name: Download Artifacts uses: actions/download-artifact@v4 with: path: ./artifacts/ + # Optional: Display downloaded artifacts for debugging - name: Display Downloaded Artifacts run: find ./artifacts/ - - name: Add 161 to github.run_number + # Step 3: Extract the latest version from changelog.md + - name: Extract Version from Changelog + id: get_version run: | - NEW_RUN_NUMBER=$(( ${{ github.run_number }} + 161 )) - echo "NEW_RUN_NUMBER=$NEW_RUN_NUMBER" >> $GITHUB_ENV + # Define the path to the changelog file (adjust if it's not at the root) + CHANGELOG_FILE="./docs/changelog" - - name: Create Preview Release - if: github.ref == 'refs/heads/master' + echo "Attempting to extract version from $CHANGELOG_FILE..." + + # Check if the changelog file exists + if [[ ! -f "$CHANGELOG_FILE" ]]; then + echo "Error: Changelog file '$CHANGELOG_FILE' not found." + exit 1 + fi + + VERSION=$(awk '/^## \[/ { match($0, /\[([^]]+)\]/, arr); print arr[1]; exit }' "$CHANGELOG_FILE") + + # Check if a version was actually extracted + if [[ -z "$VERSION" ]]; then + echo "Error: Could not find version in '$CHANGELOG_FILE'. Expected format like '## [X.Y.Z]' near the top." + exit 1 + fi + + echo "Found version: $VERSION" + + # Set environment variables for the release step + # RELEASE_TAG often includes a 'v' prefix, RELEASE_VERSION is the plain version + echo "RELEASE_VERSION=$VERSION" >> $GITHUB_ENV + echo "RELEASE_TAG=v$VERSION" >> $GITHUB_ENV # Add 'v' prefix for the tag + echo "Using tag: v$VERSION" + + # Step 4: Create the release using the calculated tag + - name: Create Release uses: "marvinpinto/action-automatic-releases@latest" with: repo_token: "${{ secrets.GITHUB_TOKEN }}" - automatic_release_tag: v${{ env.NEW_RUN_NUMBER }} + # Use the environment variable set in the previous step + # automatic_release_tag: ${{ env.NEXT_TAG }} + automatic_release_tag: ${{ env.RELEASE_TAG }} + # Keep prerelease as false unless you want preview releases prerelease: false - title: "Build v${{ env.NEW_RUN_NUMBER }}" + # Update the title to use the new tag + # title: "Build ${{ env.NEXT_TAG }}" + title: "Build ${{ env.RELEASE_TAG }}" files: | ./artifacts/linux-flatpak/lindbergh-loader.flatpak ./artifacts/linux-build/build.tar.gz diff --git a/.gitignore b/.gitignore index 5625ce6..32682cd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.cache bld build/ test/ diff --git a/docs/changelog b/docs/changelog index e6641b1..6a456b8 100644 --- a/docs/changelog +++ b/docs/changelog @@ -2,6 +2,24 @@ All notable changes to this project will be documented in this file. +## [2.0.14] +### Added + - Bobby's birthday checking! + - FPS target to float. +### Fixed + - a bub in config.c where MJ4_ENABLED_ALL_THE_TIME was using the wrong variable. + +## [2.0.13] +### Added + + - Clear window when the game is loading to prevent ghosting in SDL + - Prevent the created windows to resize/maximize. + - Version in github now matches the version in the changelog. +### Fixed + - Fixed a bug in Let's Go Jungle Special Resolution Patch. + - Cleaned unnecessary global variables in resolution.c + - Fixed a bug in that prevented the loader to start when the current folder contained spaces and lindbergh.so was there. + ## [2.0.12] ### Added - AppImage support. diff --git a/scripts/flatpak/com.github.lindberghloader.yml b/scripts/flatpak/com.github.lindberghloader.yml index 4f483cf..38f3607 100644 --- a/scripts/flatpak/com.github.lindberghloader.yml +++ b/scripts/flatpak/com.github.lindberghloader.yml @@ -72,7 +72,7 @@ modules: x86_64: *i386-build-options sources: - type: archive - url: https://mesa.freedesktop.org/archive/glu/glu-9.0.2.tar.xz + url: https://archive.mesa3d.org/glu/glu-9.0.2.tar.xz sha256: 6e7280ff585c6a1d9dfcdf2fca489251634b3377bfc33c29e4002466a38d02d4 # Build 32-bit freeglut diff --git a/src/lindbergh/baseboard.c b/src/lindbergh/baseboard.c index 7e75fae..b893c19 100644 --- a/src/lindbergh/baseboard.c +++ b/src/lindbergh/baseboard.c @@ -88,6 +88,24 @@ int initBaseboard() return -1; } + strcpy(serialString, SERIAL_STRING); + + time_t t = time(NULL); // Get current time + struct tm *tm_info = localtime(&t); // Convert to local time structure + + int month = tm_info->tm_mon + 1; // tm_mon is 0-based (0 = Jan, 4 = May) + int day = tm_info->tm_mday; // tm_mday is the day of the month + + if (month == 1 && day == 18) + { + strcpy(serialString, "HAPPY BIRTHDAY F"); + } + + if (month == 5 && day == 21) + { + strcpy(serialString, "HAPPY BIRTHDAY B"); + } + initJVSSerial(jvsFileDescriptor); startJVSFrameThread(&jvsFileDescriptor); } diff --git a/src/lindbergh/config.c b/src/lindbergh/config.c index b1d8d08..55347e1 100644 --- a/src/lindbergh/config.c +++ b/src/lindbergh/config.c @@ -1238,7 +1238,7 @@ int readConfig(FILE *configFile, EmulatorConfig *config) config->fpsLimiter = atoi(getNextToken(NULL, " ", &saveptr)); else if (strcmp(command, "FPS_TARGET") == 0) - config->fpsTarget = atoi(getNextToken(NULL, " ", &saveptr)); + config->fpsTarget = atof(getNextToken(NULL, " ", &saveptr)); else if (strcmp(command, "LGJ_RENDER_WITH_MESA") == 0) config->lgjRenderWithMesa = atoi(getNextToken(NULL, " ", &saveptr)); @@ -1274,7 +1274,7 @@ int readConfig(FILE *configFile, EmulatorConfig *config) config->phTouchCursorHeight = atoi(getNextToken(NULL, " ", &saveptr)); else if (strcmp(command, "MJ4_ENABLED_ALL_THE_TIME") == 0) - config->phMode = atoi(getNextToken(NULL, " ", &saveptr)); + config->mj4EnabledAtT = atoi(getNextToken(NULL, " ", &saveptr)); else if (strcmp(command, "OR2_IP") == 0) strcpy(config->or2IP, getNextToken(NULL, " ", &saveptr)); @@ -1567,7 +1567,7 @@ int initConfig(const char* configFilePath) config.jvsIOType = SEGA_TYPE_3; config.GPUVendor = AUTO_DETECT_GPU; config.fpsLimiter = 0; - config.fpsTarget = 60; + config.fpsTarget = 60.0f; config.noSDL = 0; config.phMode = 2; config.disableBuiltinFont = 0; diff --git a/src/lindbergh/config.h b/src/lindbergh/config.h index 9ce7933..75d85c6 100644 --- a/src/lindbergh/config.h +++ b/src/lindbergh/config.h @@ -261,7 +261,7 @@ typedef struct int hummerFlickerFix; int keepAspectRatio; int fpsLimiter; - int fpsTarget; + float fpsTarget; int lgjRenderWithMesa; int noSDL; int phMode; diff --git a/src/lindbergh/lindbergh.c b/src/lindbergh/lindbergh.c index 91732e6..2e2dfc1 100644 --- a/src/lindbergh/lindbergh.c +++ b/src/lindbergh/lindbergh.c @@ -240,14 +240,15 @@ char *findPreloadLibrary(const char *originalDir, const char *gameDir) const char *folderCandidates[] = {"/app/lib32", appImageLib, originalDir, "/usr/lib/i386-linux-gnu", "/usr/lib/i686-linux-gnu", "/usr/lib32", "/usr/lib", NULL}; + if (fileExists(PRELOAD_FILE_NAME)) + return PRELOAD_FILE_NAME; + for (int i = 0; i < sizeof(folderCandidates) / sizeof(folderCandidates[0]); i++) { snprintf(result, MAX_PATH_LENGTH, "%s/%s", folderCandidates[i], PRELOAD_FILE_NAME); if (fileExists(result)) return result; } - if (fileExists(PRELOAD_FILE_NAME)) - return PRELOAD_FILE_NAME; return NULL; } diff --git a/src/lindbergh/resolution.c b/src/lindbergh/resolution.c index bd8e8de..628ee4d 100644 --- a/src/lindbergh/resolution.c +++ b/src/lindbergh/resolution.c @@ -48,11 +48,6 @@ float newReducedWidthABC, newReducedHeightABC; float newHalfWidthABC, newHalfHeightABC; float newWidthRangeABC, newHeightRangeABC; double new410ABC, new330ABC, new280ABC, new200ABC; -uint32_t *newWidthRangePtr_CEI_ABC, *newHeightRangePtr_CEI_ABC; -uint32_t *newWidthPtrABC, *newHeightPtrABC; -uint32_t *newReducedWidthPtrABC, *newReducedHeightPtrABC; -uint32_t *newHalfWidthPtrABC, *newHalfHeightPtrABC; -uint32_t *new410PtrABC, *new330PtrABC, *new280PtrABC, *new200PtrABC; float angleABC; float newVT3, newVT3HW, newVT3HH; @@ -68,6 +63,9 @@ int idTextShift = 0; float id4NewCaptionY; float idShiftX = 0.0; float isShiftY = 0.0; + +float newHeightLGJ, newWidth2LGJ, newWidthHLGJ, newWidthSLGJ; + bool myEnableScaling = false; int hummerRespatch() @@ -1057,15 +1055,15 @@ void patchABCMarkers(uint32_t addrCtrlEnemyInfo, uint32_t addrCtrlPlayerRivalFon new280ABC = (gWidth / 2.0) - 40.0; // 280 new200ABC = (gHeight / 2.0) - 40.0; // 200 - newWidthPtrABC = (uint32_t *)&newWidthABC; - newHeightPtrABC = (uint32_t *)&newHeightABC; + uint32_t *newWidthPtrABC = (uint32_t *)&newWidthABC; + uint32_t *newHeightPtrABC = (uint32_t *)&newHeightABC; setVariable(addrCtrlPlayerRivalFont + 0x15b, (size_t)newWidthPtrABC); // 640 setVariable(addrCtrlPlayerRivalFont + 0x163, (size_t)newHeightPtrABC); // 480 setVariable(addrCtrlEnemyPursuit2d + 0x80, (size_t)newWidthPtrABC); // 640 setVariable(addrCtrlEnemyPursuit2d + 0x88, (size_t)newHeightPtrABC); // 480 - newReducedWidthPtrABC = (uint32_t *)&newReducedWidthABC; - newReducedHeightPtrABC = (uint32_t *)&newReducedHeightABC; + uint32_t *newReducedWidthPtrABC = (uint32_t *)&newReducedWidthABC; + uint32_t *newReducedHeightPtrABC = (uint32_t *)&newReducedHeightABC; setVariable(addrCtrlPlayerRivalFont + 0x272, (size_t)newReducedWidthPtrABC); // 600 setVariable(addrCtrlPlayerRivalFont + 0x29f, (size_t)newReducedHeightPtrABC); // 440 setVariable(addrCtrlPlayerRivalFont + 0x8ff, *(uint32_t *)&newReducedHeightABC); // 440 @@ -1076,8 +1074,8 @@ void patchABCMarkers(uint32_t addrCtrlEnemyInfo, uint32_t addrCtrlPlayerRivalFon setVariable(addrCtrlEnemyPursuit2d + 0x7b3, *(uint32_t *)&newReducedHeightABC); // 440 setVariable(addrCtrlEnemyPursuit2d + 0x812, *(uint32_t *)&newReducedHeightABC); // 440 - newHalfWidthPtrABC = (uint32_t *)&newHalfWidthABC; - newHalfHeightPtrABC = (uint32_t *)&newHalfHeightABC; + uint32_t *newHalfWidthPtrABC = (uint32_t *)&newHalfWidthABC; + uint32_t *newHalfHeightPtrABC = (uint32_t *)&newHalfHeightABC; setVariable(addrCtrlPlayerRivalFont + 0x346, (size_t)newHalfWidthPtrABC); // 320 setVariable(addrCtrlPlayerRivalFont + 0x34e, (size_t)newHalfHeightPtrABC); // 240 setVariable(addrCtrlPlayerRivalFont + 0x4cb, (size_t)newHalfWidthPtrABC); // 320 @@ -1103,10 +1101,10 @@ void patchABCMarkers(uint32_t addrCtrlEnemyInfo, uint32_t addrCtrlPlayerRivalFon setVariable(addrCtrlEnemyPursuit2d + 0x4ea, *(uint32_t *)&newWidthRangeABC); // 730 setVariable(addrCtrlEnemyPursuit2d + 0x77b, *(uint32_t *)&newHeightRangeABC); // 570 - new410PtrABC = (uint32_t *)&new410ABC; - new330PtrABC = (uint32_t *)&new330ABC; - new280PtrABC = (uint32_t *)&new280ABC; - new200PtrABC = (uint32_t *)&new200ABC; + uint32_t *new410PtrABC = (uint32_t *)&new410ABC; + uint32_t *new330PtrABC = (uint32_t *)&new330ABC; + uint32_t *new280PtrABC = (uint32_t *)&new280ABC; + uint32_t *new200PtrABC = (uint32_t *)&new200ABC; setVariable(addrCtrlPlayerRivalFont + 0x40e, (size_t)new410PtrABC); // 410 setVariable(addrCtrlPlayerRivalFont + 0x44a, (size_t)new330PtrABC); // 330 setVariable(addrCtrlPlayerRivalFont + 0x5de, (size_t)new280PtrABC); // 280 @@ -2431,23 +2429,18 @@ int initResolutionPatches() setVariable(0x080d6ea0, gWidth); // 800 setVariable(0x080d6eaa, gHeight); // 600 + patchMemory(0x08303c27, "01"); // FSAA - setVariable(0x080cf6ac, gWidth); // 800 - setVariable(0x080cf6b9, gHeight); // 600 - patchMemory(0x08303c27, "01"); // FSAA - - float newWidthLGJ = (float)gWidth; - float newHeightLGJ = (float)gHeight; - uint32_t *newWidthPtrLGJ = (uint32_t *)&newWidthLGJ; + newHeightLGJ = (float)gHeight; uint32_t *newHeightPtrLGJ = (uint32_t *)&newHeightLGJ; - float newWidth2LGJ = (float)gWidth * 2.0; + newWidth2LGJ = (float)gWidth * 2.0; uint32_t *newWidth2PtrLGJ = (uint32_t *)&newWidth2LGJ; unsigned int address = 0x080cb730; - float newWidthHLGJ = (float)gWidth / 2.0; + newWidthHLGJ = (float)gWidth / 2.0; uint32_t *newWidthHPtrLGJ = (uint32_t *)&newWidthHLGJ; - float newWidthSLGJ = 1360.0 / (float)gWidth; + newWidthSLGJ = 1360.0 / (float)gWidth; uint32_t *newWidthSPtrLGJ = (uint32_t *)&newWidthSLGJ; unsigned int addressC = 0x080cb3be; diff --git a/src/lindbergh/sdlcalls.c b/src/lindbergh/sdlcalls.c index 946e1c0..d1e9a24 100644 --- a/src/lindbergh/sdlcalls.c +++ b/src/lindbergh/sdlcalls.c @@ -119,7 +119,7 @@ void initSDL(int *argcp, char **argv) SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1); } - uint32_t windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; + uint32_t windowFlags = SDL_WINDOW_OPENGL; strcat(SDLgameTitle, getGameName()); @@ -156,6 +156,16 @@ void initSDL(int *argcp, char **argv) fprintf(stderr, "OpenGL context could not be created! SDL_Error: %s\n", SDL_GetError()); exit(1); } + + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); // Your bg color + + // Force initial clear + glClear(GL_COLOR_BUFFER_BIT); + SDL_GL_SwapWindow(SDLwindow); + + // Now show the window + SDL_ShowWindow(SDLwindow); + printf(" SDL RESOLUTION: %dx%d\n\n", getConfig()->width, getConfig()->height); if (getConfig()->fullscreen) diff --git a/src/lindbergh/x11hooks.c b/src/lindbergh/x11hooks.c index 5760548..8767d62 100644 --- a/src/lindbergh/x11hooks.c +++ b/src/lindbergh/x11hooks.c @@ -60,6 +60,20 @@ Display *XOpenDisplay(const char *display_name) return x11Display; } +void setWindowProperties(Display *display, Window window) +{ + XSizeHints *hints = XAllocSizeHints(); + + hints->flags = PMinSize | PMaxSize; + hints->min_width = hints->max_width = getConfig()->width; + hints->min_height = hints->max_height = getConfig()->height; + XSetWMNormalHints(display, window, hints); + XFree(hints); + Atom hintsAtom = XInternAtom(display, "_MOTIF_WM_HINTS", False); + XMapWindow(display, window); + XFlush(display); +} + 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) { @@ -98,9 +112,21 @@ Window XCreateWindow(Display *display, Window parent, int x, int y, unsigned int { window = x11Window; } + + // Eliminate the maximize window button and no more resizing + if (!gettingGPUVendor && !creatingWindow) + setWindowProperties(display, window); + return window; } +// Here we prevent the games to change the window properties +void XSetWMProperties(Display *display, Window w, XTextProperty *window_name, XTextProperty *icon_name, char **argv, int argc, + XSizeHints *normal_hints, XWMHints *wm_hints, XClassHint *class_hints) +{ + return; +} + int XGrabPointer(Display *display, Window grab_window, Bool owner_events, unsigned int event_mask, int pointer_mode, int keyboard_mode, Window confine_to, Cursor cursor, Time time) {