diff --git a/.gitignore b/.gitignore index 4c11873..978054b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,4 @@ *.swp *.log *.jim - +game.map diff --git a/egamap.h b/egamap.h index ca621c5..bc97221 100755 --- a/egamap.h +++ b/egamap.h @@ -1,6 +1,6 @@ #include "tiles.h" -#define NUM_TILES 128 +#define NUM_TILES 64 #define NUM_PORTRAITS 16 #define SIZE_FOOTER (PAGE_STRIDE * 48) diff --git a/egavga.bgi b/egavga.bgi new file mode 100755 index 0000000..1771336 Binary files /dev/null and b/egavga.bgi differ diff --git a/footer2.tif b/footer2.tif new file mode 100755 index 0000000..f3b0665 Binary files /dev/null and b/footer2.tif differ diff --git a/game.exe b/game.exe index 0eae2db..c44a8e3 100755 Binary files a/game.exe and b/game.exe differ diff --git a/game.jor b/game.jor index 07826d2..aa1bcd8 100755 --- a/game.jor +++ b/game.jor @@ -112,9 +112,6 @@ player :tick ;entity ( S T U F F ) -: hello-world - player.state DRIVING fnot! ; - : reset-level :| player yield 0 |; ' entities redefine :| drop drop 0 |; ' player-touch redefine ; @@ -122,9 +119,6 @@ player :tick : mode-move entities each EVTICK entity>do more tick-mapedit - ^SPACE key-pressed if - ' hello-world JOB send - then tick-debounce q-level @ dup if 0 q-level ! @@ -141,13 +135,17 @@ player :tick r@ entity.dir @ r< entity>sprite draw-sprite ; +var showmouse +1 showmouse ! : full-draw player entity.x @ 152 - player entity.y @ 92 - scroll entities each draw-entity more - mouseworldpos 4 draw-sprite + showmouse @ if + mouseworldpos 4 draw-sprite + then draw-screen draw-footer ; diff --git a/game.prj b/game.prj index f55f6b0..1983900 100755 Binary files a/game.prj and b/game.prj differ diff --git a/gameboot.jor b/gameboot.jor index 8fd38bc..4fa810f 100755 --- a/gameboot.jor +++ b/gameboot.jor @@ -1,7 +1,11 @@ : blah ' seremit task-emit ! ; blah -: start-repl activate blah +s" game.log" open seekend fdeactivate const LOGFILE +: emit-log fdeactivate LOGFILE factivate fputc fdeactivate drop factivate ; +: atexit LOGFILE factivate close ; + +: start-repl activate blah ' emit-log task-echo ! s" .:: J O R T H ( jean forth) ::." type cr begin receive loadstring s" ok" type cr again ; task const REPL @@ -19,6 +23,7 @@ s" footer.jor" loadfile s" map.jor" loadfile s" game.jor" loadfile s" state.jor" loadfile +s" slide.jor" loadfile ; execute intern pete.jor @@ -30,4 +35,4 @@ intern trail1.jor :noname loadfile ; checkpoint _loadlevel ' _loadlevel ' loadlevel redefine -pete.jor loadlevel +( pete.jor loadlevel ) diff --git a/goth.chr b/goth.chr new file mode 100755 index 0000000..75f9a7e Binary files /dev/null and b/goth.chr differ diff --git a/jopl.exe b/jopl.exe index 925e76d..735eb43 100755 Binary files a/jopl.exe and b/jopl.exe differ diff --git a/jopl.jor b/jopl.jor index 1c2c959..9bef52e 100755 --- a/jopl.jor +++ b/jopl.jor @@ -228,6 +228,7 @@ var t2 : ontick startt2 player status trackstatus ; : files findfile begin dup while yield findnext repeat ; +: .files files each type s" " type more ; : keynote [ inline| 44 b, 31 b, 45 b, 32 b, 46 b, 47 b, 34 b, 48 b, 35 b, 49 b, 36 b, 50 b, diff --git a/jopl.prj b/jopl.prj index bca732d..2dabce4 100755 Binary files a/jopl.prj and b/jopl.prj differ diff --git a/jorth.c b/jorth.c index cd26a41..60a425d 100755 --- a/jorth.c +++ b/jorth.c @@ -342,6 +342,10 @@ void f_fputc() { DROP(1); } +void f_gets() { + gets(TOP().s); +} + void f_fput() { if (ACTIVE_FILE) { fwrite(&TOP().u, 2, 1, ACTIVE_FILE); @@ -747,6 +751,12 @@ void f_tell() { PUSHU(ftell(ACTIVE_FILE)); } +void f_exists() { + struct stat statbuf; + int rc = stat(TOP().s, &statbuf); + TOP().i = rc == 0; +} + void f_swapinput() { cell *key = RUNNING + TASK_USER_KEY; cell *keysrc = RUNNING + TASK_USER_KEYSRC; @@ -1111,6 +1121,7 @@ void f_init(char *exe) { CDEF("swap-input", f_swapinput); CDEF("putc", f_putc); CDEF("fputc", f_fputc); + CDEF("gets", f_gets); CDEF("number", f_number); CDEF("LIT_", f_lit_); CDEF("GOTO_", f_goto_); @@ -1127,6 +1138,7 @@ void f_init(char *exe) { CDEF("open", f_open); CDEF("overwrite", f_overwrite); CDEF("close", f_close); + CDEF("exists", f_exists); CDEF("factivate", f_activate); CDEF("fdeactivate", f_deactivate); CDEF("seek", f_seek); diff --git a/litt.chr b/litt.chr new file mode 100755 index 0000000..08c3067 Binary files /dev/null and b/litt.chr differ diff --git a/sans.chr b/sans.chr new file mode 100755 index 0000000..c38bc69 Binary files /dev/null and b/sans.chr differ diff --git a/serial.c b/serial.c index d40ce44..4346321 100755 --- a/serial.c +++ b/serial.c @@ -85,3 +85,25 @@ void ser_write(char *str) { ser_write_byte(*str); } } + +int ser_getline(char *line) { + int i = strlen(line); + int value; + for (value = ser_poll(); value != SER_NODATA; value = ser_poll()) { + if (value == '\b' || value == 127) { + i --; + } else { + line[i] = value; + i ++; + } + line[i] = '\0'; + ser_write_byte(value); // echo + + if (value == '\r') { + line[i - 1] = '\n'; + ser_write_byte('\n'); + return 1; + } + } + return 0; +} \ No newline at end of file diff --git a/serial.h b/serial.h index 361cb38..c293072 100755 --- a/serial.h +++ b/serial.h @@ -19,10 +19,11 @@ #define BAUD_57600 0x0002 #define BAUD_115200 0x0001 -#define SER_READ_BUFFER_SIZE 0x200 +#define SER_READ_BUFFER_SIZE 64 #define SER_NODATA -1 void ser_init(int port, int baudrate, int protocol); int ser_poll(); void ser_write_byte(char byte); void ser_write(char *str); +int ser_getline(char *line); diff --git a/slide.c b/slide.c new file mode 100755 index 0000000..8516ff2 --- /dev/null +++ b/slide.c @@ -0,0 +1,82 @@ +#include +#include "jorth.h" + +static int bgi_on = 0; +void bgi_shutdown() { + if (bgi_on) { + closegraph(); + bgi_on = 0; + } +} + +void bgi_init() { + int driver = VGA; + int mode = VGAHI; + if (!bgi_on) { + initgraph(&driver, &mode, NULL); + bgi_on = 1; + } +} + +void s_outtext() { + outtext(TOP().s); + DROP(1); +} + +void s_justify() { + settextjustify(TOP().i, TOP_TEXT); + DROP(1); +} + +void s_font() { + struct textsettingstype settings; + gettextsettings(&settings); + settextstyle(ST1().i, settings.direction, TOP().i); + DROP(2); +} + +void s_direction() { + struct textsettingstype settings; + gettextsettings(&settings); + settextstyle(settings.font, TOP().i, settings.charsize); + DROP(1); +} + +void s_moveto() { + moveto(ST1().i, TOP().i); + DROP(2); +} + +void s_pos() { + PUSHI(getx()); + PUSHI(gety()); +} + +void s_setcolor() { + setcolor(TOP().i); + DROP(1); +} + +void s_setbgcolor() { + setbkcolor(TOP().i); + DROP(1); +} + +void s_clear() { + cleardevice(); +} + +void slide_init() { + CDEF("bgi-on", bgi_init); + CDEF("bgi-off", bgi_shutdown); + CDEF("outtext", s_outtext); + CDEF("justify", s_justify); + CDEF("font", s_font); + CDEF("direction", s_direction); + CDEF("moveto", s_moveto); + CDEF("pos", s_pos); + CDEF("color!", s_setcolor); + CDEF("bg!", s_setbgcolor); + CDEF("wipe", s_clear); + atexit(bgi_shutdown); +} diff --git a/slide.exe b/slide.exe new file mode 100755 index 0000000..6cca455 Binary files /dev/null and b/slide.exe differ diff --git a/slide.h b/slide.h new file mode 100755 index 0000000..a706ec9 --- /dev/null +++ b/slide.h @@ -0,0 +1 @@ +void slide_init(); \ No newline at end of file diff --git a/slide.jor b/slide.jor new file mode 100755 index 0000000..51a59e5 --- /dev/null +++ b/slide.jor @@ -0,0 +1,181 @@ +( K E Y B O A R D ) +57 const ^SPACE +75 const ^LEFT +77 const ^RIGHT +51 const ^< +52 const ^> +31 const ^S +59 const ^F1 + +0 const BLACK +1 const BLUE +2 const GREEN +3 const CYAN +4 const RED +5 const MAGENTA +6 const BROWN +7 const LGRAY +8 const DGRAY +9 const LBLUE +10 const LGREEN +11 const LCYAN +12 const PINK +13 const LMAGENTA +14 const YELLOW +15 const WHITE + +: rungame + 0 player.state DRIVING f! + 1 showmouse ! + [ MODE-MOVE @ lit ] dup MODE-MOVE ! ' tick redefine + ' full-draw ' draw redefine + 12 11 tile>world player entity.pos! + bgi-off 320x200 loadportraits + s" pete.jor" loadfile + begin suspend again ; + +( S L I D E ) +var skip +var autoslide +: pause + skip @ not if + begin + suspend 0 + ^< key-pressed if drop 1 1 skip ! -1 autoslide ! then + ^> key-pressed if drop 1 1 skip ! 1 autoslide ! then + ^S key-pressed if drop 1 1 skip ! then + ^RIGHT key-pressed ^SPACE key-pressed or if drop 1 then + ^F1 key-pressed if rungame then + until + then ; + +defer write +: y pos swap drop ; +: nexty ( dy -- y ) y + ; +: writeline ( s x dy ) nexty world player entity.pos! + s" pete.jor" loadfile ; +:noname :| player yield 0 |; ' entities redefine + 0 player.state DRIVING f! + 1 showmouse ! MODE-MOVE @ ' tick redefine + 12 11 tile>world player entity.pos! + loadportraits ; +:noname s" hide-footer" REPL send ; +:noname s" show-footer" REPL send ; +:noname :| player yield 0 |; ' entities redefine + 1 player.state DRIVING f! E player entity.dir ! ; +:noname :| 0 |; ' entities redefine 0 showmouse ! ; +array demostates , , , , , , , +var demostate + +: enterdemostate + demostate @ cells demostates + @ execute ; + +: tick-nextslide + ^SPACE key-pressed if 1 demostate +! enterdemostate then ; + +: demotick + tick-nextslide + 0 ^LEFT key-down if 3 - then + ^RIGHT key-down if 3 + then + 0 ^UP key-down if 3 - then + ^DOWN key-down if 3 + then + player entity.y +! + player entity.x +! + tick-mapedit + tick-debounce ; + +: autoadvance autoslide @ not if 1 autoslide ! then ; +: demo ( endstate startstate -- ) + bgi-off 320x200 + ' full-draw ' draw redefine + ' demotick ' tick redefine + demostate ! enterdemostate + begin suspend dup demostate @ <= until drop + ' noop ' draw redefine + ' noop ' tick redefine + bgi-on autoadvance ; + +var demorepldone +: quit 1 demorepldone ! ; +: start-demorepl activate ' putc task-emit ! + s" .:: J O R T H ( jean forth) ::." type cr + begin receive loadstring s" ok" type cr again ; +task const DEMOREPL +array replbuf 256 allot + +: demorepl + bgi-off key-end 0 demorepldone ! + DEMOREPL start-demorepl suspend + begin replbuf gets DEMOREPL send suspend + demorepldone @ until + bgi-on key-start autoadvance ; + +array filenamebuf 13 allot +var filenameindex +: store-fn-char filenamebuf filenameindex @ + b! ; +: filename-emit + dup [ key lit ] != if + store-fn-char + 1 filenameindex +! + 0 store-fn-char + else drop then ; + +: slidefilename ( i -- s ) + task-emit @ + ' filename-emit task-emit ! + 0 filenameindex ! + s" slide" type + swap . + s" .jor" type + task-emit ! + filenamebuf ; + +var slidecount +var slideindex + +: skipto ( i -- ) + slideindex @ - autoslide ! 1 skip ! ; + +: fixindex + slideindex @ 0 < if slidecount @ 1 - slideindex ! else + slideindex @ slidecount @ >= if 0 slideindex ! then then ; + +: show ( i -- ) 0 skip ! 0 autoslide ! slidefilename loadjor ; +: nextslide + autoslide @ if + autoslide @ slideindex +! + else + begin + suspend + ^LEFT key-pressed ^< key-pressed or + if -1 else + ^RIGHT key-pressed ^SPACE key-pressed or ^> key-pressed or + if 1 else 0 then then + dup if dup slideindex +! then + until + then fixindex ; + +: slideshow activate blah + bgi-on ' noop ' draw redefine ' noop ' tick redefine + begin slideindex @ show nextslide again ; +task const SLIDESHOW +SLIDESHOW slideshow + +:noname + 0 begin dup slidefilename exists while 1 + repeat slidecount ! + :| tick-nextslide [ MODE-MOVE @ , ] |; MODE-MOVE ! +; ' onload redefine diff --git a/slide.prj b/slide.prj new file mode 100755 index 0000000..8a21db2 Binary files /dev/null and b/slide.prj differ diff --git a/slide0.jor b/slide0.jor new file mode 100755 index 0000000..2441a9d --- /dev/null +++ b/slide0.jor @@ -0,0 +1,8 @@ +MAGENTA bg! +goof +s" What A 30-Year" write +s" Old PC Can Teach" write +s" Us About Graphic" write +s" Design" write pause +BLUE bg! bullet +s" (just kidding)" write diff --git a/slide1.jor b/slide1.jor new file mode 100755 index 0000000..7d445c1 --- /dev/null +++ b/slide1.jor @@ -0,0 +1,4 @@ +header 320 180 moveto +s" Building Your Own Tools" write pause +bullet +s" Or, Be Moore Like Chuck" write diff --git a/slide10.jor b/slide10.jor new file mode 100755 index 0000000..ccda40d --- /dev/null +++ b/slide10.jor @@ -0,0 +1,16 @@ +header +s" Things Jorth is missing" write pause +bullet +s" * Garbage collection" write pause +s" * Dynamic memory allocation" write pause +s" * Garbage" write pause +s" * Memory safety" write pause +s" * Error reporting" write pause +s" * Static types" write pause +s" * Dynamic types" write pause +s" * Objects" write pause +s" * Polymorphic methods" write pause +s" * Closures" write pause +s" * Flow control (in the interpreter)" write pause +s" * Local variables" write pause +s" * Syntax" write diff --git a/slide11.jor b/slide11.jor new file mode 100755 index 0000000..2975928 --- /dev/null +++ b/slide11.jor @@ -0,0 +1,10 @@ +header +s" Things Jorth has" write +bullet +s" * An interactive embedded REPL" write pause +s" * Lightweight co-operative multitasking" write pause +s" * A C FFI" write pause +s" * An extensible compiler, defined in itself" write pause +s" * The ability to fit comfortably in 16kb of RAM" write pause +s" * An entire codebase I completely understand" write +s" and am willing to change to fit my problem" write diff --git a/slide12.jor b/slide12.jor new file mode 100755 index 0000000..38038b4 --- /dev/null +++ b/slide12.jor @@ -0,0 +1,15 @@ +header +s" Jorth Crash Course" write +s" Syntax & Semantics" write +bullet +s" * Read text until a space is encountered" write pause +s" * Look up word in dictionary" write pause +s" * If a definition is found: Execute it" write pause +s" * Otherwise: Parse it as a number" write pause +s" * Otherwise: Give up" write pause +s" * Postfix / Reverse Polish Notation" write +s" parameters and return values live on The Stack" write pause +s" * D E M O !" write pause +demorepl + + diff --git a/slide13.jor b/slide13.jor new file mode 100755 index 0000000..fb38001 --- /dev/null +++ b/slide13.jor @@ -0,0 +1,9 @@ +header +s" Jorth Crash Course" write +s" The Jorth Virtual Machine" write +bullet +s" while (IP.p) {" write +s" W = *IP.p;" write +s" IP.p++;" write +s" W.p->f();" write +s" }" write diff --git a/slide14.jor b/slide14.jor new file mode 100755 index 0000000..5abd9b7 --- /dev/null +++ b/slide14.jor @@ -0,0 +1,11 @@ +header +s" Jorth Crash Course" write +s" Calling Conventions" write +bullet +s" void f_docolon() {" write +s" RPUSH(IP);" write +s" IP.p = W.p + 1;" write +s" }" write pause +s" void f_ret() { " write +s" IP = *RPOP();" write +s" }" write diff --git a/slide15.jor b/slide15.jor new file mode 100755 index 0000000..d92987e --- /dev/null +++ b/slide15.jor @@ -0,0 +1,14 @@ +header +s" Jorth Crash Course" write +s" Writing Jorth In Itself" write +bullet +s" : begin here ; immediate" write +s" : until ' BZ_ , , ; immediate" write pause +s" " write +s" : if ' BZ_ , here 0 , ; immediate" write +s" : then here swap ! ; immediate" write pause +s" " write +s" : ( begin key ')' = until ; immediate" write + + + diff --git a/slide16.jor b/slide16.jor new file mode 100755 index 0000000..c9aface --- /dev/null +++ b/slide16.jor @@ -0,0 +1,8 @@ +header +s" What Good Was It?" write +bullet +s" * Jorth soon spread to every part of the project" write pause +s" * C for the hardware, Jorth for everything else" write pause +s" * All game & drawing logic" write pause +s" * Map editing" write pause +6 4 demo \ No newline at end of file diff --git a/slide17.jor b/slide17.jor new file mode 100755 index 0000000..e1738c9 --- /dev/null +++ b/slide17.jor @@ -0,0 +1,9 @@ +header +s" Entirely Intuitive Results" write +bullet +s" * Forth does not scale up" write pause +s" * Arranging postfix expressions without local" write +s" variables is hard" write pause +s" * It's too easy to fill 64kb of memory" write pause +s" * This would have been impossible without" write +s" the internet" write diff --git a/slide18.jor b/slide18.jor new file mode 100755 index 0000000..eeedb12 --- /dev/null +++ b/slide18.jor @@ -0,0 +1,16 @@ +header +s" Counterintuitive Results" write +bullet +s" * Complicated Forth code is AWFUL..." write pause +s" ... which is a powerful force for simplicity" write pause +s" * Virtually ALL state is global..." write pause +s" ... which makes it all visible when debugging" write pause +s" ... and which lets code stay small and focussed" write pause +s" * Hard to tell what a word might do..." write pause +s" ... but this makes huge implementation" write +s" changes possible!" write pause +s" * The most flexible abstraction may be the tiniest" write pause +s" * It's easier to write my own!" write pause +s" * Map editor" write pause +s" * Music livecoding REPL (<300 LOC!)" write pause +s" * This presentation software (<200 LOC!)" write diff --git a/slide19.jor b/slide19.jor new file mode 100755 index 0000000..46f1c0b --- /dev/null +++ b/slide19.jor @@ -0,0 +1,4 @@ +header +s" I should shut up now" write pause +goof CYAN bg! MAGENTA color! +s" Questions?" write \ No newline at end of file diff --git a/slide2.jor b/slide2.jor new file mode 100755 index 0000000..f4be0f3 --- /dev/null +++ b/slide2.jor @@ -0,0 +1,6 @@ +header +s" Background" write +bullet +s" I decided to write a game" write pause +s" for a 30-year-old computer" write pause +s" on a 30-year-old computer" write diff --git a/slide3.jor b/slide3.jor new file mode 100755 index 0000000..4ae3119 --- /dev/null +++ b/slide3.jor @@ -0,0 +1,6 @@ +header +s" WHY?!" write pause +bullet +s" * I fell in love with MS-DOS" write pause +s" * I wanted to see if I could" write pause +s" * Learning is fun" write diff --git a/slide4.jor b/slide4.jor new file mode 100755 index 0000000..17971b0 --- /dev/null +++ b/slide4.jor @@ -0,0 +1,30 @@ +header +s" What were my restrictions?" write +bullet +s" * Turbo C++ 1.0 (C & assembler)" write pause +s" * 16-bit real-mode x86" write pause +pos s" * 640kb of RAM" write pause +moveto s" -----" write +pos s" * ~550-600kb of RAM" write pause +moveto s" ----------" write + s" * 64kb of code, 64kb of data," write + s" 256kb of video memory" write pause + s" * E" outtext +2 color! s" G" outtext +3 color! s" A " outtext +4 color! s" G" outtext +5 color! s" r" outtext +6 color! s" a" outtext +7 color! s" p" outtext +8 color! s" h" outtext +9 color! s" i" outtext +10 color! s" c" outtext +11 color! s" s" outtext +12 color! s" !" outtext +13 color! s" !" outtext +14 color! s" !" write +LCYAN color! +s" * 320x200 pixel resolution, 16 colours" write pause +s" * AdLib sound" write +s" * FM synthesis - no digital sampling" write pause +s" * All work done ON THE 286" write diff --git a/slide5.jor b/slide5.jor new file mode 100755 index 0000000..e660fef --- /dev/null +++ b/slide5.jor @@ -0,0 +1,11 @@ +header +s" How would I learn all this?" write +bullet +pos s" * StackOverflow" write pause +moveto s" -----------" write pause +s" * Graphics Programming Black Book" write +s" by Michael Abrash" write pause +s" * Teach Yourself Game Programming in 21 Days" write +s" by Andre LaMothe" write pause +s" * Commander Keen Dreams source code" write pause +s" * Google... sometimes helped" write diff --git a/slide6.jor b/slide6.jor new file mode 100755 index 0000000..035f53f --- /dev/null +++ b/slide6.jor @@ -0,0 +1,8 @@ +header +s" First Steps" write +bullet +s" * Could I write a tile engine?" write pause +s" * Stretch goal: Could I make it scroll smoothly?" write pause +s" * And obviously I've got to draw stuff on top..." write pause +s" * Ooh, what about a stationary HUD?" write pause +3 0 demo diff --git a/slide7.jor b/slide7.jor new file mode 100755 index 0000000..fc34a66 --- /dev/null +++ b/slide7.jor @@ -0,0 +1,7 @@ +BLUE bg! +header +s" Problems: One Month In" write +bullet +s" * Game logic was messy" write pause +s" * Debugging is hard!" write pause +s" * How to edit maps?" write diff --git a/slide8.jor b/slide8.jor new file mode 100755 index 0000000..942eeb4 --- /dev/null +++ b/slide8.jor @@ -0,0 +1,20 @@ +header +s" I know, I'll just..." write pause +s" WRITE MY OWN" write +s" SCRIPTING LANGUAGE" write pause +bullet +s" What could POSSIBLY go wrong??" write pause + +header +s" @SpindleyQ" write pause +bullet +s" ohhh noooo I am definitely going to" write +s" write a 16-bit x86 Forth as a scripting" write +s" language for my game, this is happeniiiiing" write pause + +header +s" @mogwai_poet" write pause +bullet +s" @SpindleyQ Have you used forth before?" write +s" It's like programming assembly" write +s" on a CPU designed by an alien." write diff --git a/slide9.jor b/slide9.jor new file mode 100755 index 0000000..1b0ebb1 --- /dev/null +++ b/slide9.jor @@ -0,0 +1,8 @@ +header +s" FORTH" write +bullet +s" * Invented by Chuck Moore around 1970" write pause +s" * Still used in embedded systems & firmware" write pause +s" * The tiniest possible useful language" write pause +s" * 'If you've seen one Forth, you've seen one forth'" write pause +s" * I called mine Jorth ( jean forth)" write diff --git a/slidenot.es b/slidenot.es new file mode 100755 index 0000000..50a292d --- /dev/null +++ b/slidenot.es @@ -0,0 +1,19 @@ +: slideNotes + bullet + s" * The tiniest abstraction may be the most flexible" write + s" (if you're willing to trade off 'safety')" write + +* Forth is really, really good for one person who understands everything +* It is not necessarily great for complex problems + (Change the problem!) +* It is not necessarily great for co-operation + (write-only language) +* It's kind of an anti-social language + (not least because you want to talk about it at length once you learn it!) + +Challenges: +* I spent a couple of hours figuring out how to free up enough + memory in the data segment to hold my game engine, Jorth data, + graphics data, and the slide fonts, all at the same time +* Then I wrote some more slides and ran out of RAM to store all + the text, so I diff --git a/testbed.c b/testbed.c index 83d2f94..ee32f03 100755 --- a/testbed.c +++ b/testbed.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "video.h" #include "kbd.h" @@ -12,6 +13,7 @@ #include "jorth.h" #include "egamap.h" #include "adlib.h" +#include "slide.h" /*** T E X T ***/ char far *font = NULL; @@ -54,11 +56,23 @@ void text_draw(unsigned int vidOffset, unsigned char *s) { #define NUM_SPRITES 64 #define TILE_STRIDE 64 #define SPRITE_STRIDE 80 -unsigned int tiles[NUM_TILES * TILE_STRIDE]; -unsigned int sprites[NUM_SPRITES * SPRITE_STRIDE]; - +unsigned int far *tiles; +unsigned int far *sprites; unsigned char map[10000]; +void allocate_gfx() { + unsigned long memleft = farcoreleft(); + tiles = farmalloc(NUM_TILES * TILE_STRIDE); + sprites = farmalloc(NUM_SPRITES * SPRITE_STRIDE); + if (!tiles || !sprites) { + printf("%lu bytes free - need %lu\n", memleft, + (unsigned long) + ((NUM_TILES * TILE_STRIDE) + + (NUM_SPRITES * SPRITE_STRIDE))); + exit(1); + } +} + void fillMap() { unsigned int x, y, z; z = 0; @@ -74,6 +88,8 @@ void game_init() { FILE *f; TifImageMeta_t meta; + allocate_gfx(); + mouse_init(); setEGAMode(); @@ -125,13 +141,16 @@ void f_keyWasPressed() { TOP().i = keyWasPressed(k); consumeKey(k); } + void f_keyIsDown() { TOP().i = keyIsDown(TOP().i); } + void f_drawSprite() { // ( x y sprite -- ) drawSprite(&sprites[TOP().i * SPRITE_STRIDE], ST2().i, ST1().i); DROP(3); } + void f_scroll() { // ( x y -- ) scroll(ST1().i, TOP().i); DROP(2); @@ -141,9 +160,11 @@ void f_scrollpos() { // ( -- x y ) PUSHI(screen.scrollX); PUSHI(screen.scrollY); } + void f_ticks() { PUSHU(timer_counter); } + void f_splitscreen() { setSplitScreen(399 - (TOP().i << 1)); DROP(1); @@ -199,11 +220,51 @@ void f_adlib() { DROP(2); } +cell f_atexit; +void f_cleanup() { + f_execcp(f_atexit); +} + +void f_320x200() { + FILE *f; + TifImageMeta_t meta; + + setEGAMode(); + tile_init(); + + f = fopen("FOOTER2.TIF", "rb"); + meta = tifLoadMeta(f); + tifLoadEGA(f, meta, 0, 48, 336); + fclose(f); + + f = fopen("TILES.TIF", "rb"); + meta = tifLoadMeta(f); + tifLoadEGA(f, meta, OFF_TILES, NUM_TILES * 16, 16); + fclose(f); +} + +void f_loadportraits() { + FILE *f; + TifImageMeta_t meta; + + f = fopen("FOOTER.TIF", "rb"); + meta = tifLoadMeta(f); + tifLoadEGA(f, meta, 0, 48, 336); + fclose(f); + + f = fopen("PORTRAIT.TIF", "rb"); + meta = tifLoadMeta(f); + tifLoadEGA(f, meta, OFF_PORTRAITS, NUM_PORTRAITS * 32, 32); + fclose(f); + +} void game_f_init(char *exe) { f_init(exe); CDEF("seremit", f_seremit); CDEF("key-pressed", f_keyWasPressed); CDEF("key-down", f_keyIsDown); + CDEF("key-start", kbd_init); + CDEF("key-end", kbd_cleanup); CDEF("draw-sprite", f_drawSprite); CDEF("draw-portrait", f_drawportrait); CDEF("scroll", f_scroll); @@ -219,33 +280,25 @@ void game_f_init(char *exe) { CDEF("mousepos", f_mousepos); CDEF("mousebuttons", f_mousebuttons); CDEF("unfuck", tile_init); + CDEF("320x200", f_320x200); + CDEF("loadportraits", f_loadportraits); + + slide_init(); f_loadjor("gameboot.jor"); + + f_atexit = f_lookupcp("atexit"); + atexit(f_cleanup); + } void f_poll() { static char line[128] = { 0 }; - int i = strlen(line); - int value; - for (value = ser_poll(); value != SER_NODATA; value = ser_poll()) { - if (value == '\b' || value == 127) { - i --; - } else { - line[i] = value; - i ++; - } - line[i] = '\0'; - ser_write_byte(value); // echo - - if (value == '\r') { - line[i - 1] = '\n'; - ser_write_byte('\n'); - PUSHS(line); - f_runstring("REPL send"); - f_taskloop(); - i = 0; - line[i] = '\0'; - } + while (ser_getline(line)) { + PUSHS(line); + f_runstring("REPL send"); + f_taskloop(); + line[0] = '\0'; } } diff --git a/tiff.c b/tiff.c index cdb2a2f..f0d088e 100755 --- a/tiff.c +++ b/tiff.c @@ -117,7 +117,7 @@ int tifLoadEGA(FILE *f, TifImageMeta_t meta, unsigned int vidOffset, int maxY, u return y; } -int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int yRepeat, int planes) { +int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int far *planeBuf, int maxY, int yRepeat, int planes) { int istrip; int irow; int ipixelpair; @@ -125,11 +125,11 @@ int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int unsigned long offset; unsigned char rowData[MAX_WIDTH >> 1]; unsigned int planeStride = (meta.width >> 4) * yRepeat; - unsigned int *bp = planeBuf; - unsigned int *gp = bp + planeStride; - unsigned int *rp = gp + planeStride; - unsigned int *ip = rp + planeStride; - unsigned int *mp = ip + planeStride; + unsigned int far *bp = planeBuf; + unsigned int far *gp = bp + planeStride; + unsigned int far *rp = gp + planeStride; + unsigned int far *ip = rp + planeStride; + unsigned int far *mp = ip + planeStride; unsigned int bv, gv, rv, iv; if (meta.width > MAX_WIDTH || (meta.width % 16) != 0 || planes < 4 || planes > 5) { diff --git a/tiff.h b/tiff.h index 3af7942..2ee2fcd 100755 --- a/tiff.h +++ b/tiff.h @@ -14,4 +14,4 @@ typedef struct { TifImageMeta_t tifLoadMeta(FILE *f); int tifLoadEGA(FILE *f, TifImageMeta_t meta, unsigned int vidOffset, int maxY, unsigned int w); -int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int *planeBuf, int maxY, int yRepeat, int planes); +int tifLoad(FILE *f, TifImageMeta_t meta, unsigned int far *planeBuf, int maxY, int yRepeat, int planes); diff --git a/tiles.c b/tiles.c index 44db0b4..9e5cc77 100755 --- a/tiles.c +++ b/tiles.c @@ -52,7 +52,7 @@ void blit32x32(unsigned int offsetFrom, unsigned int offsetTo) { TiledScreen_t screen = { 0, 0, 0, 0, { OFF_PAGE1, OFF_PAGE2 }, 0, 0, NULL, NULL, 0, 0, 0, 0, 0 }; -void loadTiles(unsigned int tilesOffset, unsigned int *memTiles) { +void loadTiles(unsigned int tilesOffset, unsigned int far *memTiles) { screen.tilesOffset = tilesOffset; screen.memTiles = memTiles; } @@ -66,6 +66,7 @@ void loadMap(unsigned char *map, unsigned int w, unsigned int h) { int prepareBuffer(int pageX, int pageY) { unsigned char *dirty = &screen.dirty[screen.currentPage][pageX + (pageY * PAGE_TILES_W)]; + int i; if (!isBufIndex(*dirty)) { unsigned int startX = screen.scrollX >> 4; unsigned int startY = screen.scrollY >> 4; @@ -73,15 +74,18 @@ int prepareBuffer(int pageX, int pageY) { unsigned char ibuffer = screen.nextBuffer; screen.nextBuffer = nextBufferIndex(ibuffer); *dirty = ibuffer; - memcpy(screen.buffer[ibuffer], &screen.memTiles[tile * BUF_WSIZE], BUF_WSIZE << 1); + for (i = 0; i < BUF_WSIZE; i ++) { + screen.buffer[ibuffer][i] = (&screen.memTiles[tile * BUF_WSIZE])[i]; + } screen.bufferOffset[ibuffer] = screen.pageOffset[screen.currentPage] + (pageX << 1) + (pageY * PAGE_STRIDE * 16); } return *dirty; } -void drawSpriteToBuf(unsigned int *sprite, int pageX, int pageY, int shift, int yStart) { - unsigned int *buf, *mask; +void drawSpriteToBuf(unsigned int far *sprite, int pageX, int pageY, int shift, int yStart) { + unsigned int *buf; + unsigned int far *mask; unsigned int maskval; int y, h, plane; if (pageX < 0 || pageY < 0 || @@ -122,7 +126,7 @@ void drawSpriteToBuf(unsigned int *sprite, int pageX, int pageY, int shift, int } } -void drawSprite(unsigned int *sprite, int x, int y) { +void drawSprite(unsigned int far *sprite, int x, int y) { int pageX = (int)(x - (screen.scrollX & 0xfff0)) >> 4; int pageY = (int)(y - (screen.scrollY & 0xfff0)) >> 4; int pageOffsetX = x & 0x0f; diff --git a/tiles.h b/tiles.h index 1401e45..d6064ee 100755 --- a/tiles.h +++ b/tiles.h @@ -4,9 +4,9 @@ void tile_init(); -void loadTiles(unsigned int tilesOffset, unsigned int *memTiles); +void loadTiles(unsigned int tilesOffset, unsigned int far *memTiles); void loadMap(unsigned char *map, unsigned int w, unsigned int h); -void drawSprite(unsigned int *sprite, int x, int y); +void drawSprite(unsigned int far *sprite, int x, int y); void scroll(int newX, int newY); void drawScreen(); @@ -17,7 +17,7 @@ void blit32x32(unsigned int offsetFrom, unsigned int offsetTo); #define PAGE_TILES_COUNT (PAGE_TILES_H * PAGE_TILES_W) #define PAGE_STRIDE (PAGE_TILES_W << 1) -#define NUM_BUFFERS 32 +#define NUM_BUFFERS 20 #define BUF_WSTRIDE 16 #define BUF_WSIZE (BUF_WSTRIDE * 4) @@ -29,7 +29,7 @@ typedef struct { unsigned int pageOffset[2]; unsigned char dirty[2][PAGE_TILES_COUNT]; unsigned int tilesOffset; - unsigned int *memTiles; + unsigned int far *memTiles; unsigned char *map; unsigned int buffer[NUM_BUFFERS][BUF_WSIZE]; unsigned int bufferOffset[NUM_BUFFERS]; diff --git a/trip.chr b/trip.chr new file mode 100755 index 0000000..d1f79f8 Binary files /dev/null and b/trip.chr differ