diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2f993e39..8c1ce8ee 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -377,3 +377,28 @@ jobs: with: name: butterscotch-ps3 path: build/butterscotch.elf + + build-old-gcc: + strategy: + fail-fast: false + matrix: + include: + - name: GCC 3.0 + compiler: gcc-3.0 + flags: '-std=gnu99 -w' + - name: GCC 2.95 + compiler: g++-2.95 + flags: '-fpermissive -w' + name: Build (${{ matrix.name }}) + runs-on: ubuntu-latest + steps: + - name: Create Debian Woody chroot + run: | + sudo apt-get install --no-install-recommends -y debootstrap + sudo debootstrap --arch=i386 --include='${{ matrix.compiler }},make,libsdl1.2-dev' woody ~/woody http://archive.debian.org/debian + + - name: Checkout repo into chroot + run: sudo git clone https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git ~/woody/butterscotch + + - name: Build + run: sudo chroot ~/woody /bin/sh --login -c 'make -C /butterscotch CC="${{ matrix.compiler }} ${{ matrix.flags }}" DESKTOP_BACKEND=sdl1 AUDIO_BACKEND=none SDL1_LIBS='-lSDL' DISABLE_MMD=1' diff --git a/Makefile b/Makefile index d729b27d..65c76ac2 100644 --- a/Makefile +++ b/Makefile @@ -53,8 +53,6 @@ endif SRCS += $(wildcard src/desktop/*.c) $(wildcard src/desktop/backends/$(DESKTOP_BACKEND).c) ifeq ($(OS),Windows) PKG_CONFIG_FLAGS := --static -else -PKG_CONFIG_FLAGS := endif INCLUDES += -Isrc/desktop ifeq ($(DESKTOP_BACKEND),glfw3) @@ -75,7 +73,7 @@ LIBS += $(SDL1_LIBS) DEFINES += -DUSE_SDL1 endif ifeq ($(DESKTOP_BACKEND),sdl2) -SDL2_LIBS += $(shell pkg-config --libs sdl2) +SDL2_LIBS += $(shell pkg-config $(PKG_CONFIG_FLAGS) --libs sdl2) LIBS += $(SDL2_LIBS) DEFINES += -DUSE_SDL2 endif diff --git a/src/audio/ps2/ps2_audio_system.h b/src/audio/ps2/ps2_audio_system.h index 1c547242..ec88620c 100644 --- a/src/audio/ps2/ps2_audio_system.h +++ b/src/audio/ps2/ps2_audio_system.h @@ -4,7 +4,6 @@ #include "audio_system.h" #include -#include #include #define MAX_PS2_SOUND_INSTANCES 64 diff --git a/src/audio_system.h b/src/audio_system.h index 82dcd266..1f43a3df 100644 --- a/src/audio_system.h +++ b/src/audio_system.h @@ -2,7 +2,6 @@ #include "common.h" #include -#include #include "data_win.h" #include "file_system.h" diff --git a/src/binary_reader.h b/src/binary_reader.h index e61f6e0e..6f05bcae 100644 --- a/src/binary_reader.h +++ b/src/binary_reader.h @@ -4,7 +4,6 @@ #include #include #include -#include typedef struct { FILE* file; diff --git a/src/clock_gettime_macos.h b/src/clock_gettime_macos.h index d5f6d8a6..b86778db 100644 --- a/src/clock_gettime_macos.h +++ b/src/clock_gettime_macos.h @@ -19,9 +19,9 @@ #include #include #include -#include #include #include +#include "common.h" #ifndef CLOCK_REALTIME typedef int clockid_t; diff --git a/src/common.h b/src/common.h index 53f82562..6f135de0 100644 --- a/src/common.h +++ b/src/common.h @@ -1,10 +1,19 @@ #pragma once +/* + * GCC 2.95 requires building in C++ mode. + * GCC 2.95's stdbool.h doesn't work in C++ mode. + * C++ defines bool as a built-in type anyway. + */ +#ifndef __cplusplus #include +#endif #ifndef nullptr #define nullptr NULL #endif +#include + #ifndef UINT32_MAX #define UINT32_MAX 0xFFFFFFFFU #endif diff --git a/src/data_win.c b/src/data_win.c index f44cee24..7e321704 100644 --- a/src/data_win.c +++ b/src/data_win.c @@ -1,7 +1,6 @@ #include "data_win.h" #include "binary_reader.h" -#include #include #include #include diff --git a/src/data_win.h b/src/data_win.h index 90c26355..20af8709 100644 --- a/src/data_win.h +++ b/src/data_win.h @@ -3,7 +3,6 @@ #include "common.h" #include #include -#include #include #include diff --git a/src/desktop/backends/sdl1.c b/src/desktop/backends/sdl1.c index c5785707..564ab7e5 100644 --- a/src/desktop/backends/sdl1.c +++ b/src/desktop/backends/sdl1.c @@ -9,6 +9,13 @@ #include "input_recording.h" #include "desktop/platformdefs.h" +#ifndef SDL_BUTTON_WHEELUP +#define SDL_BUTTON_WHEELUP 4 +#endif +#ifndef SDL_BUTTON_WHEELDOWN +#define SDL_BUTTON_WHEELDOWN 5 +#endif + static Runner *g_runner; static int32_t fbWidth, fbHeight; static SDL_Surface* scr; diff --git a/src/desktop/platformdefs.h b/src/desktop/platformdefs.h index 5d2ec2dc..84484021 100644 --- a/src/desktop/platformdefs.h +++ b/src/desktop/platformdefs.h @@ -1,7 +1,5 @@ #pragma once -#include - #include "runner.h" #include "input_recording.h" diff --git a/src/int_int_hashmap.h b/src/int_int_hashmap.h index dce3d11d..3ec1c81e 100644 --- a/src/int_int_hashmap.h +++ b/src/int_int_hashmap.h @@ -3,7 +3,6 @@ #include "common.h" #include "utils.h" #include -#include // Open-addressing, linear-probing hashmap from int32_t to RValue. // diff --git a/src/int_rvalue_hashmap.h b/src/int_rvalue_hashmap.h index a9d5c4e7..d20f09a2 100644 --- a/src/int_rvalue_hashmap.h +++ b/src/int_rvalue_hashmap.h @@ -4,7 +4,6 @@ #include "utils.h" #include "rvalue.h" #include -#include // Open-addressing, linear-probing hashmap from int32_t to RValue. // diff --git a/src/json_reader.c b/src/json_reader.c index fca05643..72378698 100644 --- a/src/json_reader.c +++ b/src/json_reader.c @@ -357,7 +357,7 @@ JsonValue* JsonReader_parse(const char* json) { pos = 3; } - JsonParser parser = {0}; + JsonParser parser; parser.input = json; parser.position = pos; parser.length = len; diff --git a/src/ps2/gs_renderer.c b/src/ps2/gs_renderer.c index a146b9df..c7113ef0 100644 --- a/src/ps2/gs_renderer.c +++ b/src/ps2/gs_renderer.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -15,9 +16,17 @@ #include "matrix_math.h" #ifdef ENABLE_PS2_RENDERER_LOGS -#define rendererPrintf(...) fprintf(stderr, __VA_ARGS__) +static void rendererPrintf(const char* fmt, ...) { + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); +} #else -#define rendererPrintf(...) ((void) 0) +static void _rendererPrintf(const char* fmt, ...) { + (void)fmt; +} +#define rendererPrintf if (0) _rendererPrintf #endif // ===[ Constants ]=== @@ -149,7 +158,12 @@ static void loadAtlas(GsRenderer* gs) { gs->tileEntryMap = nullptr; repeat(gs->atlasTileCount, i) { AtlasTileEntry* entry = &gs->atlasTileEntries[i]; - TileLookupKey key = { .bgDef = entry->bgDef, .srcX = entry->srcX, .srcY = entry->srcY, .srcW = entry->srcW, .srcH = entry->srcH }; + TileLookupKey key = {0}; + key.bgDef = entry->bgDef; + key.srcX = entry->srcX; + key.srcY = entry->srcY; + key.srcW = entry->srcW; + key.srcH = entry->srcH; hmput(gs->tileEntryMap, key, entry); } @@ -910,7 +924,12 @@ static bool setupTextureForTPAG(GsRenderer* gs, GSTEXTURE* tex, int32_t tpagInde // Finds a tile entry by (bgDef, srcX, srcY, srcW, srcH). Returns nullptr if not found. static AtlasTileEntry* findTileEntry(GsRenderer* gs, int16_t bgDef, uint16_t srcX, uint16_t srcY, uint16_t srcW, uint16_t srcH) { - TileLookupKey key = { .bgDef = bgDef, .srcX = srcX, .srcY = srcY, .srcW = srcW, .srcH = srcH }; + TileLookupKey key = {0}; + key.bgDef = bgDef; + key.srcX = srcX; + key.srcY = srcY; + key.srcW = srcW; + key.srcH = srcH; ptrdiff_t idx = hmgeti(gs->tileEntryMap, key); if (idx == -1) return nullptr; return gs->tileEntryMap[idx].value; @@ -2947,54 +2966,7 @@ static bool gsSurfaceGetPixels(MAYBE_UNUSED Renderer* renderer, MAYBE_UNUSED int // ===[ Vtable ]=== -static RendererVtable gsVtable = { - .init = gsInit, - .destroy = gsDestroy, - .beginFrame = gsBeginFrame, - .endFrameInit = gsEndFrameInit, - .endFrameEnd = gsEndFrameEnd, - .beginView = gsBeginView, - .endView = gsEndView, - .applyProjection = gsApplyProjection, - .beginGUI = gsBeginGUI, - .endGUI = gsEndGUI, - .drawSprite = gsDrawSprite, - .drawSpritePos = gsDrawSpritePos, - .drawSpritePart = gsDrawSpritePart, - .drawRectangle = gsDrawRectangle, - .drawRectangleColor = gsDrawRectangleColor, - .drawLine = gsDrawLine, - .drawLineColor = gsDrawLineColor, - .drawText = gsDrawText, - .drawTextColor = gsDrawTextColor, - .drawTriangle = gsDrawTriangle, - .flush = gsFlush, - .clearScreen = gsClearScreen, - .createSpriteFromSurface = gsCreateSpriteFromSurface, - .deleteSprite = gsDeleteSprite, - .gpuSetBlendMode = gsGpuSetBlendMode, - .gpuSetBlendModeExt = gsGpuSetBlendModeExt, - .gpuSetBlendEnable = gsGpuSetBlendEnable, - .gpuGetBlendEnable = gsGpuGetBlendEnable, - .gpuSetAlphaTestEnable = gsGpuSetAlphaTestEnable, - .gpuSetAlphaTestRef = gsGpuSetAlphaTestRef, - .gpuSetColorWriteEnable = gsGpuSetColorWriteEnable, - .gpuGetColorWriteEnable = gsGpuGetColorWriteEnable, - .drawTile = gsDrawTile, - .drawTiled = gsDrawTiled, - .drawTiledPart = gsDrawTiledPart, - .createSurface = gsCreateSurface, - .surfaceExists = gsSurfaceExists, - .setRenderTarget = gsSetRenderTarget, - .ensureApplicationSurface = gsEnsureApplicationSurface, - .getSurfaceWidth = gsGetSurfaceWidth, - .getSurfaceHeight = gsGetSurfaceHeight, - .drawSurface = gsDrawSurface, - .surfaceResize = gsSurfaceResize, - .surfaceFree = gsSurfaceFree, - .surfaceCopy = gsSurfaceCopy, - .surfaceGetPixels = gsSurfaceGetPixels, -}; +static RendererVtable gsVtable; // ===[ Public API ]=== @@ -3002,6 +2974,52 @@ Renderer* GsRenderer_create(GSGLOBAL* gsGlobal, int64_t eeAtlasCacheMiB) { GsRenderer* gs = safeCalloc(1, sizeof(GsRenderer)); gs->eeAtlasCacheBytes = eeAtlasCacheMiB; gs->base.vtable = &gsVtable; + gsVtable.init = gsInit; + gsVtable.destroy = gsDestroy; + gsVtable.beginFrame = gsBeginFrame; + gsVtable.endFrameInit = gsEndFrameInit; + gsVtable.endFrameEnd = gsEndFrameEnd; + gsVtable.beginView = gsBeginView; + gsVtable.endView = gsEndView; + gsVtable.applyProjection = gsApplyProjection; + gsVtable.beginGUI = gsBeginGUI; + gsVtable.endGUI = gsEndGUI; + gsVtable.drawSprite = gsDrawSprite; + gsVtable.drawSpritePart = gsDrawSpritePart; + gsVtable.drawSpritePos = gsDrawSpritePos; + gsVtable.drawRectangle = gsDrawRectangle; + gsVtable.drawRectangleColor = gsDrawRectangleColor; + gsVtable.drawLine = gsDrawLine; + gsVtable.drawTriangle = gsDrawTriangle; + gsVtable.drawLineColor = gsDrawLineColor; + gsVtable.drawText = gsDrawText; + gsVtable.drawTextColor = gsDrawTextColor; + gsVtable.flush = gsFlush; + gsVtable.clearScreen = gsClearScreen; + gsVtable.createSpriteFromSurface = gsCreateSpriteFromSurface; + gsVtable.deleteSprite = gsDeleteSprite; + gsVtable.gpuSetBlendMode = gsGpuSetBlendMode; + gsVtable.gpuSetBlendModeExt = gsGpuSetBlendModeExt; + gsVtable.gpuSetBlendEnable = gsGpuSetBlendEnable; + gsVtable.gpuSetAlphaTestEnable = gsGpuSetAlphaTestEnable; + gsVtable.gpuSetAlphaTestRef = gsGpuSetAlphaTestRef; + gsVtable.gpuSetColorWriteEnable = gsGpuSetColorWriteEnable; + gsVtable.gpuGetColorWriteEnable = gsGpuGetColorWriteEnable; + gsVtable.gpuGetBlendEnable = gsGpuGetBlendEnable; + gsVtable.drawTile = gsDrawTile; + gsVtable.drawTiled = gsDrawTiled; + gsVtable.drawTiledPart = gsDrawTiledPart; + gsVtable.createSurface = gsCreateSurface; + gsVtable.surfaceExists = gsSurfaceExists; + gsVtable.setRenderTarget = gsSetRenderTarget; + gsVtable.ensureApplicationSurface = gsEnsureApplicationSurface; + gsVtable.getSurfaceWidth = gsGetSurfaceWidth; + gsVtable.getSurfaceHeight = gsGetSurfaceHeight; + gsVtable.drawSurface = gsDrawSurface; + gsVtable.surfaceResize = gsSurfaceResize; + gsVtable.surfaceFree = gsSurfaceFree; + gsVtable.surfaceCopy = gsSurfaceCopy; + gsVtable.surfaceGetPixels = gsSurfaceGetPixels; gs->gsGlobal = gsGlobal; gs->scaleX = 2.0f; gs->scaleY = 2.0f; diff --git a/src/ps2/ps2_file_system.c b/src/ps2/ps2_file_system.c index dbea9e48..f87b45e6 100644 --- a/src/ps2/ps2_file_system.c +++ b/src/ps2/ps2_file_system.c @@ -503,27 +503,7 @@ static FileSystemDirEntry* ps2ListDirectory(MAYBE_UNUSED FileSystem* fs, MAYBE_U // ===[ Vtable ]=== -static FileSystemVtable ps2FileSystemVtable = { - .resolvePath = resolvePath, - .fileExists = fileExists, - .readFileText = readFileText, - .writeFileText = writeFileText, - .deleteFile = deleteFile, - .readFileBinary = ps2ReadFileBinary, - .writeFileBinary = ps2WriteFileBinary, - .binaryOpen = ps2BinaryOpen, - .binaryClose = ps2BinaryClose, - .binaryRead = ps2BinaryRead, - .binaryWrite = ps2BinaryWrite, - .binaryTell = ps2BinaryTell, - .binarySeek = ps2BinarySeek, - .binarySize = ps2BinarySize, - .binaryRewrite = ps2BinaryRewrite, - .directoryExists = ps2DirectoryExists, - .createDirectory = ps2CreateDirectory, - .deleteDirectory = ps2DeleteDirectory, - .listDirectory = ps2ListDirectory, -}; +static FileSystemVtable ps2FileSystemVtable; // ===[ Lifecycle ]=== @@ -584,6 +564,25 @@ FileSystem* Ps2FileSystem_create(JsonValue* configRoot, const char* gameTitle) { Ps2FileSystem* pfs = safeCalloc(1, sizeof(Ps2FileSystem)); pfs->base.vtable = &ps2FileSystemVtable; + ps2FileSystemVtable.resolvePath = resolvePath; + ps2FileSystemVtable.fileExists = fileExists; + ps2FileSystemVtable.readFileText = readFileText; + ps2FileSystemVtable.writeFileText = writeFileText; + ps2FileSystemVtable.deleteFile = deleteFile; + ps2FileSystemVtable.readFileBinary = ps2ReadFileBinary; + ps2FileSystemVtable.writeFileBinary = ps2WriteFileBinary; + ps2FileSystemVtable.binaryOpen = ps2BinaryOpen; + ps2FileSystemVtable.binaryClose = ps2BinaryClose; + ps2FileSystemVtable.binaryRead = ps2BinaryRead; + ps2FileSystemVtable.binaryWrite = ps2BinaryWrite; + ps2FileSystemVtable.binaryTell = ps2BinaryTell; + ps2FileSystemVtable.binarySeek = ps2BinarySeek; + ps2FileSystemVtable.binarySize = ps2BinarySize; + ps2FileSystemVtable.binaryRewrite = ps2BinaryRewrite; + ps2FileSystemVtable.directoryExists = ps2DirectoryExists; + ps2FileSystemVtable.createDirectory = ps2CreateDirectory; + ps2FileSystemVtable.deleteDirectory = ps2DeleteDirectory; + ps2FileSystemVtable.listDirectory = ps2ListDirectory; pfs->gameTitle = safeStrdup(gameTitle); pfs->saveIconConfig = parseSaveIconConfig(configRoot); pfs->mappings = nullptr; diff --git a/src/ps2/ps2_utils.c b/src/ps2/ps2_utils.c index 39ac083d..9d293fd4 100644 --- a/src/ps2/ps2_utils.c +++ b/src/ps2/ps2_utils.c @@ -21,10 +21,8 @@ void PS2Utils_extractDeviceKey(const char* path) { result[length] = '\0'; // The "result" is the device key as a string (example: "mass" or "host") - deviceKey = (PS2DeviceKey) { - .key = result, - .usesISO9660 = strncmp(result, "cdrom", strlen("cdrom")) == 0, - }; + deviceKey.key = result; + deviceKey.usesISO9660 = strncmp(result, "cdrom", strlen("cdrom")) == 0; deviceKeyLoaded = true; } diff --git a/src/ps3/ps3_textures.h b/src/ps3/ps3_textures.h index b075524d..a04ba25b 100644 --- a/src/ps3/ps3_textures.h +++ b/src/ps3/ps3_textures.h @@ -1,7 +1,7 @@ #pragma once +#include "common.h" #include -#include #include // Loader for the PS3 textures.bin bundle produced by ButterscotchPreprocessor. diff --git a/src/runner_gamepad.h b/src/runner_gamepad.h index 97b67fee..4f79059d 100644 --- a/src/runner_gamepad.h +++ b/src/runner_gamepad.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include "common.h" #define MAX_GAMEPADS 16 @@ -74,4 +74,4 @@ void RunnerGamepad_setAxisDeadzone(RunnerGamepadState* gp, int device, float dea int RunnerGamepad_getAxisCount(RunnerGamepadState* gp, int device); int RunnerGamepad_getButtonCount(RunnerGamepadState* gp, int device); int RunnerGamepad_getHatCount(RunnerGamepadState* gp, int device); -int RunnerGamepad_getHatValue(RunnerGamepadState* gp, int device, int hat); \ No newline at end of file +int RunnerGamepad_getHatValue(RunnerGamepadState* gp, int device, int hat); diff --git a/src/runner_keyboard.h b/src/runner_keyboard.h index 2ad58508..a5aca7be 100644 --- a/src/runner_keyboard.h +++ b/src/runner_keyboard.h @@ -2,7 +2,6 @@ #include "common.h" #include -#include // GML uses key codes 0-255 (vk_nokey=0, vk_anykey=1, ASCII codes, etc.) #define GML_KEY_COUNT 256 diff --git a/src/runner_mouse.c b/src/runner_mouse.c index e6ce6aa2..fcec3445 100644 --- a/src/runner_mouse.c +++ b/src/runner_mouse.c @@ -1,6 +1,5 @@ #include "runner_mouse.h" #include "utils.h" -#include #include #include #include diff --git a/src/text_utils.h b/src/text_utils.h index bc0d6563..37ca8778 100644 --- a/src/text_utils.h +++ b/src/text_utils.h @@ -2,7 +2,6 @@ #include "common.h" #include -#include #include #include #include "data_win.h" diff --git a/src/web/main.c b/src/web/main.c index 59d648e1..6be2ab20 100644 --- a/src/web/main.c +++ b/src/web/main.c @@ -171,10 +171,9 @@ void* loop() { double remainingMs = nextFrameTimeMs - emscripten_get_now(); // Sleep for most of the remaining time, then spin-wait for precision. if (remainingMs > 2.0) { - struct timespec ts = { - .tv_sec = 0, - .tv_nsec = (long) ((remainingMs - 1.0) * 1000000.0) - }; + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = (long) ((remainingMs - 1.0) * 1000000.0); nanosleep(&ts, nullptr); } while (emscripten_get_now() < nextFrameTimeMs) {