diff --git a/desktop/Makefile.ems b/desktop/Makefile.ems index 73bd131..6471ca7 100644 --- a/desktop/Makefile.ems +++ b/desktop/Makefile.ems @@ -16,7 +16,16 @@ CXXFLAGS = \ -I../firmware/src \ -D__DESKTOP__ \ -s USE_SDL=2 \ - -sSTACK_SIZE=200000 + -sSTACK_SIZE=200000 \ + --shell-file src/shell.html \ + -s "EXPORTED_RUNTIME_METHODS=['ccall','cwrap']" \ + -s EXPORTED_FUNCTIONS="['_main']" \ + -s DISABLE_EXCEPTION_CATCHING=0 \ + -s ALLOW_MEMORY_GROWTH=1 \ + -s NO_EXIT_RUNTIME=1 \ + -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'cwrap']" \ + -s WASM=1 \ + -lembind # Linker flags (including Cocoa framework for macOS file picker support) LDFLAGS = -L/usr/local/lib @@ -49,7 +58,7 @@ all: $(TARGET) # Create executable from object files $(TARGET): $(OBJS) Makefile - $(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS) `sdl2-config --libs` $(LDFLAGS) --embed-file filesystem + $(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS) `sdl2-config --libs` $(LDFLAGS) --embed-file filesystem -lembind # Object file rules (object files are placed next to the source files) %.o: %.cpp Makefile diff --git a/desktop/src/loadgame.cpp b/desktop/src/loadgame.cpp index da122f1..5710d4b 100644 --- a/desktop/src/loadgame.cpp +++ b/desktop/src/loadgame.cpp @@ -24,10 +24,10 @@ void loadGame(const std::string& filename, ZXSpectrum* machine) { } std::vector buffer(std::istreambuf_iterator(file), {}); - loadGame(buffer.data(), buffer.size(), filename, machine); + loadTapeGame(buffer.data(), buffer.size(), filename, machine); } -void loadGame(uint8_t* tzx_data, size_t file_size, const std::string& filename, ZXSpectrum* machine) { +void loadTapeGame(uint8_t* tzx_data, size_t file_size, const std::string& filename, ZXSpectrum* machine) { // time how long it takes to load the tape int start = SDL_GetTicks(); // load the tape diff --git a/desktop/src/loadgame.h b/desktop/src/loadgame.h index c3821b2..4cd44f5 100644 --- a/desktop/src/loadgame.h +++ b/desktop/src/loadgame.h @@ -5,4 +5,4 @@ #include "spectrum.h" void loadGame(const std::string& filename, ZXSpectrum* machine); -void loadGame(uint8_t* data, size_t length, const std::string& filename, ZXSpectrum* machine); \ No newline at end of file +void loadTapeGame(uint8_t* data, size_t length, const std::string& filename, ZXSpectrum* machine); \ No newline at end of file diff --git a/desktop/src/main.mm b/desktop/src/main.mm index a790436..19f5695 100644 --- a/desktop/src/main.mm +++ b/desktop/src/main.mm @@ -1,6 +1,8 @@ #include #ifdef __EMSCRIPTEN__ #include +#include +#include #endif #ifndef __EMSCRIPTEN__ #import @@ -263,6 +265,84 @@ void main_loop() #endif } +#ifdef __EMSCRIPTEN__ +void loadDroppedFile(std::string filename, const emscripten::val& arrayBuffer) { + machine->reset(); + machine->init_spectrum(SPECMDL_48K); + machine->reset_spectrum(machine->z80Regs); + for(int i = 0; i < 200; i++) { + machine->runForFrame(nullptr, nullptr); + } + // we need to do load "" + machine->updateKey(SPECKEY_J, 1); + for(int i = 0; i < 10; i++) { + machine->runForFrame(nullptr, nullptr); + } + machine->updateKey(SPECKEY_J, 0); + for(int i = 0; i < 10; i++) { + machine->runForFrame(nullptr, nullptr); + } + machine->updateKey(SPECKEY_SYMB, 1); + for(int i = 0; i < 10; i++) { + machine->runForFrame(nullptr, nullptr); + } + machine->updateKey(SPECKEY_P, 1); + for(int i = 0; i < 10; i++) { + machine->runForFrame(nullptr, nullptr); + } + machine->updateKey(SPECKEY_P, 0); + for(int i = 0; i < 10; i++) { + machine->runForFrame(nullptr, nullptr); + } + machine->updateKey(SPECKEY_P, 1); + for(int i = 0; i < 10; i++) { + machine->runForFrame(nullptr, nullptr); + } + machine->updateKey(SPECKEY_P, 0); + for(int i = 0; i < 10; i++) { + machine->runForFrame(nullptr, nullptr); + } + machine->updateKey(SPECKEY_SYMB, 0); + // press enter + machine->updateKey(SPECKEY_ENTER, 1); + for(int i = 0; i < 10; i++) { + machine->runForFrame(nullptr, nullptr); + } + machine->updateKey(SPECKEY_ENTER, 0); + for(int i = 0; i < 10; i++) { + machine->runForFrame(nullptr, nullptr); + } + + + // press the enter key to trigger tape loading + // machine->updateKey(SPECKEY_ENTER, 1); + // for(int i = 0; i < 10; i++) { + // machine->runForFrame(nullptr, nullptr); + // } + // machine->updateKey(SPECKEY_ENTER, 0); + // for(int i = 0; i < 10; i++) { + // machine->runForFrame(nullptr, nullptr); + // } + + size_t length = arrayBuffer["byteLength"].as(); + uint8_t* data = (uint8_t*)malloc(length); + + // Copy data from JS ArrayBuffer to C++ memory + emscripten::val memoryView = emscripten::val::global("Uint8Array").new_(arrayBuffer); + for (size_t i = 0; i < length; i++) { + data[i] = memoryView[i].as(); + } + isLoading = true; + loadGame(data, length, filename, machine); + isLoading = false; + free(data); +} + +EMSCRIPTEN_BINDINGS(module) { + emscripten::function("loadDroppedFile", &loadDroppedFile); +} +#endif + // Main function int main() { diff --git a/desktop/src/shell.html b/desktop/src/shell.html new file mode 100644 index 0000000..e341e97 --- /dev/null +++ b/desktop/src/shell.html @@ -0,0 +1,84 @@ + + + + + + ZX Spectrum Emulator + + + + +
Drop TAP, TZX, or Z80 file here
+ + {{{ SCRIPT }}} + + \ No newline at end of file diff --git a/firmware/data/JetSet.tzx b/firmware/data/JetSet.tzx new file mode 100644 index 0000000..1210bdf Binary files /dev/null and b/firmware/data/JetSet.tzx differ