239 lines
4.8 KiB
C
Executable file
239 lines
4.8 KiB
C
Executable file
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <dos.h>
|
|
|
|
#include "video.h"
|
|
#include "kbd.h"
|
|
#include "mouse.h"
|
|
#include "tiff.h"
|
|
#include "tiles.h"
|
|
#include "serial.h"
|
|
#include "timer.h"
|
|
#include "jorth.h"
|
|
|
|
/*** S C R A T C H ***/
|
|
|
|
#define NUM_TILES 128
|
|
#define NUM_SPRITES 64
|
|
#define OFF_TILES 0x5000
|
|
#define TILE_STRIDE 64
|
|
#define SPRITE_STRIDE 80
|
|
unsigned int tiles[NUM_TILES * TILE_STRIDE];
|
|
unsigned int sprites[NUM_SPRITES * SPRITE_STRIDE];
|
|
|
|
unsigned char map[10000];
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
#define DIR_N 0
|
|
#define DIR_E 1
|
|
#define DIR_W 2
|
|
#define DIR_S 3
|
|
|
|
#define STATE_MAP 0
|
|
#define STATE_DIALOG 1
|
|
|
|
struct entity;
|
|
typedef struct entity Entity_t;
|
|
|
|
struct entity {
|
|
int x;
|
|
int y;
|
|
int dir;
|
|
int sprites[4];
|
|
};
|
|
|
|
void drawEntity(Entity_t *entity) {
|
|
int isprite = entity->sprites[entity->dir];
|
|
drawSprite(&sprites[isprite * SPRITE_STRIDE], entity->x, entity->y);
|
|
}
|
|
|
|
void playerThink(Entity_t *self) {
|
|
if (keyIsDown(K_LEFT)) { self->x -= 3; self->dir = DIR_W; }
|
|
if (keyIsDown(K_RIGHT)) { self->x += 3; self->dir = DIR_E; }
|
|
if (keyIsDown(K_UP)) { self->y -= 3; self->dir = DIR_N; }
|
|
if (keyIsDown(K_DOWN)) { self->y += 3; self->dir = DIR_S; }
|
|
}
|
|
|
|
typedef struct {
|
|
int dy;
|
|
int y;
|
|
} Footer_t;
|
|
|
|
typedef struct {
|
|
Entity_t player;
|
|
Footer_t footer;
|
|
int state;
|
|
} Game_t;
|
|
|
|
Game_t game;
|
|
|
|
void game_init() {
|
|
FILE *f;
|
|
TifImageMeta_t meta;
|
|
|
|
game.player.x = 100;
|
|
game.player.y = 100;
|
|
game.player.dir = DIR_E;
|
|
game.player.sprites[DIR_E] = 0;
|
|
game.player.sprites[DIR_N] = 1;
|
|
game.player.sprites[DIR_W] = 2;
|
|
game.player.sprites[DIR_S] = 3;
|
|
game.footer.y = 0;
|
|
game.state = STATE_MAP;
|
|
|
|
setEGAMode();
|
|
atexit(vid_cleanup);
|
|
|
|
kbd_init();
|
|
timer_init(TIMER_30HZ);
|
|
|
|
tile_init();
|
|
fillMap();
|
|
|
|
f = fopen("FOOTER.TIF", "rb");
|
|
meta = tifLoadMeta(f);
|
|
tifLoadEGA(f, meta, 0, 24, 336);
|
|
fclose(f);
|
|
|
|
f = fopen("TILES.TIF", "rb");
|
|
meta = tifLoadMeta(f);
|
|
tifLoad(f, meta, tiles, NUM_TILES * 16, 16, 4);
|
|
tifLoadEGA(f, meta, OFF_TILES, NUM_TILES * 16, 16);
|
|
fclose(f);
|
|
|
|
f = fopen("SPRITE.TIF", "rb");
|
|
meta = tifLoadMeta(f);
|
|
tifLoad(f, meta, sprites, NUM_SPRITES * 16, 16, 5);
|
|
fclose(f);
|
|
|
|
loadTiles(OFF_TILES, tiles);
|
|
loadMap(map, 100, 100);
|
|
scroll(0, 0);
|
|
}
|
|
|
|
void showDialog() {
|
|
game.state = STATE_DIALOG;
|
|
game.footer.dy = 1;
|
|
}
|
|
|
|
void dialogThink() {
|
|
if (keyWasPressed(K_SPACE)) {
|
|
game.footer.dy = -1;
|
|
}
|
|
game.footer.y += game.footer.dy;
|
|
if (game.footer.dy > 0 && game.footer.y > 24) {
|
|
game.footer.y = 24;
|
|
game.footer.dy = 0;
|
|
} else if (game.footer.dy < 0 && game.footer.y < 0) {
|
|
game.footer.y = 0;
|
|
game.footer.dy = 0;
|
|
game.state = STATE_MAP;
|
|
}
|
|
setSplitScreen(399 - (game.footer.y << 1));
|
|
}
|
|
|
|
void overworldThink() {
|
|
if (keyWasPressed(K_SPACE)) {
|
|
showDialog();
|
|
}
|
|
playerThink(&game.player);
|
|
scroll(game.player.x - 152, game.player.y - 92);
|
|
}
|
|
|
|
void f_seremit() {
|
|
ser_write_byte(TOP().i);
|
|
if (TOP().i == '\n') {
|
|
ser_write_byte('\r');
|
|
}
|
|
DROP(1);
|
|
}
|
|
|
|
void f_keyWasPressed() {
|
|
TOP().i = keyWasPressed(TOP().i);
|
|
}
|
|
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);
|
|
}
|
|
void f_ticks() {
|
|
PUSHU(timer_counter);
|
|
}
|
|
|
|
void game_f_init() {
|
|
f_init();
|
|
CDEF("seremit", f_seremit);
|
|
CDEF("key-pressed", f_keyWasPressed);
|
|
CDEF("key-down", f_keyIsDown);
|
|
CDEF("sprite", f_drawSprite);
|
|
CDEF("scroll", f_scroll);
|
|
CDEF("draw", drawScreen);
|
|
CDEF("ticks", f_ticks);
|
|
|
|
f_loadfile("game.jor");
|
|
}
|
|
|
|
void f_poll() {
|
|
static char line[256] = { 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';
|
|
}
|
|
}
|
|
f_taskloop();
|
|
}
|
|
|
|
int main() {
|
|
ser_init(SER_COM2, BAUD_19200, SER_8N1);
|
|
game_init();
|
|
game_f_init();
|
|
|
|
while (!keyIsDown(K_ESC)) {
|
|
kbd_debounce();
|
|
f_poll();
|
|
|
|
if (game.state == STATE_MAP) {
|
|
overworldThink();
|
|
} else if (game.state == STATE_DIALOG) {
|
|
dialogThink();
|
|
}
|
|
drawEntity(&game.player);
|
|
drawScreen();
|
|
}
|
|
|
|
return 0;
|
|
}
|