├── .editorconfig ├── .gitignore ├── Gulpfile.js ├── Gulpfile.json ├── README.md ├── compile ├── minify.bat └── minify.sh ├── data ├── congrat.png ├── control_left.png ├── control_right.png ├── control_sleft.png ├── control_sright.png ├── haf.png ├── sprites.png ├── tiles.png └── title.png ├── include ├── control.js ├── draw.js ├── e_bomb.js ├── e_bullet.js ├── e_rick.js ├── ents.js ├── game.js ├── maps.js ├── rects.js ├── screens.js ├── scroller.js ├── sprites.js ├── system.js └── tiles.js ├── index.html ├── package-lock.json ├── package.json ├── sound ├── bombshht.mp3 ├── bombshht.ogg ├── bombshht.wav ├── bonus.mp3 ├── bonus.ogg ├── bonus.wav ├── box.mp3 ├── box.ogg ├── box.wav ├── bullet.mp3 ├── bullet.ogg ├── bullet.wav ├── crawl.mp3 ├── crawl.ogg ├── crawl.wav ├── die.mp3 ├── die.ogg ├── die.wav ├── ent0.mp3 ├── ent0.ogg ├── ent0.wav ├── ent1.mp3 ├── ent1.ogg ├── ent1.wav ├── ent2.mp3 ├── ent2.ogg ├── ent2.wav ├── ent3.mp3 ├── ent3.ogg ├── ent3.wav ├── ent4.mp3 ├── ent4.ogg ├── ent4.wav ├── ent5.mp3 ├── ent5.ogg ├── ent5.wav ├── ent6.mp3 ├── ent6.ogg ├── ent6.wav ├── ent7.mp3 ├── ent7.ogg ├── ent7.wav ├── ent8.mp3 ├── ent8.ogg ├── ent8.wav ├── explode.mp3 ├── explode.ogg ├── explode.wav ├── gameover.mp3 ├── gameover.ogg ├── gameover.wav ├── jump.mp3 ├── jump.ogg ├── jump.wav ├── pad.mp3 ├── pad.ogg ├── pad.wav ├── sbonus1.mp3 ├── sbonus1.ogg ├── sbonus1.wav ├── sbonus2.mp3 ├── sbonus2.ogg ├── sbonus2.wav ├── stick.mp3 ├── stick.ogg ├── stick.wav ├── tune0.mp3 ├── tune0.ogg ├── tune0.wav ├── tune1.mp3 ├── tune1.ogg ├── tune1.wav ├── tune2.mp3 ├── tune2.ogg ├── tune2.wav ├── tune3.mp3 ├── tune3.ogg ├── tune3.wav ├── tune4.mp3 ├── tune4.ogg ├── tune4.wav ├── tune5.mp3 ├── tune5.ogg ├── tune5.wav ├── walk.mp3 ├── walk.ogg └── walk.wav ├── source ├── control.js ├── dat_ents.js ├── dat_maps.js ├── dat_screens.js ├── dat_spritesST.js ├── draw.js ├── e_bomb.js ├── e_bonus.js ├── e_box.js ├── e_bullet.js ├── e_rick.js ├── e_sbonus.js ├── e_them.js ├── ents.js ├── game.js ├── maps.js ├── rects.js ├── scr_gameover.js ├── scr_getname.js ├── scr_imain.js ├── scr_imap.js ├── scr_pause.js ├── scr_xrick.js ├── screens.js ├── scroller.js ├── sysarg.js ├── sysevt.js ├── syssnd.js ├── system.js ├── sysvid.js ├── template.js ├── tiles.js ├── util.js ├── xrick.debug.js └── xrick.js ├── src ├── c.js ├── control.js ├── dat_ents.js ├── dat_loader.js ├── dat_maps.js ├── dat_picST.js ├── dat_screens.js ├── dat_snd.js ├── dat_spritesST.js ├── dat_tilesST.js ├── draw.js ├── e_bomb.js ├── e_bonus.js ├── e_box.js ├── e_bullet.js ├── e_rick.js ├── e_sbonus.js ├── e_them.js ├── ents.js ├── game.js ├── maps.js ├── rects.js ├── scr_gameover.js ├── scr_getname.js ├── scr_imain.js ├── scr_imap.js ├── scr_pause.js ├── scr_xrick.js ├── scroller.js ├── sysarg.js ├── sysevt.js ├── syssnd.js ├── system.js ├── sysvid.js ├── util.js └── xrick.js └── xrick.html /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | indent_style = tab 3 | indent_size = 2 4 | end_of_line = lf 5 | charset = utf-8 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | 9 | [{*.json,.babelrc,.tern-project}] 10 | indent_style = space 11 | indent_size = 2 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | *sublime* 3 | *.min.* 4 | *.jar 5 | .DS_Store 6 | temp/ 7 | tools/ 8 | compile/old/ 9 | compile/*.js 10 | compile/*.jar 11 | test/ 12 | build/ 13 | TODO.TXT 14 | -------------------------------------------------------------------------------- /Gulpfile.js: -------------------------------------------------------------------------------- 1 | const config = require("./Gulpfile.json"); 2 | 3 | const gulp = require("gulp"); 4 | const webpack = require('webpack-stream'); 5 | var del = require('del'); 6 | 7 | // Tasks 8 | gulp.task("webpack", () => { 9 | return gulp.src("src/xrick.js") 10 | .pipe(webpack({ 11 | mode: "development", 12 | output: { 13 | library: "RickJS", 14 | filename: "xrick.debug.js" 15 | } 16 | })) 17 | .pipe(gulp.dest(config.dir.build)); 18 | }); 19 | 20 | gulp.task('clean', () => { 21 | return del(config.dir.clean); 22 | }); 23 | 24 | gulp.task("build-web", gulp.series("clean", "webpack")); 25 | -------------------------------------------------------------------------------- /Gulpfile.json: -------------------------------------------------------------------------------- 1 | { 2 | "dir": { 3 | "build": "build/", 4 | "clean": [ 5 | "build/" 6 | ] 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | RickJS 2 | ====== 3 | 4 | A JavaScript port of XRick 5 | 6 | Based on xrick - version #021212 7 | 8 | Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net) 9 | Copyright (C) 2012 Chrilith (me@chrilith.com) 10 | 11 | http://www.bigorno.net/xrick/ 12 | http://www.gamalto.com/games/rickjs/ 13 | 14 | 15 | LICENSE AGREEMENT & LEGAL BABLE 16 | =============================== 17 | 18 | From the original author of xrick: 19 | 20 | I have written the xrick code. However, graphics and maps and sounds 21 | are by the authors of the original Rick Dangerous game, and "Rick 22 | Dangerous" remains a trademark of its owner(s) -- maybe Core Design 23 | (who wrote the game) or FireBird (who published it). As of today, I 24 | have not been successful at contacting Core Design. 25 | 26 | This makes it a bit difficult to formally release the whole code, 27 | including data for graphics and maps and sounds, under the terms of 28 | licences such as the GNU General Public Licence. So the code is 29 | released "in the spirit" of the GNU GPL. Whatever that means. 30 | 31 | This program is distributed in the hope that it will be useful, but 32 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 33 | or FITNESS FOR A PARTICULAR PURPOSE. 34 | 35 | 36 | HOWTO 37 | ===== 38 | 39 | Controls: 40 | 41 | - left, right, up (jump) or down (crawl): arrow keys. 42 | - fire: SPACE, pause: P. 43 | - use left, right, up, down + fire to poke something with your stick, 44 | lay a stick of dynamite, or fire a bullet. 45 | 46 | More details at http://www.bigorno.net/xrick/ and http://www.gamalto.com/ 47 | 48 | Report problems, or ask questions, to me@chrilith.com. 49 | 50 | Enjoy! 51 | -------------------------------------------------------------------------------- /compile/minify.bat: -------------------------------------------------------------------------------- 1 | REM DOS Btach script 2 | 3 | REM Minify using Google Closure Compiler 4 | REM https://developers.google.com/closure/compiler/ 5 | 6 | java -jar compiler.jar ^ 7 | --js=../source/Gamalto.js ^ 8 | --js=../source/Compat.js ^ 9 | --js=../source/GObject.js ^ 10 | --js=../source/Extensions.js ^ 11 | --js=../source/Missing.js ^ 12 | ^ 13 | --js=../source/GSectionList.js ^ 14 | --js=../source/GSpriteSheet.js ^ 15 | --js=../source/GAnimation.js ^ 16 | --js=../source/GTileSet.js ^ 17 | --js=../source/GFont.js ^ 18 | --js=../source/GTiming.js ^ 19 | --js=../source/GTimer.js ^ 20 | --js=../source/GVector.js ^ 21 | --js=../source/GRect.js ^ 22 | --js=../source/GSize.js ^ 23 | --js=../source/GSurface.js ^ 24 | --js=../source/GRenderer.js ^ 25 | --js=../source/GScreen.js ^ 26 | --js=../source/GBitmap.js ^ 27 | --js=../source/GBaseLibrary.js ^ 28 | --js=../source/GBitmapLibrary.js ^ 29 | --js=../source/GXMLLibrary.js ^ 30 | --js=../source/GDataLibrary.js ^ 31 | --js=../source/GSequence.js ^ 32 | --js=../source/GState.js ^ 33 | --js=../source/GColor.js ^ 34 | --js=../source/GPattern.js ^ 35 | --js=../source/GEvent.js ^ 36 | --js=../source/GEventManager.js ^ 37 | --js=../source/GKeyboardEvent.js ^ 38 | --js=../source/GEventManager_Keyboard.js ^ 39 | ^ 40 | --js_output_file=gamalto.min.js REM ^ 41 | REM --summary_detail_level=3 ^ 42 | REM --warning_level=VERBOSE 43 | -------------------------------------------------------------------------------- /compile/minify.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Minify using Google Closure Compiler 4 | # https://developers.google.com/closure/compiler/ 5 | 6 | java -jar compiler.jar \ 7 | --js=../source/xrick.js \ 8 | --js=../source/system.js \ 9 | --js=../source/sysarg.js \ 10 | --js=../source/sysvid.js \ 11 | --js=../source/sysevt.js \ 12 | --js=../source/syssnd.js \ 13 | --js=../source/game.js \ 14 | --js=../source/draw.js \ 15 | --js=../source/maps.js \ 16 | --js=../source/control.js \ 17 | --js=../source/screens.js \ 18 | --js=../source/scr_gameover.js \ 19 | --js=../source/scr_getname.js \ 20 | --js=../source/scr_xrick.js \ 21 | --js=../source/scr_imain.js \ 22 | --js=../source/scr_imap.js \ 23 | --js=../source/scr_pause.js \ 24 | --js=../source/dat_maps.js \ 25 | --js=../source/dat_screens.js \ 26 | --js=../source/dat_spritesST.js \ 27 | --js=../source/dat_ents.js \ 28 | --js=../source/e_rick.js \ 29 | --js=../source/e_sbonus.js \ 30 | --js=../source/e_bomb.js \ 31 | --js=../source/e_bonus.js \ 32 | --js=../source/e_box.js \ 33 | --js=../source/e_them.js \ 34 | --js=../source/e_bullet.js \ 35 | --js=../source/ents.js \ 36 | --js=../source/rects.js \ 37 | --js=../source/scroller.js \ 38 | --js=../source/tiles.js \ 39 | --js=../source/util.js \ 40 | \ 41 | --language_in=ECMASCRIPT5 \ 42 | --js_output_file=xrick.min.js #\ 43 | 44 | # --summary_detail_level=3 \ 45 | # --warning_level=VERBOSE 46 | -------------------------------------------------------------------------------- /data/congrat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/data/congrat.png -------------------------------------------------------------------------------- /data/control_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/data/control_left.png -------------------------------------------------------------------------------- /data/control_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/data/control_right.png -------------------------------------------------------------------------------- /data/control_sleft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/data/control_sleft.png -------------------------------------------------------------------------------- /data/control_sright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/data/control_sright.png -------------------------------------------------------------------------------- /data/haf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/data/haf.png -------------------------------------------------------------------------------- /data/sprites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/data/sprites.png -------------------------------------------------------------------------------- /data/tiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/data/tiles.png -------------------------------------------------------------------------------- /data/title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/data/title.png -------------------------------------------------------------------------------- /include/control.js: -------------------------------------------------------------------------------- 1 | export const CONTROL_UP = 0x08; 2 | export const CONTROL_DOWN = 0x04; 3 | export const CONTROL_LEFT = 0x02; 4 | export const CONTROL_RIGHT = 0x01; 5 | export const CONTROL_PAUSE = 0x80; 6 | export const CONTROL_END = 0x40; 7 | export const CONTROL_EXIT = 0x20; 8 | export const CONTROL_FIRE = 0x10; 9 | 10 | -------------------------------------------------------------------------------- /include/draw.js: -------------------------------------------------------------------------------- 1 | /* map coordinates of the screen */ 2 | export const DRAW_XYMAP_SCRLEFT = (-0x0020); 3 | export const DRAW_XYMAP_SCRTOP = (0x0040); 4 | /* map coordinates of the top of the hidden bottom of the map */ 5 | export const DRAW_XYMAP_HBTOP = (0x0100); 6 | -------------------------------------------------------------------------------- /include/e_bomb.js: -------------------------------------------------------------------------------- 1 | import { ent } from "./ents"; 2 | 3 | const E_BOMB_NO = 3; 4 | export function E_BOMB_ENT() { return ent.ents[E_BOMB_NO]; } 5 | export const E_BOMB_TICKER = (0x2D); 6 | -------------------------------------------------------------------------------- /include/e_bullet.js: -------------------------------------------------------------------------------- 1 | import { ent } from "./ents"; 2 | 3 | export const E_BULLET_NO = 2; 4 | export function E_BULLET_ENT() { return ent.ents[E_BULLET_NO]; } 5 | -------------------------------------------------------------------------------- /include/e_rick.js: -------------------------------------------------------------------------------- 1 | import { ent } from "./ents"; 2 | 3 | export const E_RICK_NO = 1; 4 | export function E_RICK_ENT() { return ent.ents[E_RICK_NO]; } 5 | 6 | export const e_rick = { 7 | state: 0, 8 | stop_x: 0, stop_y: 0 9 | }; 10 | 11 | export const E_RICK_STSTOP = 0x01; 12 | export const E_RICK_STSHOOT = 0x02; 13 | export const E_RICK_STCLIMB = 0x04; 14 | export const E_RICK_STJUMP = 0x08; 15 | export const E_RICK_STZOMBIE = 0x10; 16 | export const E_RICK_STDEAD = 0x20; 17 | export const E_RICK_STCRAWL = 0x40; 18 | 19 | export function E_RICK_STSET(X) { e_rick.state |= (X) } 20 | export function E_RICK_STRST(X) { e_rick.state &= ~(X) } 21 | export function E_RICK_STTST(X) { return (e_rick.state & (X)) } 22 | -------------------------------------------------------------------------------- /include/ents.js: -------------------------------------------------------------------------------- 1 | /* 2 | * RickJS, a JavaScript port of XRick 3 | * 4 | * This source file is based on the folliwing files: 5 | * - xrick/include/ents.h 6 | * 7 | * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved. 8 | * Copyright (C) 2012-2022 Chrilith (me@chrilith.com). All rights reserved. 9 | * 10 | * The use and distribution terms for this software are contained in the file 11 | * named README, which can be found in the root of this distribution. By 12 | * using this software in any fashion, you are agreeing to be bound by the 13 | * terms of this license. 14 | * 15 | * You must not remove this notice, or any other, from this software. 16 | */ 17 | 18 | import { create_struct } from "../src/c"; 19 | 20 | export function ENT_XRICK() { return ent.ents[1]; } 21 | 22 | export const ENT_ENTSNUM = 0x0c; 23 | 24 | /* 25 | * flags for ent_ents[e].n ("yes" when set) 26 | * 27 | * ENT_LETHAL: is entity lethal? 28 | */ 29 | export const ENT_LETHAL = 0x80; 30 | 31 | /* 32 | * flags for ent_ents[e].flag ("yes" when set) 33 | * 34 | * ENT_FLG_ONCE: should the entity run once only? 35 | * ENT_FLG_STOPRICK: does the entity stops rick (and goes to slot zero)? 36 | * ENT_FLG_LETHALR: is entity lethal when restarting? 37 | * ENT_FLG_LETHALI: is entity initially lethal? 38 | * ENT_FLG_TRIGBOMB: can entity be triggered by a bomb? 39 | * ENT_FLG_TRIGBULLET: can entity be triggered by a bullet? 40 | * ENT_FLG_TRIGSTOP: can entity be triggered by rick stop? 41 | * ENT_FLG_TRIGRICK: can entity be triggered by rick? 42 | */ 43 | export const ENT_FLG_ONCE = 0x01; 44 | export const ENT_FLG_STOPRICK = 0x02; 45 | export const ENT_FLG_LETHALR = 0x04; 46 | export const ENT_FLG_LETHALI = 0x08; 47 | export const ENT_FLG_TRIGBOMB = 0x10; 48 | export const ENT_FLG_TRIGBULLET = 0x20; 49 | export const ENT_FLG_TRIGSTOP = 0x40; 50 | export const ENT_FLG_TRIGRICK = 0x80; 51 | 52 | const struct_ent_t = [ 53 | "n", /* b00 */ 54 | /*U8 b01;*/ /* b01 in ASM code but never used */ 55 | "x", /* b02 - position */ 56 | "y", /* w04 - position */ 57 | "sprite", /* b08 - sprite number */ 58 | /*U16 w0C;*/ /* w0C in ASM code but never used */ 59 | "w", /* b0E - width */ 60 | "h", /* b10 - height */ 61 | "mark", /* w12 - number of the mark that created the entity */ 62 | "flags", /* b14 */ 63 | "trig_x", /* b16 - position of trigger box */ 64 | "trig_y", /* w18 - position of trigger box */ 65 | "xsave", /* b1C */ 66 | "ysave", /* w1E */ 67 | "sprbase", /* w20 */ 68 | "step_no_i", /* w22 */ 69 | "step_no", /* w24 */ 70 | "c1", /* b26 */ 71 | "c2", /* b28 */ 72 | "ylow", /* b2A */ 73 | "offsy", /* w2C */ 74 | "latency", /* b2E */ 75 | "prev_n", /* new */ 76 | "prev_x", /* new */ 77 | "prev_y", /* new */ 78 | "prev_s", /* new */ 79 | "front", /* new */ 80 | "trigsnd" /* new */ 81 | ]; 82 | export function ent_t(...values) { 83 | const base = { 84 | get seq() { return this.c1; }, // e_bonus.c 85 | set seq(x) { this.c1 = x; }, 86 | get cnt() { return this.c1; }, // e_box.c 87 | set cnt(x) { this.c1 = x; }, 88 | get flgclmb() { return this.c1; }, // e_them.c 89 | set flgclmb(x) { this.c1 = x; }, 90 | get offsx() { return this.c1; }, // e_them.c 91 | set offsx(x) { this.c1 = x; }, 92 | get sproffs() { return this.c1; }, // e_them.c 93 | set sproffs(x) { this.c1 = x; }, 94 | get step_count() { return this.c2; }, // e_them.c 95 | set step_count(x) { this.c2 = x; }, 96 | get offsx2() { return this.c2; }, // e_them.c 97 | set offsx2(x) { this.c2 = x; } 98 | }; 99 | return create_struct(struct_ent_t, values, base); 100 | } 101 | export function ent_t_array(size) { 102 | const values = Array(struct_ent_t.length).fill(0); 103 | const result = Array(size) 104 | for (let i = 0; i < size; i++) { 105 | result[i] = ent_t(...values); 106 | } 107 | return result; 108 | } 109 | 110 | 111 | const struct_entdata_t = [ 112 | "w", "h", 113 | "spr", "sni", 114 | "trig_w", "trig_h", 115 | "snd" 116 | ]; 117 | export function entdata_t(...values) { 118 | return create_struct(struct_entdata_t, values); 119 | } 120 | 121 | const struct_mvstep_t = [ 122 | "count", 123 | "dx", "dy" 124 | ]; 125 | export function mvstep_t(...values) { 126 | return create_struct(struct_mvstep_t, values); 127 | } 128 | 129 | export const ent = { 130 | ents: ent_t_array(ENT_ENTSNUM + 1), 131 | rects: null 132 | }; 133 | -------------------------------------------------------------------------------- /include/game.js: -------------------------------------------------------------------------------- 1 | import { create_struct } from "../src/c"; 2 | 3 | export const LEFT = 1; 4 | export const RIGHT = 0; 5 | 6 | export const GAME_PERIOD = 75 7 | 8 | export const GAME_BOMBS_INIT = 6; 9 | export const GAME_BULLETS_INIT = 6; 10 | 11 | const struct_hscore_t = [ 12 | "score", 13 | "name" 14 | ]; 15 | export function hscore_t(...values) { 16 | return create_struct(struct_hscore_t, values); 17 | } 18 | 19 | //#ifdef ENABLE_SOUND 20 | export const WAV_GAMEOVER = "WAV_GAMEOVER"; 21 | export const WAV_SBONUS2 = "WAV_SBONUS2"; 22 | export const WAV_BULLET = "WAV_BULLET"; 23 | export const WAV_BOMBSHHT = "WAV_BOMBSHHT"; 24 | export const WAV_EXPLODE = "WAV_EXPLODE"; 25 | export const WAV_STICK = "WAV_STICK"; 26 | export const WAV_WALK = "WAV_WALK"; 27 | export const WAV_CRAWL = "WAV_CRAWL"; 28 | export const WAV_JUMP = "WAV_JUMP"; 29 | export const WAV_PAD = "WAV_PAD"; 30 | export const WAV_BOX = "WAV_BOX"; 31 | export const WAV_BONUS = "WAV_BONUS"; 32 | export const WAV_SBONUS1 = "WAV_SBONUS1"; 33 | export const WAV_DIE = "WAV_DIE"; 34 | export const WAV_ENTITY = [0, 1, 2, 3, 4, 5, 6, 7, 8]; 35 | //#endif 36 | -------------------------------------------------------------------------------- /include/maps.js: -------------------------------------------------------------------------------- 1 | import { create_struct } from "../src/c"; 2 | 3 | export const MAP_NBR_MARKS = 0x020B; 4 | 5 | /* 6 | * map row definitions, for three zones : hidden top, screen, hidden bottom 7 | * the three zones compose map_map, which contains the definition of the 8 | * current portion of the submap. 9 | */ 10 | export const MAP_ROW_HTTOP = 0x00; 11 | export const MAP_ROW_HTBOT = 0x07; 12 | export const MAP_ROW_SCRTOP = 0x08; 13 | export const MAP_ROW_SCRBOT = 0x1F; 14 | export const MAP_ROW_HBTOP = 0x20; 15 | export const MAP_ROW_HBBOT = 0x27; 16 | 17 | /* 18 | * main maps 19 | */ 20 | const struct_map_t = [ 21 | "x", "y", /* initial position for rick */ 22 | "row", /* initial map_map top row within the submap */ 23 | "submap", /* initial submap */ 24 | "tune" /* map tune */ 25 | ]; 26 | export function map_t(...values) { 27 | return create_struct(struct_map_t, values); 28 | } 29 | 30 | /* 31 | * sub maps 32 | */ 33 | const struct_submap_t = [ 34 | "page", /* tiles page */ 35 | "bnum", /* first block number */ 36 | "connect", /* first connection */ 37 | "mark" /* first entity mark */ 38 | ]; 39 | export function submap_t(...values) { 40 | return create_struct(struct_submap_t, values); 41 | } 42 | 43 | /* 44 | * connections 45 | */ 46 | const struct_connect_t = [ 47 | "dir", 48 | "rowout", 49 | "submap", 50 | "rowin" 51 | ]; 52 | export function connect_t(...values) { 53 | return create_struct(struct_connect_t, values); 54 | } 55 | 56 | /* 57 | * blocks - one block is 4 by 4 tiles. 58 | */ 59 | // typedef U8 block_t[0x10]; 60 | export function block_t(...values) { 61 | return values; 62 | } 63 | 64 | /* 65 | * flags for map_marks[].ent ("yes" when set) 66 | * 67 | * MAP_MARK_NACT: this mark is not active anymore. 68 | */ 69 | export const MAP_MARK_NACT = (0x80); 70 | 71 | /* 72 | * mark structure 73 | */ 74 | const struct_mark_t = [ 75 | "row", 76 | "ent", 77 | "flags", 78 | "xy", /* bits XXXX XYYY (from b03) with X->x, Y->y */ 79 | "lt" /* bits XXXX XNNN (from b04) with X->trig_x, NNN->lat & trig_y */ 80 | ]; 81 | export function mark_t(...values) { 82 | return create_struct(struct_mark_t, values); 83 | } 84 | 85 | /* 86 | * flags for map_eflg[map_map[row][col]] ("yes" when set) 87 | * 88 | * MAP_EFLG_VERT: vertical move only (usually on top of _CLIMB). 89 | * MAP_EFLG_SOLID: solid block, can't go through. 90 | * MAP_EFLG_SPAD: super pad. can't go through, but sends entities to the sky. 91 | * MAP_EFLG_WAYUP: solid block, can't go through except when going up. 92 | * MAP_EFLG_FGND: foreground (hides entities). 93 | * MAP_EFLG_LETHAL: lethal (kill entities). 94 | * MAP_EFLG_CLIMB: entities can climb here. 95 | * MAP_EFLG_01: 96 | */ 97 | export const MAP_EFLG_VERT = (0x80); 98 | export const MAP_EFLG_SOLID = (0x40); 99 | export const MAP_EFLG_SPAD = (0x20); 100 | export const MAP_EFLG_WAYUP = (0x10); 101 | export const MAP_EFLG_FGND = (0x08); 102 | export const MAP_EFLG_LETHAL = (0x04); 103 | export const MAP_EFLG_CLIMB = (0x02); 104 | export const MAP_EFLG_01 = (0x01); 105 | -------------------------------------------------------------------------------- /include/rects.js: -------------------------------------------------------------------------------- 1 | 2 | import { create_struct } from "../src/c"; 3 | 4 | const struct_rect_t = [ 5 | "x", "y", 6 | "width", "height", 7 | "next" 8 | ]; 9 | export function rect_t(...values) { 10 | return create_struct(struct_rect_t, values); 11 | } 12 | -------------------------------------------------------------------------------- /include/screens.js: -------------------------------------------------------------------------------- 1 | import { create_struct } from "../src/c"; 2 | 3 | export const SCREEN_TIMEOUT = 4000; 4 | export const SCREEN_RUNNING = 0; 5 | export const SCREEN_DONE = 1; 6 | export const SCREEN_EXIT = 2; 7 | 8 | const struct_screen_imapsteps_t = [ 9 | "count", /* number of loops */ 10 | "dx", "dy", /* sprite x and y deltas */ 11 | "base" /* base for sprite numbers table */ 12 | ]; /* description of one step */ 13 | export function screen_imapsteps_t(...values) { 14 | return create_struct(struct_screen_imapsteps_t, values); 15 | } 16 | -------------------------------------------------------------------------------- /include/scroller.js: -------------------------------------------------------------------------------- 1 | export const SCROLL_RUNNING = 1; 2 | export const SCROLL_DONE = 0; 3 | 4 | export const SCROLL_PERIOD = 24; 5 | -------------------------------------------------------------------------------- /include/sprites.js: -------------------------------------------------------------------------------- 1 | //#ifdef GFXST 2 | 3 | export const SPRITES_NBR_SPRITES = (0xD5); 4 | 5 | //#endif 6 | -------------------------------------------------------------------------------- /include/system.js: -------------------------------------------------------------------------------- 1 | /* 2 | * video section 3 | */ 4 | export const SYSVID_WIDTH = 320; 5 | export const SYSVID_HEIGHT = 200; 6 | 7 | /* 8 | * args section 9 | */ 10 | -------------------------------------------------------------------------------- /include/tiles.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * three special tile numbers 4 | */ 5 | export const TILES_BULLET = 0x01; 6 | export const TILES_BOMB = 0x02; 7 | export const TILES_RICK = 0x03; 8 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | RickJS, a JavaScript port of XRick using HTML5 7 | 28 | 29 | 54 | 55 | 56 |
57 |
58 |
RickJS, based on xrick by BigOrno
59 | Powered by Gamalto 60 |
61 |
62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "del": "^6.1.1", 4 | "gulp": "^4.0.2", 5 | "webpack-stream": "^7.0.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /sound/bombshht.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/bombshht.mp3 -------------------------------------------------------------------------------- /sound/bombshht.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/bombshht.ogg -------------------------------------------------------------------------------- /sound/bombshht.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/bombshht.wav -------------------------------------------------------------------------------- /sound/bonus.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/bonus.mp3 -------------------------------------------------------------------------------- /sound/bonus.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/bonus.ogg -------------------------------------------------------------------------------- /sound/bonus.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/bonus.wav -------------------------------------------------------------------------------- /sound/box.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/box.mp3 -------------------------------------------------------------------------------- /sound/box.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/box.ogg -------------------------------------------------------------------------------- /sound/box.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/box.wav -------------------------------------------------------------------------------- /sound/bullet.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/bullet.mp3 -------------------------------------------------------------------------------- /sound/bullet.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/bullet.ogg -------------------------------------------------------------------------------- /sound/bullet.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/bullet.wav -------------------------------------------------------------------------------- /sound/crawl.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/crawl.mp3 -------------------------------------------------------------------------------- /sound/crawl.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/crawl.ogg -------------------------------------------------------------------------------- /sound/crawl.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/crawl.wav -------------------------------------------------------------------------------- /sound/die.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/die.mp3 -------------------------------------------------------------------------------- /sound/die.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/die.ogg -------------------------------------------------------------------------------- /sound/die.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/die.wav -------------------------------------------------------------------------------- /sound/ent0.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent0.mp3 -------------------------------------------------------------------------------- /sound/ent0.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent0.ogg -------------------------------------------------------------------------------- /sound/ent0.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent0.wav -------------------------------------------------------------------------------- /sound/ent1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent1.mp3 -------------------------------------------------------------------------------- /sound/ent1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent1.ogg -------------------------------------------------------------------------------- /sound/ent1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent1.wav -------------------------------------------------------------------------------- /sound/ent2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent2.mp3 -------------------------------------------------------------------------------- /sound/ent2.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent2.ogg -------------------------------------------------------------------------------- /sound/ent2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent2.wav -------------------------------------------------------------------------------- /sound/ent3.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent3.mp3 -------------------------------------------------------------------------------- /sound/ent3.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent3.ogg -------------------------------------------------------------------------------- /sound/ent3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent3.wav -------------------------------------------------------------------------------- /sound/ent4.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent4.mp3 -------------------------------------------------------------------------------- /sound/ent4.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent4.ogg -------------------------------------------------------------------------------- /sound/ent4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent4.wav -------------------------------------------------------------------------------- /sound/ent5.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent5.mp3 -------------------------------------------------------------------------------- /sound/ent5.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent5.ogg -------------------------------------------------------------------------------- /sound/ent5.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent5.wav -------------------------------------------------------------------------------- /sound/ent6.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent6.mp3 -------------------------------------------------------------------------------- /sound/ent6.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent6.ogg -------------------------------------------------------------------------------- /sound/ent6.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent6.wav -------------------------------------------------------------------------------- /sound/ent7.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent7.mp3 -------------------------------------------------------------------------------- /sound/ent7.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent7.ogg -------------------------------------------------------------------------------- /sound/ent7.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent7.wav -------------------------------------------------------------------------------- /sound/ent8.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent8.mp3 -------------------------------------------------------------------------------- /sound/ent8.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent8.ogg -------------------------------------------------------------------------------- /sound/ent8.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/ent8.wav -------------------------------------------------------------------------------- /sound/explode.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/explode.mp3 -------------------------------------------------------------------------------- /sound/explode.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/explode.ogg -------------------------------------------------------------------------------- /sound/explode.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/explode.wav -------------------------------------------------------------------------------- /sound/gameover.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/gameover.mp3 -------------------------------------------------------------------------------- /sound/gameover.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/gameover.ogg -------------------------------------------------------------------------------- /sound/gameover.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/gameover.wav -------------------------------------------------------------------------------- /sound/jump.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/jump.mp3 -------------------------------------------------------------------------------- /sound/jump.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/jump.ogg -------------------------------------------------------------------------------- /sound/jump.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/jump.wav -------------------------------------------------------------------------------- /sound/pad.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/pad.mp3 -------------------------------------------------------------------------------- /sound/pad.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/pad.ogg -------------------------------------------------------------------------------- /sound/pad.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/pad.wav -------------------------------------------------------------------------------- /sound/sbonus1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/sbonus1.mp3 -------------------------------------------------------------------------------- /sound/sbonus1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/sbonus1.ogg -------------------------------------------------------------------------------- /sound/sbonus1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/sbonus1.wav -------------------------------------------------------------------------------- /sound/sbonus2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/sbonus2.mp3 -------------------------------------------------------------------------------- /sound/sbonus2.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/sbonus2.ogg -------------------------------------------------------------------------------- /sound/sbonus2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/sbonus2.wav -------------------------------------------------------------------------------- /sound/stick.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/stick.mp3 -------------------------------------------------------------------------------- /sound/stick.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/stick.ogg -------------------------------------------------------------------------------- /sound/stick.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/stick.wav -------------------------------------------------------------------------------- /sound/tune0.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune0.mp3 -------------------------------------------------------------------------------- /sound/tune0.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune0.ogg -------------------------------------------------------------------------------- /sound/tune0.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune0.wav -------------------------------------------------------------------------------- /sound/tune1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune1.mp3 -------------------------------------------------------------------------------- /sound/tune1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune1.ogg -------------------------------------------------------------------------------- /sound/tune1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune1.wav -------------------------------------------------------------------------------- /sound/tune2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune2.mp3 -------------------------------------------------------------------------------- /sound/tune2.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune2.ogg -------------------------------------------------------------------------------- /sound/tune2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune2.wav -------------------------------------------------------------------------------- /sound/tune3.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune3.mp3 -------------------------------------------------------------------------------- /sound/tune3.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune3.ogg -------------------------------------------------------------------------------- /sound/tune3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune3.wav -------------------------------------------------------------------------------- /sound/tune4.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune4.mp3 -------------------------------------------------------------------------------- /sound/tune4.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune4.ogg -------------------------------------------------------------------------------- /sound/tune4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune4.wav -------------------------------------------------------------------------------- /sound/tune5.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune5.mp3 -------------------------------------------------------------------------------- /sound/tune5.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune5.ogg -------------------------------------------------------------------------------- /sound/tune5.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/tune5.wav -------------------------------------------------------------------------------- /sound/walk.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/walk.mp3 -------------------------------------------------------------------------------- /sound/walk.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/walk.ogg -------------------------------------------------------------------------------- /sound/walk.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrilith/RickJS/79172693588a93946b2843f838fa49c7723eb854/sound/walk.wav -------------------------------------------------------------------------------- /source/control.js: -------------------------------------------------------------------------------- 1 | /* 2 | * RickJS, a JavaScript port of XRick 3 | * 4 | * This source file is based on the folliwing files: 5 | * - xrick/src/control.c 6 | * - xrick/src/control.h 7 | * 8 | * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved. 9 | * Copyright (C) 2012 Chrilith (me@chrilith.com). All rights reserved. 10 | * 11 | * The use and distribution terms for this software are contained in the file 12 | * named README, which can be found in the root of this distribution. By 13 | * using this software in any fashion, you are agreeing to be bound by the 14 | * terms of this license. 15 | * 16 | * You must not remove this notice, or any other, from this software. 17 | */ 18 | 19 | /* 20 | * constants 21 | */ 22 | var CONTROL_UP = 0x08, 23 | CONTROL_DOWN = 0x04, 24 | CONTROL_LEFT = 0x02, 25 | CONTROL_RIGHT = 0x01, 26 | CONTROL_PAUSE = 0x80, 27 | CONTROL_END = 0x40, 28 | CONTROL_EXIT = 0x20, 29 | CONTROL_FIRE = 0x10; 30 | 31 | (function() { 32 | 33 | Control.status = 0; 34 | Control.last = 0; 35 | Control.active = true; 36 | 37 | /* EOF */ 38 | })(); 39 | -------------------------------------------------------------------------------- /source/dat_screens.js: -------------------------------------------------------------------------------- 1 | /* 2 | * RickJS, a JavaScript port of XRick 3 | * 4 | * This source file is based on the folliwing files: 5 | * - xrick/src/control.c 6 | * - xrick/src/control.h 7 | * 8 | * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved. 9 | * Copyright (C) 2012 Chrilith (me@chrilith.com). All rights reserved. 10 | * 11 | * The use and distribution terms for this software are contained in the file 12 | * named README, which can be found in the root of this distribution. By 13 | * using this software in any fashion, you are agreeing to be bound by the 14 | * terms of this license. 15 | * 16 | * You must not remove this notice, or any other, from this software. 17 | */ 18 | 19 | (function() { 20 | /* 21 | * map intro, sprites lists 22 | */ 23 | Screen.imapsl = [ 24 | 0x1b, 0x00, 25 | 0x1c, 0x1d, 0x00, 26 | 0x01, 0x00, 27 | 0x02, 0x03, 0x04, 0x05, 0x06, 0x00, 28 | 0x1e, 0x00, 29 | 0x0d, 0x00, 30 | 0x13, 0x14, 0x00, 31 | 0x1f, 0x00 32 | ]; 33 | 34 | /* 35 | * map intro, steps 36 | */ 37 | /* 38 | typedef struct { 39 | U16 count; // number of loops 40 | U16 dx, dy; // sprite x and y deltas 41 | U16 base; // base for sprite numbers table 42 | } screen_imapsteps_t; // description of one step 43 | */ 44 | Screen.imapsteps = [ 45 | { count: 0x0000, dx: 0x0002, dy: 0x0002, base: 0x0000 }, 46 | 47 | { count: 0x000b, dx: 0x0000, dy: 0x0001, base: 0x0000 }, 48 | { count: 0x0008, dx: 0x0001, dy: 0x0000, base: 0x0002 }, 49 | 50 | { count: 0x0000, dx: 0x0000, dy: 0x000c, base: 0x0000 }, 51 | 52 | { count: 0x000a, dx: 0x0000, dy: 0x0000, base: 0x0005 }, 53 | { count: 0x0006, dx: 0x0002, dy: 0x0000, base: 0x0007 }, 54 | { count: 0x0005, dx: 0x0000, dy: 0x0000, base: 0x0005 }, 55 | 56 | { count: 0x0000, dx: 0x0006, dy: 0x0000, base: 0x0000 }, 57 | 58 | { count: 0x000c, dx: 0x0000, dy: 0x0001, base: 0x0000 }, 59 | { count: 0x0005, dx: 0x0000, dy: 0x0000, base: 0x000d }, 60 | 61 | { count: 0x0000, dx: 0x000c, dy: 0x000c, base: 0x0000 }, 62 | 63 | { count: 0x0005, dx: 0x0000, dy: 0x0000, base: 0x0005 }, 64 | { count: 0x000a, dx: 0x0000, dy: 0x0000, base: 0x000f }, 65 | { count: 0x000c, dx: 0xffff, dy: 0x0000, base: 0x0011 }, 66 | { count: 0x0005, dx: 0x0000, dy: 0x0000, base: 0x000f }, 67 | 68 | { count: 0x0000, dx: 0x0006, dy: 0x0001, base: 0x0000 }, 69 | 70 | { count: 0x000a, dx: 0x0000, dy: 0x0000, base: 0x0014 }, 71 | { count: 0x0006, dx: 0x0000, dy: 0x0001, base: 0x0014 }, 72 | { count: 0x0005, dx: 0x0000, dy: 0x0000, base: 0x0014 }, 73 | { count: 0x0003, dx: 0x0001, dy: 0x0000, base: 0x0014 }, 74 | { count: 0x0006, dx: 0xffff, dy: 0x0000, base: 0x0014 }, 75 | { count: 0x0003, dx: 0x0000, dy: 0xffff, base: 0x0014 }, 76 | 77 | { count: 0x0000, dx: 0x0000, dy: 0x0000, base: 0x0000 } 78 | ]; 79 | 80 | /* 81 | * map intro, step offset per map 82 | */ 83 | Screen.imapsofs = [ 84 | 0x00, 0x03, 0x07, 0x0a, 0x0f 85 | ]; 86 | 87 | /* 88 | * map intro, text 89 | * (from ds + 0x8810 + 0x2000, 0x2138, 0x2251, 0x236a, 0x2464) 90 | * 91 | * \376=0xfe \377=0xff 92 | */ 93 | var screen_imaptext_amazon = "\ 94 | @@@@@SOUTH@AMERICA,@1945@@@@@@\xFF\ 95 | RICK@DANGEROUS@CRASH@LANDS@HIS\xFF\ 96 | @PLANE@OVER@THE@AMAZON@WHILE@@\xFF\ 97 | @SEARCHING@FOR@THE@LOST@GOOLU@\xFF\ 98 | @@@@@@@@@@@@TRIBE.@@@@@@@@@@@@\xFF\xFF\ 99 | @BUT,@BY@A@TERRIBLE@TWIST@OF@@\xFF\ 100 | FATE@HE@LANDS@IN@THE@MIDDLE@OF\xFF\ 101 | @@@A@BUNCH@OF@WILD@GOOLUS.@@@@\xFF\xFF\ 102 | @@CAN@RICK@ESCAPE@THESE@ANGRY@\xFF\ 103 | @@@AMAZONIAN@ANTAGONISTS?@@@@@\xFE".replace(/\s+/g, ""); 104 | 105 | screen_imaptext_egypt = "\ 106 | @@@@EGYPT,@SOMETIME@LATER@@@@@\xFF\ 107 | RICK@HEADS@FOR@THE@PYRAMIDS@AT\xFF\ 108 | @@@@THE@REQUEST@OF@LONDON.@@@@\xFF\xFF\ 109 | HE@IS@TO@RECOVER@THE@JEWEL@OF@\xFF\ 110 | ANKHEL@THAT@HAS@BEEN@STOLEN@BY\xFF\ 111 | FANATICS@WHO@THREATEN@TO@SMASH\xFF\ 112 | @IT,@IF@A@RANSOM@IS@NOT@PAID.@\xFF\xFF\ 113 | CAN@RICK@SAVE@THE@GEM,@OR@WILL\xFF\ 114 | HE@JUST@GET@A@BROKEN@ANKHEL@?@\xFE".replace(/\s+/g, ""), 115 | 116 | screen_imaptext_castle = "\ 117 | @@@@EUROPE,@LATER@THAT@WEEK@@@\xFF\ 118 | @@RICK@RECEIVES@A@COMMUNIQUE@@\xFF\ 119 | @@FROM@BRITISH@INTELLIGENCE@@@\xFF\ 120 | @@ASKING@HIM@TO@RESCUE@ALLIED@\xFF\ 121 | @PRISONERS@FROM@THE@NOTORIOUS@\xFF\ 122 | @@@@SCHWARZENDUMPF@CASTLE.@@@@\xFF\xFF\ 123 | @@RICK@ACCEPTS@THE@MISSION.@@@\xFF\xFF\ 124 | @@@BUT@CAN@HE@LIBERATE@THE@@@@\xFF\ 125 | @CRUELLY@CAPTURED@COOMANDOS@?@\xFE".replace(/\s+/g, ""), 126 | 127 | screen_imaptext_missile = "\ 128 | @@@@@@EUROPE,@EVEN@LATER@@@@@@\xFF\ 129 | RICK@LEARNS@FROM@THE@PRISONERS\xFF\ 130 | @THAT@THE@ENEMY@ARE@TO@LAUNCH@\xFF\ 131 | AN@ATTACK@ON@LONDON@FROM@THEIR\xFF\ 132 | @@@@@SECRET@MISSILE@BASE.@@@@@\xFF\xFF\ 133 | WITHOUT@HESITATION,@HE@DECIDES\xFF\ 134 | @@@TO@INFILTRATE@THE@BASE.@@@@\xFF\xFF\ 135 | CAN@RICK@SAVE@LONDON@IN@TIME@?\xFE".replace(/\s+/g, ""), 136 | 137 | screen_imaptext_muchlater = "\ 138 | @@@LONDON,@MUCH,@MUCH@LATER@@@\xFF\ 139 | @RICK@RETURNS@TO@A@TRIUMPHANT@\xFF\ 140 | @@WELCOME@HOME@HAVING@HELPED@@\xFF\ 141 | @@@@SECURE@ALLIED@VICTORY.@@@@\xFF\xFF\ 142 | BUT,@MEANWHILE,@IN@SPACE,@THE@\xFF\ 143 | @@@MASSED@STARSHIPS@OF@THE@@@@\xFF\ 144 | @@@BARFIAN@EMPIRE@ARE@POISED@@\xFF\ 145 | @@@@@TO@INVADE@THE@EARTH.@@@@@\xFF\xFF\ 146 | @WHAT@WILL@RICK@DO@NEXT@...@?@\xFE".replace(/\s+/g, ""); 147 | 148 | Screen.imaptext = [ 149 | screen_imaptext_amazon, 150 | screen_imaptext_egypt, 151 | screen_imaptext_castle, 152 | screen_imaptext_missile, 153 | screen_imaptext_muchlater 154 | ]; 155 | 156 | /* 157 | * main intro, hall of fame title 158 | * (from ds + 0x8810 + 0x2642) 159 | */ 160 | Screen.imainhoft = [ 161 | 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0xd4, 0xb7, 0xb1, 162 | 0xac, 0xc6, 0x2f, 0xc6, 0x2f, 0x2f, 0xa4, 0xac, 163 | 0x9b, 0xc1, 0x2f, 0x9b, 0xc1, 0xb1, 0xac, 0xb6, 164 | 0xbd, 0x9b, 0xc1, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 165 | 0xff, 166 | 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0xb2, 0xb3, 0xb2, 167 | 0xb3, 0xad, 0x2f, 0xad, 0x2f, 0x2f, 0xa6, 0xae, 168 | 0xc2, 0xc3, 0x2f, 0xc2, 0xc3, 0xb2, 0xb3, 0xbe, 169 | 0xbf, 0xc2, 0xc3, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 170 | 0xff, 171 | 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x9f, 0xc0, 0xb4, 172 | 0xb5, 0xaf, 0xc4, 0xaf, 0xc4, 0x2f, 0xa7, 0xb0, 173 | 0xb4, 0x2f, 0x2f, 0xb4, 0x2f, 0xb4, 0xb5, 0xb4, 174 | 0xb5, 0xaf, 0xc4, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 175 | 0xfe 176 | ]; 177 | 178 | /* 179 | * main intro, Rick Dangerous title 180 | * (from ds + 0x8810 + 0x27a1) 181 | */ 182 | Screen.imainrdt = [ 183 | 0x2f, 0x2f, 0x2f, 0x9b, 0x9c, 0xa1, 0xa4, 0xa5, 184 | 0xa9, 0xaa, 0x2f, 0x9b, 0xac, 0xb1, 0xac, 0xb6, 185 | 0xb7, 0xa4, 0xa5, 0x9b, 0xc1, 0x9b, 0x9c, 0xa4, 186 | 0xac, 0xc6, 0xc7, 0xc8, 0xc9, 0x2f, 0x2f, 0x2f, 187 | 0xff, 188 | 0x2f, 0x2f, 0x2f, 0x9d, 0x9e, 0xa2, 0xa6, 0x2f, 189 | 0x9d, 0xab, 0x2f, 0xad, 0xae, 0xb2, 0xb3, 0xb8, 190 | 0xb9, 0xa6, 0xbb, 0xc2, 0xc3, 0x9d, 0x9e, 0xa6, 191 | 0xae, 0xad, 0xae, 0xca, 0xcb, 0x2f, 0x2f, 0x2f, 192 | 0xff, 193 | 0x2f, 0x2f, 0x2f, 0x9f, 0xa0, 0xa3, 0xa7, 0xa8, 194 | 0x9f, 0xa0, 0x2f, 0xaf, 0xb0, 0xb4, 0xb5, 0x9f, 195 | 0xba, 0xa7, 0xbc, 0xaf, 0xc4, 0x9f, 0xa0, 0xa7, 196 | 0xb0, 0xc5, 0xb0, 0xcc, 0xb0, 0x2f, 0x2f, 0x2f, 197 | 0xfe 198 | ]; 199 | 200 | /* 201 | * congratulations 202 | * (from ds + 0x8810 + 0x257d) 203 | */ 204 | Screen.congrats = [ 205 | 0xa4, 0xa5, 0xa4, 0xac, 0xb6, 0xb7, 0xa4, 0xa5, 206 | 0x9b, 0x9c, 0xb1, 0xac, 0xcd, 0xce, 0xc6, 0xc7, 207 | 0xd3, 0x2f, 0xb1, 0xac, 0xcd, 0xce, 0xa1, 0xa4, 208 | 0xac, 0xb6, 0xb7, 0xc8, 0xc9, 0x2f, 0xd5, 0xd6, 209 | 0xff, 210 | 0xa6, 0x2f, 0xa6, 0xae, 0xb8, 0xb9, 0xa6, 0xbb, 211 | 0x9d, 0x9e, 0xb2, 0xb3, 0xcf, 0xd0, 0xad, 0xae, 212 | 0xad, 0x2f, 0xb2, 0xb3, 0xcf, 0xd0, 0xa2, 0xa6, 213 | 0xae, 0xb8, 0xb9, 0xca, 0xcb, 0x2f, 0xd7, 0xd8, 214 | 0xff, 215 | 0xa7, 0xa8, 0xa7, 0xb0, 0x9f, 0xba, 0xa7, 0xbc, 216 | 0x9f, 0xa0, 0xb4, 0xb5, 0xd1, 0xd2, 0xc5, 0xb0, 217 | 0xaf, 0xc4, 0xb4, 0xb5, 0xd1, 0xd2, 0xa3, 0xa7, 218 | 0xb0, 0x9f, 0xba, 0xcc, 0xb0, 0x2f, 0xd9, 0xda, 219 | 0xfe 220 | ]; 221 | 222 | /* 223 | * main intro, Core Design copyright text 224 | * (from ds + 0x8810 + 0x2288) 225 | * 226 | * \376=0xfe \377=0xff 227 | */ 228 | Screen.imaincdc = "\ 229 | @@@@@@@@@@@@@@@@@@@\xFF\xFF\ 230 | (C)@1989@CORE@DESIGN\xFF\xFF\xFF\ 231 | @PRESS@SPACE@TO@START\xFE".replace(/\s+/g, ""); 232 | 233 | /* 234 | * gameover 235 | * (from ds + 0x8810 + 0x2864) 236 | * 237 | * \376=0xfe \377=0xff 238 | */ 239 | Screen.gameovertxt = "\ 240 | @@@@@@@@@@@\xFF\ 241 | @GAME@OVER@\xFF\ 242 | @@@@@@@@@@@\xFE".replace(/\s+/g, ""); 243 | 244 | /* 245 | * paused 246 | * 247 | * \376=0xfe \377=0xff 248 | */ 249 | Screen.pausedtxt = "\ 250 | @@@@@@@@@@\xFF\ 251 | @@PAUSED@@\xFF\ 252 | @@@@@@@@@@\xFE".replace(/\s+/g, ""); 253 | 254 | /* EOF */ 255 | })(); 256 | -------------------------------------------------------------------------------- /source/dat_spritesST.js: -------------------------------------------------------------------------------- 1 | var SPRITES_NBR_SPRITES = (0xD5); 2 | 3 | //sprite_t sprites_data[SPRITES_NBR_SPRITES] = {...} => image file 4 | -------------------------------------------------------------------------------- /source/draw.js: -------------------------------------------------------------------------------- 1 | /* 2 | * counters positions (pixels, screen) 3 | */ 4 | var DRAW_STATUS_BULLETS_X = 0x68, 5 | DRAW_STATUS_BOMBS_X = 0xA8, 6 | 7 | DRAW_STATUS_SCORE_X = 0x20, 8 | DRAW_STATUS_LIVES_X = 0xF0, 9 | DRAW_STATUS_Y = 0, 10 | 11 | /* map coordinates of the screen */ 12 | DRAW_XYMAP_SCRLEFT = (-0x0020), 13 | DRAW_XYMAP_SCRTOP = (0x0040), 14 | 15 | /* map coordinates of the top of the hidden bottom of the map */ 16 | DRAW_XYMAP_HBTOP = (0x0100); 17 | 18 | (function() { 19 | /* 20 | * public vars 21 | */ 22 | Draw.tllst = 0; /* pointer to tiles list */ 23 | Draw.tilesBank = 0; /* tile number offset */ 24 | 25 | Draw.STATUSRECT = new G.Rect(DRAW_STATUS_SCORE_X, DRAW_STATUS_Y, 26 | DRAW_STATUS_LIVES_X + 6 * 8 - DRAW_STATUS_SCORE_X, 8); 27 | 28 | Draw.SCREENRECT = new G.Rect(0, 0, SYSVID_WIDTH, SYSVID_HEIGHT); 29 | 30 | /* 31 | * private vars 32 | */ 33 | var fb = new G.Vector(); 34 | 35 | /* 36 | * Set the frame buffer pointer 37 | * 38 | * x, y: position (pixels, screen) 39 | */ 40 | Draw.setfb = function(x, y) { 41 | fb.x = x; 42 | fb.y = y; 43 | } 44 | 45 | /* 46 | * Clip to map screen 47 | * 48 | * x, y: position (pixels, map) CHANGED clipped 49 | * width, height: dimension CHANGED clipped 50 | * return: TRUE if fully clipped, FALSE if still (at least partly) visible 51 | */ 52 | Draw.clipms = function(x, y, width, height) { 53 | if (x < 0) { 54 | if (x + width < 0) { 55 | return { returns: true, x: x, y: y, width: width, height: height }; 56 | } else { 57 | width += x; 58 | x = 0; 59 | } 60 | } else { 61 | if (x > 0x0100) { 62 | return { returns: true, x: x, y: y, width: width, height: height }; 63 | } else if (x + width > 0x0100) { 64 | width = 0x0100 - x; 65 | } 66 | } 67 | 68 | if (y < DRAW_XYMAP_SCRTOP) { 69 | if ((y + height) < DRAW_XYMAP_SCRTOP) { 70 | return { returns: true, x: x, y: y, width: width, height: height }; 71 | } else { 72 | height += y - DRAW_XYMAP_SCRTOP; 73 | y = DRAW_XYMAP_SCRTOP; 74 | } 75 | } else { 76 | if (y >= DRAW_XYMAP_HBTOP) { 77 | return { returns: true, x: x, y: y, width: width, height: height }; 78 | } else if (y + height > DRAW_XYMAP_HBTOP) { 79 | height = DRAW_XYMAP_HBTOP - y; 80 | } 81 | } 82 | 83 | return { returns: false, x: x, y: y, width: width, height: height }; 84 | } 85 | 86 | /* 87 | * Draw a list of tiles onto the frame buffer 88 | * start at position indicated by fb ; at the end of each (sub)list, 89 | * perform a "carriage return + line feed" i.e. go back to the initial 90 | * position then go down one tile row (8 pixels) 91 | * 92 | * ASM 1e33 93 | * fb: CHANGED (see above) 94 | * draw_tllst: CHANGED points to the element following 0xfe/0xff end code 95 | */ 96 | Draw.tilesList = function() { 97 | var t = fb.clone(); 98 | while (Draw.tilesSubList() != 0xFE) { /* draw sub-list */ 99 | t.y += 8; /* go down one tile i.e. 8 lines */ 100 | fb = t.clone(); 101 | } 102 | } 103 | 104 | /* 105 | * Draw a list of tiles onto the frame buffer -- same as draw_tilesList, 106 | * but accept an immediate string as parameter. Note that the string needs 107 | * to be properly terminated with 0xfe (\376) and 0xff (\377) chars. 108 | */ 109 | Draw.tilesListImm = function(list) { 110 | Draw.tllst = (typeof list == "array") ? list : list.split(""); // FIXME? 111 | Draw.tilesList(); 112 | } 113 | 114 | /* 115 | * Draw a sub-list of tiles onto the frame buffer 116 | * start at position indicated by fb ; leave fb pointing to the next 117 | * tile to the right of the last tile drawn 118 | * 119 | * ASM 1e41 120 | * fpb: CHANGED (see above) 121 | * draw_tllst: CHANGED points to the element following 0xfe/0xff end code 122 | * returns: end code (0xfe : end of list ; 0xff : end of sub-list) 123 | */ 124 | Draw.tilesSubList = function() { 125 | var i = Draw.tllst.shift().charCodeAt(0); 126 | 127 | while (i != 0xFF && i != 0xFE) { /* while not end */ 128 | Draw.tile(i); /* draw tile */ 129 | i = Draw.tllst.shift().charCodeAt(0); 130 | } 131 | 132 | return i; 133 | } 134 | 135 | /* 136 | * Draw a tile 137 | * at position indicated by fb ; leave fb pointing to the next tile 138 | * to the right of the tile drawn 139 | * 140 | * ASM 1e6c 141 | * tlnbr: tile number 142 | * draw_filter: CGA colors filter 143 | * fb: CHANGED (see above) 144 | */ 145 | Draw.tile = function(tileNumber) { 146 | Tiles.data[Draw.tilesBank].draw(Sysvid.fb.renderer, fb.x, fb.y, tileNumber); 147 | // Sysvid.fb.renderer.fillRect(new G.Rect(fb.x, fb.y, 8, 8), new G.Color(Math.random() * 255 | 0, 0, 0)); 148 | fb.x += 8; /* next tile */ 149 | } 150 | 151 | /* 152 | * Draw a sprite 153 | * 154 | * ASM 1a09 155 | * nbr: sprite number 156 | * x, y: sprite position (pixels, screen) 157 | * fb: CHANGED 158 | */ 159 | Draw.sprite = function(number, x, y) { 160 | Draw.setfb(x, y); 161 | Sprites.data.draw(Sysvid.fb.renderer, fb.x, fb.y, number); 162 | } 163 | 164 | /* 165 | * Draw a sprite 166 | * 167 | * NOTE re-using original ST graphics format 168 | */ 169 | Draw.sprite2 = function(number, x, y, front) { 170 | var d = 0; /* sprite data */ 171 | var x0, y0; /* clipped x, y */ 172 | var w, h; /* width, height */ 173 | var g, /* sprite data offset*/ 174 | r, c, /* row, column */ 175 | i, /* frame buffer shifter */ 176 | im; /* tile flag shifter */ 177 | var flg, tmp;/* tile flag */ 178 | 179 | x0 = x; 180 | y0 = y; 181 | w = 0x20; 182 | h = 0x15; 183 | 184 | tmp = Draw.clipms(x0, y0, w, h); 185 | if (tmp.returns) { /* return if not visible */ 186 | return; 187 | } 188 | x0 = tmp.x; 189 | y0 = tmp.y; 190 | w = tmp.width; 191 | h = tmp.height; 192 | 193 | g = 0; 194 | 195 | Sysvid.fb.enableClipping(new G.Rect(x0 - DRAW_XYMAP_SCRLEFT, y0 - DRAW_XYMAP_SCRTOP + 8, w, h)); 196 | Draw.setfb(x - DRAW_XYMAP_SCRLEFT, y - DRAW_XYMAP_SCRTOP + 8); 197 | Draw.sprite(number, fb.x, fb.y); 198 | Sysvid.fb.disableClipping(); 199 | /* 200 | for (r = 0; r < 0x15; r++) { 201 | if (r >= h || y + r < y0) continue; 202 | 203 | i = 0x1f; 204 | im = x - (x & 0xfff8); 205 | flg = World.eflg[World.map[(y + r) >> 3][(x + 0x1f)>> 3]]; 206 | 207 | #define LOOP(N, C0, C1) \ 208 | d = sprites_data[number][g + N]; \ 209 | for (c = C0; c >= C1; c--, i--, d >>= 4, im--) { \ 210 | if (im == 0) { \ 211 | flg = map_eflg[map_map[(y + r) >> 3][(x + c) >> 3]]; \ 212 | im = 8; \ 213 | } \ 214 | if (!front && (flg & MAP_EFLG_FGND)) continue; \ 215 | if (c >= w || x + c < x0) continue; \ 216 | if (d & 0x0F) fb[i] = (fb[i] & 0xF0) | (d & 0x0F); \ 217 | } 218 | 219 | LOOP(3, 0x1f, 0x18); 220 | LOOP(2, 0x17, 0x10); 221 | LOOP(1, 0x0f, 0x08); 222 | LOOP(0, 0x07, 0x00); 223 | 224 | #undef LOOP 225 | fb += SYSVID_WIDTH; 226 | g += 4; 227 | } 228 | */ 229 | } 230 | 231 | /* 232 | * Redraw the map behind a sprite 233 | * align to tile column and row, and clip 234 | * 235 | * x, y: sprite position (pixels, map). 236 | */ 237 | Draw.spriteBackground = function(x, y) { 238 | var r, c; 239 | var rmax, cmax; 240 | var xmap, ymap; // S16 241 | var xs, ys, tmp; 242 | 243 | /* aligne to column and row, prepare map coordinate, and clip */ 244 | xmap = G.Convert.toInt16(x & 0xFFF8); 245 | ymap = G.Convert.toInt16(y & 0xFFF8); 246 | cmax = (x - xmap == 0 ? 0x20 : 0x28); /* width, 4 tl cols, 8 pix each */ 247 | rmax = (y & 0x04) ? 0x20 : 0x18; /* height, 3 or 4 tile rows */ 248 | 249 | tmp = Draw.clipms(xmap, ymap, cmax, rmax); 250 | if (tmp.returns) { /* don't draw if fully clipped */ 251 | return; 252 | } 253 | xmap = tmp.x; 254 | ymap = tmp.y; 255 | cmax = tmp.width; 256 | rmax = tmp.height; 257 | 258 | /* get back to screen */ 259 | xs = xmap - DRAW_XYMAP_SCRLEFT; 260 | ys = ymap - DRAW_XYMAP_SCRTOP; 261 | xmap >>= 3; 262 | ymap >>= 3; 263 | cmax >>= 3; 264 | rmax >>= 3; 265 | 266 | /* draw */ 267 | for (r = 0; r < rmax; r++) { /* for each row */ 268 | Draw.setfb(xs, 8 + ys + r * 8); 269 | for (c = 0; c < cmax; c++) { /* for each column */ 270 | Draw.tile(World.map[ymap + r][xmap + c]); 271 | } 272 | } 273 | } 274 | 275 | /* 276 | * Draw entire map screen background tiles onto frame buffer. 277 | * 278 | * ASM 0af5, 0a54 279 | */ 280 | Draw.map = function() { 281 | var i, j; 282 | 283 | Draw.tilesBank = World.tilesBank; 284 | 285 | for (i = 0; i < 0x18; i++) { /* 0x18 rows */ 286 | Draw.setfb(0x20, 8 + (i * 8)); 287 | for (j = 0; j < 0x20; j++) /* 0x20 tiles per row */ 288 | Draw.tile(World.map[i + 8][j]); 289 | } 290 | } 291 | /* 292 | * Draw status indicators 293 | * 294 | * ASM 0309 295 | */ 296 | Draw.drawStatus = function() { 297 | var i; 298 | // var sv; 299 | // var s = [0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfe]; 300 | 301 | Draw.tilesBank = 0; 302 | 303 | // for (i = 5, sv = Game.score; i >= 0; i--) { 304 | // s[i] = 0x30 + (sv % 10 | 0); 305 | // sv /= 10; 306 | // } 307 | Draw.tllst = ("00000" + Game.score + "\xFE").substr(-7).split(""); 308 | 309 | Draw.setfb(DRAW_STATUS_SCORE_X, DRAW_STATUS_Y); 310 | Draw.tilesList(); 311 | 312 | Draw.setfb(DRAW_STATUS_BULLETS_X, DRAW_STATUS_Y); 313 | for (i = 0; i < Game.bullets; i++) { 314 | Draw.tile(TILES_BULLET); 315 | } 316 | 317 | Draw.setfb(DRAW_STATUS_BOMBS_X, DRAW_STATUS_Y); 318 | for (i = 0; i < Game.bombs; i++) { 319 | Draw.tile(TILES_BOMB); 320 | } 321 | 322 | Draw.setfb(DRAW_STATUS_LIVES_X, DRAW_STATUS_Y); 323 | for (i = 0; i < Game.lives; i++) { 324 | Draw.tile(TILES_RICK); 325 | } 326 | } 327 | 328 | /* 329 | * Clear status indicators 330 | */ 331 | Draw.clearStatus = function() { 332 | var i; 333 | 334 | Draw.tilesBank = 0; 335 | Draw.setfb(DRAW_STATUS_SCORE_X, DRAW_STATUS_Y); 336 | for (i = 0; i < DRAW_STATUS_LIVES_X/8 + 6 - DRAW_STATUS_SCORE_X/8; i++) { 337 | Draw.tile('@'); 338 | } 339 | } 340 | 341 | /* 342 | * Draw a picture 343 | */ 344 | Draw.pic = function(x, y, w, h, pic) { 345 | Sysvid.fb.renderer.drawBitmapSection(pic, x, y, new G.Rect(0, 0, w, h)); 346 | } 347 | 348 | /* EOF */ 349 | })(); 350 | -------------------------------------------------------------------------------- /source/e_bomb.js: -------------------------------------------------------------------------------- 1 | var E_BOMB_NO = 3, 2 | E_BOMB_ENT, // Defined later in ents.js 3 | E_BOMB_TICKER = (0x2D); 4 | 5 | (function() { 6 | 7 | /* 8 | * public vars (for performance reasons) 9 | */ 10 | EBomb.lethal = 0; 11 | EBomb.xc = 0; 12 | EBomb.yc = 0; 13 | 14 | /* 15 | * private vars 16 | */ 17 | var e_bomb_ticker; 18 | 19 | /* 20 | * Bomb hit test 21 | * 22 | * ASM 11CD 23 | * returns: TRUE/hit, FALSE/not 24 | */ 25 | EBomb.hit = function(e) { 26 | if (Ent.ents[e].x > (E_BOMB_ENT.x >= 0xE0 ? 0xFF : E_BOMB_ENT.x + 0x20)) { 27 | return false; 28 | } 29 | if (Ent.ents[e].x + Ent.ents[e].w < (E_BOMB_ENT.x > 0x04 ? E_BOMB_ENT.x - 0x04 : 0)) { 30 | return false; 31 | } 32 | if (Ent.ents[e].y > (E_BOMB_ENT.y + 0x1D)) { 33 | return false; 34 | } 35 | if (Ent.ents[e].y + Ent.ents[e].h < (E_BOMB_ENT.y > 0x0004 ? E_BOMB_ENT.y - 0x0004 : 0)) { 36 | return false; 37 | } 38 | return true; 39 | } 40 | 41 | /* 42 | * Initialize bomb 43 | */ 44 | EBomb.init = function(x, y) { 45 | E_BOMB_ENT.n = 0x03; 46 | E_BOMB_ENT.x = x; 47 | E_BOMB_ENT.y = y; 48 | e_bomb_ticker = E_BOMB_TICKER; 49 | EBomb.lethal = false; 50 | 51 | /* 52 | * Atari ST dynamite sprites are not centered the 53 | * way IBM PC sprites were ... need to adjust things a little bit 54 | */ 55 | E_BOMB_ENT.x += 4; 56 | E_BOMB_ENT.y += 5; 57 | 58 | } 59 | 60 | /* 61 | * Entity action 62 | * 63 | * ASM 18CA 64 | */ 65 | EBomb.action = function(/*UNUSED(U8 e)*/) { 66 | /* tick */ 67 | e_bomb_ticker--; 68 | 69 | if (e_bomb_ticker == 0) { 70 | /* 71 | * end: deactivate 72 | */ 73 | E_BOMB_ENT.n = 0; 74 | EBomb.lethal = false; 75 | 76 | } else if (e_bomb_ticker >= 0x0A) { 77 | /* 78 | * ticking 79 | */ 80 | if ((e_bomb_ticker & 0x03) == 0x02) { 81 | Syssnd.play("WAV_BOMBSHHT", 1); 82 | } 83 | 84 | /* ST bomb sprites sequence is longer */ 85 | if (e_bomb_ticker < 40) 86 | E_BOMB_ENT.sprite = 0x99 + 19 - (e_bomb_ticker >> 1); 87 | else 88 | 89 | E_BOMB_ENT.sprite = (e_bomb_ticker & 0x01) ? 0x23 : 0x22; 90 | 91 | } else if (e_bomb_ticker == 0x09) { 92 | /* 93 | * explode 94 | */ 95 | Syssnd.play("WAV_EXPLODE", 1); 96 | /* See above: fixing alignment */ 97 | E_BOMB_ENT.x -= 4; 98 | E_BOMB_ENT.y -= 5; 99 | E_BOMB_ENT.sprite = 0xa8 + 4 - (e_bomb_ticker >> 1); 100 | 101 | EBomb.xc = E_BOMB_ENT.x + 0x0C; 102 | EBomb.yc = E_BOMB_ENT.y + 0x000A; 103 | EBomb.lethal = true; 104 | if (EBomb.hit(E_RICK_NO)) { 105 | ERick.gozombie(); 106 | } 107 | } else { 108 | /* 109 | * exploding 110 | */ 111 | E_BOMB_ENT.sprite = 0xa8 + 4 - (e_bomb_ticker >> 1); 112 | 113 | /* exploding, hence lethal */ 114 | if (EBomb.hit(E_RICK_NO)) { 115 | ERick.gozombie(); 116 | } 117 | } 118 | } 119 | 120 | /* EOF */ 121 | })(); 122 | -------------------------------------------------------------------------------- /source/e_bonus.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | /* 4 | * Entity action 5 | * 6 | * ASM 242C 7 | */ 8 | EBonus.action = function(e) { 9 | //#define seq c1 10 | 11 | if (Ent.ents[e].seq == 0) { 12 | if (ERick.boxtest(e)) { 13 | Game.score += 500; 14 | Syssnd.play("WAV_BONUS", 1); 15 | World.marks[Ent.ents[e].mark].ent |= MAP_MARK_NACT; 16 | Ent.ents[e].seq = 1; 17 | Ent.ents[e].sprite = 0xad; 18 | Ent.ents[e].front = true; 19 | Ent.ents[e].y -= 0x08; 20 | } 21 | 22 | } else if (Ent.ents[e].seq > 0 && Ent.ents[e].seq < 10) { 23 | Ent.ents[e].seq++; 24 | Ent.ents[e].y -= 2; 25 | 26 | } else { 27 | Ent.ents[e].n = 0; 28 | } 29 | } 30 | 31 | /* EOF */ 32 | })(); 33 | -------------------------------------------------------------------------------- /source/e_box.js: -------------------------------------------------------------------------------- 1 | /* 2 | * FIXME this is because the same structure is used 3 | * for all entities. Need to replace this w/ an inheritance 4 | * solution. 5 | */ 6 | //#define cnt c1 7 | 8 | /* 9 | * Constants 10 | */ 11 | var SEQ_INIT = 0x0A; 12 | 13 | (function() { 14 | 15 | var sp = [ 0x24, 0x25, 0x26, 0x27, 0x28 ]; /* explosion sprites sequence */ 16 | 17 | /* 18 | * Entity action 19 | * 20 | * ASM 245A 21 | */ 22 | EBox.action = function(e) { 23 | 24 | if (Ent.ents[e].n & ENT_LETHAL) { 25 | /* 26 | * box is lethal i.e. exploding 27 | * play sprites sequence then stop 28 | */ 29 | Ent.ents[e].sprite = sp[Ent.ents[e].cnt >> 1]; 30 | if (--Ent.ents[e].cnt == 0) { 31 | Ent.ents[e].n = 0; 32 | World.marks[Ent.ents[e].mark].ent |= MAP_MARK_NACT; 33 | } 34 | } else { 35 | /* 36 | * not lethal: check to see if triggered 37 | */ 38 | if (ERick.boxtest(e)) { 39 | /* rick: collect bombs or bullets and stop */ 40 | Syssnd.play("WAV_BOX", 1); 41 | 42 | if (Ent.ents[e].n == 0x10) { 43 | Game.bombs = GAME_BOMBS_INIT; 44 | } else { /* 0x11 */ 45 | Game.bullets = GAME_BULLETS_INIT; 46 | } 47 | Ent.ents[e].n = 0; 48 | World.marks[Ent.ents[e].mark].ent |= MAP_MARK_NACT; 49 | 50 | } else if (E_RICK_STTST(E_RICK_STSTOP) && 51 | U.fboxtest(e, ERick.stop_x, ERick.stop_y)) { 52 | /* rick's stick: explode */ 53 | explode(e); 54 | 55 | } else if (E_BULLET_ENT.n && U.fboxtest(e, EBullet.xc, EBullet.yc)) { 56 | /* bullet: explode (and stop bullet) */ 57 | E_BULLET_ENT.n = 0; 58 | explode(e); 59 | 60 | } else if (EBomb.lethal && EBomb.hit(e)) { 61 | /* bomb: explode */ 62 | explode(e); 63 | } 64 | } 65 | } 66 | 67 | /* 68 | * Explode when 69 | */ 70 | function explode(e) { 71 | Ent.ents[e].cnt = SEQ_INIT; 72 | Ent.ents[e].n |= ENT_LETHAL; 73 | Syssnd.play("WAV_EXPLODE", 1); 74 | } 75 | 76 | 77 | /* EOF */ 78 | })(); 79 | -------------------------------------------------------------------------------- /source/e_bullet.js: -------------------------------------------------------------------------------- 1 | /* const 2 | ********/ 3 | var E_BULLET_NO = 2, 4 | E_BULLET_ENT // defined later; 5 | 6 | (function() { 7 | 8 | /* 9 | * public vars (for performance reasons) 10 | */ 11 | EBullet.offsx = 0; 12 | EBullet.xc = EBullet.yc = 0; 13 | 14 | /* 15 | * Initialize bullet 16 | */ 17 | EBullet.init = function(x, y) { 18 | E_BULLET_ENT.n = 0x02; 19 | E_BULLET_ENT.x = x; 20 | E_BULLET_ENT.y = y + 0x0006; 21 | if (Game.dir == LEFT) { 22 | EBullet.offsx = -0x08; 23 | E_BULLET_ENT.sprite = 0x21; 24 | } else { 25 | EBullet.offsx = 0x08; 26 | E_BULLET_ENT.sprite = 0x20; 27 | } 28 | Syssnd.play("WAV_BULLET", 1); 29 | } 30 | 31 | /* 32 | * Entity action 33 | * 34 | * ASM 1883, 0F97 35 | */ 36 | EBullet.action = function(/*UNUSED(U8 e)*/) { 37 | /* move bullet */ 38 | E_BULLET_ENT.x += EBullet.offsx; 39 | 40 | if (E_BULLET_ENT.x <= -0x10 || E_BULLET_ENT.x > 0xe8) { 41 | /* out: deactivate */ 42 | E_BULLET_ENT.n = 0; 43 | 44 | } else { 45 | /* update bullet center coordinates */ 46 | EBullet.xc = E_BULLET_ENT.x + 0x0c; 47 | EBullet.yc = E_BULLET_ENT.y + 0x05; 48 | if (World.eflg[World.map[EBullet.yc >> 3][EBullet.xc >> 3]] & 49 | MAP_EFLG_SOLID) { 50 | /* hit something: deactivate */ 51 | E_BULLET_ENT.n = 0; 52 | } 53 | } 54 | } 55 | 56 | /* EOF */ 57 | })(); 58 | -------------------------------------------------------------------------------- /source/e_sbonus.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | /* 3 | * public vars 4 | */ 5 | ESbonus.counting = false; 6 | ESbonus.counter = 0; 7 | ESbonus.bonus = 0; 8 | 9 | /* 10 | * Entity action / start counting 11 | * 12 | * ASM 2182 13 | */ 14 | ESbonus.start = function(e) { 15 | Ent.ents[e].sprite = 0; /* invisible */ 16 | if (U.trigbox(e, ENT_XRICK.x + 0x0C, ENT_XRICK.y + 0x0A)) { 17 | /* rick is within trigger box */ 18 | Ent.ents[e].n = 0; 19 | ESbonus.counting = true; /* 6DD5 */ 20 | ESbonus.counter = 0x1e; /* 6DDB */ 21 | ESbonus.bonus = 2000; /* 291A-291D */ 22 | Syssnd.play("WAV_SBONUS1", 1); 23 | } 24 | } 25 | 26 | /* 27 | * Entity action / stop counting 28 | * 29 | * ASM 2143 30 | */ 31 | ESbonus.stop = function(e) { 32 | Ent.ents[e].sprite = 0; /* invisible */ 33 | 34 | if (!ESbonus.counting) { 35 | return; 36 | } 37 | 38 | if (U.trigbox(e, ENT_XRICK.x + 0x0C, ENT_XRICK.y + 0x0A)) { 39 | /* rick is within trigger box */ 40 | ESbonus.counting = false; /* stop counting */ 41 | Ent.ents[e].n = 0; /* deactivate entity */ 42 | Game.score += ESbonus.bonus; /* add bonus to score */ 43 | Syssnd.play("WAV_SBONUS2", 1); 44 | /* make sure the entity won't be activated again */ 45 | World.marks[Ent.ents[e].mark].ent |= MAP_MARK_NACT; 46 | } else { 47 | /* keep counting */ 48 | if (--ESbonus.counter == 0) { 49 | ESbonus.counter = 0x1e; 50 | if (ESbonus.bonus) ESbonus.bonus--; 51 | } 52 | } 53 | } 54 | 55 | /* EOF */ 56 | })(); 57 | -------------------------------------------------------------------------------- /source/maps.js: -------------------------------------------------------------------------------- 1 | var MAP_NBR_MAPS = 0x05, 2 | MAP_NBR_SUBMAPS = 0x2F, 3 | MAP_NBR_CONNECT = 0x99, 4 | MAP_NBR_BNUMS = 0x1FD8, 5 | MAP_NBR_BLOCKS = 0x0100, 6 | MAP_NBR_MARKS = 0x020B, 7 | MAP_NBR_EFLGC = 0x0020, 8 | 9 | /* 10 | * map row definitions, for three zones : hidden top, screen, hidden bottom 11 | * the three zones compose map_map, which contains the definition of the 12 | * current portion of the submap. 13 | */ 14 | MAP_ROW_HTTOP = 0x00, 15 | MAP_ROW_HTBOT = 0x07, 16 | MAP_ROW_SCRTOP = 0x08, 17 | MAP_ROW_SCRBOT = 0x1F, 18 | MAP_ROW_HBTOP = 0x20, 19 | MAP_ROW_HBBOT = 0x27, 20 | 21 | /* 22 | * flags for map_marks[].ent ("yes" when set) 23 | * 24 | * MAP_MARK_NACT: this mark is not active anymore. 25 | */ 26 | MAP_MARK_NACT = (0x80), 27 | 28 | /* 29 | * flags for map_eflg[map_map[row][col]] ("yes" when set) 30 | * 31 | * MAP_EFLG_VERT: vertical move only (usually on top of _CLIMB). 32 | * MAP_EFLG_SOLID: solid block, can't go through. 33 | * MAP_EFLG_SPAD: super pad. can't go through, but sends entities to the sky. 34 | * MAP_EFLG_WAYUP: solid block, can't go through except when going up. 35 | * MAP_EFLG_FGND: foreground (hides entities). 36 | * MAP_EFLG_LETHAL: lethal (kill entities). 37 | * MAP_EFLG_CLIMB: entities can climb here. 38 | * MAP_EFLG_01: 39 | */ 40 | MAP_EFLG_VERT = (0x80), 41 | MAP_EFLG_SOLID = (0x40), 42 | MAP_EFLG_SPAD = (0x20), 43 | MAP_EFLG_WAYUP = (0x10), 44 | MAP_EFLG_FGND = (0x08), 45 | MAP_EFLG_LETHAL = (0x04), 46 | MAP_EFLG_CLIMB = (0x02), 47 | MAP_EFLG_01 = (0x01); 48 | 49 | (function() { 50 | /* 51 | * global vars 52 | */ 53 | World.map = []; // [0x2C][0x20]; 54 | World.eflg = []; // [0x100]; 55 | World.frow = 0; 56 | World.tilesBank = 0; 57 | 58 | for (var n = 0; n < 0x2C; n++) { 59 | World.map[n] = []; 60 | for (var m = 0; m < 0x20; m++) { 61 | World.map[n][m] = 0; 62 | } 63 | } 64 | 65 | /* 66 | * Fill in map_map with tile numbers by expanding blocks. 67 | * 68 | * add map_submaps[].bnum to map_frow to find out where to start from. 69 | * We need to /4 map_frow to convert from tile rows to block rows, then 70 | * we need to *8 to convert from block rows to block numbers (there 71 | * are 8 blocks per block row). This is achieved by *2 then &0xfff8. 72 | */ 73 | World.expand = function() { 74 | var i, j, k, l; 75 | var row = 0, col = 0; 76 | var pbnum = 0; 77 | 78 | pbnum = World.submaps[Game.submap].bnum + ((2 * World.frow) & 0xfff8); 79 | row = col = 0; 80 | 81 | for (i = 0; i < 0x0b; i++) { /* 0x0b rows of blocks */ 82 | for (j = 0; j < 0x08; j++) { /* 0x08 blocks per row */ 83 | for (k = 0, l = 0; k < 0x04; k++) { /* expand one block */ 84 | World.map[row][col++] = World.blocks[World.bnums[pbnum]][l++]; 85 | World.map[row][col++] = World.blocks[World.bnums[pbnum]][l++]; 86 | World.map[row][col++] = World.blocks[World.bnums[pbnum]][l++]; 87 | World.map[row][col] = World.blocks[World.bnums[pbnum]][l++]; 88 | row += 1; col -= 3; 89 | } 90 | row -= 4; col += 4; 91 | pbnum++; 92 | } 93 | row += 4; col = 0; 94 | } 95 | } 96 | 97 | /* 98 | * Initialize a new submap 99 | * 100 | * ASM 0cc3 101 | */ 102 | World.init = function() { 103 | /*sys_printf("xrick/map_init: map=%#04x submap=%#04x\n", g_map, game_submap);*/ 104 | World.tilesBank = (World.submaps[Game.submap].page == 1) ? 2 : 1; 105 | 106 | World.eflg_expand((World.submaps[Game.submap].page == 1) ? 0x10 : 0x00); 107 | World.expand(); 108 | Ent.reset(); 109 | Ent.actvis(World.frow + MAP_ROW_SCRTOP, World.frow + MAP_ROW_SCRBOT); 110 | Ent.actvis(World.frow + MAP_ROW_HTTOP, World.frow + MAP_ROW_HTBOT); 111 | Ent.actvis(World.frow + MAP_ROW_HBTOP, World.frow + MAP_ROW_HBBOT); 112 | } 113 | 114 | /* 115 | * Expand entity flags for this map 116 | * 117 | * ASM 1117 118 | */ 119 | World.eflg_expand = function(offs) { 120 | var i, j, k; 121 | 122 | for (i = 0, k = 0; i < 0x10; i++) { 123 | j = World.eflg_c[offs + i++]; 124 | while (j--) World.eflg[k++] = World.eflg_c[offs + i]; 125 | } 126 | } 127 | 128 | /* 129 | * Chain (sub)maps 130 | * 131 | * ASM 0c08 132 | * return: TRUE/next submap OK, FALSE/map finished 133 | */ 134 | World.chain = function() { 135 | var c, t; 136 | 137 | Game.chsm = 0; 138 | ESbonus.counting = false; 139 | 140 | /* find connection */ 141 | c = World.submaps[Game.submap].connect; 142 | t = 3; 143 | /* 144 | IFDEBUG_MAPS( 145 | sys_printf("xrick/maps: chain submap=%#04x frow=%#04x .connect=%#04x %s\n", 146 | game_submap, map_frow, c, 147 | (game_dir == LEFT ? "-> left" : "-> right")); 148 | ); 149 | */ 150 | /* 151 | * look for the first connector with compatible row number. if none 152 | * found, then panic 153 | */ 154 | for (c = World.submaps[Game.submap].connect; ; c++) { 155 | if (World.connect[c].dir == 0xff) { 156 | sys_panic("(map_chain) can not find connector\n"); 157 | } 158 | if (World.connect[c].dir != Game.dir) { continue; } 159 | t = (Ent.ents[1].y >> 3) + World.frow - World.connect[c].rowout; 160 | if (t < 3) { break; } 161 | } 162 | 163 | /* got it */ 164 | /* IFDEBUG_MAPS( 165 | sys_printf("xrick/maps: chain frow=%#04x y=%#06x\n", 166 | map_frow, ent_ents[1].y); 167 | sys_printf("xrick/maps: chain connect=%#04x rowout=%#04x - ", 168 | c, map_connect[c].rowout); 169 | ); 170 | */ 171 | 172 | if (World.connect[c].submap == 0xff) { 173 | /* no next submap - request next map */ 174 | /* IFDEBUG_MAPS( 175 | sys_printf("chain to next map\n"); 176 | );*/ 177 | return false; 178 | 179 | } else { 180 | /* next submap */ 181 | /* IFDEBUG_MAPS( 182 | sys_printf("chain to submap=%#04x rowin=%#04x\n", 183 | map_connect[c].submap, map_connect[c].rowin); 184 | );*/ 185 | World.frow = World.frow - World.connect[c].rowout + World.connect[c].rowin; 186 | Game.submap = World.connect[c].submap; 187 | /* IFDEBUG_MAPS( 188 | sys_printf("xrick/maps: chain frow=%#04x\n", 189 | map_frow); 190 | );*/ 191 | return true; 192 | } 193 | } 194 | 195 | /* 196 | * Reset all marks, i.e. make them all active again. 197 | * 198 | * ASM 0025 199 | * 200 | */ 201 | World.resetMarks = function() { 202 | var i; 203 | 204 | for (i = 0; i < MAP_NBR_MARKS; i++) { 205 | World.marks[i].ent &= ~MAP_MARK_NACT; 206 | } 207 | } 208 | 209 | /* EOF */ 210 | })(); 211 | -------------------------------------------------------------------------------- /source/rects.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | /* 4 | * Free a list of rectangles and set the pointer to NULL. 5 | * 6 | * p: rectangle list CHANGED to NULL 7 | */ 8 | Rects.free = function(r) { 9 | if (r) { 10 | r.splice(0, r.length); 11 | } 12 | } 13 | 14 | /* 15 | * Add a rectangle to a list of rectangles 16 | */ 17 | Rects.create = function(x, y, width, height, next) { // was new() 18 | var r; 19 | 20 | r = new G.Rect(x, y, width, height); 21 | next = next || []; 22 | next.unshift(r); 23 | return next; 24 | } 25 | 26 | /* EOF */ 27 | })(); 28 | -------------------------------------------------------------------------------- /source/scr_gameover.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | /* 4 | * Display the game over screen 5 | * 6 | * return: SCREEN_RUNNING, SCREEN_DONE, SCREEN_EXIT 7 | */ 8 | var seq = 0; /* static */ 9 | var period = 0; /* static */ 10 | var tm = 0; /* static */ 11 | 12 | Screen.gameover = function() { 13 | 14 | if (seq == 0) { 15 | Draw.tilesBank = 0; 16 | seq = 1; 17 | period = Game.period; /* save period, */ 18 | Game.period = 50; /* and use our own */ 19 | Game.setmusic("WAV_GAMEOVER", 1); 20 | } 21 | 22 | switch (seq) { 23 | case 1: /* display banner */ 24 | Sysvid.clear(); 25 | tm = Date.now(); 26 | 27 | Draw.tllst = Screen.gameovertxt.split(""); 28 | Draw.setfb(120, 80); 29 | Draw.tilesList(); 30 | Draw.drawStatus(); 31 | 32 | Game.rects = [Draw.SCREENRECT]; 33 | seq = 2; 34 | break; 35 | 36 | case 2: /* wait for key pressed */ 37 | if (Control.status & CONTROL_FIRE) { 38 | seq = 3; 39 | } else if (Date.now() - tm > SCREEN_TIMEOUT) { 40 | seq = 4; 41 | } 42 | // else { 43 | // sys_sleep(50); 44 | // } 45 | break; 46 | 47 | case 3: /* wait for key released */ 48 | if (!(Control.status & CONTROL_FIRE)) { 49 | seq = 4; 50 | } 51 | // else { 52 | // sys_sleep(50); 53 | // } 54 | break; 55 | } 56 | 57 | if (Control.status & CONTROL_EXIT) /* check for exit request */ 58 | return SCREEN_EXIT; 59 | 60 | if (seq == 4) { /* we're done */ 61 | Sysvid.clear(); 62 | seq = 0; 63 | Game.period = period; 64 | return SCREEN_DONE; 65 | } 66 | 67 | return SCREEN_RUNNING; 68 | } 69 | 70 | /* EOF */ 71 | })(); 72 | -------------------------------------------------------------------------------- /source/scr_getname.js: -------------------------------------------------------------------------------- 1 | /* 2 | * RickJS, a JavaScript port of XRick 3 | * 4 | * This source file is based on the folliwing files: 5 | * - xrick/src/scr_getname.c 6 | * 7 | * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved. 8 | * Copyright (C) 2012 Chrilith (me@chrilith.com). All rights reserved. 9 | * 10 | * The use and distribution terms for this software are contained in the file 11 | * named README, which can be found in the root of this distribution. By 12 | * using this software in any fashion, you are agreeing to be bound by the 13 | * terms of this license. 14 | * 15 | * You must not remove this notice, or any other, from this software. 16 | */ 17 | 18 | /* 19 | * constants 20 | */ 21 | var TILE_POINTER = 0x3A, // \072 22 | TILE_CURSOR = 0x3B, // \073 23 | TOPLEFT_X = 116, 24 | TOPLEFT_Y = 64, 25 | NAMEPOS_X = 120, 26 | NAMEPOS_Y = 160, 27 | AUTOREPEAT_TMOUT = 100; 28 | 29 | (function() { 30 | /* 31 | * local vars 32 | */ 33 | var seq = 0, 34 | x, y, p, 35 | name = []; 36 | 37 | /* 38 | * Get name 39 | * 40 | * return: 0 while running, 1 when finished. 41 | */ 42 | var tm = 0; // static 43 | Screen.getname = function() { 44 | var i, j; 45 | 46 | if (seq == 0) { 47 | /* figure out if this is a high score */ 48 | if (Game.score < Game.hscores[7].score) { 49 | return SCREEN_DONE; 50 | } 51 | 52 | /* prepare */ 53 | Draw.tilesBank = 0; 54 | for (i = 0; i < 10; i++) { 55 | name[i] = '@'.charCodeAt(0); 56 | } 57 | x = 5; 58 | y = 4; 59 | p = 0; 60 | Game.rects = [Draw.SCREENRECT]; 61 | seq = 1; 62 | } 63 | 64 | switch (seq) { 65 | 66 | case 1: /* prepare screen */ 67 | Sysvid.clear(); 68 | 69 | Draw.pic(36, 4, 244, 22, Data.getItem("pic_congrat")); 70 | 71 | Draw.setfb(72, 40); 72 | Draw.tilesListImm("PLEASE@ENTER@YOUR@NAME\xFE"); 73 | for (i = 0; i < 6; i++) { 74 | for (j = 0; j < 4; j++) { 75 | Draw.setfb(TOPLEFT_X + i * 8 * 2, TOPLEFT_Y + j * 8 * 2); 76 | Draw.tile('A'.charCodeAt(0) + i + j * 6); 77 | } 78 | } 79 | Draw.setfb(TOPLEFT_X, TOPLEFT_Y + 64); 80 | Draw.tilesListImm("Y@Z@.@@@\x3C\xFB\xFC\xFD\xFE"); 81 | name_draw(); 82 | pointer_show(true); 83 | seq = 2; 84 | break; 85 | 86 | case 2: /* wait for key pressed */ 87 | if (Control.status & CONTROL_FIRE) { 88 | seq = 3; 89 | } 90 | if (Control.status & CONTROL_UP) { 91 | if (y > 0) { 92 | pointer_show(false); 93 | y--; 94 | pointer_show(true); 95 | tm = Sys.gettime(); 96 | } 97 | seq = 4; 98 | } 99 | if (Control.status & CONTROL_DOWN) { 100 | if (y < 4) { 101 | pointer_show(false); 102 | y++; 103 | pointer_show(true); 104 | tm = Sys.gettime(); 105 | } 106 | seq = 5; 107 | } 108 | if (Control.status & CONTROL_LEFT) { 109 | if (x > 0) { 110 | pointer_show(false); 111 | x--; 112 | pointer_show(true); 113 | tm = Sys.gettime(); 114 | } 115 | seq = 6; 116 | } 117 | if (Control.status & CONTROL_RIGHT) { 118 | if (x < 5) { 119 | pointer_show(false); 120 | x++; 121 | pointer_show(true); 122 | tm = Sys.gettime(); 123 | } 124 | seq = 7; 125 | } 126 | if (seq == 2) { 127 | //sys_sleep(50); 128 | } 129 | break; 130 | 131 | case 3: /* wait for FIRE released */ 132 | if (!(Control.status & CONTROL_FIRE)) { 133 | if (x == 5 && y == 4) { /* end */ 134 | i = 0; 135 | while (Game.score < Game.hscores[i].score) { 136 | i++; 137 | } 138 | j = 7; 139 | while (j > i) { 140 | Game.hscores[j].score = Game.hscores[j - 1].score; 141 | // for (x = 0; x < 10; x++) { 142 | Game.hscores[j].name = Game.hscores[j - 1].name; 143 | // } 144 | j--; 145 | } 146 | Game.hscores[i].score = Game.score; 147 | var tmp = ""; 148 | for (x = 0; x < 10; x++) { 149 | tmp += String.fromCharCode(name[x]); 150 | } 151 | Game.hscores[i].name = tmp; 152 | seq = 99; 153 | } else { 154 | name_update(); 155 | name_draw(); 156 | seq = 2; 157 | } 158 | } else { 159 | // sys_sleep(50); 160 | } 161 | break; 162 | 163 | case 4: /* wait for UP released */ 164 | if (!(Control.status & CONTROL_UP) || 165 | Sys.gettime() - tm > AUTOREPEAT_TMOUT) { 166 | seq = 2; 167 | } else { 168 | // sys_sleep(50); 169 | } 170 | break; 171 | 172 | case 5: /* wait for DOWN released */ 173 | if (!(Control.status & CONTROL_DOWN) || 174 | Sys.gettime() - tm > AUTOREPEAT_TMOUT) { 175 | seq = 2; 176 | } else { 177 | // sys_sleep(50); 178 | } 179 | break; 180 | 181 | case 6: /* wait for LEFT released */ 182 | if (!(Control.status & CONTROL_LEFT) || 183 | Sys.gettime() - tm > AUTOREPEAT_TMOUT) { 184 | seq = 2; 185 | } else { 186 | // sys_sleep(50); 187 | } 188 | break; 189 | 190 | case 7: /* wait for RIGHT released */ 191 | if (!(Control.status & CONTROL_RIGHT) || 192 | Sys.gettime() - tm > AUTOREPEAT_TMOUT) { 193 | seq = 2; 194 | } else { 195 | // sys_sleep(50); 196 | } 197 | break; 198 | } 199 | 200 | if (Control.status & CONTROL_EXIT) { /* check for exit request */ 201 | return SCREEN_EXIT; 202 | } 203 | 204 | if (seq == 99) { /* seq 99, we're done */ 205 | Sysvid.clear(); 206 | seq = 0; 207 | return SCREEN_DONE; 208 | } else { 209 | return SCREEN_RUNNING; 210 | } 211 | } 212 | 213 | 214 | function pointer_show(show) { 215 | Draw.setfb(TOPLEFT_X + x * 8 * 2, TOPLEFT_Y + y * 8 * 2 + 8); 216 | Draw.tile((show == true)?TILE_POINTER:'@'.charCodeAt(0)); 217 | } 218 | 219 | function name_update() { 220 | var i; 221 | 222 | i = x + y * 6; 223 | if (i < 26 && p < 10) { 224 | name[p++] = 'A'.charCodeAt(0) + i; 225 | } 226 | if (i == 26 && p < 10) { 227 | name[p++] = '.'.charCodeAt(0); 228 | } 229 | if (i == 27 && p < 10) { 230 | name[p++] = '@'.charCodeAt(0); 231 | } 232 | if (i == 28 && p > 0) { 233 | p--; 234 | } 235 | } 236 | 237 | 238 | function name_draw() { 239 | var i; 240 | 241 | Draw.setfb(NAMEPOS_X, NAMEPOS_Y); 242 | 243 | for (i = 0; i < p; i++) { 244 | Draw.tile(name[i]); 245 | } 246 | for (i = p; i < 10; i++) { 247 | Draw.tile(TILE_CURSOR); 248 | } 249 | 250 | Draw.setfb(NAMEPOS_X, NAMEPOS_Y + 8); 251 | for (i = 0; i < 10; i++) { 252 | Draw.tile('@'.charCodeAt(0)); 253 | } 254 | Draw.setfb(NAMEPOS_X + 8 * (p < 9 ? p : 9), NAMEPOS_Y + 8); 255 | Draw.tile(TILE_POINTER); 256 | } 257 | 258 | /* EOF */ 259 | })(); 260 | -------------------------------------------------------------------------------- /source/scr_imain.js: -------------------------------------------------------------------------------- 1 | /* 2 | * RickJS, a JavaScript port of XRick 3 | * 4 | * This source file is based on the folliwing files: 5 | * - xrick/src/scr_imain.c 6 | * 7 | * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved. 8 | * Copyright (C) 2012 Chrilith (me@chrilith.com). All rights reserved. 9 | * 10 | * The use and distribution terms for this software are contained in the file 11 | * named README, which can be found in the root of this distribution. By 12 | * using this software in any fashion, you are agreeing to be bound by the 13 | * terms of this license. 14 | * 15 | * You must not remove this notice, or any other, from this software. 16 | */ 17 | 18 | (function() { 19 | /* 20 | * static 21 | */ 22 | var seq = 0, 23 | seen = 0, 24 | first = true, 25 | period = 0, 26 | tm = 0, 27 | i , s = [], 28 | fading; 29 | 30 | /* 31 | * Main introduction 32 | * 33 | * return: SCREEN_RUNNING, SCREEN_DONE, SCREEN_EXIT 34 | */ 35 | Screen.introMain = function(timer) { 36 | if (seq == 0) { 37 | Draw.tilesBank = 0; 38 | if (first == true) { 39 | seq = 1; 40 | } else { 41 | seq = 4; 42 | } 43 | period = Game.period; 44 | Game.period = 50; 45 | Game.rects = [Draw.SCREENRECT]; 46 | Game.setmusic("WAV_TUNE5", -1); 47 | } 48 | 49 | switch (seq) { 50 | case 1: /* display Rick Dangerous title and Core Design copyright */ 51 | if (fading) { 52 | break; 53 | } 54 | Sysvid.clear(); 55 | tm = Sys.gettime(); 56 | Draw.pic(0, 0, 0x140, 0xc8, Data.getItem("pic_splash")); 57 | seq = 2; 58 | 59 | fading = GE.Fader.IN; 60 | Sysvid.fade_start(); 61 | break; 62 | 63 | case 2: /* wait for key pressed or timeout */ 64 | if (Control.status & CONTROL_FIRE) { 65 | seq = 3; 66 | } else if (Sys.gettime() - tm > SCREEN_TIMEOUT) { 67 | seen++; 68 | seq = 4; 69 | 70 | fading = GE.Fader.OUT; 71 | Sysvid.fade_start(); 72 | } 73 | break; 74 | 75 | case 3: /* wait for key released */ 76 | 77 | if (!(Control.status & CONTROL_FIRE)) { 78 | if (seen++ == 0) { 79 | seq = 4; 80 | } else { 81 | seq = 7; 82 | 83 | fading = GE.Fader.OUT; 84 | Sysvid.fade_start(); 85 | } 86 | } 87 | break; 88 | 89 | case 4: /* dispay hall of fame */ 90 | if (fading) { 91 | break; 92 | } 93 | Sysvid.clear(); 94 | tm = Sys.gettime(); 95 | 96 | /* hall of fame title */ 97 | Draw.pic(64, 4, 190, 22, Data.getItem("pic_haf")); 98 | 99 | /* hall of fame content */ 100 | Draw.setfb(56, 48); 101 | 102 | for (i = 0; i < 8; i++) { 103 | var score = ("00" + Game.hscores[i].score).substr(-6); 104 | Draw.tllst = (score + 105 | "@@@====@@@" + 106 | Game.hscores[i].name + 107 | "\xFF\xFF\xFE").split(""); // \377\377\376 108 | Draw.tilesList(); 109 | } 110 | 111 | seq = 5; 112 | 113 | fading = GE.Fader.IN; 114 | Sysvid.fade_start(); 115 | break; 116 | 117 | case 5: /* wait for key pressed or timeout */ 118 | 119 | if (Control.status & CONTROL_FIRE) { 120 | seq = 6; 121 | } else if (Sys.gettime() - tm > SCREEN_TIMEOUT) { 122 | seen++; 123 | seq = 1; 124 | 125 | fading = GE.Fader.OUT; 126 | Sysvid.fade_start(); 127 | } 128 | break; 129 | 130 | case 6: /* wait for key released */ 131 | if (!(Control.status & CONTROL_FIRE)) { 132 | if (seen++ == 0) { 133 | seq = 1; 134 | } else { 135 | seq = 7; 136 | 137 | fading = GE.Fader.OUT; 138 | Sysvid.fade_start(); 139 | } 140 | } 141 | break; 142 | } 143 | 144 | if (fading) { 145 | Game.rects = [Draw.SCREENRECT]; 146 | if (!Sysvid.fader.update(timer, fading)) { 147 | fading = Sysvid.fade_end(); 148 | // Loop directly to prevent flipping 149 | if (seq !=7) { 150 | Screen.introMain(timer); 151 | } 152 | } 153 | } 154 | 155 | if (Control.status & CONTROL_EXIT) { /* check for exit request */ 156 | return SCREEN_EXIT; 157 | } 158 | 159 | if (seq == 7 && !fading) { /* we're done */ 160 | Sysvid.clear(); 161 | seq = 0; 162 | seen = 0; 163 | first = false; 164 | Game.period = period; 165 | return SCREEN_DONE; 166 | } else { 167 | return SCREEN_RUNNING; 168 | } 169 | } 170 | 171 | /* EOF */ 172 | })(); 173 | -------------------------------------------------------------------------------- /source/scr_imap.js: -------------------------------------------------------------------------------- 1 | /* const 2 | ********/ 3 | // ... 4 | var SCREEN_TIMEOUT = 4000; 5 | 6 | (function() { 7 | /* local 8 | ********/ 9 | var step, /* current step */ 10 | count, /* number of loops for current step */ 11 | run, /* 1 = run, 0 = no more step */ 12 | flipflop = 0, /* flipflop for top, bottom, left, right */ 13 | spnum, /* sprite number */ 14 | spx, spdx, /* sprite x position and delta */ 15 | spy, spdy, /* sprite y position and delta */ 16 | spbase, spoffs, /* base, offset for sprite numbers table */ 17 | seq = 0, /* anim sequence */ 18 | fading; 19 | 20 | var anim_rect = new G.Rect(128, 16 + 16, 64, 64); /* anim rectangle */ 21 | 22 | /* global 23 | *********/ 24 | Screen.introMap = function(timer) { 25 | switch (seq) { 26 | case 0: 27 | Sysvid.clear(); 28 | Draw.tilesBank = 0; 29 | Draw.tllst = Screen.imaptext[Game.map].split(""); 30 | 31 | Draw.setfb(40, 16); 32 | Draw.tilesSubList(); 33 | 34 | Draw.setfb(40, 104); 35 | Draw.tilesList(); 36 | 37 | Game.rects = null; 38 | 39 | init(); 40 | 41 | nextstep(); 42 | drawcenter(); 43 | drawtb(); 44 | drawlr(); 45 | drawsprite(); 46 | Draw.drawStatus(); 47 | Control.last = 0; 48 | 49 | Game.rects = [Draw.SCREENRECT]; 50 | 51 | Game.setmusic(World.maps[Game.map].tune, 1); 52 | 53 | seq = 1; 54 | fading = GE.Fader.IN; 55 | Sysvid.fade_start(); 56 | break; 57 | 58 | case 1: /* top and bottom borders */ 59 | drawtb(); 60 | Game.rects = [anim_rect]; 61 | seq = 2; 62 | break; 63 | 64 | case 2: /* background and sprite */ 65 | anim(); 66 | drawcenter(); 67 | drawsprite(); 68 | Game.rects = [anim_rect]; 69 | seq = 3; 70 | break; 71 | 72 | case 3: /* all borders */ 73 | drawtb(); 74 | drawlr(); 75 | Game.rects = [anim_rect]; 76 | seq = 1; 77 | break; 78 | 79 | case 4: /* wait for key release */ 80 | if (!(Control.status & CONTROL_FIRE)) { 81 | seq = 5; 82 | } else { 83 | Sys.sleep(50); /* .5s */ 84 | } 85 | break; 86 | } 87 | 88 | if (Control.status & CONTROL_FIRE) { /* end as soon as key pressed */ 89 | seq = 4; 90 | fading = GE.Fader.OUT; 91 | Sysvid.fade_start(); 92 | } 93 | 94 | if (fading) { 95 | Game.rects = [Draw.SCREENRECT]; 96 | if (!Sysvid.fader.update(timer, fading)) { 97 | fading = Sysvid.fade_end(); 98 | } 99 | } 100 | 101 | if (Control.status & CONTROL_EXIT) /* check for exit request */ 102 | return SCREEN_EXIT; 103 | 104 | if (seq == 5 && !fading) { /* end as soon as key pressed */ 105 | Sysvid.clear(); 106 | seq = 0; 107 | return SCREEN_DONE; 108 | } else { 109 | return SCREEN_RUNNING; 110 | } 111 | } 112 | 113 | /* local 114 | ********/ 115 | 116 | /* 117 | * Display top and bottom borders (0x1B1F) 118 | * 119 | */ 120 | function drawtb() { 121 | var i; 122 | 123 | flipflop++; 124 | if (flipflop & 0x01) { 125 | Draw.setfb(136, 16 + 16); 126 | for (i = 0; i < 6; i++) { 127 | Draw.tile(0x40); 128 | } 129 | Draw.setfb(136, 72 + 16); 130 | for (i = 0; i < 6; i++) { 131 | Draw.tile(0x06); 132 | } 133 | } else { 134 | Draw.setfb(136, 16 + 16); 135 | for (i = 0; i < 6; i++) { 136 | Draw.tile(0x05); 137 | } 138 | Draw.setfb(136, 72 + 16); 139 | for (i = 0; i < 6; i++) { 140 | Draw.tile(0x40); 141 | } 142 | } 143 | } 144 | 145 | /* 146 | * Display left and right borders (0x1B7C) 147 | * 148 | */ 149 | function drawlr() { 150 | var i; 151 | 152 | if (flipflop & 0x02) { 153 | for (i = 0; i < 8; i++) { 154 | Draw.setfb(128, 16 + i * 8 + 16); 155 | Draw.tile(0x04); 156 | Draw.setfb(184, 16 + i * 8 + 16); 157 | Draw.tile(0x04); 158 | } 159 | } else { 160 | for (i = 0; i < 8; i++) { 161 | Draw.setfb(128, 16 + i * 8 + 16); 162 | Draw.tile(0x2B); 163 | Draw.setfb(184, 16 + i * 8 + 16); 164 | Draw.tile(0x2B); 165 | } 166 | } 167 | } 168 | 169 | /* 170 | * Draw the sprite (0x19C6) 171 | * 172 | */ 173 | function drawsprite() { 174 | Draw.sprite(spnum, 136 + ((spx << 1) & 0x1C), 24 + (spy << 1) + 16); 175 | } 176 | 177 | /* 178 | * Draw the background (0x1AF1) 179 | * 180 | */ 181 | function drawcenter() { 182 | var tn0 = [ 0x07, 0x5B, 0x7F, 0xA3, 0xC7 ], 183 | i, j, tn = tn0[Game.map]; 184 | 185 | for (i = 0; i < 6; i++) { 186 | Draw.setfb(136, (24 + 8 * i) + 16); 187 | for (j = 0; j < 6; j++) { 188 | Draw.tile(tn++); 189 | } 190 | } 191 | } 192 | 193 | /* 194 | * Next Step (0x1A74) 195 | * 196 | */ 197 | function nextstep() { 198 | if (Screen.imapsteps[step].count) { 199 | count = Screen.imapsteps[step].count; 200 | spdx = Screen.imapsteps[step].dx; 201 | spdy = Screen.imapsteps[step].dy; 202 | spbase = Screen.imapsteps[step].base; 203 | spoffs = 0; 204 | step++; 205 | } else { 206 | run = 0; 207 | } 208 | } 209 | 210 | /* 211 | * Anim (0x1AA8) 212 | * 213 | */ 214 | function anim() { 215 | var i; 216 | 217 | if (run) { 218 | i = Screen.imapsl[spbase + spoffs]; 219 | if (i == 0) { 220 | spoffs = 0; 221 | i = Screen.imapsl[spbase]; 222 | } 223 | spnum = i; 224 | spoffs++; 225 | spx += spdx; 226 | spy += spdy; 227 | count--; 228 | if (count == 0) { 229 | nextstep(); 230 | } 231 | } 232 | } 233 | 234 | function init() { 235 | run = 0; run--; 236 | step = Screen.imapsofs[Game.map]; 237 | spx = Screen.imapsteps[step].dx; 238 | spy = Screen.imapsteps[step].dy; 239 | step++; 240 | spnum = 0; /* NOTE spnum in [8728] is never initialized ? */ 241 | } 242 | 243 | /* EOF */ 244 | })(); 245 | -------------------------------------------------------------------------------- /source/scr_pause.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | /* 4 | * Display the pause indicator 5 | */ 6 | Screen.pause = function(pause) { 7 | if (pause == true) { 8 | Draw.tilesBank = 0; 9 | Draw.tllst = Screen.pausedtxt.split(""); 10 | Draw.setfb(120, 80); 11 | Draw.tilesList(); 12 | } else { 13 | Draw.map(); 14 | Ent.draw(); 15 | Draw.drawStatus(); 16 | } 17 | Game.rects = [Draw.SCREENRECT]; 18 | } 19 | 20 | /* EOF */ 21 | })(); 22 | -------------------------------------------------------------------------------- /source/scr_xrick.js: -------------------------------------------------------------------------------- 1 | /* const 2 | ********/ 3 | var SCREEN_RUNNING = 0, 4 | SCREEN_DONE = 1, 5 | SCREEN_EXIT = 2; 6 | 7 | (function() { 8 | /* local 9 | ********/ 10 | var seq = 0, 11 | wait = 0; 12 | 13 | /* global 14 | *********/ 15 | Screen.xrick = function(timer) { 16 | 17 | if (seq == 0) { 18 | Sysvid.clear(); 19 | // draw_img(IMG_SPLASH); 20 | Game.rects = [Draw.SCREENRECT]; 21 | seq = 1; 22 | } 23 | 24 | switch (seq) { 25 | case 1: 26 | if (wait++ > 0x2) { 27 | Syssnd.play("WAV_BULLET", 1); 28 | seq = 2; 29 | wait = 0; 30 | } 31 | break; 32 | 33 | case 2: /* wait */ 34 | if (wait++ > 0x20) { 35 | seq = 99; 36 | wait = 0; 37 | } 38 | break; 39 | } 40 | 41 | if (Control.status & CONTROL_EXIT) { /* check for exit request */ 42 | return SCREEN_EXIT; 43 | } 44 | 45 | if (seq == 99) { /* we're done */ 46 | Sysvid.clear(); 47 | Sysvid.setGamePalette(); 48 | seq = 0; 49 | return SCREEN_DONE; 50 | } 51 | 52 | return SCREEN_RUNNING; 53 | } 54 | 55 | /* EOF */ 56 | })(); 57 | -------------------------------------------------------------------------------- /source/screens.js: -------------------------------------------------------------------------------- 1 | /* 2 | * RickJS, a JavaScript port of XRick 3 | * 4 | * This source file is based on the folliwing files: 5 | * - xrick/src/screens.h 6 | * 7 | * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved. 8 | * Copyright (C) 2012 Chrilith (me@chrilith.com). All rights reserved. 9 | * 10 | * The use and distribution terms for this software are contained in the file 11 | * named README, which can be found in the root of this distribution. By 12 | * using this software in any fashion, you are agreeing to be bound by the 13 | * terms of this license. 14 | * 15 | * You must not remove this notice, or any other, from this software. 16 | */ 17 | 18 | /* 19 | * constants 20 | */ 21 | var SCREEN_TIMEOUT = 4000; 22 | -------------------------------------------------------------------------------- /source/scroller.js: -------------------------------------------------------------------------------- 1 | /* const 2 | ********/ 3 | var SCROLL_RUNNING = 1, 4 | SCROLL_DONE = 0, 5 | 6 | SCROLL_PERIOD = 24; 7 | 8 | 9 | (function() { 10 | /* local 11 | ********/ 12 | var period; 13 | 14 | /* global 15 | *********/ 16 | /* 17 | * Scroll up 18 | * 19 | */ 20 | var static_n1 = 0; 21 | Scroll.up = function() { 22 | var i, j; 23 | 24 | /* last call: restore */ 25 | if (static_n1 == 8) { 26 | static_n1 = 0; 27 | Game.period = period; 28 | return SCROLL_DONE; 29 | } 30 | 31 | /* first call: prepare */ 32 | if (static_n1 == 0) { 33 | period = Game.period; 34 | Game.period = SCROLL_PERIOD; 35 | } 36 | 37 | /* translate map */ 38 | for (i = MAP_ROW_SCRTOP; i < MAP_ROW_HBBOT; i++) { 39 | for (j = 0x00; j < 0x20; j++) { 40 | World.map[i][j] = World.map[i + 1][j]; 41 | } 42 | } 43 | 44 | /* translate entities */ 45 | for (i = 0; Ent.ents[i].n != 0xFF; i++) { 46 | if (Ent.ents[i].n) { 47 | Ent.ents[i].ysave -= 8; 48 | Ent.ents[i].trig_y -= 8; 49 | Ent.ents[i].y -= 8; 50 | if (Ent.ents[i].y & 0x8000) { /* map coord. from 0x0000 to 0x0140 */ 51 | /* IFDEBUG_SCROLLER( 52 | sys_printf("xrick/scroller: entity %#04X is gone\n", i); 53 | );*/ 54 | Ent.ents[i].n = 0; 55 | } 56 | } 57 | } 58 | 59 | /* display */ 60 | Draw.map(); 61 | Ent.draw(); 62 | Draw.drawStatus(); 63 | World.frow++; 64 | 65 | /* loop */ 66 | if (static_n1++ == 7) { 67 | /* activate visible entities */ 68 | Ent.actvis(World.frow + MAP_ROW_HBTOP, World.frow + MAP_ROW_HBBOT); 69 | 70 | /* prepare map */ 71 | World.expand(); 72 | 73 | /* display */ 74 | Draw.map(); 75 | Ent.draw(); 76 | Draw.drawStatus(); 77 | } 78 | 79 | Game.rects = [Draw.SCREENRECT]; 80 | 81 | return SCROLL_RUNNING; 82 | } 83 | 84 | /* 85 | * Scroll down 86 | * 87 | */ 88 | var static_n2 = 0; 89 | Scroll.down =function() { 90 | var i, j; 91 | 92 | /* last call: restore */ 93 | if (static_n2 == 8) { 94 | static_n2 = 0; 95 | Game.period = period; 96 | return SCROLL_DONE; 97 | } 98 | 99 | /* first call: prepare */ 100 | if (static_n2 == 0) { 101 | period = Game.period; 102 | Game.period = SCROLL_PERIOD; 103 | } 104 | 105 | /* translate map */ 106 | for (i = MAP_ROW_SCRBOT; i > MAP_ROW_HTTOP; i--) { 107 | for (j = 0x00; j < 0x20; j++) { 108 | World.map[i][j] = World.map[i - 1][j]; 109 | } 110 | } 111 | 112 | /* translate entities */ 113 | for (i = 0; Ent.ents[i].n != 0xFF; i++) { 114 | if (Ent.ents[i].n) { 115 | Ent.ents[i].ysave += 8; 116 | Ent.ents[i].trig_y += 8; 117 | Ent.ents[i].y += 8; 118 | if (Ent.ents[i].y > 0x0140) { /* map coord. from 0x0000 to 0x0140 */ 119 | /* IFDEBUG_SCROLLER( 120 | sys_printf("xrick/scroller: entity %#04X is gone\n", i); 121 | );*/ 122 | Ent.ents[i].n = 0; 123 | } 124 | } 125 | } 126 | 127 | /* display */ 128 | Draw.map(); 129 | Ent.draw(); 130 | Draw.drawStatus(); 131 | World.frow--; 132 | 133 | /* loop */ 134 | if (static_n2++ == 7) { 135 | /* activate visible entities */ 136 | Ent.actvis(World.frow + MAP_ROW_HTTOP, World.frow + MAP_ROW_HTBOT); 137 | 138 | /* prepare map */ 139 | World.expand(); 140 | 141 | /* display */ 142 | Draw.map(); 143 | Ent.draw(); 144 | Draw.drawStatus(); 145 | } 146 | 147 | Game.rects = [Draw.SCREENRECT]; 148 | 149 | return SCROLL_RUNNING; 150 | } 151 | 152 | /* EOF */ 153 | })(); 154 | -------------------------------------------------------------------------------- /source/sysarg.js: -------------------------------------------------------------------------------- 1 | /* 2 | * RickJS, a JavaScript port of XRick 3 | * 4 | * This source file is based on the folliwing files: 5 | * - xrick/src/sysarg.c 6 | * 7 | * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved. 8 | * Copyright (C) 2012 Chrilith (me@chrilith.com). All rights reserved. 9 | * 10 | * The use and distribution terms for this software are contained in the file 11 | * named README, which can be found in the root of this distribution. By 12 | * using this software in any fashion, you are agreeing to be bound by the 13 | * terms of this license. 14 | * 15 | * You must not remove this notice, or any other, from this software. 16 | */ 17 | 18 | (function() { 19 | 20 | Sysarg.args_map = 0; 21 | Sysarg.args_submap = 0; 22 | 23 | /* 24 | * Read and process arguments 25 | */ 26 | Sysarg.init = function() { 27 | var argv = new G.CommandLine(); 28 | 29 | if (argv.hasParam("map")) { 30 | //if (++i == argc) sysarg_fail("missing map number"); 31 | Sysarg.args_map = parseInt(argv.getParam("map"), 10) - 1; 32 | // if (sysarg_args_map < 0 || sysarg_args_map >= MAP_NBR_MAPS-1) 33 | // sysarg_fail("invalid map number"); 34 | } 35 | 36 | if (argv.hasParam("submap")) { 37 | // if (++i == argc) sysarg_fail("missing submap number"); 38 | Sysarg.args_submap = parseInt(argv.getParam("submap"), 10) - 1; 39 | // if (sysarg_args_submap < 0 || sysarg_args_submap >= MAP_NBR_SUBMAPS) 40 | // sysarg_fail("invalid submap number"); 41 | } 42 | 43 | /* this is dirty (sort of) */ 44 | if (Sysarg.args_submap > 0 && Sysarg.args_submap < 9) { 45 | Sysarg.args_map = 0; 46 | } 47 | 48 | if (Sysarg.args_submap >= 9 && Sysarg.args_submap < 20) { 49 | Sysarg.args_map = 1; 50 | } 51 | 52 | if (Sysarg.args_submap >= 20 && Sysarg.args_submap < 38) { 53 | Sysarg.args_map = 2; 54 | } 55 | 56 | if (Sysarg.args_submap >= 38) { 57 | Sysarg.args_map = 3; 58 | } 59 | 60 | if (Sysarg.args_submap == 9 || 61 | Sysarg.args_submap == 20 || 62 | Sysarg.args_submap == 38) { 63 | 64 | Sysarg.args_submap = 0; 65 | } 66 | } 67 | 68 | /* EOF */ 69 | })(); 70 | -------------------------------------------------------------------------------- /source/sysevt.js: -------------------------------------------------------------------------------- 1 | 2 | (function() { 3 | /* local 4 | ********/ 5 | var gamepad, MAN = G.EventManager, 6 | eventMan = new G.EventManager(MAN.BIT_KEYBOARD/*|MAN.BIT_KBICADE*/); 7 | 8 | function TSTBIT(b) { 9 | return (Control.status && b) == b; 10 | } 11 | function SETBIT(b) { 12 | Control.status |= (b); 13 | } 14 | function CLRBIT(b) { 15 | Control.status &= ~(b); 16 | } 17 | 18 | function processGamepad() { 19 | if (!gamepad) { return; } 20 | 21 | CLRBIT(CONTROL_UP); 22 | CLRBIT(CONTROL_DOWN); 23 | CLRBIT(CONTROL_LEFT); 24 | CLRBIT(CONTROL_RIGHT); 25 | CLRBIT(CONTROL_FIRE); 26 | 27 | if (gamepad.buttons[0]) { 28 | SETBIT(CONTROL_FIRE); 29 | } 30 | 31 | if (gamepad.axes[0] || gamepad.axes[1]) { 32 | var v = new G.Vector(gamepad.axes[0], gamepad.axes[1]), 33 | a = v.getAngle() * 180 / Math.PI, 34 | s = v.getLength(); 35 | 36 | a = (a + 22.5) % 360 / 45 | 0; 37 | 38 | if (a == 0) { 39 | SETBIT(CONTROL_UP); 40 | } else if (a == 1) { 41 | SETBIT(CONTROL_UP); 42 | SETBIT(CONTROL_RIGHT); 43 | } else if (a == 2) { 44 | SETBIT(CONTROL_RIGHT); 45 | } else if (a == 3) { 46 | SETBIT(CONTROL_RIGHT); 47 | SETBIT(CONTROL_DOWN); 48 | } else if (a == 4) { 49 | SETBIT(CONTROL_DOWN); 50 | } else if (a == 5) { 51 | SETBIT(CONTROL_DOWN); 52 | SETBIT(CONTROL_LEFT); 53 | } else if (a == 6) { 54 | SETBIT(CONTROL_LEFT); 55 | } else if (a == 7) { 56 | SETBIT(CONTROL_LEFT); 57 | SETBIT(CONTROL_UP); 58 | } 59 | } 60 | } 61 | 62 | function processEvent(event) { 63 | var key, E = G.Event; 64 | 65 | switch (event.type) { 66 | case E.KEYDOWN: 67 | key = event.keyCode; 68 | 69 | if (key == E.K_UP || key == E.K_ICADE_UP) { 70 | SETBIT(CONTROL_UP); 71 | Control.last = CONTROL_UP; 72 | 73 | } else if (key == E.K_DOWN || key == E.K_ICADE_DOWN) { 74 | SETBIT(CONTROL_DOWN); 75 | Control.last = CONTROL_DOWN; 76 | 77 | } else if (key == E.K_LEFT || key == E.K_ICADE_LEFT) { 78 | SETBIT(CONTROL_LEFT); 79 | Control.last = CONTROL_LEFT; 80 | 81 | } else if (key == E.K_RIGHT || key == E.K_ICADE_RIGHT) { 82 | SETBIT(CONTROL_RIGHT); 83 | Control.last = CONTROL_RIGHT; 84 | 85 | } else if (key == 'P'.charCodeAt(0) || key == E.K_ICADE_FIRE4) { 86 | SETBIT(CONTROL_PAUSE); 87 | Control.last = CONTROL_PAUSE; 88 | 89 | } else if (key == E.K_ESCAPE || key == E.K_ICADE_FIREX2) { 90 | SETBIT(CONTROL_END); 91 | Control.last = CONTROL_END; 92 | /* 93 | } else if (key == syskbd_xtra) { 94 | SETBIT(CONTROL_EXIT); 95 | Control.last = CONTROL_EXIT; 96 | */ 97 | } else if (key == E.K_SPACE || key == E.K_ICADE_FIRE1) { 98 | SETBIT(CONTROL_FIRE); 99 | Control.last = CONTROL_FIRE; 100 | } 101 | break; 102 | 103 | case E.KEYUP: 104 | key = event.keyCode; 105 | 106 | if (key == E.K_UP || key == E.K_ICADE_UP) { 107 | CLRBIT(CONTROL_UP); 108 | Control.last = CONTROL_UP; 109 | 110 | } else if (key == E.K_DOWN || key == E.K_ICADE_DOWN) { 111 | CLRBIT(CONTROL_DOWN); 112 | Control.last = CONTROL_DOWN; 113 | 114 | } else if (key == E.K_LEFT || key == E.K_ICADE_LEFT) { 115 | CLRBIT(CONTROL_LEFT); 116 | Control.last = CONTROL_LEFT; 117 | 118 | } else if (key == E.K_RIGHT || key == E.K_ICADE_RIGHT) { 119 | CLRBIT(CONTROL_RIGHT); 120 | Control.last = CONTROL_RIGHT; 121 | 122 | } else if (key == 'P'.charCodeAt(0) || key == E.K_ICADE_FIRE4) { 123 | CLRBIT(CONTROL_PAUSE); 124 | Control.last = CONTROL_PAUSE; 125 | 126 | } else if (key == 'S'.charCodeAt(0) || key == E.K_ICADE_FIREX1) { 127 | Sysvid.toggle_scanlines(); 128 | 129 | } else if (key == E.K_ESCAPE || key == E.K_ICADE_FIREX2) { 130 | CLRBIT(CONTROL_END); 131 | Control.last = CONTROL_END; 132 | /* 133 | } else if (key == syskbd_xtra) { 134 | CLRBIT(CONTROL_EXIT); 135 | Control.last = CONTROL_EXIT; 136 | */ 137 | } else if (key == E.K_SPACE || key == E.K_ICADE_FIRE1) { 138 | CLRBIT(CONTROL_FIRE); 139 | Control.last = CONTROL_FIRE; 140 | } 141 | break; 142 | } 143 | } 144 | 145 | /* global 146 | *********/ 147 | Sysevt.init = function() { 148 | /* var pad = document.getElementById("gamepad"), 149 | s1, s2, S = G.Shape; 150 | 151 | if (G.TouchGamepad.isSupported()) { 152 | pad.style.display = "block"; 153 | gamepad = new G.TouchGamepad("pad", pad); 154 | if (pad.offsetHeight == 120) { 155 | s1 = new G.Circle(65, 0, 55); 156 | s2 = new G.Circle(-50, 0, 30); 157 | } else { 158 | s1 = new G.Circle(100, 0, 90); 159 | s2 = new G.Circle(-100, 0, 40); 160 | } 161 | gamepad.addAxes(s1, S.ALIGN_LEFT | S.ALIGN_MIDDLE); 162 | gamepad.addButton(s2, S.ALIGN_RIGHT | S.ALIGN_MIDDLE); 163 | gamepad.setActive(true); 164 | } 165 | */ 166 | } 167 | 168 | Sysevt.poll = function() { 169 | var e; 170 | 171 | if (!gamepad || (!gamepad.connected)) { 172 | while ((e = eventMan.poll())) { 173 | processEvent(e); 174 | } 175 | } else { 176 | processGamepad(); 177 | } 178 | } 179 | 180 | Sysevt.wait = function() { 181 | Sysevt.poll(); 182 | } 183 | 184 | /* EOF */ 185 | })(); 186 | -------------------------------------------------------------------------------- /source/syssnd.js: -------------------------------------------------------------------------------- 1 | /* 2 | * RickJS, a JavaScript port of XRick 3 | * 4 | * This source file is based on the folliwing files: 5 | * - xrick/src/syssnd.c 6 | * 7 | * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved. 8 | * Copyright (C) 2012 Chrilith (me@chrilith.com). All rights reserved. 9 | * 10 | * The use and distribution terms for this software are contained in the file 11 | * named README, which can be found in the root of this distribution. By 12 | * using this software in any fashion, you are agreeing to be bound by the 13 | * terms of this license. 14 | * 15 | * You must not remove this notice, or any other, from this software. 16 | */ 17 | 18 | (function() { 19 | 20 | var mixer, 21 | A = G.AudioMixer; 22 | 23 | Syssnd.init = function() { 24 | mixer = Snd.mixer; 25 | } 26 | 27 | /* 28 | * Play a sound 29 | * 30 | * loop: number of times the sound should be played, -1 to loop forever 31 | * returns: channel number, or -1 if none was available 32 | * 33 | * NOTE if sound is already playing, simply reset it (i.e. can not have 34 | * twice the same sound playing -- tends to become noisy when too many 35 | * bad guys die at the same time). 36 | */ 37 | Syssnd.play = function(name, loop) { 38 | // TODO 39 | var snd = Snd.getItem(name); 40 | if (snd) { 41 | //snd.play(G.Convert.toUInt16(loop)); 42 | mixer.play(snd, G.Convert.toUint16(loop) - 1); 43 | } 44 | } 45 | 46 | /* 47 | * Pause 48 | * 49 | * pause: TRUE or FALSE 50 | * clear: TRUE to cleanup all sounds and make sure we start from scratch 51 | */ 52 | Syssnd.pause = function(pause, clear) { 53 | // TODO 54 | } 55 | 56 | /* 57 | * Stop a sound 58 | */ 59 | Syssnd.stopsound = function(sound) { 60 | mixer.stopAll(); 61 | /* if (!sound) { return; } 62 | var mus = Snd.getItem(sound); 63 | if (mus) { 64 | mus.pause(); 65 | }*/ 66 | } 67 | 68 | /* 69 | * Load a sound. 70 | */ 71 | Syssnd.load = function(name) { 72 | return name; 73 | } 74 | 75 | /* EOF */ 76 | })(); 77 | -------------------------------------------------------------------------------- /source/system.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var timer; 4 | 5 | /* 6 | * Return number of microseconds elapsed since first call 7 | */ 8 | var ticks_base = 0; // static 9 | Sys.gettime = function() { 10 | var ticks; 11 | 12 | ticks = Date.now(); 13 | 14 | if (!ticks_base) { 15 | ticks_base = ticks; 16 | } 17 | 18 | return ticks - ticks_base; 19 | } 20 | 21 | /* 22 | * Sleep a number of microseconds 23 | */ 24 | Sys.sleep = function(s) { 25 | // Game.timer.sleep(s); 26 | } 27 | 28 | /* 29 | * Initialize system 30 | */ 31 | Sys.init = function() { 32 | Gamalto.core.setContainer("container"); 33 | Sysarg.init(); 34 | Sysvid.init(); 35 | Sysevt.init(); 36 | Syssnd.init(); 37 | } 38 | 39 | /* EOF */ 40 | })(); 41 | -------------------------------------------------------------------------------- /source/sysvid.js: -------------------------------------------------------------------------------- 1 | /* const 2 | ********/ 3 | var SYSVID_WIDTH = 320; 4 | SYSVID_HEIGHT = 200; 5 | 6 | (function() { 7 | /* local 8 | ********/ 9 | var screen, buffer, scanlines = false; 10 | 11 | /* global 12 | *********/ 13 | Sysvid.SCREENRECT = new G.Rect(0, 0, SYSVID_WIDTH, SYSVID_HEIGHT); 14 | 15 | function init_screen(w, h/*, bpp, flags*/) { 16 | var s = new G.Screen(SYSVID_WIDTH, SYSVID_HEIGHT); 17 | G.Screen.setActive(s); 18 | s.enableFiltering(false); 19 | s.setStretch(s.STRETCH_UNIFORM); 20 | return s; 21 | } 22 | 23 | Sysvid.setPalette = function() { 24 | } 25 | 26 | Sysvid.restorePalette = function() { 27 | } 28 | 29 | Sysvid.setGamePalette = function() { 30 | // Sysvid.setPalette(); 31 | } 32 | 33 | Sysvid.init = function() { 34 | screen = init_screen(SYSVID_WIDTH, SYSVID_HEIGHT); 35 | Sysvid.fb = new G.Surface(SYSVID_WIDTH, SYSVID_HEIGHT); 36 | buffer = Sysvid.fb; 37 | Sysvid.fader = new GE.Fader(Sysvid.fb, new G.Color(), 150); 38 | } 39 | 40 | Sysvid.fade_start = function() { 41 | Sysvid.fader.reset(); 42 | buffer = Sysvid.fader.surface; 43 | } 44 | 45 | Sysvid.fade_end = function() { 46 | buffer = Sysvid.fb; 47 | } 48 | 49 | Sysvid.update = function(rects) { 50 | if (rects == null) { 51 | return; 52 | } 53 | screen.redraw(buffer, 0, 0, rects); 54 | screen.refresh(); 55 | } 56 | 57 | Sysvid.toggle_scanlines = function(isOn) { 58 | scanlines = !scanlines; 59 | if (scanlines) { 60 | screen.setScanlines(50, 5); 61 | } else { 62 | screen.setScanlines(); 63 | } 64 | } 65 | 66 | Sysvid.clear = function() { 67 | Sysvid.fb.renderer.fillRect(null, new G.Color(0,0,0)); 68 | } 69 | 70 | /* EOF */ 71 | })(); 72 | -------------------------------------------------------------------------------- /source/template.js: -------------------------------------------------------------------------------- 1 | /* const 2 | ********/ 3 | // ... 4 | 5 | (function() { 6 | /* local 7 | ********/ 8 | // ... 9 | 10 | /* global 11 | *********/ 12 | // ... 13 | 14 | 15 | /* EOF */ 16 | })(); 17 | -------------------------------------------------------------------------------- /source/tiles.js: -------------------------------------------------------------------------------- 1 | var TILES_BULLET = 0x01, 2 | TILES_BOMB = 0x02, 3 | TILES_RICK = 0x03; 4 | -------------------------------------------------------------------------------- /source/util.js: -------------------------------------------------------------------------------- 1 | 2 | (function() { 3 | 4 | /* 5 | * Full box test. 6 | * 7 | * ASM 1199 8 | * 9 | * e: entity to test against. 10 | * x,y: coordinates to test. 11 | * ret: TRUE/(x,y) is within e's space, FALSE/not. 12 | */ 13 | U.fboxtest = function(e, x, y) { 14 | if (Ent.ents[e].x >= x || 15 | Ent.ents[e].x + Ent.ents[e].w < x || 16 | Ent.ents[e].y >= y || 17 | Ent.ents[e].y + Ent.ents[e].h < y) { 18 | 19 | return false; 20 | } else { 21 | return true; 22 | } 23 | } 24 | 25 | /* 26 | * Box test (then whole e2 is checked agains the center of e1). 27 | * 28 | * ASM 113E 29 | * 30 | * e1: entity to test against (corresponds to DI in asm code). 31 | * e2: entity to test (corresponds to SI in asm code). 32 | * ret: TRUE/intersect, FALSE/not. 33 | */ 34 | 35 | U.boxtest = function(e1, e2) { 36 | /* rick is special (may be crawling) */ 37 | if (e1 == E_RICK_NO) { 38 | return ERick.boxtest(e2); 39 | } 40 | 41 | /* 42 | * entity 1: x+0x05 to x+0x011, y to y+0x14 43 | * entity 2: x to x+ .w, y to y+ .h 44 | */ 45 | if (Ent.ents[e1].x + 0x11 < Ent.ents[e2].x || 46 | Ent.ents[e1].x + 0x05 > Ent.ents[e2].x + Ent.ents[e2].w || 47 | Ent.ents[e1].y + 0x14 < Ent.ents[e2].y || 48 | Ent.ents[e1].y > Ent.ents[e2].y + Ent.ents[e2].h - 1) { 49 | 50 | return false; 51 | } else { 52 | return true; 53 | } 54 | } 55 | 56 | /* 57 | * Compute the environment flag. 58 | * 59 | * ASM 0FBC if !crawl, else 103E 60 | * 61 | * x, y: coordinates where to compute the environment flag 62 | * crawl: is rick crawling? 63 | * rc0: anything CHANGED to the environment flag for crawling (6DBA) 64 | * rc1: anything CHANGED to the environment flag (6DAD) 65 | */ 66 | 67 | U.envtest = function(x, y, crawl, rc0, rc1) { 68 | 69 | var i, xx; 70 | 71 | /* prepare for ent #0 test */ 72 | Ent.ents[ENT_ENTSNUM].x = x; 73 | Ent.ents[ENT_ENTSNUM].y = y; 74 | 75 | i = 1; 76 | if (!crawl) i++; 77 | if (y & 0x0004) i++; 78 | 79 | x += 4; 80 | xx = x % 256; /* FIXME? */ // (U8)x 81 | 82 | x = x >> 3; /* from pixels to tiles */ 83 | y = y >> 3; /* from pixels to tiles */ 84 | 85 | rc0 = 0; 86 | rc1 = 0; 87 | 88 | if (xx & 0x07) { /* tiles columns alignment */ 89 | 90 | if (crawl) { 91 | rc0 |= (World.eflg[World.map[y][x]] & 92 | (MAP_EFLG_VERT|MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP)); 93 | rc0 |= (World.eflg[World.map[y][x + 1]] & 94 | (MAP_EFLG_VERT|MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP)); 95 | rc0 |= (World.eflg[World.map[y][x + 2]] & 96 | (MAP_EFLG_VERT|MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP)); 97 | y++; 98 | } 99 | 100 | do { 101 | rc1 |= (World.eflg[World.map[y][x]] & 102 | (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_FGND| 103 | MAP_EFLG_LETHAL|MAP_EFLG_01)); 104 | rc1 |= (World.eflg[World.map[y][x + 1]] & 105 | (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_FGND| 106 | MAP_EFLG_LETHAL|MAP_EFLG_CLIMB|MAP_EFLG_01)); 107 | rc1 |= (World.eflg[World.map[y][x + 2]] & 108 | (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_FGND| 109 | MAP_EFLG_LETHAL|MAP_EFLG_01)); 110 | y++; 111 | } while (--i > 0); 112 | 113 | rc1 |= (World.eflg[World.map[y][x]] & 114 | (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP|MAP_EFLG_FGND| 115 | MAP_EFLG_LETHAL|MAP_EFLG_01)); 116 | rc1 |= (World.eflg[World.map[y][x + 1]]); 117 | rc1 |= (World.eflg[World.map[y][x + 2]] & 118 | (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP|MAP_EFLG_FGND| 119 | MAP_EFLG_LETHAL|MAP_EFLG_01)); 120 | } else { 121 | 122 | if (crawl) { 123 | rc0 |= (World.eflg[World.map[y][x]] & 124 | (MAP_EFLG_VERT|MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP)); 125 | rc0 |= (World.eflg[World.map[y][x + 1]] & 126 | (MAP_EFLG_VERT|MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP)); 127 | y++; 128 | } 129 | 130 | do { 131 | rc1 |= (World.eflg[World.map[y][x]] & 132 | (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_FGND| 133 | MAP_EFLG_LETHAL|MAP_EFLG_CLIMB|MAP_EFLG_01)); 134 | rc1 |= (World.eflg[World.map[y][x + 1]] & 135 | (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_FGND| 136 | MAP_EFLG_LETHAL|MAP_EFLG_CLIMB|MAP_EFLG_01)); 137 | y++; 138 | } while (--i > 0); 139 | 140 | rc1 |= (World.eflg[World.map[y][x]]); 141 | rc1 |= (World.eflg[World.map[y][x + 1]]); 142 | } 143 | 144 | /* 145 | * If not lethal yet, and there's an entity on slot zero, and (x,y) 146 | * boxtests this entity, then raise SOLID flag. This is how we make 147 | * sure that no entity can move over the entity that is on slot zero. 148 | * 149 | * Beware! When game_cheat2 is set, this means that a block can 150 | * move over rick without killing him -- but then rick is trapped 151 | * because the block is solid. 152 | */ 153 | if (!(rc1 & MAP_EFLG_LETHAL) 154 | && Ent.ents[0].n 155 | && U.boxtest(ENT_ENTSNUM, 0)) { 156 | 157 | rc1 |= MAP_EFLG_SOLID; 158 | } 159 | 160 | return { rc0: rc0, rc1: rc1 }; 161 | } 162 | 163 | /* 164 | * Check if x,y is within e trigger box. 165 | * 166 | * ASM 126F 167 | * return: FALSE if not in box, TRUE if in box. 168 | */ 169 | U.trigbox = function(e, x, y) { 170 | var xmax, ymax; 171 | 172 | xmax = Ent.ents[e].trig_x + (Ent.entdata[Ent.ents[e].n & 0x7F].trig_w << 3); 173 | ymax = Ent.ents[e].trig_y + (Ent.entdata[Ent.ents[e].n & 0x7F].trig_h << 3); 174 | 175 | if (xmax > 0xFF) xmax = 0xFF; 176 | 177 | if (x <= Ent.ents[e].trig_x || x > xmax || 178 | y <= Ent.ents[e].trig_y || y > ymax) { 179 | return false; 180 | } else { 181 | return true; 182 | } 183 | } 184 | 185 | 186 | /* EOF */ 187 | })(); 188 | -------------------------------------------------------------------------------- /source/xrick.debug.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var all = document.getElementsByTagName('script'), 4 | path = all[all.length - 1].src, 5 | dir = path.substr(0, path.indexOf("xrick.debug.js")); 6 | 7 | document.write(' \ 8 | \ 9 | \ 10 | \ 11 | \ 12 | \ 13 | \ 14 | \ 15 | \ 16 | \ 17 | \ 18 | \ 19 | \ 20 | \ 21 | \ 22 | \ 23 | \ 24 | \ 25 | \ 26 | \ 27 | \ 28 | \ 29 | \ 30 | \ 31 | \ 32 | \ 33 | \ 34 | \ 35 | \ 36 | \ 37 | \ 38 | \ 39 | \ 40 | \ 41 | '); 42 | 43 | })(); 44 | -------------------------------------------------------------------------------- /source/xrick.js: -------------------------------------------------------------------------------- 1 | var G = Gamalto; 2 | var GE = G.Effects; 3 | // Fix problem with use of old version of Gamalto (and some internal problems too...) 4 | G.Vector = G.Vector2; 5 | 6 | var 7 | 8 | Sys = {}, 9 | Game = {}, 10 | Screen = {}, 11 | Sysvid = {}, 12 | World = {}, 13 | Draw = {}, 14 | Tiles = {}, 15 | Control = {}, 16 | Sysevt = {}, 17 | Sysarg = {}, 18 | Syssnd = {} , 19 | Sprites = {}, 20 | ERick = {}, 21 | Ent = {}, 22 | EBullet = {}, 23 | EBomb = {}, 24 | EThem = {}, 25 | EBox = {}, 26 | EBonus = {}, 27 | ESbonus = {}, 28 | U = {}, 29 | Rects = {}, 30 | Scroll = {}, 31 | 32 | Data, 33 | XRick = { 34 | 35 | main: function() { 36 | Sys.init(); 37 | Game.run(); 38 | }, 39 | 40 | init: function() { 41 | var nb = 0; 42 | 43 | Data = new G.BitmapLibrary(); 44 | var mixer = G.AudioMixer.create(4, G.AudioMixer.MIX_HTML5AUDIO); 45 | Snd = new G.SoundPool(mixer); 46 | 47 | Data.pushItem("pic_splash", "data/title.png"); 48 | Data.pushItem("pic_haf", "data/haf.png"); 49 | Data.pushItem("pic_congrat", "data/congrat.png"); 50 | Data.pushItem("tiles_data", "data/tiles.png"); 51 | Data.pushItem("sprites_data", "data/sprites.png"); 52 | 53 | Data.load().then(function() { 54 | // var pool = G.SoundPool; 55 | // var ext = pool.isSupported(pool.MP3) ? ".mp3" : 56 | // pool.isSupported(pool.WAVE) ? ".wav" : ".ogg"; 57 | 58 | var ext = ".mp3"; 59 | 60 | Snd.pushItem("WAV_GAMEOVER", "sound/gameover" + ext); 61 | Snd.pushItem("WAV_SBONUS2", "sound/sbonus2" + ext); 62 | Snd.pushItem("WAV_BULLET", "sound/bullet" + ext); 63 | Snd.pushItem("WAV_BOMBSHHT", "sound/bombshht" + ext); 64 | Snd.pushItem("WAV_EXPLODE", "sound/explode" + ext); 65 | Snd.pushItem("WAV_STICK", "sound/stick" + ext); 66 | Snd.pushItem("WAV_WALK", "sound/walk" + ext); 67 | Snd.pushItem("WAV_CRAWL", "sound/crawl" + ext); 68 | Snd.pushItem("WAV_JUMP", "sound/jump" + ext); 69 | Snd.pushItem("WAV_PAD", "sound/pad" + ext); 70 | Snd.pushItem("WAV_BOX", "sound/box" + ext); 71 | Snd.pushItem("WAV_BONUS", "sound/bonus" + ext); 72 | Snd.pushItem("WAV_SBONUS1", "sound/sbonus1" + ext); 73 | Snd.pushItem("WAV_DIE", "sound/die" + ext); 74 | Snd.pushItem("WAV_ENTITY0", "sound/ent0" + ext); 75 | Snd.pushItem("WAV_ENTITY1", "sound/ent1" + ext); 76 | Snd.pushItem("WAV_ENTITY2", "sound/ent2" + ext); 77 | Snd.pushItem("WAV_ENTITY3", "sound/ent3" + ext); 78 | Snd.pushItem("WAV_ENTITY4", "sound/ent4" + ext); 79 | Snd.pushItem("WAV_ENTITY5", "sound/ent5" + ext); 80 | Snd.pushItem("WAV_ENTITY6", "sound/ent6" + ext); 81 | Snd.pushItem("WAV_ENTITY7", "sound/ent7" + ext); 82 | Snd.pushItem("WAV_ENTITY8", "sound/ent8" + ext); 83 | 84 | Snd.pushItem("WAV_TUNE0", "sound/tune0" + ext); 85 | Snd.pushItem("WAV_TUNE1", "sound/tune1" + ext); 86 | Snd.pushItem("WAV_TUNE2", "sound/tune2" + ext); 87 | Snd.pushItem("WAV_TUNE3", "sound/tune3" + ext); 88 | Snd.pushItem("WAV_TUNE4", "sound/tune4" + ext); 89 | Snd.pushItem("WAV_TUNE5", "sound/tune5" + ext); 90 | 91 | return Snd.load(); 92 | 93 | }, function(e) { 94 | console.log("error", e); 95 | }).then(function() { 96 | 97 | Snd.getItem("WAV_STICK").priority = -1; 98 | Snd.getItem("WAV_WALK").priority = -1; 99 | Snd.getItem("WAV_CRAWL").priority = -1; 100 | Snd.getItem("WAV_JUMP").priority = -1; 101 | 102 | 103 | var size = new G.Size(8, 8); 104 | Tiles.data = []; 105 | Tiles.data[0] = new G.TileSet(Data.getItem("tiles_data"), size).addSections(256, new G.Rect(0, 0 * 8 * 256, 8, 8 * 256)); 106 | Tiles.data[1] = new G.TileSet(Data.getItem("tiles_data"), size).addSections(256, new G.Rect(0, 1 * 8 * 256, 8, 8 * 256)); 107 | Tiles.data[2] = new G.TileSet(Data.getItem("tiles_data"), size).addSections(256, new G.Rect(0, 2 * 8 * 256, 8, 8 * 256)); 108 | 109 | Sprites.data = new G.SpriteSheet(Data.getItem("sprites_data")).addSections(new G.Size(32, 21), SPRITES_NBR_SPRITES); 110 | 111 | XRick.main(); 112 | }, function(e) { 113 | console.log("error2", e); 114 | }); 115 | 116 | Sysarg.args_map = 0; 117 | Sysarg.args_submap = 0; 118 | } 119 | 120 | }; 121 | 122 | Gamalto.core.init(XRick.init); 123 | -------------------------------------------------------------------------------- /src/c.js: -------------------------------------------------------------------------------- 1 | export function create_struct(props, values, base) { 2 | const struct = base || {}; 3 | for (let i = 0; i < values.length; i++) { 4 | struct[props[i]] = values[i]; 5 | } 6 | return struct; 7 | } 8 | 9 | export function as_const(obj) { 10 | return Object.freeze(obj); 11 | } 12 | 13 | export function create_array(...sizes) { 14 | const result = Array(sizes[0]); 15 | 16 | if (sizes.length === 2) { 17 | for (let i = 0; i < result.length; i++) { 18 | result[i] = Array(sizes[1]); 19 | } 20 | } 21 | 22 | return result; 23 | } 24 | 25 | export function sprintf(s, format, ...vargs) { 26 | const result = format.replace(/{(\d+)}/g, (match, capture) => { 27 | const index = Number(capture); 28 | return index < vargs.length ? vargs[index] : match; 29 | }); 30 | for (let i = 0; i < Math.min(s.length, result.length); i++) { 31 | s[i] = result[i]; 32 | } 33 | } 34 | 35 | export function plusplus(arr) { 36 | const c = arr.shift(); 37 | return typeof c === "number" ? c : c.charCodeAt(0); 38 | } 39 | 40 | export function $(obj) { 41 | return {...obj}; 42 | } 43 | 44 | export function _STR(arr) { 45 | return arr.reduce((r, c) => r + String.fromCharCode(c), ""); 46 | } 47 | 48 | export function _U8(val) { 49 | return val & 0xff; 50 | } 51 | 52 | export function _S16(val) { 53 | return G.Convert.toInt16(val); 54 | } 55 | 56 | export function _U16(val) { 57 | return G.Convert.toUint16(val); 58 | } 59 | -------------------------------------------------------------------------------- /src/control.js: -------------------------------------------------------------------------------- 1 | /* 2 | * RickJS, a JavaScript port of XRick 3 | * 4 | * This source file is based on the folliwing files: 5 | * - xrick/src/control.c 6 | * 7 | * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved. 8 | * Copyright (C) 2012-2022 Chrilith (me@chrilith.com). All rights reserved. 9 | * 10 | * The use and distribution terms for this software are contained in the file 11 | * named README, which can be found in the root of this distribution. By 12 | * using this software in any fashion, you are agreeing to be bound by the 13 | * terms of this license. 14 | * 15 | * You must not remove this notice, or any other, from this software. 16 | */ 17 | 18 | export const control = { 19 | status: 0, 20 | last: 0, 21 | active: true 22 | }; 23 | 24 | /* eof */ 25 | 26 | -------------------------------------------------------------------------------- /src/dat_loader.js: -------------------------------------------------------------------------------- 1 | import { pic_congrats, pic_haf, pic_splash } from "./dat_picST"; 2 | import { sprites_data, sprites_init } from "./dat_spritesST"; 3 | import { tiles_data, tiles_init } from "./dat_tilesST"; 4 | 5 | const path = "../data"; 6 | let data; 7 | 8 | export async function dat_init() { 9 | data = new G.BitmapLibrary(); 10 | 11 | data.pushItem(pic_congrats, `${path}/congrat.png`); 12 | data.pushItem(pic_haf, `${path}/haf.png`); 13 | data.pushItem(pic_splash, `${path}/title.png`); 14 | 15 | data.pushItem(tiles_data, `${path}/tiles.png`); 16 | data.pushItem(sprites_data, `${path}/sprites.png`); 17 | 18 | await data.load(); 19 | 20 | tiles_init(dat_get(tiles_data)); 21 | sprites_init(dat_get(sprites_data)); 22 | } 23 | 24 | export function dat_get(name) { 25 | return data.getItem(name); 26 | } 27 | -------------------------------------------------------------------------------- /src/dat_picST.js: -------------------------------------------------------------------------------- 1 | 2 | export const pic_congrats = "picCongrats"; 3 | export const pic_haf = "PicHoF"; 4 | export const pic_splash = "splashScreen"; 5 | -------------------------------------------------------------------------------- /src/dat_screens.js: -------------------------------------------------------------------------------- 1 | import { screen_imapsteps_t } from "../include/screens"; 2 | 3 | /* 4 | * map intro, sprites lists 5 | */ 6 | export const screen_imapsl = [ 7 | 0x1b, 0x00, 8 | 0x1c, 0x1d, 0x00, 9 | 0x01, 0x00, 10 | 0x02, 0x03, 0x04, 0x05, 0x06, 0x00, 11 | 0x1e, 0x00, 12 | 0x0d, 0x00, 13 | 0x13, 0x14, 0x00, 14 | 0x1f, 0x00 15 | ]; 16 | 17 | /* 18 | * map intro, steps 19 | */ 20 | export const screen_imapsteps = [ 21 | screen_imapsteps_t( 0x0000, 0x0002, 0x0002, 0x0000 ), 22 | 23 | screen_imapsteps_t( 0x000b, 0x0000, 0x0001, 0x0000 ), 24 | screen_imapsteps_t( 0x0008, 0x0001, 0x0000, 0x0002 ), 25 | 26 | screen_imapsteps_t( 0x0000, 0x0000, 0x000c, 0x0000 ), 27 | 28 | screen_imapsteps_t( 0x000a, 0x0000, 0x0000, 0x0005 ), 29 | screen_imapsteps_t( 0x0006, 0x0002, 0x0000, 0x0007 ), 30 | screen_imapsteps_t( 0x0005, 0x0000, 0x0000, 0x0005 ), 31 | 32 | screen_imapsteps_t( 0x0000, 0x0006, 0x0000, 0x0000 ), 33 | 34 | screen_imapsteps_t( 0x000c, 0x0000, 0x0001, 0x0000 ), 35 | screen_imapsteps_t( 0x0005, 0x0000, 0x0000, 0x000d ), 36 | 37 | screen_imapsteps_t( 0x0000, 0x000c, 0x000c, 0x0000 ), 38 | 39 | screen_imapsteps_t( 0x0005, 0x0000, 0x0000, 0x0005 ), 40 | screen_imapsteps_t( 0x000a, 0x0000, 0x0000, 0x000f ), 41 | screen_imapsteps_t( 0x000c, 0xffff, 0x0000, 0x0011 ), 42 | screen_imapsteps_t( 0x0005, 0x0000, 0x0000, 0x000f ), 43 | 44 | screen_imapsteps_t( 0x0000, 0x0006, 0x0001, 0x0000 ), 45 | 46 | screen_imapsteps_t( 0x000a, 0x0000, 0x0000, 0x0014 ), 47 | screen_imapsteps_t( 0x0006, 0x0000, 0x0001, 0x0014 ), 48 | screen_imapsteps_t( 0x0005, 0x0000, 0x0000, 0x0014 ), 49 | screen_imapsteps_t( 0x0003, 0x0001, 0x0000, 0x0014 ), 50 | screen_imapsteps_t( 0x0006, 0xffff, 0x0000, 0x0014 ), 51 | screen_imapsteps_t( 0x0003, 0x0000, 0xffff, 0x0014 ), 52 | 53 | screen_imapsteps_t( 0x0000, 0x0000, 0x0000, 0x0000 ) 54 | ]; 55 | 56 | /* 57 | * map intro, step offset per map 58 | */ 59 | export const screen_imapsofs = [ 60 | 0x00, 0x03, 0x07, 0x0a, 0x0f 61 | ]; 62 | 63 | /* 64 | * map intro, text 65 | * (from ds + 0x8810 + 0x2000, 0x2138, 0x2251, 0x236a, 0x2464) 66 | * 67 | * \xFE=0xfe \xFF=0xff 68 | */ 69 | const screen_imaptext_amazon = "\ 70 | @@@@@SOUTH@AMERICA@1945@@@@@@@\xFF\ 71 | RICK@DANGEROUS@CRASH@LANDS@HIS\xFF\ 72 | @PLANE@OVER@THE@AMAZON@WHILE@@\xFF\ 73 | @SEARCHING@FOR@THE@LOST@GOOLU@\xFF\ 74 | @@@@@@@@@@@@TRIBE.@@@@@@@@@@@@\xFF\xFF\ 75 | @BUT,@BY@A@TERRIBLE@TWIST@OF@@\xFF\ 76 | FATE@HE@LANDS@IN@THE@MIDDLE@OF\xFF\ 77 | @@@A@BUNCH@OF@WILD@GOOLUS.@@@@\xFF\xFF\ 78 | @@CAN@RICK@ESCAPE@THESE@ANGRY@\xFF\ 79 | @@@AMAZONIAN@ANTAGONISTS@?@@@@\xFE"; 80 | 81 | const screen_imaptext_egypt = "\ 82 | @@@@EGYPT,@SOMETIMES@LATER@@@@\xFF\ 83 | RICK@HEADS@FOR@THE@PYRAMIDS@AT\xFF\ 84 | @@@@THE@REQUEST@OF@LONDON.@@@@\xFF\xFF\ 85 | HE@IS@TO@RECOVER@THE@JEWEL@OF@\xFF\ 86 | ANKHEL@THAT@HAS@BEEN@STOLEN@BY\xFF\ 87 | FANATICS@WHO@THREATEN@TO@SMASH\xFF\ 88 | @IT,@IF@A@RANSOM@IS@NOT@PAID.@\xFF\xFF\ 89 | CAN@RICK@SAVE@THE@GEM,@OR@WILL\xFF\ 90 | HE@JUST@GET@A@BROKEN@ANKHEL@?@\xFE"; 91 | 92 | const screen_imaptext_castle = "\ 93 | @@@@EUROPE,@LATER@THAT@WEEK@@@\xFF\ 94 | @@RICK@RECEIVES@A@COMMUNIQUE@@\xFF\ 95 | @@FROM@BRITISH@INTELLIGENCE@@@\xFF\ 96 | @@ASKING@HIM@TO@RESCUE@ALLIED@\xFF\ 97 | @PRISONERS@FROM@THE@NOTORIOUS@\xFF\ 98 | @@@@SCHWARZENDUMPF@CASTLE.@@@@\xFF\xFF\ 99 | @@RICK@ACCEPTS@THE@MISSION.@@@\xFF\xFF\ 100 | @@@BUT@CAN@HE@LIBERATE@THE@@@@\xFF\ 101 | @CRUELLY@CAPTURED@COOMANDOS@?@\xFE"; 102 | 103 | const screen_imaptext_missile = "\ 104 | @@@@@@EUROPE,@EVEN@LATER@@@@@@\xFF\ 105 | RICK@LEARNS@FROM@THE@PRISONERS\xFF\ 106 | @THAT@THE@ENEMY@ARE@TO@LAUNCH@\xFF\ 107 | AN@ATTACK@ON@LONDON@FROM@THEIR\xFF\ 108 | @@@@@SECRET@MISSILE@BASE.@@@@@\xFF\xFF\ 109 | WITHOUT@HESITATION,@HE@DECIDES\xFF\ 110 | @@@TO@INFILTRATE@THE@BASE.@@@@\xFF\xFF\ 111 | CAN@RICK@SAVE@LONDON@IN@TIME@?\xFE"; 112 | 113 | const screen_imaptext_muchlater = "\ 114 | @@@LONDON,@MUCH,@MUCH@LATER@@@\xFF\ 115 | @RICK@RETURNS@TO@A@TRIUMPHANT@\xFF\ 116 | @@WELCOME@HOME@HAVING@HELPED@@\xFF\ 117 | @@@@SECURE@ALLIED@VICTORY.@@@@\xFF\xFF\ 118 | BUT,@MEANWHILE,@IN@SPACE,@THE@\xFF\ 119 | @@@MASSED@STARSHIPS@OF@THE@@@@\xFF\ 120 | @@@BARFIAN@EMPIRE@ARE@POISED@@\xFF\ 121 | @@@@@TO@INVADE@THE@EARTH.@@@@@\xFF\xFF\ 122 | @WHAT@WILL@RICK@DO@NEXT@...@?@\xFE"; 123 | 124 | export const screen_imaptext = 125 | [ screen_imaptext_amazon, 126 | screen_imaptext_egypt, 127 | screen_imaptext_castle, 128 | screen_imaptext_missile, 129 | screen_imaptext_muchlater 130 | ].map((s) => s.split('')); 131 | 132 | /* 133 | * main intro, hall of fame title 134 | * (from ds + 0x8810 + 0x2642) 135 | */ 136 | export const screen_imainhoft = 137 | [ 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0xd4, 0xb7, 0xb1, 138 | 0xac, 0xc6, 0x2f, 0xc6, 0x2f, 0x2f, 0xa4, 0xac, 139 | 0x9b, 0xc1, 0x2f, 0x9b, 0xc1, 0xb1, 0xac, 0xb6, 140 | 0xbd, 0x9b, 0xc1, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 141 | 0xff, 142 | 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0xb2, 0xb3, 0xb2, 143 | 0xb3, 0xad, 0x2f, 0xad, 0x2f, 0x2f, 0xa6, 0xae, 144 | 0xc2, 0xc3, 0x2f, 0xc2, 0xc3, 0xb2, 0xb3, 0xbe, 145 | 0xbf, 0xc2, 0xc3, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 146 | 0xff, 147 | 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x9f, 0xc0, 0xb4, 148 | 0xb5, 0xaf, 0xc4, 0xaf, 0xc4, 0x2f, 0xa7, 0xb0, 149 | 0xb4, 0x2f, 0x2f, 0xb4, 0x2f, 0xb4, 0xb5, 0xb4, 150 | 0xb5, 0xaf, 0xc4, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 151 | 0xfe 152 | ]; 153 | 154 | /* 155 | * main intro, Rick Dangerous title 156 | * (from ds + 0x8810 + 0x27a1) 157 | */ 158 | export const screen_imainrdt = 159 | [ 0x2f, 0x2f, 0x2f, 0x9b, 0x9c, 0xa1, 0xa4, 0xa5, 160 | 0xa9, 0xaa, 0x2f, 0x9b, 0xac, 0xb1, 0xac, 0xb6, 161 | 0xb7, 0xa4, 0xa5, 0x9b, 0xc1, 0x9b, 0x9c, 0xa4, 162 | 0xac, 0xc6, 0xc7, 0xc8, 0xc9, 0x2f, 0x2f, 0x2f, 163 | 0xff, 164 | 0x2f, 0x2f, 0x2f, 0x9d, 0x9e, 0xa2, 0xa6, 0x2f, 165 | 0x9d, 0xab, 0x2f, 0xad, 0xae, 0xb2, 0xb3, 0xb8, 166 | 0xb9, 0xa6, 0xbb, 0xc2, 0xc3, 0x9d, 0x9e, 0xa6, 167 | 0xae, 0xad, 0xae, 0xca, 0xcb, 0x2f, 0x2f, 0x2f, 168 | 0xff, 169 | 0x2f, 0x2f, 0x2f, 0x9f, 0xa0, 0xa3, 0xa7, 0xa8, 170 | 0x9f, 0xa0, 0x2f, 0xaf, 0xb0, 0xb4, 0xb5, 0x9f, 171 | 0xba, 0xa7, 0xbc, 0xaf, 0xc4, 0x9f, 0xa0, 0xa7, 172 | 0xb0, 0xc5, 0xb0, 0xcc, 0xb0, 0x2f, 0x2f, 0x2f, 173 | 0xfe 174 | ]; 175 | 176 | /* 177 | * congratulations 178 | * (from ds + 0x8810 + 0x257d) 179 | */ 180 | export const screen_congrats = 181 | [ 0xa4, 0xa5, 0xa4, 0xac, 0xb6, 0xb7, 0xa4, 0xa5, 182 | 0x9b, 0x9c, 0xb1, 0xac, 0xcd, 0xce, 0xc6, 0xc7, 183 | 0xd3, 0x2f, 0xb1, 0xac, 0xcd, 0xce, 0xa1, 0xa4, 184 | 0xac, 0xb6, 0xb7, 0xc8, 0xc9, 0x2f, 0xd5, 0xd6, 185 | 0xff, 186 | 0xa6, 0x2f, 0xa6, 0xae, 0xb8, 0xb9, 0xa6, 0xbb, 187 | 0x9d, 0x9e, 0xb2, 0xb3, 0xcf, 0xd0, 0xad, 0xae, 188 | 0xad, 0x2f, 0xb2, 0xb3, 0xcf, 0xd0, 0xa2, 0xa6, 189 | 0xae, 0xb8, 0xb9, 0xca, 0xcb, 0x2f, 0xd7, 0xd8, 190 | 0xff, 191 | 0xa7, 0xa8, 0xa7, 0xb0, 0x9f, 0xba, 0xa7, 0xbc, 192 | 0x9f, 0xa0, 0xb4, 0xb5, 0xd1, 0xd2, 0xc5, 0xb0, 193 | 0xaf, 0xc4, 0xb4, 0xb5, 0xd1, 0xd2, 0xa3, 0xa7, 194 | 0xb0, 0x9f, 0xba, 0xcc, 0xb0, 0x2f, 0xd9, 0xda, 195 | 0xfe 196 | ]; 197 | 198 | /* 199 | * main intro, Core Design copyright text 200 | * (from ds + 0x8810 + 0x2288) 201 | * 202 | * \xFE=0xfe \xFF=0xff 203 | */ 204 | export const screen_imaincdc = "\ 205 | @@@@@@@@@@@@@@@@@@@\xFF\xFF\ 206 | (C)@1989@CORE@DESIGN\xFF\xFF\xFF\ 207 | @PRESS@SPACE@TO@START\xFE".split(''); 208 | 209 | /* 210 | * gameover 211 | * (from ds + 0x8810 + 0x2864) 212 | * 213 | * \xFE=0xfe \xFF=0xff 214 | */ 215 | export const screen_gameovertxt = "\ 216 | @@@@@@@@@@@\xFF\ 217 | @GAME@OVER@\xFF\ 218 | @@@@@@@@@@@\xFE".split(''); 219 | 220 | /* 221 | * paused 222 | * 223 | * \xFE=0xfe \xFF=0xff 224 | */ 225 | export const screen_pausedtxt = "\ 226 | @@@@@@@@@@\xFF\ 227 | @@PAUSED@@\xFF\ 228 | @@@@@@@@@@\xFE".split(''); 229 | 230 | /* eof */ 231 | 232 | 233 | 234 | -------------------------------------------------------------------------------- /src/dat_snd.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | export async function snd_init() { 4 | // TODO: see loaddata() 5 | } 6 | -------------------------------------------------------------------------------- /src/dat_spritesST.js: -------------------------------------------------------------------------------- 1 | import { SPRITES_NBR_SPRITES } from "../include/sprites"; 2 | 3 | export const sprites_data = "spritesData"; 4 | export const sprites = { 5 | data: null 6 | }; 7 | 8 | export function sprites_init(data) { 9 | sprites.data = new G.SpriteSheet(data).addSections(new G.Size(32, 21), SPRITES_NBR_SPRITES); 10 | } 11 | -------------------------------------------------------------------------------- /src/dat_tilesST.js: -------------------------------------------------------------------------------- 1 | 2 | export const tiles_data = "tilesData"; 3 | export const tiles = { 4 | data: [] 5 | }; 6 | 7 | export function tiles_init(data) { 8 | const size = new G.Size(8, 8); 9 | tiles.data[0] = new G.TileSet(data, size).addSections(256, new G.Rect(0, 0 * 8 * 256, 8, 8 * 256)); 10 | tiles.data[1] = new G.TileSet(data, size).addSections(256, new G.Rect(0, 1 * 8 * 256, 8, 8 * 256)); 11 | tiles.data[2] = new G.TileSet(data, size).addSections(256, new G.Rect(0, 2 * 8 * 256, 8, 8 * 256)); 12 | } 13 | -------------------------------------------------------------------------------- /src/draw.js: -------------------------------------------------------------------------------- 1 | import { as_const, plusplus, _S16 } from "./c"; 2 | import { rect_t } from "../include/rects"; 3 | import { SYSVID_WIDTH, SYSVID_HEIGHT } from "../include/system"; 4 | import { dat_get } from "./dat_loader"; 5 | import { tiles } from "./dat_tilesST"; 6 | import { sprites } from "./dat_spritesST"; 7 | import { sysvid } from "./sysvid"; 8 | import { map } from "./maps"; 9 | import { TILES_BULLET, TILES_BOMB, TILES_RICK } from "../include/tiles"; 10 | import { game } from "./game"; 11 | import { DRAW_XYMAP_HBTOP, DRAW_XYMAP_SCRLEFT, DRAW_XYMAP_SCRTOP } from "../include/draw"; 12 | 13 | /* 14 | * counters positions (pixels, screen) 15 | */ 16 | const DRAW_STATUS_BULLETS_X = 0x68; 17 | const DRAW_STATUS_BOMBS_X = 0xA8; 18 | //#ifdef GFXST 19 | const DRAW_STATUS_SCORE_X = 0x20; 20 | const DRAW_STATUS_LIVES_X = 0xF0; 21 | const DRAW_STATUS_Y = 0; 22 | //#endif 23 | 24 | /* 25 | * public vars 26 | */ 27 | export const draw = { 28 | /*U8*/ tllst: 0, /* pointer to tiles list */ 29 | /*U8*/ tilesBank: 0 /* tile number offset */ 30 | }; 31 | export const draw_STATUSRECT = rect_t( 32 | DRAW_STATUS_SCORE_X, DRAW_STATUS_Y, 33 | DRAW_STATUS_LIVES_X + 6 * 8 - DRAW_STATUS_SCORE_X, 8, 34 | null 35 | ); 36 | export const draw_SCREENRECT = as_const(rect_t( 0, 0, SYSVID_WIDTH, SYSVID_HEIGHT, null )); 37 | 38 | /* 39 | * private vars 40 | */ 41 | let fb = new G.Vector2(); /* frame buffer pointer */ 42 | 43 | 44 | 45 | /* 46 | * Set the frame buffer pointer 47 | * 48 | * x, y: position (pixels, screen) 49 | */ 50 | export function draw_setfb(x, y) { 51 | fb.x = x; 52 | fb.y = y; 53 | } 54 | 55 | 56 | /* 57 | * Clip to map screen 58 | * 59 | * x, y: position (pixels, map) CHANGED clipped 60 | * width, height: dimension CHANGED clipped 61 | * return: TRUE if fully clipped, FALSE if still (at least partly) visible 62 | */ 63 | export function 64 | draw_clipms(x, y, width, height) 65 | { 66 | if (x < 0) { 67 | if (x + width < 0) 68 | return { returns: true, x, y, width, height }; 69 | else { 70 | width += x; 71 | x = 0; 72 | } 73 | } 74 | else { 75 | if (x > 0x0100) 76 | return { returns: true, x, y, width, height }; 77 | else if (x + width > 0x0100) { 78 | width = 0x0100 - x; 79 | } 80 | } 81 | 82 | if (y < DRAW_XYMAP_SCRTOP) { 83 | if ((y + height) < DRAW_XYMAP_SCRTOP) 84 | return { returns: true, x, y, width, height }; 85 | else { 86 | height += y - DRAW_XYMAP_SCRTOP; 87 | y = DRAW_XYMAP_SCRTOP; 88 | } 89 | } 90 | else { 91 | if (y >= DRAW_XYMAP_HBTOP) 92 | return { returns: true, x, y, width, height }; 93 | else if (y + height > DRAW_XYMAP_HBTOP) 94 | height = DRAW_XYMAP_HBTOP - y; 95 | } 96 | 97 | return { returns: false, x, y, width, height }; 98 | } 99 | 100 | 101 | /* 102 | * Draw a list of tiles onto the frame buffer 103 | * start at position indicated by fb ; at the end of each (sub)list, 104 | * perform a "carriage return + line feed" i.e. go back to the initial 105 | * position then go down one tile row (8 pixels) 106 | * 107 | * ASM 1e33 108 | * fb: CHANGED (see above) 109 | * draw_tllst: CHANGED points to the element following 0xfe/0xff end code 110 | */ 111 | export function draw_tilesList() { 112 | let t; 113 | 114 | t = fb.clone(); 115 | while (draw_tilesSubList() !== 0xFE) { /* draw sub-list */ 116 | t.y += 8/* * SYSVID_WIDTH*/; /* go down one tile i.e. 8 lines */ 117 | fb = t.clone(); 118 | } 119 | } 120 | 121 | 122 | /* 123 | * Draw a list of tiles onto the frame buffer -- same as draw_tilesList, 124 | * but accept an immediate string as parameter. Note that the string needs 125 | * to be properly terminated with 0xfe (\376) and 0xff (\377) chars. 126 | */ 127 | export function 128 | draw_tilesListImm(list) 129 | { 130 | if (typeof list === "string") { 131 | list = list.split(''); 132 | } 133 | draw.tllst = [...list]; 134 | draw_tilesList(); 135 | } 136 | 137 | 138 | /* 139 | * Draw a sub-list of tiles onto the frame buffer 140 | * start at position indicated by fb ; leave fb pointing to the next 141 | * tile to the right of the last tile drawn 142 | * 143 | * ASM 1e41 144 | * fpb: CHANGED (see above) 145 | * draw_tllst: CHANGED points to the element following 0xfe/0xff end code 146 | * returns: end code (0xfe : end of list ; 0xff : end of sub-list) 147 | */ 148 | export function draw_tilesSubList() { 149 | let i; 150 | 151 | i = plusplus(draw.tllst); 152 | while (i !== 0xFF && i !== 0xFE) { /* while not end */ 153 | draw_tile(i); /* draw tile */ 154 | i = plusplus(draw.tllst); 155 | } 156 | return i; 157 | } 158 | 159 | 160 | /* 161 | * Draw a tile 162 | * at position indicated by fb ; leave fb pointing to the next tile 163 | * to the right of the tile drawn 164 | * 165 | * ASM 1e6c 166 | * tlnbr: tile number 167 | * draw_filter: CGA colors filter 168 | * fb: CHANGED (see above) 169 | */ 170 | export function 171 | draw_tile(tileNumber) 172 | { 173 | tiles.data[draw.tilesBank].draw(sysvid.fb.renderer, fb.x, fb.y, tileNumber); 174 | fb.x += 8; /* next tile */ 175 | } 176 | 177 | 178 | /* 179 | * Draw a sprite 180 | * 181 | * foobar 182 | */ 183 | //#ifdef GFXST 184 | export function 185 | draw_sprite(number, x, y) 186 | { 187 | draw_setfb(x, y); 188 | sprites.data.draw(sysvid.fb.renderer, fb.x, fb.y, number); 189 | } 190 | //#endif 191 | 192 | 193 | /* 194 | * Draw a sprite 195 | * 196 | * NOTE re-using original ST graphics format 197 | */ 198 | //#ifdef GFXST 199 | export function 200 | draw_sprite2(number, x, y, front) 201 | { 202 | let d = 0; /* sprite data */ 203 | let x0, y0; /* clipped x, y */ 204 | let w, h; /* width, height */ 205 | let g, /* sprite data offset*/ 206 | r, c, /* row, column */ 207 | i, /* frame buffer shifter */ 208 | im; /* tile flag shifter */ 209 | let flg; /* tile flag */ 210 | let tmp; 211 | 212 | x0 = x; 213 | y0 = y; 214 | w = 0x20; 215 | h = 0x15; 216 | 217 | if ((tmp = draw_clipms(x0, y0, w, h)).returns) /* return if not visible */ 218 | return; 219 | x0 = tmp.x; 220 | y0 = tmp.y; 221 | w = tmp.width; 222 | h = tmp.height; 223 | 224 | g = 0; 225 | sysvid.fb.enableClipping(new G.Rect(x0 - DRAW_XYMAP_SCRLEFT, y0 - DRAW_XYMAP_SCRTOP + 8, w, h)); 226 | draw_setfb(x0 - DRAW_XYMAP_SCRLEFT, y0 - DRAW_XYMAP_SCRTOP + 8); 227 | draw_sprite(number, fb.x, fb.y); 228 | sysvid.fb.disableClipping(); 229 | /* 230 | for (r = 0; r < 0x15; r++) { 231 | if (r >= h || y + r < y0) continue; 232 | 233 | i = 0x1f; 234 | im = x - (x & 0xfff8); 235 | flg = map.eflg[map.map[(y + r) >> 3][(x + 0x1f)>> 3]]; 236 | 237 | //#ifdef ENABLE_CHEATS 238 | function LOOP(N, C0, C1) { 239 | d = sprites.data[number][g + N]; 240 | for (c = C0; c >= C1; c--, i--, d >>= 4, im--) { 241 | if (im == 0) { 242 | flg = map.eflg[map.map[(y + r) >> 3][(x + c) >> 3]]; 243 | im = 8; 244 | } 245 | if (c >= w || x + c < x0) continue; 246 | if (!front && !game.cheat3 && (flg & MAP_EFLG_FGND)) continue; 247 | if (d & 0x0F) fb[i] = (fb[i] & 0xF0) | (d & 0x0F); 248 | if (game.cheat3) fb[i] |= 0x10; 249 | } 250 | }*/ 251 | /*#else 252 | #define LOOP(N, C0, C1) \ 253 | d = sprites_data[number][g + N]; \ 254 | for (c = C0; c >= C1; c--, i--, d >>= 4, im--) { \ 255 | if (im == 0) { \ 256 | flg = map_eflg[map_map[(y + r) >> 3][(x + c) >> 3]]; \ 257 | im = 8; \ 258 | } \ 259 | if (!front && (flg & MAP_EFLG_FGND)) continue; \ 260 | if (c >= w || x + c < x0) continue; \ 261 | if (d & 0x0F) fb[i] = (fb[i] & 0xF0) | (d & 0x0F); \ 262 | } 263 | #endif 264 | */ 265 | /* LOOP(3, 0x1f, 0x18); 266 | LOOP(2, 0x17, 0x10); 267 | LOOP(1, 0x0f, 0x08); 268 | LOOP(0, 0x07, 0x00); 269 | 270 | //#undef LOOP 271 | 272 | fb += SYSVID_WIDTH; 273 | g += 4; 274 | } 275 | */ 276 | } 277 | 278 | //#endif 279 | 280 | 281 | /* 282 | * Redraw the map behind a sprite 283 | * align to tile column and row, and clip 284 | * 285 | * x, y: sprite position (pixels, map). 286 | */ 287 | export function 288 | draw_spriteBackground(x, y) 289 | { 290 | let r, c; 291 | let rmax, cmax; 292 | let xmap, ymap; // S16 293 | let xs, ys; 294 | let tmp; 295 | 296 | /* aligne to column and row, prepare map coordinate, and clip */ 297 | xmap = _S16(x & 0xFFF8); 298 | ymap = _S16(y & 0xFFF8); 299 | cmax = (x - xmap == 0 ? 0x20 : 0x28); /* width, 4 tl cols, 8 pix each */ 300 | rmax = (y & 0x04) ? 0x20 : 0x18; /* height, 3 or 4 tile rows */ 301 | if ((tmp = draw_clipms(xmap, ymap, cmax, rmax)).returns) /* don't draw if fully clipped */ 302 | return; 303 | xmap = tmp.x; 304 | ymap = tmp.y; 305 | cmax = tmp.width; 306 | rmax = tmp.height; 307 | 308 | /* get back to screen */ 309 | xs = xmap - DRAW_XYMAP_SCRLEFT; 310 | ys = ymap - DRAW_XYMAP_SCRTOP; 311 | xmap >>= 3; 312 | ymap >>= 3; 313 | cmax >>= 3; 314 | rmax >>= 3; 315 | 316 | /* draw */ 317 | for (r = 0; r < rmax; r++) { /* for each row */ 318 | //#ifdef GFXPC 319 | // draw_setfb(xs, ys + r * 8); 320 | //#endif 321 | //#ifdef GFXST 322 | draw_setfb(xs, 8 + ys + r * 8); 323 | //#endif 324 | for (c = 0; c < cmax; c++) { /* for each column */ 325 | draw_tile(map.map[ymap + r][xmap + c]); 326 | } 327 | } 328 | } 329 | 330 | 331 | /* 332 | * Draw entire map screen background tiles onto frame buffer. 333 | * 334 | * ASM 0af5, 0a54 335 | */ 336 | export function 337 | draw_map() 338 | { 339 | let i, j; 340 | 341 | draw.tilesBank = map.tilesBank; 342 | 343 | for (i = 0; i < 0x18; i++) { /* 0x18 rows */ 344 | //#ifdef GFXPC 345 | // draw_setfb(0x20, (i * 8)); 346 | //#endif 347 | //#ifdef GFXST 348 | draw_setfb(0x20, 8 + (i * 8)); 349 | //#endif 350 | for (j = 0; j < 0x20; j++) /* 0x20 tiles per row */ 351 | draw_tile(map.map[i + 8][j]); 352 | } 353 | } 354 | 355 | 356 | /* 357 | * Draw status indicators 358 | * 359 | * ASM 0309 360 | */ 361 | export function 362 | draw_drawStatus() 363 | { 364 | let i; 365 | let sv; 366 | const s = [0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfe]; 367 | 368 | draw.tilesBank = 0; 369 | 370 | for (i = 5, sv = game.score; i >= 0; i--) { 371 | s[i] = 0x30 + ((sv | 0) % 10); 372 | sv /= 10; 373 | } 374 | draw.tllst = [...s]; 375 | 376 | draw_setfb(DRAW_STATUS_SCORE_X, DRAW_STATUS_Y); 377 | draw_tilesList(); 378 | 379 | draw_setfb(DRAW_STATUS_BULLETS_X, DRAW_STATUS_Y); 380 | for (i = 0; i < game.bullets; i++) 381 | draw_tile(TILES_BULLET); 382 | 383 | draw_setfb(DRAW_STATUS_BOMBS_X, DRAW_STATUS_Y); 384 | for (i = 0; i < game.bombs; i++) 385 | draw_tile(TILES_BOMB); 386 | 387 | draw_setfb(DRAW_STATUS_LIVES_X, DRAW_STATUS_Y); 388 | for (i = 0; i < game.lives; i++) 389 | draw_tile(TILES_RICK); 390 | } 391 | 392 | 393 | /* 394 | * Draw info indicators 395 | */ 396 | //#ifdef ENABLE_CHEATS 397 | export function 398 | draw_infos() 399 | { 400 | draw.tilesBank = 0; 401 | 402 | //#ifdef GFXPC 403 | // draw_filter = 0xffff; 404 | //#endif 405 | 406 | draw_setfb(0x00 , DRAW_STATUS_Y); 407 | draw_tile(game.cheat1 ? 'T' : '@'); 408 | draw_setfb(0x08, DRAW_STATUS_Y); 409 | draw_tile(game.cheat2 ? 'N' : '@'); 410 | draw_setfb(0x10, DRAW_STATUS_Y); 411 | draw_tile(game.cheat3 ? 'V' : '@'); 412 | } 413 | //#endif 414 | 415 | 416 | /* 417 | * Clear status indicators 418 | */ 419 | export function 420 | draw_clearStatus() 421 | { 422 | let i; 423 | 424 | //#ifdef GFXPC 425 | // draw_tilesBank = map_tilesBank; 426 | //#endif 427 | //#ifdef GFXST 428 | draw.tilesBank = 0; 429 | //#endif 430 | draw_setfb(DRAW_STATUS_SCORE_X, DRAW_STATUS_Y); 431 | for (i = 0; i < DRAW_STATUS_LIVES_X/8 + 6 - DRAW_STATUS_SCORE_X/8; i++) { 432 | //#ifdef GFXPC 433 | // draw_tile(map_map[MAP_ROW_SCRTOP + (DRAW_STATUS_Y / 8)][i]); 434 | //#endif 435 | //#ifdef GFXST 436 | draw_tile('@'); 437 | //#endif 438 | } 439 | } 440 | 441 | 442 | /* 443 | * Draw a picture 444 | */ 445 | //#ifdef GFXST 446 | export function 447 | draw_pic(x, y, w, h, pic) 448 | { 449 | sysvid.fb.renderer.drawBitmapSection(dat_get(pic), x, y, new G.Rect(0, 0, w, h)); 450 | } 451 | //#endif 452 | 453 | 454 | /* 455 | * Draw a bitmap 456 | */ 457 | /*export function 458 | draw_img(i) 459 | { 460 | let k; 461 | 462 | draw_setfb(0, 0); 463 | if (i->ncolors > 0) 464 | sysvid_setPalette(i->colors, i->ncolors); 465 | for (k = 0; k < SYSVID_WIDTH * SYSVID_HEIGHT; k++) 466 | fb[k] = i->pixels[k]; 467 | } 468 | */ 469 | 470 | /* eof */ 471 | -------------------------------------------------------------------------------- /src/e_bomb.js: -------------------------------------------------------------------------------- 1 | import { WAV_BOMBSHHT, WAV_EXPLODE } from "../include/game"; 2 | import { E_BOMB_TICKER, E_BOMB_ENT } from "../include/e_bomb"; 3 | import { syssnd_play } from "./syssnd"; 4 | import { ent } from "../include/ents"; 5 | import { e_rick_gozombie } from "./e_rick"; 6 | import { E_RICK_NO } from "../include/e_rick"; 7 | 8 | /* 9 | * public vars (for performance reasons) 10 | */ 11 | export const e_bomb = { 12 | lethal: false, 13 | xc: 0, 14 | yc: 0 15 | }; 16 | 17 | /* 18 | * private vars 19 | */ 20 | let e_bomb_ticker; 21 | 22 | 23 | /* 24 | * Bomb hit test 25 | * 26 | * ASM 11CD 27 | * returns: TRUE/hit, FALSE/not 28 | */ 29 | export function e_bomb_hit(e) 30 | { 31 | if (ent.ents[e].x > (E_BOMB_ENT().x >= 0xE0 ? 0xFF : E_BOMB_ENT().x + 0x20)) 32 | return false; 33 | if (ent.ents[e].x + ent.ents[e].w < (E_BOMB_ENT().x > 0x04 ? E_BOMB_ENT().x - 0x04 : 0)) 34 | return false; 35 | if (ent.ents[e].y > (E_BOMB_ENT().y + 0x1D)) 36 | return false; 37 | if (ent.ents[e].y + ent.ents[e].h < (E_BOMB_ENT().y > 0x0004 ? E_BOMB_ENT().y - 0x0004 : 0)) 38 | return false; 39 | return true; 40 | } 41 | 42 | /* 43 | * Initialize bomb 44 | */ 45 | export function e_bomb_init(x, y) 46 | { 47 | E_BOMB_ENT().n = 0x03; 48 | E_BOMB_ENT().x = x; 49 | E_BOMB_ENT().y = y; 50 | e_bomb_ticker = E_BOMB_TICKER; 51 | e_bomb.lethal = false; 52 | 53 | /* 54 | * Atari ST dynamite sprites are not centered the 55 | * way IBM PC sprites were ... need to adjust things a little bit 56 | */ 57 | //#ifdef GFXST 58 | E_BOMB_ENT().x += 4; 59 | E_BOMB_ENT().y += 5; 60 | //#endif 61 | 62 | } 63 | 64 | 65 | /* 66 | * Entity action 67 | * 68 | * ASM 18CA 69 | */ 70 | export function 71 | e_bomb_action(UNUSED_e) 72 | { 73 | /* tick */ 74 | e_bomb_ticker--; 75 | 76 | if (e_bomb_ticker === 0) 77 | { 78 | /* 79 | * end: deactivate 80 | */ 81 | E_BOMB_ENT().n = 0; 82 | e_bomb.lethal = false; 83 | } 84 | else if (e_bomb_ticker >= 0x0A) 85 | { 86 | /* 87 | * ticking 88 | */ 89 | //#ifdef ENABLE_SOUND 90 | if ((e_bomb_ticker & 0x03) == 0x02) 91 | syssnd_play(WAV_BOMBSHHT, 1); 92 | //#endif 93 | //#ifdef GFXST 94 | /* ST bomb sprites sequence is longer */ 95 | if (e_bomb_ticker < 40) 96 | E_BOMB_ENT().sprite = 0x99 + 19 - (e_bomb_ticker >> 1); 97 | else 98 | //#endif 99 | E_BOMB_ENT().sprite = (e_bomb_ticker & 0x01) ? 0x23 : 0x22; 100 | } 101 | else if (e_bomb_ticker == 0x09) 102 | { 103 | /* 104 | * explode 105 | */ 106 | //#ifdef ENABLE_SOUND 107 | syssnd_play(WAV_EXPLODE, 1); 108 | //#endif 109 | //#ifdef GFXPC 110 | // E_BOMB_ENT().sprite = 0x24 + 4 - (e_bomb_ticker >> 1); 111 | //#endif 112 | //#ifdef GFXST 113 | /* See above: fixing alignment */ 114 | E_BOMB_ENT().x -= 4; 115 | E_BOMB_ENT().y -= 5; 116 | E_BOMB_ENT().sprite = 0xa8 + 4 - (e_bomb_ticker >> 1); 117 | //#endif 118 | e_bomb.xc = E_BOMB_ENT().x + 0x0C; 119 | e_bomb.yc = E_BOMB_ENT().y + 0x000A; 120 | e_bomb.lethal = true; 121 | if (e_bomb_hit(E_RICK_NO)) 122 | e_rick_gozombie(); 123 | } 124 | else 125 | { 126 | /* 127 | * exploding 128 | */ 129 | //#ifdef GFXPC 130 | // E_BOMB_ENT().sprite = 0x24 + 4 - (e_bomb_ticker >> 1); 131 | //#endif 132 | //#ifdef GFXST 133 | E_BOMB_ENT().sprite = 0xa8 + 4 - (e_bomb_ticker >> 1); 134 | //#endif 135 | /* exploding, hence lethal */ 136 | if (e_bomb_hit(E_RICK_NO)) 137 | e_rick_gozombie(); 138 | } 139 | } 140 | 141 | /* eof */ 142 | 143 | 144 | -------------------------------------------------------------------------------- /src/e_bonus.js: -------------------------------------------------------------------------------- 1 | import { WAV_BONUS } from "../include/game"; 2 | import { ent } from "../include/ents"; 3 | import { e_rick_boxtest } from "./e_rick"; 4 | import { syssnd_play } from "./syssnd"; 5 | import { map_marks } from "./dat_maps"; 6 | import { game } from "./game"; 7 | import { MAP_MARK_NACT } from "../include/maps"; 8 | /* 9 | * Entity action 10 | * 11 | * ASM 242C 12 | */ 13 | export function 14 | e_bonus_action(e) 15 | { 16 | //#define seq c1 17 | 18 | if (ent.ents[e].seq === 0) { 19 | if (e_rick_boxtest(e)) { 20 | game.score += 500; 21 | //#ifdef ENABLE_SOUND 22 | syssnd_play(WAV_BONUS, 1); 23 | //#endif 24 | map_marks[ent.ents[e].mark].ent |= MAP_MARK_NACT; 25 | ent.ents[e].seq = 1; 26 | ent.ents[e].sprite = 0xad; 27 | ent.ents[e].front = true; 28 | ent.ents[e].y -= 0x08; 29 | } 30 | } 31 | 32 | else if (ent.ents[e].seq > 0 && ent.ents[e].seq < 10) { 33 | ent.ents[e].seq++; 34 | ent.ents[e].y -= 2; 35 | } 36 | 37 | else { 38 | ent.ents[e].n = 0; 39 | } 40 | } 41 | 42 | 43 | /* eof */ 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/e_box.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * FIXME this is because the same structure is used 4 | * for all entities. Need to replace this w/ an inheritance 5 | * solution. 6 | */ 7 | //#define cnt c1 8 | 9 | import { GAME_BOMBS_INIT, GAME_BULLETS_INIT, WAV_BOX, 10 | WAV_EXPLODE } from "../include/game"; 11 | import { ent, ENT_LETHAL } from "../include/ents"; 12 | import { e_rick_boxtest } from "./e_rick"; 13 | import { MAP_MARK_NACT } from "../include/maps"; 14 | import { E_RICK_STSTOP, E_RICK_STTST } from "../include/e_rick"; 15 | import { u_fboxtest } from "./util"; 16 | import { E_BULLET_ENT } from "../include/e_bullet"; 17 | import { e_bomb, e_bomb_hit } from "./e_bomb"; 18 | import { game } from "./game"; 19 | import { map_marks } from "./dat_maps"; 20 | import { e_bullet } from "./e_bullet"; 21 | import { syssnd_play } from "./syssnd"; 22 | 23 | /* 24 | * Constants 25 | */ 26 | const SEQ_INIT = 0x0A; 27 | 28 | /* 29 | * Entity action 30 | * 31 | * ASM 245A 32 | */ 33 | export function 34 | e_box_action(e) 35 | { 36 | const sp = [0x24, 0x25, 0x26, 0x27, 0x28]; /* explosion sprites sequence */ 37 | 38 | if (ent.ents[e].n & ENT_LETHAL) { 39 | /* 40 | * box is lethal i.e. exploding 41 | * play sprites sequence then stop 42 | */ 43 | ent.ents[e].sprite = sp[ent.ents[e].cnt >> 1]; 44 | if (--ent.ents[e].cnt == 0) { 45 | ent.ents[e].n = 0; 46 | map_marks[ent.ents[e].mark].ent |= MAP_MARK_NACT; 47 | } 48 | } else { 49 | /* 50 | * not lethal: check to see if triggered 51 | */ 52 | if (e_rick_boxtest(e)) { 53 | /* rick: collect bombs or bullets and stop */ 54 | //#ifdef ENABLE_SOUND 55 | syssnd_play(WAV_BOX, 1); 56 | //#endif 57 | if (ent.ents[e].n == 0x10) 58 | game.bombs = GAME_BOMBS_INIT; 59 | else /* 0x11 */ 60 | game.bullets = GAME_BULLETS_INIT; 61 | ent.ents[e].n = 0; 62 | map_marks[ent.ents[e].mark].ent |= MAP_MARK_NACT; 63 | } 64 | else if (E_RICK_STTST(E_RICK_STSTOP) && 65 | u_fboxtest(e, e_rick.stop_x, e_rick.stop_y)) { 66 | /* rick's stick: explode */ 67 | explode(e); 68 | } 69 | else if (E_BULLET_ENT().n && u_fboxtest(e, e_bullet.xc, e_bullet.yc)) { 70 | /* bullet: explode (and stop bullet) */ 71 | E_BULLET_ENT().n = 0; 72 | explode(e); 73 | } 74 | else if (e_bomb.lethal && e_bomb_hit(e)) { 75 | /* bomb: explode */ 76 | explode(e); 77 | } 78 | } 79 | } 80 | 81 | 82 | /* 83 | * Explode when 84 | */ 85 | function explode(e) 86 | { 87 | ent.ents[e].cnt = SEQ_INIT; 88 | ent.ents[e].n |= ENT_LETHAL; 89 | //#ifdef ENABLE_SOUND 90 | syssnd_play(WAV_EXPLODE, 1); 91 | //#endif 92 | } 93 | 94 | /* eof */ 95 | 96 | 97 | -------------------------------------------------------------------------------- /src/e_bullet.js: -------------------------------------------------------------------------------- 1 | import { E_BULLET_ENT } from "../include/e_bullet"; 2 | import { LEFT, WAV_BULLET } from "../include/game"; 3 | import { MAP_EFLG_SOLID } from "../include/maps"; 4 | import { game } from "./game"; 5 | import { syssnd_play } from "./syssnd"; 6 | import { map } from "./maps"; 7 | 8 | /* 9 | * public vars (for performance reasons) 10 | */ 11 | export const e_bullet = { 12 | offsx: 0, 13 | xc: 0, yc: 0 14 | }; 15 | 16 | /* 17 | * Initialize bullet 18 | */ 19 | export function 20 | e_bullet_init(x, y) 21 | { 22 | E_BULLET_ENT().n = 0x02; 23 | E_BULLET_ENT().x = x; 24 | E_BULLET_ENT().y = y + 0x0006; 25 | if (game.dir === LEFT) { 26 | e_bullet.offsx = -0x08; 27 | E_BULLET_ENT().sprite = 0x21; 28 | } 29 | else { 30 | e_bullet.offsx = 0x08; 31 | E_BULLET_ENT().sprite = 0x20; 32 | } 33 | //#ifdef ENABLE_SOUND 34 | syssnd_play(WAV_BULLET, 1); 35 | //#endif 36 | } 37 | 38 | 39 | /* 40 | * Entity action 41 | * 42 | * ASM 1883, 0F97 43 | */ 44 | export function 45 | e_bullet_action(_UNUSED_e) 46 | { 47 | /* move bullet */ 48 | E_BULLET_ENT().x += e_bullet.offsx; 49 | 50 | if (E_BULLET_ENT().x <= -0x10 || E_BULLET_ENT().x > 0xe8) { 51 | /* out: deactivate */ 52 | E_BULLET_ENT().n = 0; 53 | } 54 | else { 55 | /* update bullet center coordinates */ 56 | e_bullet.xc = E_BULLET_ENT().x + 0x0c; 57 | e_bullet.yc = E_BULLET_ENT().y + 0x05; 58 | if (map.eflg[map.map[e_bullet.yc >> 3][e_bullet.xc >> 3]] & 59 | MAP_EFLG_SOLID) { 60 | /* hit something: deactivate */ 61 | E_BULLET_ENT().n = 0; 62 | } 63 | } 64 | } 65 | 66 | 67 | /* eof */ 68 | 69 | -------------------------------------------------------------------------------- /src/e_sbonus.js: -------------------------------------------------------------------------------- 1 | import { game } from "./game"; 2 | import { ent, ENT_XRICK } from "../include/ents"; 3 | import { u_trigbox } from "./util"; 4 | import { syssnd_play } from "./syssnd"; 5 | import { WAV_SBONUS1, WAV_SBONUS2 } from "../include/game"; 6 | import { map_marks } from "./dat_maps"; 7 | import { MAP_MARK_NACT } from "../include/maps"; 8 | 9 | /* 10 | * public vars 11 | */ 12 | export const e_sbonus = { 13 | counting: false, 14 | counter: 0, 15 | bonus: 0 16 | }; 17 | 18 | 19 | /* 20 | * Entity action / start counting 21 | * 22 | * ASM 2182 23 | */ 24 | export function 25 | e_sbonus_start(e) 26 | { 27 | ent.ents[e].sprite = 0; /* invisible */ 28 | if (u_trigbox(e, ENT_XRICK().x + 0x0C, ENT_XRICK().y + 0x0A)) { 29 | /* rick is within trigger box */ 30 | ent.ents[e].n = 0; 31 | e_sbonus.counting = true; /* 6DD5 */ 32 | e_sbonus.counter = 0x1e; /* 6DDB */ 33 | e_sbonus.bonus = 2000; /* 291A-291D */ 34 | //#ifdef ENABLE_SOUND 35 | syssnd_play(WAV_SBONUS1, 1); 36 | //#endif 37 | } 38 | } 39 | 40 | 41 | /* 42 | * Entity action / stop counting 43 | * 44 | * ASM 2143 45 | */ 46 | export function 47 | e_sbonus_stop(e) 48 | { 49 | ent.ents[e].sprite = 0; /* invisible */ 50 | 51 | if (!e_sbonus.counting) 52 | return; 53 | 54 | if (u_trigbox(e, ENT_XRICK().x + 0x0C, ENT_XRICK().y + 0x0A)) { 55 | /* rick is within trigger box */ 56 | e_sbonus.counting = false; /* stop counting */ 57 | ent.ents[e].n = 0; /* deactivate entity */ 58 | game.score += e_sbonus.bonus; /* add bonus to score */ 59 | //#ifdef ENABLE_SOUND 60 | syssnd_play(WAV_SBONUS2, 1); 61 | //#endif 62 | /* make sure the entity won't be activated again */ 63 | map_marks[ent.ents[e].mark].ent |= MAP_MARK_NACT; 64 | } 65 | else { 66 | /* keep counting */ 67 | if (--e_sbonus.counter == 0) { 68 | e_sbonus.counter = 0x1e; 69 | if (e_sbonus.bonus) e_sbonus.bonus--; 70 | } 71 | } 72 | } 73 | 74 | /* eof */ 75 | 76 | 77 | -------------------------------------------------------------------------------- /src/maps.js: -------------------------------------------------------------------------------- 1 | import { create_array, _U8 } from "./c"; 2 | import { map_submaps, map_marks, map_eflg_c, map_blocks, map_bnums, map_connect } from "./dat_maps"; 3 | import { 4 | MAP_NBR_MARKS, MAP_MARK_NACT, 5 | MAP_ROW_SCRTOP, MAP_ROW_SCRBOT, 6 | MAP_ROW_HTTOP, MAP_ROW_HTBOT, 7 | MAP_ROW_HBTOP, MAP_ROW_HBBOT } from "../include/maps"; 8 | import { game } from "./game"; 9 | import { ent_reset, ent_actvis } from "./ents"; 10 | import { ent } from "../include/ents"; 11 | import { e_sbonus } from "./e_sbonus"; 12 | 13 | /* 14 | * global vars 15 | */ 16 | export const map = { 17 | map: create_array(0x2C, 0x20), 18 | eflg: create_array(0x100), 19 | frow: 0, 20 | tilesBank: 0 21 | }; 22 | 23 | 24 | /* 25 | * Fill in map_map with tile numbers by expanding blocks. 26 | * 27 | * add map_submaps[].bnum to map_frow to find out where to start from. 28 | * We need to /4 map_frow to convert from tile rows to block rows, then 29 | * we need to *8 to convert from block rows to block numbers (there 30 | * are 8 blocks per block row). This is achieved by *2 then &0xfff8. 31 | */ 32 | export function 33 | map_expand() 34 | { 35 | let i, j, k, l; 36 | let row, col; 37 | let pbnum; 38 | 39 | pbnum = map_submaps[game.submap].bnum + ((2 * map.frow) & 0xfff8); 40 | row = col = 0; 41 | console.log("START", map_submaps[game.submap].bnum, map.frow) 42 | for (i = 0; i < 0x0b; i++) { /* 0x0b rows of blocks */ 43 | for (j = 0; j < 0x08; j++) { /* 0x08 blocks per row */ 44 | for (k = 0, l = 0; k < 0x04; k++) { /* expand one block */ 45 | 46 | //console.log(i, j, k, l, row, col, pbnum) 47 | map.map[row][col++] = map_blocks[map_bnums[pbnum]][l++]; 48 | map.map[row][col++] = map_blocks[map_bnums[pbnum]][l++]; 49 | map.map[row][col++] = map_blocks[map_bnums[pbnum]][l++]; 50 | map.map[row][col] = map_blocks[map_bnums[pbnum]][l++]; 51 | row += 1; col -= 3; 52 | } 53 | row -= 4; col += 4; 54 | pbnum++; 55 | } 56 | row += 4; col = 0; 57 | } 58 | } 59 | 60 | 61 | /* 62 | * Initialize a new submap 63 | * 64 | * ASM 0cc3 65 | */ 66 | export function 67 | map_init() 68 | { 69 | /*sys_printf("xrick/map_init: map=%#04x submap=%#04x\n", g_map, game_submap);*/ 70 | 71 | map.tilesBank = (map_submaps[game.submap].page === 1) ? 2 : 1; 72 | 73 | map_eflg_expand((map_submaps[game.submap].page === 1) ? 0x10 : 0x00); 74 | map_expand(); 75 | ent_reset(); 76 | ent_actvis(map.frow + MAP_ROW_SCRTOP, map.frow + MAP_ROW_SCRBOT); 77 | ent_actvis(map.frow + MAP_ROW_HTTOP, map.frow + MAP_ROW_HTBOT); 78 | ent_actvis(map.frow + MAP_ROW_HBTOP, map.frow + MAP_ROW_HBBOT); 79 | } 80 | 81 | 82 | /* 83 | * Expand entity flags for this map 84 | * 85 | * ASM 1117 86 | */ 87 | export function 88 | map_eflg_expand(offs) 89 | { 90 | let i, j, k; 91 | 92 | for (i = 0, k = 0; i < 0x10; i++) { 93 | j = map_eflg_c[offs + i++]; 94 | while (j--) map.eflg[k++] = map_eflg_c[offs + i]; 95 | } 96 | } 97 | 98 | 99 | /* 100 | * Chain (sub)maps 101 | * 102 | * ASM 0c08 103 | * return: TRUE/next submap OK, FALSE/map finished 104 | */ 105 | export function 106 | map_chain() 107 | { 108 | let c, t; 109 | 110 | game.chsm = 0; 111 | e_sbonus.counting = false; 112 | 113 | /* find connection */ 114 | c = map_submaps[game.submap].connect; 115 | t = 3; 116 | /* 117 | IFDEBUG_MAPS( 118 | sys_printf("xrick/maps: chain submap=%#04x frow=%#04x .connect=%#04x %s\n", 119 | game_submap, map_frow, c, 120 | (game_dir == LEFT ? "-> left" : "-> right")); 121 | ); 122 | */ 123 | /* 124 | * look for the first connector with compatible row number. if none 125 | * found, then panic 126 | */ 127 | for (c = map_submaps[game.submap].connect; ; c++) { 128 | if (map_connect[c].dir === 0xff) 129 | sys_panic("(map_chain) can not find connector\n"); 130 | if (map_connect[c].dir != game.dir) continue; 131 | t = (ent.ents[1].y >> 3) + map.frow - map_connect[c].rowout; 132 | if (t < 3) break; 133 | } 134 | 135 | /* got it */ 136 | /* IFDEBUG_MAPS( 137 | sys_printf("xrick/maps: chain frow=%#04x y=%#06x\n", 138 | map_frow, ent_ents[1].y); 139 | sys_printf("xrick/maps: chain connect=%#04x rowout=%#04x - ", 140 | c, map_connect[c].rowout); 141 | ); 142 | */ 143 | if (map_connect[c].submap === 0xff) { 144 | /* no next submap - request next map */ 145 | /* IFDEBUG_MAPS( 146 | sys_printf("chain to next map\n"); 147 | );*/ 148 | return false; 149 | } 150 | else { 151 | /* next submap */ 152 | /* IFDEBUG_MAPS( 153 | sys_printf("chain to submap=%#04x rowin=%#04x\n", 154 | map_connect[c].submap, map_connect[c].rowin); 155 | );*/ 156 | map.frow = _U8(map.frow - map_connect[c].rowout + map_connect[c].rowin); 157 | game.submap = map_connect[c].submap; 158 | /* IFDEBUG_MAPS( 159 | sys_printf("xrick/maps: chain frow=%#04x\n", 160 | map_frow); 161 | );*/ 162 | return true; 163 | } 164 | } 165 | 166 | 167 | /* 168 | * Reset all marks, i.e. make them all active again. 169 | * 170 | * ASM 0025 171 | * 172 | */ 173 | export function 174 | map_resetMarks() 175 | { 176 | let i; 177 | for (i = 0; i < MAP_NBR_MARKS; i++) 178 | map_marks[i].ent &= ~MAP_MARK_NACT; 179 | } 180 | 181 | 182 | /* eof */ 183 | -------------------------------------------------------------------------------- /src/rects.js: -------------------------------------------------------------------------------- 1 | import { rect_t } from "../include/rects"; 2 | 3 | /* 4 | * Free a list of rectangles and set the pointer to NULL. 5 | * 6 | * p: rectangle list CHANGED to NULL 7 | */ 8 | export function 9 | rects_free(r) { 10 | if (r) { 11 | rects_free(r.next); 12 | r.next = null; 13 | // free(r); 14 | } 15 | } 16 | 17 | /* 18 | * Add a rectangle to a list of rectangles 19 | */ 20 | export function 21 | rects_new(x, y, width, height, next) 22 | { 23 | let r; 24 | 25 | r = rect_t( 26 | x, 27 | y, 28 | width, 29 | height, 30 | next 31 | ); 32 | return r; 33 | } 34 | 35 | /* eof */ 36 | -------------------------------------------------------------------------------- /src/scr_gameover.js: -------------------------------------------------------------------------------- 1 | import { CONTROL_EXIT, CONTROL_FIRE } from "../include/control"; 2 | import { SCREEN_DONE, SCREEN_EXIT, SCREEN_RUNNING, 3 | SCREEN_TIMEOUT } from "../include/screens"; 4 | import { control } from "./control"; 5 | import { screen_gameovertxt } from "./dat_screens"; 6 | import { draw, draw_SCREENRECT, draw_setfb, draw_tilesList } from "./draw"; 7 | import { game, game_setmusic } from "./game"; 8 | import { sys_gettime, sys_sleep } from "./system"; 9 | import { sysvid_clear } from "./sysvid"; 10 | 11 | /* 12 | * Display the game over screen 13 | * 14 | * return: SCREEN_RUNNING, SCREEN_DONE, SCREEN_EXIT 15 | */ 16 | let seq = 0; 17 | let period = 0; 18 | let tm = 0; 19 | 20 | export function 21 | screen_gameover() 22 | { 23 | // static U8 seq = 0; 24 | // static U8 period = 0; 25 | //#ifdef GFXST 26 | // static U32 tm = 0; 27 | //#endif 28 | //#ifdef ENABLE_SOUND 29 | // static sound_t *snd; 30 | // static U8 chan; 31 | //#endif 32 | 33 | if (seq === 0) { 34 | draw.tilesBank = 0; 35 | seq = 1; 36 | period = game.period; /* save period, */ 37 | game.period = 50; /* and use our own */ 38 | //#ifdef ENABLE_SOUND 39 | game_setmusic("sounds/gameover.wav", 1); 40 | //#endif 41 | } 42 | 43 | switch (seq) { 44 | case 1: /* display banner */ 45 | //#ifdef GFXST 46 | sysvid_clear(); 47 | tm = sys_gettime(); 48 | //#endif 49 | draw.tllst = [...screen_gameovertxt]; 50 | draw_setfb(120, 80); 51 | //#ifdef GFXPC 52 | // draw_filter = 0xAAAA; 53 | //#endif 54 | draw_tilesList(); 55 | 56 | game.rects = draw_SCREENRECT; 57 | seq = 2; 58 | break; 59 | 60 | case 2: /* wait for key pressed */ 61 | if (control.status & CONTROL_FIRE) 62 | seq = 3; 63 | //#ifdef GFXST 64 | else if (sys_gettime() - tm > SCREEN_TIMEOUT) 65 | seq = 4; 66 | //#endif 67 | else 68 | sys_sleep(50); 69 | break; 70 | 71 | case 3: /* wait for key released */ 72 | if (!(control.status & CONTROL_FIRE)) 73 | seq = 4; 74 | else 75 | sys_sleep(50); 76 | break; 77 | } 78 | 79 | if (control.status & CONTROL_EXIT) /* check for exit request */ 80 | return SCREEN_EXIT; 81 | 82 | if (seq === 4) { /* we're done */ 83 | sysvid_clear(); 84 | seq = 0; 85 | game.period = period; 86 | return SCREEN_DONE; 87 | } 88 | 89 | return SCREEN_RUNNING; 90 | } 91 | 92 | /* eof */ 93 | 94 | -------------------------------------------------------------------------------- /src/scr_getname.js: -------------------------------------------------------------------------------- 1 | import { CONTROL_DOWN, CONTROL_EXIT, CONTROL_FIRE, CONTROL_LEFT, 2 | CONTROL_RIGHT, CONTROL_UP } from "../include/control"; 3 | import { SCREEN_DONE, SCREEN_RUNNING } from "../include/screens"; 4 | import { _STR } from "./c"; 5 | import { control } from "./control"; 6 | import { draw, draw_SCREENRECT, draw_setfb, draw_tile, 7 | draw_tilesListImm } from "./draw"; 8 | import { game } from "./game"; 9 | import { sys_gettime, sys_sleep } from "./system"; 10 | import { sysvid_clear } from "./sysvid"; 11 | 12 | /* 13 | * local vars 14 | */ 15 | let seq = 0; 16 | let x, y, p; 17 | const name = Array(10); 18 | 19 | const TILE_POINTER = 0x3A; // '\072'; 20 | const TILE_CURSOR = 0x3B; // '\073'; 21 | const TOPLEFT_X = 116; 22 | const TOPLEFT_Y = 64; 23 | const NAMEPOS_X = 120; 24 | const NAMEPOS_Y = 160; 25 | const AUTOREPEAT_TMOUT = 100; 26 | 27 | 28 | /* 29 | * Get name 30 | * 31 | * return: 0 while running, 1 when finished. 32 | */ 33 | let tm = 0; 34 | 35 | export function 36 | screen_getname() 37 | { 38 | // static U32 tm = 0; 39 | let i, j; 40 | 41 | if (seq === 0) { 42 | /* figure out if this is a high score */ 43 | if (game.score < game.hscores[7].score) 44 | return SCREEN_DONE; 45 | 46 | /* prepare */ 47 | draw.tilesBank = 0; 48 | //#ifdef GFXPC 49 | // draw_filter = 0xffff; 50 | //#endif 51 | for (i = 0; i < 10; i++) 52 | name[i] = '@'; 53 | x = y = p = 0; 54 | game.rects = draw_SCREENRECT; 55 | seq = 1; 56 | } 57 | 58 | switch (seq) { 59 | case 1: /* prepare screen */ 60 | sysvid_clear(); 61 | //#ifdef GFXPC 62 | // draw_setfb(32, 8); 63 | // draw_filter = 0xaaaa; /* red */ 64 | // draw_tilesListImm(screen_congrats); 65 | //#endif 66 | draw_setfb(76, 40); 67 | //#ifdef GFXPC 68 | // draw_filter = 0xffff; /* yellow */ 69 | //#endif 70 | draw_tilesListImm("PLEASE@ENTER@YOUR@NAME\xFE"); 71 | //#ifdef GFXPC 72 | // draw_filter = 0x5555; /* green */ 73 | //#endif 74 | for (i = 0; i < 6; i++) 75 | for (j = 0; j < 4; j++) { 76 | draw_setfb(TOPLEFT_X + i * 8 * 2, TOPLEFT_Y + j * 8 * 2); 77 | draw_tile('A'.charCodeAt(0) + i + j * 6); 78 | } 79 | draw_setfb(TOPLEFT_X, TOPLEFT_Y + 64); 80 | //#ifdef GFXST 81 | draw_tilesListImm("Y@Z@.@@@\x3C\xFB\xFC\xFD\xFE"); 82 | //#endif 83 | //#ifdef GFXPC 84 | // draw_tilesListImm((U8 *)"Y@Z@.@@@\074@\075@\376"); 85 | //#endif 86 | name_draw(); 87 | pointer_show(true); 88 | seq = 2; 89 | break; 90 | 91 | case 2: /* wait for key pressed */ 92 | if (control.status & CONTROL_FIRE) 93 | seq = 3; 94 | if (control.status & CONTROL_UP) { 95 | if (y > 0) { 96 | pointer_show(false); 97 | y--; 98 | pointer_show(true); 99 | tm = sys_gettime(); 100 | } 101 | seq = 4; 102 | } 103 | if (control.status & CONTROL_DOWN) { 104 | if (y < 4) { 105 | pointer_show(false); 106 | y++; 107 | pointer_show(true); 108 | tm = sys_gettime(); 109 | } 110 | seq = 5; 111 | } 112 | if (control.status & CONTROL_LEFT) { 113 | if (x > 0) { 114 | pointer_show(false); 115 | x--; 116 | pointer_show(true); 117 | tm = sys_gettime(); 118 | } 119 | seq = 6; 120 | } 121 | if (control.status & CONTROL_RIGHT) { 122 | if (x < 5) { 123 | pointer_show(false); 124 | x++; 125 | pointer_show(true); 126 | tm = sys_gettime(); 127 | } 128 | seq = 7; 129 | } 130 | if (seq === 2) 131 | sys_sleep(50); 132 | break; 133 | 134 | case 3: /* wait for FIRE released */ 135 | if (!(control.status & CONTROL_FIRE)) { 136 | if (x == 5 && y == 4) { /* end */ 137 | i = 0; 138 | while (game.score < game.hscores[i].score) 139 | i++; 140 | j = 7; 141 | while (j > i) { 142 | game.hscores[j].score = game.hscores[j - 1].score; 143 | //for (x = 0; x < 10; x++) 144 | game.hscores[j].name/*[x]*/ = game.hscores[j - 1].name/*[x]*/; 145 | j--; 146 | } 147 | game.hscores[i].score = game.score; 148 | //for (x = 0; x < 10; x++) 149 | game.hscores[i].name/*[x]*/ = _STR(name)/*[x]*/; 150 | seq = 99; 151 | } 152 | else { 153 | name_update(); 154 | name_draw(); 155 | seq = 2; 156 | } 157 | } 158 | else 159 | sys_sleep(50); 160 | break; 161 | 162 | case 4: /* wait for UP released */ 163 | if (!(control.status & CONTROL_UP) || 164 | sys_gettime() - tm > AUTOREPEAT_TMOUT) 165 | seq = 2; 166 | else 167 | sys_sleep(50); 168 | break; 169 | 170 | case 5: /* wait for DOWN released */ 171 | if (!(control.status & CONTROL_DOWN) || 172 | sys_gettime() - tm > AUTOREPEAT_TMOUT) 173 | seq = 2; 174 | else 175 | sys_sleep(50); 176 | break; 177 | 178 | case 6: /* wait for LEFT released */ 179 | if (!(control.status & CONTROL_LEFT) || 180 | sys_gettime() - tm > AUTOREPEAT_TMOUT) 181 | seq = 2; 182 | else 183 | sys_sleep(50); 184 | break; 185 | 186 | case 7: /* wait for RIGHT released */ 187 | if (!(control.status & CONTROL_RIGHT) || 188 | sys_gettime() - tm > AUTOREPEAT_TMOUT) 189 | seq = 2; 190 | else 191 | sys_sleep(50); 192 | break; 193 | 194 | } 195 | 196 | if (control.status & CONTROL_EXIT) /* check for exit request */ 197 | return SCREEN_EXIT; 198 | 199 | if (seq === 99) { /* seq 99, we're done */ 200 | sysvid_clear(); 201 | seq = 0; 202 | return SCREEN_DONE; 203 | } 204 | else 205 | return SCREEN_RUNNING; 206 | } 207 | 208 | 209 | function 210 | pointer_show(show) 211 | { 212 | draw_setfb(TOPLEFT_X + x * 8 * 2, TOPLEFT_Y + y * 8 * 2 + 8); 213 | //#ifdef GFXPC 214 | // draw_filter = 0xaaaa; /* red */ 215 | //#endif 216 | draw_tile((show === true)?TILE_POINTER:'@'.charCodeAt(0)); 217 | } 218 | 219 | function 220 | name_update() 221 | { 222 | let i; 223 | 224 | i = x + y * 6; 225 | if (i < 26 && p < 10) 226 | name[p++] = 'A'.charCodeAt(0) + i; 227 | if (i == 26 && p < 10) 228 | name[p++] = '.'.charCodeAt(0); 229 | if (i == 27 && p < 10) 230 | name[p++] = '@'.charCodeAt(0); 231 | if (i == 28 && p > 0) { 232 | p--; 233 | } 234 | } 235 | 236 | function 237 | name_draw() 238 | { 239 | let i; 240 | 241 | draw_setfb(NAMEPOS_X, NAMEPOS_Y); 242 | //#ifdef GFXPC 243 | // draw_filter = 0xaaaa; /* red */ 244 | //#endif 245 | for (i = 0; i < p; i++) 246 | draw_tile(name[i]); 247 | for (i = p; i < 10; i++) 248 | draw_tile(TILE_CURSOR); 249 | 250 | //#ifdef GFXST 251 | draw_setfb(NAMEPOS_X, NAMEPOS_Y + 8); 252 | for (i = 0; i < 10; i++) 253 | draw_tile('@'); 254 | draw_setfb(NAMEPOS_X + 8 * (p < 9 ? p : 9), NAMEPOS_Y + 8); 255 | draw_tile(TILE_POINTER); 256 | //#endif 257 | } 258 | 259 | 260 | /* eof */ 261 | -------------------------------------------------------------------------------- /src/scr_imain.js: -------------------------------------------------------------------------------- 1 | import { sprintf, struct } from "./c"; 2 | import { game, game_setmusic } from "./game"; 3 | import { draw, draw_SCREENRECT, draw_pic, draw_tilesList, draw_setfb } from "./draw"; 4 | import { sysvid, sysvid_clear, sysvid_fadeStart, sysvid_fadeEnd } from "./sysvid"; 5 | import { sys_gettime } from "./system"; 6 | import { pic_splash, pic_haf } from "./dat_picST"; 7 | import { control } from "./control"; 8 | import { CONTROL_FIRE, CONTROL_EXIT } from "../include/control"; 9 | import { SCREEN_RUNNING, SCREEN_TIMEOUT, SCREEN_DONE } from "../include/screens"; 10 | 11 | // static in screen_introMain() 12 | let /*U8*/ seq = 0; 13 | let /*U8*/ seen = 0; 14 | let /*U8*/ first = true; 15 | let /*U8*/ period = 0; 16 | let /*U32*/ tm = 0; 17 | let /*U8*/ i, s = Array(32); 18 | let fading; 19 | 20 | /* 21 | * Main introduction 22 | * 23 | * return: SCREEN_RUNNING, SCREEN_DONE, SCREEN_EXIT 24 | */ 25 | export function 26 | screen_introMain(timer) 27 | { 28 | // See static above 29 | 30 | if (seq === 0) { 31 | draw.tilesBank = 0; 32 | if (first === true) { 33 | seq = 1; 34 | } else { 35 | seq = 4; 36 | } 37 | period = game.period; 38 | game.period = 50; 39 | game.rects = draw_SCREENRECT; 40 | //#ifdef ENABLE_SOUND 41 | game_setmusic("sounds/tune5.wav", -1); 42 | //#endif 43 | } 44 | 45 | switch (seq) { 46 | case 1: /* display Rick Dangerous title and Core Design copyright */ 47 | if (fading) { 48 | break; 49 | } 50 | sysvid_clear(); 51 | tm = sys_gettime(); 52 | /* 53 | #ifdef GFXPC 54 | /* Rick Dangerous title // 55 | draw_tllst = (U8 *)screen_imainrdt; 56 | draw_setfb(32, 16); 57 | draw_filter = 0xaaaa; 58 | draw_tilesList(); 59 | 60 | /* Core Design copyright + press space to start // 61 | draw_tllst = (U8 *)screen_imaincdc; 62 | draw_setfb(64, 80); 63 | draw_filter = 0x5555; 64 | draw_tilesList(); 65 | #endif 66 | */ 67 | //#ifdef GFXST 68 | draw_pic(0, 0, 0x140, 0xc8, pic_splash); 69 | //#endif 70 | 71 | seq = 2; 72 | fading = GE.Fader.IN; 73 | sysvid_fadeStart(); 74 | break; 75 | 76 | case 2: /* wait for key pressed or timeout */ 77 | if (control.status & CONTROL_FIRE) { 78 | seq = 3; 79 | } else if (sys_gettime() - tm > SCREEN_TIMEOUT) { 80 | seen++; 81 | seq = 4; 82 | 83 | fading = GE.Fader.OUT; 84 | sysvid_fadeStart(); 85 | } 86 | break; 87 | 88 | case 3: /* wait for key released */ 89 | if (!(control.status & CONTROL_FIRE)) { 90 | if (seen++ === 0) { 91 | seq = 4; 92 | } else { 93 | seq = 7; 94 | 95 | fading = GE.Fader.OUT; 96 | sysvid_fadeStart(); 97 | } 98 | } 99 | break; 100 | 101 | case 4: /* dispay hall of fame */ 102 | if (fading) { 103 | break; 104 | } 105 | sysvid_clear(); 106 | tm = sys_gettime(); 107 | 108 | /* hall of fame title *//* 109 | #ifdef GFXPC 110 | draw_tllst = (U8 *)screen_imainhoft; 111 | draw_setfb(32, 0); 112 | draw_filter = 0xaaaa; 113 | draw_tilesList(); 114 | #endif*/ 115 | //#ifdef GFXST 116 | draw_pic(64, 4, 0x140, 0x20, pic_haf); 117 | //#endif 118 | 119 | /* hall of fame content */ 120 | draw_setfb(56, 40); 121 | //#ifdef GFXPC 122 | // draw_filter = 0x5555; 123 | //#endif 124 | for (i = 0; i < 8; i++) { 125 | const tmp = `00${game.hscores[i].score}`; // %06d 126 | const game_hscores_i_score = tmp.substring(tmp.length - 6, tmp.length); 127 | 128 | sprintf(s, "{0}@@@....@@@{1}", 129 | game_hscores_i_score, game.hscores[i].name); 130 | s[26] = '\xFF'; s[27] = '\xFF'; s[28] = '\xFE'; // \377 \377 \376 131 | draw.tllst = [...s]; 132 | draw_tilesList(); 133 | } 134 | 135 | seq = 5; 136 | fading = GE.Fader.IN; 137 | sysvid_fadeStart(); 138 | break; 139 | 140 | case 5: /* wait for key pressed or timeout */ 141 | if (control.status & CONTROL_FIRE) { 142 | seq = 6; 143 | } else if (sys_gettime() - tm > SCREEN_TIMEOUT) { 144 | seen++; 145 | seq = 1; 146 | 147 | fading = GE.Fader.OUT; 148 | sysvid_fadeStart(); 149 | } 150 | break; 151 | 152 | case 6: /* wait for key released */ 153 | if (!(control.status & CONTROL_FIRE)) { 154 | if (seen++ == 0) { 155 | seq = 1; 156 | } else { 157 | seq = 7; 158 | 159 | fading = GE.Fader.OUT; 160 | sysvid_fadeStart(); 161 | } 162 | } 163 | break; 164 | } 165 | 166 | if (fading) { 167 | game.rects = draw_SCREENRECT; 168 | if (!sysvid.fader.update(timer, fading)) { 169 | fading = sysvid_fadeEnd(); 170 | // Loop directly to prevent flipping 171 | if (seq !== 7) { 172 | screen_introMain(timer); 173 | } 174 | } 175 | } 176 | 177 | if (control.status & CONTROL_EXIT) { /* check for exit request */ 178 | return SCREEN_EXIT; 179 | } 180 | 181 | if (seq == 7) { /* we're done */ 182 | sysvid_clear(); 183 | seq = 0; 184 | seen = 0; 185 | first = false; 186 | game.period = period; 187 | return SCREEN_DONE; 188 | } else { 189 | return SCREEN_RUNNING; 190 | } 191 | } 192 | 193 | /* eof */ 194 | 195 | 196 | -------------------------------------------------------------------------------- /src/scr_imap.js: -------------------------------------------------------------------------------- 1 | import { control } from "./control"; 2 | import { game, game_setmusic } from "./game"; 3 | import { sysvid, sysvid_clear, sysvid_fadeStart, sysvid_fadeEnd } from "./sysvid"; 4 | import { draw, draw_SCREENRECT, draw_setfb, draw_tilesSubList, draw_tilesList, draw_tile, draw_sprite } from "./draw"; 5 | import { map_maps } from "./dat_maps"; 6 | import { screen_imapsteps, screen_imapsl, screen_imapsofs, screen_imaptext } from "./dat_screens"; 7 | import { rect_t } from "../include/rects"; 8 | import { CONTROL_FIRE, CONTROL_EXIT } from "../include/control"; 9 | import { SCREEN_EXIT, SCREEN_DONE, SCREEN_RUNNING } from "../include/screens"; 10 | import { sys_sleep } from "./system"; 11 | import { struct } from "./c"; 12 | 13 | /* 14 | * local vars 15 | */ 16 | let step; /* current step */ 17 | let count; /* number of loops for current step */ 18 | let run; /* 1 = run, 0 = no more step */ 19 | let flipflop; /* flipflop for top, bottom, left, right */ 20 | let spnum; /* sprite number */ 21 | let spx, spdx; /* sprite x position and delta */ 22 | let spy, spdy; /* sprite y position and delta */ 23 | let spbase, spoffs; /* base, offset for sprite numbers table */ 24 | let seq = 0; /* anim sequence */ 25 | 26 | let fading; 27 | 28 | // FIXME: like draw_setfb() with +8, +16??? 29 | const anim_rect = rect_t( 120 + 8, 16 + 16, 64, 64, null ); /* anim rectangle */ 30 | 31 | /* 32 | * Map introduction 33 | * 34 | * ASM: 1948 35 | * 36 | * return: SCREEN_RUNNING, SCREEN_DONE, SCREEN_EXIT 37 | */ 38 | export function 39 | screen_introMap(timer) 40 | { 41 | switch (seq) { 42 | case 0: 43 | sysvid_clear(); 44 | /* 45 | #ifdef GFXPC 46 | draw_tilesBank = 1; 47 | draw_filter = 0xAAAA; 48 | #endif*/ 49 | //#ifdef GFXST 50 | draw.tilesBank = 0; 51 | //#endif 52 | draw.tllst = [...screen_imaptext[game.map]]; 53 | draw_setfb(32 + 8, 0 + 16); 54 | draw_tilesSubList(); 55 | 56 | draw_setfb(32 + 8, 96 + 16); // +2??? 57 | //#ifdef GFXPC 58 | // draw_filter = 0x5555; 59 | //#endif 60 | draw_tilesList(); 61 | 62 | game.rects = null; 63 | 64 | //#ifdef GFXPC 65 | // draw_filter = 0xFFFF; 66 | //#endif 67 | 68 | init(); 69 | nextstep(); 70 | drawcenter(); 71 | drawtb(); 72 | drawlr(); 73 | drawsprite(); 74 | control.last = 0; 75 | 76 | game.rects = draw_SCREENRECT; 77 | 78 | //#ifdef ENABLE_SOUND 79 | game_setmusic(map_maps[game.map].tune, 1); 80 | //#endif 81 | 82 | seq = 1; 83 | fading = GE.Fader.IN; 84 | sysvid_fadeStart(); 85 | break; 86 | case 1: /* top and bottom borders */ 87 | drawtb(); 88 | game.rects = anim_rect; 89 | seq = 2; 90 | break; 91 | case 2: /* background and sprite */ 92 | anim(); 93 | drawcenter(); 94 | drawsprite(); 95 | game.rects = anim_rect; 96 | seq = 3; 97 | break; 98 | case 3: /* all borders */ 99 | drawtb(); 100 | drawlr(); 101 | game.rects = anim_rect; 102 | seq = 1; 103 | break; 104 | case 4: /* wait for key release */ 105 | if (!(control.status & CONTROL_FIRE)) 106 | seq = 5; 107 | else 108 | sys_sleep(50); /* .5s */ 109 | break; 110 | } 111 | 112 | if (control.status & CONTROL_FIRE) { /* end as soon as key pressed */ 113 | seq = 4; 114 | fading = GE.Fader.OUT; 115 | sysvid_fadeStart(); 116 | } 117 | 118 | if (fading) { 119 | game.rects = draw_SCREENRECT; 120 | if (!sysvid.fader.update(timer, fading)) { 121 | fading = sysvid_fadeEnd(); 122 | } 123 | } 124 | 125 | if (control.status & CONTROL_EXIT) { /* check for exit request */ 126 | return SCREEN_EXIT; 127 | } 128 | 129 | if (seq === 5 && !fading) { /* end as soon as key pressed */ 130 | sysvid_clear(); 131 | seq = 0; 132 | return SCREEN_DONE; 133 | } else { 134 | return SCREEN_RUNNING; 135 | } 136 | } 137 | 138 | 139 | /* 140 | * Display top and bottom borders (0x1B1F) 141 | * 142 | */ 143 | function 144 | drawtb() 145 | { 146 | let i; 147 | 148 | flipflop++; 149 | if (flipflop & 0x01) { 150 | draw_setfb(128 + 8, 16 + 16); 151 | for (i = 0; i < 6; i++) 152 | draw_tile(0x40); 153 | draw_setfb(128 + 8, 72 + 16); 154 | for (i = 0; i < 6; i++) 155 | draw_tile(0x06); 156 | } 157 | else { 158 | draw_setfb(128 + 8, 16 + 16); 159 | for (i = 0; i < 6; i++) 160 | draw_tile(0x05); 161 | draw_setfb(128 + 8, 72 + 16); 162 | for (i = 0; i < 6; i++) 163 | draw_tile(0x40); 164 | } 165 | } 166 | 167 | 168 | /* 169 | * Display left and right borders (0x1B7C) 170 | * 171 | */ 172 | function 173 | drawlr() 174 | { 175 | let i; 176 | 177 | if (flipflop & 0x02) { 178 | for (i = 0; i < 8; i++) { 179 | draw_setfb(120 + 8, 16 + i * 8 + 16); 180 | draw_tile(0x04); 181 | draw_setfb(176 + 8, 16 + i * 8 + 16); 182 | draw_tile(0x04); 183 | } 184 | } 185 | else { 186 | for (i = 0; i < 8; i++) { 187 | draw_setfb(120 + 8, 16 + i * 8 + 16); 188 | draw_tile(0x2B); 189 | draw_setfb(176 + 8, 16 + i * 8 + 16); 190 | draw_tile(0x2B); 191 | } 192 | } 193 | } 194 | 195 | 196 | /* 197 | * Draw the sprite (0x19C6) 198 | * 199 | */ 200 | function 201 | drawsprite() 202 | { 203 | draw_sprite(spnum, 128 + ((spx << 1) & 0x1C) + 8, 24 + (spy << 1) + 16); 204 | } 205 | 206 | 207 | /* 208 | * Draw the background (0x1AF1) 209 | * 210 | */ 211 | function 212 | drawcenter() 213 | { 214 | const tn0 = [ 0x07, 0x5B, 0x7F, 0xA3, 0xC7 ]; 215 | let i, j, tn; 216 | 217 | tn = tn0[game.map]; 218 | for (i = 0; i < 6; i++) { 219 | draw_setfb(128 + 8, (24 + 8 * i) + 16); 220 | for (j = 0; j < 6; j++) 221 | draw_tile(tn++); 222 | } 223 | } 224 | 225 | 226 | /* 227 | * Next Step (0x1A74) 228 | * 229 | */ 230 | function 231 | nextstep() 232 | { 233 | if (screen_imapsteps[step].count) { 234 | count = screen_imapsteps[step].count; 235 | spdx = screen_imapsteps[step].dx; 236 | spdy = screen_imapsteps[step].dy; 237 | spbase = screen_imapsteps[step].base; 238 | spoffs = 0; 239 | step++; 240 | } 241 | else { 242 | run = 0; 243 | } 244 | } 245 | 246 | 247 | /* 248 | * Anim (0x1AA8) 249 | * 250 | */ 251 | function 252 | anim() 253 | { 254 | let i; 255 | 256 | if (run) { 257 | i = screen_imapsl[spbase + spoffs]; 258 | if (i == 0) { 259 | spoffs = 0; 260 | i = screen_imapsl[spbase]; 261 | } 262 | spnum = i; 263 | spoffs++; 264 | spx += spdx; 265 | spy += spdy; 266 | count--; 267 | if (count == 0) 268 | nextstep(); 269 | } 270 | } 271 | 272 | 273 | /* 274 | * Initialize (0x1A43) 275 | * 276 | */ 277 | function 278 | init() 279 | { 280 | run = 0; run--; 281 | step = screen_imapsofs[game.map]; 282 | spx = screen_imapsteps[step].dx; 283 | spy = screen_imapsteps[step].dy; 284 | step++; 285 | spnum = 0; /* NOTE spnum in [8728] is never initialized ? */ 286 | } 287 | 288 | /* eof */ 289 | -------------------------------------------------------------------------------- /src/scr_pause.js: -------------------------------------------------------------------------------- 1 | import { struct } from "./c"; 2 | import { screen_pausedtxt } from "./dat_screens"; 3 | 4 | /* 5 | * Display the pause indicator 6 | */ 7 | export function 8 | screen_pause(pause) 9 | { 10 | if (pause === true) { 11 | draw.tilesBank = 0; 12 | draw.tllst = [...screen_pausedtxt]; 13 | draw_setfb(120, 80); 14 | //#ifdef GFXPC 15 | // draw_filter = 0xAAAA; 16 | //#endif 17 | draw_tilesList(); 18 | } 19 | else { 20 | //#ifdef GFXPC 21 | // draw_filter = 0xFFFF; 22 | //#endif 23 | draw_map(); 24 | ent_draw(); 25 | draw_drawStatus(); 26 | } 27 | game.rects = draw_SCREENRECT; 28 | } 29 | 30 | 31 | /* eof */ 32 | 33 | -------------------------------------------------------------------------------- /src/scr_xrick.js: -------------------------------------------------------------------------------- 1 | import { sysvid_clear, sysvid_setGamePalette } from "./sysvid"; 2 | import { SCREEN_EXIT, SCREEN_DONE, SCREEN_RUNNING } from "../include/screens"; 3 | import { CONTROL_EXIT } from "../include/control"; 4 | import { control } from "./control"; 5 | import { draw_SCREENRECT } from "./draw" 6 | import { game, game_setmusic } from "./game"; 7 | import { struct } from "./c"; 8 | 9 | let seq = 0; 10 | let wait = 0; 11 | 12 | /* 13 | * Display XRICK splash screen 14 | * 15 | * return: SCREEN_RUNNING, SCREEN_DONE, SCREEN_EXIT 16 | */ 17 | export function 18 | screen_xrick() 19 | { 20 | 21 | 22 | if (seq === 0) { 23 | sysvid_clear(); 24 | // draw_img(IMG_SPLASH); 25 | game.rects = draw_SCREENRECT; 26 | seq = 1; 27 | } 28 | 29 | switch (seq) { 30 | case 1: /* wait */ 31 | if (wait++ > 0x2) { 32 | //#ifdef ENABLE_SOUND 33 | game_setmusic("sounds/bullet.wav", 1); 34 | //#endif 35 | seq = 2; 36 | wait = 0; 37 | } 38 | break; 39 | 40 | case 2: /* wait */ 41 | if (wait++ > 0x20) { 42 | seq = 99; 43 | wait = 0; 44 | } 45 | break; 46 | } 47 | 48 | if (control.status & CONTROL_EXIT) /* check for exit request */ 49 | return SCREEN_EXIT; 50 | 51 | if (seq === 99) { /* we're done */ 52 | sysvid_clear(); 53 | sysvid_setGamePalette(); 54 | seq = 0; 55 | return SCREEN_DONE; 56 | } 57 | 58 | return SCREEN_RUNNING; 59 | } 60 | -------------------------------------------------------------------------------- /src/scroller.js: -------------------------------------------------------------------------------- 1 | import { draw_drawStatus, draw_map, draw_SCREENRECT } from "./draw"; 2 | import { SCROLL_DONE, SCROLL_PERIOD, SCROLL_RUNNING } from "../include/scroller"; 3 | import { MAP_ROW_HBBOT, MAP_ROW_HBTOP, MAP_ROW_HTBOT, MAP_ROW_HTTOP, 4 | MAP_ROW_SCRBOT, MAP_ROW_SCRTOP } from "../include/maps"; 5 | import { ent_draw, ent_actvis } from "./ents"; 6 | import { map, map_expand } from "./maps"; 7 | import { game } from "./game"; 8 | import { ent } from "../include/ents"; 9 | import { struct, _U8 } from "./c"; 10 | 11 | let period; 12 | 13 | /* 14 | * Scroll up 15 | * 16 | */ 17 | let n1 = 0; 18 | 19 | export function 20 | scroll_up() 21 | { 22 | let i, j; 23 | // static U8 n = 0; 24 | 25 | /* last call: restore */ 26 | if (n1 === 8) { 27 | n1 = 0; 28 | game.period = period; 29 | return SCROLL_DONE; 30 | } 31 | 32 | /* first call: prepare */ 33 | if (n1 === 0) { 34 | period = game.period; 35 | game.period = SCROLL_PERIOD; 36 | } 37 | 38 | /* translate map */ 39 | for (i = MAP_ROW_SCRTOP; i < MAP_ROW_HBBOT; i++) 40 | for (j = 0x00; j < 0x20; j++) 41 | map.map[i][j] = map.map[i + 1][j]; 42 | 43 | /* translate entities */ 44 | for (i = 0; ent.ents[i].n != 0xFF; i++) { 45 | if (ent.ents[i].n) { 46 | ent.ents[i].ysave -= 8; 47 | ent.ents[i].trig_y -= 8; 48 | ent.ents[i].y -= 8; 49 | if (ent.ents[i].y & 0x8000) { /* map coord. from 0x0000 to 0x0140 */ 50 | /* IFDEBUG_SCROLLER( 51 | sys_printf("xrick/scroller: entity %#04X is gone\n", i); 52 | );*/ 53 | ent.ents[i].n = 0; 54 | } 55 | } 56 | } 57 | 58 | /* display */ 59 | draw_map(); 60 | ent_draw(); 61 | draw_drawStatus(); 62 | map.frow = _U8(++map.frow); 63 | 64 | /* loop */ 65 | if (n1++ === 7) { 66 | /* activate visible entities */ 67 | ent_actvis(map.frow + MAP_ROW_HBTOP, map.frow + MAP_ROW_HBBOT); 68 | 69 | /* prepare map */ 70 | map_expand(); 71 | 72 | /* display */ 73 | draw_map(); 74 | ent_draw(); 75 | draw_drawStatus(); 76 | } 77 | 78 | game.rects = draw_SCREENRECT; 79 | 80 | return SCROLL_RUNNING; 81 | } 82 | 83 | /* 84 | * Scroll down 85 | * 86 | */ 87 | let n2 = 0; 88 | 89 | export function 90 | scroll_down() 91 | { 92 | let i, j; 93 | // static U8 n = 0; 94 | 95 | /* last call: restore */ 96 | if (n2 === 8) { 97 | n2 = 0; 98 | game.period = period; 99 | return SCROLL_DONE; 100 | } 101 | 102 | /* first call: prepare */ 103 | if (n2 === 0) { 104 | period = game.period; 105 | game.period = SCROLL_PERIOD; 106 | } 107 | 108 | /* translate map */ 109 | for (i = MAP_ROW_SCRBOT; i > MAP_ROW_HTTOP; i--) 110 | for (j = 0x00; j < 0x20; j++) 111 | map.map[i][j] = map.map[i - 1][j]; 112 | 113 | /* translate entities */ 114 | for (i = 0; ent.ents[i].n != 0xFF; i++) { 115 | if (ent.ents[i].n) { 116 | ent.ents[i].ysave += 8; 117 | ent.ents[i].trig_y += 8; 118 | ent.ents[i].y += 8; 119 | if (ent.ents[i].y > 0x0140) { /* map coord. from 0x0000 to 0x0140 */ 120 | /* IFDEBUG_SCROLLER( 121 | sys_printf("xrick/scroller: entity %#04X is gone\n", i); 122 | );*/ 123 | ent.ents[i].n = 0; 124 | } 125 | } 126 | } 127 | 128 | /* display */ 129 | draw_map(); 130 | ent_draw(); 131 | draw_drawStatus(); 132 | map.frow = _U8(--map.frow); 133 | 134 | /* loop */ 135 | if (n2++ === 7) { 136 | /* activate visible entities */ 137 | ent_actvis(map.frow + MAP_ROW_HTTOP, map.frow + MAP_ROW_HTBOT); 138 | 139 | /* prepare map */ 140 | map_expand(); 141 | 142 | /* display */ 143 | draw_map(); 144 | ent_draw(); 145 | draw_drawStatus(); 146 | } 147 | 148 | game.rects = draw_SCREENRECT; 149 | 150 | return SCROLL_RUNNING; 151 | } 152 | 153 | /* eof */ 154 | -------------------------------------------------------------------------------- /src/sysarg.js: -------------------------------------------------------------------------------- 1 | /* 2 | * RickJS, a JavaScript port of XRick 3 | * 4 | * This source file is based on the folliwing files: 5 | * - xrick/src/sysarg.c 6 | * 7 | * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved. 8 | * Copyright (C) 2012-2022 Chrilith (me@chrilith.com). All rights reserved. 9 | * 10 | * The use and distribution terms for this software are contained in the file 11 | * named README, which can be found in the root of this distribution. By 12 | * using this software in any fashion, you are agreeing to be bound by the 13 | * terms of this license. 14 | * 15 | * You must not remove this notice, or any other, from this software. 16 | */ 17 | 18 | export const sysarg = { 19 | args_period: 0, 20 | args_map: 3, 21 | args_submap: 0, 22 | 23 | args_nosound: 0 24 | }; 25 | 26 | /* 27 | * Read and process arguments 28 | */ 29 | export function sysarg_init(argc, argv) { 30 | // TODO 31 | console.log("sysarg_init()"); 32 | } 33 | -------------------------------------------------------------------------------- /src/sysevt.js: -------------------------------------------------------------------------------- 1 | import { control } from "./control"; 2 | import { CONTROL_UP, CONTROL_DOWN, CONTROL_LEFT, CONTROL_RIGHT, 3 | CONTROL_PAUSE, CONTROL_END, CONTROL_FIRE } from "../include/control"; 4 | 5 | const MAN = G.EventManager; 6 | const event_man = new G.EventManager(MAN.BIT_KEYBOARD); 7 | 8 | function SETBIT(b) { control.status |= (b); } 9 | function CLRBIT(b) { control.status &= ~(b); } 10 | 11 | /* 12 | * Process an event 13 | */ 14 | function 15 | processEvent(event) 16 | { 17 | let key; 18 | const E = G.Event; 19 | 20 | switch (event.type) { 21 | case E.KEYDOWN: 22 | key = event.keyCode; 23 | if (key == E.K_UP) { 24 | SETBIT(CONTROL_UP); 25 | control.last = CONTROL_UP; 26 | 27 | } else if (key == E.K_DOWN) { 28 | SETBIT(CONTROL_DOWN); 29 | control.last = CONTROL_DOWN; 30 | 31 | } else if (key == E.K_LEFT) { 32 | SETBIT(CONTROL_LEFT); 33 | control.last = CONTROL_LEFT; 34 | 35 | } else if (key == E.K_RIGHT) { 36 | SETBIT(CONTROL_RIGHT); 37 | control.last = CONTROL_RIGHT; 38 | 39 | } else if (key == 'P'.charCodeAt(0)) { 40 | SETBIT(CONTROL_PAUSE); 41 | control.last = CONTROL_PAUSE; 42 | 43 | } else if (key == E.K_ESCAPE) { 44 | SETBIT(CONTROL_END); 45 | control.last = CONTROL_END; 46 | /* 47 | } else if (key == syskbd_xtra) { 48 | SETBIT(CONTROL_EXIT); 49 | Control.last = CONTROL_EXIT; 50 | */ 51 | } else if (key == E.K_SPACE) { 52 | SETBIT(CONTROL_FIRE); 53 | control.last = CONTROL_FIRE; 54 | } 55 | /* 56 | else if (key == SDLK_F1) { 57 | sysvid_toggleFullscreen(); 58 | } 59 | else if (key == SDLK_F2) { 60 | sysvid_zoom(-1); 61 | } 62 | else if (key == SDLK_F3) { 63 | sysvid_zoom(+1); 64 | } 65 | #ifdef ENABLE_SOUND 66 | else if (key == SDLK_F4) { 67 | syssnd_toggleMute(); 68 | } 69 | else if (key == SDLK_F5) { 70 | syssnd_vol(-1); 71 | } 72 | else if (key == SDLK_F6) { 73 | syssnd_vol(+1); 74 | } 75 | #endif 76 | #ifdef ENABLE_CHEATS 77 | else if (key == SDLK_F7) { 78 | game_toggleCheat(1); 79 | } 80 | else if (key == SDLK_F8) { 81 | game_toggleCheat(2); 82 | } 83 | else if (key == SDLK_F9) { 84 | game_toggleCheat(3); 85 | } 86 | #endif 87 | */ 88 | break; 89 | 90 | case E.KEYUP: 91 | key = event.keyCode; 92 | 93 | if (key == E.K_UP) { 94 | CLRBIT(CONTROL_UP); 95 | control.last = CONTROL_UP; 96 | 97 | } else if (key == E.K_DOWN) { 98 | CLRBIT(CONTROL_DOWN); 99 | control.last = CONTROL_DOWN; 100 | 101 | } else if (key == E.K_LEFT) { 102 | CLRBIT(CONTROL_LEFT); 103 | control.last = CONTROL_LEFT; 104 | 105 | } else if (key == E.K_RIGHT) { 106 | CLRBIT(CONTROL_RIGHT); 107 | control.last = CONTROL_RIGHT; 108 | 109 | } else if (key == 'P'.charCodeAt(0)) { 110 | CLRBIT(CONTROL_PAUSE); 111 | control.last = CONTROL_PAUSE; 112 | 113 | } else if (key == 'S'.charCodeAt(0)) { 114 | sysvid.toggle_scanlines(); 115 | 116 | } else if (key == E.K_ESCAPE) { 117 | CLRBIT(CONTROL_END); 118 | control.last = CONTROL_END; 119 | /* 120 | } else if (key == syskbd_xtra) { 121 | CLRBIT(CONTROL_EXIT); 122 | Control.last = CONTROL_EXIT; 123 | */ 124 | } else if (key == E.K_SPACE) { 125 | CLRBIT(CONTROL_FIRE); 126 | control.last = CONTROL_FIRE; 127 | } 128 | break; 129 | default: 130 | break; 131 | } 132 | } 133 | 134 | /* 135 | * Process events, if any, then return 136 | */ 137 | export function 138 | sysevt_poll() 139 | { 140 | let e; 141 | 142 | while ((e = event_man.poll())) { 143 | processEvent(e); 144 | } 145 | } 146 | 147 | /* 148 | * Wait for an event, then process it and return 149 | */ 150 | export function 151 | sysevt_wait() 152 | { 153 | sysevt_poll(); 154 | } 155 | 156 | /* eof */ 157 | -------------------------------------------------------------------------------- /src/syssnd.js: -------------------------------------------------------------------------------- 1 | /* 2 | * RickJS, a JavaScript port of XRick 3 | * 4 | * This source file is based on the folliwing files: 5 | * - xrick/src/syssnd.c 6 | * 7 | * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved. 8 | * Copyright (C) 2012-2022 Chrilith (me@chrilith.com). All rights reserved. 9 | * 10 | * The use and distribution terms for this software are contained in the file 11 | * named README, which can be found in the root of this distribution. By 12 | * using this software in any fashion, you are agreeing to be bound by the 13 | * terms of this license. 14 | * 15 | * You must not remove this notice, or any other, from this software. 16 | */ 17 | 18 | 19 | let isAudioActive = false; 20 | 21 | 22 | export function 23 | syssnd_init() 24 | { 25 | console.log("syssnd_init()"); 26 | // TODO 27 | } 28 | 29 | /* 30 | * Play a sound 31 | * 32 | * loop: number of times the sound should be played, -1 to loop forever 33 | * returns: channel number, or -1 if none was available 34 | * 35 | * NOTE if sound is already playing, simply reset it (i.e. can not have 36 | * twice the same sound playing -- tends to become noisy when too many 37 | * bad guys die at the same time). 38 | */ 39 | export function 40 | syssnd_play(sound, loop) 41 | { 42 | let c; 43 | 44 | if (!isAudioActive) return -1; 45 | if (sound === null) return -1; 46 | 47 | c = 0; 48 | /* SDL_mutexP(sndlock); 49 | while ((channel[c].snd != sound || channel[c].loop == 0) && 50 | channel[c].loop != 0 && 51 | c < SYSSND_MIXCHANNELS) 52 | c++; 53 | if (c == SYSSND_MIXCHANNELS) 54 | c = -1; 55 | 56 | IFDEBUG_AUDIO( 57 | if (channel[c].snd == sound && channel[c].loop != 0) 58 | sys_printf("xrick/sound: already playing %s on channel %d - resetting\n", 59 | sound->name, c); 60 | else if (c >= 0) 61 | sys_printf("xrick/sound: playing %s on channel %d\n", sound->name, c); 62 | ); 63 | 64 | if (c >= 0) { 65 | channel[c].loop = loop; 66 | channel[c].snd = sound; 67 | channel[c].buf = sound->buf; 68 | channel[c].len = sound->len; 69 | } 70 | SDL_mutexV(sndlock);*/ 71 | 72 | console.log("syssnd_play(%s) %dx", sound, loop); 73 | return c; 74 | } 75 | -------------------------------------------------------------------------------- /src/system.js: -------------------------------------------------------------------------------- 1 | /* 2 | * RickJS, a JavaScript port of XRick 3 | * 4 | * This source file is based on the folliwing files: 5 | * - xrick/src/system.c 6 | * 7 | * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved. 8 | * Copyright (C) 2012-2022 Chrilith (me@chrilith.com). All rights reserved. 9 | * 10 | * The use and distribution terms for this software are contained in the file 11 | * named README, which can be found in the root of this distribution. By 12 | * using this software in any fashion, you are agreeing to be bound by the 13 | * terms of this license. 14 | * 15 | * You must not remove this notice, or any other, from this software. 16 | */ 17 | 18 | import { sysarg_init, sysarg } from "./sysarg"; 19 | import { sysvid_init } from "./sysvid"; 20 | import { syssnd_init } from "./syssnd"; 21 | 22 | let /*U32*/ ticks_base = 0; // static 23 | 24 | /* 25 | * Return number of microseconds elapsed since first call 26 | */ 27 | export function 28 | sys_gettime() 29 | { 30 | // See static above 31 | let ticks; 32 | 33 | ticks = Date.now(); 34 | 35 | if (!ticks_base) { 36 | ticks_base = ticks; 37 | } 38 | 39 | return ticks - ticks_base; 40 | } 41 | 42 | 43 | /* 44 | * Sleep a number of microseconds 45 | */ 46 | export function 47 | sys_sleep(s) 48 | { 49 | console.log("sys_sleep(%d)", s); 50 | //SDL_Delay(s); 51 | } 52 | 53 | /* 54 | * Initialize system 55 | */ 56 | export function 57 | sys_init(argc, argv) 58 | { 59 | sysarg_init(argc, argv); 60 | sysvid_init(); 61 | //#ifdef ENABLE_JOYSTICK 62 | // sysjoy_init(); 63 | //#endif 64 | //#ifdef ENABLE_SOUND 65 | if (sysarg.args_nosound === 0) { 66 | syssnd_init(); 67 | } 68 | //#endif 69 | // atexit(sys_shutdown); 70 | // signal(SIGINT, exit); 71 | // signal(SIGTERM, exit); 72 | } 73 | 74 | /* 75 | * Shutdown system 76 | */ 77 | export function 78 | sys_shutdown() 79 | { 80 | //#ifdef ENABLE_SOUND 81 | syssnd_shutdown(); 82 | //#endif 83 | //#ifdef ENABLE_JOYSTICK 84 | // sysjoy_shutdown(); 85 | //#endif 86 | sysvid_shutdown(); 87 | } 88 | 89 | /* eof */ 90 | -------------------------------------------------------------------------------- /src/sysvid.js: -------------------------------------------------------------------------------- 1 | /* 2 | * RickJS, a JavaScript port of XRick 3 | * 4 | * This source file is based on the folliwing files: 5 | * - xrick/src/sysvid.c 6 | * 7 | * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved. 8 | * Copyright (C) 2012-2022 Chrilith (me@chrilith.com). All rights reserved. 9 | * 10 | * The use and distribution terms for this software are contained in the file 11 | * named README, which can be found in the root of this distribution. By 12 | * using this software in any fashion, you are agreeing to be bound by the 13 | * terms of this license. 14 | * 15 | * You must not remove this notice, or any other, from this software. 16 | */ 17 | 18 | import { rect_t } from "../include/rects"; 19 | import { SYSVID_WIDTH, SYSVID_HEIGHT } from "../include/system"; 20 | import { as_const } from "./c"; 21 | 22 | export const sysvid = { 23 | fb: null /* frame buffer */, 24 | fader: null 25 | }; 26 | const SCREENRECT = as_const(rect_t(0, 0, SYSVID_WIDTH, SYSVID_HEIGHT, null)); 27 | 28 | let screen, buffer; 29 | 30 | /* 31 | * Initialize screen 32 | */ 33 | function 34 | initScreen(w, h/*, bpp, flags*/) 35 | { 36 | var s = new G.Screen(w, h); 37 | G.Screen.setActive(s); 38 | s.enableFiltering(false); 39 | s.setStretch(s.STRETCH_UNIFORM); 40 | 41 | return s; 42 | } 43 | 44 | export function 45 | sysvid_setGamePalette() 46 | { 47 | console.log("sysvid_setGamePalette()"); 48 | // TODO 49 | } 50 | 51 | /* 52 | * Initialise video 53 | */ 54 | export function 55 | sysvid_init() 56 | { 57 | // TODO: zoom 58 | screen = initScreen(SYSVID_WIDTH, SYSVID_HEIGHT); 59 | 60 | /* 61 | * create v_ frame buffer 62 | */ 63 | sysvid.fb = new G.Surface(SYSVID_WIDTH, SYSVID_HEIGHT); 64 | 65 | // Gamalto specific to handle true color mode 66 | buffer = sysvid.fb; 67 | sysvid.fader = new GE.Fader(sysvid.fb, new G.Color(), 150); 68 | } 69 | 70 | /* 71 | * Shutdown video 72 | */ 73 | export function 74 | sysvid_shutdown() 75 | { 76 | // free(sysvid_fb); 77 | sysvid.fb = null; 78 | console.log("sysvid_shutdown()"); 79 | // SDL_Quit(); 80 | } 81 | 82 | 83 | /* 84 | * Update screen 85 | * NOTE errors processing ? 86 | */ 87 | export function 88 | sysvid_update(rects) 89 | { 90 | if (rects == null) 91 | return; 92 | 93 | const rs = []; 94 | while (rects) { 95 | rs.push(new G.Rect(rects.x, rects.y, rects.width, rects.height)); 96 | rects = rects.next; 97 | } 98 | screen.redraw(buffer, 0, 0, rs); 99 | screen.refresh(); 100 | } 101 | 102 | /* 103 | * Clear screen 104 | * (077C) 105 | */ 106 | export function 107 | sysvid_clear() 108 | { 109 | sysvid.fb.renderer.fillRect(null, new G.Color(0,0,0)); 110 | } 111 | 112 | /* 113 | * Gamalto 114 | */ 115 | export function 116 | sysvid_fadeStart() 117 | { 118 | sysvid.fader.reset(); 119 | buffer = sysvid.fader.surface; 120 | } 121 | 122 | export function 123 | sysvid_fadeEnd() 124 | { 125 | buffer = sysvid.fb; 126 | } 127 | 128 | /* eof */ 129 | -------------------------------------------------------------------------------- /src/util.js: -------------------------------------------------------------------------------- 1 | import { ent, ENT_ENTSNUM } from "../include/ents"; 2 | import { ent_entdata } from "./dat_ents"; 3 | import { map } from "./maps"; 4 | import { game } from "./game"; 5 | import { e_rick_boxtest } from "./e_rick"; 6 | import { E_RICK_NO } from "../include/e_rick"; 7 | import { MAP_EFLG_01, MAP_EFLG_CLIMB, MAP_EFLG_FGND, MAP_EFLG_LETHAL, 8 | MAP_EFLG_SOLID, MAP_EFLG_SPAD, MAP_EFLG_VERT, 9 | MAP_EFLG_WAYUP } from "../include/maps"; 10 | import { _U8 } from "./c"; 11 | 12 | /* 13 | * Full box test. 14 | * 15 | * ASM 1199 16 | * 17 | * e: entity to test against. 18 | * x,y: coordinates to test. 19 | * ret: TRUE/(x,y) is within e's space, FALSE/not. 20 | */ 21 | export function 22 | u_fboxtest(e, x, y) 23 | { 24 | if (ent.ents[e].x >= x || 25 | ent.ents[e].x + ent.ents[e].w < x || 26 | ent.ents[e].y >= y || 27 | ent.ents[e].y + ent.ents[e].h < y) 28 | return false; 29 | else 30 | return true; 31 | } 32 | 33 | 34 | 35 | 36 | /* 37 | * Box test (then whole e2 is checked agains the center of e1). 38 | * 39 | * ASM 113E 40 | * 41 | * e1: entity to test against (corresponds to DI in asm code). 42 | * e2: entity to test (corresponds to SI in asm code). 43 | * ret: TRUE/intersect, FALSE/not. 44 | */ 45 | export function 46 | u_boxtest(e1, e2) 47 | { 48 | /* rick is special (may be crawling) */ 49 | if (e1 === E_RICK_NO) 50 | return e_rick_boxtest(e2); 51 | 52 | /* 53 | * entity 1: x+0x05 to x+0x011, y to y+0x14 54 | * entity 2: x to x+ .w, y to y+ .h 55 | */ 56 | if (ent.ents[e1].x + 0x11 < ent.ents[e2].x || 57 | ent.ents[e1].x + 0x05 > ent.ents[e2].x + ent.ents[e2].w || 58 | ent.ents[e1].y + 0x14 < ent.ents[e2].y || 59 | ent.ents[e1].y > ent.ents[e2].y + ent.ents[e2].h - 1) 60 | return false; 61 | else 62 | return true; 63 | } 64 | 65 | 66 | /* 67 | * Compute the environment flag. 68 | * 69 | * ASM 0FBC if !crawl, else 103E 70 | * 71 | * x, y: coordinates where to compute the environment flag 72 | * crawl: is rick crawling? 73 | * rc0: anything CHANGED to the environment flag for crawling (6DBA) 74 | * rc1: anything CHANGED to the environment flag (6DAD) 75 | */ 76 | export function 77 | u_envtest(x, y, crawl, rc0, rc1) 78 | { 79 | let i, xx; 80 | 81 | /* prepare for ent #0 test */ 82 | ent.ents[ENT_ENTSNUM].x = x; 83 | ent.ents[ENT_ENTSNUM].y = y; 84 | 85 | i = 1; 86 | if (!crawl) i++; 87 | if (y & 0x0004) i++; 88 | 89 | x += 4; 90 | xx = _U8(x); /* FIXME? */ 91 | 92 | x = x >> 3; /* from pixels to tiles */ 93 | y = y >> 3; /* from pixels to tiles */ 94 | 95 | rc0 = rc1 = 0; 96 | 97 | if (xx & 0x07) { /* tiles columns alignment */ 98 | if (crawl) { 99 | rc0 |= (map.eflg[map.map[y][x]] & 100 | (MAP_EFLG_VERT|MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP)); 101 | rc0 |= (map.eflg[map.map[y][x + 1]] & 102 | (MAP_EFLG_VERT|MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP)); 103 | rc0 |= (map.eflg[map.map[y][x + 2]] & 104 | (MAP_EFLG_VERT|MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP)); 105 | y++; 106 | } 107 | do { 108 | rc1 |= (map.eflg[map.map[y][x]] & 109 | (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_FGND| 110 | MAP_EFLG_LETHAL|MAP_EFLG_01)); 111 | rc1 |= (map.eflg[map.map[y][x + 1]] & 112 | (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_FGND| 113 | MAP_EFLG_LETHAL|MAP_EFLG_CLIMB|MAP_EFLG_01)); 114 | rc1 |= (map.eflg[map.map[y][x + 2]] & 115 | (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_FGND| 116 | MAP_EFLG_LETHAL|MAP_EFLG_01)); 117 | y++; 118 | } while (--i > 0); 119 | 120 | rc1 |= (map.eflg[map.map[y][x]] & 121 | (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP|MAP_EFLG_FGND| 122 | MAP_EFLG_LETHAL|MAP_EFLG_01)); 123 | rc1 |= (map.eflg[map.map[y][x + 1]]); 124 | rc1 |= (map.eflg[map.map[y][x + 2]] & 125 | (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP|MAP_EFLG_FGND| 126 | MAP_EFLG_LETHAL|MAP_EFLG_01)); 127 | } 128 | else { 129 | if (crawl) { 130 | rc0 |= (map.eflg[map.map[y][x]] & 131 | (MAP_EFLG_VERT|MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP)); 132 | rc0 |= (map.eflg[map.map[y][x + 1]] & 133 | (MAP_EFLG_VERT|MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP)); 134 | y++; 135 | } 136 | do { 137 | rc1 |= (map.eflg[map.map[y][x]] & 138 | (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_FGND| 139 | MAP_EFLG_LETHAL|MAP_EFLG_CLIMB|MAP_EFLG_01)); 140 | rc1 |= (map.eflg[map.map[y][x + 1]] & 141 | (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_FGND| 142 | MAP_EFLG_LETHAL|MAP_EFLG_CLIMB|MAP_EFLG_01)); 143 | y++; 144 | } while (--i > 0); 145 | 146 | rc1 |= (map.eflg[map.map[y][x]]); 147 | rc1 |= (map.eflg[map.map[y][x + 1]]); 148 | } 149 | 150 | /* 151 | * If not lethal yet, and there's an entity on slot zero, and (x,y) 152 | * boxtests this entity, then raise SOLID flag. This is how we make 153 | * sure that no entity can move over the entity that is on slot zero. 154 | * 155 | * Beware! When game_cheat2 is set, this means that a block can 156 | * move over rick without killing him -- but then rick is trapped 157 | * because the block is solid. 158 | */ 159 | if (!(rc1 & MAP_EFLG_LETHAL) 160 | && ent.ents[0].n 161 | && u_boxtest(ENT_ENTSNUM, 0)) { 162 | rc1 |= MAP_EFLG_SOLID; 163 | } 164 | 165 | /* When game_cheat2 is set, the environment can not be lethal. */ 166 | //#ifdef ENABLE_CHEATS 167 | if (game.cheat2) rc1 &= ~MAP_EFLG_LETHAL; 168 | //#endif 169 | 170 | return { rc0, rc1 }; 171 | } 172 | 173 | 174 | /* 175 | * Check if x,y is within e trigger box. 176 | * 177 | * ASM 126F 178 | * return: FALSE if not in box, TRUE if in box. 179 | */ 180 | export function 181 | u_trigbox(e, x, y) 182 | { 183 | let xmax, ymax; 184 | 185 | xmax = ent.ents[e].trig_x + (ent_entdata[ent.ents[e].n & 0x7F].trig_w << 3); 186 | ymax = ent.ents[e].trig_y + (ent_entdata[ent.ents[e].n & 0x7F].trig_h << 3); 187 | 188 | if (xmax > 0xFF) xmax = 0xFF; 189 | 190 | if (x <= ent.ents[e].trig_x || x > xmax || 191 | y <= ent.ents[e].trig_y || y > ymax) 192 | return false; 193 | else 194 | return true; 195 | } 196 | 197 | 198 | /* eof */ 199 | 200 | 201 | -------------------------------------------------------------------------------- /src/xrick.js: -------------------------------------------------------------------------------- 1 | /* 2 | * RickJS, a JavaScript port of XRick 3 | * 4 | * This source file is based on the folliwing files: 5 | * - xrick/src/xrick.c 6 | * 7 | * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved. 8 | * Copyright (C) 2012-2022 Chrilith (me@chrilith.com). All rights reserved. 9 | * 10 | * The use and distribution terms for this software are contained in the file 11 | * named README, which can be found in the root of this distribution. By 12 | * using this software in any fashion, you are agreeing to be bound by the 13 | * terms of this license. 14 | * 15 | * You must not remove this notice, or any other, from this software. 16 | */ 17 | 18 | import { sys_init } from "./system"; 19 | import { game_run } from "./game"; 20 | import { dat_init } from "./dat_loader"; 21 | 22 | import { sysarg } from "./sysarg"; 23 | 24 | /* 25 | * main 26 | */ 27 | export async function main(argc, argv) { 28 | console.log("Running xrick..."); 29 | sys_init(argc, argv); 30 | /* if (sysarg_args_data) { 31 | data_setpath(sysarg_args_data); 32 | } else { 33 | data_setpath("data.zip"); 34 | }*/ 35 | await dat_init(); 36 | game_run(); 37 | /* data_closepath(); 38 | sys_shutdown();*/ 39 | return 0; 40 | } 41 | 42 | /* eof */ 43 | -------------------------------------------------------------------------------- /xrick.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | RickJS, a JavaScript port of XRick using HTML5 10 | 11 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | --------------------------------------------------------------------------------