From 226dac5a1a8b5d632acf5d5cf1dd71dd3dc16df8 Mon Sep 17 00:00:00 2001 From: Jon Bell Date: Mon, 15 Jan 2024 10:21:40 -0700 Subject: [PATCH] WIP- zepto 8 bios displaying --- platform/libretro/libretro.cpp | 10 +- source/{FakoBios.h => DefaultCart.h} | 2 +- source/FakoSettings.h | 2 +- source/cart.cpp | 8 +- source/main.cpp | 22 ++- source/p8GlobalLuaFunctions.h | 4 +- source/picoluaapi.cpp | 4 +- source/picoluaapi.h | 2 +- source/vm.cpp | 215 ++++++++++++++++++++++++--- source/vm.h | 2 + test/carttests.cpp | 4 +- 11 files changed, 234 insertions(+), 41 deletions(-) rename source/{FakoBios.h => DefaultCart.h} (99%) diff --git a/platform/libretro/libretro.cpp b/platform/libretro/libretro.cpp index be637a56..9001f501 100644 --- a/platform/libretro/libretro.cpp +++ b/platform/libretro/libretro.cpp @@ -138,7 +138,7 @@ EXPORT void retro_init() _vm->SetCartList(_host->listcarts()); - _vm->LoadBiosCart(); + //_vm->LoadBiosCart(); } EXPORT void retro_deinit() @@ -615,10 +615,10 @@ EXPORT void retro_cheat_set(unsigned index, bool enabled, const char *code) EXPORT bool retro_load_game(struct retro_game_info const *info) { - if (!info) { - _vm->QueueCartChange("__FAKE08-BIOS.p8"); - return true; - } + // if (!info) { + // _vm->QueueCartChange("__FAKE08-DEFAULT.p8"); + // return true; + // } auto containingDir = getDirectory(info->path); diff --git a/source/FakoBios.h b/source/DefaultCart.h similarity index 99% rename from source/FakoBios.h rename to source/DefaultCart.h index 5fca2006..7aae6a0a 100644 --- a/source/FakoBios.h +++ b/source/DefaultCart.h @@ -10,7 +10,7 @@ //this shouldn't really count as the bios //this is the cart loader cart -const char * fake08BiosP8 = R"#( +const char * fake08DefaultCart = R"#( pico-8 cartridge // http://www.pico-8.com version 35 __lua__ diff --git a/source/FakoSettings.h b/source/FakoSettings.h index 3bc12ef1..13d6bccb 100644 --- a/source/FakoSettings.h +++ b/source/FakoSettings.h @@ -174,7 +174,7 @@ function updatecursor() cursorpos = deli(path) if not cursorpos then --exit to bios - __loadbioscart() + __loaddefaultcart() end else if inoption then diff --git a/source/cart.cpp b/source/cart.cpp index bd5e71f9..3985037d 100644 --- a/source/cart.cpp +++ b/source/cart.cpp @@ -20,7 +20,7 @@ #include "emojiconversion.h" -#include "FakoBios.h" +#include "DefaultCart.h" #include "FakoSettings.h" @@ -456,11 +456,11 @@ Cart::Cart(std::string filename, std::string cartDirectory){ std::string firstFourChars = get_first_four_chars(FullCartPath); - if (FullCartPath == "__FAKE08-BIOS.p8" || FullCartPath == "__FAKE08-SETTINGS.p8" || firstFourChars == "pico"){ + if (FullCartPath == "__FAKE08-DEFAULT.p8" || FullCartPath == "__FAKE08-SETTINGS.p8" || firstFourChars == "pico"){ std::string cartStr; - if (FullCartPath == "__FAKE08-BIOS.p8") { - cartStr = fake08BiosP8; + if (FullCartPath == "__FAKE08-DEFAULT.p8") { + cartStr = fake08DefaultCart; } else if (FullCartPath == "__FAKE08-SETTINGS.p8") { cartStr = fake08SettingsP8; diff --git a/source/main.cpp b/source/main.cpp index 6fffa7a4..e669fed0 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -27,7 +27,7 @@ int main(int argc, char* argv[]) Logger_Initialize(host->logFilePrefix()); Vm *vm = new Vm(host, memory, nullptr, nullptr, audio); - + host->setUpPaletteColors(); host->oneTimeSetup(audio); @@ -35,6 +35,15 @@ int main(int argc, char* argv[]) host->unpackCarts(); #endif + + Logger_Write("initializing Vm\n"); + + bool vmInitResult = vm->Initialize(); + + if (!vmInitResult) { + Logger_Write("vm init failed\n"); + return 1; + } Logger_Write("initialized Vm and host\n"); @@ -59,14 +68,15 @@ int main(int argc, char* argv[]) } #endif - Logger_Write("Loading Bios cart\n"); + if (loadCart){ + Logger_Write("Loading arg cart \n"); vm->LoadCart(cart); } - else { - vm->LoadBiosCart(); - } - Logger_Write("Bios Cart Loaded\n"); + // else { + // vm->LoadBiosCart(); + // } + //Logger_Write("Bios Cart Loaded\n"); // Main loop Logger_Write("Starting main loop\n"); diff --git a/source/p8GlobalLuaFunctions.h b/source/p8GlobalLuaFunctions.h index 2cf71cb0..5f836b56 100644 --- a/source/p8GlobalLuaFunctions.h +++ b/source/p8GlobalLuaFunctions.h @@ -6,7 +6,7 @@ //from zepto 8 bios.p8 //this is the bios-- needs to get loaded first, and then will run every cart -const char * p8GlobalLuaFunctions = R"#( +const char * p8Bios = R"#( -- The functions below are normally attached to the program code, but are here for simplicity --------------------------------- --Table Helpers @@ -182,7 +182,7 @@ __f08_menu_items = { {nil, nil}, {nil, nil}, {"reset cart", __resetcart}, - {"exit to menu", __loadbioscart}, + {"exit to menu", __loaddefaultcart}, {"exit to settings", __loadsettingscart} } diff --git a/source/picoluaapi.cpp b/source/picoluaapi.cpp index c8a205d0..ae660090 100644 --- a/source/picoluaapi.cpp +++ b/source/picoluaapi.cpp @@ -1321,8 +1321,8 @@ int getbioserror(lua_State *L) { return 1; } -int loadbioscart(lua_State *L) { - _vmForLuaApi->QueueCartChange("__FAKE08-BIOS.p8"); +int loaddefaultcart(lua_State *L) { + _vmForLuaApi->QueueCartChange("__FAKE08-DEFAULT.p8"); return 0; } diff --git a/source/picoluaapi.h b/source/picoluaapi.h index 48c3eb8d..7196a37a 100644 --- a/source/picoluaapi.h +++ b/source/picoluaapi.h @@ -95,7 +95,7 @@ int printh(lua_State *L); int listcarts(lua_State *L); int getbioserror(lua_State *L); -int loadbioscart(lua_State *L); +int loaddefaultcart(lua_State *L); int loadsettingscart(lua_State *L); int togglepausemenu(lua_State *L); int resetcart(lua_State *L); diff --git a/source/vm.cpp b/source/vm.cpp index e52cd55f..0de0ec1d 100644 --- a/source/vm.cpp +++ b/source/vm.cpp @@ -34,7 +34,7 @@ using namespace z8; -static const char BiosCartName[] = "__FAKE08-BIOS.p8"; +static const char DefaultCartName[] = "__FAKE08-DEFAULT.p8"; static const char SettingsCartName[] = "__FAKE08-SETTINGS.p8"; Vm::Vm( @@ -115,6 +115,181 @@ PicoRam* Vm::getPicoRam(){ jmp_buf place; bool abortLua; +bool Vm::Initialize() { + _picoFrameCount = 0; + + _cartdataKey = ""; + + //reset memory (may have to be more selective about zeroing out to be accurate?) + _memory->Reset(); + + //seed rng + auto now = std::chrono::high_resolution_clock::now(); + api_srand(fix32::frombits((int32_t)now.time_since_epoch().count())); + + //set graphics state + _graphics->color(); + _graphics->clip(); + _graphics->pal(); + + //reset audio + _audio->resetAudioState(); + + _cartChangeQueued = false; + abortLua = false; + + // initialize Lua interpreter + _luaState = luaL_newstate(); + + lua_setpico8memory(_luaState, (uint8_t *)&_memory->data); + // load Lua base libraries (print / math / etc) + luaL_openlibs(_luaState); + lua_pushglobaltable(_luaState); + + //system + //must be registered before loading globals for pause menu to work + lua_register(_luaState, "__listcarts", listcarts); + lua_register(_luaState, "__getbioserror", getbioserror); + lua_register(_luaState, "__loaddefaultcart", loaddefaultcart); + lua_register(_luaState, "__loadsettingscart", loadsettingscart); + lua_register(_luaState, "__togglepausemenu", togglepausemenu); + lua_register(_luaState, "__resetcart", resetcart); + //lua_register(_luaState, "load", load); + + //settings + lua_register(_luaState, "__getsetting", getsetting); + lua_register(_luaState, "__setsetting", setsetting); + + lua_register(_luaState, "__installpackins", installpackins); + + //label + lua_register(_luaState, "__loadlabel", loadlabel); + + lua_register(_luaState, "__getlualine", getlualine); + + //register global functions first, they will get local aliases when + //the rest of the api is registered + //graphics + lua_register(_luaState, "cls", cls); + lua_register(_luaState, "pset", pset); + lua_register(_luaState, "pget", pget); + lua_register(_luaState, "color", color); + lua_register(_luaState, "line", line); + lua_register(_luaState, "tline", tline); + lua_register(_luaState, "circ", circ); + lua_register(_luaState, "circfill", circfill); + lua_register(_luaState, "oval", oval); + lua_register(_luaState, "ovalfill", ovalfill); + lua_register(_luaState, "rect", rect); + lua_register(_luaState, "rectfill", rectfill); + lua_register(_luaState, "print", print); + lua_register(_luaState, "cursor", cursor); + lua_register(_luaState, "spr", spr); + lua_register(_luaState, "sspr", sspr); + lua_register(_luaState, "fget", fget); + lua_register(_luaState, "fset", fset); + lua_register(_luaState, "sget", sget); + lua_register(_luaState, "sset", sset); + lua_register(_luaState, "camera", camera); + lua_register(_luaState, "clip", clip); + + lua_register(_luaState, "pal", pal); + lua_register(_luaState, "palt", palt); + + lua_register(_luaState, "mget", mget); + lua_register(_luaState, "mset", mset); + lua_register(_luaState, "map", gfx_map); + lua_register(_luaState, "mapdraw", gfx_map); + + //stubbed in graphics: + lua_register(_luaState, "fillp", fillp); + //lua_register(_luaState, "flip", flip); + + //input + lua_register(_luaState, "btn", btn); + lua_register(_luaState, "btnp", btnp); + + lua_register(_luaState, "time", time); + lua_register(_luaState, "t", time); + + //audio: + lua_register(_luaState, "music", music); + lua_register(_luaState, "sfx", sfx); + + //memory + lua_register(_luaState, "cstore", cstore); + lua_register(_luaState, "memcpy", api_memcpy); + lua_register(_luaState, "memset", api_memset); + lua_register(_luaState, "peek", peek); + lua_register(_luaState, "poke", poke); + lua_register(_luaState, "peek2", peek2); + lua_register(_luaState, "poke2", poke2); + lua_register(_luaState, "peek4", peek4); + lua_register(_luaState, "poke4", poke4); + lua_register(_luaState, "reload", reload); + lua_register(_luaState, "reset", reset); + + //cart data + lua_register(_luaState, "cartdata", cartdata); + lua_register(_luaState, "dget", dget); + lua_register(_luaState, "dset", dset); + + // + lua_register(_luaState, "printh", printh); + lua_register(_luaState, "stat", stat); + lua_register(_luaState, "_update_buttons", _update_buttons); + lua_register(_luaState, "run", run); + lua_register(_luaState, "extcmd", extcmd); + lua_register(_luaState, "_set_fps", setFps); + + //rng + lua_register(_luaState, "rnd", rnd); + lua_register(_luaState, "srand", srand); + + //load in global lua fuctions for pico 8- part of this is setting a local variable + //with the same name as all the globals we just registered + //auto convertedGlobalLuaFunctions = convert_emojis(p8GlobalLuaFunctions); + auto convertedP8Bios = charset::utf8_to_pico8(p8Bios); + int loadedBiosResult = luaL_dostring(_luaState, convertedP8Bios.c_str()); + + if (loadedBiosResult != LUA_OK) { + _cartLoadError = "ERROR loading pico 8 bios"; + Logger_Write("ERROR loading pico 8 bios\n"); + Logger_Write("Error: %s\n", lua_tostring(_luaState, -1)); + lua_pop(_luaState, 1); + + return false; + } + + // Push the eris.init_persist_all function on the top of the lua stack (or nil if it doesn't exist) + // we call this function to establish the default global state of things not to save in the save state + // needs to be called after globals are loaded but before the cart is run, or _init is called + //TODO: move these calls to the glue code? + lua_getglobal(_luaState, "eris"); + lua_getfield(_luaState, -1, "init_persist_all"); + + if (lua_pcall(_luaState, 0, 0, 0)){ + Logger_Write("Error setting up lua persistence: %s\n", lua_tostring(_luaState, -1)); + lua_pop(_luaState, 1); + return false; + } + + //pop the eris.init_persist_all fuction off the stack now that we're done with it + lua_pop(_luaState, 1); + + + + if (abortLua) { + //trigger closing of cart and reload of bios + return false; + } + + _cartLoadError = ""; + + return true; + +} + bool Vm::loadCart(Cart* cart) { _picoFrameCount = 0; @@ -163,7 +338,7 @@ bool Vm::loadCart(Cart* cart) { //must be registered before loading globals for pause menu to work lua_register(_luaState, "__listcarts", listcarts); lua_register(_luaState, "__getbioserror", getbioserror); - lua_register(_luaState, "__loadbioscart", loadbioscart); + lua_register(_luaState, "__loaddefaultcart", loaddefaultcart); lua_register(_luaState, "__loadsettingscart", loadsettingscart); lua_register(_luaState, "__togglepausemenu", togglepausemenu); lua_register(_luaState, "__resetcart", resetcart); @@ -262,7 +437,7 @@ bool Vm::loadCart(Cart* cart) { //load in global lua fuctions for pico 8- part of this is setting a local variable //with the same name as all the globals we just registered //auto convertedGlobalLuaFunctions = convert_emojis(p8GlobalLuaFunctions); - auto convertedGlobalLuaFunctions = charset::utf8_to_pico8(p8GlobalLuaFunctions); + auto convertedGlobalLuaFunctions = charset::utf8_to_pico8(p8Bios); int loadedGlobals = luaL_dostring(_luaState, convertedGlobalLuaFunctions.c_str()); if (loadedGlobals != LUA_OK) { @@ -386,7 +561,7 @@ end //customize bios per host's requirements - if (cart->FullCartPath == BiosCartName || cart->FullCartPath == SettingsCartName) { + if (cart->FullCartPath == DefaultCartName || cart->FullCartPath == SettingsCartName) { std::string customBiosLua = _host->customBiosLua(); if (customBiosLua.length() > 0) { @@ -412,7 +587,7 @@ end void Vm::LoadBiosCart(){ CloseCart(); - Cart *cart = new Cart(BiosCartName, ""); + Cart *cart = new Cart(DefaultCartName, ""); bool success = loadCart(cart); @@ -434,10 +609,10 @@ void Vm::LoadSettingsCart(){ } void Vm::LoadCart(std::string filename, bool loadBiosOnFail){ - if (filename == "__FAKE08-BIOS.p8") { - LoadBiosCart(); - return; - } + // if (filename == "__FAKE08-DEFAULT.p8") { + // LoadBiosCart(); + // return; + // } if (filename == "__FAKE08-SETTINGS.p8") { LoadSettingsCart(); return; @@ -456,7 +631,7 @@ void Vm::LoadCart(std::string filename, bool loadBiosOnFail){ if (loadBiosOnFail && !success) { CloseCart(); //todo: show an error message on the bios? - LoadBiosCart(); + //LoadBiosCart(); } } @@ -474,7 +649,7 @@ void Vm::LoadCart(const unsigned char* cartData, size_t size, bool loadBiosOnFai if (loadBiosOnFail && !success) { CloseCart(); //todo: show an error message on the bios? - LoadBiosCart(); + //LoadBiosCart(); } } @@ -565,21 +740,24 @@ void Vm::deserializeCartDataToMemory(std::string cartDataStr) { } bool Vm::Step(){ + Logger_Write("getting __z8_tick\n"); bool ret = false; lua_getglobal(_luaState, "__z8_tick"); int status = lua_pcall(_luaState, 0, 1, 0); if (status != LUA_OK) { + Logger_Write("error calling tick"); char const *message = lua_tostring(_luaState, -1); _cartLoadError = "Error in main loop: " + std::string(message); } else { + Logger_Write("successfully called __z8_tick\n"); ret = (int)lua_tonumber(_luaState, -1) >= 0; } lua_pop(_luaState, 1); - + Logger_Write("end of Step()\n"); return ret; } @@ -734,6 +912,7 @@ string Vm::GetBiosError() { } void Vm::GameLoop() { + Logger_Write("Start of GameLoop()"); while (_host->shouldRunMainLoop()) { //shouldn't need to set this every frame @@ -742,19 +921,21 @@ void Vm::GameLoop() { //is this better at the end of the loop? //_host->waitForTargetFps(); - if (_host->shouldQuit()) break; // break in order to return to hbmenu + //if (_host->shouldQuit()) break; // break in order to return to hbmenu //this should probably be handled just in the host class - _host->changeStretch(); + //_host->changeStretch(); //update buttons needs to be callable from the cart, and also flip //it should update call the pico part of scanInput and set the values in memory //then we don't need to pass them in here //UpdateAndDraw(); + Logger_Write("Step()"); Step(); uint8_t* picoFb = GetPicoInteralFb(); uint8_t* screenPaletteMap = GetScreenPaletteMap(); + Logger_Write("drawframe()"); _host->drawFrame(picoFb, screenPaletteMap, _memory->drawState.drawMode); if (_host->shouldFillAudioBuff()) { @@ -865,12 +1046,12 @@ void Vm::vm_poke4(int addr, fix32 value){ bool Vm::vm_cartdata(string key) { //match pico 8 errors if (_cartdataKey != "") { - QueueCartChange(BiosCartName); + QueueCartChange(DefaultCartName); _cartLoadError = "cartdata() can only be called once"; return false; } if (key.length() == 0 || key.length() > 64) { - QueueCartChange(BiosCartName); + QueueCartChange(DefaultCartName); _cartLoadError = "cart data id too long"; return false; } @@ -1084,7 +1265,7 @@ void Vm::vm_extcmd(std::string cmd){ togglePauseMenu(); } else if (cmd == "shutdown") { - QueueCartChange(BiosCartName); + QueueCartChange(DefaultCartName); } } diff --git a/source/vm.h b/source/vm.h index a940c9d4..1be52368 100644 --- a/source/vm.h +++ b/source/vm.h @@ -67,6 +67,8 @@ class Vm { Audio* audio = nullptr); ~Vm(); + bool Initialize(); + void LoadBiosCart(); void LoadSettingsCart(); diff --git a/test/carttests.cpp b/test/carttests.cpp index 24e918ff..688b6e74 100644 --- a/test/carttests.cpp +++ b/test/carttests.cpp @@ -3,10 +3,10 @@ #include "../source/filehelpers.h" TEST_CASE("Loads bios cart") { - Cart* cart = new Cart("__FAKE08-BIOS.p8", ""); + Cart* cart = new Cart("__FAKE08-DEFAULT.p8", ""); SUBCASE("FullCartPath is correct") { - CHECK(cart->FullCartPath == "__FAKE08-BIOS.p8"); + CHECK(cart->FullCartPath == "__FAKE08-DEFAULT.p8"); } SUBCASE("error is empty") { CHECK(cart->LoadError == "");