@lewismoten/gamemaker-sandbox-engine 0.0.0-stage → 3.1.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/LICENSE +24 -0
- package/NOTICE.md +753 -0
- package/README.md +65 -2
- package/dist/assets/music.worklet-NqOeNo6T.js +464 -0
- package/dist/engine.js +5436 -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 +39 -0
- package/dist/types/audio/music.worklet.d.ts +14 -0
- package/dist/types/audio/opl.d.ts +37 -0
- package/dist/types/audio/output.d.ts +13 -0
- package/dist/types/dosPlayer/fileExtensions.d.ts +44 -0
- package/dist/types/dosPlayer/patchRules.d.ts +24 -0
- package/dist/types/dosPlayer/patchTable.d.ts +80 -0
- package/dist/types/engine/character.d.ts +30 -0
- package/dist/types/engine/funcKeys.d.ts +33 -0
- package/dist/types/engine/game.d.ts +52 -0
- package/dist/types/engine/keys.d.ts +17 -0
- package/dist/types/engine/machine.d.ts +99 -0
- package/dist/types/engine/menus.d.ts +46 -0
- package/dist/types/engine/monsters.d.ts +19 -0
- package/dist/types/engine/package.d.ts +4 -0
- package/dist/types/engine/playGain.d.ts +11 -0
- package/dist/types/engine/playerLook.d.ts +26 -0
- package/dist/types/engine/recorder.d.ts +60 -0
- package/dist/types/engine/render.d.ts +8 -0
- package/dist/types/engine/scene.d.ts +156 -0
- package/dist/types/engine/scroll.d.ts +16 -0
- package/dist/types/engine/showGraphic.d.ts +39 -0
- package/dist/types/engine/slowPc.d.ts +62 -0
- package/dist/types/engine/touch.d.ts +33 -0
- package/dist/types/engine/world.d.ts +215 -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/fli.d.ts +45 -0
- package/dist/types/formats/game.d.ts +72 -0
- package/dist/types/formats/gif.d.ts +15 -0
- package/dist/types/formats/graphicScripts.d.ts +18 -0
- package/dist/types/formats/highscore.d.ts +10 -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/cp437Glyphs.d.ts +2 -0
- package/dist/types/gfx/font8x8.d.ts +2 -0
- package/dist/types/gfx/screen.d.ts +46 -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/project/gameFiles.d.ts +49 -0
- package/package.json +26 -4
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export declare class Reader {
|
|
2
|
+
readonly bytes: Uint8Array;
|
|
3
|
+
offset: number;
|
|
4
|
+
constructor(bytes: Uint8Array, offset?: number);
|
|
5
|
+
get length(): number;
|
|
6
|
+
get eof(): boolean;
|
|
7
|
+
skip(n: number): this;
|
|
8
|
+
u8(): number;
|
|
9
|
+
i8(): number;
|
|
10
|
+
u16(): number;
|
|
11
|
+
i16(): number;
|
|
12
|
+
u32(): number;
|
|
13
|
+
i32(): number;
|
|
14
|
+
/** Copies n bytes (zero padded when the source is short). */
|
|
15
|
+
bytesOf(n: number): Uint8Array;
|
|
16
|
+
/** Reads a fixed size, NUL terminated string field. */
|
|
17
|
+
cstr(n: number): string;
|
|
18
|
+
}
|
|
19
|
+
export declare class Writer {
|
|
20
|
+
private buf;
|
|
21
|
+
offset: number;
|
|
22
|
+
constructor(initial?: number);
|
|
23
|
+
private ensure;
|
|
24
|
+
u8(v: number): this;
|
|
25
|
+
i8(v: number): this;
|
|
26
|
+
u16(v: number): this;
|
|
27
|
+
i16(v: number): this;
|
|
28
|
+
u32(v: number): this;
|
|
29
|
+
i32(v: number): this;
|
|
30
|
+
bytes(b: ArrayLike<number>, length?: number): this;
|
|
31
|
+
/** Writes a string into a fixed size NUL padded field (truncated to leave room for the NUL). */
|
|
32
|
+
cstr(s: string, length: number): this;
|
|
33
|
+
/**
|
|
34
|
+
* Writes a fixed size string field. When the text is unchanged the original raw
|
|
35
|
+
* bytes (including any garbage after the NUL) are kept so files round-trip exactly.
|
|
36
|
+
*/
|
|
37
|
+
cstrOver(s: string, original: Uint8Array | undefined, length: number): this;
|
|
38
|
+
toBytes(): Uint8Array;
|
|
39
|
+
}
|
|
40
|
+
/** Decodes a NUL terminated string; the whole array when there is no NUL. */
|
|
41
|
+
export declare function cString(bytes: Uint8Array): string;
|
|
42
|
+
export declare function latin1Text(bytes: Uint8Array): string;
|
|
43
|
+
/** One byte per character (low 8 bits of each UTF-16 code unit). */
|
|
44
|
+
export declare function textBytes(text: string): Uint8Array;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export declare const BLEN = 20;
|
|
2
|
+
export declare const BLOCK_SIZE = 420;
|
|
3
|
+
export declare const BACKBL = 150;
|
|
4
|
+
export declare const MONBL = 100;
|
|
5
|
+
export declare const CHARBL = 50;
|
|
6
|
+
export declare const TRANSPARENT = 255;
|
|
7
|
+
export declare const SOLTOP = 1;
|
|
8
|
+
export declare const SOLRIG = 2;
|
|
9
|
+
export declare const SOLBOT = 4;
|
|
10
|
+
export declare const SOLLEF = 8;
|
|
11
|
+
export type BlockKind = 'bbl' | 'mbl' | 'cbl';
|
|
12
|
+
export declare const BLOCK_COUNTS: Record<BlockKind, number>;
|
|
13
|
+
export interface Block {
|
|
14
|
+
/** 20x20 palette indices, row major (y * 20 + x). 255 is transparent for sprites. */
|
|
15
|
+
pixels: Uint8Array;
|
|
16
|
+
/** Monster number to give birth to (background blocks). */
|
|
17
|
+
birthMon: number;
|
|
18
|
+
/** Clock ticks between monster births; 0 = never. */
|
|
19
|
+
birthTime: number;
|
|
20
|
+
xtra: Uint8Array;
|
|
21
|
+
/** Solid sides: SOLTOP | SOLRIG | SOLBOT | SOLLEF. */
|
|
22
|
+
solid: number;
|
|
23
|
+
/** Sides that hurt (unused by playgame, kept for fidelity). */
|
|
24
|
+
hitpt: number;
|
|
25
|
+
/** Score points when touched. */
|
|
26
|
+
scorePts: number;
|
|
27
|
+
/** Hit points added (negative hurts) when touched. */
|
|
28
|
+
chHitPt: number;
|
|
29
|
+
/** Block this one animates into after ntime ticks (== self means never). */
|
|
30
|
+
nextBl: number;
|
|
31
|
+
ntime: number;
|
|
32
|
+
/** Block this one becomes when touched (== self means unchanged). */
|
|
33
|
+
touchBl: number;
|
|
34
|
+
/** Gravity direction bits: 1 up, 2 right, 4 down, 8 left. */
|
|
35
|
+
grav: number;
|
|
36
|
+
/** Non-zero if the character can pick this block up. */
|
|
37
|
+
obj: number;
|
|
38
|
+
/** Which counter is affected: 1 lives, 3 money, 5..19 sequence counters, 20..29 extra counters. */
|
|
39
|
+
effect: number;
|
|
40
|
+
/** Amount the effect counter changes. */
|
|
41
|
+
eamt: number;
|
|
42
|
+
}
|
|
43
|
+
export declare function emptyBlock(index: number, transparent?: boolean): Block;
|
|
44
|
+
export declare function parseBlocks(bytes: Uint8Array, count: number): Block[];
|
|
45
|
+
export declare function serializeBlocks(blocks: Block[]): Uint8Array;
|
|
46
|
+
export declare function newBlockSet(kind: BlockKind): Block[];
|
|
47
|
+
/**
|
|
48
|
+
* Pixel lookup for a block drawn with one of the 8 orientations used by playgame
|
|
49
|
+
* (rotations/mirrors; see Sdrawspbloc in PLAYGAME.C). Returns the source index for
|
|
50
|
+
* destination (x, y).
|
|
51
|
+
*/
|
|
52
|
+
export declare function orientIndex(orient: number, x: number, y: number): number;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export declare const MAXSEQ = 20;
|
|
2
|
+
export declare const MAXFRAME = 10;
|
|
3
|
+
export declare const MAXINV = 10;
|
|
4
|
+
export declare const METERS: number;
|
|
5
|
+
export declare const INF_REPEAT = 32767;
|
|
6
|
+
export declare const CHR_RECORD_SIZE = 3784;
|
|
7
|
+
export declare const IDLESEQ = 0;
|
|
8
|
+
export declare const DIESEQ = 1;
|
|
9
|
+
export declare const HURTSEQ = 2;
|
|
10
|
+
export declare const PICKUPSEQ = 3;
|
|
11
|
+
export declare const DROPSEQ = 4;
|
|
12
|
+
export declare const SEQUENCE_NAMES: string[];
|
|
13
|
+
export interface Frame {
|
|
14
|
+
/** Pixel offset from the previous frame. */
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
/** Low nibble: orientation of top block. High nibble: orientation of bottom block. */
|
|
18
|
+
orient: number;
|
|
19
|
+
/** Top block number (CHARBL = none). When pic2 == MONBL, pic1 is the monster to give birth to. */
|
|
20
|
+
pic1: number;
|
|
21
|
+
/** Bottom block number. CHARBL+1 marks the end of the sequence. */
|
|
22
|
+
pic2: number;
|
|
23
|
+
/** Clock ticks (1/18.2 s) to wait before the next frame. */
|
|
24
|
+
pause: number;
|
|
25
|
+
extra: Uint8Array;
|
|
26
|
+
}
|
|
27
|
+
export interface Sequence {
|
|
28
|
+
frames: Frame[];
|
|
29
|
+
/** Activation key: high byte = PC scan code, low byte = ASCII. */
|
|
30
|
+
key: number;
|
|
31
|
+
/** Sound effect number (>= 30 means none). */
|
|
32
|
+
sound: number;
|
|
33
|
+
on: number;
|
|
34
|
+
/** Background block required in inventory to use this sequence (150 = none). */
|
|
35
|
+
bloc: number;
|
|
36
|
+
/** Non-zero: sequence cannot be interrupted. */
|
|
37
|
+
ground: number;
|
|
38
|
+
/** Joystick button (0 any, 1/2 button, 4 none). */
|
|
39
|
+
jstkBut: number;
|
|
40
|
+
/** Joystick direction (0 none, 1-8 directions, 9 any). */
|
|
41
|
+
jstkMov: number;
|
|
42
|
+
/** Non-zero: one run per key press. */
|
|
43
|
+
norepeat: number;
|
|
44
|
+
/** Non-zero: motion adds to momentum instead of moving directly. */
|
|
45
|
+
momentum: number;
|
|
46
|
+
xtra: Uint8Array;
|
|
47
|
+
}
|
|
48
|
+
export interface Character {
|
|
49
|
+
sequences: Sequence[];
|
|
50
|
+
x: number[];
|
|
51
|
+
y: number[];
|
|
52
|
+
cframe: number;
|
|
53
|
+
cseq: number;
|
|
54
|
+
inv: Uint8Array;
|
|
55
|
+
/** Repetition counters: 0 hit points, 1 lives, 3 money, 5..19 sequence counters, 20..29 extra. */
|
|
56
|
+
meter: number[];
|
|
57
|
+
/** Raw bytes of the unused second player record. */
|
|
58
|
+
rest: Uint8Array;
|
|
59
|
+
}
|
|
60
|
+
export declare function parseCharacter(bytes: Uint8Array): Character;
|
|
61
|
+
export declare function serializeCharacter(c: Character): Uint8Array;
|
|
62
|
+
export declare function emptyFrame(end?: boolean): Frame;
|
|
63
|
+
export declare function newCharacter(): Character;
|
|
64
|
+
/** Number of frames before the end marker. */
|
|
65
|
+
export declare function frameCount(s: Sequence): number;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export declare const CMF_GAMEMAKER_CLOCK = 146;
|
|
2
|
+
interface CmfFile {
|
|
3
|
+
version: number;
|
|
4
|
+
ticksPerBeat: number;
|
|
5
|
+
/** Ticks per second the song was converted for. */
|
|
6
|
+
clockTicks: number;
|
|
7
|
+
channelUsed: Uint8Array;
|
|
8
|
+
/** 16 byte SBI instrument records. */
|
|
9
|
+
instruments: Uint8Array[];
|
|
10
|
+
basicTempo: number;
|
|
11
|
+
/** The event stream (music block to end of file). */
|
|
12
|
+
music: Uint8Array;
|
|
13
|
+
}
|
|
14
|
+
export declare function isCmf(bytes: Uint8Array): boolean;
|
|
15
|
+
export declare function parseCmf(bytes: Uint8Array): CmfFile;
|
|
16
|
+
/** One event of a song: when (in ticks from the start) and its MIDI bytes. */
|
|
17
|
+
export interface CmfEvent {
|
|
18
|
+
tick: number;
|
|
19
|
+
data: number[];
|
|
20
|
+
}
|
|
21
|
+
interface CmfSong {
|
|
22
|
+
/** 16-byte SBI FM instruments; instrument n starts on MIDI channel n. */
|
|
23
|
+
instruments: Uint8Array[];
|
|
24
|
+
events: CmfEvent[];
|
|
25
|
+
ticksPerBeat?: number;
|
|
26
|
+
basicTempo?: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Writes a Creative Music File at Game-Maker's 146 ticks a second (PLAYGAME refuses any
|
|
30
|
+
* other clock). Events are sorted by tick; the song ends with an end-of-track marker.
|
|
31
|
+
*/
|
|
32
|
+
export declare function encodeCmf(song: CmfSong): Uint8Array;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
interface FliAnimation {
|
|
2
|
+
width: number;
|
|
3
|
+
height: number;
|
|
4
|
+
frameCount: number;
|
|
5
|
+
/** Delay per frame in 1/70 s (FLI) — FLC files are converted from milliseconds. */
|
|
6
|
+
speed: number;
|
|
7
|
+
/** Byte offsets of each frame record. */
|
|
8
|
+
frames: number[];
|
|
9
|
+
bytes: Uint8Array;
|
|
10
|
+
}
|
|
11
|
+
interface FliCanvas {
|
|
12
|
+
pixels: Uint8Array;
|
|
13
|
+
/** 6-bit palette, 768 bytes. */
|
|
14
|
+
palette: Uint8Array;
|
|
15
|
+
}
|
|
16
|
+
export declare function isFli(bytes: Uint8Array): boolean;
|
|
17
|
+
export declare function parseFli(bytes: Uint8Array): FliAnimation;
|
|
18
|
+
export declare function newFliCanvas(anim: FliAnimation): FliCanvas;
|
|
19
|
+
/** Applies frame n to the canvas. Returns true if the palette changed. */
|
|
20
|
+
export declare function applyFliFrame(anim: FliAnimation, n: number, c: FliCanvas): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* The most bytes a chunk (with its 6-byte header) may take. PLAYGAME reads an .FLI through
|
|
23
|
+
* FileRead (code/DRV/FILECLSS.CPP): one buffer of up to 0xFFF0 bytes, 2 bytes smaller each
|
|
24
|
+
* time `new` fails, and FrameHeader::View (code/Image/FLI/FLI.CPP) hands each chunk to its
|
|
25
|
+
* decoder only when the whole chunk fits in that buffer (FileRead::Peek). With a game loaded
|
|
26
|
+
* through XFERPLAY there is less memory, and a 63K chunk drew garbage where a 32.7K one
|
|
27
|
+
* played. 16,000 bytes is under half of that 32.7K, so it fits with a quarter of the 64K
|
|
28
|
+
* buffer PLAYGAME asks for; splitting a full 64,000-pixel frame into bands this size costs a
|
|
29
|
+
* few dozen bytes of headers.
|
|
30
|
+
*/
|
|
31
|
+
export declare const FLI_CHUNK_MAX = 16000;
|
|
32
|
+
/**
|
|
33
|
+
* Writes an Autodesk Animator .FLI (Game-Maker shows 320x200): each frame run-length coded
|
|
34
|
+
* or as the lines that changed, the 6-bit palette in the first frame, and a closing "ring"
|
|
35
|
+
* frame that leads back to the start. No chunk is bigger than FLI_CHUNK_MAX: a bigger frame
|
|
36
|
+
* is split into bands of lines. `speed` is the delay after each frame in 1/70 s.
|
|
37
|
+
*/
|
|
38
|
+
export declare function encodeFli(frames: Uint8Array[], palette: Uint8Array, opts?: {
|
|
39
|
+
width?: number;
|
|
40
|
+
height?: number;
|
|
41
|
+
speed?: number;
|
|
42
|
+
/** A palette per frame (fades, flashes); changes are stored where they happen. */ palettes?: Uint8Array[];
|
|
43
|
+
/** Code runs of a color inside changed spans as run packets too (smaller deltas for drawn art). */ runs?: boolean;
|
|
44
|
+
}): Uint8Array;
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export declare const NOSCENE = 65535;
|
|
2
|
+
export declare const STARTTYPE = 1;
|
|
3
|
+
export declare const ENDTYPE = 2;
|
|
4
|
+
export declare const ADVTYPE = 10;
|
|
5
|
+
export declare const SCENEDESCLEN = 20;
|
|
6
|
+
export declare const SCENEFILES = 20;
|
|
7
|
+
export declare const MAXSCENELINKS = 20;
|
|
8
|
+
export declare const GAM_VERSION = 300;
|
|
9
|
+
/** Scene 0 (title/menu) file slots. */
|
|
10
|
+
export declare const START_FILES: readonly ["Title graphic", "Title song", "Menu graphic", "Menu song", "Storyline graphic", "Storyline song", "Game instructions", "Beginning credits", "High score backdrop", "Load game background", "Save game background", "Demo recording"];
|
|
11
|
+
/** Scene 1 (game over) file slots. */
|
|
12
|
+
export declare const END_FILES: readonly ["Game won graphic", "Game won song", "Game lost graphic", "Game lost song"];
|
|
13
|
+
/** Adventure (level) scene file slots. */
|
|
14
|
+
export declare const ADV_FILES: readonly ["Palette", "Map", "Background block set", "Monsters", "Monster block set", "Character", "Character block set", "Sound set", "Sound Blaster music", "Level intro graphic", "Level exit graphic"];
|
|
15
|
+
export declare const ADV_EXTS: readonly ["pal", "map", "bbl", "mon", "mbl", "chr", "cbl", "snd", "cmf", "graphic", "graphic"];
|
|
16
|
+
export declare const GRAPHIC_EXTS: string[];
|
|
17
|
+
export interface Point {
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
}
|
|
21
|
+
export interface Link {
|
|
22
|
+
/** Scene to go to, NOSCENE = unused. */
|
|
23
|
+
toScene: number;
|
|
24
|
+
/** Map block that triggers the link. */
|
|
25
|
+
from: Point;
|
|
26
|
+
/** Map block where the character starts in the next scene. */
|
|
27
|
+
to: Point;
|
|
28
|
+
}
|
|
29
|
+
interface ScrollInfo {
|
|
30
|
+
/** 0 = no scrolling, 0xFF = scroll when the character nears the edge. */
|
|
31
|
+
up: number;
|
|
32
|
+
down: number;
|
|
33
|
+
left: number;
|
|
34
|
+
right: number;
|
|
35
|
+
style: number;
|
|
36
|
+
xtra: Uint8Array;
|
|
37
|
+
}
|
|
38
|
+
export interface Scene {
|
|
39
|
+
gametype: number;
|
|
40
|
+
/** Position of the scene box in the integrator's world view. */
|
|
41
|
+
pos: Point;
|
|
42
|
+
scroll: ScrollInfo;
|
|
43
|
+
numLinks: number;
|
|
44
|
+
desc: string;
|
|
45
|
+
descRaw?: Uint8Array;
|
|
46
|
+
/** File names by slot ('' = none). */
|
|
47
|
+
files: string[];
|
|
48
|
+
links: Link[];
|
|
49
|
+
}
|
|
50
|
+
export interface Game {
|
|
51
|
+
version: number;
|
|
52
|
+
/** Raw 256 byte header so unknown bytes survive a round trip. */
|
|
53
|
+
header: Uint8Array;
|
|
54
|
+
filesPerScene: number;
|
|
55
|
+
linksPerScene: number;
|
|
56
|
+
scenes: Scene[];
|
|
57
|
+
/** Original string pool, kept to reproduce the file exactly when nothing changed. */
|
|
58
|
+
pool?: Uint8Array;
|
|
59
|
+
poolOffsets?: number[][];
|
|
60
|
+
/** True when the file was converted from the pre-3.00 layout. */
|
|
61
|
+
converted: boolean;
|
|
62
|
+
}
|
|
63
|
+
export declare function emptyLink(): Link;
|
|
64
|
+
export declare function emptyScene(gametype?: number): Scene;
|
|
65
|
+
export declare function defaultHeader(): Uint8Array;
|
|
66
|
+
export declare function newGame(title?: string): Game;
|
|
67
|
+
export declare function parseGame(bytes: Uint8Array): Game;
|
|
68
|
+
export declare function serializeGame(g: Game): Uint8Array;
|
|
69
|
+
export declare function sceneKind(s: Scene): 'start' | 'end' | 'adventure' | 'unused';
|
|
70
|
+
export declare function fileSlotsFor(s: Scene): readonly string[];
|
|
71
|
+
export declare function slotExtensions(s: Scene): readonly string[];
|
|
72
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type Palette } from './palette';
|
|
2
|
+
export interface IndexedImage {
|
|
3
|
+
width: number;
|
|
4
|
+
height: number;
|
|
5
|
+
pixels: Uint8Array;
|
|
6
|
+
palette: Palette;
|
|
7
|
+
}
|
|
8
|
+
export declare function isGif(bytes: Uint8Array): boolean;
|
|
9
|
+
export declare function decodeGif(bytes: Uint8Array): IndexedImage;
|
|
10
|
+
export declare function lzwDecode(data: Uint8Array, minCodeSize: number, pixelCount: number, done?: {
|
|
11
|
+
count: number;
|
|
12
|
+
}): Uint8Array;
|
|
13
|
+
/** Encodes an 8-bit indexed image as GIF87a with a full 256 color table. */
|
|
14
|
+
export declare function encodeGif(img: IndexedImage): Uint8Array;
|
|
15
|
+
export declare function lzwEncode(pixels: Uint8Array, minCodeSize: number): Uint8Array;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface Backdrop {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
gif: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function parseBackdrop(bytes: Uint8Array): Backdrop;
|
|
7
|
+
export declare function serializeBackdrop(b: Backdrop): Uint8Array;
|
|
8
|
+
export interface SlideEntry {
|
|
9
|
+
name: string;
|
|
10
|
+
/** Seconds to wait; undefined = the caller's default. */
|
|
11
|
+
pause?: number;
|
|
12
|
+
}
|
|
13
|
+
/** Port of FileEntry/FileListClass: "name [pause]" per line, names up to 15 chars. */
|
|
14
|
+
export declare function parseSlideList(bytes: Uint8Array): SlideEntry[];
|
|
15
|
+
export declare function serializeSlideList(entries: SlideEntry[]): Uint8Array;
|
|
16
|
+
/** Splits a .txt file into the 31 character lines Display_File shows (fgets with a 32 byte buffer). */
|
|
17
|
+
export declare function textLines(bytes: Uint8Array): string[];
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface HighScore {
|
|
2
|
+
score: number;
|
|
3
|
+
name: string;
|
|
4
|
+
}
|
|
5
|
+
export declare const HIGH_SCORES = 10;
|
|
6
|
+
export declare function parseHighScores(bytes: Uint8Array): HighScore[];
|
|
7
|
+
export declare function serializeHighScores(list: HighScore[]): Uint8Array;
|
|
8
|
+
/** Port of CheckHighScores' ranking: returns the 0-based place, or -1 if not in the top ten. */
|
|
9
|
+
export declare function placeFor(list: HighScore[], score: number): number;
|
|
10
|
+
export declare function insertHighScore(list: HighScore[], place: number, entry: HighScore): HighScore[];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare const MLEN = 100;
|
|
2
|
+
export declare const MWID = 100;
|
|
3
|
+
export declare const LASTMM = 200;
|
|
4
|
+
export interface PlacedMonster {
|
|
5
|
+
/** Monster number in the .mon file; LASTMON (64) or more = empty slot. */
|
|
6
|
+
monnum: number;
|
|
7
|
+
status: number;
|
|
8
|
+
xtra: number;
|
|
9
|
+
curx: number;
|
|
10
|
+
cury: number;
|
|
11
|
+
extra: number;
|
|
12
|
+
}
|
|
13
|
+
export interface GameMap {
|
|
14
|
+
/** Background block per cell (index = y * 100 + x). */
|
|
15
|
+
blocks: Uint8Array;
|
|
16
|
+
/** Placed monster index per cell (LASTMM = none). */
|
|
17
|
+
mons: Uint8Array;
|
|
18
|
+
monsters: PlacedMonster[];
|
|
19
|
+
}
|
|
20
|
+
export declare function parseMap(bytes: Uint8Array): GameMap;
|
|
21
|
+
export declare function serializeMap(m: GameMap): Uint8Array;
|
|
22
|
+
export declare function newMap(): GameMap;
|
|
23
|
+
/** Rebuilds the per-cell monster index from the placed monster list (as the map editor does). */
|
|
24
|
+
export declare function reindexMonsters(m: GameMap): void;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export declare const LASTMON = 64;
|
|
2
|
+
export declare const LASTSL = 20;
|
|
3
|
+
export declare const MAXMARCH = 10;
|
|
4
|
+
export declare const MONSTER_SIZE = 300;
|
|
5
|
+
export declare const NORMALMOVEMENT = 0;
|
|
6
|
+
export declare const ATTACKMOVEMENT = 1;
|
|
7
|
+
export interface March {
|
|
8
|
+
/** Block offset from the previous corner (first corner: from the start). */
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
/** Speed (pixels per tick) to move toward this corner; 0 ends the path. */
|
|
12
|
+
pic: number;
|
|
13
|
+
/** Picture orientation (0-7) while moving to this corner. */
|
|
14
|
+
orient: number;
|
|
15
|
+
}
|
|
16
|
+
export interface Monster {
|
|
17
|
+
used: number;
|
|
18
|
+
/** Non-zero: monster is not affected by gravity (unused by playgame). */
|
|
19
|
+
fly: number;
|
|
20
|
+
jump: number;
|
|
21
|
+
stick: number;
|
|
22
|
+
/** Higher power kills lower power; >= 100 (CHARPOWER) can't be killed by touching the character. */
|
|
23
|
+
power: number;
|
|
24
|
+
/** Non-zero: monster stops at solid blocks. */
|
|
25
|
+
thru: number;
|
|
26
|
+
/** Animation: [block number (>= 100 ends), ticks to show] x 21. */
|
|
27
|
+
pic: [number, number][];
|
|
28
|
+
lasttime: number;
|
|
29
|
+
/** Monster this becomes when it dies (64 = none). */
|
|
30
|
+
newmon: number;
|
|
31
|
+
/** Score bonus when killed by the character's weapons. */
|
|
32
|
+
upscore: number;
|
|
33
|
+
xtra: Uint8Array;
|
|
34
|
+
/** 0 no attack path, 1 attack path is absolute, 2 relative to the character. */
|
|
35
|
+
activate: number;
|
|
36
|
+
/** -2 never dies, -1 dies after path, 0 dies when killed, > 0 lifetime in ticks. */
|
|
37
|
+
end: number;
|
|
38
|
+
/** 0 follow path, 1..63 toward the character at this speed (negative: away), >= 64 random (speed = towards >> 6). */
|
|
39
|
+
towards: number;
|
|
40
|
+
close: [number, number];
|
|
41
|
+
/** [normal path, attack path], 10 corners each. */
|
|
42
|
+
march: [March[], March[]];
|
|
43
|
+
cur: March;
|
|
44
|
+
}
|
|
45
|
+
export declare function parseMonsters(bytes: Uint8Array): Monster[];
|
|
46
|
+
export declare function serializeMonsters(mons: Monster[]): Uint8Array;
|
|
47
|
+
export declare function emptyMonster(): Monster;
|
|
48
|
+
export declare function newMonsterSet(): Monster[];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const PALETTE_SIZE: number;
|
|
2
|
+
export type Palette = Uint8Array;
|
|
3
|
+
export declare function parsePalette(bytes: Uint8Array): Palette;
|
|
4
|
+
export declare function serializePalette(pal: Palette): Uint8Array;
|
|
5
|
+
/** Expands 6-bit VGA components to packed 0xAABBGGRR values for ImageData/Uint32Array. */
|
|
6
|
+
export declare function paletteToRGBA(pal: Palette): Uint32Array;
|
|
7
|
+
export declare function vga8(v: number): number;
|
|
8
|
+
export declare function paletteCss(pal: Palette, index: number): string;
|
|
9
|
+
/**
|
|
10
|
+
* Port of RGBdata::Match: the palette index whose color is closest to (r,g,b)
|
|
11
|
+
* (6-bit components), by squared distance; first match wins ties.
|
|
12
|
+
*/
|
|
13
|
+
export declare function matchColor(pal: Palette, r: number, g: number, b: number): number;
|
|
14
|
+
/** Default palette GameMaker editors start with: a rainbow ramp plus grays (port of RainbowCols-ish). */
|
|
15
|
+
export declare function defaultPalette(): Palette;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const LASTSND = 30;
|
|
2
|
+
export declare const NUMFREQ = 36;
|
|
3
|
+
export declare const SOUND_NAMES: string[];
|
|
4
|
+
export interface SoundSet {
|
|
5
|
+
/** freqs[n] has NUMFREQ frequencies in Hz (0 = silence). */
|
|
6
|
+
freqs: Uint16Array[];
|
|
7
|
+
/** Digital .voc file name (without extension) for each effect, '' = use PC speaker. */
|
|
8
|
+
digital: string[];
|
|
9
|
+
digitalRaw: Uint8Array[];
|
|
10
|
+
}
|
|
11
|
+
export declare function parseSoundSet(bytes: Uint8Array): SoundSet;
|
|
12
|
+
export declare function serializeSoundSet(s: SoundSet): Uint8Array;
|
|
13
|
+
export declare function newSoundSet(): SoundSet;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface DecodedVoc {
|
|
2
|
+
sampleRate: number;
|
|
3
|
+
samples: Float32Array;
|
|
4
|
+
}
|
|
5
|
+
export declare function isVoc(bytes: Uint8Array): boolean;
|
|
6
|
+
export declare function decodeVoc(bytes: Uint8Array): DecodedVoc;
|
|
7
|
+
/**
|
|
8
|
+
* Encodes mono samples (-1..1) as an 8-bit unsigned PCM Creative Voice File, the kind a
|
|
9
|
+
* Sound Blaster plays. The rate is stored as a time constant, so it is rounded the way
|
|
10
|
+
* the card did (11025 Hz is stored as 10,989 Hz: time constant 165, 1,000,000 / 91).
|
|
11
|
+
*/
|
|
12
|
+
export declare function encodeVoc(samples: Float32Array, sampleRate?: number): Uint8Array;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export declare const SIZEX = 320;
|
|
2
|
+
export declare const SIZEY = 200;
|
|
3
|
+
export declare class Screen {
|
|
4
|
+
readonly pixels: Uint8Array<ArrayBuffer>;
|
|
5
|
+
/** Palette currently shown by the "DAC" (6-bit components). */
|
|
6
|
+
readonly palette: Uint8Array<ArrayBuffer>;
|
|
7
|
+
readonly canvas: HTMLCanvasElement;
|
|
8
|
+
private ctx;
|
|
9
|
+
private image;
|
|
10
|
+
private rgba;
|
|
11
|
+
private lut;
|
|
12
|
+
private dirty;
|
|
13
|
+
constructor(canvas: HTMLCanvasElement);
|
|
14
|
+
setPalette(pal: ArrayLike<number>): void;
|
|
15
|
+
/** SetAllPalTo: every entry the same color. */
|
|
16
|
+
setPaletteTo(r: number, g: number, b: number): void;
|
|
17
|
+
setColor(index: number, r: number, g: number, b: number): void;
|
|
18
|
+
private updateLut;
|
|
19
|
+
markDirty(): void;
|
|
20
|
+
present(): void;
|
|
21
|
+
clear(col?: number): void;
|
|
22
|
+
point(x: number, y: number, col: number): void;
|
|
23
|
+
getCol(x: number, y: number): number;
|
|
24
|
+
/** BoxFill: inclusive corners. */
|
|
25
|
+
boxFill(x: number, y: number, x1: number, y1: number, col: number): void;
|
|
26
|
+
/** Box: rectangle outline. */
|
|
27
|
+
box(x: number, y: number, x1: number, y1: number, col: number): void;
|
|
28
|
+
line(x0: number, y0: number, x1: number, y1: number, col: number): void;
|
|
29
|
+
/**
|
|
30
|
+
* GPutChar: transparent background, 8x8 glyph from the BIOS font (GetROMFont). That ROM font
|
|
31
|
+
* holds only characters 0-127, and GPutChar takes a signed char (code/GM/GRAPHC.C), so 128-255
|
|
32
|
+
* read whatever lies before the font: scribbles on a real VGA card. They draw nothing here.
|
|
33
|
+
* (Text read from a file with TextDecoder('latin1') brings 0x80-0x9F as code points above 255.)
|
|
34
|
+
*/
|
|
35
|
+
putChar(x: number, y: number, col: number, code: number): void;
|
|
36
|
+
/** GWrite: '\n' moves to the next line at the starting column. */
|
|
37
|
+
write(x: number, y: number, col: number, text: string): void;
|
|
38
|
+
/** drawblk / BufDrawBlk: opaque 20x20 block, clipped. */
|
|
39
|
+
drawBlock(x: number, y: number, pixels: Uint8Array): void;
|
|
40
|
+
/** BufDrawSpBlk: transparent (255) sprite with one of 8 orientations, clipped. */
|
|
41
|
+
drawSprite(x: number, y: number, orient: number, pixels: Uint8Array): void;
|
|
42
|
+
/** Copies an indexed image (e.g. a GIF) with its top-left at (-sx, -sy). */
|
|
43
|
+
drawImage(pixels: Uint8Array, width: number, height: number, sx?: number, sy?: number): void;
|
|
44
|
+
snapshot(): Uint8Array;
|
|
45
|
+
restore(snap: Uint8Array): void;
|
|
46
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** The DOM key codes of the four arrow keys (the keypad's own 8 4 6 2 never chord). */
|
|
2
|
+
export declare const ARROW_CODES: Record<string, number>;
|
|
3
|
+
/**
|
|
4
|
+
* Turns the arrow keys physically held into the keys the game should see held.
|
|
5
|
+
* `bound` says whether the game uses a key; chords whose key it doesn't use stay plain arrows.
|
|
6
|
+
*/
|
|
7
|
+
export declare function chordKeys(held: ReadonlySet<number>, bound: (scan: number) => boolean): Set<number>;
|
|
8
|
+
/**
|
|
9
|
+
* Tracks the arrows held and the keys the game was told about, and returns the scan code
|
|
10
|
+
* events (bit 7 set = released) that take the game from what it saw to what it should see.
|
|
11
|
+
* Releases come before presses, so the game never sees a chord and its arrows held at once.
|
|
12
|
+
*/
|
|
13
|
+
export declare class ArrowChords {
|
|
14
|
+
bound: (scan: number) => boolean;
|
|
15
|
+
private held;
|
|
16
|
+
private shown;
|
|
17
|
+
constructor(bound?: (scan: number) => boolean);
|
|
18
|
+
/** An arrow key went down or up; returns the events for the game. */
|
|
19
|
+
arrow(scan: number, pressed: boolean): number[];
|
|
20
|
+
/** Forgets everything (focus lost: the keyboard lets go of every key). */
|
|
21
|
+
reset(): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** dx, dy in 320x200 screen pixels (fractions allowed); buttons: 1 = left, 2 = right. */
|
|
2
|
+
type DeskMouseListener = (dx: number, dy: number, buttons: number) => void;
|
|
3
|
+
/** Listens to the desk mouse; returns the function that stops listening. */
|
|
4
|
+
export declare function listenDeskMouse(f: DeskMouseListener): () => void;
|
|
5
|
+
/** The desk mouse rolled by (dx, dy) screen pixels with these buttons down. */
|
|
6
|
+
export declare function deskMouse(dx: number, dy: number, buttons: number): void;
|
|
7
|
+
/** Moves a pointer by whole pixels, keeping the fractions for next time. */
|
|
8
|
+
export declare class Mickeys {
|
|
9
|
+
private rx;
|
|
10
|
+
private ry;
|
|
11
|
+
/** Whole pixels to move now for a roll of (dx, dy). */
|
|
12
|
+
take(dx: number, dy: number): [number, number];
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ArrowChords } from './chords';
|
|
2
|
+
export interface TypedKey {
|
|
3
|
+
scan: number;
|
|
4
|
+
/** ASCII code (0 for extended keys such as arrows). */
|
|
5
|
+
ascii: number;
|
|
6
|
+
/** The DOM key, for text entry. */
|
|
7
|
+
key: string;
|
|
8
|
+
}
|
|
9
|
+
export declare class Keyboard {
|
|
10
|
+
/** Scan code events; bit 7 set = released. */
|
|
11
|
+
readonly events: number[];
|
|
12
|
+
readonly typed: TypedKey[];
|
|
13
|
+
readonly down: Set<number>;
|
|
14
|
+
private target?;
|
|
15
|
+
private waiters;
|
|
16
|
+
/** Two arrows held together stand for the keypad key between them when the game binds it. */
|
|
17
|
+
readonly chords: ArrowChords;
|
|
18
|
+
/** Which keys the game binds, for arrow chords (none: arrows stay arrows). */
|
|
19
|
+
set chordable(bound: ((scan: number) => boolean) | undefined);
|
|
20
|
+
private onDown;
|
|
21
|
+
private onUp;
|
|
22
|
+
private onBlur;
|
|
23
|
+
attach(target?: EventTarget): void;
|
|
24
|
+
detach(): void;
|
|
25
|
+
private handle;
|
|
26
|
+
/** One scan code event for the game (an arrow chord's press or release). */
|
|
27
|
+
private apply;
|
|
28
|
+
/** Simulates a key event (touch controls, gamepad, demo playback). */
|
|
29
|
+
inject(scan: number, pressed: boolean): void;
|
|
30
|
+
/** Queues a recorded scan code as-is (demo playback while a screen waits for a key). */
|
|
31
|
+
feed(scan: number): void;
|
|
32
|
+
releaseAll(): void;
|
|
33
|
+
/** bioskey(1)/bioskey(0): peek or take the next typed key. */
|
|
34
|
+
peekKey(): TypedKey | undefined;
|
|
35
|
+
readKey(): TypedKey | undefined;
|
|
36
|
+
clear(): void;
|
|
37
|
+
/** Resolves on the next key press. */
|
|
38
|
+
nextPress(): Promise<void>;
|
|
39
|
+
}
|