v0.68: compiler bug fixes, improved efficiency

- Fixed indentation of VM code. Turned on stack checks for GCC only.
- Added new `VM_DISCARD` VM instruction (and compiler support).  This makes the VM significantly more efficient.
- Configured Linux VM to be compatible with Apple II environment.
- Added line to force to interpret mode to prevent surprises.
- Compiler: fixed bug when exiting `for` loop using `return`.  The compiler was leaking a word on the evalutation stack after jumping out of the body of the `for` loop.
This commit is contained in:
Bobbi Webber-Manners 2018-05-13 13:59:40 -04:00 committed by GitHub
parent 43d45a06dd
commit ea3a6a83e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 550 additions and 198 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -104,13 +104,17 @@ test.d64: 8ball20.prg 8ballvm20.prg 8ball64.prg 8ballvm64.prg unittest.8bp sieve
c1541 -attach test.d64 -write unittest.8bp unit.8b,s
c1541 -attach test.d64 -write sieve4.8bp sieve4.8b,s
test.dsk: eightball.system ebvm.system sieve4.8b
test.dsk: eightball.system ebvm.system sieve4.8b tetris.8b bytecode
java -jar $(APPLECMDR) -d test.dsk e8ball.system
java -jar $(APPLECMDR) -d test.dsk ebvm.system
java -jar $(APPLECMDR) -d test.dsk sieve4.8b
java -jar $(APPLECMDR) -d test.dsk tetris.8b
java -jar $(APPLECMDR) -d test.dsk bytecode
java -jar $(APPLECMDR) -p test.dsk e8ball.system sys <eightball.system
java -jar $(APPLECMDR) -p test.dsk ebvm.system sys <ebvm.system
java -jar $(APPLECMDR) -p test.dsk sieve4.8b txt <sieve4.8b
java -jar $(APPLECMDR) -p test.dsk tetris.8b txt <tetris.8b
java -jar $(APPLECMDR) -p test.dsk bytecode txt <bytecode
xvic: test.d64
xvic -mem all -drive8type 1541 -8 test.d64

Binary file not shown.

BIN
eightball

Binary file not shown.

View File

