Now runs PLASMA code\!

This commit is contained in:
Martin Haye 2014-06-25 08:47:28 -07:00
parent 10f9d8640b
commit 786853a4a7
24 changed files with 5438 additions and 36 deletions

View File

@ -776,6 +776,7 @@ class PackPartitions
readCode("render", "src/raycast/build/render.b")
readCode("expand", "src/raycast/build/expand.b")
readCode("fontEngine", "src/font/build/fontEngine.b")
readCode("gameloop", "src/plasma/build/gameloop.b")
// We have only one font, for now at least.
println "Reading fonts."

View File

@ -26,17 +26,49 @@
<!-- Create build directory -->
<mkdir dir="${build.dir}"/>
<!-- Assemble all .s files -->
<apply executable="${ACME_TOOL}" dir="${src.dir}"
relative="true" parallel="false" failonerror="true" verbose="true">
<fileset dir="${src.dir}" includes="*.s"/>
<!-- Assemble the PLASMA vm -->
<apply executable="acme" dir="${src.dir}"
relative="true" parallel="true" failonerror="true" verbose="true">
<fileset dir="${src.dir}" includes="plvm02.s"/>
<arg line="${ASM_SETTINGS}"/>
<arg value="-o"/>
<arg value="${build.dir}/plvm02.system.sys#2000"/>
<srcfile/>
</apply>
<!-- Build the PLASMA compiler -->
<apply executable="cc" dir="${src.dir}"
relative="true" parallel="true" failonerror="true" verbose="true">
<fileset dir="${src.dir}" includes="*.c" excludes="plvm.c"/>
<arg value="-o"/>
<arg value="${build.dir}/plasm"/>
</apply>
<!-- Translate the game loop from PLASMA to ACME assembly code-->
<apply executable="${build.dir}/plasm" dir="${src.dir}"
relative="true" parallel="false" failonerror="true" verbose="true"
addsourcefile="false">
<fileset dir="${src.dir}" includes="gameloop.pla"/>
<arg value="-A"/>
<redirector logError="yes">
<!-- redirect STDIN; fileset collects relative to its dir, but we need -->
<!-- relative to basedir -->
<inputmapper type="glob" from="*" to="${src.dir}/*"/>
<!-- redirect STDOUT to file in dest-dir -->
<outputmapper id="out" type="glob" from="*.pla" to="${build.dir}/*.a"/>
</redirector>
</apply>
<!-- Assmeble the ACME code -->
<apply executable="acme" dir="${src.dir}"
relative="true" parallel="false" failonerror="true" verbose="true">
<fileset dir="${src.dir}" includes="gamestub.s"/>
<arg line="${ASM_SETTINGS}"/>
<arg value="-o"/>
<arg value="${build.dir}/gameloop.b"/>
<srcfile/>
</apply>
</target>
</project>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
INTERP = $03D0
LCRDEN = $C080
LCWTEN = $C081
ROMEN = $C082
LCRWEN = $C083
LCBNK2 = $00
LCBNK1 = $08
!SOURCE "plvm02zp.inc"
;*
;* MOVE CMD DOWN TO $1000-$2000
;*
LDA #<_CMDBEGIN
STA SRCL
LDA #>_CMDBEGIN
STA SRCH
LDY #$00
STY DSTL
LDA #$10
STA DSTH
- LDA (SRC),Y
STA (DST),Y
INY
BNE -
INC SRCH
INC DSTH
LDA DSTH
CMP #$20 ; STOP WHEN DST=$2000 REACHED
BNE -
LDA #<_CMDEND
STA SRCL
LDA #>_CMDEND
STA SRCH
;
; INIT VM ENVIRONMENT STACK POINTERS
;
LDA #$00 ; INIT FRAME POINTER
STA IFPL
LDA #$BF
STA IFPH
LDX #$FE ; INIT STACK POINTER (YES, $FE. SEE GETS)
TXS
LDX #ESTKSZ/2 ; INIT EVAL STACK INDEX
JMP $1000
_CMDBEGIN = *
!PSEUDOPC $1000 {
!SOURCE "cmd.a"
_CMDEND = *
}

View File

