Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_compile_definitions("$<$<CONFIG:DEBUG>:_DEBUG>")
add_compile_options(-Werror=return-type -Wno-switch)

if (EMSCRIPTEN)
add_compile_options(
-fexceptions
-Oz
)

add_link_options(
-fexceptions
-sALLOW_MEMORY_GROWTH=1
-Oz
)
endif()

if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
add_compile_options(-Werror=format -Wno-error=format-overflow -Wno-error=format-truncation -Wno-psabi)
endif()
Expand Down
10 changes: 6 additions & 4 deletions minizip/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ target_include_directories(minizip INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/..
)

# use 32‑bit file API to fix Android compilation issue
target_compile_definitions(minizip PUBLIC
-DUSE_FILE32API
)
if (NOT EMSCRIPTEN)
# use 32‑bit file API to fix Android compilation issue
target_compile_definitions(minizip PUBLIC
-DUSE_FILE32API
)
endif()

target_link_libraries(minizip PUBLIC
zlib2
Expand Down
2 changes: 1 addition & 1 deletion source/AY8910.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ void AY8913::sound_ay_write( int reg, int val, libspectrum_dword now )
}
else
{
LogOutput("AY reg write discarded: %02X = %02X\n", reg, val);
// LogOutput("AY reg write discarded: %02X = %02X\n", reg, val);
}
}

Expand Down
2 changes: 1 addition & 1 deletion source/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
include(FindPkgConfig)

if (NOT WIN32)
if (NOT WIN32 AND NOT EMSCRIPTEN)
pkg_search_module(SLIRP slirp)

# if slirp is not found, we will try pcap
Expand Down
7 changes: 7 additions & 0 deletions source/Video.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,17 @@ enum AppleFont_e
// TODO: Replace with WinGDI.h / RGBQUAD
struct bgra_t
{
#ifdef __EMSCRIPTEN__
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a; // reserved on Win32
#else
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a; // reserved on Win32
#endif
};

struct WinBmpHeader_t
Expand Down
1 change: 0 additions & 1 deletion source/frontends/common2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ set(SOURCE_FILES
timer.cpp
speed.cpp
yamlmap.cpp
yamlselftest.cpp
)

