mirror of
https://github.com/badvision/lawless-legends.git
synced 2024-06-26 00:29:30 +00:00
Now runs PLASMA code\!
This commit is contained in:
parent
10f9d8640b
commit
786853a4a7
|
@ -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."
|
||||
|
|
|
@ -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>
|
||||
|
|
1302
Platform/Apple/virtual/src/plasma/cmd.pla
Normal file
1302
Platform/Apple/virtual/src/plasma/cmd.pla
Normal file
File diff suppressed because it is too large
Load Diff
48
Platform/Apple/virtual/src/plasma/cmdstub.s
Normal file
48
Platform/Apple/virtual/src/plasma/cmdstub.s
Normal 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 = *
|
||||
}
|
812
Platform/Apple/virtual/src/plasma/codegen.c
Executable file
812
Platform/Apple/virtual/src/plasma/codegen.c
Executable 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);
|
||||
}
|
59
Platform/Apple/virtual/src/plasma/codegen.h
Executable file
59
Platform/Apple/virtual/src/plasma/codegen.h
Executable 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);
|
80
Platform/Apple/virtual/src/plasma/gameloop.pla
Normal file
80
Platform/Apple/virtual/src/plasma/gameloop.pla
Normal 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
|
21
Platform/Apple/virtual/src/plasma/gamestub.s
Normal file
21
Platform/Apple/virtual/src/plasma/gamestub.s
Normal 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
|
8
Platform/Apple/virtual/src/plasma/hello.pla
Normal file
8
Platform/Apple/virtual/src/plasma/hello.pla
Normal file
|
@ -0,0 +1,8 @@
|
|||
import STDLIB
|
||||
predef puts
|
||||
end
|
||||
|
||||
byte hellostr[] = "Hello, world.\n"
|
||||
|
||||
puts(@hellostr)
|
||||
done
|
364
Platform/Apple/virtual/src/plasma/lex.c
Executable file
364
Platform/Apple/virtual/src/plasma/lex.c
Executable 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);
|
||||
}
|
10
Platform/Apple/virtual/src/plasma/lex.h
Executable file
10
Platform/Apple/virtual/src/plasma/lex.h
Executable 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);
|
60
Platform/Apple/virtual/src/plasma/makefile
Executable file
60
Platform/Apple/virtual/src/plasma/makefile
Executable 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
|
1335
Platform/Apple/virtual/src/plasma/parse.c
Executable file
1335
Platform/Apple/virtual/src/plasma/parse.c
Executable file
File diff suppressed because it is too large
Load Diff
1
Platform/Apple/virtual/src/plasma/parse.h
Executable file
1
Platform/Apple/virtual/src/plasma/parse.h
Executable file
|
@ -0,0 +1 @@
|
|||
int parse_module(void);
|
35
Platform/Apple/virtual/src/plasma/plasm.c
Executable file
35
Platform/Apple/virtual/src/plasma/plasm.c
Executable 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);
|
||||
}
|
928
Platform/Apple/virtual/src/plasma/plvm.c
Executable file
928
Platform/Apple/virtual/src/plasma/plvm.c
Executable 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;
|
||||
}
|
18
Platform/Apple/virtual/src/plasma/stdlib.plh
Normal file
18
Platform/Apple/virtual/src/plasma/stdlib.plh
Normal 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
|
39
Platform/Apple/virtual/src/plasma/symbols.h
Executable file
39
Platform/Apple/virtual/src/plasma/symbols.h
Executable 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);
|
81
Platform/Apple/virtual/src/plasma/test.pla
Executable file
81
Platform/Apple/virtual/src/plasma/test.pla
Executable 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
|
43
Platform/Apple/virtual/src/plasma/testlib.pla
Executable file
43
Platform/Apple/virtual/src/plasma/testlib.pla
Executable 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
|
9
Platform/Apple/virtual/src/plasma/testlib.plh
Normal file
9
Platform/Apple/virtual/src/plasma/testlib.plh
Normal 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
|
106
Platform/Apple/virtual/src/plasma/tokens.h
Executable file
106
Platform/Apple/virtual/src/plasma/tokens.h
Executable 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;
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user