@ -0,0 +1,812 @@
#include <stdio.h>
#include <ctype.h>
#include "tokens.h"
#include "lex.h"
#include "symbols.h"
#include "codegen.h"
/*
* Symbol table and fixup information.
*/
static int consts = 0;
static int externs = 0;
static int globals = 0;
static int locals = 0;
static int predefs = 0;
static int defs = 0;
static int asmdefs = 0;
static int codetags = 0;
static int fixups = 0;
static char idconst_name[1024][17];
static int idconst_value[1024];
static char idglobal_name[1024][17];
static int idglobal_type[1024];
static int idglobal_tag[1024];
static int localsize = 0;
static char idlocal_name[128][17];
static int idlocal_type[128];
static int idlocal_offset[128];
static char fixup_size[2048];
static int fixup_type[2048];
static int fixup_tag[2048];
#define FIXUP_BYTE 0x00
#define FIXUP_WORD 0x80
int id_match(char *name, int len, char *id)
{
if (len == id[0])
{
if (len > 16) len = 16;
while (len--)
{
if (name[len] != id[1 + len])
return (0);
}
return (1);
}
return (0);
}
int idconst_lookup(char *name, int len)
{
int i;
for (i = 0; i < consts; i++)
if (id_match(name, len, &(idconst_name[i][0])))
return (i);
return (-1);
}
int idlocal_lookup(char *name, int len)
{
int i;
for (i = 0; i < locals; i++)
if (id_match(name, len, &(idlocal_name[i][0])))
return (i);
return (-1);
}
int idglobal_lookup(char *name, int len)
{
int i;
for (i = 0; i < globals; i++)
if (id_match(name, len, &(idglobal_name[i][0])))
return (i);
return (-1);
}
int idconst_add(char *name, int len, int value)
{
char c = name[len];
if (consts > 1024)
{
printf("Constant count overflow\n");
return (0);
}
name[len] = '\0';
emit_idconst(name, value);
name[len] = c;
idconst_name[consts][0] = len;
if (len > 16) len = 16;
while (len--)
idconst_name[consts][1 + len] = name[len];
idconst_value[consts] = value;
consts++;
return (1);
}
int idlocal_add(char *name, int len, int type, int size)
{
char c = name[len];
if (localsize > 255)
{
printf("Local variable size overflow\n");
return (0);
}
name[len] = '\0';
emit_idlocal(name, localsize);
name[len] = c;
idlocal_name[locals][0] = len;
if (len > 16) len = 16;
while (len--)
idlocal_name[locals][1 + len] = name[len];
idlocal_type[locals] = type | LOCAL_TYPE;
idlocal_offset[locals] = localsize;
localsize += size;
locals++;
return (1);
}
int idglobal_add(char *name, int len, int type, int size)
{
char c = name[len];
if (globals > 1024)
{
printf("Global variable count overflow\n");
return (0);
}
name[len] = '\0';
name[len] = c;
idglobal_name[globals][0] = len;
if (len > 16) len = 16;
while (len--)
idglobal_name[globals][1 + len] = name[len];
idglobal_type[globals] = type;
if (!(type & EXTERN_TYPE))
{
emit_idglobal(globals, size, name);
idglobal_tag[globals] = globals;
globals++;
}
else
{
printf("\t\t\t\t\t; %s -> X%03d\n", &idglobal_name[globals][1], externs);
idglobal_tag[globals++] = externs++;
}
return (1);
}
int id_add(char *name, int len, int type, int size)
{
return ((type & LOCAL_TYPE) ? idlocal_add(name, len, type, size) : idglobal_add(name, len, type, size));
}
int idfunc_add(char *name, int len, int type, int tag)
{
if (globals > 1024)
{
printf("Global variable count overflow\n");
return (0);
}
idglobal_name[globals][0] = len;
if (len > 16) len = 16;
while (len--)
idglobal_name[globals][1 + len] = name[len];
idglobal_type[globals] = type;
idglobal_tag[globals++] = tag;
if (type & EXTERN_TYPE)
printf("\t\t\t\t\t; %s -> X%03d\n", &idglobal_name[globals - 1][1], tag);
return (1);
}
int idfunc_set(char *name, int len, int type, int tag)
{
int i;
if (((i = idglobal_lookup(name, len)) >= 0) && (idglobal_type[i] & FUNC_TYPE))
{
idglobal_tag[i] = tag;
idglobal_type[i] = type;
return (type);
}
parse_error("Undeclared identifier");
return (0);
}
void idglobal_size(int type, int size, int constsize)
{
if (size > constsize)
emit_data(0, 0, 0, size - constsize);
else if (size)
emit_data(0, 0, 0, size);
}
int idlocal_size(void)
{
return (localsize);
}
void idlocal_reset(void)
{
locals = 0;
localsize = 2;
}
int id_tag(char *name, int len)
{
int i;
if ((i = idlocal_lookup(name, len)) >= 0)
return (idlocal_offset[i]);
if ((i = idglobal_lookup(name, len)) >= 0)
return (idglobal_tag[i]);
return (-1);
}
int id_const(char *name, int len)
{
int i;
if ((i = idconst_lookup(name, len)) >= 0)
return (idconst_value[i]);
parse_error("Undeclared constant");
return (0);
}
int id_type(char *name, int len)
{
int i;
if ((i = idconst_lookup(name, len)) >= 0)
return (CONST_TYPE);
if ((i = idlocal_lookup(name, len)) >= 0)
return (idlocal_type[i] | LOCAL_TYPE);
if ((i = idglobal_lookup(name, len)) >= 0)
return (idglobal_type[i]);
parse_error("Undeclared identifier");
return (0);
}
int tag_new(int type)
{
if (type & EXTERN_TYPE)
{
if (externs > 254)
parse_error("External variable count overflow\n");
return (externs++);
}
if (type & PREDEF_TYPE)
return (predefs++);
if (type & ASM_TYPE)
return (asmdefs++);
if (type & DEF_TYPE)
return (defs++);
if (type & BRANCH_TYPE)
return (codetags++);
return globals++;
}
int fixup_new(int tag, int type, int size)
{
fixup_tag[fixups] = tag;
fixup_type[fixups] = type;
fixup_size[fixups] = size;
return (fixups++);
}
/*
* Emit assembly code.
*/
#define BYTECODE_SEG 8
#define INIT 16
#define SYSFLAGS 32
static int outflags = 0;
static char *DB = ".BYTE";
static char *DW = ".WORD";
static char *DS = ".RES";
static char LBL = ':';
char *supper(char *s)
{
static char su[80];
int i;
for (i = 0; s[i]; i++)
su[i] = toupper(s[i]);
su[i] = '\0';
return su;
}
char *tag_string(int tag, int type)
{
static char str[16];
char t;
if (type & EXTERN_TYPE)
t = 'X';
else if (type & DEF_TYPE)
t = 'C';
else if (type & ASM_TYPE)
t = 'A';
else if (type & BRANCH_TYPE)
t = 'B';
else if (type & PREDEF_TYPE)
t = 'P';
else
t = 'D';
sprintf(str, "_%c%03d", t, tag);
return str;
}
void emit_dci(char *str, int len)
{
if (len--)
{
printf("\t; DCI STRING: %s\n", supper(str));
printf("\t%s\t$%02X", DB, toupper(*str++) | (len ? 0x80 : 0x00));
while (len--)
printf(",$%02X", toupper(*str++) | (len ? 0x80 : 0x00));
printf("\n");
}
}
void emit_flags(int flags)
{
outflags = flags;
if (outflags & ACME)
{
DB = "!BYTE";
DW = "!WORD";
DS = "!FILL";
LBL = ' ';
}
}
void emit_header(void)
{
if (outflags & ACME)
printf("; ACME COMPATIBLE OUTPUT\n");
else
printf("; CA65 COMPATIBLE OUTPUT\n");
if (outflags & MODULE)
{
printf("\t%s\t_SEGEND-_SEGBEGIN\t; LENGTH OF HEADER + CODE/DATA + BYTECODE SEGMENT\n", DW);
printf("_SEGBEGIN%c\n", LBL);
printf("\t%s\t$DA7E\t\t\t; MAGIC #\n", DW);
printf("\t%s\t_SYSFLAGS\t\t\t; SYSTEM FLAGS\n", DW);
printf("\t%s\t_SUBSEG\t\t\t; BYTECODE SUB-SEGMENT\n", DW);
printf("\t%s\t_DEFCNT\t\t\t; BYTECODE DEF COUNT\n", DW);
printf("\t%s\t_INIT\t\t\t; MODULE INITIALIZATION ROUTINE\n", DW);
}
else
{
printf("\tJMP\t_INIT\t\t\t; MODULE INITIALIZATION ROUTINE\n");
}
}
void emit_rld(void)
{
int i;
printf(";\n; RE-LOCATEABLE DICTIONARY\n;\n");
/*
* First emit the bytecode definition entrypoint information.
*/
for (i = 0; i < globals; i++)
if (!(idglobal_type[i] & EXTERN_TYPE) && (idglobal_type[i] & DEF_TYPE))
{
printf("\t%s\t$02\t\t\t; CODE TABLE FIXUP\n", DB);
printf("\t%s\t_C%03d\t\t\n", DW, idglobal_tag[i]);
printf("\t%s\t$00\n", DB);
}
/*
* Now emit the fixup table.
*/
for (i = 0; i < fixups; i++)
{
if (fixup_type[i] & EXTERN_TYPE)
{
printf("\t%s\t$%02X\t\t\t; EXTERNAL FIXUP\n", DB, 0x11 + fixup_size[i] & 0xFF);
printf("\t%s\t_F%03d-_SEGBEGIN\t\t\n", DW, i);
printf("\t%s\t%d\t\t\t; ESD INDEX\n", DB, fixup_tag[i]);
}
else
{
printf("\t%s\t$%02X\t\t\t; INTERNAL FIXUP\n", DB, 0x01 + fixup_size[i] & 0xFF);
printf("\t%s\t_F%03d-_SEGBEGIN\t\t\n", DW, i);
printf("\t%s\t$00\n", DB);
}
}
printf("\t%s\t$00\t\t\t; END OF RLD\n", DB);
}
void emit_esd(void)
{
int i;
printf(";\n; EXTERNAL/ENTRY SYMBOL DICTIONARY\n;\n");
for (i = 0; i < globals; i++)
{
if (idglobal_type[i] & EXTERN_TYPE)
{
emit_dci(&idglobal_name[i][1], idglobal_name[i][0]);
printf("\t%s\t$10\t\t\t; EXTERNAL SYMBOL FLAG\n", DB);
printf("\t%s\t%d\t\t\t; ESD INDEX\n", DW, idglobal_tag[i]);
}
else if (idglobal_type[i] & EXPORT_TYPE)
{
emit_dci(&idglobal_name[i][1], idglobal_name[i][0]);
printf("\t%s\t$08\t\t\t; ENTRY SYMBOL FLAG\n", DB);
printf("\t%s\t%s\t\t\n", DW, tag_string(idglobal_tag[i], idglobal_type[i]));
}
}
printf("\t%s\t$00\t\t\t; END OF ESD\n", DB);
}
void emit_trailer(void)
{
if (!(outflags & BYTECODE_SEG))
emit_bytecode_seg();
if (!(outflags & INIT))
printf("_INIT\t=\t0\n");
if (!(outflags & SYSFLAGS))
printf("_SYSFLAGS\t=\t0\n");
if (outflags & MODULE)
{
printf("_DEFCNT\t=\t%d\n", defs);
printf("_SEGEND%c\n", LBL);
emit_rld();
emit_esd();
}
}
void emit_moddep(char *name, int len)
{
if (name)
emit_dci(name, len);
else
printf("\t%s\t$00\t\t\t; END OF MODULE DEPENDENCIES\n", DB);
}
void emit_sysflags(int val)
{
printf("_SYSFLAGS\t=\t$%04X\t\t; SYSTEM FLAGS\n", val);
outflags |= SYSFLAGS;
}
void emit_bytecode_seg(void)
{
if ((outflags & MODULE) && !(outflags & BYTECODE_SEG))
printf("_SUBSEG%c\t\t\t\t; BYTECODE STARTS\n", LBL);
outflags |= BYTECODE_SEG;
}
void emit_comment(char *s)
{
printf("\t\t\t\t\t; %s\n", s);
}
void emit_asm(char *s)
{
printf("%s\n", s);
}
void emit_idlocal(char *name, int value)
{
printf("\t\t\t\t\t; %s -> [%d]\n", name, value);
}
void emit_idglobal(int tag, int size, char *name)
{
if (size == 0)
printf("_D%03d%c\t\t\t\t\t; %s\n", tag, LBL, name);
else
printf("_D%03d%c\t%s\t%d\t\t\t; %s\n", tag, LBL, DS, size, name);
}
void emit_idfunc(int tag, int type, char *name)
{
printf("%s%c\t\t\t\t\t; %s()\n", tag_string(tag, type), LBL, name);
}
void emit_idconst(char *name, int value)
{
printf("\t\t\t\t\t; %s = %d\n", name, value);
}
int emit_data(int vartype, int consttype, long constval, int constsize)
{
int datasize, i;
char *str;
if (consttype == 0)
{
datasize = constsize;
printf("\t%s\t$%02X\n", DS, constsize);
}
else if (consttype & STRING_TYPE)
{
datasize = constsize;
str = (char *)constval;
printf("\t%s\t$%02X\n", DB, --constsize);
while (constsize-- > 0)
{
printf("\t%s\t$%02X", DB, *str++);
for (i = 0; i < 7; i++)
{
if (constsize-- > 0)
printf(",$%02X", *str++);
else
break;
}
printf("\n");
}
}
else if (consttype & ADDR_TYPE)
{
if (vartype & WORD_TYPE)
{
int fixup = fixup_new(constval, consttype, FIXUP_WORD);
datasize = 2;
if (consttype & EXTERN_TYPE)
printf("_F%03d%c\t%s\t0\t\t\t; %s\n", fixup, LBL, DW, tag_string(constval, consttype));
else
printf("_F%03d%c\t%s\t%s\n", fixup, LBL, DW, tag_string(constval, consttype));
}
else
{
int fixup = fixup_new(constval, consttype, FIXUP_BYTE);
datasize = 1;
if (consttype & EXTERN_TYPE)
printf("_F%03d%c\t%s\t0\t\t\t; %s\n", fixup, LBL, DB, tag_string(constval, consttype));
else
printf("_F%03d%c\t%s\t%s\n", fixup, LBL, DB, tag_string(constval, consttype));
}
}
else
{
if (vartype & WORD_TYPE)
{
datasize = 2;
printf("\t%s\t$%04lX\n", DW, constval & 0xFFFF);
}
else
{
datasize = 1;
printf("\t%s\t$%02lX\n", DB, constval & 0xFF);
}
}
return (datasize);
}
void emit_def(char *name, int is_bytecode)
{
if (!(outflags & MODULE))
{
//printf("%s%c\n", name, LBL);
if (is_bytecode)
printf("\tJSR\tINTERP\n");
}
}
void emit_codetag(int tag)
{
printf("_B%03d%c\n", tag, LBL);
}
void emit_const(int cval)
{
if (cval == 0)
printf("\t%s\t$00\t\t\t; ZERO\n", DB);
else if (cval > 0 && cval < 256)
printf("\t%s\t$2A,$%02X\t\t\t; CB\t%d\n", DB, cval, cval);
else
printf("\t%s\t$2C,$%02X,$%02X\t\t; CW\t%d\n", DB, cval&0xFF,(cval>>8)&0xFF, cval);
}
void emit_lb(void)
{
printf("\t%s\t$60\t\t\t; LB\n", DB);
}
void emit_lw(void)
{
printf("\t%s\t$62\t\t\t; LW\n", DB);
}
void emit_llb(int index)
{
printf("\t%s\t$64,$%02X\t\t\t; LLB\t[%d]\n", DB, index, index);
}
void emit_llw(int index)
{
printf("\t%s\t$66,$%02X\t\t\t; LLW\t[%d]\n", DB, index, index);
}
void emit_lab(int tag, int offset, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$68\t\t\t; LAB\t%s+%d\n", DB, taglbl, offset);
printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl, offset);
}
void emit_law(int tag, int offset, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$6A\t\t\t; LAW\t%s+%d\n", DB, taglbl, offset);
printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl, offset);
}
void emit_sb(void)
{
printf("\t%s\t$70\t\t\t; SB\n", DB);
}
void emit_sw(void)
{
printf("\t%s\t$72\t\t\t; SW\n", DB);
}
void emit_slb(int index)
{
printf("\t%s\t$74,$%02X\t\t\t; SLB\t[%d]\n", DB, index, index);
}
void emit_slw(int index)
{
printf("\t%s\t$76,$%02X\t\t\t; SLW\t[%d]\n", DB, index, index);
}
void emit_dlb(int index)
{
printf("\t%s\t$6C,$%02X\t\t\t; DLB\t[%d]\n", DB, index, index);
}
void emit_dlw(int index)
{
printf("\t%s\t$6E,$%02X\t\t\t; DLW\t[%d]\n", DB, index, index);
}
void emit_sab(int tag, int offset, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$78\t\t\t; SAB\t%s+%d\n", DB, taglbl, offset);
printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl, offset);
}
void emit_saw(int tag, int offset, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$7A\t\t\t; SAW\t%s+%d\n", DB, taglbl, offset);
printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl, offset);
}
void emit_dab(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$7C\t\t\t; DAB\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_daw(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$7E\t\t\t; DAW\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_localaddr(int index)
{
printf("\t%s\t$28,$%02X\t\t\t; LLA\t[%d]\n", DB, index, index);
}
void emit_globaladdr(int tag, int offset, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$26\t\t\t; LA\t%s+%d\n", DB, taglbl, offset);
printf("_F%03d%c\t%s\t%s+%d\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "" : taglbl, offset);
}
void emit_indexbyte(void)
{
printf("\t%s\t$02\t\t\t; IDXB\n", DB);
}
void emit_indexword(void)
{
printf("\t%s\t$1E\t\t\t; IDXW\n", DB);
}
void emit_brfls(int tag)
{
printf("\t%s\t$4C\t\t\t; BRFLS\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_brtru(int tag)
{
printf("\t%s\t$4E\t\t\t; BRTRU\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_brnch(int tag)
{
printf("\t%s\t$50\t\t\t; BRNCH\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_breq(int tag)
{
printf("\t%s\t$3C\t\t\t; BREQ\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_brne(int tag)
{
printf("\t%s\t$3E\t\t\t; BRNE\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_brgt(int tag)
{
printf("\t%s\t$38\t\t\t; BRGT\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_brlt(int tag)
{
printf("\t%s\t$3A\t\t\t; BRLT\t_B%03d\n", DB, tag);
printf("\t%s\t_B%03d-*\n", DW, tag);
}
void emit_call(int tag, int type)
{
int fixup = fixup_new(tag, type, FIXUP_WORD);
char *taglbl = tag_string(tag, type);
printf("\t%s\t$54\t\t\t; CALL\t%s\n", DB, taglbl);
printf("_F%03d%c\t%s\t%s\t\t\n", fixup, LBL, DW, type & EXTERN_TYPE ? "0" : taglbl);
}
void emit_ical(void)
{
printf("\t%s\t$56\t\t\t; ICAL\n", DB);
}
void emit_leave(int framesize)
{
if (framesize > 2)
printf("\t%s\t$5A\t\t\t; LEAVE\n", DB);
else
printf("\t%s\t$5C\t\t\t; RET\n", DB);
}
void emit_ret(void)
{
printf("\t%s\t$5C\t\t\t; RET\n", DB);
}
void emit_enter(int framesize, int cparams)
{
if (framesize > 2)
printf("\t%s\t$58,$%02X,$%02X\t\t; ENTER\t%d,%d\n", DB, framesize, cparams, framesize, cparams);
}
void emit_start(void)
{
printf("_INIT%c\n", LBL);
outflags |= INIT;
defs++;
}
void emit_dup(void)
{
printf("\t%s\t$32\t\t\t; DUP\n", DB);
}
void emit_push(void)
{
printf("\t%s\t$34\t\t\t; PUSH\n", DB);
}
void emit_pull(void)
{
printf("\t%s\t$36\t\t\t; PULL\n", DB);
}
void emit_swap(void)
{
printf("\t%s\t$2E\t\t\t; SWAP\n", DB);
}
void emit_drop(void)
{
printf("\t%s\t$30\t\t\t; DROP\n", DB);
}
int emit_unaryop(int op)
{
switch (op)
{
case NEG_TOKEN:
printf("\t%s\t$10\t\t\t; NEG\n", DB);
break;
case COMP_TOKEN:
printf("\t%s\t$12\t\t\t; COMP\n", DB);
break;
case LOGIC_NOT_TOKEN:
printf("\t%s\t$20\t\t\t; NOT\n", DB);
break;
case INC_TOKEN:
printf("\t%s\t$0C\t\t\t; INCR\n", DB);
break;
case DEC_TOKEN:
printf("\t%s\t$0E\t\t\t; DECR\n", DB);
break;
case BPTR_TOKEN:
emit_lb();
break;
case WPTR_TOKEN:
emit_lw();
break;
default:
printf("emit_unaryop(%c) ???\n", op & 0x7F);
return (0);
}
return (1);
}
int emit_op(t_token op)
{
switch (op)
{
case MUL_TOKEN:
printf("\t%s\t$06\t\t\t; MUL\n", DB);
break;
case DIV_TOKEN:
printf("\t%s\t$08\t\t\t; DIV\n", DB);
break;
case MOD_TOKEN:
printf("\t%s\t$0A\t\t\t; MOD\n", DB);
break;
case ADD_TOKEN:
printf("\t%s\t$02\t\t\t; ADD\n", DB);
break;
case SUB_TOKEN:
printf("\t%s\t$04\t\t\t; SUB\n", DB);
break;
case SHL_TOKEN:
printf("\t%s\t$1A\t\t\t; SHL\n", DB);
break;
case SHR_TOKEN:
printf("\t%s\t$1C\t\t\t; SHR\n", DB);
break;
case AND_TOKEN:
printf("\t%s\t$14\t\t\t; AND\n", DB);
break;
case OR_TOKEN:
printf("\t%s\t$16\t\t\t; IOR\n", DB);
break;
case EOR_TOKEN:
printf("\t%s\t$18\t\t\t; XOR\n", DB);
break;
case EQ_TOKEN:
printf("\t%s\t$40\t\t\t; ISEQ\n", DB);
break;
case NE_TOKEN:
printf("\t%s\t$42\t\t\t; ISNE\n", DB);
break;
case GE_TOKEN:
printf("\t%s\t$48\t\t\t; ISGE\n", DB);
break;
case LT_TOKEN:
printf("\t%s\t$46\t\t\t; ISLT\n", DB);
break;
case GT_TOKEN:
printf("\t%s\t$44\t\t\t; ISGT\n", DB);
break;
case LE_TOKEN:
printf("\t%s\t$4A\t\t\t; ISLE\n", DB);
break;
case LOGIC_OR_TOKEN:
printf("\t%s\t$22\t\t\t; LOR\n", DB);
break;
case LOGIC_AND_TOKEN:
printf("\t%s\t$24\t\t\t; LAND\n", DB);
break;
case COMMA_TOKEN:
break;
default:
return (0);
}
return (1);
}

View File

@ -0,0 +1,59 @@
#define ACME 1
#define MODULE 2
void emit_flags(int flags);
void emit_header(void);
void emit_trailer(void);
void emit_moddep(char *name, int len);
void emit_sysflags(int val);
void emit_bytecode_seg(void);
void emit_comment(char *s);
void emit_asm(char *s);
void emit_idlocal(char *name, int value);
void emit_idglobal(int value, int size, char *name);
void emit_idfunc(int tag, int type, char *name);
void emit_idconst(char *name, int value);
void emit_def(char *name, int is_bytecode);
int emit_data(int vartype, int consttype, long constval, int constsize);
void emit_codetag(int tag);
void emit_const(int cval);
void emit_lb(void);
void emit_lw(void);
void emit_llb(int index);
void emit_llw(int index);
void emit_lab(int tag, int offset, int type);
void emit_law(int tag, int offset, int type);
void emit_sb(void);
void emit_sw(void);
void emit_slb(int index);
void emit_slw(int index);
void emit_dlb(int index);
void emit_dlw(int index);
void emit_sab(int tag, int offset, int type);
void emit_saw(int tag, int ofset, int type);
void emit_dab(int tag, int type);
void emit_daw(int tag, int type);
void emit_call(int tag, int type);
void emit_ical(void);
void emit_localaddr(int index);
void emit_globaladdr(int tag, int offset, int type);
void emit_indexbyte(void);
void emit_indexword(void);
int emit_unaryop(int op);
int emit_op(t_token op);
void emit_brtru(int tag);
void emit_brfls(int tag);
void emit_brgt(int tag);
void emit_brlt(int tag);
void emit_brne(int tag);
void emit_brnch(int tag);
void emit_swap(void);
void emit_dup(void);
void emit_push(void);
void emit_pull(void);
void emit_drop(void);
void emit_leave(int framesize);
void emit_ret(void);
void emit_enter(int framesize, int cparams);
void emit_start(void);
void emit_rld(void);
void emit_esd(void);

View File

@ -0,0 +1,80 @@
;
; Handy constants.
;
const FALSE = 0
const TRUE = !FALSE
;
; Hardware addresses.
;
const keyboard = $C000
const keystrobe = $C010
;
; call() return register structure.
;
const Accum = 0
const Xreg = 1
const Yreg = 2
const Preg = 3
;
; Processor Status (Preg) flag bits.
;
const Cflag = $01
const Zflag = $02
const Iflag = $04
const Dflag = $08
const Bflag = $10
const Vflag = $40
const Sflag = $80
;
; CALL 6502 ROUTINE
; CALL(ADDR, AREG, XREG, YREG, STATUS)
;
asm call
REGVALS = SRC
PHP
LDA ESTKL+4,X
STA TMPL
LDA ESTKH+4,X
STA TMPH
LDA ESTKL,X
PHA
LDA ESTKL+1,X
TAY
LDA ESTKL+3,X
PHA
LDA ESTKL+2,X
INX
INX
INX
INX
STX ESP
TAX
PLA
BIT ROMEN
PLP
JSR JMPTMP
PHP
BIT LCRDEN+LCBNK2
STA REGVALS+0
STX REGVALS+1
STY REGVALS+2
PLA
STA REGVALS+3
LDX ESP
LDA #<REGVALS
LDY #>REGVALS
STA ESTKL,X
STY ESTKH,X
PLP
RTS
JMPTMP JMP (TMP)
end
;
; Main loop.
;
call($FDF0, 65, 0, 0, 0)
call($FDF0, 65, 0, 0, 0)
call($FDF0, 65, 0, 0, 0)
call($FDF0, 13+128, 0, 0, 0)
done

View File

@ -0,0 +1,21 @@
INTERP = $03D0
LCRDEN = $C080
LCWTEN = $C081
ROMEN = $C082
LCRWEN = $C083
LCBNK2 = $00
LCBNK1 = $08
!SOURCE "plvm02zp.inc"
;
; INIT VM ENVIRONMENT STACK POINTERS
;
* = $B800
LDA #$00 ; INIT FRAME POINTER
STA IFPL
LDA #$BF
STA IFPH
LDX #$FE ; INIT STACK POINTER (YES, $FE. SEE GETS)
TXS
LDX #ESTKSZ/2 ; INIT EVAL STACK INDEX
!SOURCE "build/gameloop.a"
RTS

View File

@ -0,0 +1,8 @@
import STDLIB
predef puts
end
byte hellostr[] = "Hello, world.\n"
puts(@hellostr)
done

View File

@ -0,0 +1,364 @@
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "tokens.h"
#include "symbols.h"
char *statement, *scanpos, *tokenstr;
t_token scantoken, prevtoken;
int tokenlen;
long constval;
int lineno = 0;
t_token keywords[] = {
IF_TOKEN, 'I', 'F',
ELSE_TOKEN, 'E', 'L', 'S', 'E',
ELSEIF_TOKEN, 'E', 'L', 'S', 'I', 'F',
FIN_TOKEN, 'F', 'I', 'N',
WHILE_TOKEN, 'W', 'H', 'I', 'L', 'E',
LOOP_TOKEN, 'L', 'O', 'O', 'P',
CASE_TOKEN, 'W', 'H', 'E', 'N',
OF_TOKEN, 'I', 'S',
DEFAULT_TOKEN, 'O', 'T', 'H', 'E', 'R', 'W', 'I', 'S', 'E',
ENDCASE_TOKEN, 'W', 'E', 'N', 'D',
FOR_TOKEN, 'F', 'O', 'R',
TO_TOKEN, 'T', 'O',
DOWNTO_TOKEN, 'D', 'O', 'W', 'N', 'T', 'O',
STEP_TOKEN, 'S', 'T', 'E', 'P',
NEXT_TOKEN, 'N', 'E', 'X', 'T',
REPEAT_TOKEN, 'R', 'E', 'P', 'E', 'A', 'T',
UNTIL_TOKEN, 'U', 'N', 'T', 'I', 'L',
BREAK_TOKEN, 'B', 'R', 'E', 'A', 'K',
ASM_TOKEN, 'A', 'S', 'M',
DEF_TOKEN, 'D', 'E', 'F',
EXPORT_TOKEN, 'E', 'X', 'P', 'O', 'R', 'T',
IMPORT_TOKEN, 'I', 'M', 'P', 'O', 'R', 'T',
RETURN_TOKEN, 'R', 'E', 'T', 'U', 'R', 'N',
END_TOKEN, 'E', 'N', 'D',
EXIT_TOKEN, 'E', 'X', 'I', 'T',
DONE_TOKEN, 'D', 'O', 'N', 'E',
LOGIC_NOT_TOKEN, 'N', 'O', 'T',
LOGIC_AND_TOKEN, 'A', 'N', 'D',
LOGIC_OR_TOKEN, 'O', 'R',
BYTE_TOKEN, 'B', 'Y', 'T', 'E',
WORD_TOKEN, 'W', 'O', 'R', 'D',
CONST_TOKEN, 'C', 'O', 'N', 'S', 'T',
PREDEF_TOKEN, 'P', 'R', 'E', 'D', 'E', 'F',
SYSFLAGS_TOKEN, 'S', 'Y', 'S', 'F', 'L', 'A', 'G', 'S',
EOL_TOKEN
};
void parse_error(char *errormsg)
{
char *error_carrot = statement;
fprintf(stderr, "\n%4d: %s\n ", lineno, statement);
for (error_carrot = statement; error_carrot != tokenstr; error_carrot++)
putc(*error_carrot == '\t' ? '\t' : ' ', stderr);
fprintf(stderr, "^\nError: %s\n", errormsg);
exit(1);
}
t_token scan(void)
{
prevtoken = scantoken;
/*
* Skip whitespace.
*/
while (*scanpos && (*scanpos == ' ' || *scanpos == '\t')) scanpos++;
tokenstr = scanpos;
/*
* Scan for token based on first character.
*/
if (*scanpos == '\0' || *scanpos == '\n' || *scanpos == ';')
scantoken = EOL_TOKEN;
else if ((scanpos[0] >= 'a' && scanpos[0] <= 'z')
|| (scanpos[0] >= 'A' && scanpos[0] <= 'Z')
|| (scanpos[0] == '_'))
{
/*
* ID, either variable name or reserved word.
*/
int keypos = 0, matchpos = 0;
do
{
scanpos++;
}
while ((*scanpos >= 'a' && *scanpos <= 'z')
|| (*scanpos >= 'A' && *scanpos <= 'Z')
|| (*scanpos == '_')
|| (*scanpos >= '0' && *scanpos <= '9'));
scantoken = ID_TOKEN;
tokenlen = scanpos - tokenstr;
/*
* Search for matching keyword.
*/
while (keywords[keypos] != EOL_TOKEN)
{
while (keywords[keypos + 1 + matchpos] == toupper(tokenstr[matchpos]))
matchpos++;
if (IS_TOKEN(keywords[keypos + 1 + matchpos]) && (matchpos == tokenlen))
{
/*
* A match.
*/
scantoken = keywords[keypos];
break;
}
else
{
/*
* Find next keyword.
*/
keypos += matchpos + 1;
matchpos = 0;
while (!IS_TOKEN(keywords[keypos])) keypos++;
}
}
}
else if (scanpos[0] >= '0' && scanpos[0] <= '9')
{
/*
* Number constant.
*/
for (constval = 0; *scanpos >= '0' && *scanpos <= '9'; scanpos++)
constval = constval * 10 + *scanpos - '0';
scantoken = INT_TOKEN;
}
else if (scanpos[0] == '$')
{
/*
* Hexadecimal constant.
*/
constval = 0;
while (scanpos++)
{
if (*scanpos >= '0' && *scanpos <= '9')
constval = constval * 16 + *scanpos - '0';
else if (*scanpos >= 'A' && *scanpos <= 'F')
constval = constval * 16 + *scanpos - 'A' + 10;
else if (*scanpos >= 'a' && *scanpos <= 'f')
constval = constval * 16 + *scanpos - 'a' + 10;
else
break;
}
scantoken = INT_TOKEN;
}
else if (scanpos[0] == '\'')
{
/*
* Character constant.
*/
scantoken = CHAR_TOKEN;
if (scanpos[1] != '\\')
{
constval = scanpos[1];
if (scanpos[2] != '\'')
{
parse_error("Bad character constant");
return (-1);
}
scanpos += 3;
}
else
{
switch (scanpos[2])
{
case 'n':
constval = 0x0D;
break;
case 'r':
constval = '\r';
break;
case 't':
constval = '\t';
break;
case '\'':
constval = '\'';
break;
case '\\':
constval = '\\';
break;
case '0':
constval = '\0';
break;
default:
parse_error("Bad character constant");
return (-1);
}
if (scanpos[3] != '\'')
{
parse_error("Bad character constant");
return (-1);
}
scanpos += 4;
}
}
else if (scanpos[0] == '\"')
{
char *scanshift;
/*
* String constant.
*/
scantoken = STRING_TOKEN;
constval = (long)++scanpos;
while (*scanpos && *scanpos != '\"')
{
if (*scanpos == '\\')
{
switch (scanpos[1])
{
case 'n':
*scanpos = 0x0D;
break;
case 'r':
*scanpos = '\r';
break;
case 't':
*scanpos = '\t';
break;
case '\'':
*scanpos = '\'';
break;
case '\\':
*scanpos = '\\';
break;
case '0':
*scanpos = '\0';
break;
default:
parse_error("Bad string constant");
return (-1);
}
for (scanshift = scanpos + 1; *scanshift; scanshift++)
scanshift[0] = scanshift[1];
}
else
scanpos++;
}
if (!*scanpos++)
{
parse_error("Unterminated string");
return (-1);
}
}
else
{
/*
* Potential two and three character tokens.
*/
switch (scanpos[0])
{
case '>':
if (scanpos[1] == '>')
{
scantoken = SHR_TOKEN;
scanpos += 2;
}
else if (scanpos[1] == '=')
{
scantoken = GE_TOKEN;
scanpos += 2;
}
else
{
scantoken = GT_TOKEN;
scanpos++;
}
break;
case '<':
if (scanpos[1] == '<')
{
scantoken = SHL_TOKEN;
scanpos += 2;
}
else if (scanpos[1] == '=')
{
scantoken = LE_TOKEN;
scanpos += 2;
}
else if (scanpos[1] == '>')
{
scantoken = NE_TOKEN;
scanpos += 2;
}
else
{
scantoken = LT_TOKEN;
scanpos++;
}
break;
case '=':
if (scanpos[1] == '=')
{
scantoken = EQ_TOKEN;
scanpos += 2;
}
else
{
scantoken = SET_TOKEN;
scanpos++;
}
break;
case '+':
if (scanpos[1] == '+')
{
scantoken = INC_TOKEN;
scanpos += 2;
}
else
{
scantoken = ADD_TOKEN;
scanpos++;
}
break;
case '-':
if (scanpos[1] == '-')
{
scantoken = DEC_TOKEN;
scanpos += 2;
}
else
{
scantoken = SUB_TOKEN;
scanpos++;
}
break;
default:
/*
* Simple single character tokens.
*/
scantoken = TOKEN(*scanpos++);
}
}
tokenlen = scanpos - tokenstr;
return (scantoken);
}
void scan_rewind(char *backptr)
{
scanpos = backptr;
}
int scan_lookahead(void)
{
char *backpos = scanpos;
char *backstr = tokenstr;
int prevtoken = scantoken;
int prevlen = tokenlen;
int look = scan();
scanpos = backpos;
tokenstr = backstr;
scantoken = prevtoken;
tokenlen = prevlen;
return (look);
}
char inputline[512];
int next_line(void)
{
gets(inputline);
lineno++;
statement = inputline;
scanpos = inputline;
scantoken = EOL_TOKEN;
scan();
printf("; %03d: %s\n", lineno, inputline);
return (1);
}

View File

@ -0,0 +1,10 @@
extern char *statement, *scanpos, *tokenstr;
extern t_token scantoken, prevtoken;
extern int tokenlen;
extern long constval;
extern char inputline[];
void parse_error(char *errormsg);
int next_line(void);
void scan_rewind(char *backptr);
int scan_lookahead(void);
t_token scan(void);

View File

@ -0,0 +1,60 @@
.SUFFIXES =
AFLAGS = -o $@
LFLAGS = -C default.cfg
PLVM = plvm
PLVM02 = PLASMA.SYSTEM\#FF2000
CMD = CMD\#FF2000
PLASM = plasm
INCS = tokens.h symbols.h lex.h parse.h codegen.h
OBJS = plasm.c parse.o lex.o codegen.o
#
# Image filetypes for Virtual ][
#
PLATYPE = .\$$ED
BINTYPE = .BIN
SYSTYPE = .SYS
TXTTYPE = .TXT
#
# Image filetypes for CiderPress
#
#PLATYPE = \#ed0000
#BINTYPE = \#060000
#SYSTYPE = \#ff0000
#TXTTYPE = \#040000
all: $(PLASM) $(PLVM) $(PLVM02) $(CMD)
clean:
-rm *.o *~ *.a *FE1000 $(PLVM02) $(CMD) $(PLASM) $(PLVM)
$(PLASM): $(OBJS) $(INCS)
cc $(OBJS) -o $(PLASM)
$(PLVM): plvm.c
cc plvm.c -o $(PLVM)
$(PLVM02): plvm02.s
acme -o $(PLVM02) plvm02.s
$(CMD): cmd.pla cmdstub.s $(PLVM) $(PLASM)
./$(PLASM) -A < cmd.pla > cmd.a
acme --setpc 8192 -o $(CMD) cmdstub.s
TESTLIB\#FE1000: testlib.pla $(PLVM) $(PLASM)
m4 < testlib.pla |./$(PLASM) -AM > testlib.a
acme --setpc 4094 -o TESTLIB\#FE1000 testlib.a
test: test.pla TESTLIB\#FE1000 $(PLVM) $(PLASM)
m4 < test.pla | ./$(PLASM) -AM > test.a
acme --setpc 4094 -o TEST\#FE1000 test.a
./$(PLVM) TEST
debug: test.pla TESTLIB $(PLVM) $(PLASM)
m4 < test.pla | ./$(PLASM) -AM > test.a
acme --setpc 4094 -o TEST\#FE1000 test.a
./$(PLVM) -s TEST MAIN
hello: hello.pla $(PLVM) $(PLASM)
m4 < hello.pla | ./$(PLASM) -AM > hello.a
acme --setpc 4094 -o HELLO\#FE1000 hello.a
./$(PLVM) HELLO

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
int parse_module(void);

View File

@ -0,0 +1,35 @@
#include <stdio.h>
#include "tokens.h"
#include "lex.h"
#include "codegen.h"
#include "parse.h"
int main(int argc, char **argv)
{
int j, i, flags = 0;
for (i = 1; i < argc; i++)
{
if (argv[i][0] == '-')
{
j = 1;
while (argv[i][j])
{
switch(argv[i][j++])
{
case 'A':
flags |= ACME;
break;
case 'M':
flags |= MODULE;
break;
}
}
}
}
emit_flags(flags);
if (parse_module())
{
fprintf(stderr, "Compilation complete.\n");
}
return (0);
}

View File

@ -0,0 +1,928 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
typedef unsigned char code;
typedef unsigned char byte;
typedef signed short word;
typedef unsigned short uword;
typedef unsigned short address;
/*
* Debug
*/
int show_state = 0;
/*
* Bytecode memory
*/
#define BYTE_PTR(bp) ((byte)((bp)[0]))
#define WORD_PTR(bp) ((word)((bp)[0] | ((bp)[1] << 8)))
#define UWORD_PTR(bp) ((uword)((bp)[0] | ((bp)[1] << 8)))
#define TO_UWORD(w) ((uword)((w)))
#define MOD_ADDR 0x1000
#define DEF_CALL 0x0800
#define DEF_CALLSZ 0x0800
#define DEF_ENTRYSZ 6
#define MEM_SIZE 65536
byte mem_data[MEM_SIZE];
uword sp = 0x01FE, fp = 0xFFFF, heap = 0x0200, deftbl = DEF_CALL, lastdef = DEF_CALL;
#define EVAL_STACKSZ 16
#define PUSH(v) (*(--esp))=(v)
#define POP ((word)(*(esp++)))
#define UPOP ((uword)(*(esp++)))
#define TOS (esp[0])
word eval_stack[EVAL_STACKSZ];
word *esp = eval_stack + EVAL_STACKSZ;
#define SYMTBLSZ 1024
#define SYMSZ 16
#define MODTBLSZ 128
#define MODSZ 16
#define MODLSTSZ 32
byte symtbl[SYMTBLSZ];
byte *lastsym = symtbl;
byte modtbl[MODTBLSZ];
byte *lastmod = modtbl;
/*
* Predef.
*/
void interp(code *ip);
/*
* Utility routines.
*
* A DCI string is one that has the high bit set for every character except the last.
* More efficient than C or Pascal strings.
*/
int dcitos(byte *dci, char *str)
{
int len = 0;
do
str[len] = *dci & 0x7F;
while ((len++ < 16) && (*dci++ & 0x80));
str[len] = 0;
return len;
}
int stodci(char *str, byte *dci)
{
int len = 0;
do
dci[len] = toupper(*str) | 0x80;
while (*str++ && (len++ < 16));
dci[len - 1] &= 0x7F;
return len;
}
/*
* Heap routines.
*/
uword avail_heap(void)
{
return fp - heap;
}
uword alloc_heap(int size)
{
uword addr = heap;
heap += size;
if (heap >= fp)
{
printf("Error: heap/frame collision.\n");
exit (1);
}
return addr;
}
uword free_heap(int size)
{
heap -= size;
return fp - heap;
}
uword mark_heap(void)
{
return heap;
}
uword release_heap(uword newheap)
{
heap = newheap;
return fp - heap;
}
/*
* DCI table routines,
*/
void dump_tbl(byte *tbl)
{
int len;
byte *entbl;
while (*tbl)
{
len = 0;
while (*tbl & 0x80)
{
putchar(*tbl++ & 0x7F);
len++;
}
putchar(*tbl++);
putchar(':');
while (len++ < 15)
putchar(' ');
printf("$%04X\n", tbl[0] | (tbl[1] << 8));
tbl += 2;
}
}
uword lookup_tbl(byte *dci, byte *tbl)
{
char str[20];
byte *match, *entry = tbl;
while (*entry)
{
match = dci;
while (*entry == *match)
{
if (!(*entry & 0x80))
return entry[1] | (entry[2] << 8);
entry++;
match++;
}
while (*entry++ & 0x80);
entry += 2;
}
dcitos(dci, str);
printf("\nError: symbols %s not found in symbol table.\n", str);
return 0;
}
uword add_tbl(byte *dci, int val, byte **last)
{
while (*dci & 0x80)
*(*last)++ = *dci++;
*(*last)++ = *dci++;
*(*last)++ = val;
*(*last)++ = val >> 8;
return 0;
}
/*
* Symbol table routines.
*/
void dump_sym(void)
{
printf("\nSystem Symbol Table:\n");
dump_tbl(symtbl);
}
uword lookup_sym(byte *sym)
{
return lookup_tbl(sym, symtbl);
}
uword add_sym(byte *sym, int addr)
{
return add_tbl(sym, addr, &lastsym);
}
/*
* Module routines.
*/
void dump_mod(void)
{
printf("\nSystem Module Table:\n");
dump_tbl(modtbl);
}
uword lookup_mod(byte *mod)
{
return lookup_tbl(mod, modtbl);
}
uword add_mod(byte *mod, int addr)
{
return add_tbl(mod, addr, &lastmod);
}
uword defcall_add(int bank, int addr)
{
mem_data[lastdef] = bank ? 2 : 1;
mem_data[lastdef + 1] = addr;
mem_data[lastdef + 2] = addr >> 8;
return lastdef++;
}
uword def_lookup(byte *cdd, int defaddr)
{
int i, calldef = 0;
for (i = 0; cdd[i * 4] == 0x02; i++)
{
if ((cdd[i * 4 + 1] | (cdd[i * 4 + 2] << 8)) == defaddr)
{
calldef = cdd + i * 4 - mem_data;
break;
}
}
return calldef;
}
uword extern_lookup(byte *esd, int index)
{
byte *sym;
char string[32];
while (*esd)
{
sym = esd;
esd += dcitos(esd, string);
if ((esd[0] & 0x10) && (esd[1] == index))
return lookup_sym(sym);
esd += 3;
}
printf("\nError: extern index %d not found in ESD.\n", index);
return 0;
}
int load_mod(byte *mod)
{
uword modsize, hdrlen, len, end, magic, bytecode, fixup, addr, sysflags, defcnt = 0, init = 0, modaddr = mark_heap();
word modfix;
byte *moddep, *rld, *esd, *cdd, *sym;
byte header[128];
int fd;
char filename[48], string[17];
dcitos(mod, filename);
printf("Load module %s\n", filename);
if (strlen(filename) < 8 || (filename[strlen(filename) - 7] != '#'))
strcat(filename, "#FE1000");
fd = open(filename, O_RDONLY, 0);
if ((fd > 0) && (len = read(fd, header, 128)) > 0)
{
moddep = header + 1;
modsize = header[0] | (header[1] << 8);
magic = header[2] | (header[3] << 8);
if (magic == 0xDA7E)
{
/*
* This is a relocatable bytecode module.
*/
sysflags = header[4] | (header[5] << 8);
bytecode = header[6] | (header[7] << 8);
defcnt = header[8] | (header[9] << 8);
init = header[10] | (header[11] << 8);
moddep = header + 12;
/*
* Load module dependencies.
*/
while (*moddep)
{
if (lookup_mod(moddep) == 0)
{
if (fd)
{
close(fd);
fd = 0;
}
load_mod(moddep);
}
moddep += dcitos(moddep, string);
}
if (fd == 0)
{
fd = open(filename, O_RDONLY, 0);
len = read(fd, header, 128);
}
}
/*
* Alloc heap space for relocated module (data + bytecode).
*/
moddep += 1;
hdrlen = moddep - header;
len -= hdrlen;
modaddr = mark_heap();
end = modaddr + len;
/*
* Read in remainder of module into memory for fixups.
*/
memcpy(mem_data + modaddr, moddep, len);
while ((len = read(fd, mem_data + end, 4096)) > 0)
end += len;
close(fd);
/*
* Apply all fixups and symbol import/export.
*/
modfix = modaddr - hdrlen + 2; // - MOD_ADDR;
bytecode += modfix - MOD_ADDR;
end = modaddr - hdrlen + modsize + 2;
rld = mem_data + end; // Re-Locatable Directory
esd = rld; // Extern+Entry Symbol Directory
while (*esd != 0x00) // Scan to end of RLD
esd += 4;
esd++;
cdd = rld;
if (show_state)
{
/*
* Dump different parts of module.
*/
printf("Module load addr: $%04X\n", modaddr);
printf("Module size: %d\n", end - modaddr + hdrlen);
printf("Module code+data size: %d\n", modsize);
printf("Module magic: $%04X\n", magic);
printf("Module sysflags: $%04X\n", sysflags);
printf("Module bytecode: $%04X\n", bytecode);
printf("Module def count: $%04X\n", defcnt);
printf("Module init: $%04X\n", init ? init + modfix - MOD_ADDR : 0);
}
/*
* Add module to symbol table.
*/
add_mod(mod, modaddr);
/*
* Print out the Re-Location Dictionary.
*/
if (show_state)
printf("\nRe-Location Dictionary:\n");
while (*rld)
{
if (rld[0] == 0x02)
{
if (show_state) printf("\tDEF CODE");
addr = rld[1] | (rld[2] << 8);
addr += modfix - MOD_ADDR;
rld[1] = addr;
rld[2] = addr >> 8;
end = rld - mem_data + 4;
}
else
{
addr = rld[1] | (rld[2] << 8);
if (addr > 12)
{
addr += modfix;
if (rld[0] & 0x80)
fixup = (mem_data[addr] | (mem_data[addr + 1] << 8));
else
fixup = mem_data[addr];
if (rld[0] & 0x10)
{
if (show_state) printf("\tEXTERN[$%02X] ", rld[3]);
fixup += extern_lookup(esd, rld[3]);
}
else
{
fixup += modfix - MOD_ADDR;
if (fixup >= bytecode)
{
/*
* Replace with call def dictionary.
*/
if (show_state) printf("\tDEF[$%04X->", fixup);
fixup = def_lookup(cdd, fixup);
if (show_state) printf("$%04X] ", fixup);
}
else
if (show_state) printf("\tINTERN ");
}
if (rld[0] & 0x80)
{
if (show_state) printf("WORD");
mem_data[addr] = fixup;
mem_data[addr + 1] = fixup >> 8;
}
else
{
if (show_state) printf("BYTE");
mem_data[addr] = fixup;
}
}
else
{
if (show_state) printf("\tIGNORE (HDR) ");
}
}
if (show_state) printf("@$%04X\n", addr);
rld += 4;
}
if (show_state) printf("\nExternal/Entry Symbol Directory:\n");
while (*esd)
{
sym = esd;
esd += dcitos(esd, string);
if (esd[0] & 0x10)
{
if (show_state) printf("\tIMPORT %s[$%02X]\n", string, esd[1]);
}
else if (esd[0] & 0x08)
{
addr = esd[1] | (esd[2] << 8);
addr += modfix - MOD_ADDR;
if (show_state) printf("\tEXPORT %s@$%04X\n", string, addr);
if (addr >= bytecode)
addr = def_lookup(cdd, addr);
add_sym(sym, addr);
}
esd += 3;
}
}
else
{
printf("Error: Unable to load module %s\n", filename);
exit (1);
}
/*
* Reserve heap space for relocated module.
*/
alloc_heap(end - modaddr);
/*
* Call init routine.
*/
if (init)
{
interp(mem_data + init + modfix - MOD_ADDR);
// release_heap(init + modfix - MOD_ADDR); // Free up init code
return POP;
}
return 0;
}
void interp(code *ip);
void call(uword pc)
{
unsigned int i, s;
char c, sz[64];
if (show_state)
printf("\nCall code:$%02X\n", mem_data[pc]);
switch (mem_data[pc++])
{
case 0: // NULL call
printf("NULL call code\n");
break;
case 1: // BYTECODE in mem_code
//interp(mem_code + (mem_data[pc] + (mem_data[pc + 1] << 8)));
break;
case 2: // BYTECODE in mem_data
interp(mem_data + (mem_data[pc] + (mem_data[pc + 1] << 8)));
break;
case 3: // LIBRARY STDLIB::PUTC
c = POP;
if (c == 0x0D)
c = '\n';
putchar(c);
PUSH(0);
break;
case 4: // LIBRARY STDLIB::PUTS
s = POP;
i = mem_data[s++];
PUSH(i);
while (i--)
{
c = mem_data[s++];
if (c == 0x0D)
c = '\n';
putchar(c);
}
break;
case 5: // LIBRARY STDLIB::PUTSZ
s = POP;
while ((c = mem_data[s++]))
{
if (c == 0x0D)
c = '\n';
putchar(c);
}
PUSH(0);
break;
case 6: // LIBRARY STDLIB::GETC
PUSH(getchar());
break;
case 7: // LIBRARY STDLIB::GETS
gets(sz);
for (i = 0; sz[i]; i++)
mem_data[0x200 + i] = sz[i];
mem_data[0x200 + i] = 0;
mem_data[0x1FF] = i;
PUSH(i);
break;
case 8: // LIBRARY STDLIB::PUTNL
putchar('\n');
fflush(stdout);
PUSH(0);
break;
default:
printf("\nBad call code:$%02X\n", mem_data[pc - 1]);
exit(1);
}
}
/*
* OPCODE TABLE
*
OPTBL: DW ZERO,ADD,SUB,MUL,DIV,MOD,INCR,DECR ; 00 02 04 06 08 0A 0C 0E
DW NEG,COMP,AND,IOR,XOR,SHL,SHR,IDXW ; 10 12 14 16 18 1A 1C 1E
DW NOT,LOR,LAND,LA,LLA,CB,CW,SWAP ; 20 22 24 26 28 2A 2C 2E
DW DROP,DUP,PUSH,PULL,BRGT,BRLT,BREQ,BRNE ; 30 32 34 36 38 3A 3C 3E
DW ISEQ,ISNE,ISGT,ISLT,ISGE,ISLE,BRFLS,BRTRU ; 40 42 44 46 48 4A 4C 4E
DW BRNCH,IBRNCH,CALL,ICAL,ENTER,LEAVE,RET,??? ; 50 52 54 56 58 5A 5C 5E
DW LB,LW,LLB,LLW,LAB,LAW,DLB,DLW ; 60 62 64 66 68 6A 6C 6E
DW SB,SW,SLB,SLW,SAB,SAW,DAB,DAW ; 70 72 74 76 78 7A 7C 7E
*/
void interp(code *ip)
{
int val, ea, frmsz, parmcnt;
while (1)
{
if (show_state)
{
char cmdline[16];
word *dsp = &eval_stack[EVAL_STACKSZ - 1];
printf("$%04X: $%02X [ ", ip - mem_data, *ip);
while (dsp >= esp)
printf("$%04X ", (*dsp--) & 0xFFFF);
printf("]\n");
gets(cmdline);
}
switch (*ip++)
{
/*
* 0x00-0x0F
*/
case 0x00: // ZERO : TOS = 0
PUSH(0);
break;
case 0x02: // ADD : TOS = TOS + TOS-1
val = POP;
ea = POP;
PUSH(ea + val);
break;
case 0x04: // SUB : TOS = TOS-1 - TOS
val = POP;
ea = POP;
PUSH(ea - val);
break;
case 0x06: // MUL : TOS = TOS * TOS-1
val = POP;
ea = POP;
PUSH(ea * val);
break;
case 0x08: // DIV : TOS = TOS-1 / TOS
val = POP;
ea = POP;
PUSH(ea / val);
break;
case 0x0A: // MOD : TOS = TOS-1 % TOS
val = POP;
ea = POP;
PUSH(ea % val);
break;
case 0x0C: // INCR : TOS = TOS + 1
TOS++;;
break;
case 0x0E: // DECR : TOS = TOS - 1
TOS--;
break;
/*
* 0x10-0x1F
*/
case 0x10: // NEG : TOS = -TOS
TOS = -TOS;
break;
case 0x12: // COMP : TOS = ~TOS
TOS = ~TOS;
break;
case 0x14: // AND : TOS = TOS & TOS-1
val = POP;
ea = POP;
PUSH(ea & val);
break;
case 0x16: // IOR : TOS = TOS ! TOS-1
val = POP;
ea = POP;
PUSH(ea | val);
break;
case 0x18: // XOR : TOS = TOS ^ TOS-1
val = POP;
ea = POP;
PUSH(ea ^ val);
break;
case 0x1A: // SHL : TOS = TOS-1 << TOS
val = POP;
ea = POP;
PUSH(ea << val);
break;
case 0x1C: // SHR : TOS = TOS-1 >> TOS
val = POP;
ea = POP;
PUSH(ea >> val);
break;
case 0x1E: // IDXW : TOS = TOS * 2
TOS *= 2;
break;
/*
* 0x20-0x2F
*/
case 0x20: // NOT : TOS = !TOS
TOS = !TOS;
break;
case 0x22: // LOR : TOS = TOS || TOS-1
val = POP;
ea = POP;
PUSH(ea || val);
break;
case 0x24: // LAND : TOS = TOS && TOS-1
val = POP;
ea = POP;
PUSH(ea && val);
break;
case 0x26: // LA : TOS = @VAR ; equivalent to CW ADDRESSOF(VAR)
PUSH(WORD_PTR(ip));
ip += 2;
break;
case 0x28: // LLA : TOS = @LOCALVAR ; equivalent to CW FRAMEPTR+OFFSET(LOCALVAR)
PUSH(fp + BYTE_PTR(ip));
ip++;
break;
case 0x2A: // CB : TOS = CONSTANTBYTE (IP)
PUSH(BYTE_PTR(ip));
ip++;
break;
case 0x2C: // CW : TOS = CONSTANTWORD (IP)
PUSH(WORD_PTR(ip));
ip += 2;
break;
case 0x2E: // SWAP : TOS = TOS-1, TOS-1 = TOS
val = POP;
ea = POP;
PUSH(val);
PUSH(ea);
break;
/*
* 0x30-0x3F
*/
case 0x30: // DROP : TOS =
POP;
break;
case 0x32: // DUP : TOS = TOS
val = TOS;
PUSH(val);
break;
case 0x34: // PUSH : TOSP = TOS
val = POP;
mem_data[sp--] = val >> 8;
mem_data[sp--] = val;
break;
case 0x36: // PULL : TOS = TOSP
PUSH(mem_data[sp] | (mem_data[sp + 1] << 8));
sp += 2;
break;
case 0x38: // BRGT : TOS-1 > TOS ? IP += (IP)
val = POP;
if (TOS > val)
ip += WORD_PTR(ip);
else
ip += 2;
break;
case 0x3A: // BRLT : TOS-1 < TOS ? IP += (IP)
val = POP;
if (TOS < val)
ip += WORD_PTR(ip);
else
ip += 2;
break;
case 0x3C: // BREQ : TOS == TOS-1 ? IP += (IP)
val = POP;
if (TOS == val)
ip += WORD_PTR(ip);
else
ip += 2;
break;
case 0x3E: // BRNE : TOS != TOS-1 ? IP += (IP)
val = POP;
if (TOS != val)
ip += WORD_PTR(ip);
else
ip += 2;
break;
/*
* 0x40-0x4F
*/
case 0x40: // ISEQ : TOS = TOS == TOS-1
val = POP;
ea = POP;
PUSH((ea == val) ? -1 : 0);
break;
case 0x42: // ISNE : TOS = TOS != TOS-1
val = POP;
ea = POP;
PUSH((ea != val) ? -1 : 0);
break;
case 0x44: // ISGT : TOS = TOS-1 > TOS
val = POP;
ea = POP;
PUSH((ea > val) ? -1 : 0);
break;
case 0x46: // ISLT : TOS = TOS-1 < TOS
val = POP;
ea = POP;
PUSH((ea < val) ? -1 : 0);
break;
case 0x48: // ISGE : TOS = TOS-1 >= TOS
val = POP;
ea = POP;
PUSH((ea >= val) ? -1 : 0);
break;
case 0x4A: // ISLE : TOS = TOS-1 <= TOS
val = POP;
ea = POP;
PUSH((ea <= val) ? -1 : 0);
break;
case 0x4C: // BRFLS : !TOS ? IP += (IP)
if (!POP)
ip += WORD_PTR(ip) ;
else
ip += 2;
break;
case 0x4E: // BRTRU : TOS ? IP += (IP)
if (POP)
ip += WORD_PTR(ip);
else
ip += 2;
break;
/*
* 0x50-0x5F
*/
case 0x50: // BRNCH : IP += (IP)
ip += WORD_PTR(ip);
break;
case 0x52: // IBRNCH : IP += TOS
ip += POP;
break;
case 0x54: // CALL : TOFP = IP, IP = (IP) ; call
call(UWORD_PTR(ip));
ip += 2;
break;
case 0x56: // ICALL : IP = TOS ; indirect call
ea = UPOP;
call(ea);
break;
case 0x58: // ENTER : NEW FRAME, FOREACH PARAM LOCALVAR = TOS
frmsz = BYTE_PTR(ip);
ip++;
mem_data[fp - frmsz] = fp;
mem_data[fp - frmsz + 1] = fp >> 8;
if (show_state)
printf("< $%04X: $%04X > ", fp - frmsz, fp);
fp -= frmsz;
parmcnt = BYTE_PTR(ip);
ip++;
while (parmcnt--)
{
val = POP;
mem_data[fp + parmcnt * 2 + 2] = val;
mem_data[fp + parmcnt * 2 + 3] = val >> 8;
if (show_state)
printf("< $%04X: $%04X > ", fp + parmcnt * 2 + 2, mem_data[fp + parmcnt * 2 + 2] | (mem_data[fp + parmcnt * 2 + 3] >> 8));
}
if (show_state)
printf("\n");
break;
case 0x5A: // LEAVE : DEL FRAME, IP = TOFP
fp = mem_data[fp] | (mem_data[fp + 1] << 8);
case 0x5C: // RET : IP = TOFP
return;
case 0x5E: // ???
break;
/*
* 0x60-0x6F
*/
case 0x60: // LB : TOS = BYTE (TOS)
ea = TO_UWORD(POP);
PUSH(mem_data[ea]);
break;
case 0x62: // LW : TOS = WORD (TOS)
ea = UPOP;
PUSH(mem_data[ea] | (mem_data[ea + 1] << 8));
break;
case 0x64: // LLB : TOS = LOCALBYTE [IP]
PUSH(mem_data[TO_UWORD(fp + BYTE_PTR(ip))]);
ip++;
break;
case 0x66: // LLW : TOS = LOCALWORD [IP]
ea = TO_UWORD(fp + BYTE_PTR(ip));
PUSH(mem_data[ea] | (mem_data[ea + 1] << 8));
ip++;
break;
case 0x68: // LAB : TOS = BYTE (IP)
PUSH(mem_data[UWORD_PTR(ip)]);
ip += 2;
break;
case 0x6A: // LAW : TOS = WORD (IP)
ea = UWORD_PTR(ip);
PUSH(mem_data[ea] | (mem_data[ea + 1] << 8));
ip += 2;
break;
case 0x6C: // DLB : TOS = TOS, LOCALBYTE [IP] = TOS
mem_data[TO_UWORD(fp + BYTE_PTR(ip))] = TOS;
ip++;
break;
case 0x6E: // DLW : TOS = TOS, LOCALWORD [IP] = TOS
ea = TO_UWORD(fp + BYTE_PTR(ip));
mem_data[ea] = TOS;
mem_data[ea + 1] = TOS >> 8;
ip++;
break;
/*
* 0x70-0x7F
*/
case 0x70: // SB : BYTE (TOS) = TOS-1
val = POP;
ea = UPOP;
mem_data[ea] = val;
break;
case 0x72: // SW : WORD (TOS) = TOS-1
val = POP;
ea = UPOP;
mem_data[ea] = val;
mem_data[ea + 1] = val >> 8;
break;
case 0x74: // SLB : LOCALBYTE [TOS] = TOS-1
mem_data[TO_UWORD(fp + BYTE_PTR(ip))] = POP;
ip++;
break;
case 0x76: // SLW : LOCALWORD [TOS] = TOS-1
ea = TO_UWORD(fp + BYTE_PTR(ip));
val = POP;
mem_data[ea] = val;
mem_data[ea + 1] = val >> 8;
ip++;
break;
case 0x78: // SAB : BYTE (IP) = TOS
mem_data[UWORD_PTR(ip)] = POP;
ip += 2;
break;
case 0x7A: // SAW : WORD (IP) = TOS
ea = UWORD_PTR(ip);
val = POP;
mem_data[ea] = val;
mem_data[ea + 1] = val >> 8;
ip += 2;
break;
case 0x7C: // DAB : TOS = TOS, BYTE (IP) = TOS
mem_data[UWORD_PTR(ip)] = TOS;
ip += 2;
break;
case 0x7E: // DAW : TOS = TOS, WORD (IP) = TOS
ea = UWORD_PTR(ip);
mem_data[ea] = TOS;
mem_data[ea + 1] = TOS >> 8;
ip += 2;
break;
/*
* Odd codes and everything else are errors.
*/
default:
fprintf(stderr, "Illegal opcode 0x%02X @ 0x%04X\n", ip[-1], ip - mem_data);
}
}
}
char *stdlib_exp[] = {
"PUTC",
"PUTS",
"PUTSZ",
"GETC",
"GETS",
"PUTLN",
"MACHID",
0
};
int main(int argc, char **argv)
{
byte dci[32];
int i;
if (--argc)
{
argv++;
if ((*argv)[0] == '-' && (*argv)[1] == 's')
{
show_state = 1;
argc--;
argv++;
}
/*
* Add default library.
*/
stodci("STDLIB", dci);
add_mod(dci, 0xFFFF);
for (i = 0; stdlib_exp[i]; i++)
{
mem_data[i] = i + 3;
stodci(stdlib_exp[i], dci);
add_sym(dci, i);
}
if (argc)
{
stodci(*argv, dci);
load_mod(dci);
if (show_state) dump_sym();
argc--;
argv++;
}
if (argc)
{
stodci(*argv, dci);
call(lookup_sym(dci));
}
}
return 0;
}

View File

@ -0,0 +1,18 @@
import stdlib
predef putc, putln, puts, getc, gets
predef call, syscall
predef heapmark, heapallocallign, heapalloc, heaprelease, heapavail
predef memset, memcpy
predef isugt, isuge, isult, isule
predef load, exec
word MACHID, sysvars
;
; System flags: memory allocator screen holes.
;
const restxt1 = $0001
const restxt2 = $0002
const reshgr1 = $0004
const reshgr2 = $0008
const resxhgr1 = $0010
const resxhgr2 = $0020
end

View File

@ -0,0 +1,39 @@
/*
* Symbol table types.
*/
#define GLOBAL_TYPE (0)
#define CONST_TYPE (1 << 0)
#define WORD_TYPE (1 << 1)
#define BYTE_TYPE (1 << 2)
#define VAR_TYPE (WORD_TYPE | BYTE_TYPE)
#define ASM_TYPE (1 << 3)
#define DEF_TYPE (1 << 4)
#define BRANCH_TYPE (1 << 5)
#define LOCAL_TYPE (1 << 6)
#define EXTERN_TYPE (1 << 7)
#define ADDR_TYPE (VAR_TYPE | FUNC_TYPE | EXTERN_TYPE)
#define WPTR_TYPE (1 << 8)
#define BPTR_TYPE (1 << 9)
#define PTR_TYPE (BPTR_TYPE | WPTR_TYPE)
#define STRING_TYPE (1 << 10)
#define TAG_TYPE (1 << 11)
#define EXPORT_TYPE (1 << 12)
#define PREDEF_TYPE (1 << 13)
#define FUNC_TYPE (ASM_TYPE | DEF_TYPE | PREDEF_TYPE)
int id_match(char *name, int len, char *id);
int idlocal_lookup(char *name, int len);
int idglobal_lookup(char *name, int len);
int idconst_lookup(char *name, int len);
int idlocal_add(char *name, int len, int type, int size);
int idglobal_add(char *name, int len, int type, int size);
int id_add(char *name, int len, int type, int size);
int idfunc_set(char *name, int len, int type, int tag);
int idfunc_add(char *name, int len, int type, int tag);
int idconst_add(char *name, int len, int value);
int id_tag(char *name, int len);
int id_const(char *name, int len);
int id_type(char *name, int len);
void idglobal_size(int type, int size, int constsize);
int idlocal_size(void);
void idlocal_reset(void);
int tag_new(int type);

View File

@ -0,0 +1,81 @@
;
; Include all imported modules and their data/functions.
;
include(stdlib.plh)
include(testlib.plh)
;
; Declare all global variables for this module.
;
byte hello[] = "Hello, Apple "
byte a1[] = "1"
byte a2[] = "]["
byte a2p[] = "][+"
byte a2e[] = "//e"
byte a2c[] = "//c"
byte a3[] = "///"
word struct[] = 1, 10, 100, 1000, 10000
byte spaces[] = " "
;
; Define functions.
;
def tens(start)
word i
i = start
repeat
print:hex(i)
print:str(@spaces)
print:dec(i)
print:newln()
i = i / 10
until i == 0
end
def ascii
byte i
i = 32
while i < 128
putc(i)
i = i + 1
loop
end
def nums(range)
word i
for i = range downto -range step range/10
puti(i)
putln
next
end
export def main(range)
nums(*range)
tens(*range*10)
ascii
putln
puts(@hello)
when MACHID & $C8
is $08
puts(@a1)
is $00
puts(@a2)
is $40
puts(@a2p)
is $80
puts(@a2e)
is $88
puts(@a2c)
is $C0
puts(@a3)
otherwise
putc('?')
wend
putln
end
main(@struct:6)
done

View File

@ -0,0 +1,43 @@
;
; Include all imported modules and their data/functions.
;
include(stdlib.plh)
;
; Module data.
;
predef puti, puth, putln
export word print[] = @puti, @puth, @putln, @puts, @putc
byte valstr[] = '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
byte loadstr[] = "testlib loaded!"
;
; Define functions.
;
def puth(h)
putc('$')
putc(valstr[(h >> 12) & $0F])
putc(valstr[(h >> 8) & $0F])
putc(valstr[(h >> 4) & $0F])
putc(valstr[ h & $0F])
end
export def puti(i)
if i < 0
putc('-')
i = -i
fin
if i < 10
putc(i + '0')
else
puti(i / 10)
putc(i % 10 + '0')
fin
end
puts(@loadstr)
putln
done

View File

@ -0,0 +1,9 @@
import testlib
predef puti, putln
word print
const dec = 0
const hex = 2
const newln = 4
const str = 6
const char = 8
end

View File

@ -0,0 +1,106 @@
#define TOKEN(c) (0x80|(c))
#define IS_TOKEN(c) (0x80&(c))
/*
* Identifier and constant tokens.
*/
#define ID_TOKEN TOKEN('V')
#define CHAR_TOKEN TOKEN('Y')
#define INT_TOKEN TOKEN('Z')
#define FLOAT_TOKEN TOKEN('F')
#define STRING_TOKEN TOKEN('S')
/*
* Keyword tokens.
*/
#define CONST_TOKEN TOKEN(1)
#define BYTE_TOKEN TOKEN(2)
#define WORD_TOKEN TOKEN(3)
#define IF_TOKEN TOKEN(4)
#define ELSEIF_TOKEN TOKEN(5)
#define ELSE_TOKEN TOKEN(6)
#define FIN_TOKEN TOKEN(7)
#define END_TOKEN TOKEN(8)
#define WHILE_TOKEN TOKEN(9)
#define LOOP_TOKEN TOKEN(10)
#define CASE_TOKEN TOKEN(11)
#define OF_TOKEN TOKEN(12)
#define DEFAULT_TOKEN TOKEN(13)
#define ENDCASE_TOKEN TOKEN(14)
#define FOR_TOKEN TOKEN(15)
#define TO_TOKEN TOKEN(16)
#define DOWNTO_TOKEN TOKEN(17)
#define STEP_TOKEN TOKEN(18)
#define NEXT_TOKEN TOKEN(19)
#define REPEAT_TOKEN TOKEN(20)
#define UNTIL_TOKEN TOKEN(21)
#define PREDEF_TOKEN TOKEN(22)
#define DEF_TOKEN TOKEN(23)
#define ASM_TOKEN TOKEN(24)
#define IMPORT_TOKEN TOKEN(25)
#define EXPORT_TOKEN TOKEN(26)
#define DONE_TOKEN TOKEN(27)
#define RETURN_TOKEN TOKEN(28)
#define BREAK_TOKEN TOKEN(29)
#define SYSFLAGS_TOKEN TOKEN(30)
#define EXIT_TOKEN TOKEN(31)
#define EVAL_TOKEN TOKEN(32)
/*
* Double operand operators.
*/
#define SET_TOKEN TOKEN('=')
#define ADD_TOKEN TOKEN('+')
#define ADD_SELF_TOKEN TOKEN('a')
#define SUB_TOKEN TOKEN('-')
#define SUB_SELF_TOKEN TOKEN('u')
#define MUL_TOKEN TOKEN('*')
#define MUL_SELF_TOKEN TOKEN('m')
#define DIV_TOKEN TOKEN('/')
#define DIV_SELF_TOKEN TOKEN('d')
#define MOD_TOKEN TOKEN('%')
#define OR_TOKEN TOKEN('|')
#define OR_SELF_TOKEN TOKEN('o')
#define EOR_TOKEN TOKEN('^')
#define EOR_SELF_TOKEN TOKEN('x')
#define AND_TOKEN TOKEN('&')
#define AND_SELF_TOKEN TOKEN('n')
#define SHR_TOKEN TOKEN('R')
#define SHR_SELF_TOKEN TOKEN('r')
#define SHL_TOKEN TOKEN('L')
#define SHL_SELF_TOKEN TOKEN('l')
#define GT_TOKEN TOKEN('>')
#define GE_TOKEN TOKEN('H')
#define LT_TOKEN TOKEN('<')
#define LE_TOKEN TOKEN('B')
#define NE_TOKEN TOKEN('U')
#define EQ_TOKEN TOKEN('E')
#define LOGIC_AND_TOKEN TOKEN('N')
#define LOGIC_OR_TOKEN TOKEN('O')
/*
* Single operand operators.
*/
#define NEG_TOKEN TOKEN('-')
#define COMP_TOKEN TOKEN('~')
#define LOGIC_NOT_TOKEN TOKEN('!')
#define INC_TOKEN TOKEN('P')
#define DEC_TOKEN TOKEN('K')
#define BPTR_TOKEN TOKEN('^')
#define WPTR_TOKEN TOKEN('*')
#define POST_INC_TOKEN TOKEN('p')
#define POST_DEC_TOKEN TOKEN('k')
#define OPEN_PAREN_TOKEN TOKEN('(')
#define CLOSE_PAREN_TOKEN TOKEN(')')
#define OPEN_BRACKET_TOKEN TOKEN('[')
#define CLOSE_BRACKET_TOKEN TOKEN(']')
/*
* Misc. tokens.
*/
#define AT_TOKEN TOKEN('@')
#define DOT_TOKEN TOKEN('.')
#define COLON_TOKEN TOKEN(':')
#define POUND_TOKEN TOKEN('#')
#define COMMA_TOKEN TOKEN(',')
#define COMMENT_TOKEN TOKEN(';')
#define EOL_TOKEN TOKEN(0)
#define EOF_TOKEN TOKEN(0x7F)
typedef unsigned char t_token;

View File

@ -87,21 +87,24 @@ expandVec = $800
;---------------------------------
; Main-mem tables and buffers
tableStart = $A700
decodeTo01 = $A700
decodeTo01b = $A800
decodeTo23 = $A900
decodeTo23b = $AA00
decodeTo45 = $AB00
decodeTo56 = $AC00
decodeTo57 = $AD00
clrBlitRollE = $AE00 ; size 3*(128/2) = $C0, plus 2 for tya and rts
clrBlitRollO = $AEC2 ; size 3*(128/2) = $C0, plus 2 for tya and rts
texAddrLo = $AF84
tableStart = $A000
decodeTo01 = $A000
decodeTo01b = $A100
decodeTo23 = $A200
decodeTo23b = $A300
decodeTo45 = $A400
decodeTo56 = $A500
decodeTo57 = $A600
clrBlitRollE = $A700 ; size 3*(128/2) = $C0, plus 2 for tya and rts
clrBlitRollO = $A7C2 ; size 3*(128/2) = $C0, plus 2 for tya and rts
texAddrLo = $A884
texAddrHi = texAddrLo + MAX_TEXTURES
blitRoll = $B000 ; Unrolled blitting code. Size 29*128 = $E80, plus 1 for rts
tableEnd = $BE81
memMap = $BF58 ; ProDOS memory map
blitRoll = $A900 ; Unrolled blitting code. Size 29*128 = $E80, plus 1 for rts
tableEnd = $B781
plasmaCode = $B800
plasmaFrames = $BD00
plasmaEnd = $BF00
; mipmap level offsets
MIP_OFFSET_0 = 0

View File

@ -13,8 +13,8 @@ start:
; Conditional assembly flags
DOUBLE_BUFFER = 1 ; whether to double-buffer
DEBUG = 0 ; 1=some logging, 2=lots of logging
DEBUG_COLUMN = 0
DEBUG = 1 ; 1=some logging, 2=lots of logging
DEBUG_COLUMN = -1
; temporary hack to try blocker sprites
BLOCKER_FOO = 0
@ -559,7 +559,6 @@ castRay: !zone
lda #$FF ; clamp large line heights to 255
+ tay ; save the height in Y reg
pla ; get the depth back
!if DEBUG { jsr .debugDepth }
jmp saveLink ; save final column data to link buffer
!if DEBUG >= 2 {
@ -602,18 +601,6 @@ castRay: !zone
+prA
+crout
rts
.debugDepth:
pha
lda screenCol
cmp #4
bne +
+prStr : !text "depth for col4=",0
pla
pha
+prA
+crout
+ pla
rts
}
;------------------------------------------------------------------------------
@ -1203,7 +1190,6 @@ saveLink: !zone
pha
+prStr : !text "Links for col ",0
+prByte screenCol
+prStr : !text ": ",0
ldx screenCol
ldy firstLink,x
.dlup +prStr : !text "[ht=",0
@ -1581,6 +1567,15 @@ initMem: !zone
ldx #<(tableEnd-tableStart)
ldy #>(tableEnd-tableStart)
jsr mainLoader
; Reserve memory for the PLASMA frame stack
lda #SET_MEM_TARGET
ldx #<plasmaFrames
ldy #>plasmaFrames
jsr mainLoader
lda #REQUEST_MEMORY
ldx #<(plasmaEnd-plasmaFrames)
ldy #>(plasmaEnd-plasmaFrames)
jsr mainLoader
; Load the font engine
!if DEBUG { +prStr : !text "Loading font engine.",0 }
lda #SET_MEM_TARGET
@ -1591,6 +1586,16 @@ initMem: !zone
ldx #RES_TYPE_CODE
ldy #3 ; hard coded for now: code #3 is the font engine
jsr mainLoader
; Load the font engine
!if DEBUG { +prStr : !text "Loading game loop.",0 }
lda #SET_MEM_TARGET
ldx #<plasmaCode
ldy #>plasmaCode
jsr mainLoader
lda #QUEUE_LOAD
ldx #RES_TYPE_CODE
ldy #4 ; hard coded for now: code #4 is the game loop
jsr mainLoader
!if DEBUG { +prStr : !text "Loading expansion code.",0 }
; Load the texture expansion code into aux mem.
lda #SET_MEM_TARGET
@ -1637,6 +1642,8 @@ initMem: !zone
pla
tax ; and hi byte in X
jsr setFONT
; Test PLASMA
jsr plasmaCode
; Set to write text on both hi-res pages at the same time
lda #pHGR3
jsr displayMODE