Commit 321f9bd2 authored by phcoder's avatar phcoder
Browse files

Change machine to be a pointer and avoid the need for global constructors

parent ea2b1efa
......@@ -20,7 +20,7 @@ constexpr int SAMPLE_RATE = 44100;
constexpr int SAMPLES_PER_FRAME = SAMPLE_RATE / 60;
constexpr int SOUND_CHANNELS = 2;
r8::Machine machine;
r8::Machine *machine;
r8::io::Loader loader;
r8::input::InputManager input;
......@@ -146,10 +146,6 @@ extern "C"
{
audioBuffer = new int16_t[SAMPLE_RATE * 2];
env.logger(retro_log_level::RETRO_LOG_INFO, "Initializing audio buffer of %d bytes\n", sizeof(int16_t) * SAMPLE_RATE * 2);
machine.font().load();
machine.code().loadAPI();
input.setMachine(&machine);
}
void retro_deinit()
......@@ -211,6 +207,11 @@ extern "C"
bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info) { return false; }
bool retro_load_game(const retro_game_info* info)
{
machine = new r8::Machine();
machine->font().load();
machine->code().loadAPI();
input.setMachine(machine);
if (info && info->data)
{
input.reset();
......@@ -234,23 +235,23 @@ extern "C"
buf[i] = out[4 * i] | (out[4 * i + 1] << 8) | (out[4 * i + 2] << 16) | (out[4 * i + 3] << 24);
}
r8::io::PngData pngData = { buf, NULL, out.size() / 4 };
stegano.load(pngData, machine);
stegano.load(pngData, *machine);
delete[] buf;
}
else
{
//TODO: not efficient since it's copied and it's not checking for '\0'
std::string raw(bdata);
loader.loadRaw(raw, machine);
loader.loadRaw(raw, *machine);
}
machine.memory().backupCartridge();
machine->memory().backupCartridge();
if (machine.code().hasInit())
if (machine->code().hasInit())
{
//_initFuture = std::async(std::launch::async, []() {
LIBRETRO_LOG("[Retro8] Cartridge has _init() function, calling it.");
machine.code().init();
machine->code().init();
LIBRETRO_LOG("[Retro8] _init() function completed execution.");
//});
}
......@@ -288,20 +289,21 @@ extern "C"
delete screen32;
screen16 = NULL;
screen32 = NULL;
delete machine;
}
void retro_run()
{
/* if code is at 60fps or every 2 frames (30fps) */
if (machine.code().require60fps() || env.frameCounter % 2 == 0)
if (machine->code().require60fps() || env.frameCounter % 2 == 0)
{
/* call _update and _draw of PICO-8 code */
machine.code().update();
machine.code().draw();
machine->code().update();
machine->code().draw();
/* rasterize screen memory to ARGB framebuffer */
auto* data = machine.memory().screenData();
auto* screenPalette = machine.memory().paletteAt(retro8::gfx::SCREEN_PALETTE_INDEX);
auto* data = machine->memory().screenData();
auto* screenPalette = machine->memory().paletteAt(retro8::gfx::SCREEN_PALETTE_INDEX);
if (env.isRGB32)
screen32->draw(data, screenPalette);
......@@ -318,7 +320,7 @@ extern "C"
++env.frameCounter;
#if SOUND_ENABLED
machine.sound().renderSounds(audioBuffer, SAMPLES_PER_FRAME);
machine->sound().renderSounds(audioBuffer, SAMPLES_PER_FRAME);
/* duplicate channels */
auto* audioBuffer2 = audioBuffer + SAMPLE_RATE;
......
#include "views/view_manager.h"
#include "views/main_view.h"
#include "vm/machine.h"
/*
* D-PAD Left - SDLK_LEFT
......@@ -28,6 +29,7 @@ extern int testMain(int argc, char* argv[]);
int main(int argc, char* argv[])
{
machine = new retro8::Machine();
#if TEST_MODE
return testMain(argc, argv);
#endif
......
......@@ -15,8 +15,7 @@
using namespace retro8;
using namespace retro8::gfx;
extern retro8::Machine machine;
Machine& m = machine;
Machine& m = *machine;
TEST_CASE("cursor([x,] [y,] [col])")
{
......
......@@ -69,8 +69,7 @@ SDLAudio sdlAudio;
using namespace ui;
namespace r8 = retro8;
retro8::Machine machine;
retro8::Machine *machine;
GameView::GameView(ViewManager* manager) : manager(manager),
_paused(false), _showFPS(false), _showCartridgeName(false)
......@@ -80,8 +79,8 @@ _paused(false), _showFPS(false), _showCartridgeName(false)
void GameView::update()
{
machine.code().update();
machine.code().draw();
machine->code().update();
machine->code().draw();
}
......@@ -138,8 +137,8 @@ struct ColorMapper
void GameView::rasterize()
{
auto* data = machine.memory().screenData();
auto* screenPalette = machine.memory().paletteAt(r8::gfx::SCREEN_PALETTE_INDEX);
auto* data = machine->memory().screenData();
auto* screenPalette = machine->memory().paletteAt(r8::gfx::SCREEN_PALETTE_INDEX);
uint32_t* output = _output.pixels();
for (size_t i = 0; i < r8::gfx::BYTES_PER_SCREEN; ++i)
......@@ -155,7 +154,6 @@ void GameView::rasterize()
}
bool init = false;
void GameView::render()
{
......@@ -181,8 +179,8 @@ void GameView::render()
_frameCounter = 0;
machine.code().loadAPI();
_input.setMachine(&machine);
machine->code().loadAPI();
_input.setMachine(machine);
if (_path.empty())
......@@ -193,7 +191,7 @@ void GameView::render()
auto cartridge = loadPng(_path);
retro8::io::Stegano stegano;
stegano.load(cartridge, machine);
stegano.load(cartridge, *machine);
manager->setPngCartridge(static_cast<SDL_Surface*>(cartridge.userData));
SDL_FreeSurface(static_cast<SDL_Surface*>(cartridge.userData));
......@@ -201,27 +199,27 @@ void GameView::render()
else
{
r8::io::Loader loader;
loader.loadFile(_path, machine);
loader.loadFile(_path, *machine);
manager->setPngCartridge(nullptr);
}
machine.memory().backupCartridge();
machine->memory().backupCartridge();
int32_t fps = machine.code().require60fps() ? 60 : 30;
int32_t fps = machine->code().require60fps() ? 60 : 30;
manager->setFrameRate(fps);
if (machine.code().hasInit())
if (machine->code().hasInit())
{
/* init is launched on a different thread because some developers are using busy loops and manual flips */
_initFuture = std::async(std::launch::async, []() {
LOGD("Cartridge has _init() function, calling it.");
machine.code().init();
machine->code().init();
LOGD("_init() function completed execution.");
});
}
machine.sound().init();
sdlAudio.init(&machine.sound());
machine->sound().init();
sdlAudio.init(&machine->sound());
sdlAudio.resume();
init = true;
......@@ -259,7 +257,7 @@ void GameView::render()
if (_showFPS)
{
char buffer[16];
sprintf(buffer, "%.0f/%c0", 1000.0f / manager->lastFrameTicks(), machine.code().require60fps() ? '6' : '3');
sprintf(buffer, "%.0f/%c0", 1000.0f / manager->lastFrameTicks(), machine->code().require60fps() ? '6' : '3');
manager->text(buffer, 10, 10);
}
......@@ -276,7 +274,7 @@ void GameView::render()
for (r8::coord_t y = 0; y < r8::gfx::SPRITE_SHEET_HEIGHT; ++y)
for (r8::coord_t x = 0; x < r8::gfx::SPRITE_SHEET_PITCH; ++x)
{
const r8::gfx::color_byte_t* data = machine.memory().as<r8::gfx::color_byte_t>(r8::address::SPRITE_SHEET + y * r8::gfx::SPRITE_SHEET_PITCH + x);
const r8::gfx::color_byte_t* data = machine->memory().as<r8::gfx::color_byte_t>(r8::address::SPRITE_SHEET + y * r8::gfx::SPRITE_SHEET_PITCH + x);
RASTERIZE_PIXEL_PAIR(machine, dest, data);
}
......@@ -296,7 +294,7 @@ void GameView::render()
for (r8::palette_index_t j = 0; j < 2; ++j)
{
const r8::gfx::palette_t* palette = machine.memory().paletteAt(j);
const r8::gfx::palette_t* palette = machine->memory().paletteAt(j);
for (size_t i = 0; i < r8::gfx::COLOR_COUNT; ++i)
dest[j*16 + i] = colorTable.get(palette->get(r8::color_t(i)));
......@@ -323,13 +321,13 @@ void GameView::render()
{
for (r8::coord_t tx = 0; tx < r8::gfx::TILE_MAP_WIDTH; ++tx)
{
r8::sprite_index_t index = *machine.memory().spriteInTileMap(tx, ty);
r8::sprite_index_t index = *machine->memory().spriteInTileMap(tx, ty);
for (r8::coord_t y = 0; y < r8::gfx::SPRITE_HEIGHT; ++y)
for (r8::coord_t x = 0; x < r8::gfx::SPRITE_WIDTH; ++x)
{
auto* dest = base + x + tx * r8::gfx::SPRITE_WIDTH + (y + ty * r8::gfx::SPRITE_HEIGHT) * tilemap->h;
const r8::gfx::color_byte_t& pixels = machine.memory().spriteAt(index)->byteAt(x, y);
const r8::gfx::color_byte_t& pixels = machine->memory().spriteAt(index)->byteAt(x, y);
RASTERIZE_PIXEL_PAIR(machine, dest, &pixels);
}
}
......@@ -384,9 +382,9 @@ void GameView::handleKeyboardEvent(const SDL_Event& event)
{
if (event.type == SDL_KEYDOWN)
{
bool s = machine.sound().isMusicEnabled();
machine.sound().toggleMusic(!s);
machine.sound().toggleSound(!s);
bool s = machine->sound().isMusicEnabled();
machine->sound().toggleMusic(!s);
machine->sound().toggleSound(!s);
}
break;
}
......
#include "main_view.h"
extern retro8::Machine machine;
using namespace ui;
struct MenuEntry
......@@ -65,15 +63,15 @@ MenuView::MenuView(ViewManager* gvm) : _gvm(gvm), _cartridge(nullptr)
};
optionsMenu[SOUND].lambda = [this]() {
bool v = !machine.sound().isSoundEnabled();
machine.sound().toggleSound(v);
bool v = !machine->sound().isSoundEnabled();
machine->sound().toggleSound(v);
updateLabels();
};
optionsMenu[MUSIC].lambda = [this]() {
bool v = !machine.sound().isMusicEnabled();
machine.sound().toggleMusic(v);
bool v = !machine->sound().isMusicEnabled();
machine->sound().toggleMusic(v);
updateLabels();
};
......@@ -123,8 +121,8 @@ void MenuView::handleMouseEvent(const SDL_Event& event)
void MenuView::updateLabels()
{
optionsMenu[MUSIC].caption = std::string("music ") + (machine.sound().isMusicEnabled() ? "on" : "off");
optionsMenu[SOUND].caption = std::string("sound ") + (machine.sound().isSoundEnabled() ? "on" : "off");
optionsMenu[MUSIC].caption = std::string("music ") + (machine->sound().isMusicEnabled() ? "on" : "off");
optionsMenu[SOUND].caption = std::string("sound ") + (machine->sound().isSoundEnabled() ? "on" : "off");
optionsMenu[SHOW_FPS].caption = std::string("show fps ") + (_gvm->gameView()->isFPSShown() ? "on" : "off");
auto scaler = _gvm->gameView()->scaler();
......@@ -168,7 +166,7 @@ void MenuView::render()
_gvm->text("retro8", bx, by, { 0, 47, 255 }, TextAlign::CENTER, 4.0f);
_gvm->text("v0.1b", bx + _gvm->textWidth("retro8", 4.0)/2 - _gvm->textWidth("v0.1b", 1.0), by + 24, { 0, 47, 255 }, TextAlign::LEFT, 1.0f);
retro8::point_t menuBase = { bx, by + 70 };
retro8::point_t menuBase(bx, by + 70);
for (auto it = menu->begin(); it != menu->end(); ++it)
{
......
......@@ -11,8 +11,6 @@
using namespace ui;
extern retro8::Machine machine;
ui::ViewManager::ViewManager() : SDL<ui::ViewManager, ui::ViewManager>(*this, *this), _font(),
_gameView(new GameView(this)), _menuView(new MenuView(this))
{
......@@ -46,7 +44,7 @@ bool ui::ViewManager::loadData()
_font.releaseSurface();
}
machine.font().load();
machine->font().load();
return true;
}
......
......@@ -36,7 +36,11 @@ namespace retro8
using color_index_t = uint8_t;
using palette_index_t = size_t;
using address_t = int32_t;
struct point_t { coord_t x, y; };
struct point_t {
coord_t x, y;
point_t(): x(0), y(0) { }
point_t(coord_t x_, coord_t y_): x(x_), y(y_) { }
};
static constexpr coord_t TEXT_LINE_HEIGHT = 6;
}
......
......@@ -104,7 +104,7 @@ namespace retro8
uint8_t value;
public:
color_byte_t() = default;
color_byte_t() : value(0) {}
color_byte_t(color_t low, color_t high) : value(low | (high << 4)) { }
inline color_t low() const { return static_cast<color_t>(value & 0x0F); }
inline color_t high() const { return static_cast<color_t>((value >> 4) & 0x0F); }
......
......@@ -16,8 +16,6 @@
using namespace lua;
using namespace retro8;
extern retro8::Machine machine;
using real_t = float;
int pset(lua_State* L)
......@@ -32,9 +30,9 @@ int pset(lua_State* L)
if (args == 3)
c = lua_tonumber(L, 3);
else
c = machine.memory().penColor()->low();
c = machine->memory().penColor()->low();
machine.pset(x, y, static_cast<color_t>(c));
machine->pset(x, y, static_cast<color_t>(c));
return 0;
}
......@@ -44,7 +42,7 @@ int pget(lua_State* L)
int x = lua_tonumber(L, 1);
int y = lua_tonumber(L, 2);
lua_pushinteger(L, machine.pget(x, y));
lua_pushinteger(L, machine->pget(x, y));
return 1;
}
......@@ -53,7 +51,7 @@ int color(lua_State* L)
{
int c = lua_tonumber(L, 1);
machine.color(static_cast<color_t>(c));
machine->color(static_cast<color_t>(c));
return 0;
}
......@@ -65,9 +63,9 @@ int line(lua_State* L)
int x1 = lua_tonumber(L, 3);
int y1 = lua_tonumber(L, 4);
int c = lua_gettop(L) == 5 ? lua_tonumber(L, 5) : machine.memory().penColor()->low();
int c = lua_gettop(L) == 5 ? lua_tonumber(L, 5) : machine->memory().penColor()->low();
machine.line(x0, y0, x1, y1, static_cast<color_t>(c));
machine->line(x0, y0, x1, y1, static_cast<color_t>(c));
return 0;
}
......@@ -85,9 +83,9 @@ int rect(lua_State* L)
int x1 = lua_tonumber(L, 3);
int y1 = lua_tonumber(L, 4);
int c = lua_gettop(L) == 5 ? lua_tonumber(L, 5) : machine.memory().penColor()->low();
int c = lua_gettop(L) == 5 ? lua_tonumber(L, 5) : machine->memory().penColor()->low();
machine.rect(x0, y0, x1, y1, static_cast<color_t>(c));
machine->rect(x0, y0, x1, y1, static_cast<color_t>(c));
return 0;
}
......@@ -100,9 +98,9 @@ int rectfill(lua_State* L)
int x1 = lua_tonumber(L, 3);
int y1 = lua_tonumber(L, 4);
int c = lua_gettop(L) >= 5 ? lua_tonumber(L, 5) : machine.memory().penColor()->low();
int c = lua_gettop(L) >= 5 ? lua_tonumber(L, 5) : machine->memory().penColor()->low();
machine.rectfill(x0, y0, x1, y1, static_cast<color_t>(c));
machine->rectfill(x0, y0, x1, y1, static_cast<color_t>(c));
return 0;
}
......@@ -112,9 +110,9 @@ int circ(lua_State* L)
int x = lua_tonumber(L, 1);
int y = lua_tonumber(L, 2);
int r = lua_gettop(L) >= 3 ? lua_tonumber(L, 3) : 4;
int c = lua_gettop(L) >= 4 ? lua_tonumber(L, 4) : machine.memory().penColor()->low();
int c = lua_gettop(L) >= 4 ? lua_tonumber(L, 4) : machine->memory().penColor()->low();
machine.circ(x, y, r, static_cast<color_t>(c));
machine->circ(x, y, r, static_cast<color_t>(c));
return 0;
}
......@@ -124,9 +122,9 @@ int circfill(lua_State* L)
int x = lua_tonumber(L, 1);
int y = lua_tonumber(L, 2);
int r = lua_gettop(L) >= 3 ? lua_tonumber(L, 3) : 4;
int c = lua_gettop(L) >= 4 ? lua_tonumber(L, 4) : machine.memory().penColor()->low();
int c = lua_gettop(L) >= 4 ? lua_tonumber(L, 4) : machine->memory().penColor()->low();
machine.circfill(x, y, r, color_t(c));
machine->circfill(x, y, r, color_t(c));
return 0;
}
......@@ -135,7 +133,7 @@ int cls(lua_State* L)
{
int c = lua_gettop(L) == 1 ? lua_tonumber(L, -1) : 0;
machine.cls(color_t(c));
machine->cls(color_t(c));
return 0;
}
......@@ -162,11 +160,11 @@ int spr(lua_State* L)
if (lua_gettop(L) >= 7)
fy = lua_toboolean(L, 7);
machine.spr(idx, x, y, w, h, fx, fy);
machine->spr(idx, x, y, w, h, fx, fy);
}
else
/* optimized path */
machine.spr(idx, x, y);
machine->spr(idx, x, y);
return 0;
}
......@@ -176,7 +174,7 @@ int sget(lua_State* L)
int x = lua_tonumber(L, 1);
int y = lua_tonumber(L, 2);
lua_pushnumber(L, machine.memory().spriteSheet(x, y)->get(x));
lua_pushnumber(L, machine->memory().spriteSheet(x, y)->get(x));
return 1;
}
......@@ -185,9 +183,9 @@ int sset(lua_State* L)
{
int x = lua_tonumber(L, 1);
int y = lua_tonumber(L, 2);
color_t c = lua_gettop(L) >= 3 ? color_t((int)lua_tonumber(L, 3)) : machine.memory().penColor()->low();
color_t c = lua_gettop(L) >= 3 ? color_t((int)lua_tonumber(L, 3)) : machine->memory().penColor()->low();
machine.memory().spriteSheet(x, y)->set(x, c);
machine->memory().spriteSheet(x, y)->set(x, c);
return 0;
}
......@@ -198,8 +196,8 @@ int pal(lua_State* L)
/* no arguments, reset palette */
if (lua_gettop(L) == 0)
{
machine.memory().paletteAt(gfx::DRAW_PALETTE_INDEX)->reset();
machine.memory().paletteAt(gfx::SCREEN_PALETTE_INDEX)->reset();
machine->memory().paletteAt(gfx::DRAW_PALETTE_INDEX)->reset();
machine->memory().paletteAt(gfx::SCREEN_PALETTE_INDEX)->reset();
}
else
{
......@@ -210,7 +208,7 @@ int pal(lua_State* L)
if (lua_gettop(L) == 3)
index = lua_tonumber(L, 3);
machine.pal(static_cast<color_t>(c0), static_cast<color_t>(c1), index);
machine->pal(static_cast<color_t>(c0), static_cast<color_t>(c1), index);
}
return 0;
}
......@@ -220,8 +218,8 @@ int palt(lua_State* L)
/* no arguments, reset palette */
if (lua_gettop(L) == 0)
{
machine.memory().paletteAt(gfx::DRAW_PALETTE_INDEX)->resetTransparency();
machine.memory().paletteAt(gfx::SCREEN_PALETTE_INDEX)->resetTransparency();
machine->memory().paletteAt(gfx::DRAW_PALETTE_INDEX)->resetTransparency();
machine->memory().paletteAt(gfx::SCREEN_PALETTE_INDEX)->resetTransparency();
}
else
{
......@@ -229,7 +227,7 @@ int palt(lua_State* L)
int f = lua_toboolean(L, 2);
palette_index_t index = gfx::DRAW_PALETTE_INDEX;
machine.memory().paletteAt(gfx::DRAW_PALETTE_INDEX)->transparent(c, f);
machine->memory().paletteAt(gfx::DRAW_PALETTE_INDEX)->transparent(c, f);
}
return 0;
}
......@@ -239,7 +237,7 @@ namespace draw
int clip(lua_State* L)
{
if (lua_gettop(L) == 0)
machine.memory().clipRect()->reset();
machine->memory().clipRect()->reset();
else
{
uint8_t x0 = lua_tonumber(L, 1);
......@@ -247,7 +245,7 @@ namespace draw
uint8_t w = lua_tonumber(L, 3);
uint8_t h = lua_tonumber(L, 4);
machine.memory().clipRect()->set(x0, y0, std::min<int32_t>(x0 + w, gfx::SCREEN_WIDTH-1), std::min<int32_t>(y0 + h, gfx::SCREEN_HEIGHT-1));
machine->memory().clipRect()->set(x0, y0, std::min<int32_t>(x0 + w, gfx::SCREEN_WIDTH-1), std::min<int32_t>(y0 + h, gfx::SCREEN_HEIGHT-1));
}
return 0;
......@@ -260,7 +258,7 @@ int camera(lua_State* L)
{
int16_t cx = lua_gettop(L) >= 1 ? lua_tonumber(L, 1) : 0;
int16_t cy = lua_gettop(L) == 2 ? lua_tonumber(L, 2) : 0;
machine.memory().camera()->set(cx, cy);
machine->memory().camera()->set(cx, cy);
return 0;
}
......@@ -278,7 +276,7 @@ int map(lua_State* L)
if (lua_gettop(L) == 7)
layer = lua_tonumber(L, 7);
machine.map(cx, cy, x, y, cw, ch, layer);
machine->map(cx, cy, x, y, cw, ch, layer);
return 0;
}
......@@ -291,7 +289,7 @@ int mget(lua_State* L)
sprite_index_t index = 0;
if (x >= 0 && x <= gfx::TILE_MAP_WIDTH && y >= 0 && y < gfx::TILE_MAP_HEIGHT)
index = *machine.memory().spriteInTileMap(x, y);
index = *machine->memory().spriteInTileMap(x, y);
//printf("mget(%d, %d) = %d\n", x, y, index);
......@@ -306,7 +304,7 @@ int mset(lua_State* L)
int y = lua_tonumber(L, 2);
retro8::sprite_index_t index = lua_tonumber(L, 3);
*machine.memory().spriteInTileMap(x, y) = index;
*machine->memory().spriteInTileMap(x, y) = index;
return 0;
}
......@@ -318,21 +316,21 @@ int print(lua_State* L)
if (lua_gettop(L) == 1)
{
auto* cursor = machine.memory().cursor();
auto* cursor = machine->memory().cursor();
retro8::coord_t x = cursor->x();
retro8::coord_t y = cursor->y();
retro8::color_t c = machine.memory().penColor()->low();
machine.print(text, x, y, c);
retro8::color_t c = machine->memory().penColor()->low();
machine->print(text, x, y, c);
cursor->set(cursor->x(), cursor->y() + TEXT_LINE_HEIGHT); //TODO: check height
}
else if (lua_gettop(L) >= 3)
{
int x = lua_tonumber(L, 2);
int y = lua_tonumber(L, 3);
int c = lua_gettop(L) == 4 ? lua_tonumber(L, 4) : machine.memory().penColor()->low();
int c = lua_gettop(L) == 4 ? lua_tonumber(L, 4) : machine->memory().penColor()->low();
machine.print(text, x, y, static_cast<retro8::color_t>(c));
machine->print(text, x, y, static_cast<retro8::color_t>(c));
}
else
assert(false);
......@@ -347,16 +345,16 @@ int cursor(lua_State* L)
{
int x = lua_tonumber(L, 1);
int y = lua_tonumber(L, 2);