Skip to content

Commit

Permalink
Implement ability to import/export hi-score data #37 (#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
irdcat authored Jan 16, 2024
1 parent aed163f commit 7d9f0e5
Show file tree
Hide file tree
Showing 21 changed files with 157 additions and 35 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ if(EMSCRIPTEN)
set(CMAKE_EXECUTABLE_SUFFIX ".js")
set(CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -sWASM=1 -sUSE_SDL_MIXER=2 -sUSE_SDL=2 -sASYNCIFY -sALLOW_MEMORY_GROWTH=1 -O3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -sEXPORTED_FUNCTIONS=_run -sEXPORTED_RUNTIME_METHODS=ccall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -sEXPORTED_FUNCTIONS=_run,_reset,_exportHiScoreData -sEXPORTED_RUNTIME_METHODS=ccall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --preload-file ${ROMS_DIR} --use-preload-plugins")
add_executable(wasm-invaders ${APP_SOURCES})
endif()
Expand Down
2 changes: 2 additions & 0 deletions src/Apu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ class Apu
public:
virtual ~Apu() = default;

virtual void reset() = 0;

virtual void write(unsigned bank, u8 value) = 0;
};
5 changes: 5 additions & 0 deletions src/ApuImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

ApuImpl::ApuImpl(AudioPlayCallback audioPlayCallback)
: audioPlayCallback(audioPlayCallback)
{
reset();
}

void ApuImpl::reset()
{
sound1.raw = 0x00;
sound2.raw = 0x00;
Expand Down
2 changes: 2 additions & 0 deletions src/ApuImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ class ApuImpl : public Apu

explicit ApuImpl(AudioPlayCallback audioPlayCallback);

void reset() override;

~ApuImpl() = default;

void write(unsigned bank, u8 value) override;
Expand Down
2 changes: 2 additions & 0 deletions src/Cpu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ class Cpu
public:
virtual ~Cpu() = default;

virtual void reset() = 0;

virtual u8 fetchOpcode() = 0;

virtual Registers& getRegisters() = 0;
Expand Down
31 changes: 22 additions & 9 deletions src/CpuImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,28 @@
CpuImpl::CpuImpl(const std::shared_ptr<Bus>& busPtr)
: registers()
, bus(busPtr)
, interrupt_enable(false)
, interrupt_delay(false)
, interrupt_pending(false)
, interrupt_source(0x00)
, halted(false)
, cycles(0)
{
auto& rawFlags = registers.getAf().getLow().raw;
rawFlags = 0x2; // Set bit between Carry and Parity to 1
{
reset();
}

void CpuImpl::reset()
{
auto& af = registers.getAf();
auto& bc = registers.getBc();
auto& de = registers.getDe();
auto& hl = registers.getHl();
auto& pc = registers.getPc();
auto& sp = registers.getSp();

af = bc = de = hl = pc = sp = 0;
af.getLow().raw = 0x2; // Set bit between Carry and Parity to 1

cycles = 0;
halted = false;
interrupt_enable = false;
interrupt_delay = false;
interrupt_pending = false;
interrupt_source = 0x00;
}

u8 CpuImpl::fetchOpcode()
Expand Down
2 changes: 2 additions & 0 deletions src/CpuImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class CpuImpl : public Cpu

~CpuImpl() = default;

void reset() override;

u8 fetchOpcode() override;

Registers& getRegisters() override;
Expand Down
30 changes: 26 additions & 4 deletions src/Emulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,17 @@ Emulator::Emulator()
});
bus = std::make_shared<BusImpl>(memory, inputs, apu, shiftRegister);
cpu = std::make_shared<CpuImpl>(bus);

shouldRun = initializeSdlResources() && loadRoms();
}

Emulator::~Emulator()
void Emulator::reset()
{
cpu->reset();
apu->reset();
memory->reset();
inputs->reset();
shiftRegister->reset();

shouldRun = initializeSdlResources(!shouldRun) && loadRoms();
}

void Emulator::run()
Expand All @@ -55,8 +60,25 @@ void Emulator::run()
}
}

bool Emulator::initializeSdlResources()
u16 Emulator::exportHiScoreData()
{
const u16 hiScoreAddress = 0x20F4;
return static_cast<u16>(memory->read(hiScoreAddress)) |
static_cast<u16>(memory->read(hiScoreAddress + 1)) << 8;
}