@ -1232,9 +1232,11 @@ unsigned char *heap2PtrBttm; /* Arena 2: bottom-up heap */
* Heap 2: Program text
*/
#define HEAP1TOP (char*)0xb7ff
#define HEAP1LIM (char*)0x9800
//#define HEAP1LIM (char*)0x9800
#define HEAP1LIM (char*)0xa800
#define HEAP2TOP (char*)0x97ff
//#define HEAP2TOP (char*)0x97ff
#define HEAP2TOP (char*)0xa7ff
#define HEAP2LIM (char*)0x8a00
/* HEAP2LIM HAS TO BE ADJUSTED TO NOT
* TRASH THE CODE, WHICH LOADS FROM $2000 UP
@ -2560,7 +2562,7 @@ void doif(unsigned char arg)
push_return(IFFRAME);
if (compile) {
/* **** Value of IF expression is on the VM stack **** */
/* **** Value of IF expression is on the eval stack **** */
emit(VM_NOT);
push_return(rtPC + 1);
emitldi(0xffff); /* To be filled in later */
@ -2828,10 +2830,10 @@ unsigned char assignorcreate(unsigned char mode)
* When compiling:
*
* - Magic value FORFRAME_B or FORFRAME_W.
* - 0 if absolute addressing, 1 if relative addressing
* - Runtime PC
* - Pointer to loop control variable.
* - Dummy word
* - Dummy word
*/
/* Get the address of the variable */
@ -2849,10 +2851,11 @@ unsigned char assignorcreate(unsigned char mode)
/* Find out if it is a local or a global */
findintvar(name, &local);
push_return(local && compilingsub); /* 0: absolute, 1: relative addr */
push_return(rtPC); /* Store PC for compile case */
emit(VM_DUP);
/* Loop limit k should be on the runtime VM stack already */
/* Loop limit k should be on the runtime eval stack, move it to call stack */
emit(VM_PSHWORD);
push_return(rtPC); /* Store PC so we know where to come back to */
push_return(j);
push_return(0); /* Dummy */
} else {
@ -2925,13 +2928,19 @@ unsigned char doendfor()
}
if (compile) {
/* **** Loop limit is on the VM stack **** */
emitldi(return_stack[returnSP + 2]);
if (return_stack[returnSP + 4]) {
/* **** Loop limit is on the call stack **** */
emit(VM_POPWORD);
emit(VM_DUP);
emit(VM_PSHWORD);
emitldi(return_stack[returnSP + 2]); /* Pointer to loop variable */
if (return_stack[returnSP + 4]) { /* Rel or abs */
emit((type == TYPE_WORD) ? VM_LDRWORD : VM_LDRBYTE);
} else {
emit((type == TYPE_WORD) ? VM_LDAWORD : VM_LDABYTE);
}
/* Increment and store loop variable */
emit(VM_INC);
emit(VM_DUP);
emitldi(return_stack[returnSP + 2]);
@ -2940,9 +2949,14 @@ unsigned char doendfor()
} else {
emit((type == TYPE_WORD) ? VM_STAWORD : VM_STABYTE);
}
/* Compare with loop limit already on eval stack */
emit(VM_GTE);
emitldi(return_stack[returnSP + 3]);
emitldi(return_stack[returnSP + 3]); /* Branch destination */
emit(VM_BRNCH);
/* Drop loop limit from call stack */
emit(VM_POPWORD);
emit(VM_DROP);
goto unwind;
}
@ -3010,7 +3024,7 @@ void dowhile(char *startTxtPtr, unsigned char arg)
if (compile) {
push_return(rtPCBeforeEval);
/* **** Value of WHILE expression is on the VM stack **** */
/* **** Value of WHILE expression is on the eval stack **** */
emit(VM_NOT);
push_return(rtPC + 1); /* Address of dummy 0xffff */
emitldi(0xffff);
@ -3623,10 +3637,12 @@ unsigned char docall()
/* Caller must drop the arguments
* pushed to call stack above */
for (j = 0; j < argbytes; ++j) {
emit(VM_POPBYTE);
emit(VM_DROP);
}
emitldi(argbytes);
emit(VM_DISCARD);
//for (j = 0; j < argbytes; ++j) {
// emit(VM_POPBYTE);
// emit(VM_DROP);
//}
} else {
/* Stash pointer to just after the call stmt */
push_return((int) txtPtr);
@ -4975,6 +4991,7 @@ main()
#endif
}
compile = 0;
getln(lnbuf, 255);
switch (editmode) {

Binary file not shown.

View File

@ -37,7 +37,7 @@
/* */
/**************************************************************************/
#define VERSIONSTR "0.67"
#define VERSIONSTR "0.68"
void print(char *str);

Binary file not shown.

View File

@ -51,7 +51,11 @@
*/
/* Define STACKCHECKS to enable paranoid stack checking */
#ifdef __GNUC__
#define STACKCHECKS
#else
#undef STACKCHECKS
#endif
#include "eightballvm.h"
#include "eightballutils.h"
@ -180,7 +184,8 @@ void checkstackunderflow(unsigned char bytes)
{
if ((MEMORYSZ - sp) < bytes) {
print("Call stack underflow\nPC=");
printhex(pc); printchar('\n');
printhex(pc);
printchar('\n');
while (1);
}
}
@ -227,12 +232,19 @@ void execute_instruction()
#ifdef DEBUGREGS
unsigned int i;
print("\n");
print("--->PC "); printhex(pc); print("\n");
print("--->SP "); printhex(sp); print("\n");
print("--->FP "); printhex(fp); print("\n");
print("--->PC ");
printhex(pc);
print("\n");
print("--->SP ");
printhex(sp);
print("\n");
print("--->FP ");
printhex(fp);
print("\n");
print("Call Stk: ");
for(i = sp+1; i <= RTCALLSTACKTOP; ++i) {
printhexbyte(memory[i]); printchar(' ');
for (i = sp + 1; i <= RTCALLSTACKTOP; ++i) {
printhexbyte(memory[i]);
printchar(' ');
}
print("\nEval Stk: ");
printhex(XREG);
@ -293,25 +305,25 @@ void execute_instruction()
* Miscellaneous
*/
case VM_END: /* Terminate execution */
if (evalptr > 0) {
print("WARNING: evalptr ");
printdec(evalptr);
printchar('\n');
}
if (evalptr > 0) {
print("WARNING: evalptr ");
printdec(evalptr);
printchar('\n');
}
#ifdef __GNUC__
exit(0);
#else
for (delay = 0; delay < 25000; ++delay);
exit(0);
exit(0);
#endif
break;
/*
* Load Immediate
*/
/*
* Load Immediate
*/
case VM_LDIMM: /* Pushes the following 16 bit word to the evaluation stack */
++evalptr;
CHECKOVERFLOW();
CHECKOVERFLOW();
/* Note: Word is stored in little endian format! */
tempword = memory[++pc];
tempword += memory[++pc] * 256;
@ -364,7 +376,9 @@ void execute_instruction()
printchar('\n');
#endif
XREG = memory[(XREG + fp + 1) & 0xffff] + 256 * memory[(XREG + fp + 2) & 0xffff];
XREG =
memory[(XREG + fp + 1) & 0xffff] +
256 * memory[(XREG + fp + 2) & 0xffff];
break;
case VM_LDRBYTE: /* Replaces X with 8 bit value pointed to by X. */
CHECKUNDERFLOW(1);
@ -446,10 +460,11 @@ void execute_instruction()
XREG = memory[sp];
break;
case VM_PSHWORD: /* Push 16 bit value in X onto call stack. Drop X. */
CHECKUNDERFLOW(1);
#ifdef DEBUGSTACK
print("\n Push word to ");
printhex(sp-1);
printhex(sp - 1);
printchar('\n');
#endif
@ -462,6 +477,7 @@ void execute_instruction()
--evalptr;
break;
case VM_PSHBYTE: /* Push 8 bit value in X onto call stack. Drop X. */
CHECKUNDERFLOW(1);
#ifdef DEBUGSTACK
print("\n Push byte to ");
@ -474,17 +490,22 @@ void execute_instruction()
CHECKSTACKOVERFLOW();
--evalptr;
break;
case VM_DISCARD: /* Discard X bytes from call stack. Drop X. */
CHECKUNDERFLOW(1);
sp += XREG;
--evalptr;
break;
case VM_SPTOFP: /* Copy stack pointer to frame pointer. (Enter function scope) */
#ifdef DEBUGSTACK
print("\n SPTOFP FP before ");
printhex(fp);
print(" SP ");
print(" SP ");
printhex(sp);
printchar('\n');
#endif
/* Push old FP to stack */
/* Push old FP to stack */
memory[sp] = (fp & 0xff00) >> 8;
--sp;
CHECKSTACKOVERFLOW();
@ -499,14 +520,14 @@ void execute_instruction()
#ifdef DEBUGSTACK
print("\n FPTOSP SP before ");
printhex(sp);
print(" FP ");
print(" FP ");
printhex(fp);
printchar('\n');
#endif
sp = fp;
/* Pop old FP from stack -> FP */
/* Pop old FP from stack -> FP */
CHECKSTACKUNDERFLOW(2);
sp += 2;
CHECKOVERFLOW();
@ -514,17 +535,17 @@ void execute_instruction()
#ifdef DEBUGSTACK
print(" Recovered FP ");
printhex(fp);
print(" from stack\n");
printhex(fp);
print(" from stack\n");
#endif
break;
case VM_ATOR: /* Convert absolute address in X to relative address */
XREG = (XREG - fp - 1) & 0xffff;
break;
break;
case VM_RTOA: /* Convert relative address in X to absolute address */
XREG = (XREG + fp + 1) & 0xffff;
break;
break;
/*
* Integer math
*/
@ -699,20 +720,20 @@ void execute_instruction()
CHECKUNDERFLOW(1);
printchar((unsigned char) XREG);
--evalptr;
break;
break;
case VM_PRSTR: /* Print null terminated string pointed to by X. Drop X */
CHECKUNDERFLOW(1);
while(memory[XREG]) {
printchar(memory[XREG++]);
}
while (memory[XREG]) {
printchar(memory[XREG++]);
}
--evalptr;
break;
break;
case VM_PRMSG: /* Print literal string at PC (null terminated) */
++pc;
while(memory[pc]) {
printchar(memory[pc++]);
}
break;
++pc;
while (memory[pc]) {
printchar(memory[pc++]);
}
break;
case VM_KBDCH: /* Push character from keyboard onto eval stack */
CHECKUNDERFLOW(1);
++evalptr;
@ -723,15 +744,15 @@ void execute_instruction()
while (!(*(char *) XREG = cbm_k_getin()));
#else
/* TODO: Unimplemented in Linux */
XREG = 0;
XREG = 0;
#endif
break;
case VM_KBDLN: /* Obtain line from keyboard and write to memory pointed to by */
/* Y. X contains the max number of bytes in buf. Drop X, Y. */
break;
case VM_KBDLN: /* Obtain line from keyboard and write to memory pointed to by */
/* Y. X contains the max number of bytes in buf. Drop X, Y. */
CHECKUNDERFLOW(2);
getln((char *) &memory[YREG], XREG);
evalptr -= 2;
break;
evalptr -= 2;
break;
/*
* Unsupported instruction
*/
@ -786,7 +807,7 @@ int main()
videomode(VIDEOMODE_80COL);
clrscr();
#elif defined(CBM)
printchar(147); /* Clear */
printchar(147); /* Clear */
#endif
execute();
return 0;

View File

@ -68,140 +68,142 @@
* stack, and also to release the locals on return from sub.)
*/
enum bytecode {
/**** Miscellaneous ********************************************************/
VM_END, /* Terminate execution */
/**** Load Immediate *******************************************************/
VM_LDIMM, /* Pushes the following 16 bit word to the evaluation stack */
/* Absolute addressing: */
VM_LDAWORD,/* Replaces X with 16 bit value pointed to by X. */
VM_LDABYTE,/* Replaces X with 8 bit value pointed to by X. */
VM_STAWORD,/* Stores 16 bit value Y in addr pointed to by X. Drops X and Y.*/
VM_STABYTE,/* Stores 8 bit value Y in addr pointed to by X. Drops X and Y. */
/* Relative to Frame Pointer addressing: */
VM_LDRWORD,/* Replaces X with 16 bit value pointed to by X. */
VM_LDRBYTE,/* Replaces X with 8 bit value pointed to by X. */
VM_STRWORD,/* Stores 16 bit value Y in addr pointed to by X. Drops X and Y.*/
VM_STRBYTE,/* Stores 8 bit value Y in addr pointed to by X. Drops X and Y. */
/**** Manipulate evaluation stack ******************************************/
VM_SWAP, /* Swaps X and Y */
VM_DUP, /* Duplicates X -> X, Y */
VM_DUP2, /* Duplicates X -> X,Z; Y -> Y,T */
VM_DROP, /* Drops X */
VM_OVER, /* Duplicates Y -> X,Z */
VM_PICK, /* Duplicates stack level specified in X+1 -> X */
/**** Manipulate call stack ************************************************/
VM_POPWORD,/* Pop 16 bit value from call stack, push onto eval stack [X] */
VM_POPBYTE,/* Pop 8 bit value from call stack, push onto eval stack [X] */
VM_PSHWORD,/* Push 16 bit value in X onto call stack. Drop X. */
VM_PSHBYTE,/* Push 8 bit value in X onto call stack. Drop X. */
VM_SPTOFP, /* Copy stack pointer to frame pointer. (Enter function scope) */
VM_FPTOSP, /* Copy frame pointer to stack pointer. (Release local vars) */
VM_ATOR, /* Convert absolute address in X to relative address */
VM_RTOA, /* Convert relative address in X to absolute address */
/**** Integer math *********************************************************/
VM_INC, /* X = X+1. */
VM_DEC, /* X = X-1. */
VM_ADD, /* X = Y+X. Y is dropped. */
VM_SUB, /* X = Y-X. Y is dropped. */
VM_MUL, /* X = Y*X. Y is dropped. */
VM_DIV, /* X = Y/X. Y is dropped. */
VM_MOD, /* X = Y%X. Y is dropped . */
VM_NEG, /* X = -X */
/**** Comparisons **********************************************************/
VM_GT, /* X = Y>X. Y is dropped. */
VM_GTE, /* X = Y>=X. Y is dropped. */
VM_LT, /* X = Y<X. Y is dropped. */
VM_LTE, /* X = Y<=X. Y is dropped. */
VM_EQL, /* X = Y==X. Y is dropped. */
VM_NEQL, /* X = Y!=X. Y is dropped. */
/**** Logical operations ***************************************************/
VM_AND, /* X = Y&&X. Y is dropped. */
VM_OR, /* X = Y||X. Y is dropped. */
VM_NOT, /* X = !X */
/**** Bitwise operations ***************************************************/
VM_BITAND, /* X = Y&X. Y is dropped. */
VM_BITOR, /* X = Y|X. Y is dropped. */
VM_BITXOR, /* X = Y^X. Y is dropped. */
VM_BITNOT, /* X = ~X. */
VM_LSH, /* X = Y<<X. Y is dropped. */
VM_RSH, /* X = Y>>X. Y is dropped. */
/**** Flow control *********************************************************/
VM_JMP, /* Jump to address X. Drop X. */
VM_BRNCH, /* If Y!= 0, jump to address X. Drop X, Y. */
VM_JSR, /* Push PC to call stack. Jump to address X. Drop X. */
VM_RTS, /* Pop call stack, jump to the address popped. */
/**** Input / Output *******************************************************/
VM_PRDEC, /* Print 16 bit decimal in X. Drop X */
VM_PRHEX, /* Print 16 bit hex in X. Drop X */
VM_PRCH, /* Print character in X. Drop X */
VM_PRSTR, /* Print null terminated string pointed to by X. Drop X */
VM_PRMSG, /* Print literal string at PC (null terminated) */
VM_KBDCH, /* Push character from keyboard onto eval stack */
VM_KBDLN /* Obtain line from keyboard and write to memory pointed to by */
/* Y. X contains the max number of bytes in buf. Drop X, Y. */
/***************************************************************************/
/**** Miscellaneous *************************************************************************/
VM_END, /* Terminate execution */
/**** Load Immediate ************************************************************************/
VM_LDIMM, /* Pushes the following 16 bit word to the evaluation stack */
/* Absolute addressing: */
VM_LDAWORD, /* Replaces X with 16 bit value pointed to by X. */
VM_LDABYTE, /* Replaces X with 8 bit value pointed to by X. */
VM_STAWORD, /* Stores 16 bit value Y in addr pointed to by X. Drops X and Y.*/
VM_STABYTE, /* Stores 8 bit value Y in addr pointed to by X. Drops X and Y. */
/* Relative to Frame Pointer addressing: */
VM_LDRWORD, /* Replaces X with 16 bit value pointed to by X. */
VM_LDRBYTE, /* Replaces X with 8 bit value pointed to by X. */
VM_STRWORD, /* Stores 16 bit value Y in addr pointed to by X. Drops X and Y.*/
VM_STRBYTE, /* Stores 8 bit value Y in addr pointed to by X. Drops X and Y. */
/**** Manipulate evaluation stack ***********************************************************/
VM_SWAP, /* Swaps X and Y */
VM_DUP, /* Duplicates X -> X, Y */
VM_DUP2, /* Duplicates X -> X,Z; Y -> Y,T */
VM_DROP, /* Drops X */
VM_OVER, /* Duplicates Y -> X,Z */
VM_PICK, /* Duplicates stack level specified in X+1 -> X */
/**** Manipulate call stack *****************************************************************/
VM_POPWORD, /* Pop 16 bit value from call stack, push onto eval stack [X] */
VM_POPBYTE, /* Pop 8 bit value from call stack, push onto eval stack [X] */
VM_PSHWORD, /* Push 16 bit value in X onto call stack. Drop X. */
VM_PSHBYTE, /* Push 8 bit value in X onto call stack. Drop X. */
VM_DISCARD, /* Discard X bytes from call stack. Drop X. */
VM_SPTOFP, /* Copy stack pointer to frame pointer. (Enter function scope) */
VM_FPTOSP, /* Copy frame pointer to stack pointer. (Release local vars) */
VM_ATOR, /* Convert absolute address in X to relative address */
VM_RTOA, /* Convert relative address in X to absolute address */
/**** Integer math **************************************************************************/
VM_INC, /* X = X+1. */
VM_DEC, /* X = X-1. */
VM_ADD, /* X = Y+X. Y is dropped. */
VM_SUB, /* X = Y-X. Y is dropped. */
VM_MUL, /* X = Y*X. Y is dropped. */
VM_DIV, /* X = Y/X. Y is dropped. */
VM_MOD, /* X = Y%X. Y is dropped . */
VM_NEG, /* X = -X */
/**** Comparisons ***************************************************************************/
VM_GT, /* X = Y>X. Y is dropped. */
VM_GTE, /* X = Y>=X. Y is dropped. */
VM_LT, /* X = Y<X. Y is dropped. */
VM_LTE, /* X = Y<=X. Y is dropped. */
VM_EQL, /* X = Y==X. Y is dropped. */
VM_NEQL, /* X = Y!=X. Y is dropped. */
/**** Logical operations ********************************************************************/
VM_AND, /* X = Y&&X. Y is dropped. */
VM_OR, /* X = Y||X. Y is dropped. */
VM_NOT, /* X = !X */
/**** Bitwise operations ********************************************************************/
VM_BITAND, /* X = Y&X. Y is dropped. */
VM_BITOR, /* X = Y|X. Y is dropped. */
VM_BITXOR, /* X = Y^X. Y is dropped. */
VM_BITNOT, /* X = ~X. */
VM_LSH, /* X = Y<<X. Y is dropped. */
VM_RSH, /* X = Y>>X. Y is dropped. */
/**** Flow control **************************************************************************/
VM_JMP, /* Jump to address X. Drop X. */
VM_BRNCH, /* If Y!= 0, jump to address X. Drop X, Y. */
VM_JSR, /* Push PC to call stack. Jump to address X. Drop X. */
VM_RTS, /* Pop call stack, jump to the address popped. */
/**** Input / Output ************************************************************************/
VM_PRDEC, /* Print 16 bit decimal in X. Drop X */
VM_PRHEX, /* Print 16 bit hex in X. Drop X */
VM_PRCH, /* Print character in X. Drop X */
VM_PRSTR, /* Print null terminated string pointed to by X. Drop X */
VM_PRMSG, /* Print literal string at PC (null terminated) */
VM_KBDCH, /* Push character from keyboard onto eval stack */
VM_KBDLN /* Obtain line from keyboard and write to memory pointed to by */
/* Y. X contains the max number of bytes in buf. Drop X, Y. */
/********************************************************************************************/
};
/* Order must match enum bytecode */
char *bytecodenames[] = {
"END",
"LDI",
"LDAW",
"LDAB",
"STAW",
"STAB",
"LDRW",
"LDRB",
"STRW",
"STRB",
"SWP",
"DUP",
"DUP2",
"DRP",
"OVER",
"PICK",
"POPW",
"POPB",
"PSHW",
"PSHB",
"SPFP",
"FPSP",
"ATOR",
"RTOA",
"INC",
"DEC",
"ADD",
"SUB",
"MUL",
"DIV",
"MOD",
"NEG",
"GT",
"GTE",
"LT",
"LTE",
"EQL",
"NEQL",
"AND",
"OR",
"NOT",
"BAND",
"BOR",
"BXOR",
"BNOT",
"LSH",
"RSH",
"JMP",
"BRC",
"JSR",
"RTS",
"PRDEC",
"PRHEX",
"PRCH",
"PRSTR",
"PRMSG",
"KBDCH",
"KBDLN"
"END",
"LDI",
"LDAW",
"LDAB",
"STAW",
"STAB",
"LDRW",
"LDRB",
"STRW",
"STRB",
"SWP",
"DUP",
"DUP2",
"DRP",
"OVER",
"PICK",
"POPW",
"POPB",
"PSHW",
"PSHB",
"DISC",
"SPFP",
"FPSP",
"ATOR",
"RTOA",
"INC",
"DEC",
"ADD",
"SUB",
"MUL",
"DIV",
"MOD",
"NEG",
"GT",
"GTE",
"LT",
"LTE",
"EQL",
"NEQL",
"AND",
"OR",
"NOT",
"BAND",
"BOR",
"BXOR",
"BNOT",
"LSH",
"RSH",
"JMP",
"BRC",
"JSR",
"RTS",
"PRDEC",
"PRHEX",
"PRCH",
"PRSTR",
"PRMSG",
"KBDCH",
"KBDLN"
};
#ifdef A2E
@ -211,7 +213,7 @@ char *bytecodenames[] = {
*/
#define RTCALLSTACKTOP 0xb7ff
#define RTCALLSTACKLIM 0x9800
#define RTPCSTART 0x5000 /* TBC */
#define RTPCSTART 0x5000 /* TBC */
#elif defined(C64)
@ -220,7 +222,7 @@ char *bytecodenames[] = {
*/
#define RTCALLSTACKTOP 0xbfff
#define RTCALLSTACKLIM 0xa000
#define RTPCSTART 0x3000 /* TBC */
#define RTPCSTART 0x3000 /* TBC */
#elif defined(VIC20)
@ -229,7 +231,7 @@ char *bytecodenames[] = {
*/
#define RTCALLSTACKTOP 0xbfff
#define RTCALLSTACKLIM 0xa000
#define RTPCSTART 0x4000 /* TBC */
#define RTPCSTART 0x4000 /* TBC */
#elif defined(__GNUC__)
@ -237,8 +239,10 @@ char *bytecodenames[] = {
* Linux
*/
//#define RTCALLSTACKTOP 64 * 1024 - 1
#define RTCALLSTACKTOP 48 * 1024 - 1 // FOR TESTING
#define RTCALLSTACKLIM 32 * 1024
#define RTPCSTART 0
//#define RTCALLSTACKTOP 48 * 1024 - 1 // FOR TESTING
#define RTCALLSTACKTOP 0xb7ff
//#define RTCALLSTACKLIM 32 * 1024
#define RTCALLSTACKLIM 0x9800
//#define RTPCSTART 0
#define RTPCSTART 0x5000 // SO THINGS WORK ON APPLE II :)
#endif

BIN
test.d64

Binary file not shown.

BIN
test.dsk

Binary file not shown.

306
tetris.8b Normal file
View File

@ -0,0 +1,306 @@
' Apple II Low Res Tetris
' Bobbi 2018
word addrs[24]={$400,$480,$500,$580,$600,$680,$700,$780,$428,$4a8,$528,$5a8,$628,$6a8,$728,$7a8,$450,$4d0,$550,$5d0,$650,$6d0,$750,$7d0}
const lhs=14
const rhs=lhs+11
const top=10
const bttm=top+22
const spkr=$c030
const kbdata=$c000
const kbstrb=$c010
byte col=18
byte row=5
byte rot=0
byte key=0
byte ocol=18
byte orow=5
byte orot=0
byte piece=0
byte canl=1
byte canr=1
call lores()
call clrlo()
call frame()
while 1
key=getkey()
orow=row;ocol=col;orot=rot
if key=='s'
if rot==3
rot=0
else
rot=rot+1
endif
else
if (key=='a')&&canl
col=col-1
else
if (key=='d')&&canr
col=col+1
endif
endif
endif
key=^spkr
row=row+1
canl=1
canr=1
call drawPiece(ocol,orow,orot,1); 'Erase
if drawPiece(col,row,rot,0)
call checkframe(row)
col=18;row=5;rot=0
piece=piece+1
if piece==4
piece=0
endif
endif
endwhile
call text()
end
sub getkey()
if ^kbdata<128
return 0
endif
^kbstrb=0
return ^kbdata
endsub
sub lores()
^$c050=0
^$c052=0
^$c054=0
^$c056=0
endsub
sub loresmix()
^$c050=0
^$c053=0
^$c054=0
^$c056=0
endsub
sub text()
^$c051=0
^$c054=0
endsub
sub clrlo()
byte r=0
byte c=0
for r=0:23
for c=0:39
^(addrs[r]+c)=0
endfor
endfor
endsub
sub plot(byte c,byte r,byte color)
word a=addrs[r/2]+c
if r%2
^a=(^a&$0f)|(color<<4)
else
^a=(^a&$f0)|color
endif
endsub
sub readpix(byte c,byte r)
word a=addrs[r/2]+c
if r%2
return (^a&$f0)>>4
else
return ^a&$0f
endif
endsub
sub hlin(byte c1,byte c2,byte r,byte color)
byte i=0
for i=c1:c2
call plot(i,r,color)
endfor
endsub
sub vlin(byte c,byte r1,byte r2,byte color)
byte i=0
for i=r1:r2
call plot(c,i,color)
endfor
endsub
sub frame()
call hlin(lhs,rhs,bttm,4)
call vlin(lhs,top,bttm,4)
call vlin(rhs,top,bttm,4)
endsub
sub drawPiece(byte c,byte r,byte rot,byte erase)
if piece==0
return drawT(c,r,rot,erase)
else; if piece==1
return drawZ(c,r,rot,erase)
else; if piece==2
return drawSq(c,r,rot,erase)
else
return drawI(c,r,rot,erase)
endif;endif;endif
endsub
sub drawT(byte c,byte r,byte rot,byte erase)
byte color=1
if erase
color=0
endif
if rot==0
call plot(c,r+1,color)
call plot(c+1,r+1,color)
call plot(c+2,r+1,color)
call plot(c+1,r+2,color)
canl=!(readpix(c-1,r+1)||readpix(c,r+2))
canr=!(readpix(c+3,r+1)||readpix(c+2,r+2))
return readpix(c,r+2)||readpix(c+1,r+3)||readpix(c+2,r+2)
else
if rot==1
call plot(c+1,r,color)
call plot(c,r+1,color)
call plot(c+1,r+1,color)
call plot(c+1,r+2,color)
canl=!(readpix(c,r)||readpix(c-1,r+1)||readpix(c,r+2))
canr=!(readpix(c+2,r)||readpix(c+2,r+1)||readpix(c+2,r+2))
return readpix(c,r+2)||readpix(c+1,r+3)
else
if rot==2
call plot(c+1,r,color)
call plot(c,r+1,color)
call plot(c+1,r+1,color)
call plot(c+2,r+1,color)
canl=!(readpix(c,r)||readpix(c-1,r+1))
canr=!(readpix(c+2,r)||readpix(c+3,r+1))
return readpix(c,r+2)||readpix(c+1,r+2)||readpix(c+2,r+2)
else
if rot==3
call plot(c+1,r,color)
call plot(c+1,r+1,color)
call plot(c+2,r+1,color)
call plot(c+1,r+2,color)
canl=!(readpix(c,r)||readpix(c,r+1)||readpix(c,r+2))
canr=!(readpix(c+2,r)||readpix(c+3,r+1)||readpix(c+2,r+2))
return readpix(c+1,r+3)||readpix(c+2,r+2)
endif
endif
endif
endif
endsub
sub drawZ(byte c,byte r,byte rot,byte erase)
byte color=2
if erase
color=0
endif
if (rot==0)||(rot==2)
call plot(c+1,r,color)
call plot(c+1,r+1,color)
call plot(c+2,r+1,color)
call plot(c+2,r+2,color)
canl=!(readpix(c,r)||readpix(c,r+1)||readpix(c,r+2))
canr=!(readpix(c+2,r)||readpix(c+3,r+1)||readpix(c+3,r+2))
return readpix(c+2,r+3)
else
if (rot==1)||(rot==3)
call plot(c+1,r+1,color)
call plot(c+2,r+1,color)
call plot(c,r+2,color)
call plot(c+1,r+2,color)
canl=!(readpix(c,r+1)||readpix(c-1,r+2))
canr=!(readpix(c+3,r+1)||readpix(c+2,r+2))
return readpix(c,r+3)||readpix(c+1,r+3)
endif
endif
endsub
sub drawI(byte c,byte r,byte rot,byte erase)
byte color=14
if erase
color=0
endif
if (rot==0)||(rot==2)
call plot(c,r+2,color)
call plot(c+1,r+2,color)
call plot(c+2,r+2,color)
call plot(c+3,r+2,color)
canl=!readpix(c-1,r+2)
canr=!readpix(c+4,r+2)
return readpix(c,r+3)||readpix(c+1,r+3)||readpix(c+2,r+3)||readpix(c+3,r+3)
else
if (rot==1)||(rot==3)
call plot(c+2,r,color)
call plot(c+2,r+1,color)
call plot(c+2,r+2,color)
call plot(c+2,r+3,color)
canl=!(readpix(c+1,r)||readpix(c+1,r+1)||readpix(c+1,r+2)||readpix(c+1,r+3))
canr=!(readpix(c+3,r)||readpix(c+3,r+1)||readpix(c+3,r+2)||readpix(c+3,r+3))
return readpix(c+2,r+4)
endif
endif
endsub
sub drawSq(byte c,byte r,byte rot,byte erase)
byte color=13
if erase
color=0
endif
call plot(c+1,r+1,color)
call plot(c+2,r+1,color)
call plot(c+1,r+2,color)
call plot(c+2,r+2,color)
canl=!(readpix(c,r+1)||readpix(c,r+2))
canr=!(readpix(c+3,r+1)||readpix(c+3,r+2))
return readpix(c+1,r+3)||readpix(c+2,r+3)
endsub
sub checkframe(byte r)
byte rr=r+3
if rr>bttm-1
rr=bttm-1
endif
while rr>=r
if checkline(rr)
pr.ch 7; 'Beep
else
rr=rr-1
endif
endwhile
endsub
sub checkline(byte r)
byte c=0
for c=lhs+1:rhs-1
if !readpix(c,r)
return 0
endif
endfor
call deleterow(r)
return 1
endsub
sub deleterow(byte r)
byte i=r
byte c=0
byte v=0
byte empty=0
while (i>top+1)&&(!empty)
empty=1
for c=lhs+1:rhs-1
v=readpix(c,i-1)
if v
empty=0
endif
call plot(c,i,v)
endfor
i=i-1
endwhile
endsub