set(HEADER_FILES
Expand Down
4 changes: 4 additions & 0 deletions source/frontends/common2/gnuframe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,11 @@ namespace common2
: CommonFrame(options)
{
// should this go down to LinuxFrame (maybe Initialisation?)
#ifndef __EMSCRIPTEN__
g_sProgramDir = getResourceFolder("bin").string() + PATH_SEPARATOR;
#else
g_sProgramDir = "/home/web_user/disks/";
#endif
LogFileOutput("Program Dir: '%s'\n", g_sProgramDir.c_str());
}

Expand Down
32 changes: 27 additions & 5 deletions source/frontends/common2/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,29 @@
#include "SaveState.h"
#include "Registry.h"

#include <iostream>

namespace
{

std::string getEnvOrDefault(const char *var, const char *fallback = nullptr)
std::optional<std::string> tryGetEnv(const char *var)
{
const char *value = getenv(var);
if (value)
{
return value;
std::cout << "Environment variable " << var << " = " << value << std::endl;
return std::string(value);
}
std::cout << "Environment variable " << var << " missing" << std::endl;
return std::nullopt;
}

std::string getEnvOrDefault(const char *var, const char *fallback = nullptr)
{
std::optional<std::string> value = tryGetEnv(var);
if (value.has_value())
{
return *value;
}
if (fallback)
{
Expand All @@ -34,10 +48,18 @@ namespace common2
return profile;
#else
// https://specifications.freedesktop.org/basedir-spec/latest/
const std::filesystem::path home = getHomeDir();
const std::filesystem::path config = getEnvOrDefault("XDG_CONFIG_HOME", ".config");
#ifdef __EMSCRIPTEN__
const std::optional<std::string> xdgConfigHome = "/defaults/.config";
#else
const std::optional<std::string> xdgConfigHome = tryGetEnv("XDG_CONFIG_HOME");
#endif
if (xdgConfigHome.has_value())
{
return *xdgConfigHome;
}

return home / config;
const std::filesystem::path home = getHomeDir();
return home / ".config";
#endif
}

Expand Down
44 changes: 38 additions & 6 deletions source/frontends/sdl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ option(SA2_SDL3 "Use SDL3" OFF)

if (SA2_SDL3)
message("sa2: using SDL3")
find_package(SDL3 REQUIRED)
find_package(SDL3_image REQUIRED)

target_link_libraries(sa2 PRIVATE
SDL3::SDL3
SDL3_image::SDL3_image
)
if (NOT EMSCRIPTEN)
find_package(SDL3 REQUIRED)
find_package(SDL3_image REQUIRED)

target_link_libraries(sa2 PRIVATE
SDL3::SDL3
SDL3_image::SDL3_image
)
endif()

target_sources(sa2 PRIVATE
${IMGUI_PATH}/backends/imgui_impl_sdl3.cpp
Expand All @@ -25,6 +28,11 @@ if (SA2_SDL3)
target_compile_definitions(sa2 PRIVATE SDL_ENABLE_OLD_NAMES)
else()
message("sa2: using SDL2")

if (EMSCRIPTEN)
message(FATAL_ERROR "Emscripten only supports SDL3")
endif()

find_package(SDL2 REQUIRED)
# we should use find_package, but Ubuntu does not provide it for SDL2_image
pkg_search_module(SDL2_IMAGE REQUIRED SDL2_image)
Expand Down Expand Up @@ -67,6 +75,7 @@ endif()


set(SOURCE_FILES
em_js.cpp
main.cpp
gamepad.cpp
sdirectsound.cpp
Expand Down Expand Up @@ -154,6 +163,29 @@ target_compile_definitions(sa2 PRIVATE
IMGUI_USER_CONFIG="frontends/sdl/imgui/sa2_imconfig.h"
)

if (EMSCRIPTEN)
set_target_properties(sa2 PROPERTIES
SUFFIX ".html"
)

target_compile_options(sa2 PRIVATE
--use-port=sdl3
)

set(EMSC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/emsc)

target_link_options(sa2 PRIVATE
--use-port=sdl3
-sFULL_ES3=1
-sMIN_WEBGL_VERSION=2
"SHELL:-lidbfs.js"
"SHELL:--pre-js ${EMSC_DIR}/src/fs.js"
"SHELL:--pre-js ${EMSC_DIR}/src/dragdrop.js"
"SHELL:--shell-file ${EMSC_DIR}/src/a2e.html"
"SHELL:--preload-file ${EMSC_DIR}/fs@/"
)
endif()

configure_file(sa2_config.h.in sa2_config.h)

install(TARGETS sa2
Expand Down
32 changes: 32 additions & 0 deletions source/frontends/sdl/em_js.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifdef __EMSCRIPTEN__

#include "frontends/sdl/sdlcompat.h"
#include <emscripten.h>

namespace
{
void push_simple_event(SDL_EventType type)
{
SDL_Event e;
SDL_zero(e);
e.type = type;
SDL_PushEvent(&e);
}

} // namespace

extern "C" EMSCRIPTEN_KEEPALIVE void sdl_dropfile(const char *filename)
{
push_simple_event(SDL_DROPBEGIN);

SDL_Event e;
SDL_zero(e);
e.type = SDL_DROPFILE;
e.drop.data = SDL_strdup(filename); // SDL3 will free this memory
printf("[DND] pushing SDL_DROPFILE event for '%s'\n", filename);
SDL_PushEvent(&e);

push_simple_event(SDL_DROPCOMPLETE);
}

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
Configuration:
Emulation Speed: 10
Configuration\Slot 0:
Card type: 17
Configuration\Slot 1:
Card type: 0
Configuration\Slot 2:
Card type: 0
Configuration\Slot 3:
Card type: 0
Uthernet Interface:
Configuration\Slot 6:
Card type: 1
Last Disk Image 1: /disks/DOS 3.3 System Master - 680-0210-A.dsk
Last Disk Image 2: /disks/ProDOS_2_4_3.po
Configuration\Slot Auxiliary:
Card type: 13
Number of Banks: 1
Preferences:
Starting Directory: /disks/
24 changes: 24 additions & 0 deletions source/frontends/sdl/emsc/fs/defaults/.config/applewin/imgui.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[Window][Debug##Default]
Pos=60,60
Size=400,400

[Window][Shortcuts]
Pos=60,60
Size=1148,656

[Window][Settings]
Pos=60,60
Size=1199,504

[Window][Memory viewer]
Pos=60,60
Size=772,492

[Window][Memory editor]
Pos=60,60
Size=924,672

[Window][Debugger]
Pos=60,60
Size=1077,799

1 change: 1 addition & 0 deletions source/frontends/sdl/emsc/fs/disks/A2_BASIC.SYM
1 change: 1 addition & 0 deletions source/frontends/sdl/emsc/fs/disks/APPLE2E.SYM
1 change: 1 addition & 0 deletions source/frontends/sdl/emsc/fs/disks/BLANK.DSK
Binary file not shown.
54 changes: 54 additions & 0 deletions source/frontends/sdl/emsc/src/a2e.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<!doctype html>
<html lang="en">

<head>
<meta charset="utf-8">
<title>AppleWin Emscripten</title>
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0">
<style>
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
background: black;
}

canvas {
display: block;
width: 100%;
height: 100%;
background: black;
}
</style>
</head>

<body>
<canvas id="canvas" oncontextmenu="event.preventDefault()"></canvas>

<script>
// Module setup before Emscripten runtime
var Module = {
canvas: document.getElementById('canvas'),
ENV: { XDG_CONFIG_HOME: '/persist/.config' },

onRuntimeInitialized: function () {
console.log('[Module] Runtime ready');

// Init persistent filesystem
Module.js_init_fs();

// Init drag & drop (pure JS)
Module.init_dragdrop();
}
};
</script>

<!-- Emscripten-generated JS goes here -->
{{{ SCRIPT }}}

</body>

</html>
Loading