void Emulator::importHiScoreData(u16 hiScore)
{
const u16 hiScoreAddress = 0x1BF4;
memory->write(hiScoreAddress, hiScore & 0xFF);
memory->write(hiScoreAddress + 1, (hiScore >> 8) & 0xFF);
}

bool Emulator::initializeSdlResources(bool initSdlResources)
{
if(!initSdlResources)
return true;

if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) {
return false;
}
Expand Down
10 changes: 8 additions & 2 deletions src/Emulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,18 @@ class Emulator
public:
Emulator();

~Emulator();
~Emulator() = default;

void reset();

void run();

u16 exportHiScoreData();

void importHiScoreData(u16 hiScore);

private:
bool initializeSdlResources();
bool initializeSdlResources(bool initSdlResources);
bool loadRoms();

void handleInput();
Expand Down
2 changes: 2 additions & 0 deletions src/Inputs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ class Inputs
public:
virtual ~Inputs() = default;

virtual void reset() = 0;

virtual u8 getInput(unsigned index) = 0;

virtual void setCredit(bool deposit) = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/InputsImpl.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "InputsImpl.hpp"

InputsImpl::InputsImpl()
void InputsImpl::reset()
{
input1.raw = 1 << 3;
input2.raw = 0;
Expand Down
4 changes: 3 additions & 1 deletion src/InputsImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
class InputsImpl : public Inputs
{
public:
InputsImpl();
InputsImpl() = default;

~InputsImpl() = default;

void reset() override;

u8 getInput(unsigned index) override;

void setCredit(bool deposit) override;
Expand Down
7 changes: 2 additions & 5 deletions src/Memory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@ constexpr const unsigned ROM_SIZE = 0x2000;
constexpr const unsigned RAM_SIZE = 0x0400;
constexpr const unsigned VRAM_SIZE = 0x1C00;

constexpr const unsigned ROM_START_ADDR = 0x0000;
constexpr const unsigned RAM_START_ADDR = 0x2000;
constexpr const unsigned VRAM_START_ADDR = 0x2400;
constexpr const unsigned RAM_MIRROR_START_ADDR = 0x4000;

using Rom = std::array<u8, ROM_SIZE>;
using Ram = std::array<u8, RAM_SIZE>;
using VRam = std::array<u8, VRAM_SIZE>;
Expand All @@ -21,6 +16,8 @@ class Memory
public:
virtual ~Memory() = default;

virtual void reset() = 0;

virtual u8 read(u16 addr) const = 0;

virtual void write(u16 addr, u8 value) = 0;
Expand Down
10 changes: 10 additions & 0 deletions src/MemoryImpl.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
#include "MemoryImpl.hpp"
#include <algorithm>

void MemoryImpl::reset()
{
auto clear = [](auto& n){ n = 0x00; };

std::for_each(rom.begin(), rom.end(), clear);
std::for_each(ram.begin(), ram.end(), clear);
std::for_each(vram.begin(), vram.end(), clear);
}

u8 MemoryImpl::read(u16 addr) const
{
Expand Down
11 changes: 11 additions & 0 deletions src/MemoryImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
class MemoryImpl : public Memory
{
public:
MemoryImpl() = default;

~MemoryImpl() = default;

void reset() override;

u8 read(u16 addr) const override;

void write(u16 addr, u8 value) override;
Expand All @@ -18,4 +24,9 @@ class MemoryImpl : public Memory
Rom rom;
Ram ram;
VRam vram;

static constexpr const unsigned ROM_START_ADDR = 0x0000;
static constexpr const unsigned RAM_START_ADDR = 0x2000;
static constexpr const unsigned VRAM_START_ADDR = 0x2400;
static constexpr const unsigned RAM_MIRROR_START_ADDR = 0x4000;
};
2 changes: 2 additions & 0 deletions src/ShiftRegister.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ class ShiftRegister
public:
virtual ~ShiftRegister() = default;

virtual void reset() = 0;

virtual u8 readShiftResult() const = 0;

virtual void writeShiftOffset(u8 value) = 0;
Expand Down
8 changes: 4 additions & 4 deletions src/ShiftRegisterImpl.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#include "ShiftRegisterImpl.hpp"

ShiftRegisterImpl::ShiftRegisterImpl()
: shift_low(0x00)
, shift_high(0x00)
, shift_offset(0x00)
void ShiftRegisterImpl::reset()
{
shift_low = 0x00;
shift_high = 0x00;
shift_offset = 0x00;
}

u8 ShiftRegisterImpl::readShiftResult() const
Expand Down
4 changes: 3 additions & 1 deletion src/ShiftRegisterImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
class ShiftRegisterImpl : public ShiftRegister
{
public:
ShiftRegisterImpl();
ShiftRegisterImpl() = default;

~ShiftRegisterImpl() = default;

void reset() override;

u8 readShiftResult() const override;

void writeShiftOffset(u8 value) override;
Expand Down
19 changes: 17 additions & 2 deletions src/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,29 @@

#include "Emulator.hpp"

Emulator emulator;

extern "C"
{
EMSCRIPTEN_KEEPALIVE int run()
EMSCRIPTEN_KEEPALIVE int run(u16 hiScore = 0)
{
Emulator emulator;
emulator.reset();
emulator.importHiScoreData(hiScore);
emulator.run();
Mix_CloseAudio();
SDL_Quit();
return 0;
}

EMSCRIPTEN_KEEPALIVE void reset()
{
u16 hiScore = emulator.exportHiScoreData();
emulator.reset();
emulator.importHiScoreData(hiScore);
}

EMSCRIPTEN_KEEPALIVE u16 exportHiScoreData()
{
return emulator.exportHiScoreData();
}
}
16 changes: 12 additions & 4 deletions src/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,28 @@
<html>
<head>
<meta charset="utf-8"/>
<link href="https://cdn.jsdelivr.net/npm/daisyui@3.2.1/dist/full.css" rel="stylesheet" type="text/css"/>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/npm/daisyui@3.2.1/dist/full.css" rel="stylesheet" type="text/css"/>
</head>
<body class="m-0 p-0 bg-slate-900">
<body class="m-0 p-0 bg-slate-400">
<div class="p-2 m-0 absolute top-2/4 left-2/4 -translate-y-2/4 -translate-x-2/4 box-border bg-slate-300 rounded-xl">
<div id="loading-container">
<span class="loading loading-spinner loading-lg text-accent"></span>
</div>
<div id="run-button-container" style="display: none">
<button onclick="run_emulator()" type="button" class="btn btn-sm btn-accent">Run</button>
<button onclick="run_emulator()" type="button" class="btn btn-sm btn-primary">Run</button>
</div>
<div id="emulator-container" style="display: none">
<div class="flex mb-2 p-2 rounded-2xl bg-slate-900">
<div class="grow">
<button onclick="reset_emulator()" type="button" class="btn btn-sm btn-primary">Reset</button>
</div>
<div class="grow">
<button onclick="export_hiscore()" type="button" class="btn btn-sm btn-primary">Save Hi-Score</button>
</div>
</div>
<canvas oncontextmenu="event.preventDefault()" id="canvas" width="448" height="512" class="bg-gray-950"></canvas>
<div class="collapse collapse-arrow mt-2 p-0 bg-slate-900">
<div class="collapse collapse-arrow mt-2 p-0 bg-slate-900">
<input type="checkbox"/>
<div class="collapse-title text-xl font-medium">
Controls
Expand Down
21 changes: 20 additions & 1 deletion src/web/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@ const EMULATOR_CONTAINER_ID = "emulator-container";

const CANVAS_ID = "canvas";

const HISCORE_KEY = "Wasm-Invaders-HiScore";

var Module = {
onRuntimeInitialized: function() {
let loadingContainer = document.getElementById(LOADING_CONTAINER_ID);
loadingContainer.style.display = 'none';
let runButtonContainer = document.getElementById(RUN_BUTTON_CONTAINER_ID);
runButtonContainer.style.display = 'block';

let daisyUiStylesheet = document.querySelector("link");
document.querySelector("head").appendChild(daisyUiStylesheet);
},
canvas: (function() {
let canvas = document.getElementById(CANVAS_ID);
Expand All @@ -23,5 +28,19 @@ function run_emulator() {
let emulatorContainer = document.getElementById(EMULATOR_CONTAINER_ID);
emulatorContainer.style.display = 'block';

Module.ccall('run', null, null, null, {async: true});
let hiScore = window.localStorage.getItem(HISCORE_KEY);
if(hiScore === null) {
Module.ccall('run', null, null, null, {async: true});
} else {
Module.ccall('run', null, ['number'], [parseInt(hiScore)], {async: true});
}
}

function reset_emulator() {
Module.ccall('reset', null, null, null, {async: true});
}

async function export_hiscore() {
let hiScore = await Module.ccall('exportHiScoreData', 'number', null, null, {async: true});
localStorage.setItem(HISCORE_KEY, hiScore.toString());
}

0 comments on commit 7d9f0e5

Please sign in to comment.