#include #include #include #include #include "video.h" #include "kbd.h" #include "mouse.h" #include "tiff.h" #include "tiles.h" #include "serial.h" #include "timer.h" #include "jorth.h" #include "egamap.h" #include "adlib.h" /*** T E X T ***/ char far *font = NULL; void text_init() { unsigned int fontSeg, fontOff; asm { push es push bp mov ah, 11h mov al, 30h mov bh, 3 int 10h mov ax, bp pop bp mov fontSeg, es mov fontOff, ax pop es } font = MK_FP(fontSeg, fontOff); } void text_draw_char(unsigned int vidOffset, unsigned char c) { unsigned int fontOffset = c << 3; int i; for (i = 0; i < 8; i ++) { VID[vidOffset] = font[fontOffset++]; vidOffset += PAGE_STRIDE; } } void text_draw(unsigned int vidOffset, unsigned char *s) { while (*s) { text_draw_char(vidOffset++, *s++); } } /*** S C R A T C H ***/ #define NUM_SPRITES 64 #define TILE_STRIDE 64 #define SPRITE_STRIDE 80 unsigned int far *tiles; unsigned int far *sprites; unsigned char map[10000]; void deallocate_gfx() { if (tiles) farfree(tiles); if (sprites) farfree(sprites); } void allocate_gfx() { unsigned long memleft = farcoreleft(); tiles = farmalloc(NUM_TILES * TILE_STRIDE * 2); sprites = farmalloc(NUM_SPRITES * SPRITE_STRIDE * 2); atexit(deallocate_gfx); 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; for (y = 0; y < 100; y ++) { for (x = 0; x < 100; x ++) { map[x + (y * 100)] = ((x + y + z) >> 2) % 4; } } } void readTiles(char *filename) { FILE *f; TifImageMeta_t meta; f = fopen(filename, "rb"); meta = tifLoadMeta(f); tifLoad(f, meta, tiles, NUM_TILES * 16, 16, 4); tifLoadEGA(f, meta, OFF_TILES, NUM_TILES * 16, 16); fclose(f); loadTiles(OFF_TILES, tiles); } void f_loadtiles() { readTiles(TOP().s); DROP(1); } void game_init() { FILE *f; TifImageMeta_t meta; allocate_gfx(); mouse_init(); setEGAMode(); atexit(vid_cleanup); kbd_init(); timer_init(TIMER_30HZ); text_init(); tile_init(); fillMap(); f = fopen("FOOTER.TIF", "rb"); meta = tifLoadMeta(f); tifLoadEGA(f, meta, 0, 48, 336); fclose(f); f = fopen("SPRITE.TIF", "rb"); meta = tifLoadMeta(f); tifLoad(f, meta, sprites, NUM_SPRITES * 16, 16, 5); fclose(f); f = fopen("PORTRAIT.TIF", "rb"); meta = tifLoadMeta(f); tifLoadEGA(f, meta, OFF_PORTRAITS, NUM_PORTRAITS * 32, 32); fclose(f); readTiles("TILES.TIF"); loadMap(map, 100, 100); scroll(0, 0); } void f_seremit() { ser_write_byte(TOP().i); if (TOP().i == '\n') { ser_write_byte('\r'); } DROP(1); } void f_keyWasPressed() { int k = TOP().i; 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); } 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); } void f_textc() { // ( col line c color -- ) setWriteMode(0); setPlaneColor(TOP().u); DROP(1); text_draw_char(ST2().u + (ST1().u * PAGE_STRIDE), TOP().i); DROP(3); } void f_text() { // ( col line s color -- ) setWriteMode(0); setPlaneColor(TOP().u); DROP(1); text_draw(ST2().u + (ST1().u * PAGE_STRIDE), TOP().s); DROP(3); } void f_map() { PUSHP(map); } void f_mapsize() { // ( -- w h ) PUSHI(screen.w); PUSHI(screen.h); } void f_mapsize_set() { // ( w h -- ) loadMap(map, ST1().i, TOP().i); DROP(2); } void f_mousepos() { // ( -- x y ) PUSHI(MOUSE.x); PUSHI(MOUSE.y); } void f_mousebuttons() { PUSHI(MOUSE.buttons); } void f_drawportrait() { setAllPlanes(); setWriteMode(1); blit32x32(OFF_PORTRAITS + (TOP().u << 7), (PAGE_STRIDE << 3) + 1); DROP(1); } void f_adlib() { adlib_write(TOP().u, ST1().u); DROP(2); } cell f_atexit; void f_cleanup() { f_execcp(f_atexit); } void f_glitch() { int count = TOP().u; int i, x, y; DROP(1); for (i = 0; i < count; i ++) { x = screen.scrollX + (rand() % 352) - 16; y = screen.scrollY + (rand() % 232) - 16; switch(rand()%2) { case 0: drawSprite(sprites + (rand() % (NUM_SPRITES * SPRITE_STRIDE)), x, y); break; case 1: drawSprite(mem + (rand() % MEM_SIZE), x, y); break; } } } /* JILES */ #define SCREEN_STRIDE 40 int getsprpixel(int x, int y, unsigned int far *spr) { int shift = (15 - x); int b = (spr[y + 0] & (1 << shift)) >> shift; int g = (spr[y + 16] & (1 << shift)) >> shift; int r = (spr[y + 32] & (1 << shift)) >> shift; int i = (spr[y + 48] & (1 << shift)) >> shift; int v = (spr[y + 64] & (1 << shift)) ? 0 : 1; return b | (g << 1) | (r << 2) | (i << 3) | (v << 4); } int resetEnabledCache = 0; #define setResetEnabledCached(m) \ if (resetEnabledCache != m) { \ resetEnabledCache = m; \ setResetEnabled(m); \ } void drawFatBox(int x, int y, int color) { int faty; int fill1 = color <= 0x0f ? 0xff : 0x55; int fill2 = fill1 == 0xff ? 0xff : 0xaa; unsigned int dst = SCREEN_STRIDE * y; if (color > 0x0f) { setResetEnabledCached(0); } else { setResetEnabledCached(0x0f); setResetMask(color); } for ( faty = 0; faty < 8; faty ++) { VID[dst + x + (SCREEN_STRIDE * faty)] = (faty % 2) ? fill1 : fill2; } } void f_drawfatsprite() { int isprite = TOP().i; unsigned int far *spr = &sprites[isprite * SPRITE_STRIDE]; int x, y; DROP(1); for ( y = 0; y < 16; y ++ ) { for ( x = 0; x < 16; x ++ ) { int color = getsprpixel(x, y, spr); drawFatBox(x, y << 3, color); } } } void f_drawfatbox() { drawFatBox(ST1().i, TOP().i, ST2().i); DROP(3); } void f_mousehide() { mouse_hide(); } void f_mouseshow() { setLogicalWidth(SCREEN_STRIDE >> 1); setResetEnabledCached(0); setWriteMode(0); setAllPlanes(); mouse_show(); } void f_putpixel() { int isprite = TOP().i; unsigned int far *spr = &sprites[isprite * SPRITE_STRIDE]; int x = ST2().i; int y = ST1().i; int color, shift, b, g, r, i, v; DROP(3); color = TOP().i; DROP(1); shift = (15 - x); b = (color & 0x01); g = (color & 0x02) >> 1; r = (color & 0x04) >> 2; i = (color & 0x08) >> 3; v = ((color & 0x10) >> 4) ^ 1; spr[y + 0] = (spr[y + 0] & ~(1 << shift)) | (b << shift); spr[y + 16] = (spr[y + 16] & ~(1 << shift)) | (g << shift); spr[y + 32] = (spr[y + 32] & ~(1 << shift)) | (r << shift); spr[y + 48] = (spr[y + 48] & ~(1 << shift)) | (i << shift); spr[y + 64] = (spr[y + 64] & ~(1 << shift)) | (v << shift); } void f_getpixel() { int isprite = TOP().i; unsigned int far *spr = &sprites[isprite * SPRITE_STRIDE]; int x = ST2().i; int y = ST1().i; DROP(2); TOP().i = getsprpixel(x, y, spr); } void f_spritecount() { PUSHI(NUM_SPRITES); } /* INIT */ void game_f_init(char *exe, char *bootjor) { 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); CDEF("scrollpos", f_scrollpos); CDEF("draw-screen", drawScreen); CDEF("split-screen", f_splitscreen); CDEF("ticks", f_ticks); CDEF("text", f_text); CDEF("textc", f_textc); CDEF("map", f_map); CDEF("mapsize", f_mapsize); CDEF("mapsize!", f_mapsize_set); CDEF("mousepos", f_mousepos); CDEF("mousebuttons", f_mousebuttons); CDEF("loadtiles", f_loadtiles); CDEF("glitch", f_glitch); CDEF("unfuck", tile_init); CDEF("mouseshow", f_mouseshow); CDEF("mousehide", f_mousehide); CDEF("drawfatsprite", f_drawfatsprite); CDEF("drawfatbox", f_drawfatbox); CDEF("putpixel", f_putpixel); CDEF("getpixel", f_getpixel); CDEF("spritecount", f_spritecount); f_loadjor(bootjor); f_atexit = f_lookupcp("atexit"); atexit(f_cleanup); } void f_poll() { static char line[128] = { 0 }; while (ser_getline(line)) { PUSHS(line); f_runstring("REPL send"); f_taskloop(); line[0] = '\0'; } } int DONE = 0; static void f_quit() { DONE = 1; } void do_repl(char *exe) { char buf[128]; f_init(exe); CDEF("quit", f_quit); CDEF("adlib", f_adlib); f_loadfile("repl.jor"); f_taskloop(); while (!DONE) { PUSHS(gets(buf)); f_runstring("REPL send"); f_taskloop(); } } int main(int argc, char *argv[]) { cell tick, draw; char *bootjor = "gameboot.jor"; if (argc > 1) { bootjor = argv[1]; } ser_init(SER_COM2, BAUD_19200, SER_8N1); game_init(); game_f_init(argv[0], bootjor); tick = f_lookupcp("tick"); draw = f_lookupcp("draw"); while (!keyIsDown(K_ESC)) { kbd_debounce(); f_poll(); f_taskloop(); f_execcp(tick); f_taskloop(); f_execcp(draw); } return 0; }