diff --git a/.gitattributes b/.gitattributes index f4d504ccb..e61059165 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,3 +3,4 @@ *.mp4 filter=lfs diff=lfs merge=lfs -text *.ttf filter=lfs diff=lfs merge=lfs -text *.odt filter=lfs diff=lfs merge=lfs -text +*.mpg filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore index dd4a3b07e..b3b4be178 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +~* *~ *.log *.user diff --git a/singe/Manual.docx b/singe/Manual.docx new file mode 100644 index 000000000..6d7e8c3e5 Binary files /dev/null and b/singe/Manual.docx differ diff --git a/singe/Manual.odt b/singe/Manual.odt deleted file mode 100644 index 2ece389e5..000000000 --- a/singe/Manual.odt +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1e736b38a360a6f5fe56e9dd5dbdc17922337a0043b2710329037e105440bf7f -size 13740 diff --git a/singe/Menu.singe b/singe/Menu.singe index da0333eda..0c38a37f2 100644 --- a/singe/Menu.singe +++ b/singe/Menu.singe @@ -71,38 +71,43 @@ end function onInputPressed(what) - if what == SWITCH_UP then - if TEXT_LINE_TOP > 1 then - TEXT_LINE_TOP = TEXT_LINE_TOP - 1 - end - end + -- Are we displaying the grid background? + if (discGetFrame() >= DISC_GRID_START) then - if what == SWITCH_DOWN then - if TEXT_LINE_TOP < TEXT_LINE_COUNT - TEXT_LINE_LIMIT + 1 then - TEXT_LINE_TOP = TEXT_LINE_TOP + 1 + if what == SWITCH_UP then + if TEXT_LINE_TOP > 1 then + TEXT_LINE_TOP = TEXT_LINE_TOP - 1 + end end - end - if what == SWITCH_LEFT then - GAME_SELECTED = GAME_SELECTED - 1 - if GAME_SELECTED < 1 then - GAME_SELECTED = GAME_COUNT + if what == SWITCH_DOWN then + if TEXT_LINE_TOP < TEXT_LINE_COUNT - TEXT_LINE_LIMIT + 1 then + TEXT_LINE_TOP = TEXT_LINE_TOP + 1 + end end - loadGameAssets(false) - end - if what == SWITCH_RIGHT then - GAME_SELECTED = GAME_SELECTED + 1 - if GAME_SELECTED > GAME_COUNT then - GAME_SELECTED = 1 + if what == SWITCH_LEFT then + GAME_SELECTED = GAME_SELECTED - 1 + if GAME_SELECTED < 1 then + GAME_SELECTED = GAME_COUNT + end + loadGameAssets(false) + end + + if what == SWITCH_RIGHT then + GAME_SELECTED = GAME_SELECTED + 1 + if GAME_SELECTED > GAME_COUNT then + GAME_SELECTED = 1 + end + loadGameAssets(false) + end + + if what == SWITCH_START1 or what == SWITCH_START2 or what == SWITCH_BUTTON1 or what == SWITCH_BUTTON2 or what == SWITCH_BUTTON3 or what == SWITCH_BUTTON4 then + -- Start next game + SHUTDOWN_FROM_PUSH = true + scriptPush(GAME_LIST[GAME_SELECTED]) end - loadGameAssets(false) - end - if what == SWITCH_START1 or what == SWITCH_START2 or what == SWITCH_BUTTON1 or what == SWITCH_BUTTON2 or what == SWITCH_BUTTON3 or what == SWITCH_BUTTON4 then - saveConfig() - -- Start next game - scriptPush(GAME_LIST[GAME_SELECTED]) end end @@ -117,46 +122,55 @@ function onOverlayUpdate() overlayClear() - -- Cabinet image - x = CABINET_X + (CABINET_W - spriteGetWidth(SPRITE_CABINET)) * 0.5 - y = CABINET_Y + (CABINET_H - spriteGetHeight(SPRITE_CABINET)) * 0.5 - spriteDraw(x, y, SPRITE_CABINET) + -- Are we displaying the grid background? + if (discGetFrame() >= DISC_GRID_START) then - -- Marquee Image - x = MARQUEE_X + (MARQUEE_W - spriteGetWidth(SPRITE_MARQUEE)) * 0.5 - y = MARQUEE_Y + (MARQUEE_H - spriteGetHeight(SPRITE_MARQUEE)) * 0.5 - spriteDraw(x, y, SPRITE_MARQUEE) + -- Cabinet image + x = CABINET_X + (CABINET_W - spriteGetWidth(SPRITE_CABINET)) * 0.5 + y = CABINET_Y + (CABINET_H - spriteGetHeight(SPRITE_CABINET)) * 0.5 + spriteDraw(x, y, SPRITE_CABINET) - -- Attract Mode Video - videoDraw(VIDEO_ATTRACT, VIDEO_X, VIDEO_Y, VIDEO_X + VIDEO_W, VIDEO_Y + VIDEO_H) - if videoGetFrame(VIDEO_ATTRACT) > GAME_LIST[GAME_SELECTED].ATTRACT_END then - videoSeek(VIDEO_ATTRACT, GAME_LIST[GAME_SELECTED].ATTRACT_START) + -- Marquee Image + x = MARQUEE_X + (MARQUEE_W - spriteGetWidth(SPRITE_MARQUEE)) * 0.5 + y = MARQUEE_Y + (MARQUEE_H - spriteGetHeight(SPRITE_MARQUEE)) * 0.5 + spriteDraw(x, y, SPRITE_MARQUEE) + + -- Attract Mode Video + videoDraw(VIDEO_ATTRACT, VIDEO_X, VIDEO_Y, VIDEO_X + VIDEO_W, VIDEO_Y + VIDEO_H) + if videoGetFrame(VIDEO_ATTRACT) > GAME_LIST[GAME_SELECTED].ATTRACT_END then + videoSeek(VIDEO_ATTRACT, GAME_LIST[GAME_SELECTED].ATTRACT_START) + end + + -- Game Description + colorForeground(255, 255, 255, 255) + y = TEXT_Y + c = 0 + t = 1 + for _, handle in ipairs(TEXT_SPRITE_LIST) do + -- Find height of font and number of lines that fit + if TEXT_LINE_HEIGHT == 0 then + if (handle >= 0) then + TEXT_LINE_HEIGHT = spriteGetHeight(handle) + TEXT_LINE_LIMIT = math.floor(TEXT_H / TEXT_LINE_HEIGHT) + end + end + -- Only display what is visible in the window + if (t >= TEXT_LINE_TOP) then + if (c < TEXT_LINE_LIMIT) then + if (handle >= 0) then + spriteDraw(TEXT_X, y, handle) + end + y = y + TEXT_LINE_HEIGHT + 1 + c = c + 1 + end + end + t = t + 1 + end end - -- Game Description - colorForeground(255, 255, 255, 255) - y = TEXT_Y - c = 0 - t = 1 - for _, handle in ipairs(TEXT_SPRITE_LIST) do - -- Find height of font and number of lines that fit - if TEXT_LINE_HEIGHT == 0 then - if (handle >= 0) then - TEXT_LINE_HEIGHT = spriteGetHeight(handle) - TEXT_LINE_LIMIT = math.floor(TEXT_H / TEXT_LINE_HEIGHT) - end - end - -- Only display what is visible in the window - if (t >= TEXT_LINE_TOP) then - if (c < TEXT_LINE_LIMIT) then - if (handle >= 0) then - spriteDraw(TEXT_X, y, handle) - end - y = y + TEXT_LINE_HEIGHT + 1 - c = c + 1 - end - end - t = t + 1 + -- Loop video? + if (discGetFrame() >= DISC_LAST_FRAME) then + discSkipToFrame(DISC_GRID_START) end return(OVERLAY_UPDATED) @@ -165,15 +179,16 @@ end function onShutdown() - saveConfig() + saveConfig(not SHUTDOWN_FROM_PUSH) end -function saveConfig() +function saveConfig(showIntro) if GAME_COUNT > 0 then -- Save what game we're currently viewing local cfg = io.open(CONFIG_FILE, "w") cfg:write("GAME_SELECTED = " .. GAME_SELECTED .. "\n") + cfg:write("SHOW_INTRO = " .. tostring(showIntro) .. "\n") cfg:close() end end @@ -267,13 +282,15 @@ if GAME_COUNT == 0 then debugPrint("No games found! Exiting.") singeQuit() else - discPlay() overlaySetResolution(vldpGetWidth(), vldpGetHeight()) freeSans18 = fontLoad("Singe/FreeSansBold.ttf", 18) fontQuality(FONT_QUALITY_BLENDED) fontSelect(freeSans18) + DISC_GRID_START = 180 + DISC_LAST_FRAME = 359 + MARGIN_X = 25 MARGIN_Y = 25 @@ -319,7 +336,10 @@ else TEXT_LINE_HEIGHT = 0 TEXT_SPRITE_LIST = {} + SHUTDOWN_FROM_PUSH = false + -- Load configuration + SHOW_INTRO = true CONFIG_FILE = singeGetDataPath() .. "menu.dat" local confattr = lfs.attributes(CONFIG_FILE) if confattr then @@ -331,6 +351,11 @@ else GAME_SELECTED = 1 end + discPlay() + if (not SHOW_INTRO) then + discSkipToFrame(DISC_GRID_START) + end + -- Prime the pump loadGameAssets(true) end diff --git a/singe/buildPrerequisites.sh b/singe/buildPrerequisites.sh index 59da2ea33..b2c171d3b 100755 --- a/singe/buildPrerequisites.sh +++ b/singe/buildPrerequisites.sh @@ -622,17 +622,19 @@ createEmbeddedBinary FreeSansBold.ttf FreeSansBold_ttf.h FREESANSBOLD_TTF_H # === Singe Menu Background Video === if [[ ! -f menuBackground_mkv.h ]]; then - ffmpeg -i 180503_01_PurpleGrid.mp4 -filter:v 'crop=ih/3*4:ih' -vf scale=720:480 -c:v libx264 -c:a copy menuBackground.mkv + ffmpeg -i "Singe Engine Intro.mpg" -filter:v 'crop=ih/3*4:ih' -vf scale=720:480 -c:v libx264 -c:a aac temp1.mkv + ffmpeg -i 180503_01_PurpleGrid.mp4 -filter:v 'crop=ih/3*4:ih' -vf scale=720:480 -c:v libx264 -c:a aac temp2.mkv + ffmpeg -f concat -safe 0 -i <(echo -e "file $PWD/temp1.mkv\nfile $PWD/temp2.mkv\n") -c copy menuBackground.mkv createEmbeddedBinary menuBackground.mkv menuBackground_mkv.h MENUBACKGROUND_MKV_H - rm menuBackground.mkv + rm temp1.mkv temp2.mkv # menuBackground.mkv fi popd # === Singe Manual === -libreoffice --headless "-env:UserInstallation=file:///tmp/LibreOffice_Conversion_${USER}" --convert-to pdf:writer_pdf_Export Manual.odt +#libreoffice --headless "-env:UserInstallation=file:///tmp/LibreOffice_Conversion_${USER}" --convert-to pdf:writer_pdf_Export Manual.odt createEmbeddedBinary Manual.pdf Manual_pdf.h MANUAL_H -rm Manual.pdf +#rm Manual.pdf # Clean Uo case "${G_PLATFORM}" in diff --git a/singe/frameFile.c b/singe/frameFile.c index 21bbde95b..e3d1943c2 100644 --- a/singe/frameFile.c +++ b/singe/frameFile.c @@ -192,6 +192,8 @@ int32_t frameFileLoad(char *filename, char *indexPath, bool stretchVideo, SDL_Re free(frameLine); } + free(data); + // Allocate new framefile frameFile = malloc(sizeof(FrameFileT)); frameFile->id = _nextId; diff --git a/singe/main.c b/singe/main.c index 2da962103..a3bb5b2d1 100644 --- a/singe/main.c +++ b/singe/main.c @@ -62,7 +62,7 @@ typedef struct ModeS { } ModeT; typedef struct QueueS { - ConfigT conf; + ConfigT *conf; struct QueueS *next; } QueueT; @@ -100,12 +100,48 @@ static ModeT _modes[] = { ConfigT *createConf(char *exeName, int argc, char *argv[]); -void destroyConf(ConfigT **confPointer); bool extractFile(char *filename, unsigned char *data, int32_t length); void launcher(char *exeName, ConfigT *conf); void showUsage(char *name, char *message); +ConfigT *cloneConf(ConfigT *conf) { + int32_t x; + ConfigT *c; + + c = (ConfigT *)calloc(1, sizeof(ConfigT)); + + // Deep copy conf manually to avoid optimizer issues + if (conf->scriptFile) c->scriptFile = strdup(conf->scriptFile); + if (conf->videoFile) c->videoFile = strdup(conf->videoFile); + if (conf->dataDirBase) c->dataDirBase = strdup(conf->dataDirBase); + if (conf->dataDir) c->dataDir = strdup(conf->dataDir); + c->resolutionWasCalculated = conf->resolutionWasCalculated; + c->isFrameFile = conf->isFrameFile; + c->stretchVideo = conf->stretchVideo; + c->noMouse = conf->noMouse; + c->noSound = conf->noSound; + c->fullScreen = conf->fullScreen; + c->fullScreenWindow = conf->fullScreenWindow; + c->showCalculated = conf->showCalculated; + c->noConsole = conf->noConsole; + c->noLogos = conf->noLogos; + c->tracing = conf->tracing; + c->bestRatioIndex = conf->bestRatioIndex; + c->volumeVldp = conf->volumeVldp; + c->volumeNonVldp = conf->volumeNonVldp; + c->scaleFactor = conf->scaleFactor; + c->xResolution = conf->xResolution; + c->yResolution = conf->yResolution; + c->sindenArgc = conf->sindenArgc; + for (x=0; xsindenArgv[x] = conf->sindenArgv[x]; + } + + return c; +} + + ConfigT *createConf(char *exeName, int argc, char *argv[]) { int32_t x = 0; int32_t argCount = 0; @@ -153,10 +189,11 @@ ConfigT *createConf(char *exeName, int argc, char *argv[]) { // Default configuration values conf = (ConfigT *)calloc(1, sizeof(ConfigT)); if (!conf) utilDie("Out of memory creating config."); - conf->bestRatioIndex = -1; - conf->volumeVldp = 100; - conf->volumeNonVldp = 100; - conf->scaleFactor = 100; + conf->bestRatioIndex = -1; + conf->volumeVldp = 100; + conf->volumeNonVldp = 100; + conf->scaleFactor = 100; + conf->resolutionWasCalculated = true; // Parse command line argCount = ap_arguments(&parser); @@ -173,6 +210,7 @@ ConfigT *createConf(char *exeName, int argc, char *argv[]) { case 'a': if (aspectString) free(aspectString); aspectString = strdup(arg); + conf->resolutionWasCalculated = false; argCount++; break; @@ -263,12 +301,14 @@ ConfigT *createConf(char *exeName, int argc, char *argv[]) { // X Resolution case 'x': conf->xResolution = atoi(arg); + conf->resolutionWasCalculated = false; argCount++; break; // Y Resolution case 'y': conf->yResolution = atoi(arg); + conf->resolutionWasCalculated = false; argCount++; break; @@ -424,11 +464,13 @@ ConfigT *createConf(char *exeName, int argc, char *argv[]) { void destroyConf(ConfigT **confPointer) { ConfigT *conf = *confPointer; - if (conf->dataDir) free(conf->dataDir); - if (conf->videoFile) free(conf->videoFile); - if (conf->scriptFile) free(conf->scriptFile); + if (conf->dataDir) free(conf->dataDir); + if (conf->dataDirBase) free(conf->dataDirBase); + if (conf->videoFile) free(conf->videoFile); + if (conf->scriptFile) free(conf->scriptFile); free(conf); + conf = NULL; } @@ -553,8 +595,8 @@ void launcher(char *exeName, ConfigT *conf) { // Init SDL_ttf if (TTF_Init() < 0) utilDie("%s", TTF_GetError()); - // Create Resizable Window - window = SDL_CreateWindow("SINGE", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, conf->xResolution, conf->yResolution, SDL_WINDOW_RESIZABLE); + // Create Window + window = SDL_CreateWindow("SINGE", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, conf->xResolution, conf->yResolution, 0 /* SDL_WINDOW_RESIZABLE */); if (window == NULL) utilDie("%s", SDL_GetError()); // Window Icon @@ -640,7 +682,7 @@ void queueScript(ConfigT *conf) { QueueT *q; q = (QueueT *)calloc(1, sizeof(QueueT)); - memcpy(&q->conf, conf, sizeof(ConfigT)); + q->conf = cloneConf(conf); LL_APPEND(_scriptQueue, q); } @@ -752,14 +794,15 @@ int main(int argc, char *argv[]) { // Queue initial script conf = createConf(exeName, argc, argv); queueScript(conf); + destroyConf(&conf); // Run script queue while (_scriptQueue) { q = _scriptQueue; - conf = (ConfigT *)&q->conf; + launcher(exeName, q->conf); + destroyConf(&q->conf); LL_DELETE(_scriptQueue, q); - launcher(exeName, conf); - destroyConf(&conf); + free(q); } #ifdef _WIN32 diff --git a/singe/main.h b/singe/main.h index 43dcd9624..50d8c8387 100644 --- a/singe/main.h +++ b/singe/main.h @@ -29,8 +29,10 @@ #include "singe.h" -bool parseSindenString(char **sindenStringPointer, ConfigT *conf); -void queueScript(ConfigT *conf); +ConfigT *cloneConf(ConfigT *conf); +void destroyConf(ConfigT **confPointer); +bool parseSindenString(char **sindenStringPointer, ConfigT *conf); +void queueScript(ConfigT *conf); #endif // MAIN_H diff --git a/singe/makePDFs.docbuilder b/singe/makePDFs.docbuilder new file mode 100644 index 000000000..092530621 --- /dev/null +++ b/singe/makePDFs.docbuilder @@ -0,0 +1,3 @@ +builder.OpenFile("Manual.docx"); +builder.SaveFile("pdf", "/tmp/Manual.pdf"); +builder.CloseFile(); diff --git a/singe/singe.c b/singe/singe.c index b9bed14e2..6ed0695bb 100644 --- a/singe/singe.c +++ b/singe/singe.c @@ -221,7 +221,7 @@ typedef struct GlobalS { FontT *fontList; FontT *fontCurrent; MappingT controlMappings[INPUT_COUNT]; - ConfigT conf; // Local copy of command line options + ConfigT *conf; // Local copy of command line options } GlobalT; @@ -272,8 +272,10 @@ int32_t apiMouseDisable(lua_State *L); int32_t apiMouseEnable(lua_State *L); int32_t apiMouseGetPosition(lua_State *L); int32_t apiMouseHowMany(lua_State *L); +int32_t apiMouseSetCaptured(lua_State *L); int32_t apiMouseSetMode(lua_State *L); +int32_t apiOverlayBox(lua_State *L); int32_t apiOverlayCircle(lua_State *L); int32_t apiOverlayClear(lua_State *L); int32_t apiOverlayEllipse(lua_State *L); @@ -338,12 +340,13 @@ void doIndexDisplay(int32_t percent); void doLogos(void); void callLua(const char *func, const char *sig, ...); void channelFinished(int channel); +void line(int32_t x1, int32_t y1, int32_t x2, int32_t y2, SDL_Color *c); void luaDie(lua_State *L, char *method, char *fmt, ...); int32_t luaError(lua_State *L); void luaPreload(lua_State *L, const char *name, lua_CFunction func); void luaTrace(lua_State *L, char *method, char *fmt, ...); void processKey(bool down, int keysym, int32_t scancode); -void putPixel(int32_t x, int32_t y); +void putPixel(int32_t x, int32_t y, SDL_Color *c); void startControllers(void); void startLuaContext(lua_State *L); void stopControllers(void); @@ -367,7 +370,7 @@ int32_t apiColorBackground(lua_State *L) { d = lua_tonumber(L, 2); _global.colorBackground.g = (byte)d; d = lua_tonumber(L, 3); _global.colorBackground.b = (byte)d; if (n == 3) { - _global.colorBackground.a = (byte)255; + _global.colorBackground.a = (byte)0; // Default to transparent. } else { if (lua_isnumber(L, 4)) { d = lua_tonumber(L, 4); _global.colorBackground.a = (byte)d; @@ -404,7 +407,7 @@ int32_t apiColorForeground(lua_State *L) { d = lua_tonumber(L, 2); _global.colorForeground.g = (byte)d; d = lua_tonumber(L, 3); _global.colorForeground.b = (byte)d; if (n == 3) { - _global.colorForeground.a = (byte)255; + _global.colorForeground.a = (byte)255; // Default to opaque. } else { if (lua_isnumber(L, 4)) { d = lua_tonumber(L, 4); _global.colorForeground.a = (byte)d; @@ -517,8 +520,8 @@ int32_t apiDiscAudio(lua_State *L) { d = lua_tonumber(L, 1); channel = (int32_t)d; d = lua_toboolean(L, 2); onOff = (bool)d; videoGetVolume(_global.videoHandle, &left, &right); - if (channel == 1) left = (onOff ? _global.conf.volumeVldp : 0); - if (channel == 2) right = (onOff ? _global.conf.volumeVldp : 0); + if (channel == 1) left = (onOff ? _global.conf->volumeVldp : 0); + if (channel == 2) right = (onOff ? _global.conf->volumeVldp : 0); videoSetVolume(_global.videoHandle, left, right); result = true; } @@ -548,7 +551,7 @@ int32_t apiDiscGetFrame(lua_State *L) { int64_t frame = 0; if (!_global.discStopped) { - if (_global.conf.isFrameFile) { + if (_global.conf->isFrameFile) { frame = frameFileGetFrame(_global.frameFileHandle, _global.videoHandle); } else { if (_global.videoHandle >= 0) frame = videoGetFrame(_global.videoHandle); @@ -601,7 +604,7 @@ int32_t apiDiscSearch(lua_State *L) { if (n == 1) { if (lua_isnumber(L, 1)) { d = lua_tonumber(L, 1); frame = (int64_t)d; - if (_global.conf.isFrameFile) { + if (_global.conf->isFrameFile) { frameFileSeek(_global.frameFileHandle, frame, &_global.videoHandle, &aFrame); } else { if (_global.videoHandle >= 0) videoSeek(_global.videoHandle, frame); @@ -652,7 +655,7 @@ int32_t apiDiscSkipBackward(lua_State *L) { if (lua_isnumber(L, 1)) { d = lua_tonumber(L, 1); if (_global.videoHandle >= 0) frame = videoGetFrame(_global.videoHandle) - (int64_t)d; - if (_global.conf.isFrameFile) { + if (_global.conf->isFrameFile) { frameFileSeek(_global.frameFileHandle, frame, &_global.videoHandle, &aFrame); } else { if (_global.videoHandle >= 0) videoSeek(_global.videoHandle, frame); @@ -696,7 +699,7 @@ int32_t apiDiscSkipForward(lua_State *L) { if (n == 1) { if (lua_isnumber(L, 1)) { d = lua_tonumber(L, 1); if (_global.videoHandle >= 0) frame = videoGetFrame(_global.videoHandle) + (int64_t)d; - if (_global.conf.isFrameFile) { + if (_global.conf->isFrameFile) { frameFileSeek(_global.frameFileHandle, frame, &_global.videoHandle, &aFrame); } else { if (_global.videoHandle >= 0) videoSeek(_global.videoHandle, frame); @@ -731,7 +734,7 @@ int32_t apiDiscSkipToFrame(lua_State *L) { if (n == 1) { if (lua_isnumber(L, 1)) { d = lua_tonumber(L, 1); frame = (int64_t)d; - if (_global.conf.isFrameFile) { + if (_global.conf->isFrameFile) { frameFileSeek(_global.frameFileHandle, frame, &_global.videoHandle, &aFrame); } else { if (_global.videoHandle >= 0) videoSeek(_global.videoHandle, frame); @@ -761,7 +764,7 @@ int32_t apiDiscStepBackward(lua_State *L) { // No matter disc state, go back a frame. If playing, pause. if (_global.videoHandle >= 0) { - if (_global.conf.isFrameFile) { + if (_global.conf->isFrameFile) { frame = frameFileGetFrame(_global.frameFileHandle, _global.videoHandle) - 1; frameFileSeek(_global.frameFileHandle, frame, &_global.videoHandle, &aFrame); } else { @@ -785,7 +788,7 @@ int32_t apiDiscStepForward(lua_State *L) { // No matter disc state, go forward a frame. If playing, pause. if (_global.videoHandle >= 0) { - if (_global.conf.isFrameFile) { + if (_global.conf->isFrameFile) { frame = frameFileGetFrame(_global.frameFileHandle, _global.videoHandle) + 1; frameFileSeek(_global.frameFileHandle, frame, &_global.videoHandle, &aFrame); } else { @@ -1044,6 +1047,59 @@ int32_t apiFontToSprite(lua_State *L) { } +int32_t apiOverlayBox(lua_State *L) { + int32_t n = lua_gettop(L); + int32_t x1 = 0; + int32_t y1 = 0; + int32_t x2 = 0; + int32_t y2 = 0; + //SDL_Rect r; + double d = 0; + bool result = false; + + if (n == 4) { + if (lua_isnumber(L, 1)) { + if (lua_isnumber(L, 2)) { + if (lua_isnumber(L, 3)) { + if (lua_isnumber(L, 4)) { + d = lua_tonumber(L, 1); x1 = (int32_t)d; + d = lua_tonumber(L, 2); y1 = (int32_t)d; + d = lua_tonumber(L, 3); x2 = (int32_t)d; + d = lua_tonumber(L, 4); y2 = (int32_t)d; + + /* + r.x = x1; + r.y = y1; + r.w = abs(x2 - x1) + 1; + r.h = abs(y2 - y1) + 1; + */ + + SDL_LockSurface(_global.overlay); + //***TODO*** No filling until I can find an efficient way to blend individual pixels. + //SDL_FillRect(_global.overlay, &r, SDL_MapRGBA(_global.overlay->format, _global.colorBackground.r, _global.colorBackground.g, _global.colorBackground.b, _global.colorBackground.a)); + line(x1, y1, x2, y1, &_global.colorForeground); + line(x2, y1, x2, y2, &_global.colorForeground); + line(x2, y2, x1, y2, &_global.colorForeground); + line(x1, y2, x1, y1, &_global.colorForeground); + SDL_UnlockSurface(_global.overlay); + result = true; + } + } + } + } + } + + if (result) { + luaTrace(L, "overlayBox", "%d %d %d %d", x1, y1, x2, y2); + } else { + luaDie(L, "overlayBox", "Failed!"); + } + + return 0; + +} + + int32_t apiOverlayCircle(lua_State *L) { int32_t n = lua_gettop(L); @@ -1075,14 +1131,14 @@ int32_t apiOverlayCircle(lua_State *L) { SDL_LockSurface(_global.overlay); while (x >= y) { - putPixel(x0 + x, y0 + y); - putPixel(x0 + y, y0 + x); - putPixel(x0 - y, y0 + x); - putPixel(x0 - x, y0 + y); - putPixel(x0 - x, y0 - y); - putPixel(x0 - y, y0 - x); - putPixel(x0 + y, y0 - x); - putPixel(x0 + x, y0 - y); + putPixel(x0 + x, y0 + y, &_global.colorForeground); + putPixel(x0 + y, y0 + x, &_global.colorForeground); + putPixel(x0 - y, y0 + x, &_global.colorForeground); + putPixel(x0 - x, y0 + y, &_global.colorForeground); + putPixel(x0 - x, y0 - y, &_global.colorForeground); + putPixel(x0 - y, y0 - x, &_global.colorForeground); + putPixel(x0 + y, y0 - x, &_global.colorForeground); + putPixel(x0 + x, y0 - y, &_global.colorForeground); if (err <= 0) { y++; @@ -1178,10 +1234,10 @@ int32_t apiOverlayEllipse(lua_State *L) { b1 = 8 * b * b; do { - putPixel(x1, y0); // I. Quadrant - putPixel(x0, y0); // II. Quadrant - putPixel(x0, y1); // III. Quadrant - putPixel(x1, y1); // IV. Quadrant + putPixel(x1, y0, &_global.colorForeground); // I. Quadrant + putPixel(x0, y0, &_global.colorForeground); // II. Quadrant + putPixel(x0, y1, &_global.colorForeground); // III. Quadrant + putPixel(x1, y1, &_global.colorForeground); // IV. Quadrant e2 = 2 * err; if (e2 <= dy) { // y step y0++; @@ -1196,10 +1252,10 @@ int32_t apiOverlayEllipse(lua_State *L) { } while (x0 <= x1); while (y0-y1 < b) { // too early stop of flat ellipses a = 1 - putPixel(x0-1, y0); // -> finish tip of ellipse - putPixel(x1+1, y0++); - putPixel(x0-1, y1); - putPixel(x1+1, y1--); + putPixel(x0-1, y0, &_global.colorForeground); // -> finish tip of ellipse + putPixel(x1+1, y0++, &_global.colorForeground); + putPixel(x0-1, y1, &_global.colorForeground); + putPixel(x1+1, y1--, &_global.colorForeground); } SDL_UnlockSurface(_global.overlay); @@ -1241,13 +1297,6 @@ int32_t apiOverlayLine(lua_State *L) { int32_t y1 = 0; int32_t x2 = 0; int32_t y2 = 0; - int32_t x = 0; - int32_t y = 0; - int32_t dx = 0; - int32_t dy = 0; - int32_t incX = 0; - int32_t incY = 0; - int32_t balance = 0; double d = 0; bool result = false; @@ -1262,56 +1311,7 @@ int32_t apiOverlayLine(lua_State *L) { d = lua_tonumber(L, 4); y2 = (int32_t)d; SDL_LockSurface(_global.overlay); - - if (x2 >= x1) { - dx = x2 - x1; - incX = 1; - } else { - dx = x1 - x2; - incX = -1; - } - - if (y2 >= y1) { - dy = y2 - y1; - incY = 1; - } else { - dy = y1 - y2; - incY = -1; - } - - x = x1; - y = y1; - - if (dx >= dy) { - dy <<= 1; - balance = dy - dx; - dx <<= 1; - while (x != x2) { - putPixel(x, y); - if (balance >= 0) { - y += incY; - balance -= dx; - } - balance += dy; - x += incX; - } - putPixel(x, y); - } else { - dx <<= 1; - balance = dx - dy; - dy <<= 1; - while (y != y2) { - putPixel(x, y); - if (balance >= 0) { - x += incX; - balance -= dy; - } - balance += dx; - y += incY; - } - putPixel(x, y); - } - + line(x1, y1, x2, y2, &_global.colorForeground); SDL_UnlockSurface(_global.overlay); result = true; } @@ -1345,7 +1345,7 @@ int32_t apiOverlayPlot(lua_State *L) { d = lua_tonumber(L, 2); y1 = (int32_t)d; SDL_LockSurface(_global.overlay); - putPixel(x1, y1); + putPixel(x1, y1, &_global.colorForeground); SDL_UnlockSurface(_global.overlay); result = true; } @@ -1764,24 +1764,42 @@ int32_t apiSoundUnload(lua_State *L) { int32_t apiSpriteDraw(lua_State *L) { - int32_t n = lua_gettop(L); - int32_t id = -1; - double d = 0; - SpriteT *sprite = NULL; - SDL_Rect dest; + int32_t n = lua_gettop(L); + int32_t id = -1; + double d = 0; + SpriteT *sprite = NULL; + SDL_Rect dest; - if (n == 3) { + if ((n == 3) || (n == 5)) { if (lua_isnumber(L, 1)) { if (lua_isnumber(L, 2)) { if (lua_isnumber(L, 3)) { d = lua_tonumber(L, 1); dest.x = (int32_t)d; d = lua_tonumber(L, 2); dest.y = (int32_t)d; - d = lua_tonumber(L, 3); id = (int32_t)d; + if (n == 5) { + // Target is scaled + if (lua_isnumber(L, 4)) { + if (lua_isnumber(L, 5)) { + d = lua_tonumber(L, 3); dest.w = (int32_t)d - dest.x + 1; + d = lua_tonumber(L, 4); dest.h = (int32_t)d - dest.y + 1; + d = lua_tonumber(L, 5); id = (int32_t)d; + } + } + } else { + // Target is same size as sprite + d = lua_tonumber(L, 3); id = (int32_t)d; + } HASH_FIND_INT(_global.spriteList, &id, sprite); if (!sprite) luaDie(L, "spriteDraw", "No sprite at index %d in apiSpriteGetWidth.", id); - dest.w = sprite->surface->w; - dest.h = sprite->surface->h; - SDL_BlitSurface(sprite->surface, NULL, _global.overlay, &dest); + if (n == 5) { + // Target is scaled + SDL_BlitScaled(sprite->surface, NULL, _global.overlay, &dest); + } else { + // Target is same size as sprite + dest.w = sprite->surface->w; + dest.h = sprite->surface->h; + SDL_BlitSurface(sprite->surface, NULL, _global.overlay, &dest); + } } } } @@ -1934,8 +1952,8 @@ int32_t apiVideoDraw(lua_State *L) { d = lua_tonumber(L, 1); id = (int32_t)d; d = lua_tonumber(L, 2); dest.x = (int32_t)d; d = lua_tonumber(L, 3); dest.y = (int32_t)d; - d = lua_tonumber(L, 4); dest.w = (int32_t)d - dest.x; - d = lua_tonumber(L, 5); dest.h = (int32_t)d - dest.y; + d = lua_tonumber(L, 4); dest.w = (int32_t)d - dest.x + 1; + d = lua_tonumber(L, 5); dest.h = (int32_t)d - dest.y + 1; // Get our video structure HASH_FIND_INT(_global.videoList, &id, video); if (!video) luaDie(L, "videoDraw", "No video at index %d in apiVideoDraw.", id); @@ -2166,7 +2184,7 @@ int32_t apiVideoLoad(lua_State *L) { name = lua_tostring(L, 1); // Create data directory based on video path. temp = utilGetUpToLastPathComponent((char *)name); - data = utilCreateString("%s%s", _global.conf.dataDirBase, temp); + data = utilCreateString("%s%s", _global.conf->dataDirBase, temp); free(temp); temp = NULL; utilFixPathSeparators(&data, false); @@ -2470,8 +2488,8 @@ int32_t apiKeyboardSetMode(lua_State *L) { int32_t apiMouseEnable(lua_State *L) { // Enables mouse monitoring (void)L; - luaTrace(L, "mouseEnable", "%d", _global.conf.noMouse); - _global.mouseEnabled = (bool)!_global.conf.noMouse; + luaTrace(L, "mouseEnable", "%d", _global.conf->noMouse); + _global.mouseEnabled = (bool)!_global.conf->noMouse; return 0; } @@ -2485,6 +2503,36 @@ int32_t apiMouseDisable(lua_State *L) { } +int32_t apiMouseSetCaptured(lua_State *L) { + int32_t n = lua_gettop(L); + bool result = false; + + if (n == 1) { + if (lua_isboolean(L, 1)) { + _global.mouseGrabbed = (bool)lua_toboolean(L, 1); + if (_global.mouseGrabbed) { + // Grab mouse + SDL_SetWindowGrab(_global.window, SDL_TRUE); + SDL_ShowCursor(SDL_DISABLE); + } else { + // Ungrab mouse + SDL_SetWindowGrab(_global.window, SDL_FALSE); + SDL_ShowCursor(SDL_ENABLE); + } + result = true; + } + } + + if (result) { + luaTrace(L, "mouseSetCaptured", "%d", _global.mouseGrabbed); + } else { + luaDie(L, "mouseSetCaptured", "Failed!"); + } + + return 0; +} + + int32_t apiMouseSetMode(lua_State *L) { // Sets the scanning mode for mouse input. // Can be one of two values: @@ -2599,7 +2647,7 @@ int32_t apiScriptExecute(lua_State *L) { // Push next script. conf = buildConfFromTable(L); queueScript(conf); - free(conf); + destroyConf(&conf); // Stop this script running. _global.running = false; result = true; @@ -2626,9 +2674,9 @@ int32_t apiScriptPush(lua_State *L) { // Push next script. conf = buildConfFromTable(L); queueScript(conf); - free(conf); + destroyConf(&conf); // Push this script. - queueScript(&_global.conf); + queueScript(_global.conf); // Stop this script running. _global.running = false; result = true; @@ -2718,8 +2766,8 @@ int32_t apiSingeVersion(lua_State *L) { int32_t apiSingeGetDataPath(lua_State *L) { - luaTrace(L, "singeGetDataPath", "%s", _global.conf.dataDir); - lua_pushstring(L, _global.conf.dataDir); + luaTrace(L, "singeGetDataPath", "%s", _global.conf->dataDir); + lua_pushstring(L, _global.conf->dataDir); return 1; } @@ -2758,8 +2806,8 @@ int32_t apiSingeSetGameName(lua_State *L) { int32_t apiSingeGetScriptPath(lua_State *L) { - luaTrace(L, "singeGetScriptPath", "%s", _global.conf.scriptFile); - lua_pushstring(L, _global.conf.scriptFile); + luaTrace(L, "singeGetScriptPath", "%s", _global.conf->scriptFile); + lua_pushstring(L, _global.conf->scriptFile); return 1; } @@ -2773,12 +2821,7 @@ ConfigT *buildConfFromTable(lua_State *L) { ConfigT *c = NULL; // Start with current config. - c = (ConfigT *)calloc(1, sizeof(ConfigT)); - memcpy(c, &_global.conf, sizeof(ConfigT)); - if (_global.conf.scriptFile) c->scriptFile = strdup(_global.conf.scriptFile); - if (_global.conf.videoFile) c->videoFile = strdup(_global.conf.videoFile); - if (_global.conf.dataDirBase) c->dataDirBase = strdup(_global.conf.dataDirBase); - if (_global.conf.dataDir) c->dataDir = strdup(_global.conf.dataDir); + c = cloneConf(_global.conf); // Update with data in the table on the top of the Lua stack. lua_pushnil(L); @@ -3140,6 +3183,66 @@ void doLogos(void) { } +void line(int32_t x1, int32_t y1, int32_t x2, int32_t y2, SDL_Color *c) { + int32_t x = 0; + int32_t y = 0; + int32_t dx = 0; + int32_t dy = 0; + int32_t incX = 0; + int32_t incY = 0; + int32_t balance = 0; + + if (x2 >= x1) { + dx = x2 - x1; + incX = 1; + } else { + dx = x1 - x2; + incX = -1; + } + + if (y2 >= y1) { + dy = y2 - y1; + incY = 1; + } else { + dy = y1 - y2; + incY = -1; + } + + x = x1; + y = y1; + + if (dx >= dy) { + dy <<= 1; + balance = dy - dx; + dx <<= 1; + while (x != x2) { + putPixel(x, y, c); + if (balance >= 0) { + y += incY; + balance -= dx; + } + balance += dy; + x += incX; + } + putPixel(x, y, c); + } else { + dx <<= 1; + balance = dx - dy; + dy <<= 1; + while (y != y2) { + putPixel(x, y, c); + if (balance >= 0) { + x += incX; + balance -= dy; + } + balance += dx; + y += incY; + } + putPixel(x, y, c); + } +} + + void luaDie(lua_State *L, char *method, char *fmt, ...) { va_list args; lua_Debug ar; @@ -3297,12 +3400,12 @@ void processKey(bool down, int32_t keysym, int32_t scancode) { } -void putPixel(int32_t x, int32_t y) { +void putPixel(int32_t x, int32_t y, SDL_Color *c) { SDL_Surface *surface = _global.overlay; int32_t bpp = surface->format->BytesPerPixel; Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; - Uint32 pixel = SDL_MapRGBA(surface->format, _global.colorForeground.r, _global.colorForeground.g, _global.colorForeground.b, _global.colorForeground.a); + Uint32 pixel = SDL_MapRGBA(surface->format, c->r, c->g, c->b, c->a); if ((x < 0) || (x >= _global.overlay->w) || (y < 0) || (y >= _global.overlay->h)) return; @@ -3343,6 +3446,7 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { int64_t thisFrame = -1; int64_t lastFrame = -1; uint32_t frameClock = 0; + bool changed = false; char *temp = NULL; char *temp2 = NULL; SDL_Rect windowTarget; @@ -3382,12 +3486,8 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { _global.discStopped = true; _global.mouseEnabled = true; - // Deep copy conf - memcpy(&_global.conf, conf, sizeof(ConfigT)); - _global.conf.dataDir = strdup(conf->dataDir); - _global.conf.dataDirBase = strdup(conf->dataDirBase); - _global.conf.scriptFile = strdup(conf->scriptFile); - _global.conf.videoFile = strdup(conf->videoFile); + // Local copy of config + _global.conf = cloneConf(conf); // Input mappings _global.controlMappings[INPUT_UP].name = "INPUT_UP"; @@ -3431,20 +3531,21 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { if (luaL_loadbuffer(_global.luaContext, (char *)controls_cfg, controls_cfg_len, "Input Mappings") || lua_pcall(_global.luaContext, 0, 0, 0)) utilDie("%s", lua_tostring(_global.luaContext, -1)); if (utilFileExists("controls.cfg") && luaL_dofile(_global.luaContext, "controls.cfg")) utilDie("%s", lua_tostring(_global.luaContext, -1)); // Load mappings in main data dir - temp = utilCreateString("%s..%ccontrols.cfg", _global.conf.dataDir, utilGetPathSeparator()); + temp = utilCreateString("%s..%ccontrols.cfg", _global.conf->dataDir, utilGetPathSeparator()); if (utilFileExists(temp) && luaL_dofile(_global.luaContext, temp)) utilDie("%s", lua_tostring(_global.luaContext, -1)); free(temp); // Load mappings in game data dir - temp = utilCreateString("%scontrols.cfg", _global.conf.dataDir); + temp = utilCreateString("%scontrols.cfg", _global.conf->dataDir); if (utilFileExists(temp) && luaL_dofile(_global.luaContext, temp)) utilDie("%s", lua_tostring(_global.luaContext, -1)); free(temp); // Load mappings in game script dir - temp = strdup(_global.conf.scriptFile); + temp = strdup(_global.conf->scriptFile); temp2 = utilStrndup(temp, strlen(temp) - strlen(utilGetLastPathComponent(temp))); free(temp); temp = utilCreateString("%scontrols.cfg", temp2); if (utilFileExists(temp) && luaL_dofile(_global.luaContext, temp)) utilDie("%s", lua_tostring(_global.luaContext, -1)); free(temp); + free(temp2); // Parse results lua_getglobal(_global.luaContext, "DEAD_ZONE"); if (lua_isnumber(_global.luaContext, -1)) { @@ -3496,7 +3597,7 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { lua_close(_global.luaContext); // Show splash screens - if (!_global.conf.noLogos) { + if (!_global.conf->noLogos) { doLogos(); } @@ -3548,8 +3649,10 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { lua_register(_global.luaContext, "mouseDisable", apiMouseDisable); lua_register(_global.luaContext, "mouseGetPosition", apiMouseGetPosition); lua_register(_global.luaContext, "mouseHowMany", apiMouseHowMany); + lua_register(_global.luaContext, "mouseSetCaptured", apiMouseSetCaptured); lua_register(_global.luaContext, "mouseSetMode", apiMouseSetMode); + lua_register(_global.luaContext, "overlayBox", apiOverlayBox); lua_register(_global.luaContext, "overlayCircle", apiOverlayCircle); lua_register(_global.luaContext, "overlayClear", apiOverlayClear); lua_register(_global.luaContext, "overlayEllipse", apiOverlayEllipse); @@ -3615,39 +3718,61 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { // Open main video file doIndexDisplay(-1); videoSetIndexCallback(doIndexDisplay); - if (_global.conf.isFrameFile) { - _global.frameFileHandle = frameFileLoad(_global.conf.videoFile, _global.conf.dataDir, (bool)_global.conf.stretchVideo, _global.renderer, _global.conf.showCalculated); - if (_global.frameFileHandle < 0) utilDie("Unable to load framefile: %s", _global.conf.videoFile); + if (_global.conf->isFrameFile) { + _global.frameFileHandle = frameFileLoad(_global.conf->videoFile, _global.conf->dataDir, (bool)_global.conf->stretchVideo, _global.renderer, _global.conf->showCalculated); + if (_global.frameFileHandle < 0) utilDie("Unable to load framefile: %s", _global.conf->videoFile); frameFileSeek(_global.frameFileHandle, 0, &_global.videoHandle, &thisFrame); // Fills in _global.videoHandle } else { - _global.videoHandle = videoLoad(_global.conf.videoFile, _global.conf.dataDir, (bool)_global.conf.stretchVideo, _global.renderer); + _global.videoHandle = videoLoad(_global.conf->videoFile, _global.conf->dataDir, (bool)_global.conf->stretchVideo, _global.renderer); } - if (_global.videoHandle < 0) utilDie("Unable to load video file: %s", _global.conf.videoFile); - videoSetVolume(_global.videoHandle, _global.conf.volumeVldp, _global.conf.volumeVldp); + if (_global.videoHandle < 0) utilDie("Unable to load video file: %s", _global.conf->videoFile); + videoSetVolume(_global.videoHandle, _global.conf->volumeVldp, _global.conf->volumeVldp); videoSetIndexCallback(NULL); doIndexDisplay(-2); // Should we resize the window? - //***TODO*** + if (conf->resolutionWasCalculated) { + // Is the video wider than the display window? + if ((videoGetWidth(_global.videoHandle) / videoGetHeight(_global.videoHandle)) > (conf->xResolution / conf->yResolution)) { + // Find new window height + conf->yResolution = ((float)conf->xResolution / (float)videoGetWidth(_global.videoHandle) * (float)videoGetHeight(_global.videoHandle)); + changed = true; + } else { + // Find new window width + conf->xResolution = ((float)conf->yResolution / (float)videoGetHeight(_global.videoHandle) * (float)videoGetWidth(_global.videoHandle)); + changed = true; + } + if (changed) { + SDL_SetWindowSize(_global.window, conf->xResolution, conf->yResolution); + SDL_DestroyRenderer(_global.renderer); + // Recreate an accelerated renderer. + _global.renderer = SDL_CreateRenderer(_global.window, -1, SDL_RENDERER_ACCELERATED); + if (_global.renderer == NULL) utilDie("%s", SDL_GetError()); + // Clear screen with black + SDL_SetRenderDrawColor(_global.renderer, 0, 0, 0, 255); + SDL_RenderClear(_global.renderer); + changed = false; + } + } // Default render location is the entire window - windowTarget.x = 0; - windowTarget.y = 0; - windowTarget.w = videoGetWidth(_global.videoHandle); - windowTarget.h = videoGetHeight(_global.videoHandle); + windowTarget.x = 0; + windowTarget.y = 0; + windowTarget.w = videoGetWidth(_global.videoHandle); + windowTarget.h = videoGetHeight(_global.videoHandle); sindenWhite.x = -1; sindenBlack.x = -1; // Overscan compensation - if (_global.conf.scaleFactor < 100) { - windowTarget.w = videoGetWidth(_global.videoHandle) * _global.conf.scaleFactor / 100; - windowTarget.h = videoGetHeight(_global.videoHandle) * _global.conf.scaleFactor / 100; + if (_global.conf->scaleFactor < 100) { + windowTarget.w = videoGetWidth(_global.videoHandle) * _global.conf->scaleFactor / 100; + windowTarget.h = videoGetHeight(_global.videoHandle) * _global.conf->scaleFactor / 100; windowTarget.x = (videoGetWidth(_global.videoHandle) - windowTarget.w) / 2; windowTarget.y = (videoGetHeight(_global.videoHandle) - windowTarget.h) / 2; } // Sinden Light Gun Border Setup - if (_global.conf.sindenArgc > 0) { + if (_global.conf->sindenArgc > 0) { //***TODO*** ADD MOUSE SCALING TO COMPENSATE FOR BORDER sindenWhiteColor.r = 255; sindenWhiteColor.g = 255; @@ -3658,41 +3783,41 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { sindenBlackColor.b = 0; sindenBlackColor.a = 255; // Ok, this thing can have a mess of different arguments: - switch(_global.conf.sindenArgc) { + switch(_global.conf->sindenArgc) { // WW - Just the width of the white border case SINDEN_WHITE: - sindenWhite.x = _global.conf.sindenArgv[0]; + sindenWhite.x = _global.conf->sindenArgv[0]; break; // WW WB - Width of white border and then black border case SINDEN_WHITE_BLACK: - sindenWhite.x = _global.conf.sindenArgv[0]; - sindenBlack.x = _global.conf.sindenArgv[1]; + sindenWhite.x = _global.conf->sindenArgv[0]; + sindenBlack.x = _global.conf->sindenArgv[1]; break; // RW GW BW WW - Custom color "white" border and width case SINDEN_CUSTOM_WHITE: - sindenWhiteColor.r = _global.conf.sindenArgv[0]; - sindenWhiteColor.g = _global.conf.sindenArgv[1]; - sindenWhiteColor.b = _global.conf.sindenArgv[2]; - sindenWhite.x = _global.conf.sindenArgv[3]; + sindenWhiteColor.r = _global.conf->sindenArgv[0]; + sindenWhiteColor.g = _global.conf->sindenArgv[1]; + sindenWhiteColor.b = _global.conf->sindenArgv[2]; + sindenWhite.x = _global.conf->sindenArgv[3]; break; // RW GW BW WW WB - Custom color "white" border and width then width of black border case SINDEN_CUSTOM_WHITE_BLACK: - sindenWhiteColor.r = _global.conf.sindenArgv[0]; - sindenWhiteColor.g = _global.conf.sindenArgv[1]; - sindenWhiteColor.b = _global.conf.sindenArgv[2]; - sindenWhite.x = _global.conf.sindenArgv[3]; - sindenBlack.x = _global.conf.sindenArgv[4]; + sindenWhiteColor.r = _global.conf->sindenArgv[0]; + sindenWhiteColor.g = _global.conf->sindenArgv[1]; + sindenWhiteColor.b = _global.conf->sindenArgv[2]; + sindenWhite.x = _global.conf->sindenArgv[3]; + sindenBlack.x = _global.conf->sindenArgv[4]; break; // RW GW BW WW RB GB BB WB - Custom color "white" border and width then custom color "black" border and width case SINDEN_CUSTOM_WHITE_CUSTOM_BLACK: - sindenWhiteColor.r = _global.conf.sindenArgv[0]; - sindenWhiteColor.g = _global.conf.sindenArgv[1]; - sindenWhiteColor.b = _global.conf.sindenArgv[2]; - sindenWhite.x = _global.conf.sindenArgv[3]; - sindenBlackColor.r = _global.conf.sindenArgv[4]; - sindenBlackColor.g = _global.conf.sindenArgv[5]; - sindenBlackColor.b = _global.conf.sindenArgv[6]; - sindenBlack.x = _global.conf.sindenArgv[7]; + sindenWhiteColor.r = _global.conf->sindenArgv[0]; + sindenWhiteColor.g = _global.conf->sindenArgv[1]; + sindenWhiteColor.b = _global.conf->sindenArgv[2]; + sindenWhite.x = _global.conf->sindenArgv[3]; + sindenBlackColor.r = _global.conf->sindenArgv[4]; + sindenBlackColor.g = _global.conf->sindenArgv[5]; + sindenBlackColor.b = _global.conf->sindenArgv[6]; + sindenBlack.x = _global.conf->sindenArgv[7]; break; } if (sindenWhite.x >= 0) { @@ -3730,7 +3855,7 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { _global.mouseCount = MAX_MICE; } memset(_global.mice, 0, sizeof(_global.mice)); - _global.mouseEnabled = (bool)!_global.conf.noMouse; + _global.mouseEnabled = (bool)!_global.conf->noMouse; for (x=0; x<_global.mouseCount; x++) { strncpy(_global.mice[x].name, ManyMouse_DeviceName((unsigned)x), sizeof(_global.mice[x].name)); _global.mice[x].name[sizeof(_global.mice[x].name) - 1] = 0; @@ -3752,7 +3877,7 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { // Controllers are started by the event loop // Set volume - _global.effectsVolume = (int32_t)((float)AUDIO_MAX_VOLUME * (float)_global.conf.volumeNonVldp * (float)0.01); + _global.effectsVolume = (int32_t)((float)AUDIO_MAX_VOLUME * (float)_global.conf->volumeNonVldp * (float)0.01); Mix_Volume(-1, _global.effectsVolume * 2); // Let us know when sounds end @@ -3770,7 +3895,7 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { _global.discStopped = false; // Start script - if (luaL_dofile(_global.luaContext, _global.conf.scriptFile) != 0) utilDie("Error compiling script: %s", lua_tostring(_global.luaContext, -1)); + if (luaL_dofile(_global.luaContext, _global.conf->scriptFile) != 0) utilDie("Error compiling script: %s", lua_tostring(_global.luaContext, -1)); // Game Loop while (_global.running) { @@ -3984,7 +4109,7 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { // Update video thisFrame = videoUpdate(_global.videoHandle, &_global.videoTexture); - if (_global.conf.isFrameFile) { + if (_global.conf->isFrameFile) { frameFileUpdate(_global.frameFileHandle, &_global.videoHandle); } // Did we get a new video frame? @@ -4032,7 +4157,7 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { // Overlay overlayTexture = SDL_CreateTextureFromSurface(_global.renderer, _global.overlay); if (!overlayTexture) utilDie("%s", SDL_GetError()); - if (!_global.conf.stretchVideo) { + if (!_global.conf->stretchVideo) { SDL_RenderSetLogicalSize(renderer, videoGetWidth(_global.videoHandle), videoGetHeight(_global.videoHandle)); } SDL_RenderCopy(_global.renderer, overlayTexture, NULL, &windowTarget); @@ -4103,7 +4228,7 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { } // Unload background video - if (_global.conf.isFrameFile) { + if (_global.conf->isFrameFile) { frameFileUnload(_global.frameFileHandle); } else { videoUnload(_global.videoHandle); @@ -4115,6 +4240,14 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) { // Stop mice SDL_ShowCursor(SDL_ENABLE); ManyMouse_Quit(); + + // Release global conf memory + destroyConf(&_global.conf); + + // Release control mappings + for (x=0; xdataDir, x); if (!utilFileExists(filename)) break; x++; } diff --git a/singe/singe.h b/singe/singe.h index fe02b9b06..26a6dc3e5 100644 --- a/singe/singe.h +++ b/singe/singe.h @@ -50,6 +50,7 @@ typedef struct ConfigS { char *scriptFile; char *dataDir; char *dataDirBase; + bool resolutionWasCalculated; bool isFrameFile; bool stretchVideo; bool noMouse; diff --git a/singe/singe.pro b/singe/singe.pro index 2b9a821f1..c86ce6c39 100644 --- a/singe/singe.pro +++ b/singe/singe.pro @@ -322,3 +322,6 @@ platformLinux { write_file("source.inc.sh", FILEINFO) } + +DISTFILES += \ + makePDFs.docbuilder diff --git a/singe/util.c b/singe/util.c index b2dd535f8..a671439d5 100644 --- a/singe/util.c +++ b/singe/util.c @@ -156,7 +156,7 @@ void utilFixPathSeparators(char **path, bool slash) { // No - append one. temp = strdup(work); free(work); - work = malloc(sizeof(char) * (strlen(temp) + 1)); + work = malloc(sizeof(char) * (strlen(temp) + 2)); strcpy(work, temp); work[strlen(temp)] = utilGetPathSeparator(); work[strlen(temp) + 1] = 0; @@ -219,12 +219,18 @@ char utilGetPathSeparator(void) { char *utilGetUpToLastPathComponent(char *pathname) { - static char *copy; + static char *copy = NULL; + bool dumb = false; // Using (copy == NULL) below didn't work after optimizations, so enter the dummy. int32_t x; x = (int32_t)(strlen(pathname) - strlen(utilGetLastPathComponent(pathname))) - 1; if (x < 0) x = 0; - if (copy) free(copy); + if (dumb) { + free(copy); + copy = NULL; + } else { + dumb = true; + } copy = strdup(pathname); copy[x] = 0; utilFixPathSeparators(©, true);