diff --git a/src/views/game_view.cpp b/src/views/game_view.cpp index 83971b2..4781337 100755 --- a/src/views/game_view.cpp +++ b/src/views/game_view.cpp @@ -154,7 +154,38 @@ void GameView::rasterize() } } +void flip_callback(void *gameview){ + GameView *gv = (GameView*)gameview; + gv->flip(); +} + +void GameView::flip() +{ + // Start with black + manager->clear(0, 0, 0); + // Create pixels to display from machine memory + rasterize(); + _output.update(); + + // Write it to the SDL Surface + SDL_Rect dest; + if (_scaler == Scaler::UNSCALED) + dest = { (SCREEN_WIDTH - 128) / 2, (SCREEN_HEIGHT - 128) / 2, 128, 128 }; + else if (_scaler == Scaler::SCALED_ASPECT_2x) + dest = { (SCREEN_WIDTH - 256) / 2, (SCREEN_HEIGHT - 256) / 2, 256, 256 }; + else + dest = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT }; + manager->blitToScreen(_output, dest); + + // We aren't returning control to ::loop, so force this to display now + manager->flip(); + + // Wait out the right time between frames + // (assumes zero draw time, so this can be improved) + int32_t fps = machine.code().require60fps() ? 60 : 30; + SDL_Delay(1000.0/fps); +} bool init = false; void GameView::render() @@ -181,9 +212,16 @@ void GameView::render() _frameCounter = 0; + machine.setflip(flip_callback, (void*)this); machine.code().loadAPI(); _input.setMachine(&machine); + int32_t fps = machine.code().require60fps() ? 60 : 30; + manager->setFrameRate(fps); + + machine.sound().init(); + sdlAudio.init(&machine.sound()); + sdlAudio.resume(); if (_path.empty()) _path = "cartridges/pico-racer.png"; @@ -207,9 +245,6 @@ void GameView::render() machine.memory().backupCartridge(); - int32_t fps = machine.code().require60fps() ? 60 : 30; - manager->setFrameRate(fps); - if (machine.code().hasInit()) { /* init is launched on a different thread because some developers are using busy loops and manual flips */ @@ -220,10 +255,6 @@ void GameView::render() }); } - machine.sound().init(); - sdlAudio.init(&machine.sound()); - sdlAudio.resume(); - init = true; } diff --git a/src/views/main_view.h b/src/views/main_view.h index 272268e..b3abbea 100755 --- a/src/views/main_view.h +++ b/src/views/main_view.h @@ -67,6 +67,8 @@ namespace ui void toggleFPS(bool active) { _showFPS = active; } bool isFPSShown() { return _showFPS; } + + void flip(); }; class MenuView : public View diff --git a/src/views/sdl_helper.h b/src/views/sdl_helper.h index 08ac9e8..2a35fb3 100644 --- a/src/views/sdl_helper.h +++ b/src/views/sdl_helper.h @@ -124,6 +124,7 @@ class SDL void capFPS(); void loop(); + void flip(); void handleEvents(); void exit() { willQuit = true; } @@ -198,4 +199,4 @@ void SDL::handleEvents() #include "sdl_impl12.h" #else #include "sdl_impl.h" -#endif \ No newline at end of file +#endif diff --git a/src/views/sdl_impl.h b/src/views/sdl_impl.h index 5fce3b1..e23efef 100644 --- a/src/views/sdl_impl.h +++ b/src/views/sdl_impl.h @@ -28,6 +28,12 @@ bool SDL::init() return true; } +template +void SDL::flip() +{ + SDL_RenderPresent(_renderer); +} + template void SDL::loop() { diff --git a/src/views/sdl_impl12.h b/src/views/sdl_impl12.h index 4e71eea..c745e30 100644 --- a/src/views/sdl_impl12.h +++ b/src/views/sdl_impl12.h @@ -24,6 +24,12 @@ bool SDL::init() return true; } +template +void SDL::flip() +{ + SDL_Flip(_screen); +} + template void SDL::loop() { diff --git a/src/vm/lua_bridge.cpp b/src/vm/lua_bridge.cpp index 0174cd5..15e54de 100755 --- a/src/vm/lua_bridge.cpp +++ b/src/vm/lua_bridge.cpp @@ -975,10 +975,7 @@ namespace platform int flip(lua_State* L) { - //TODO: this call should syncronize to 30fps, at the moment it just - // returns producing a lot of flips in non synchronized code (eg. _init() busy loop) - //TODO: flip is handled by backend so we should find a way to set the callback that should be called - + machine.flip(); return 0; } @@ -1161,13 +1158,29 @@ void Code::initFromSource(const std::string& code) if (error) printError("lua_pcall on init"); + lua_getglobal(L, "_init"); + + if (lua_isfunction(L, -1)) + { + _init = lua_topointer(L, -1); + lua_pop(L, 1); + } + + fetchGlobals(); +} +void Code::fetchGlobals() +{ lua_getglobal(L, "_update"); if (lua_isfunction(L, -1)) { _update = lua_topointer(L, -1); lua_pop(L, 1); } + else + { + _update = NULL; + } lua_getglobal(L, "_update60"); @@ -1176,6 +1189,10 @@ void Code::initFromSource(const std::string& code) _update60 = lua_topointer(L, -1); lua_pop(L, 1); } + else + { + _update60 = NULL; + } lua_getglobal(L, "_draw"); @@ -1184,13 +1201,9 @@ void Code::initFromSource(const std::string& code) _draw = lua_topointer(L, -1); lua_pop(L, 1); } - - lua_getglobal(L, "_init"); - - if (lua_isfunction(L, -1)) + else { - _init = lua_topointer(L, -1); - lua_pop(L, 1); + _draw = NULL; } } @@ -1205,6 +1218,7 @@ void Code::callFunction(const char* name, int ret) void Code::update() { + fetchGlobals(); if (_update60) callFunction("_update60"); else if (_update) @@ -1213,6 +1227,7 @@ void Code::update() void Code::draw() { + fetchGlobals(); if (_draw) callFunction("_draw"); } diff --git a/src/vm/lua_bridge.h b/src/vm/lua_bridge.h index 91a7d19..2de2b3d 100755 --- a/src/vm/lua_bridge.h +++ b/src/vm/lua_bridge.h @@ -25,6 +25,8 @@ namespace lua const void* _update60; const void* _draw; + void fetchGlobals(); + public: Code() : L(nullptr) { } ~Code(); @@ -49,4 +51,4 @@ namespace lua lua_State* state() const { return L; } #endif }; -} \ No newline at end of file +} diff --git a/src/vm/machine.cpp b/src/vm/machine.cpp index 575ecdd..231a913 100755 --- a/src/vm/machine.cpp +++ b/src/vm/machine.cpp @@ -359,3 +359,15 @@ void Machine::map(coord_t cx, coord_t cy, coord_t x, coord_t y, amount_t cw, amo } } } + +void Machine::setflip(void(*newflip)(void*), void *flipdata) +{ + _flipdata = flipdata; + _flip = newflip; +} + +void Machine::flip() +{ + if (_flip) + _flip(_flipdata); +} diff --git a/src/vm/machine.h b/src/vm/machine.h index 7b0953b..42ba28f 100755 --- a/src/vm/machine.h +++ b/src/vm/machine.h @@ -29,6 +29,8 @@ namespace retro8 sfx::APU _sound; gfx::Font _font; lua::Code _code; + void *_flipdata; + void (*_flip)(void*) = NULL; private: void circHelper(coord_t xc, coord_t yc, coord_t x, coord_t y, color_t col); @@ -65,6 +67,9 @@ namespace retro8 void print(const std::string& string, coord_t x, coord_t y, color_t color); + void setflip(void (*newflip)(void *), void *flipdata); + void flip(); + State& state() { return _state; } Memory& memory() { return _memory; } gfx::Font& font() { return _font; }