Commit MetaInfo

Revision91b56854e368d087ef743bd9855d03e91e2cbdc9 (tree)
Time2020-01-18 10:20:21
AuthorDavid Ludwig <dludwig@pobo...>
CommiterDavid Ludwig

Log Message

Emscripten port's initial work-in-progress

Change Summary

Incremental Difference

diff -r 24df4a4651f7 -r 91b56854e368 Makefile
--- a/Makefile Sat Mar 03 11:36:07 2018 -0700
+++ b/Makefile Fri Jan 17 20:20:21 2020 -0500
@@ -1,15 +1,19 @@
11 # BUILD SETTINGS ###############################################################
22
3-ifneq ($(filter Msys Cygwin, $(shell uname -o)), )
3+ifeq ($(patsubst %emcc,,$(lastword $(CC))),)
4+ PLATFORM := EMSCRIPTEN
5+ TYRIAN_DIR = /tyrian21
6+ WITH_NETWORK := false
7+else ifneq ($(filter Msys Cygwin, $(shell uname -o)), )
48 PLATFORM := WIN32
59 TYRIAN_DIR = C:\\TYRIAN
10+ WITH_NETWORK := true
611 else
712 PLATFORM := UNIX
813 TYRIAN_DIR = $(gamesdir)/tyrian
14+ WITH_NETWORK := true
915 endif
1016
11-WITH_NETWORK := true
12-
1317 ################################################################################
1418
1519 # see https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html
@@ -40,7 +44,16 @@
4044
4145 ###
4246
43-TARGET := opentyrian
47+ifeq ($(PLATFORM), EMSCRIPTEN)
48+ TARGET := opentyrian.js
49+else
50+ TARGET := opentyrian
51+endif
52+
53+ALL_OUTPUT_BINARIES := $(TARGET)
54+ifeq ($(PLATFORM), EMSCRIPTEN)
55+ ALL_OUTPUT_BINARIES := $(ALL_OUTPUT_BINARIES) opentyrian.wasm opentyrian.wasm.map
56+endif
4457
4558 SRCS := $(wildcard src/*.c)
4659 OBJS := $(SRCS:src/%.c=obj/%.o)
@@ -63,11 +76,20 @@
6376 CFLAGS += -MMD
6477 CFLAGS += -Wall \
6578 -Wextra \
66- -Wno-missing-field-initializers
79+ -Wno-absolute-value \
80+ -Wno-missing-field-initializers \
81+ -Wno-unused-const-variable
6782 CFLAGS += -O2
6883 LDFLAGS :=
6984 LDLIBS :=
7085
86+ifeq ($(PLATFORM), EMSCRIPTEN)
87+ EMSCRIPTEN_CFLAGS := -s ALLOW_MEMORY_GROWTH=1 -s ASYNCIFY
88+ CPPFLAGS += $(EMSCRIPTEN_CFLAGS)
89+ CFLAGS += $(EMSCRIPTEN_CFLAGS)
90+ LDFLAGS += --preload-file tyrian21/
91+endif
92+
7193 SDL_CPPFLAGS := $(shell $(PKG_CONFIG) sdl2 --cflags)
7294 SDL_LDFLAGS := $(shell $(PKG_CONFIG) sdl2 --libs-only-L --libs-only-other)
7395 SDL_LDLIBS := $(shell $(PKG_CONFIG) sdl2 --libs-only-l)
@@ -96,8 +118,10 @@
96118 .PHONY : debug
97119 debug : CPPFLAGS += -UNDEBUG
98120 debug : CFLAGS += -Werror
99-debug : CFLAGS += -O0
100-debug : CFLAGS += -g3
121+# debug : CFLAGS += -O0
122+debug : CFLAGS += $(if $(filter EMSCRIPTEN,$(PLATFORM)),-O1,-O0)
123+debug : CFLAGS += $(if $(filter EMSCRIPTEN,$(PLATFORM)),--source-map-base http://localhost:8080/opentyrian/,)
124+debug : CFLAGS += $(if $(filter EMSCRIPTEN,$(PLATFORM)),-g4,-g3)
101125 debug : all
102126
103127 .PHONY : installdirs
@@ -122,7 +146,7 @@
122146 clean :
123147 rm -f $(OBJS)
124148 rm -f $(DEPS)
125- rm -f $(TARGET)
149+ rm -f $(ALL_OUTPUT_BINARIES)
126150
127151 $(TARGET) : $(OBJS)
128152 $(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -o $@ $^ $(ALL_LDLIBS)
diff -r 24df4a4651f7 -r 91b56854e368 opentyrian.css
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/opentyrian.css Fri Jan 17 20:20:21 2020 -0500
@@ -0,0 +1,179 @@
1+
2+:root {
3+ --canvas-scaling-factor: 1.0;
4+}
5+
6+body {
7+ background-color: black;
8+}
9+
10+.circle {
11+ position: absolute;
12+ width: 100px;
13+ height: 100px;
14+ border-radius: 50%;
15+ background-color: #dddddd;
16+ -webkit-transform: scale(1, 1);
17+ transform: scale(1, 1);
18+}
19+
20+.circle.circle_pulse {
21+ -webkit-animation-timing-function: ease;
22+ animation-timing-function: ease;
23+ -webkit-animation: circle_pulse 2s infinite;
24+ animation: circle_pulse 2s infinite;
25+ background-color: #ffffff;
26+}
27+
28+.circle_svg {
29+ fill: #333333;
30+ stroke: #333333;
31+ stroke-linejoin: round;
32+ stroke-width: 5;
33+ transition: all 0.3s;
34+}
35+
36+.circle_svg:hover {
37+ /* cursor: pointer; */
38+ fill: #000000;
39+ stroke: #000000;
40+ -webkit-transform: scale(1.2, 1.2);
41+ transform: scale(1.2, 1.2);
42+}
43+
44+@-webkit-keyframes circle_pulse {
45+ 0% {
46+ -webkit-transform: scale(1, 1);
47+ transform: scale(1, 1);
48+ }
49+ 25% {
50+ -webkit-transform: scale(1, 1);
51+ transform: scale(1, 1);
52+ }
53+ 50% {
54+ -webkit-transform: scale(1.2, 1.2);
55+ transform: scale(1.2, 1.2);
56+ }
57+ 100% {
58+ -webkit-transform: scale(1, 1);
59+ transform: scale(1, 1);
60+ }
61+}
62+
63+@keyframes circle_pulse {
64+ 0% {
65+ -webkit-transform: scale(1, 1);
66+ transform: scale(1, 1);
67+ }
68+ 25% {
69+ -webkit-transform: scale(1, 1);
70+ transform: scale(1, 1);
71+ }
72+ 50% {
73+ -webkit-transform: scale(1.2, 1.2);
74+ transform: scale(1.2, 1.2);
75+ }
76+ 100% {
77+ -webkit-transform: scale(1, 1);
78+ transform: scale(1, 1);
79+ }
80+}
81+
82+.content_window {
83+ position: absolute;
84+ top: 50%;
85+ left: 50%;
86+ transform: translate(-50%, -50%) scale(var(--canvas-scaling-factor));
87+ width: 320px;
88+ height: 200px;
89+ /* display over the HUD */
90+ z-index: 2;
91+}
92+
93+.coverer {
94+ position: absolute;
95+ top: 0;
96+ left: 0;
97+ right: 0;
98+ bottom: 0;
99+ display: flex;
100+ align-items: center;
101+ justify-content: center;
102+ cursor: pointer;
103+ background-color: darkblue;
104+ border-color: darkgrey;
105+ border-width: 1px;
106+ border-style: solid;
107+}
108+
109+canvas.emscripten {
110+ image-rendering: -moz-crisp-edges;
111+ image-rendering: -webkit-crisp-edges;
112+ image-rendering: pixelated;
113+ image-rendering: crisp-edges;
114+ background-color: black;
115+ /* the canvas *must not* have any border or padding, or mouse coords will be wrong */
116+ border: 0px none;
117+}
118+
119+#hud {
120+ position: absolute;
121+ top: 0;
122+ left: 0;
123+ right: 0;
124+ width: 100%;
125+ /* height: 100px; */
126+ z-index: 1;
127+ /* background-color: green; */
128+ color: white;
129+ padding: 4px;
130+}
131+
132+.hudButton {
133+ /* position: absolute; */
134+ position: relative;
135+ right: 8px;
136+ background-color: #ffffff;
137+ padding: 8px;
138+ border-radius: 8px;
139+ /* right: 0; */
140+ float: right;
141+ /* box-shadow: 4px 4px gray; */
142+}
143+
144+.hudIcon {
145+ display: block;
146+ margin: auto;
147+ width: 24px;
148+ height: 24px;
149+ padding: 8px;
150+}
151+
152+.hudText {
153+ display: block;
154+ color: black;
155+ font-family: Sans-serif;
156+ /* text-transform: uppercase; */
157+}
158+
159+.loader {
160+ border: 16px solid #00000033;
161+ border-top: 16px solid #ffffff;
162+ border-radius: 50%;
163+ width: 100px;
164+ height: 100px;
165+ animation: spin 2s linear infinite;
166+}
167+
168+@keyframes spin {
169+ 0% { transform: rotate(0deg); }
170+ 100% { transform: rotate(360deg); }
171+}
172+
173+#click_to_start {
174+ /* visibility: visible; */
175+}
176+
177+#waiting_to_start {
178+ visibility: hidden;
179+}
diff -r 24df4a4651f7 -r 91b56854e368 opentyrian.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/opentyrian.html Fri Jan 17 20:20:21 2020 -0500
@@ -0,0 +1,150 @@
1+<!DOCTYPE html>
2+<html>
3+
4+<head>
5+ <meta name="viewport" content="width=device-width, initial-scale=1">
6+ <!-- <script type="text/javascript" src="/live.js"></script> -->
7+ <!-- <script type="text/javascript" src="http://livejs.com/live.js"></script> -->
8+ <link rel="stylesheet" type="text/css" href="opentyrian.css">
9+
10+ <!-- HACK: use 'as="fetch" crossorigin', rather than just 'as="script"',
11+ to suppress preload-related warnings in Chrome -->
12+ <link rel="preload" href="opentyrian.js" as="fetch" crossorigin>
13+ <link rel="preload" href="opentyrian.wasm" as="fetch" crossorigin>
14+</head>
15+
16+<body>
17+ <div id="hud">
18+ <div class="hudButton" onclick="toggleFullscreen()">
19+ <svg class="hudIcon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
20+ <path d="M24 9h-2v-7h-7v-2h9v9zm-9 15v-2h7v-7h2v9h-9zm-15-9h2v7h7v2h-9v-9zm9-15v2h-7v7h-2v-9h9z"/>
21+ </svg>
22+ <div class="hudText">Fullscreen</div>
23+ </div>
24+ <!-- <span>Scaling: <span id="hudScalingFactor"></span>X</span> -->
25+ <!-- <button onclick="hideCover()">Hide Cover</button>
26+ <button onclick="startXHR()">Start XHR</button>
27+ <button onclick="execMainCode()">Exec Main Code</button> -->
28+ </div>
29+ <canvas class="content_window emscripten" id="canvas" width="320" height="200" oncontextmenu="event.preventDefault()"></canvas>
30+ <div id="cover" class="content_window" onclick="userStarted()">
31+ <div id="click_to_start" class="coverer">
32+ <div class="circle circle_pulse"></div>
33+ <div class="circle">
34+ <svg class="circle_svg" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
35+ <polygon points="40,30 65,50 40,70"></polygon>
36+ </svg>
37+ </div>
38+ </div>
39+ <div id="waiting_to_start" class="coverer">
40+ <div class="loader"></div>
41+ </div>
42+ </div>
43+ <script type="text/javascript">
44+ Module = {
45+ printErr: function (text) {
46+ if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
47+ console.error(text);
48+ },
49+ canvas: (function () {
50+ var canvas = document.getElementById('canvas');
51+
52+ // As a default initial behavior, pop up an alert when webgl context is lost. To make your
53+ // application robust, you may want to override this behavior before shipping!
54+ // See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
55+ canvas.addEventListener("webglcontextlost", function (e) {
56+ alert('WebGL context lost. You will need to reload the page.');
57+ e.preventDefault();
58+ }, false);
59+
60+ return canvas;
61+ })(),
62+ };
63+
64+ var MainCode = null;
65+ var InteractionStarted = false;
66+
67+ function toggleFullscreen() {
68+ var elem = document.documentElement;
69+ if (!document.fullscreenElement) {
70+ elem.requestFullscreen().catch(err => {
71+ alert(`Error attempting to enable full-screen mode: ${err.message} (${err.name})`);
72+ });
73+ } else {
74+ document.exitFullscreen();
75+ }
76+ }
77+
78+ function startXHR() {
79+ // console.log("XHR CREATION");
80+ var xhr = new XMLHttpRequest();
81+ xhr.open("GET", "opentyrian.js");
82+ xhr.onload = function(e) {
83+ if (xhr.readyState === 4) {
84+ if (xhr.status === 200) {
85+ // setTimeout(function () {
86+ // console.log("XHR SUCCESS");
87+ MainCode = xhr.responseText;
88+ advanceUIState();
89+ // }, 4000); // ONLY USE FOR TESTING!
90+ } else {
91+ console.error("XHR HTTP ERROR:", xhr.statusText);
92+ }
93+ }
94+ };
95+ xhr.onerror = function(e) {
96+ console.error("XHR GENERIC ERROR:", xhr.statusText);
97+ };
98+ xhr.send(null);
99+ }
100+
101+ function advanceUIState() {
102+ if (!InteractionStarted) {
103+ // keep showing '#cover'
104+ } else if (MainCode == null) {
105+ document.getElementById("waiting_to_start").style.setProperty("visibility", "visible");
106+ document.getElementById("click_to_start").style.setProperty("display", "none");
107+ // keep showing '#waiting_to_start'
108+ } else {
109+ // hide the cover
110+ document.getElementById("cover").style.setProperty("display", "none");
111+ execMainCode();
112+ }
113+ }
114+
115+ function userStarted() {
116+ InteractionStarted = true;
117+ advanceUIState();
118+ }
119+
120+ function execMainCode() {
121+ if (MainCode == null) {
122+ console.error("Cannot execute MainCode, which has not been fully-loaded")
123+ return;
124+ }
125+ const execMainCode = new Function('Module', MainCode);
126+ execMainCode(Module);
127+ }
128+
129+ function handleResize() {
130+ var canvas = document.getElementById("canvas");
131+ const scaleMaxX = Math.floor(window.innerWidth / canvas.width);
132+ const scaleMaxY = Math.floor(window.innerHeight / canvas.height);
133+ const scale = Math.max(1, Math.min(scaleMaxX, scaleMaxY));
134+ // console.log("handleResize", scale, "<--", scaleMaxX, scaleMaxY);
135+ document.documentElement.style.setProperty("--canvas-scaling-factor", scale);
136+ var hudScalingFactor = document.getElementById("hudScalingFactor");
137+ if (hudScalingFactor) {
138+ hudScalingFactor.textContent = scale;
139+ }
140+ }
141+
142+ window.addEventListener('load', handleResize);
143+ window.addEventListener('resize', handleResize);
144+ window.addEventListener("load", startXHR);
145+
146+ // drawDebugCanvas();
147+ </script>
148+</body>
149+
150+</html>
\ No newline at end of file
diff -r 24df4a4651f7 -r 91b56854e368 src/config.c
--- a/src/config.c Sat Mar 03 11:36:07 2018 -0700
+++ b/src/config.c Fri Jan 17 20:20:21 2020 -0500
@@ -222,8 +222,14 @@
222222 {
223223 // defaults
224224 fullscreen_display = -1;
225+
226+#if __EMSCRIPTEN__
227+ // The Emscripten port leaves scaling to HTML+CSS.
228+ set_scaler_by_name("None");
229+#else
225230 set_scaler_by_name("Scale2x");
226-
231+#endif
232+
227233 Config *config = &opentyrian_config;
228234
229235 FILE *file = dir_fopen_warn(get_user_directory(), "opentyrian.cfg", "r");
diff -r 24df4a4651f7 -r 91b56854e368 src/destruct.c
--- a/src/destruct.c Sat Mar 03 11:36:07 2018 -0700
+++ b/src/destruct.c Fri Jan 17 20:20:21 2020 -0500
@@ -64,6 +64,7 @@
6464 #include "video.h"
6565
6666 #include <assert.h>
67+#include <SDL.h>
6768
6869 /*** Defines ***/
6970 #define UNIT_HEIGHT 12
diff -r 24df4a4651f7 -r 91b56854e368 src/keyboard.c
--- a/src/keyboard.c Sat Mar 03 11:36:07 2018 -0700
+++ b/src/keyboard.c Fri Jan 17 20:20:21 2020 -0500
@@ -26,6 +26,10 @@
2626 #include <SDL.h>
2727 #include <stdio.h>
2828
29+#if __EMSCRIPTEN__
30+#include <emscripten.h>
31+#endif
32+
2933 JE_boolean ESCPressed;
3034
3135 JE_boolean newkey, newmouse, keydown, mousedown;
@@ -130,6 +134,15 @@
130134 void service_SDL_events( JE_boolean clear_new )
131135 {
132136 SDL_Event ev;
137+
138+#if __EMSCRIPTEN__
139+ // Yield time back to the web-browser, via use of Emscripten's
140+ // Asyncify feature (https://emscripten.org/docs/porting/asyncify.html).
141+ // This allows events to be collected without needing to overhaul
142+ // OpenTyrian to run in a web-browser's callback-based system of
143+ // events and rendering.
144+ emscripten_sleep(0);
145+#endif
133146
134147 if (clear_new)
135148 {
diff -r 24df4a4651f7 -r 91b56854e368 src/opl.c
--- a/src/opl.c Sat Mar 03 11:36:07 2018 -0700
+++ b/src/opl.c Fri Jan 17 20:20:21 2020 -0500
@@ -146,6 +146,30 @@
146146 };
147147
148148
149+// per-chip variables
150+Bitu chip_num;
151+op_type op[MAXOPERATORS];
152+
153+Bits int_samplerate;
154+
155+Bit8u status;
156+Bit32u opl_index;
157+#if defined(OPLTYPE_IS_OPL3)
158+Bit8u adlibreg[512]; // adlib register set (including second set)
159+Bit8u wave_sel[44]; // waveform selection
160+#else
161+Bit8u adlibreg[256]; // adlib register set
162+Bit8u wave_sel[22]; // waveform selection
163+#endif
164+
165+
166+// vibrato/tremolo increment/counter
167+Bit32u vibtab_pos;
168+Bit32u vibtab_add;
169+Bit32u tremtab_pos;
170+Bit32u tremtab_add;
171+
172+
149173 void operator_advance(op_type* op_pt, Bit32s vib) {
150174 op_pt->wfpos = op_pt->tcount; // waveform position
151175
diff -r 24df4a4651f7 -r 91b56854e368 src/opl.h
--- a/src/opl.h Sat Mar 03 11:36:07 2018 -0700
+++ b/src/opl.h Fri Jan 17 20:20:21 2020 -0500
@@ -148,6 +148,7 @@
148148 #endif
149149 } op_type;
150150
151+/*
151152 // per-chip variables
152153 Bitu chip_num;
153154 op_type op[MAXOPERATORS];
@@ -170,7 +171,7 @@
170171 Bit32u vibtab_add;
171172 Bit32u tremtab_pos;
172173 Bit32u tremtab_add;
173-
174+*/
174175
175176 // enable an operator
176177 void enable_operator(Bitu regbase, op_type* op_pt, Bit32u act_type);
diff -r 24df4a4651f7 -r 91b56854e368 src/video.c
--- a/src/video.c Sat Mar 03 11:36:07 2018 -0700
+++ b/src/video.c Fri Jan 17 20:20:21 2020 -0500
@@ -62,6 +62,8 @@
6262
6363 void init_video( void )
6464 {
65+ Uint32 main_window_flags;
66+
6567 if (SDL_WasInit(SDL_INIT_VIDEO))
6668 return;
6769
@@ -87,9 +89,15 @@
8789
8890 // Create the window with a temporary initial size, hidden until we set up the
8991 // scaler and find the true window size
92+ main_window_flags = SDL_WINDOW_HIDDEN;
93+#ifndef __EMSCRIPTEN__
94+ // The Emscripten port can handle resizing via HTML+CSS. Don't enable
95+ // resizable windows for that port, but do enable it for other platforms.
96+ main_window_flags |= SDL_WINDOW_RESIZABLE;
97+#endif
9098 main_window = SDL_CreateWindow("OpenTyrian",
9199 SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
92- vga_width, vga_height, SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN);
100+ vga_width, vga_height, main_window_flags);
93101
94102 if (main_window == NULL)
95103 {
Show on old repository browser