Skip to content

Commit

Permalink
Support for drag and drop in emscripten
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Greening committed Dec 10, 2024
1 parent e0d1e41 commit 52f4b37
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 5 deletions.
13 changes: 11 additions & 2 deletions desktop/Makefile.ems
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions desktop/src/loadgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ void loadGame(const std::string& filename, ZXSpectrum* machine) {
}

std::vector<uint8_t> buffer(std::istreambuf_iterator<char>(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
Expand Down
2 changes: 1 addition & 1 deletion desktop/src/loadgame.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
void loadTapeGame(uint8_t* data, size_t length, const std::string& filename, ZXSpectrum* machine);
80 changes: 80 additions & 0 deletions desktop/src/main.mm
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include <SDL.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <emscripten/bind.h>
#include <emscripten/val.h>
#endif
#ifndef __EMSCRIPTEN__
#import <Cocoa/Cocoa.h>
Expand Down Expand Up @@ -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<size_t>();
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<uint8_t>();
}
isLoading = true;
loadGame(data, length, filename, machine);
isLoading = false;
free(data);
}

EMSCRIPTEN_BINDINGS(module) {
emscripten::function("loadDroppedFile", &loadDroppedFile);
}
#endif

// Main function
int main()
{
Expand Down
84 changes: 84 additions & 0 deletions desktop/src/shell.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>ZX Spectrum Emulator</title>
<style>
body {
margin: 0;
background-color: black;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.emscripten {
padding-right: 0;
margin-left: auto;
margin-right: auto;
display: block;
}
#canvas {
border: 0px none;
background-color: black;
}
#drop-zone {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: none;
background: rgba(0,0,0,0.7);
align-items: center;
justify-content: center;
color: white;
font-family: Arial, sans-serif;
font-size: 24px;
}
.active {
display: flex !important;
}
</style>
</head>
<body>
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>
<div id="drop-zone">Drop TAP, TZX, or Z80 file here</div>
<script>
var Module = {
canvas: (function() {
var canvas = document.getElementById('canvas');
return canvas;
})()
};

// Drag and drop handling
const dropZone = document.getElementById('drop-zone');

document.body.addEventListener('dragenter', (e) => {
e.preventDefault();
dropZone.classList.add('active');
});

dropZone.addEventListener('dragleave', (e) => {
e.preventDefault();
dropZone.classList.remove('active');
});

dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
});

dropZone.addEventListener('drop', async (e) => {
e.preventDefault();
dropZone.classList.remove('active');

const file = e.dataTransfer.files[0];
const arrayBuffer = await file.arrayBuffer();
Module.loadDroppedFile(file.name, arrayBuffer);
});
</script>
{{{ SCRIPT }}}
</body>
</html>
Binary file added firmware/data/JetSet.tzx
Binary file not shown.

0 comments on commit 52f4b37

Please sign in to comment.