Add initial code
commit
d1f04810bd
|
@ -0,0 +1,8 @@
|
|||
bin/*.ir
|
||||
codedefs/*.bin
|
||||
src_crap
|
||||
src_oldtest
|
||||
doc
|
||||
sounds
|
||||
sprites
|
||||
textures
|
|
@ -0,0 +1,37 @@
|
|||
## Copyright © 2017 Project Golan, all rights reserved.
|
||||
CC=gdcc-cc
|
||||
LD=gdcc-ld
|
||||
MAKELIB=gdcc-makelib
|
||||
|
||||
BIN=codedefs
|
||||
SRC=src
|
||||
INC=inc
|
||||
IR=bin
|
||||
|
||||
TARGET=--bc-target=Doominati
|
||||
LFLAGS=$(TARGET)
|
||||
CFLAGS=$(TARGET) --alloc-Aut=4194304 -c
|
||||
|
||||
MAIN_SOURCES=$(wildcard $(SRC)/*.c)
|
||||
MAIN_HEADERS=$(wildcard $(SRC)/*.h)
|
||||
MAIN_OUTPUT=$(MAIN_SOURCES:$(SRC)/%.c=$(IR)/%.ir)
|
||||
MAIN_BINARY=$(BIN)/影響の目.bin
|
||||
|
||||
all: $(BIN)/stdlib.bin $(MAIN_BINARY)
|
||||
|
||||
$(BIN)/stdlib.bin: $(IR)/libc.ir $(IR)/libGDCC.ir
|
||||
$(LD) $(LFLAGS) -o $@ $^
|
||||
|
||||
$(MAIN_BINARY): $(MAIN_OUTPUT)
|
||||
$(LD) $(LFLAGS) -o $@ $^
|
||||
|
||||
$(IR)/%.ir: $(SRC)/%.c $(MAIN_HEADERS)
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
$(IR)/libc.ir:
|
||||
$(MAKELIB) $(TARGET) -c -o $@ libc
|
||||
|
||||
$(IR)/libGDCC.ir:
|
||||
$(MAKELIB) $(TARGET) -c -o $@ libGDCC
|
||||
|
||||
## EOF
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
// Copyright © 2017 Project Golan, all rights reserved.
|
||||
include "objdefs/player.dod"
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright © 2017 Project Golan, all rights reserved.
|
||||
entity Shootable
|
||||
{
|
||||
health 1
|
||||
}
|
||||
|
||||
entity Player < Shootable
|
||||
{
|
||||
task G_Player_Think
|
||||
size 3
|
||||
drawsize 16
|
||||
sprite "@sprites/particle3.png"
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,611 @@
|
|||
// Copyright © 2017 Project Golan, all rights reserved.
|
||||
#include "g_object.h"
|
||||
#include "m_token.h"
|
||||
#include "m_str.h"
|
||||
#include "m_darray.h"
|
||||
|
||||
#include <Doominati.h>
|
||||
#include <GDCC/HashMap.h>
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define G_dodTokBeg (4)
|
||||
#define G_dodTokEnd (10)
|
||||
|
||||
#define G_ofmap_GetKey(o) ( (o)->name)
|
||||
#define G_ofmap_GetNext(o) (&(o)->next)
|
||||
#define G_ofmap_GetPrev(o) (&(o)->prev)
|
||||
#define G_ofmap_HashObj(o) ( (o)->keyhash)
|
||||
#define G_ofmap_HashKey(k) (M_StrHash(k))
|
||||
#define G_ofmap_KeyCmp(l, r) (strcmp(l, r))
|
||||
|
||||
#define G_etmap_GetKey(o) ( (o)->name)
|
||||
#define G_etmap_GetNext(o) (&(o)->next)
|
||||
#define G_etmap_GetPrev(o) (&(o)->prev)
|
||||
#define G_etmap_HashObj(o) ( (o)->keyhash)
|
||||
#define G_etmap_HashKey(k) (M_StrHash(k))
|
||||
#define G_etmap_KeyCmp(l, r) (strcmp(l, r))
|
||||
|
||||
#define G_frmap_GetKey(o) ( (o)->name)
|
||||
#define G_frmap_GetNext(o) (&(o)->next)
|
||||
#define G_frmap_GetPrev(o) (&(o)->prev)
|
||||
#define G_frmap_HashObj(o) ( (o)->keyhash)
|
||||
#define G_frmap_HashKey(k) (M_StrHash(k))
|
||||
#define G_frmap_KeyCmp(l, r) (strcmp(l, r))
|
||||
|
||||
#define G_anmap_GetKey(o) ( (o)->name)
|
||||
#define G_anmap_GetNext(o) (&(o)->next)
|
||||
#define G_anmap_GetPrev(o) (&(o)->prev)
|
||||
#define G_anmap_HashObj(o) ( (o)->keyhash)
|
||||
#define G_anmap_HashKey(k) (M_StrHash(k))
|
||||
#define G_anmap_KeyCmp(l, r) (strcmp(l, r))
|
||||
|
||||
#define G_anims_GetKey(o) ( (o)->name)
|
||||
#define G_anims_GetNext(o) (&(o)->next)
|
||||
#define G_anims_GetPrev(o) (&(o)->prev)
|
||||
#define G_anims_HashObj(o) ( (o)->keyhash)
|
||||
#define G_anims_HashKey(k) (M_StrHash(k))
|
||||
#define G_anims_KeyCmp(l, r) (strcmp(l, r))
|
||||
|
||||
// Static Functions ----------------------------------------------------------|
|
||||
|
||||
_Noreturn static void G_ObjDef_throw (struct G_dodst *st, char const *emsg);
|
||||
static M_token *G_ObjDef_getToken(struct G_dodst *st);
|
||||
static M_token *G_ObjDef_unget (struct G_dodst *st);
|
||||
static M_token *G_ObjDef_reget (struct G_dodst *st);
|
||||
static bool G_ObjDef_drop (struct G_dodst *st, M_tokty t);
|
||||
[[__optional_args(1)]]
|
||||
static M_token *G_ObjDef_expect (struct G_dodst *st, M_tokty t, char const *exp);
|
||||
[[__optional_args(1)]]
|
||||
static struct G_odarg G_ObjDef_getArgs (struct G_dodst *st, char const *arg);
|
||||
|
||||
// Types ---------------------------------------------------------------------|
|
||||
|
||||
GDCC_HashMap_Decl(G_ofmap, char const *, struct G_ofdcl)
|
||||
GDCC_HashMap_Decl(G_etmap, char const *, struct G_etdcl)
|
||||
GDCC_HashMap_Decl(G_frmap, char const *, struct G_frdcl)
|
||||
GDCC_HashMap_Decl(G_anmap, char const *, struct G_andcl)
|
||||
GDCC_HashMap_Decl(G_anims, char const *, struct G_manim)
|
||||
|
||||
typedef struct G_dodst
|
||||
{
|
||||
__prop throw {call: G_ObjDef_throw (this)}
|
||||
__prop getToken {call: G_ObjDef_getToken(this)}
|
||||
__prop unget {call: G_ObjDef_unget (this)}
|
||||
__prop drop {call: G_ObjDef_drop (this)}
|
||||
__prop expect {call: G_ObjDef_expect (this)}
|
||||
__prop getArgs {call: G_ObjDef_getArgs (this)}
|
||||
__prop reget {call: G_ObjDef_reget (this)}
|
||||
|
||||
jmp_buf ejmp;
|
||||
int lines;
|
||||
char const *fname;
|
||||
FILE *fp;
|
||||
int tpos, tend;
|
||||
M_token toks[G_dodTokEnd];
|
||||
} G_dodst;
|
||||
|
||||
typedef union G_odprm
|
||||
{
|
||||
mword u;
|
||||
integ i;
|
||||
fixed k;
|
||||
lfrac r;
|
||||
} G_odprm;
|
||||
|
||||
typedef struct G_odarg
|
||||
{
|
||||
G_odprm argv[8];
|
||||
int argc;
|
||||
} G_odarg;
|
||||
|
||||
typedef struct G_ofdcl
|
||||
{
|
||||
DGE_CallbackType fptr;
|
||||
char const *name;
|
||||
size_t keyhash;
|
||||
struct G_ofdcl *next, **prev;
|
||||
} G_ofdcl;
|
||||
|
||||
typedef struct G_etdcl
|
||||
{
|
||||
G_entty type;
|
||||
G_anims anim;
|
||||
M_Vec_decl(struct G_manim, anims);
|
||||
|
||||
char name[32];
|
||||
size_t keyhash;
|
||||
struct G_etdcl *next, **prev;
|
||||
} G_etdcl;
|
||||
|
||||
typedef struct G_frdcl
|
||||
{
|
||||
M_texid sprite;
|
||||
char name[32];
|
||||
size_t keyhash;
|
||||
struct G_frdcl *next, **prev;
|
||||
} G_frdcl;
|
||||
|
||||
typedef struct G_andcl
|
||||
{
|
||||
M_Vec_decl(G_frame, frame);
|
||||
char name[32];
|
||||
size_t keyhash;
|
||||
struct G_andcl *next, **prev;
|
||||
} G_andcl;
|
||||
|
||||
typedef struct G_manim
|
||||
{
|
||||
G_anima anim;
|
||||
char name[32];
|
||||
size_t keyhash;
|
||||
struct G_manim *next, **prev;
|
||||
} G_manim;
|
||||
|
||||
// Static Objects ------------------------------------------------------------|
|
||||
|
||||
static G_ofmap G_objfuncs;
|
||||
static G_etmap G_enttypes;
|
||||
static G_frmap G_frametab;
|
||||
static G_anmap G_animsmap;
|
||||
|
||||
M_Vec_defn(G_ofdcl, G_ofvec, static);
|
||||
M_Vec_defn(G_etdcl, G_etvec, static);
|
||||
M_Vec_defn(G_frdcl, G_frvec, static);
|
||||
M_Vec_defn(G_andcl, G_anvec, static);
|
||||
|
||||
// Static Functions ----------------------------------------------------------|
|
||||
|
||||
GDCC_HashMap_Defn(G_ofmap, char const *, G_ofdcl)
|
||||
GDCC_HashMap_Defn(G_etmap, char const *, G_etdcl)
|
||||
GDCC_HashMap_Defn(G_frmap, char const *, G_frdcl)
|
||||
GDCC_HashMap_Defn(G_anmap, char const *, G_andcl)
|
||||
GDCC_HashMap_Defn(G_anims, char const *, G_manim)
|
||||
|
||||
//
|
||||
// G_ObjDef_throw
|
||||
//
|
||||
_Noreturn static void G_ObjDef_throw(G_dodst *st, char const *emsg)
|
||||
{
|
||||
fprintf(stderr, "ObjDef (%s:%i): %s\n", st->fname, st->reget()->line, emsg);
|
||||
longjmp(st->ejmp, 1);
|
||||
}
|
||||
|
||||
//
|
||||
// G_ObjDef_getToken
|
||||
//
|
||||
static M_token *G_ObjDef_getToken(G_dodst *st)
|
||||
{
|
||||
if(++st->tpos < st->tend)
|
||||
return &st->toks[st->tpos];
|
||||
|
||||
memmove(&st->toks[0], &st->toks[st->tend - G_dodTokBeg],
|
||||
sizeof(M_token) * G_dodTokBeg);
|
||||
|
||||
for(st->tpos = st->tend = G_dodTokBeg; st->tend < G_dodTokEnd; st->tend++)
|
||||
{
|
||||
skip:
|
||||
M_Tk_Parse(st->fp, &st->toks[st->tend]);
|
||||
st->toks[st->tend].line = st->lines;
|
||||
|
||||
switch(st->toks[st->tend].type) {
|
||||
default: break;
|
||||
case tok_eof: goto done;
|
||||
case tok_lnend: st->lines++;
|
||||
case tok_cmtlin: goto skip;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
for(int i = 0; i < st->tend; i++)
|
||||
printf("%i: %s%s\n", st->toks[i].type, st->toks[i].text, i == st->tpos ? " <-- cursor is here" : "");
|
||||
*/
|
||||
|
||||
done:
|
||||
return &st->toks[st->tpos];
|
||||
}
|
||||
|
||||
//
|
||||
// G_ObjDef_unget
|
||||
//
|
||||
static M_token *G_ObjDef_unget(G_dodst *st)
|
||||
{
|
||||
return &st->toks[st->tpos--];
|
||||
}
|
||||
|
||||
//
|
||||
// G_ObjDef_reget
|
||||
//
|
||||
static M_token *G_ObjDef_reget(G_dodst *st)
|
||||
{
|
||||
return &st->toks[st->tpos];
|
||||
}
|
||||
|
||||
//
|
||||
// G_ObjDef_drop
|
||||
//
|
||||
static bool G_ObjDef_drop(G_dodst *st, M_tokty t)
|
||||
{
|
||||
if(st->getToken()->type != t) {
|
||||
st->unget();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// G_ObjDef_expect
|
||||
//
|
||||
static M_token *G_ObjDef_expect(G_dodst *st, M_tokty t, char const *exp)
|
||||
{
|
||||
M_token *tok;
|
||||
if((tok = st->getToken())->type != t) {
|
||||
if(exp) st->throw(M_StrFmt("expected %s", exp));
|
||||
else st->throw("unexpected token");
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
|
||||
//
|
||||
// G_ObjDef_getArgs
|
||||
//
|
||||
[[__optional_args(1)]]
|
||||
static G_odarg G_ObjDef_getArgs(G_dodst *st, char const *arg)
|
||||
{
|
||||
G_odarg a = {};
|
||||
bool done = false;
|
||||
int i = 0;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
char ch = arg[i++];
|
||||
|
||||
if(!done && (arg[i] == '\0' || arg[i] == '|'))
|
||||
done = true;
|
||||
|
||||
switch(ch)
|
||||
{
|
||||
#define CaseN(c, t, f, ...) \
|
||||
case c: \
|
||||
a.argv[a.argc++].t = \
|
||||
f(st->expect(tok_number, "number")->text, __VA_ARGS__); \
|
||||
break
|
||||
CaseN('u', u, strtoui, NULL, 0);
|
||||
CaseN('i', i, strtoi, NULL, 0);
|
||||
CaseN('k', k, strtofxhk, NULL);
|
||||
CaseN('r', r, strtofxk, NULL);
|
||||
// TODO: get david to implement fracts
|
||||
//CaseN('r', r, strtofxlr, NULL);
|
||||
#undef CaseN
|
||||
case '|': done = true; continue;
|
||||
case '\0': st->throw("too many arguments");
|
||||
default: st->throw("unexpected argument type");
|
||||
}
|
||||
|
||||
if(!st->drop(tok_comma)) break;
|
||||
}
|
||||
|
||||
if(!done)
|
||||
st->throw("not enough arguments");
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
//
|
||||
// G_ObjDef_getEntAnim
|
||||
//
|
||||
static void G_ObjDef_getEntAnim(G_dodst *st, G_etdcl *decl)
|
||||
{
|
||||
char alias[M_countof(decl->name)];
|
||||
|
||||
M_strbufcpy(alias, st->expect(tok_identi, "alias name")->text);
|
||||
st->expect(tok_eq, "'='");
|
||||
|
||||
G_andcl *an = G_animsmap.find(st->expect(tok_identi, "anim name")->text);
|
||||
if(an == NULL) st->throw("anim not defined");
|
||||
if(decl->anim.find(alias)) st->throw("alias redefinition");
|
||||
|
||||
M_Vec_grow(decl->anims, 1);
|
||||
G_manim *anim = &decl->animsV[decl->animsC++];
|
||||
M_strbufcpy(anim->name, alias);
|
||||
anim->keyhash = M_StrHash(anim->name);
|
||||
anim->anim = (G_anima){an->frameV, an->frameC};
|
||||
decl->anim.insert(anim);
|
||||
}
|
||||
|
||||
//
|
||||
// G_ObjDef_getEntProp
|
||||
//
|
||||
static void G_ObjDef_getEntProp(G_dodst *st, G_entty *type, char const *id)
|
||||
{
|
||||
if(strcmp(id, "task") == 0)
|
||||
{
|
||||
G_ofdcl *fn = G_objfuncs.find(st->expect(tok_identi, "function")->text);
|
||||
if(!fn) st->throw("invalid function name");
|
||||
type->task = fn->fptr;
|
||||
}
|
||||
else if(strcmp(id, "size") == 0)
|
||||
{
|
||||
G_odarg a = st->getArgs("k|kk");
|
||||
if(a.argc == 1) {
|
||||
type->sx = type->sy = a.argv[0].k;
|
||||
} else {
|
||||
type->sx = a.argv[0].k;
|
||||
type->sy = a.argv[1].k;
|
||||
if(a.argc > 2) type->sz = a.argv[2].k;
|
||||
}
|
||||
}
|
||||
else if(strcmp(id, "drawsize") == 0)
|
||||
{
|
||||
G_odarg a = st->getArgs("k|k");
|
||||
if(a.argc == 1) {
|
||||
type->rsx = type->rsy = a.argv[0].k;
|
||||
} else {
|
||||
type->rsx = a.argv[0].k;
|
||||
type->rsy = a.argv[1].k;
|
||||
}
|
||||
}
|
||||
else if(strcmp(id, "sprite") == 0)
|
||||
{
|
||||
type->sprite = DGE_GetTexture(
|
||||
M_StrCreate(st->expect(tok_string, "sprite name")->text));
|
||||
}
|
||||
|
||||
// TODO: change this when access through rvalues is fixed
|
||||
#define Prop(name, t) \
|
||||
else if(strcmp(id, #name) == 0) \
|
||||
__with(G_odarg a = st->getArgs(#t);) type->name = a.argv[0].t
|
||||
Prop(health, i);
|
||||
Prop(friction, k);
|
||||
Prop(mass, k);
|
||||
#undef Prop
|
||||
|
||||
else
|
||||
st->throw("unknown identifier in entity definition");
|
||||
}
|
||||
|
||||
//
|
||||
// G_ObjDef_getFrameSprite
|
||||
//
|
||||
static M_texid G_ObjDef_getFrameSprite(char const *fmt, char frame, int i)
|
||||
{
|
||||
M_Vec_defn(char, buf);
|
||||
|
||||
for(; *fmt; fmt++)
|
||||
{
|
||||
if(*fmt != '%') {M_Vec_grow(buf, 1); bufV[bufC++] = *fmt; continue;}
|
||||
|
||||
switch(*++fmt)
|
||||
{
|
||||
default:
|
||||
case '%': M_Vec_grow(buf, 1); bufV[bufC++] = *fmt; break;
|
||||
case 'c': M_Vec_grow(buf, 1); bufV[bufC++] = frame; break;
|
||||
case 'i':
|
||||
M_Vec_grow(buf, 20);
|
||||
bufC += snprintf(&bufV[bufC], 20, "%i", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!bufV) return 0;
|
||||
|
||||
M_texid id = DGE_GetTexture(DGE_String_Create(bufV, bufC));
|
||||
free(bufV);
|
||||
return id;
|
||||
}
|
||||
|
||||
//
|
||||
// G_ObjDef_parseFrameDef
|
||||
//
|
||||
static void G_ObjDef_parseFrameDef(G_dodst *st)
|
||||
{
|
||||
char name[32], frame[32], fmt[32];
|
||||
M_strbufcpy(name, st->expect(tok_identi, "name")->text);
|
||||
M_strbufcpy(frame, st->expect(tok_identi, "frames")->text);
|
||||
M_strbufcpy(fmt, st->expect(tok_string, "format")->text);
|
||||
|
||||
for(int i = 0; frame[i]; i++)
|
||||
{
|
||||
if(frame[i] < 'A' || frame[i] > 'Z')
|
||||
st->throw("invalid frame");
|
||||
|
||||
char const *key = M_StrFmt("%s%c", name, frame[i]);
|
||||
G_frdcl *decl = G_frametab.find(key);
|
||||
|
||||
if(!decl)
|
||||
{
|
||||
M_Vec_grow(G_frvec, 1);
|
||||
*(decl = &G_frvecV[G_frvecC++]) = (G_frdcl){};
|
||||
M_strbufcpy(decl->name, key);
|
||||
decl->keyhash = M_StrHash(decl->name);
|
||||
G_frametab.insert(decl);
|
||||
}
|
||||
|
||||
decl->sprite = G_ObjDef_getFrameSprite(fmt, 'A' + i, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// G_ObjDef_parseAnim
|
||||
//
|
||||
static void G_ObjDef_parseAnim(G_dodst *st, G_andcl *decl)
|
||||
{
|
||||
char name[32], frames[32];
|
||||
M_strbufcpy(name, st->expect(tok_identi, "name")->text);
|
||||
M_strbufcpy(frames, st->expect(tok_identi, "frame")->text);
|
||||
int time = strtoi(st->expect(tok_number, "time")->text, NULL, 0);
|
||||
|
||||
M_Vec_growN(decl->frame, strlen(frames), 0);
|
||||
for(char const *frame = frames; *frame; frame++) {
|
||||
char *key = M_StrFmt("%s%c", name, *frame);
|
||||
G_frdcl *fr = G_frametab.find(key);
|
||||
if(!fr) st->throw(M_StrFmt("undefined frame '%s'", key));
|
||||
decl->frameV[decl->frameC++] = (G_frame){time, fr->sprite};
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// G_ObjDef_parseAnimDef
|
||||
//
|
||||
static void G_ObjDef_parseAnimDef(G_dodst *st)
|
||||
{
|
||||
bool ins = true;
|
||||
G_andcl *decl;
|
||||
|
||||
__with(char const *name = st->expect(tok_identi, "anim name")->text;)
|
||||
{
|
||||
if((decl = G_animsmap.find(name)) == NULL) {
|
||||
M_Vec_grow(G_anvec, 1);
|
||||
*(decl = &G_anvecV[G_anvecC++]) = (G_andcl){};
|
||||
M_strbufcpy(decl->name, name);
|
||||
} else {
|
||||
ins = false;
|
||||
}
|
||||
}
|
||||
|
||||
st->expect(tok_braceo, "'{'");
|
||||
|
||||
while(!st->drop(tok_bracec))
|
||||
G_ObjDef_parseAnim(st, decl);
|
||||
|
||||
if(ins) {
|
||||
decl->keyhash = M_StrHash(decl->name);
|
||||
G_animsmap.insert(decl);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// G_ObjDef_parseEntDef
|
||||
//
|
||||
static void G_ObjDef_parseEntDef(G_dodst *st)
|
||||
{
|
||||
bool ins = true;
|
||||
G_etdcl *decl;
|
||||
|
||||
__with(char const *name = st->expect(tok_identi, "entity name")->text;)
|
||||
{
|
||||
if((decl = G_enttypes.find(name)) == NULL) {
|
||||
M_Vec_grow(G_etvec, 1);
|
||||
*(decl = &G_etvecV[G_etvecC++]) = (G_etdcl){};
|
||||
M_strbufcpy(decl->name, name);
|
||||
G_anims_ctor(&decl->anim, 8, 8);
|
||||
} else {
|
||||
ins = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(st->drop(tok_lt)) {
|
||||
G_etdcl *base =
|
||||
G_enttypes.find(st->expect(tok_identi, "base entity name")->text);
|
||||
if(!base) st->throw("base type not found");
|
||||
decl->type = base->type;
|
||||
}
|
||||
|
||||
st->expect(tok_braceo, "'{'");
|
||||
|
||||
for(M_token *tok; (tok = st->getToken())->type != tok_bracec;)
|
||||
switch(tok->type)
|
||||
{
|
||||
case tok_identi:
|
||||
if(strcmp(tok->text, "anim") == 0)
|
||||
G_ObjDef_getEntAnim(st, decl);
|
||||
else
|
||||
G_ObjDef_getEntProp(st, &decl->type, tok->text);
|
||||
break;
|
||||
case tok_semico:
|
||||
continue;
|
||||
default:
|
||||
st->throw("expected '}'");
|
||||
}
|
||||
|
||||
if(ins) {
|
||||
decl->keyhash = M_StrHash(decl->name);
|
||||
G_enttypes.insert(decl);
|
||||
}
|
||||
}
|
||||
|
||||
// Extern Functions ----------------------------------------------------------|
|
||||
|
||||
//
|
||||
// G_ObjDef_Init
|
||||
//
|
||||
void G_ObjDef_Init(void)
|
||||
{
|
||||
G_ofmap_ctor(&G_objfuncs, 16, 16);
|
||||
G_etmap_ctor(&G_enttypes, 16, 16);
|
||||
G_frmap_ctor(&G_frametab, 16, 16);
|
||||
G_anmap_ctor(&G_animsmap, 16, 16);
|
||||
}
|
||||
|
||||
//
|
||||
// G_ObjDef_Load
|
||||
//
|
||||
void G_ObjDef_Load(char const *fname)
|
||||
{
|
||||
G_dodst st = {.fp = fopen(fname, "r"), .fname = fname, .lines = 1};
|
||||
|
||||
if(!st.fp) {
|
||||
fprintf(stderr, "ObjDef: couldn't open file '%s'\n", fname);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if(setjmp(st.ejmp) == 1)
|
||||
goto done;
|
||||
|
||||
for(M_token *tok; (tok = st.getToken())->type != tok_eof;)
|
||||
switch(tok->type)
|
||||
{
|
||||
case tok_identi:
|
||||
if(strcmp(tok->text, "entity") == 0)
|
||||
G_ObjDef_parseEntDef(&st);
|
||||
else if(strcmp(tok->text, "anim") == 0)
|
||||
G_ObjDef_parseAnimDef(&st);
|
||||
else if(strcmp(tok->text, "frame") == 0)
|
||||
G_ObjDef_parseFrameDef(&st);
|
||||
else if(strcmp(tok->text, "include") == 0)
|
||||
G_ObjDef_Load(st.expect(tok_string, "string")->text);
|
||||
else
|
||||
st.throw("unknown identifier in toplevel");
|
||||
continue;
|
||||
default:
|
||||
st.throw("expected toplevel definition");
|
||||
}
|
||||
|
||||
printf("ObjDef: '%s' loaded.\n", fname);
|
||||
|
||||
done:
|
||||
fclose(st.fp);
|
||||
}
|
||||
|
||||
//
|
||||
// G_ObjDef_LoadFunc
|
||||
//
|
||||
void G_ObjDef_LoadFunc(char const *name, DGE_CallbackType fptr)
|
||||
{
|
||||
M_Vec_grow(G_ofvec, 1);
|
||||
G_ofvecV[G_ofvecC] = (G_ofdcl){fptr, name, M_StrHash(name)};
|
||||
G_objfuncs.insert(&G_ofvecV[G_ofvecC++]);
|
||||
}
|
||||
|
||||
//
|
||||
// G_ObjDef_GetType
|
||||
//
|
||||
G_entty const *G_ObjDef_GetType(char const *name)
|
||||
{
|
||||
G_etdcl const *decl = G_enttypes.find(name);
|
||||
return decl ? &decl->type : NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// G_ObjDef_GetAnim
|
||||
//
|
||||
G_anima const *G_ObjDef_GetAnim(G_entty const *type, char const *name)
|
||||
{
|
||||
G_manim *anim = ((G_etdcl *)type)->anim.find(name);
|
||||
return anim ? &anim->anim : NULL;
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,65 @@
|
|||
// Copyright © 2017 Project Golan, all rights reserved.
|
||||
#ifndef g_object_h
|
||||
#define g_object_h
|
||||
|
||||
#include "m_types.h"
|
||||
|
||||
#include <Doominati.h>
|
||||
#include <GDCC/HashMap.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define G_ObjDef_setupEntity(type, th) \
|
||||
do { \
|
||||
(th).sprite = (type)->sprite; \
|
||||
(th).health = (type)->health; \
|
||||
(th).friction = (type)->friction; \
|
||||
(th).mass = (type)->mass; \
|
||||
(th).rsx = (type)->rsx; \
|
||||
(th).rsy = (type)->rsy; \
|
||||
(th).sx = (type)->sx; \
|
||||
(th).sy = (type)->sy; \
|
||||
(th).sz = (type)->sz; \
|
||||
} while(0)
|
||||
|
||||
#define G_ObjDef_createTask(type, ...) \
|
||||
(DGE_Task_Create(0, (type)->task, __VA_ARGS__))
|
||||
|
||||
#define G_ObjDef_loadFunc(fn) G_ObjDef_LoadFunc(#fn, (DGE_CallbackType)fn)
|
||||
|
||||
// Extern Functions ----------------------------------------------------------|
|
||||
|
||||
void G_ObjDef_Init(void);
|
||||
void G_ObjDef_Load(char const *fname);
|
||||
void G_ObjDef_LoadFunc(char const *name, DGE_CallbackType fptr);
|
||||
struct G_entty const *G_ObjDef_GetType(char const *name);
|
||||
struct G_anima const *G_ObjDef_GetAnim(struct G_entty const *type, char const *name);
|
||||
|
||||
// Types ---------------------------------------------------------------------|
|
||||
|
||||
typedef struct G_frame // Frame
|
||||
{
|
||||
integ time;
|
||||
M_texid sprite;
|
||||
} G_frame;
|
||||
|
||||
typedef struct G_anima // Animation
|
||||
{
|
||||
G_frame *frame;
|
||||
msize count;
|
||||
} G_anima;
|
||||
|
||||
typedef struct G_entty // Entity Type
|
||||
{
|
||||
__prop getAnim {call: G_ObjDef_GetAnim(this)}
|
||||
|
||||
M_texid sprite;
|
||||
integ health;
|
||||
lfrac friction;
|
||||
fixed mass;
|
||||
fixed rsx, rsy;
|
||||
fixed sx, sy, sz;
|
||||
DGE_CallbackType task;
|
||||
} G_entty;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright © 2017 Project Golan, all rights reserved.
|
||||
#ifndef m_darray_h
|
||||
#define m_darray_h
|
||||
|
||||
#define M_Vec_defn(type, name, ...) \
|
||||
__VA_ARGS__ type *name##V = NULL; \
|
||||
__VA_ARGS__ size_t name##C = 0, name##S = 0
|
||||
|
||||
#define M_Vec_decl(type, name, ...) \
|
||||
__VA_ARGS__ type *name##V; \
|
||||
__VA_ARGS__ size_t name##C, name##S
|
||||
|
||||
#define M_Vec_growN(vec, n, g) \
|
||||
do { \
|
||||
if((vec##C) + (n) > (vec##S)) { \
|
||||
(vec##S) += (n) + (g); \
|
||||
(vec##V) = realloc((vec##V), sizeof(*(vec##V)) * (vec##S)); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define M_Vec_grow(vec, n) M_Vec_growN(vec, n, 8)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright © 2017 Project Golan, all rights reserved.
|
||||
#include "m_str.h"
|
||||
#include "m_types.h"
|
||||
|
||||
#include <Doominati.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
// Extern Functions ----------------------------------------------------------|
|
||||
|
||||
//
|
||||
// M_StrFmt
|
||||
//
|
||||
char *M_StrFmt(char const *fmt, ...)
|
||||
{
|
||||
[[__no_init]]
|
||||
static char bufs[3][0x2800];
|
||||
static int idx;
|
||||
|
||||
va_list va;
|
||||
|
||||
if(++idx == M_countof(bufs)) idx = 0;
|
||||
|
||||
va_start(va, fmt);
|
||||
vsnprintf(bufs[idx], sizeof(bufs[idx]), fmt, va);
|
||||
va_end(va);
|
||||
|
||||
return bufs[idx];
|
||||
}
|
||||
|
||||
//
|
||||
// M_StrHash
|
||||
//
|
||||
mword M_StrHash(char const *s)
|
||||
{
|
||||
mword h = 0;
|
||||
for(; *s; s++)
|
||||
h = h * 101 + *s;
|
||||
return h;
|
||||
}
|
||||
|
||||
//
|
||||
// M_StrCreate
|
||||
//
|
||||
__str M_StrCreate(char const *s)
|
||||
{
|
||||
return DGE_String_Create(s, strlen(s));
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright © 2017 Project Golan, all rights reserved.
|
||||
#ifndef m_str_h
|
||||
#define m_str_h
|
||||
|
||||
#include "m_types.h"
|
||||
|
||||
#define M_strbufcpy(a, b) strncpy((a), (b), M_countof(a))
|
||||
|
||||
// Extern Functions ----------------------------------------------------------|
|
||||
|
||||
char *M_StrFmt(char const *fmt, ...);
|
||||
mword M_StrHash(char const *s);
|
||||
__str M_StrCreate(char const *s);
|
||||
char *M_StrDup(char const *s);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,148 @@
|
|||
// Copyright © 2017 Project Golan, all rights reserved.
|
||||
#include "m_token.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#define M_Tk_getPredStr(s, fn) \
|
||||
do { \
|
||||
int i; \
|
||||
for(i = (s); i < M_countof(tok->text)-1 && fn(ch); i++, ch = fgetc(fp)) \
|
||||
tok->text[i] = ch; \
|
||||
tok->text[i] = '\0'; \
|
||||
ungetc(ch, fp); \
|
||||
} while(0)
|
||||
|
||||
#define M_Tk_isidenti(ch) (isalnum(ch) || (ch) == '_')
|
||||
#define M_Tk_isnum(ch) (isalnum(ch) || (ch) == '_' || (ch) == '.')
|
||||
|
||||
// Extern Functions ----------------------------------------------------------|
|
||||
|
||||
//
|
||||
// M_Tk_Parse
|
||||
//
|
||||
void M_Tk_Parse(FILE *fp, M_token *tok)
|
||||
{
|
||||
if(!tok) return;
|
||||
|
||||
tok->text[0] = '\0';
|
||||
|
||||
if(!fp || feof(fp)) {
|
||||
tok->type = tok_eof;
|
||||
return;
|
||||
}
|
||||
|
||||
begin:;
|
||||
int ch;
|
||||
switch((ch = fgetc(fp)))
|
||||
{
|
||||
case EOF:
|
||||
case '\0': tok->type = tok_eof; return;
|
||||
case '\r': if((ch = fgetc(fp)) != '\n') ungetc(ch, fp);
|
||||
case '\n': tok->type = tok_lnend; return;
|
||||
case ';': tok->type = tok_semico; return;
|
||||
case ',': tok->type = tok_comma; return;
|
||||
case '[': tok->type = tok_bracko; return;
|
||||
case ']': tok->type = tok_brackc; return;
|
||||
case '{': tok->type = tok_braceo; return;
|
||||
case '}': tok->type = tok_bracec; return;
|
||||
case '(': tok->type = tok_pareno; return;
|
||||
case ')': tok->type = tok_parenc; return;
|
||||
#define TokOp2(c, c2, t, t2) \
|
||||
case c: \
|
||||
if((ch = fgetc(fp)) == c2) tok->type = t2; \
|
||||
else {ungetc(ch, fp); tok->type = t;} \
|
||||
return
|
||||
TokOp2('=', '=', tok_eq, tok_eq2);
|
||||
TokOp2('?', '=', tok_tern, tok_terneq);
|
||||
TokOp2('!', '=', tok_not, tok_neq);
|
||||
TokOp2('~', '=', tok_bnot, tok_bneq);
|
||||
TokOp2('*', '=', tok_mul, tok_muleq);
|
||||
TokOp2('@', '@', tok_at, tok_at2);
|
||||
#undef TokOp2
|
||||
#define TokOp3(c, t, t2, teq) \
|
||||
case c: \
|
||||
if((ch = fgetc(fp)) == c) tok->type = t2; \
|
||||
else if(ch == '=') tok->type = teq; \
|
||||
else {ungetc(ch, fp); tok->type = t;} \
|
||||
return
|
||||
TokOp3('<', tok_lt, tok_lt2, tok_le);
|
||||
TokOp3('>', tok_gt, tok_gt2, tok_ge);
|
||||
TokOp3('|', tok_or, tok_or2, tok_oreq);
|
||||
TokOp3('&', tok_and, tok_and2, tok_andeq);
|
||||
TokOp3('+', tok_add, tok_add2, tok_addeq);
|
||||
TokOp3('%', tok_mod, tok_mod2, tok_modeq);
|
||||
TokOp3('^', tok_xor, tok_xor2, tok_xoreq);
|
||||
TokOp3(':', tok_col, tok_col2, tok_coleq);
|
||||
#undef TokOp3
|
||||
case '-':
|
||||
if((ch = fgetc(fp)) == '-') tok->type = tok_sub2;
|
||||
else if(ch == '=') tok->type = tok_subeq;
|
||||
else if(ch == '>') tok->type = tok_rarrow;
|
||||
else if(isdigit(ch)) {ungetc(ch, fp); ch = '-'; break;}
|
||||
else {ungetc(ch, fp); tok->type = tok_sub;}
|
||||
return;
|
||||
case '/':
|
||||
if((ch = fgetc(fp)) == '=')
|
||||
tok->type = tok_diveq;
|
||||
else if(ch == '/')
|
||||
{
|
||||
#define incmt(ch) ((ch) != '\n' && !feof(fp))
|
||||
ch = fgetc(fp);
|
||||
M_Tk_getPredStr(0, incmt);
|
||||
tok->type = tok_cmtlin;
|
||||
#undef incmt
|
||||
}
|
||||
else
|
||||
{ungetc(ch, fp); tok->type = tok_div;}
|
||||
return;
|
||||
case '.':
|
||||
if((ch = fgetc(fp)) == '.')
|
||||
{
|
||||
if((ch = fgetc(fp)) == '.')
|
||||
tok->type = tok_dot3;
|
||||
else
|
||||
{ungetc(ch, fp); tok->type = tok_dot2;}
|
||||
}
|
||||
else if(isdigit(ch))
|
||||
{ungetc(ch, fp); break;}
|
||||
else
|
||||
{ungetc(ch, fp); tok->type = tok_dot;}
|
||||
return;
|
||||
case '\'': tok->type = tok_charac; goto string;
|
||||
case '"': tok->type = tok_string; goto string;
|
||||
string: {
|
||||
int i, beg;
|
||||
for(i = 0, beg = ch; (ch = fgetc(fp)) != beg && !feof(fp); i++)
|
||||
tok->text[i] = ch;
|
||||
tok->text[i] = '\0';
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(isblank(ch))
|
||||
{
|
||||
while(isblank(ch = fgetc(fp)));
|
||||
ungetc(ch, fp);
|
||||
goto begin;
|
||||
}
|
||||
else if(isdigit(ch) || ch == '.' || ch == '-')
|
||||
{
|
||||
tok->text[0] = ch;
|
||||
ch = fgetc(fp);
|
||||
M_Tk_getPredStr(1, M_Tk_isnum);
|
||||
tok->type = tok_number;
|
||||
}
|
||||
else if(M_Tk_isidenti(ch))
|
||||
{
|
||||
M_Tk_getPredStr(0, M_Tk_isidenti);
|
||||
tok->type = tok_identi;
|
||||
}
|
||||
else
|
||||
{
|
||||
tok->text[0] = ch;
|
||||
tok->text[1] = '\0';
|
||||
tok->type = tok_chrseq;
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
|
@ -0,0 +1,100 @@
|
|||
// Copyright © 2017 Project Golan, all rights reserved.
|
||||
#ifndef m_token_h
|
||||
#define m_token_h
|
||||
|
||||
#include "m_types.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// Types ---------------------------------------------------------------------|
|
||||
|
||||
typedef enum M_tokty
|
||||
{
|
||||
tok_null, // No token
|
||||
|
||||
// Text sequences
|
||||
tok_chrseq, // Arbitrary character sequence
|
||||
tok_identi, // Identifier
|
||||
tok_number, // Number
|
||||
tok_string, // String < " > <characters> < " >
|
||||
tok_charac, // Character String < ' > <characters> < ' >
|
||||
tok_cmtlin, // Line comment < // > <characters> < \n >
|
||||
|
||||
// Single characters
|
||||
tok_lnend, // \n
|
||||
tok_semico, // ;
|
||||
tok_comma, // ,
|
||||
tok_bracko, // [
|
||||
tok_brackc, // ]
|
||||
tok_braceo, // {
|
||||
tok_bracec, // }
|
||||
tok_pareno, // (
|
||||
tok_parenc, // )
|
||||
|
||||
// Paired operators
|
||||
tok_eq, // =
|
||||
tok_eq2, // ==
|
||||
tok_tern, // ?
|
||||
tok_terneq, // ?=
|
||||
tok_div, // /
|
||||
tok_diveq, // /=
|
||||
tok_not, // !
|
||||
tok_neq, // !=
|
||||
tok_bnot, // ~
|
||||
tok_bneq, // ~=
|
||||
tok_mul, // *
|
||||
tok_muleq, // *=
|
||||
tok_at, // @
|
||||
tok_at2, // @@
|
||||
|
||||
// Tupled operators
|
||||
tok_lt, // <
|
||||
tok_lt2, // <<
|
||||
tok_le, // <=
|
||||
tok_gt, // >
|
||||
tok_gt2, // >>
|
||||
tok_ge, // >=
|
||||
tok_or, // |
|
||||
tok_or2, // ||
|
||||
tok_oreq, // |=
|
||||
tok_and, // &
|
||||
tok_and2, // &&
|
||||
tok_andeq, // &=
|
||||
tok_add, // +
|
||||
tok_add2, // ++
|
||||
tok_addeq, // +=
|
||||
tok_sub, // -
|
||||
tok_sub2, // --
|
||||
tok_subeq, // -=
|
||||
tok_mod, // %
|
||||
tok_mod2, // %%
|
||||
tok_modeq, // %=
|
||||
tok_xor, // ^
|
||||
tok_xor2, // ^^
|
||||
tok_xoreq, // ^=
|
||||
tok_col, // :
|
||||
tok_col2, // ::
|
||||
tok_coleq, // :=
|
||||
|
||||
// Misc
|
||||
tok_dot, // .
|
||||
tok_dot2, // ..
|
||||
tok_dot3, // ...
|
||||
tok_rarrow, // ->
|
||||
tok_eof, // End of file
|
||||
|
||||
tok_max
|
||||
} M_tokty;
|
||||
|
||||
typedef struct M_token
|
||||
{
|
||||
M_tokty type;
|
||||
int line;
|
||||
char text[1024];
|
||||
} M_token;
|
||||
|
||||
// Extern Functions ----------------------------------------------------------|
|
||||
|
||||
void M_Tk_Parse(FILE *fp, M_token *tok);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright © 2017 Project Golan, all rights reserved.
|
||||
#ifndef m_types_h
|
||||
#define m_types_h
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdfix.h>
|
||||
#undef fixed
|
||||
|
||||
#define M_countof(a) (sizeof(a) / sizeof(*a))
|
||||
|
||||
// Types ---------------------------------------------------------------------|
|
||||
|
||||
typedef short accum fixed; // Fixed
|
||||
typedef long fract lfrac; // Long Fractional
|
||||
typedef size_t msize; // Machine Size
|
||||
typedef ptrdiff_t mpdif; // Machine Pointer Difference
|
||||
typedef uint8_t mbyte; // Machine Byte
|
||||
typedef uint16_t hword; // Half Word
|
||||
typedef uint32_t mword; // Machine Word
|
||||
typedef uint64_t dword; // Double Word
|
||||
typedef uint96_t tword; // Triple Word
|
||||
typedef int8_t chara; // Character
|
||||
typedef int16_t int16; // Integer (16 bits)
|
||||
typedef int32_t integ; // Integer (Machine)
|
||||
typedef int64_t int64; // Integer (64 bits)
|
||||
typedef int96_t int96; // Integer (96 bits)
|
||||
typedef unsigned M_texid; // Texture ID
|
||||
|
||||
#endif
|
|
@ -0,0 +1,74 @@
|
|||
// Copyright © 2017 Project Golan, all rights reserved.
|
||||
#include "g_object.h"
|
||||
#include "m_types.h"
|
||||
|
||||
#include <Doominati.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// Static Functions ----------------------------------------------------------|
|
||||
|
||||
//
|
||||
// G_Player_Think
|
||||
//
|
||||
DGE_Callback static void G_Player_Think(DGE_Entity ent)
|
||||
{
|
||||
DGE_Object_RefAdd(ent.id);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(ent.health <= 0)
|
||||
break;
|
||||
|
||||
ent.vx = ent.vx + (fixed)DGE_GetInputAxis(0, DGE_Axis_X);
|
||||
ent.vy = ent.vy - (fixed)DGE_GetInputAxis(0, DGE_Axis_Y);
|
||||
|
||||
DGE_Task_Sleep(0, 1);
|
||||
}
|
||||
|
||||
DGE_Object_RefSub(ent.id);
|
||||
}
|
||||
|
||||
//
|
||||
// G_Player_Create
|
||||
//
|
||||
static DGE_Entity G_Player_Create(fixed x, fixed y)
|
||||
{
|
||||
DGE_Entity ent = {DGE_Entity_Create(0)};
|
||||
ent.x = x;
|
||||
ent.y = y;
|
||||
G_entty const *type;
|
||||
if((type = G_ObjDef_GetType("Player"))) {
|
||||
G_ObjDef_setupEntity(type, ent);
|
||||
G_ObjDef_createTask (type, ent);
|
||||
}
|
||||
return ent;
|
||||
}
|
||||
|
||||
// Extern Functions ----------------------------------------------------------|
|
||||
|
||||
//
|
||||
// main
|
||||
//
|
||||
[[__extern("asm")]] DGE_Callback
|
||||
void main(void)
|
||||
{
|
||||
printf("\n=====================\n"
|
||||
u8"オミ:影響の目 1.0\n"
|
||||
u8"Copyright © 2017 Project Golan, all rights reserved.\n\n");
|
||||
|
||||
DGE_SetVirtualResolution(640, 480);
|
||||
|
||||
printf("Loading object function table...\n");
|
||||
G_ObjDef_Init();
|
||||
G_ObjDef_loadFunc(G_Player_Think);
|
||||
|
||||
printf("Loading object definitions...\n");
|
||||
G_ObjDef_Load("objdefs.dod");
|
||||
|
||||
printf("Ready.\n");
|
||||
|
||||
G_Player_Create(32, 32);
|
||||
}
|
||||
|
||||
// EOF
|
Loading…
Reference in New Issue