@lewismoten/gamemaker-sandbox-engine 0.0.0-stage → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/LICENSE +24 -0
- package/NOTICE.md +58 -0
- package/README.md +149 -2
- package/dist/assets/music.worklet-aD2x7RRM.js +466 -0
- package/dist/audio/cmfLoad.js +10 -0
- package/dist/audio/cmfPlayer.js +201 -0
- package/dist/audio/context.js +75 -0
- package/dist/audio/engine.js +173 -0
- package/dist/audio/mix.js +40 -0
- package/dist/audio/opl.js +245 -0
- package/dist/audio/output.js +40 -0
- package/dist/core/gameFiles.js +89 -0
- package/dist/engine/character.js +187 -0
- package/dist/engine/funcKeys.js +164 -0
- package/dist/engine/game.js +133 -0
- package/dist/engine/keys.js +68 -0
- package/dist/engine/machine.js +192 -0
- package/dist/engine/menus.js +135 -0
- package/dist/engine/monsters.js +259 -0
- package/dist/engine/playGain.js +10 -0
- package/dist/engine/playerLook.js +48 -0
- package/dist/engine/recorder.js +127 -0
- package/dist/engine/render.js +45 -0
- package/dist/engine/scene.js +324 -0
- package/dist/engine/scroll.js +79 -0
- package/dist/engine/showGraphic.js +107 -0
- package/dist/engine/slowPc.js +98 -0
- package/dist/engine/slowPcMusic.js +46 -0
- package/dist/engine/touch.js +61 -0
- package/dist/engine/world.js +205 -0
- package/dist/formats/binary.js +120 -0
- package/dist/formats/blocks.js +103 -0
- package/dist/formats/character.js +83 -0
- package/dist/formats/cmf.js +37 -0
- package/dist/formats/cmfEdit.js +154 -0
- package/dist/formats/cmfPreview.js +89 -0
- package/dist/formats/cmfSong.js +190 -0
- package/dist/formats/fli.js +340 -0
- package/dist/formats/fliFrames.js +34 -0
- package/dist/formats/fliLimits.js +54 -0
- package/dist/formats/game.js +198 -0
- package/dist/formats/gif.js +125 -0
- package/dist/formats/gifProgressive.js +99 -0
- package/dist/formats/graphicScripts.js +44 -0
- package/dist/formats/highscore.js +30 -0
- package/dist/formats/jpeg.js +359 -0
- package/dist/formats/map.js +38 -0
- package/dist/formats/monster.js +69 -0
- package/dist/formats/palette.js +58 -0
- package/dist/formats/recording.js +17 -0
- package/dist/formats/sound.js +44 -0
- package/dist/formats/voc.js +303 -0
- package/dist/gfx/colorVision.js +45 -0
- package/dist/gfx/cp437Glyphs.js +337 -0
- package/dist/gfx/font8x8.js +10 -0
- package/dist/gfx/screen.js +151 -0
- package/dist/index.js +15 -0
- package/dist/input/chords.js +46 -0
- package/dist/input/deskMouse.js +24 -0
- package/dist/input/keyboard.js +82 -0
- package/dist/input/scancodes.js +143 -0
- package/dist/player/fileExtensions.js +118 -0
- package/dist/player/patchRules.js +129 -0
- package/dist/player/patchTable.js +1753 -0
- package/dist/text/cp437.js +44 -0
- package/dist/types/audio/cmfLoad.d.ts +7 -0
- package/dist/types/audio/cmfPlayer.d.ts +69 -0
- package/dist/types/audio/context.d.ts +12 -0
- package/dist/types/audio/engine.d.ts +60 -0
- package/dist/types/audio/mix.d.ts +14 -0
- package/dist/types/audio/music.worklet.d.ts +22 -0
- package/dist/types/audio/opl.d.ts +37 -0
- package/dist/types/audio/output.d.ts +13 -0
- package/dist/types/core/gameFiles.d.ts +49 -0
- package/dist/types/engine/character.d.ts +30 -0
- package/dist/types/engine/funcKeys.d.ts +35 -0
- package/dist/types/engine/game.d.ts +57 -0
- package/dist/types/engine/keys.d.ts +17 -0
- package/dist/types/engine/machine.d.ts +103 -0
- package/dist/types/engine/menus.d.ts +46 -0
- package/dist/types/engine/monsters.d.ts +19 -0
- package/dist/types/engine/playGain.d.ts +11 -0
- package/dist/types/engine/playerLook.d.ts +44 -0
- package/dist/types/engine/recorder.d.ts +67 -0
- package/dist/types/engine/render.d.ts +8 -0
- package/dist/types/engine/scene.d.ts +188 -0
- package/dist/types/engine/scroll.d.ts +24 -0
- package/dist/types/engine/showGraphic.d.ts +39 -0
- package/dist/types/engine/slowPc.d.ts +124 -0
- package/dist/types/engine/slowPcMusic.d.ts +18 -0
- package/dist/types/engine/touch.d.ts +33 -0
- package/dist/types/engine/world.d.ts +237 -0
- package/dist/types/formats/binary.d.ts +44 -0
- package/dist/types/formats/blocks.d.ts +52 -0
- package/dist/types/formats/character.d.ts +65 -0
- package/dist/types/formats/cmf.d.ts +33 -0
- package/dist/types/formats/cmfEdit.d.ts +53 -0
- package/dist/types/formats/cmfPreview.d.ts +19 -0
- package/dist/types/formats/cmfSong.d.ts +74 -0
- package/dist/types/formats/fli.d.ts +56 -0
- package/dist/types/formats/fliFrames.d.ts +18 -0
- package/dist/types/formats/fliLimits.d.ts +13 -0
- package/dist/types/formats/game.d.ts +79 -0
- package/dist/types/formats/gif.d.ts +15 -0
- package/dist/types/formats/gifProgressive.d.ts +46 -0
- package/dist/types/formats/graphicScripts.d.ts +18 -0
- package/dist/types/formats/highscore.d.ts +10 -0
- package/dist/types/formats/jpeg.d.ts +20 -0
- package/dist/types/formats/map.d.ts +24 -0
- package/dist/types/formats/monster.d.ts +48 -0
- package/dist/types/formats/palette.d.ts +15 -0
- package/dist/types/formats/recording.d.ts +7 -0
- package/dist/types/formats/sound.d.ts +13 -0
- package/dist/types/formats/voc.d.ts +13 -0
- package/dist/types/gfx/colorVision.d.ts +26 -0
- package/dist/types/gfx/cp437Glyphs.d.ts +2 -0
- package/dist/types/gfx/font8x8.d.ts +2 -0
- package/dist/types/gfx/screen.d.ts +50 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/input/chords.d.ts +22 -0
- package/dist/types/input/deskMouse.d.ts +14 -0
- package/dist/types/input/keyboard.d.ts +39 -0
- package/dist/types/input/scancodes.d.ts +3 -0
- package/dist/types/player/fileExtensions.d.ts +44 -0
- package/dist/types/player/patchRules.d.ts +24 -0
- package/dist/types/player/patchTable.d.ts +83 -0
- package/dist/types/text/cp437.d.ts +6 -0
- package/package.json +339 -4
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { parseRecording as a, RECLEN as n, serializeRecording as d } from "../formats/recording.js";
|
|
2
|
+
const r = 1, e = 2;
|
|
3
|
+
class u {
|
|
4
|
+
mode = 0;
|
|
5
|
+
keys = [];
|
|
6
|
+
index = 0;
|
|
7
|
+
timer = 0;
|
|
8
|
+
lastKeyPress = 0;
|
|
9
|
+
paused = !1;
|
|
10
|
+
initRecord() {
|
|
11
|
+
this.mode = r, this.keys = [], this.restart();
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Whether waits for a key count toward playback time. PLAYGAME's GetKey called
|
|
15
|
+
* DoPlayBack on every poll, so while a "hit any key" screen waited the timer raced
|
|
16
|
+
* ahead (thousands of polls a second), and a demo recorded in DOS stores those polls
|
|
17
|
+
* as one huge DeltaTime before the key that dismissed the screen (Nebula's 26058).
|
|
18
|
+
* Demos recorded here count game ticks only, so for them waits must not count.
|
|
19
|
+
*/
|
|
20
|
+
countsWaits = !1;
|
|
21
|
+
initPlayback(s) {
|
|
22
|
+
return s ? (this.keys = a(s), this.countsWaits = this.keys.some((t) => t.delta > 4096), this.mode = e, this.restart(), !0) : !1;
|
|
23
|
+
}
|
|
24
|
+
stop() {
|
|
25
|
+
this.mode = 0, this.restart();
|
|
26
|
+
}
|
|
27
|
+
restart() {
|
|
28
|
+
this.lastKeyPress = 0, this.index = 0, this.timer = 0, this.paused = !1;
|
|
29
|
+
}
|
|
30
|
+
pause() {
|
|
31
|
+
this.paused = !0;
|
|
32
|
+
}
|
|
33
|
+
unpause() {
|
|
34
|
+
this.paused = !1;
|
|
35
|
+
}
|
|
36
|
+
/** Game ticks counted since the recording or playback (re)started; the playback position. */
|
|
37
|
+
get tick() {
|
|
38
|
+
return this.timer;
|
|
39
|
+
}
|
|
40
|
+
get playing() {
|
|
41
|
+
return this.mode === e;
|
|
42
|
+
}
|
|
43
|
+
/** Paused: play has left the levels (the won/lost pictures and score table follow). */
|
|
44
|
+
get halted() {
|
|
45
|
+
return this.paused;
|
|
46
|
+
}
|
|
47
|
+
/** DoPlayBack: advance one tick; returns the keys that become pending now. */
|
|
48
|
+
doPlayback() {
|
|
49
|
+
const s = [];
|
|
50
|
+
if (this.paused || (this.timer++, this.mode !== e)) return s;
|
|
51
|
+
for (; this.index < this.keys.length && this.lastKeyPress + this.keys[this.index].delta <= this.timer; )
|
|
52
|
+
s.push(this.keys[this.index].key), this.lastKeyPress += this.keys[this.index].delta, this.index++;
|
|
53
|
+
return s;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* GetKey polls while a screen waits for a key: `polls` calls to DoPlayBack at once.
|
|
57
|
+
* Returns the recorded keys that become pending (only for recordings made in DOS).
|
|
58
|
+
*/
|
|
59
|
+
advanceWait(s) {
|
|
60
|
+
const t = [];
|
|
61
|
+
if (this.paused || this.mode !== e || !this.countsWaits) return t;
|
|
62
|
+
for (this.timer += s; this.index < this.keys.length && this.lastKeyPress + this.keys[this.index].delta <= this.timer; )
|
|
63
|
+
t.push(this.keys[this.index].key), this.lastKeyPress += this.keys[this.index].delta, this.index++;
|
|
64
|
+
return t;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* One GetKey poll (DoPlayBack) by a key screen in a tick-counted recording, where waits
|
|
68
|
+
* otherwise don't count (advanceWait): the keys a demo gave that screen one tick after
|
|
69
|
+
* its opening key (DropBloc's Enter) become pending. Recordings made in DOS count their waits.
|
|
70
|
+
*/
|
|
71
|
+
pollOnce() {
|
|
72
|
+
return this.paused || this.mode !== e || this.countsWaits ? [] : this.advanceByTick();
|
|
73
|
+
}
|
|
74
|
+
advanceByTick() {
|
|
75
|
+
const s = [];
|
|
76
|
+
for (this.timer++; this.index < this.keys.length && this.lastKeyPress + this.keys[this.index].delta <= this.timer; )
|
|
77
|
+
s.push(this.keys[this.index].key), this.lastKeyPress += this.keys[this.index].delta, this.index++;
|
|
78
|
+
return s;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* A screen that read keys has finished. In DOS the next key may have come during it
|
|
82
|
+
* (the recording shows a gap of many thousands of polls), however fast that PC polled;
|
|
83
|
+
* catch up to it, and to keys a poll or two behind it (taken by the keyboard flush that
|
|
84
|
+
* follows every screen), so gameplay resumes in step. Only for DOS recordings.
|
|
85
|
+
*/
|
|
86
|
+
finishWait() {
|
|
87
|
+
const s = [];
|
|
88
|
+
if (this.paused || this.mode !== e || !this.countsWaits) return s;
|
|
89
|
+
const t = this.keys[this.index];
|
|
90
|
+
if (!t || t.delta <= 1e3) return s;
|
|
91
|
+
for (this.timer = Math.max(this.timer, this.lastKeyPress + t.delta); this.index < this.keys.length; ) {
|
|
92
|
+
const i = this.keys[this.index], h = this.lastKeyPress + i.delta <= this.timer;
|
|
93
|
+
if (!h && i.delta > 2) break;
|
|
94
|
+
h || (this.timer = this.lastKeyPress + i.delta), s.push(i.key), this.lastKeyPress += i.delta, this.index++;
|
|
95
|
+
}
|
|
96
|
+
return s;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* DoRecord: called when a key is actually applied to the character (keys held back
|
|
100
|
+
* while a sequence can't be interrupted are recorded on the tick they take effect).
|
|
101
|
+
* DeltaTime is a 16-bit uint in the C, and at most RECLEN keys are kept.
|
|
102
|
+
*/
|
|
103
|
+
doRecord(s) {
|
|
104
|
+
this.paused || this.mode !== r || this.index >= n || (this.keys[this.index] = { key: s, delta: this.timer - this.lastKeyPress & 65535 }, this.lastKeyPress = this.timer, this.index++);
|
|
105
|
+
}
|
|
106
|
+
/** The recording so far, in .rec format. */
|
|
107
|
+
save() {
|
|
108
|
+
return d(this.keys.slice(0, this.index));
|
|
109
|
+
}
|
|
110
|
+
/** For save games (the C wrote the Recording object and its keys into the .sav). */
|
|
111
|
+
snapshot() {
|
|
112
|
+
return {
|
|
113
|
+
mode: this.mode,
|
|
114
|
+
keys: this.keys.slice(0, Math.max(this.index, this.keys.length)),
|
|
115
|
+
index: this.index,
|
|
116
|
+
timer: this.timer,
|
|
117
|
+
lastKeyPress: this.lastKeyPress
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
restore(s) {
|
|
121
|
+
Object.assign(this, { mode: s.mode, keys: s.keys, index: s.index, timer: s.timer, lastKeyPress: s.lastKeyPress, paused: !1 });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
export {
|
|
125
|
+
r as RECORD,
|
|
126
|
+
u as Recorder
|
|
127
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { currentFrame as S } from "./character.js";
|
|
2
|
+
import { monPicNum as a } from "./monsters.js";
|
|
3
|
+
import { inScreenBounds as d } from "./touch.js";
|
|
4
|
+
import { SCRNBWID as y, SCRNBLEN as b, shownBlock as B, mapBlock as L, MAXMONSSHOWN as N, OFFSCRN as f } from "./world.js";
|
|
5
|
+
import { LASTMON as M, LASTSL as P } from "../formats/monster.js";
|
|
6
|
+
import { MLEN as h, MWID as k, LASTMM as I } from "../formats/map.js";
|
|
7
|
+
import { BLEN as p, MONBL as A, CHARBL as e } from "../formats/blocks.js";
|
|
8
|
+
const C = 312, D = 196;
|
|
9
|
+
function V(s) {
|
|
10
|
+
const { ci: o } = s;
|
|
11
|
+
o.update = !1, o.scrx > f && (o.oldx = o.scrx, o.oldy = o.scry, o.topthere = o.curtop < e, o.bottomthere = o.curbottom < e);
|
|
12
|
+
}
|
|
13
|
+
function _(s, o) {
|
|
14
|
+
const l = o.scroll.littleShiftx, n = o.scroll.littleShifty, x = o.scroll.nx + l, u = o.scroll.ny + n;
|
|
15
|
+
for (let t = 0; t <= y; t++)
|
|
16
|
+
for (let c = 0; c <= b; c++) {
|
|
17
|
+
const r = (o.mx + c) % h, m = (o.my + t) % k;
|
|
18
|
+
s.drawBlock(c * p - x, t * p - u, B(o, L(o, r, m)).pixels);
|
|
19
|
+
}
|
|
20
|
+
if (!o.noMons) {
|
|
21
|
+
let t = 0;
|
|
22
|
+
for (let c = 0; c < I && t < N; c++) {
|
|
23
|
+
const r = o.mi[c];
|
|
24
|
+
if (o.mm[c].monnum >= M || r.curPic < 0 || r.curPic >= P) continue;
|
|
25
|
+
const m = a(o, c);
|
|
26
|
+
if (!d(r.scrPos) || m >= A) {
|
|
27
|
+
r.picDrawn = !1;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
t++, r.picDrawn = !0, r.oldPos = { ...r.scrPos }, s.drawSprite(r.scrPos.x - l, r.scrPos.y - n, r.orient, o.mblk[m].pixels);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const { ci: i } = o;
|
|
34
|
+
if (i.scrx > f) {
|
|
35
|
+
const t = S(o).orient;
|
|
36
|
+
i.curtop < e && s.drawSprite(i.scrx - l, i.scry - p - n, t & 15, o.cblk[i.curtop].pixels), i.curbottom < e && s.drawSprite(i.scrx - l, i.scry - n, t >> 4, o.cblk[i.curbottom].pixels);
|
|
37
|
+
}
|
|
38
|
+
s.boxFill(C, 0, 319, 199, 0), s.boxFill(0, D, 319, 199, 0);
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
D as VISIBLE_H,
|
|
42
|
+
C as VISIBLE_W,
|
|
43
|
+
_ as renderWorld,
|
|
44
|
+
V as updateCharDrawState
|
|
45
|
+
};
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import { aboutScreen as ge, statusScreen as he, helpScreen as be, drawLoadHeading as ve, pickSaveSlot as $, drawSaveHeading as xe, pickDropSlot as Se } from "./funcKeys.js";
|
|
2
|
+
import { moveCharGrav as X, handleJoystick as Q, updateCharScreenPos as Me, moveChars as Ce } from "./character.js";
|
|
3
|
+
import { resetKeys as z, simKeyPress as Le } from "./keys.js";
|
|
4
|
+
import { resetMonInfo as Ae, birthMon as we, blockBirthMonsters as Oe, moveAllMonsters as Te } from "./monsters.js";
|
|
5
|
+
import { renderWorld as V, updateCharDrawState as Pe } from "./render.js";
|
|
6
|
+
import { initScroll as Y, changeScroll as Ee, drawScroll as Ne } from "./scroll.js";
|
|
7
|
+
import { showGraphic as Z } from "./showGraphic.js";
|
|
8
|
+
import { playTuning as Ke, STOCK_LOOK as K } from "./playerLook.js";
|
|
9
|
+
import { getTouchBlocks as Be } from "./touch.js";
|
|
10
|
+
import { bgBlock as H, createWorld as qe, padBlocks as I, OFFSCRN as A, SCRNBLEN as ee, SCRNBWID as oe, NEVER as Re, mapBlock as De } from "./world.js";
|
|
11
|
+
import { BACKBL as C, parseBlocks as j, MONBL as F, CHARBL as N } from "../formats/blocks.js";
|
|
12
|
+
import { parseCharacter as Ie, MAXINV as _, MAXSEQ as E } from "../formats/character.js";
|
|
13
|
+
import { parseMonsters as je, LASTMON as Fe } from "../formats/monster.js";
|
|
14
|
+
import { parseMap as Ge, MLEN as te, MWID as ne, LASTMM as U } from "../formats/map.js";
|
|
15
|
+
import { parsePalette as Ue } from "../formats/palette.js";
|
|
16
|
+
import { parseSoundSet as ce, LASTSND as We } from "../formats/sound.js";
|
|
17
|
+
import { MAXSCENELINKS as M, NOSCENE as Ve } from "../formats/game.js";
|
|
18
|
+
import { TICK_RATE as He } from "../audio/cmfPlayer.js";
|
|
19
|
+
import { SlowCpu as _e, tickCost as J, sceneLoadMs as Je, vocStallMs as $e, vocWontFit as Xe, musicHoldMs as Qe, scrollCost as ze } from "./slowPc.js";
|
|
20
|
+
import { songIsrMs as Ye, songLoad as Ze } from "./slowPcMusic.js";
|
|
21
|
+
import { newPlayGain as re, gainAtLoad as eo } from "./playGain.js";
|
|
22
|
+
const G = 2;
|
|
23
|
+
function B(e, r, t) {
|
|
24
|
+
return e.scenes[r]?.files[t] || void 0;
|
|
25
|
+
}
|
|
26
|
+
function se(e, r, t) {
|
|
27
|
+
const { m: c, game: o } = e, s = (y) => B(o, r, y), i = [], a = (y) => {
|
|
28
|
+
const b = s(y);
|
|
29
|
+
if (!b) return;
|
|
30
|
+
const T = c.files.get(b);
|
|
31
|
+
return T || i.push(b), T;
|
|
32
|
+
}, d = a(0), v = a(1), g = a(2), n = a(3), x = a(4), S = a(5), L = a(6);
|
|
33
|
+
if (i.length) return i;
|
|
34
|
+
const u = qe(Ge(v ?? new Uint8Array(0)), { play: () => !1 }, e.rand?.());
|
|
35
|
+
u.tune = Ke(e.look ?? K), d ? u.palette = Ue(d) : t && (u.palette = t.palette), u.bg = I(g ? j(g, C) : t?.bg.slice(0, C), C), u.mblk = I(x ? j(x, F) : t?.mblk.slice(0, F), F), u.cblk = I(L ? j(L, N) : t?.cblk.slice(0, N), N), u.mon = n ? je(n) : t?.mon ?? [], u.noMons = !s(3) || !s(4);
|
|
36
|
+
const h = e.onTouched;
|
|
37
|
+
if (h && (u.onTouched = (y, b, T) => h(r, y, b, T)), u.chr = S ? Ie(S) : t.chr, !u.chr) return [s(5) ?? "character"];
|
|
38
|
+
const P = s(7), w = P ? c.files.get(P) : void 0, O = s(8);
|
|
39
|
+
return { world: u, sounds: w ? ce(w) : void 0, song: O ? c.files.get(O) : void 0 };
|
|
40
|
+
}
|
|
41
|
+
const ie = [0, 1, 2, 3, 4, 5, 6, 7], oo = [0, 2, 3, 4, 6, 7];
|
|
42
|
+
function to(e, r, t, c = ie) {
|
|
43
|
+
const o = [];
|
|
44
|
+
for (const s of t ? [...c, 8] : c) {
|
|
45
|
+
const i = B(e.game, r, s);
|
|
46
|
+
i && o.push(e.m.files.get(i)?.length ?? 0);
|
|
47
|
+
}
|
|
48
|
+
return o;
|
|
49
|
+
}
|
|
50
|
+
async function ae(e, r, t) {
|
|
51
|
+
const c = e.speed.slowPc;
|
|
52
|
+
if (!c || c.vocOpenMs === void 0 || !c.vocBytesPerMs) {
|
|
53
|
+
e.sceneLoad && (e.sceneLoad = void 0);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const o = to(e, r, e.m.audio.musicEnabled, t), s = Je(c, o);
|
|
57
|
+
e.sceneLoad = { files: o.length, bytes: o.reduce((i, a) => i + a, 0), ms: s }, s > 0 && (me(e, s), await e.m.sleep(s));
|
|
58
|
+
}
|
|
59
|
+
async function le(e, r) {
|
|
60
|
+
const { m: t, game: c } = e, o = c.scenes[r]?.files ?? [];
|
|
61
|
+
await t.need(...o.slice(0, 9));
|
|
62
|
+
const s = o[7] ? t.files.get(o[7]) : void 0;
|
|
63
|
+
let i = [];
|
|
64
|
+
try {
|
|
65
|
+
i = s ? ce(s).digital.filter((d) => d && d[0] !== " ").map((d) => `${d}.voc`) : [];
|
|
66
|
+
} catch {
|
|
67
|
+
}
|
|
68
|
+
await t.need(...i);
|
|
69
|
+
const a = (c.scenes[r]?.links ?? []).flatMap((d) => c.scenes[d.toScene]?.files.slice(0, 10) ?? []);
|
|
70
|
+
t.want(o[10], ...a);
|
|
71
|
+
}
|
|
72
|
+
function no(e, r) {
|
|
73
|
+
e.vocStall = (e.vocStall ?? 0) + r, me(e, r);
|
|
74
|
+
}
|
|
75
|
+
function me(e, r) {
|
|
76
|
+
e.m.audio.holdMusic(Qe(e.speed.slowPc, r));
|
|
77
|
+
}
|
|
78
|
+
function fe(e, r, t) {
|
|
79
|
+
r.sound = {
|
|
80
|
+
play: (c) => {
|
|
81
|
+
if (!t || !e.soundOn || c < 0 || c >= We) return !1;
|
|
82
|
+
const o = t.digital[c];
|
|
83
|
+
if (!e.speakerOnly && e.m.audio.soundCardEnabled !== !1 && o && o[0] !== " ") {
|
|
84
|
+
const s = e.m.files.get(`${o}.voc`), i = e.speed.slowPc, a = s ? $e(i, s.length) : 0;
|
|
85
|
+
!s || !i || !a ? e.m.audio.playVoc(s) : (e.m.audio.stopVoc(), no(e, a), Xe(i, s.length) ? e.vocLate = void 0 : e.vocLate = { bytes: s, wait: (e.vocLate?.wait ?? 0) + a });
|
|
86
|
+
} else e.m.audio.playSpeaker(t.freqs[c]);
|
|
87
|
+
return !0;
|
|
88
|
+
}
|
|
89
|
+
}, r.joystick = e.joystick;
|
|
90
|
+
}
|
|
91
|
+
function qo(e) {
|
|
92
|
+
e.timerCounter = 1, e.sndClock = 1;
|
|
93
|
+
const r = e.ci;
|
|
94
|
+
r.hitpts = -1, r.lives = -1, r.score = 0, e.gain = re(), r.inv.fill(C + 1), r.meter.fill(-1);
|
|
95
|
+
}
|
|
96
|
+
function co(e, r) {
|
|
97
|
+
const { ci: t, chr: c } = e;
|
|
98
|
+
if (t.inv[0] === C + 1) for (let o = 0; o < _; o++) t.inv[o] = c.inv[o];
|
|
99
|
+
for (let o = 0; o < E; o++)
|
|
100
|
+
t.seqon[o] = c.sequences[o].bloc === C, t.meter[o] === -2e4 && (t.meter[o] = c.meter[o]);
|
|
101
|
+
for (let o = 0; o < _; o++) for (let s = 0; s < E; s++) c.sequences[s].bloc === t.inv[o] && (t.seqon[s] = !0);
|
|
102
|
+
if (t.meter[0] === -1) {
|
|
103
|
+
for (let o = 0; o < 5; o++) t.meter[o] = c.meter[o];
|
|
104
|
+
for (let o = 5; o < E; o++) t.meter[o] = c.sequences[o].key > 0 ? c.meter[o] : -2e4;
|
|
105
|
+
for (let o = E; o < E + 10; o++) t.meter[o] = c.meter[o];
|
|
106
|
+
}
|
|
107
|
+
c.x[0] = r.x, c.y[0] = r.y, c.x[1] = 0, c.y[1] = 0, c.cseq = 0, c.cframe = -1, t.hitpts === -1 && (t.hitpts = t.meter[0]), t.lives === -1 && (t.lives = t.meter[1]), t.netx = 5, t.nety = 0, t.gravx = 0, t.gravy = 0, t.scrx = t.oldx = t.nextx = A, t.scry = t.oldy = t.nexty = A, t.topthere = !1, t.bottomthere = !1, t.curtop = N, t.curbottom = N, t.nextAni = e.clock, e.mx = r.x - ee / 2, e.my = r.y - oe / 2, e.mx < 0 && (e.mx += te), e.my < 0 && (e.my += ne);
|
|
108
|
+
for (let o = 0; o < U; o++)
|
|
109
|
+
Ae(e.mi[o]), we(e, o, e.mm[o].monnum, e.mm[o].curx, e.mm[o].cury), e.mi[o].fromchar = 0;
|
|
110
|
+
for (let o = 0; o < C; o++)
|
|
111
|
+
e.blkmap[o] = o, e.nxtchg[o] = e.bg[o].ntime > 0 ? e.clock + e.bg[o].ntime : Re;
|
|
112
|
+
if (e.blkMon = [], !e.noMons)
|
|
113
|
+
for (let o = 0; o < C; o++) e.bg[o].birthTime > 0 && e.blkMon.push({ blnum: o, nexttime: e.clock + e.bg[o].birthTime });
|
|
114
|
+
z(e), ro(e.keydn, c.sequences[c.cseq].key);
|
|
115
|
+
}
|
|
116
|
+
function ro(e, r) {
|
|
117
|
+
r >= 0 && r < 128 && (e[r] = 1);
|
|
118
|
+
}
|
|
119
|
+
function so(e) {
|
|
120
|
+
for (let r = 0; r < C; r++) {
|
|
121
|
+
const t = e.blkmap[r], c = H(e, t);
|
|
122
|
+
e.nxtchg[r] <= e.clock && c.nextBl !== t && (e.blkmap[r] = c.nextBl, e.nxtchg[r] = c.ntime <= 0 ? 0 : e.nxtchg[r] + H(e, e.blkmap[r]).ntime);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function io(e, r, t) {
|
|
126
|
+
const c = Be(r), o = e.game.scenes[t].links;
|
|
127
|
+
for (let s = 0; s < M; s++) {
|
|
128
|
+
const i = o[s];
|
|
129
|
+
if (!(!i || i.toScene === Ve)) {
|
|
130
|
+
for (let a = 0; a < 6; a++)
|
|
131
|
+
if (i.from.x === c.blks[a][0] && i.from.y === c.blks[a][1])
|
|
132
|
+
return r.chr.x[0] = i.to.x, r.chr.y[0] = i.to.y, s;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return M;
|
|
136
|
+
}
|
|
137
|
+
async function ao(e, r) {
|
|
138
|
+
const { m: t } = e, c = e.look ?? K;
|
|
139
|
+
t.screen.setPalette(new Uint8Array(768));
|
|
140
|
+
for (let o = 1; o <= 4; o++) t.screen.setColor(o, ...c.rgb(`color.missing.${o}`));
|
|
141
|
+
t.screen.clear(), t.screen.box(...c.frame("border.missing.outer"), 4), t.screen.box(...c.frame("border.missing.inner"), 4), t.screen.write(40, 20, 1, c.text("str.missing.title")), r.forEach((o, s) => t.screen.write(32, (9 + s) * 8, 2, o)), t.screen.write(120, 168, 3, c.text("str.missing.anyKey")), await t.pauseTimeKey(c.seconds("timing.missingFiles"));
|
|
142
|
+
}
|
|
143
|
+
async function Ro(e, r, t, c) {
|
|
144
|
+
const { m: o, game: s } = e, i = e.look ?? K;
|
|
145
|
+
let a = r, d = t, v = c;
|
|
146
|
+
o.screen.setPaletteTo(0, 0, 0), await le(e, a);
|
|
147
|
+
const g = se(e, a, e.lastWorld);
|
|
148
|
+
if (Array.isArray(g))
|
|
149
|
+
return await ao(e, g), { ok: !1, link: M + 1 };
|
|
150
|
+
await ae(e, a, ie);
|
|
151
|
+
let n = g.world;
|
|
152
|
+
e.lastWorld = n, n.ci = e.ci, n.clock = e.timerCounter, fe(e, n, g.sounds);
|
|
153
|
+
let x = g.song;
|
|
154
|
+
e.musicOn && o.audio.playSong(x), co(n, s.scenes[d]?.links[v]?.to ?? { x: 0, y: 0 }), X(n, !0), Q(n, !0), Y(n, s.scenes[a].scroll), e.colors = n.palette, o.screen.dosCropped = !0, o.screen.sceneNumber = a, V(o.screen, n), await o.fadeTo(n.palette, n.tune.fadeSteps), o.keyboard.attach();
|
|
155
|
+
const L = new Set(n.chr.sequences.map((l) => l.key >> 8).filter((l) => l));
|
|
156
|
+
o.keyboard.chordable = (l) => L.has(l), o.flushKeys();
|
|
157
|
+
let u = 0, h = M, P = !1, w = e.timerCounter;
|
|
158
|
+
const O = 1e3 / He, y = new _e(O);
|
|
159
|
+
let b;
|
|
160
|
+
const T = (l) => ((!b || b.song !== l) && (b = { song: l, load: Ze(l) }), b.load), ue = () => {
|
|
161
|
+
let l = 0;
|
|
162
|
+
for (let p = 0; p < U && l < 50; p++) n.mm[p].monnum < Fe && n.mi[p].scrPos.x !== A && l++;
|
|
163
|
+
return l;
|
|
164
|
+
}, R = new Uint8Array(n.blkmap.length), pe = () => {
|
|
165
|
+
let l = 0;
|
|
166
|
+
for (let p = 0; p < oe; p++)
|
|
167
|
+
for (let m = 0; m < ee; m++) {
|
|
168
|
+
const k = De(n, (n.mx + m) % te, (n.my + p) % ne);
|
|
169
|
+
k < R.length && n.blkmap[k] !== R[k] && l++;
|
|
170
|
+
}
|
|
171
|
+
return l;
|
|
172
|
+
};
|
|
173
|
+
let D = o.now(), q = 0;
|
|
174
|
+
const W = () => {
|
|
175
|
+
D = o.now(), q = 0;
|
|
176
|
+
}, ke = async () => {
|
|
177
|
+
n.clock = w = e.timerCounter, n.noMons || (Oe(n), Te(n)), o.keyboard.typed.length = 0;
|
|
178
|
+
const l = o.keyboard.events.splice(0);
|
|
179
|
+
for (const m of e.rec.doPlayback()) l.push(m);
|
|
180
|
+
if (l.length && (!n.chr.sequences[n.chr.cseq].ground || n.chr.cframe === 0)) {
|
|
181
|
+
for (const m of l)
|
|
182
|
+
e.rec.doRecord(m), Le(n, m);
|
|
183
|
+
for (const m of l) (m === 1 || m >= 59 && m <= 68) && (n.keydn[m] = 1);
|
|
184
|
+
} else l.length && o.keyboard.events.unshift(...l);
|
|
185
|
+
let p = 0;
|
|
186
|
+
do
|
|
187
|
+
await Ce(n, async () => {
|
|
188
|
+
const m = await Se(o, n, i);
|
|
189
|
+
return o.flushKeys(), n.keydn.fill(0), W(), m;
|
|
190
|
+
}) && (u = G);
|
|
191
|
+
while (n.chr.cframe === -1 && u !== G && p++ < 50);
|
|
192
|
+
so(n), Pe(n), P = Ee(n) !== 0, n.monsolid = 0, n.mmSolid = U, h = io(e, n, a);
|
|
193
|
+
}, ye = async (l) => {
|
|
194
|
+
const p = e.sndClock;
|
|
195
|
+
o.audio.stopSpeaker(), o.screen.dosCropped = !1, o.screen.clear(), n.keydn.fill(0), o.flushKeys();
|
|
196
|
+
const m = n.palette;
|
|
197
|
+
switch (o.screen.setPalette(m), i.fkeyOn(l) ? l : 0) {
|
|
198
|
+
case 1:
|
|
199
|
+
await be(o, n, B(s, 0, 6), e.gmHelp, i);
|
|
200
|
+
break;
|
|
201
|
+
case 2:
|
|
202
|
+
await he(o, n, i);
|
|
203
|
+
break;
|
|
204
|
+
case 5:
|
|
205
|
+
await mo(e, n, { prevscene: d, doscene: a, linkin: v });
|
|
206
|
+
break;
|
|
207
|
+
case 6: {
|
|
208
|
+
const f = await uo(e, n);
|
|
209
|
+
f && ({ w: n, prevscene: d, doscene: a, linkin: v, song: x } = { ...f, song: f.song });
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
case 9:
|
|
213
|
+
o.screen.write(40, 80, i.color(m, "color.select.joyText"), "Joysticks are configured by"), o.screen.write(40, 88, i.color(m, "color.select.joyText"), "your browser (Gamepad API)."), await o.pauseTimeKey(5);
|
|
214
|
+
break;
|
|
215
|
+
case 10:
|
|
216
|
+
await ge(o, n, i);
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
const k = e.sndClock >> 3;
|
|
220
|
+
for (const f of n.mi)
|
|
221
|
+
f.nextAni = k, f.nextMove = k, f.scrPos = { x: A, y: A }, f.oldPos = { x: A, y: A }, f.picDrawn = !1;
|
|
222
|
+
n.scroll.nx = n.scroll.ny = 0, n.scroll.movx = n.scroll.movy = 0, z(n), n.chr.cseq = 0, n.chr.cframe = 0, n.ci.topthere = n.ci.bottomthere = !1, Me(n), n.ci.scrx = n.ci.nextx, n.ci.scry = n.ci.nexty, o.screen.setPalette(n.palette), e.colors = n.palette, l !== 6 && (e.sndClock = p), e.timerCounter = n.clock = e.sndClock >> 3, w = e.timerCounter, o.flushKeys(), W();
|
|
223
|
+
};
|
|
224
|
+
for (; !u && h === M; ) {
|
|
225
|
+
await o.frame();
|
|
226
|
+
const l = o.now();
|
|
227
|
+
q += l - D, D = l;
|
|
228
|
+
let p = Math.floor(q / O);
|
|
229
|
+
q -= p * O, p > 40 && (p = 40);
|
|
230
|
+
for (let m = 0; m < p && !u && h === M; m++) {
|
|
231
|
+
(e.sndClock & 7) === 0 && e.timerCounter++, e.sndClock++;
|
|
232
|
+
const k = e.speed.slowPc;
|
|
233
|
+
if (!k) y.reset();
|
|
234
|
+
else if (y.spend(Ye(k, e.musicOn && o.audio.musicEnabled ? T(x) : void 0)), y.busy()) continue;
|
|
235
|
+
if (P) {
|
|
236
|
+
const f = Ne(n);
|
|
237
|
+
k && y.spend(ze(k, f));
|
|
238
|
+
}
|
|
239
|
+
if (n.keydn[1]) {
|
|
240
|
+
u = 1;
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
for (let f = 1; f <= 10; f++)
|
|
244
|
+
n.keydn[58 + f] && (n.keydn[58 + f] = 0, f === 3 ? o.audio.musicEnabled && (e.musicOn = !e.musicOn, e.musicOn ? o.audio.playSong(x) : o.audio.stopSong()) : f === 4 ? e.soundOn = !e.soundOn : f === 8 ? n.jstickOn = !n.jstickOn : f !== 7 && await ye(f));
|
|
245
|
+
w < e.timerCounter && (k && (y.spend(J(k, ue())), R.set(n.blkmap)), e.vocStall = 0, await ke(), k && k.cellMs && y.spend(J({ ...k, tickMs: 0, monsterMs: 0 }, 0, pe())), k && e.vocStall && y.spend(e.vocStall), e.vocStall = 0);
|
|
246
|
+
}
|
|
247
|
+
e.vocLate && (e.vocLate.due ??= l + e.vocLate.wait, l >= e.vocLate.due && (e.m.audio.playVoc(e.vocLate.bytes), e.vocLate = void 0)), o.screen.dosCropped = !0, o.screen.sceneNumber = a, V(o.screen, n), e.onFrame?.(n);
|
|
248
|
+
}
|
|
249
|
+
return e.vocLate = void 0, o.audio.stopSong(), o.audio.stopSpeaker(), await o.fadeAllTo(0, 0, 0, n.tune.fadeSteps), o.screen.dosCropped = !1, o.keyboard.detach(), o.keyboard.chordable = void 0, o.keyboard.attach(), n.keydn[1] && (h = M + 1), u === G && (e.rec.playing || e.onLifeLost?.(), e.ci.lives > 0 ? (e.ci.lives--, e.ci.hitpts = -1, h = M) : h = M + 2), { ok: !0, link: h, doscene: a, prevscene: d };
|
|
250
|
+
}
|
|
251
|
+
const de = (e) => `game${e}.sav`;
|
|
252
|
+
function lo(e, r, t, c) {
|
|
253
|
+
return {
|
|
254
|
+
version: 1,
|
|
255
|
+
...r,
|
|
256
|
+
sndClock: t,
|
|
257
|
+
world: {
|
|
258
|
+
nxtchg: e.nxtchg,
|
|
259
|
+
ci: e.ci,
|
|
260
|
+
mx: e.mx,
|
|
261
|
+
my: e.my,
|
|
262
|
+
mi: e.mi,
|
|
263
|
+
mm: e.mm,
|
|
264
|
+
noMons: e.noMons,
|
|
265
|
+
blkMon: e.blkMon,
|
|
266
|
+
blkmap: [...e.blkmap],
|
|
267
|
+
map: [...e.map],
|
|
268
|
+
mapMon: [...e.mapMon],
|
|
269
|
+
chr: { x: e.chr.x, y: e.chr.y, cframe: e.chr.cframe, cseq: e.chr.cseq }
|
|
270
|
+
},
|
|
271
|
+
rec: c.snapshot()
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
async function mo(e, r, t) {
|
|
275
|
+
const { m: c, game: o } = e, s = e.look ?? K;
|
|
276
|
+
e.rec.pause();
|
|
277
|
+
const i = B(o, 0, 10), a = new Uint8Array(768);
|
|
278
|
+
i ? await Z(c, i, { cols: a, pause: 0, gamePalette: r.palette, look: s }) : (a.set(r.palette), xe(c.screen, s, a));
|
|
279
|
+
const d = await $(c, a, !0, s);
|
|
280
|
+
d >= 0 && (c.files.set(de(d), new TextEncoder().encode(JSON.stringify(lo(r, t, e.sndClock, e.rec)))), c.screen.write(112, 185, s.color(a, i ? "color.select.saveTextPic" : "color.select.saveText"), s.text("str.save.done")), await c.pauseTimeKey(s.seconds("timing.saveMessage"))), e.rec.unpause();
|
|
281
|
+
}
|
|
282
|
+
function fo(e, r, t) {
|
|
283
|
+
const c = se(e, t.doscene, r);
|
|
284
|
+
if (Array.isArray(c)) return;
|
|
285
|
+
const o = c.world, s = t.world;
|
|
286
|
+
return Object.assign(o, { nxtchg: s.nxtchg, mx: s.mx, my: s.my, mi: s.mi, mm: s.mm, noMons: s.noMons, blkMon: s.blkMon }), o.blkmap = Uint8Array.from(s.blkmap), o.map = Uint8Array.from(s.map), o.mapMon = Uint8Array.from(s.mapMon), Object.assign(e.ci, s.ci), o.ci = e.ci, Object.assign(o.chr, s.chr), Y(o, e.game.scenes[t.doscene].scroll), e.rec.restore(t.rec), e.sndClock = t.sndClock, o.clock = e.sndClock >> 3, X(o, !0), Q(o, !0), c;
|
|
287
|
+
}
|
|
288
|
+
async function uo(e, r) {
|
|
289
|
+
const { m: t, game: c } = e, o = e.look ?? K, s = B(c, 0, 9), i = new Uint8Array(768);
|
|
290
|
+
s ? await Z(t, s, { cols: i, pause: 0, gamePalette: r.palette, look: o }) : (i.set(r.palette), ve(t.screen, o, i));
|
|
291
|
+
const a = await $(t, i, !1, o);
|
|
292
|
+
if (a < 0) return;
|
|
293
|
+
const d = t.files.get(de(a)), v = o.color(i, s ? "color.select.loadTextPic" : "color.select.loadText"), g = o.seconds("timing.loadMessage");
|
|
294
|
+
if (!d) {
|
|
295
|
+
t.screen.write(40, 185, v, o.text("str.load.empty")), await t.pauseTimeKey(g);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
let n;
|
|
299
|
+
try {
|
|
300
|
+
n = JSON.parse(new TextDecoder().decode(d));
|
|
301
|
+
} catch {
|
|
302
|
+
t.screen.write(40, 185, v, "This saved game is damaged!"), await t.pauseTimeKey(g);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
await le(e, n.doscene);
|
|
306
|
+
const x = e.ci.score, S = fo(e, r, n);
|
|
307
|
+
if (!S) return;
|
|
308
|
+
eo(e.gain ??= re(), x, e.ci.score);
|
|
309
|
+
const L = S.world;
|
|
310
|
+
return fe(e, L, S.sounds), t.screen.write(88, 185, v, o.text("str.load.done")), await ae(e, n.doscene, oo), await t.pauseTimeKey(g), e.musicOn && t.audio.playSong(S.song), { w: L, prevscene: n.prevscene, doscene: n.doscene, linkin: n.linkin, song: S.song };
|
|
311
|
+
}
|
|
312
|
+
export {
|
|
313
|
+
oo as LOADGAME_SLOTS,
|
|
314
|
+
so as changeBlocks,
|
|
315
|
+
se as loadScene,
|
|
316
|
+
Ro as playScene,
|
|
317
|
+
fo as restoreSaved,
|
|
318
|
+
lo as savedState,
|
|
319
|
+
B as sceneFile,
|
|
320
|
+
to as sceneReads,
|
|
321
|
+
ro as setStartKey,
|
|
322
|
+
qo as startGameInits,
|
|
323
|
+
co as startSceneInits
|
|
324
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { updateCharDrawState as v } from "./render.js";
|
|
2
|
+
import { inScreenBounds as g } from "./touch.js";
|
|
3
|
+
import { SIZEX as m, SIZEY as M, i16 as s, sign as c, OFFSCRN as r } from "./world.js";
|
|
4
|
+
import { BLEN as x, SOLLEF as a, SOLRIG as f, SOLTOP as S, SOLBOT as d } from "../formats/blocks.js";
|
|
5
|
+
import { MLEN as p, MWID as u, LASTMM as L } from "../formats/map.js";
|
|
6
|
+
import { LASTMON as O } from "../formats/monster.js";
|
|
7
|
+
function T(i, t) {
|
|
8
|
+
const o = i.scroll;
|
|
9
|
+
Object.assign(o, {
|
|
10
|
+
nx: 0,
|
|
11
|
+
ny: 0,
|
|
12
|
+
totalx: 0,
|
|
13
|
+
totaly: 0,
|
|
14
|
+
distx: 0,
|
|
15
|
+
disty: 0,
|
|
16
|
+
inMotion: 0,
|
|
17
|
+
movx: 0,
|
|
18
|
+
movy: 0,
|
|
19
|
+
littleShiftx: 0,
|
|
20
|
+
littleShifty: 0,
|
|
21
|
+
bx: { dscroll: 0, ctr: 0, iters: 0 },
|
|
22
|
+
by: { dscroll: 0, ctr: 0, iters: 0 }
|
|
23
|
+
}), o.up = t.down, o.down = t.up, o.left = t.right, o.right = t.left, o.maxX = m / 3, o.minX = -m / 3, o.maxY = 60, o.minY = -60, o.upStop = Math.trunc(-M / 6), o.downStop = Math.trunc(M / 6), o.leftStop = -m / 4, o.rightStop = m / 4;
|
|
24
|
+
}
|
|
25
|
+
function y(i, t, o, n = !1) {
|
|
26
|
+
let l = s(s(i) * t);
|
|
27
|
+
return n && (l = s(-l)), s(Math.trunc(l / s(o)));
|
|
28
|
+
}
|
|
29
|
+
function B(i) {
|
|
30
|
+
const t = i.scroll;
|
|
31
|
+
t.totalx = t.totaly = 0;
|
|
32
|
+
const o = i.ci.nextx + x / 2 - m / 2, n = i.ci.nexty + x / 2 - M / 2;
|
|
33
|
+
return t.distx = o, t.disty = n, t.left === 255 && o > t.maxX && (t.inMotion |= a), t.right === 255 && o < t.minX && (t.inMotion |= f), t.up === 255 && n > t.maxY && (t.inMotion |= S), t.down === 255 && n < t.minY && (t.inMotion |= d), t.inMotion & a && (o < t.leftStop ? t.inMotion &= ~a : t.totalx = y(o - t.leftStop, i.tune.scrollSpeedX, t.maxX - t.leftStop)), t.inMotion & f && (o > t.rightStop ? t.inMotion &= ~f : t.totalx = y(-o + t.rightStop, i.tune.scrollSpeedX, t.rightStop - t.minX, !0)), t.inMotion & S && (n < t.upStop ? t.inMotion &= ~S : t.totaly = y(n - t.upStop, i.tune.scrollSpeedY, t.maxY - t.upStop)), t.inMotion & d && (n > t.downStop ? t.inMotion &= ~d : t.totaly = y(-n + t.downStop, i.tune.scrollSpeedY, t.downStop - t.minY, !0)), t.totalx = Math.max(-28, Math.min(28, t.totalx)), t.totaly = Math.max(-28, Math.min(28, t.totaly)), t.bx = { dscroll: t.totalx, ctr: 0, iters: i.tune.scrollSteps }, t.by = { dscroll: t.totaly, ctr: 0, iters: i.tune.scrollSteps }, t.inMotion;
|
|
34
|
+
}
|
|
35
|
+
function h(i) {
|
|
36
|
+
let t = 0;
|
|
37
|
+
const o = Math.abs(i.dscroll);
|
|
38
|
+
if (o > i.iters) {
|
|
39
|
+
for (; i.ctr < o; )
|
|
40
|
+
t += c(i.dscroll), i.ctr += i.iters;
|
|
41
|
+
i.ctr -= o;
|
|
42
|
+
} else
|
|
43
|
+
i.ctr += o, i.ctr >= i.iters && (i.ctr -= i.iters, t += c(i.dscroll));
|
|
44
|
+
return t;
|
|
45
|
+
}
|
|
46
|
+
function P(i, t) {
|
|
47
|
+
for (let l = 0; l < L; l++) {
|
|
48
|
+
if (i.mm[l].monnum >= O) continue;
|
|
49
|
+
const e = i.mi[l];
|
|
50
|
+
e.scrPos.x !== r && (e.scrPos.x += t.x, e.scrPos.y += t.y), e.oldPos.x !== r && (e.oldPos.x += t.x, e.oldPos.y += t.y, g(e.oldPos) || (e.oldPos = { x: r, y: r }));
|
|
51
|
+
}
|
|
52
|
+
const o = i.ci;
|
|
53
|
+
let n = !1;
|
|
54
|
+
return o.nexty - o.oldy === 0 || c(t.y) === c(o.nexty - o.oldy) ? o.scry !== r && (o.scry += t.y) : (n = !0, Math.abs(o.nexty - o.oldy) < 4 && (o.scry += o.nexty - o.oldy + t.y)), o.nextx - o.oldx === 0 || c(t.x) === c(o.nextx - o.oldx) ? o.scrx !== r && (o.scrx += t.x) : (n = !0, Math.abs(o.nextx - o.oldx) < 4 && (o.scrx += o.nextx - o.oldx + t.x)), o.nextx !== r && (o.nextx += t.x, o.nexty += t.y), o.oldx !== r && (o.oldx += t.x, o.oldy += t.y), n;
|
|
55
|
+
}
|
|
56
|
+
function F(i) {
|
|
57
|
+
const t = i.scroll;
|
|
58
|
+
t.movx += h(t.bx), t.movy += h(t.by);
|
|
59
|
+
const o = { x: 0, y: 0 };
|
|
60
|
+
if (t.movx < 0)
|
|
61
|
+
for (; t.movx < 0; )
|
|
62
|
+
o.x += 4, t.movx += 4, t.nx -= 4;
|
|
63
|
+
else if (t.movx > 0)
|
|
64
|
+
for (; t.movx > 3; )
|
|
65
|
+
o.x -= 4, t.movx -= 4, t.nx += 4;
|
|
66
|
+
if (t.movy < 0)
|
|
67
|
+
for (; t.movy < 0; )
|
|
68
|
+
o.y += 4, t.movy += 4, t.ny -= 4;
|
|
69
|
+
else if (t.movy > 0)
|
|
70
|
+
for (; t.movy > 3; )
|
|
71
|
+
o.y -= 4, t.movy -= 4, t.ny += 4;
|
|
72
|
+
return t.littleShiftx = t.movx & 3, t.littleShifty = t.movy & 3, t.nx >= x && (t.nx -= x, i.mx = (i.mx + 1) % p), t.ny >= x && (t.ny -= x, i.my = (i.my + 1) % u), t.nx < 0 && (t.nx += x, i.mx = (i.mx - 1 + p) % p), t.ny < 0 && (t.ny += x, i.my = (i.my - 1 + u) % u), ((o.x || o.y) && P(i, o) || t.littleShiftx || t.littleShifty) && v(i), (Math.abs(o.x) + Math.abs(o.y)) / 4;
|
|
73
|
+
}
|
|
74
|
+
export {
|
|
75
|
+
B as changeScroll,
|
|
76
|
+
y as dosSpeed,
|
|
77
|
+
F as drawScroll,
|
|
78
|
+
T as initScroll
|
|
79
|
+
};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { isGif as d, decodeGif as h } from "../formats/gif.js";
|
|
2
|
+
import { isFli as x, parseFli as y, newFliCanvas as k, applyFliFrame as G } from "../formats/fli.js";
|
|
3
|
+
import { textLines as b, parseBackdrop as p, parseSlideList as T } from "../formats/graphicScripts.js";
|
|
4
|
+
import { matchColor as P, PALETTE_SIZE as F } from "../formats/palette.js";
|
|
5
|
+
import { STOCK_LOOK as u } from "./playerLook.js";
|
|
6
|
+
const S = [63, 10, 10], A = [10, 10, 63], U = [63, 63, 0], D = [50, 10, 50], N = (e, t) => P(e, t[0], t[1], t[2]), w = (e) => (/\.[^.]*$/.exec(e)?.[0] ?? "").toLowerCase();
|
|
7
|
+
async function L(e, t, a) {
|
|
8
|
+
if (await e.need(t), w(t) === ".bkd") {
|
|
9
|
+
const s = e.files.get(t);
|
|
10
|
+
s && await e.need(p(s).gif);
|
|
11
|
+
}
|
|
12
|
+
return e.waiting(() => E(e, t, a));
|
|
13
|
+
}
|
|
14
|
+
async function E(e, t, a) {
|
|
15
|
+
e.audio.stopVoc();
|
|
16
|
+
const s = w(t);
|
|
17
|
+
let i = a.pause ?? -1;
|
|
18
|
+
const o = a.look ?? u, n = a.cols ?? new Uint8Array(F);
|
|
19
|
+
let c;
|
|
20
|
+
if (e.onItem?.(s === ".fli" ? "cartoon" : s === ".txt" ? "text" : s === ".lst" ? "slides" : "picture", t), s === ".gif" || s === ".bkd")
|
|
21
|
+
i === -1 && (i = o.seconds(s === ".gif" ? "timing.showGraphic.gif" : "timing.showGraphic.bkd")), e.screen.setPaletteTo(0, 0, 0), K(e, t, n, s === ".bkd") ? (await e.fadeTo(n, o.num("play.fadeSteps")), c = (await e.pauseTimeKey(i))?.ascii) : e.screen.clear();
|
|
22
|
+
else if (s === ".fli")
|
|
23
|
+
i === -1 && (i = o.seconds("timing.showGraphic.fli")), await C(e, t) && (n.set(e.screen.palette), c = (await e.pauseTimeKey(i))?.ascii);
|
|
24
|
+
else if (s === ".txt") {
|
|
25
|
+
i === -1 && (i = o.seconds("timing.showGraphic.txt"));
|
|
26
|
+
const r = a.cols ?? a.gamePalette;
|
|
27
|
+
return R(e, t, o.color(r, "color.select.textPages"), i, a.gamePalette, e.files.get(t), o);
|
|
28
|
+
} else if (s === ".lst") {
|
|
29
|
+
const r = e.files.get(t);
|
|
30
|
+
if (!r) return !0;
|
|
31
|
+
for (const l of T(r))
|
|
32
|
+
if (!await L(e, l.name, { cols: n, pause: l.pause ?? 65535, gamePalette: a.gamePalette, look: o })) return !1;
|
|
33
|
+
}
|
|
34
|
+
return c !== 27;
|
|
35
|
+
}
|
|
36
|
+
function K(e, t, a, s = !1) {
|
|
37
|
+
let i = 0, o = 0, n = t;
|
|
38
|
+
if (s) {
|
|
39
|
+
const r = e.files.get(t);
|
|
40
|
+
if (!r) return !1;
|
|
41
|
+
const l = p(r);
|
|
42
|
+
i = l.x, o = l.y, n = l.gif;
|
|
43
|
+
}
|
|
44
|
+
const c = e.files.get(n);
|
|
45
|
+
if (!c || !d(c)) return !1;
|
|
46
|
+
try {
|
|
47
|
+
const r = h(c);
|
|
48
|
+
return e.screen.drawImage(r.pixels, r.width, r.height, i, o), a.set(r.palette), !0;
|
|
49
|
+
} catch {
|
|
50
|
+
return !1;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function B() {
|
|
54
|
+
return new Promise((e) => {
|
|
55
|
+
const t = new MessageChannel();
|
|
56
|
+
t.port1.onmessage = () => e(), t.port2.postMessage(0);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
async function C(e, t) {
|
|
60
|
+
const a = e.files.get(t);
|
|
61
|
+
if (!a || !x(a)) return !1;
|
|
62
|
+
const s = y(a), i = k(s);
|
|
63
|
+
i.palette.set(e.screen.palette), i.pixels.set(e.screen.pixels.subarray(0, Math.min(i.pixels.length, e.screen.pixels.length)));
|
|
64
|
+
let o = e.now();
|
|
65
|
+
for (let n = 0; n < s.frameCount; n++) {
|
|
66
|
+
if (G(s, n, i) && e.screen.setPalette(i.palette), e.screen.drawImage(i.pixels, s.width, s.height), s.speed === 0) {
|
|
67
|
+
await B(), e.checkAbort();
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
o += s.speed * 1e3 / 70;
|
|
71
|
+
do
|
|
72
|
+
await e.frame();
|
|
73
|
+
while (e.now() < o);
|
|
74
|
+
}
|
|
75
|
+
return !0;
|
|
76
|
+
}
|
|
77
|
+
async function R(e, t, a, s, i, o = e.files.get(t), n = u) {
|
|
78
|
+
const c = e.screen.snapshot(), r = n.color(i, "color.select.textMissing");
|
|
79
|
+
e.flushKeys();
|
|
80
|
+
let l = !1;
|
|
81
|
+
if (!o)
|
|
82
|
+
e.screen.write(40, 80, r, n.text("str.text.missingTitle")), e.screen.write(40, 96, r, n.format("str.text.missingFile", t)), e.screen.write(40, 104, r, n.text("str.text.missingTail"));
|
|
83
|
+
else {
|
|
84
|
+
let f = 5;
|
|
85
|
+
for (const g of b(o)) {
|
|
86
|
+
if (f > 20) {
|
|
87
|
+
if (e.screen.write(224, 168, r, n.text("str.text.more")), (await e.pauseTimeKey(s))?.ascii === 27) {
|
|
88
|
+
l = !0;
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
f = 5, e.screen.restore(c);
|
|
92
|
+
}
|
|
93
|
+
e.screen.write(40, f * 8, a, g), f++;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return l || await e.pauseTimeKey(s), e.screen.restore(c), !l;
|
|
97
|
+
}
|
|
98
|
+
export {
|
|
99
|
+
A as RGB_BLUE,
|
|
100
|
+
D as RGB_PURPLE,
|
|
101
|
+
S as RGB_RED,
|
|
102
|
+
U as RGB_YELLOW,
|
|
103
|
+
R as displayFile,
|
|
104
|
+
N as match,
|
|
105
|
+
C as playFli,
|
|
106
|
+
L as showGraphic
|
|
107
|
+
};
|