Add initial code

master
Marrub 2017-09-20 11:42:57 -04:00
commit d1f04810bd
15 changed files with 1186 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
bin/*.ir
codedefs/*.bin
src_crap
src_oldtest
doc
sounds
sprites
textures

37
Makefile Normal file
View File

@ -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

1
bin/dummy Normal file
View File

@ -0,0 +1 @@

1
codedefs/dummy Normal file
View File

@ -0,0 +1 @@

4
objdefs.dod Normal file
View File

@ -0,0 +1,4 @@
// Copyright © 2017 Project Golan, all rights reserved.
include "objdefs/player.dod"
// EOF

15
objdefs/player.dod Normal file
View File

@ -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

611
src/g_objdef.c Normal file
View File

@ -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

65
src/g_object.h Normal file
View File

@ -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

23
src/m_darray.h Normal file
View File

@ -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

52
src/m_str.c Normal file
View File

@ -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

16
src/m_str.h Normal file
View File

@ -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

148
src/m_token.c Normal file
View File

@ -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

100
src/m_token.h Normal file
View File

@ -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

31
src/m_types.h Normal file
View File

@ -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

74
src/main.c Normal file
View File

@ -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