Many, many, untested opcodes added.

This commit is contained in:
Scott Duensing 2024-01-30 21:12:23 -06:00
parent af33bd6865
commit 389592fc12
25 changed files with 676 additions and 65 deletions

View file

@ -41,7 +41,7 @@
#define MSG_INT_V12_SHIFT "Add V1/V2 shifting." #define MSG_INT_V12_SHIFT "Add V1/V2 shifting."
#define MSG_INT_V12_SHIFT_LOCK "Add V1/V2 shift locking." #define MSG_INT_V12_SHIFT_LOCK "Add V1/V2 shift locking."
#define MSG_MEM_BUFFER "Unable to allocate memory buffer." #define MSG_MEM_BUFFER "Unable to allocate memory buffer."
#define MSG_OP_VAR_MISSING_PROPERTY "Missing object property." #define MSG_OP_OBJ_MISSING_PROPERTY "Missing object property."
#define MSG_OP_VAR_TOO_MANY_LOCALS "Too many local variables!" #define MSG_OP_VAR_TOO_MANY_LOCALS "Too many local variables!"
#define MSG_OP_VAR_STACK_OVERFLOW "Stack overflow!" #define MSG_OP_VAR_STACK_OVERFLOW "Stack overflow!"
#else // DEBUGGING #else // DEBUGGING

View file

@ -29,7 +29,11 @@
uint32_t objectPointerGet(uint16_t objectId); uint32_t objectPointerGet(uint16_t objectId);
uint32_t objectPointerParentGet(uint32_t objectPointer);
uint16_t objectPropertyDefaultGet(uint32_t propertyId);
uint8_t objectPropertyGet(uint16_t objectId, uint32_t propertyId, uint8_t *size); uint8_t objectPropertyGet(uint16_t objectId, uint32_t propertyId, uint8_t *size);
uint16_t objectRelationGet(uint16_t objectId, uint8_t relationship);
void objectUnparent(uint16_t objectId);
#endif // OBJECT_H #endif // OBJECT_H

View file

@ -30,6 +30,9 @@
void opcodes_call(void); void opcodes_call(void);
void opcodes_ret(void); void opcodes_ret(void);
void opcodes_rfalse(void);
void opcodes_rtrue(void);
void opcodes_ret_popped(void);
#endif // OC_CALL_H #endif // OC_CALL_H

View file

@ -28,9 +28,15 @@
#include "common.h" #include "common.h"
void opcodes_dec_chk(void);
void opcodes_inc_chk(void);
void opcodes_je(void); void opcodes_je(void);
void opcodes_jg(void);
void opcodes_jin(void);
void opcodes_jl(void);
void opcodes_jump(void); void opcodes_jump(void);
void opcodes_jz(void); void opcodes_jz(void);
void opcodes_test(void);
#endif // OC_COMPARE_H #endif // OC_COMPARE_H

View file

@ -28,4 +28,7 @@
#include "common.h" #include "common.h"
void opcodes_read(void);
#endif // OC_INPUT_H #endif // OC_INPUT_H

View file

@ -29,6 +29,13 @@
void opcodes_add(void); void opcodes_add(void);
void opcodes_and(void);
void opcodes_dec(void);
void opcodes_div(void);
void opcodes_inc(void);
void opcodes_mod(void);
void opcodes_mul(void);
void opcodes_or(void);
void opcodes_sub(void); void opcodes_sub(void);

View file

@ -28,8 +28,11 @@
#include "common.h" #include "common.h"
void opcodes_load(void);
void opcodes_loadb(void);
void opcodes_loadw(void); void opcodes_loadw(void);
void opcodes_store(void); void opcodes_store(void);
void opcodes_storeb(void);
void opcodes_storew(void); void opcodes_storew(void);

View file

@ -28,4 +28,9 @@
#include "common.h" #include "common.h"
void opcodes_nop(void);
void opcodes_quit(void);
void opcodes_random(void);
#endif // OC_MISC_H #endif // OC_MISC_H

View file

@ -28,7 +28,18 @@
#include "common.h" #include "common.h"
void opcodes_clear_attr(void);
void opcodes_get_child(void);
void opcodes_get_next_prop(void);
void opcodes_get_parent(void);
void opcodes_get_prop(void);
void opcodes_get_prop_addr(void);
void opcodes_get_prop_len(void);
void opcodes_get_sibling(void);
void opcodes_insert_obj(void);
void opcodes_put_prop(void); void opcodes_put_prop(void);
void opcodes_remove_obj(void);
void opcodes_set_attr(void);
void opcodes_test_attr(void); void opcodes_test_attr(void);

View file

@ -30,6 +30,12 @@
void opcodes_new_line(void); void opcodes_new_line(void);
void opcodes_print(void); void opcodes_print(void);
void opcodes_print_addr(void);
void opcodes_print_char(void);
void opcodes_print_num(void);
void opcodes_print_obj(void);
void opcodes_print_paddr(void);
void opcodes_print_ret(void);
#endif // OC_OUTPUT_H #endif // OC_OUTPUT_H

View file

@ -28,4 +28,9 @@
#include "common.h" #include "common.h"
void opcodes_save(void);
void opcodes_restart(void);
void opcodes_restore(void);
#endif // OC_SAVE_H #endif // OC_SAVE_H

View file

@ -28,13 +28,19 @@
#include "common.h" #include "common.h"
uint8_t portByteGet(uint16_t address); uint8_t portByteGet(uint16_t address);
void portByteSet(uint16_t address, uint8_t value); void portByteSet(uint16_t address, uint8_t value);
void portDie(char *fmt, ...); void portCharsPrint(char *chars, uint16_t len);
void portPrintChars(char *chars, uint16_t len); void portDie(char *fmt, ...);
void portStoryLoad(void); void portFileClose(uint32_t *handle);
uint16_t portWordGet(uint16_t address); byte portFileByteRead(uint32_t *handle);
void portWordSet(uint16_t address, uint16_t value); bool portFileByteWrite(uint32_t *handle, byte value);
bool portFileReadOpen(uint32_t *handle, char *name);
bool portFileWriteOpen(uint32_t *handle, char *name);
uint16_t portRandomGet(int16_t range);
void portStoryLoad(void);
uint16_t portWordGet(uint16_t address);
void portWordSet(uint16_t address, uint16_t value);
#endif // PORTME_H #endif // PORTME_H

View file

@ -42,6 +42,35 @@ uint32_t objectPointerGet(uint16_t objectId) {
} }
uint32_t objectPointerParentGet(uint32_t objectPointer) {
uint32_t result = 0;
uint32_t parent;
if (storyVersion() <= 3) {
parent = ZPEEK(objectPointer + 4);
result = parent ? objectPointerGet(parent) : 0;
} else {
portDie(MSG_UNIMPLEMENTED);
}
return result;
}
uint16_t objectPropertyDefaultGet(uint32_t propertyId) {
uint32_t values;
if (((storyVersion() <= 3) && (propertyId > 31)) || ((storyVersion() >= 4) && (propertyId > 63))) {
//***TODO*** Should we die here? This seems to work.
return 0;
}
values = storyObjectTableAddress() + ((propertyId - 1) * 2);
return ZPEEKW(values);
}
uint8_t objectPropertyGet(uint16_t objectId, uint32_t propertyId, uint8_t *size) { uint8_t objectPropertyGet(uint16_t objectId, uint32_t propertyId, uint8_t *size) {
uint32_t ptr = objectPointerGet(objectId); uint32_t ptr = objectPointerGet(objectId);
uint16_t addr; uint16_t addr;
@ -78,3 +107,35 @@ uint8_t objectPropertyGet(uint16_t objectId, uint32_t propertyId, uint8_t *size)
} }
uint16_t objectRelationGet(uint16_t objectId, uint8_t relationship) {
uint32_t objPtr = objectPointerGet(objectId);
uint16_t result = 0;
if (storyVersion() <= 3) {
result = ZPEEKW(objPtr + relationship);
} else {
portDie(MSG_UNIMPLEMENTED);
}
return result;
}
void objectUnparent(uint16_t objectId) {
uint32_t objPtr = objectPointerGet(objectId);
uint32_t parentPtr = objectPointerParentGet(objPtr);
uint32_t ptr;
if (parentPtr != 0) {
if (storyVersion() <= 3) {
ptr = parentPtr + 6; // 4 to skip attrs, 2 to skip to child.
while (ZPEEK(ptr) != objectId) { // If not direct child, look through sibling list..
ptr = objectPointerGet(ZPEEK(ptr)) + 5;
}
ZPOKE(ptr, ZPEEK(objPtr + 5)); // obj sibling takes obj's place.
} else {
portDie(MSG_UNIMPLEMENTED);
}
}
}

View file

@ -93,3 +93,18 @@ void opcodes_call(void) {
void opcodes_ret(void) { void opcodes_ret(void) {
interpreterDoReturn(__state.operands[0]); interpreterDoReturn(__state.operands[0]);
} }
void opcodes_rfalse(void) {
interpreterDoReturn(0);
}
void opcodes_rtrue(void) {
interpreterDoReturn(1);
}
void opcodes_ret_popped(void) {
// Top of stack.
interpreterDoReturn(variableLoad(0));
}

View file

@ -24,6 +24,12 @@
#include "oc_compare.h" #include "oc_compare.h"
#include "state.h" #include "state.h"
#include "interpreter.h" #include "interpreter.h"
#include "variable.h"
#include "object.h"
#include "story.h"
#include "portme.h"
#include "messages.h"
#include "memory.h"
void opcodes_je(void) { void opcodes_je(void) {
@ -41,6 +47,48 @@ void opcodes_je(void) {
} }
void opcodes_dec_chk(void) {
int16_t val = variableLoad(__state.operands[0]);
val--;
variableStore(__state.operands[0], val);
interpreterDoBranch(((int16_t)val < (int16_t)__state.operands[1]) ? 1 : 0);
}
void opcodes_inc_chk(void) {
int16_t val = variableLoad(__state.operands[0]);
val++;
variableStore(__state.operands[0], val);
interpreterDoBranch(((int16_t)val > (int16_t)__state.operands[1]) ? 1 : 0);
}
void opcodes_jg(void) {
interpreterDoBranch(((int16_t)__state.operands[0] > (int16_t)__state.operands[1]) ? 1 : 0);
}
void opcodes_jin(void) {
uint16_t objId = __state.operands[0];
uint16_t parentId = __state.operands[1];
uint32_t objPtr = objectPointerGet(objId);
// Zork 1 will trigger this on "go X" where "x" isn't a direction.
if (objPtr == 0) return;
if (storyVersion() <= 3) {
interpreterDoBranch((ZPEEKW(objPtr + 4) == parentId) ? 1 : 0);
} else {
portDie(MSG_UNIMPLEMENTED);
}
}
void opcodes_jl(void) {
interpreterDoBranch(((int16_t)__state.operands[0] < (int16_t)__state.operands[1]) ? 1 : 0);
}
void opcodes_jump(void) { void opcodes_jump(void) {
__state.pc = __state.pc + ((int16_t)__state.operands[0]) - 2; __state.pc = __state.pc + ((int16_t)__state.operands[0]) - 2;
} }
@ -51,3 +99,7 @@ void opcodes_jz(void) {
} }
void opcodes_test(void) {
interpreterDoBranch(((__state.operands[0] & __state.operands[1]) == __state.operands[0]) ? 1 : 0);
}

View file

@ -22,3 +22,11 @@
#include "oc_input.h" #include "oc_input.h"
#include "portme.h"
#include "messages.h"
void opcodes_read(void) {
//***TODO***
portDie(MSG_UNIMPLEMENTED);
}

View file

@ -28,11 +28,45 @@
void opcodes_add(void) { void opcodes_add(void) {
variableStore(ZPEEK(__state.pc++), __state.operands[0] + __state.operands[1]); variableStore(ZPEEK(__state.pc++), (int16_t)__state.operands[0] + (int16_t)__state.operands[1]);
}
void opcodes_and(void) {
variableStore(ZPEEK(__state.pc++), __state.operands[0] & __state.operands[1]);
}
void opcodes_dec(void) {
variableStore(__state.operands[0], variableLoad(__state.operands[0]) - 1);
}
void opcodes_div(void) {
variableStore(ZPEEK(__state.pc++), (int16_t)__state.operands[0] / (int16_t)__state.operands[1]);
}
void opcodes_inc(void) {
variableStore(__state.operands[0], variableLoad(__state.operands[0]) + 1);
}
void opcodes_mod(void) {
variableStore(ZPEEK(__state.pc++), (int16_t)__state.operands[0] % (int16_t)__state.operands[1]);
}
void opcodes_mul(void) {
variableStore(ZPEEK(__state.pc++), (int16_t)__state.operands[0] * (int16_t)__state.operands[1]);
}
void opcodes_or(void) {
variableStore(ZPEEK(__state.pc++), __state.operands[0] | __state.operands[1]);
} }
void opcodes_sub(void) { void opcodes_sub(void) {
variableStore(ZPEEK(__state.pc++), __state.operands[0] - __state.operands[1]); variableStore(ZPEEK(__state.pc++), (int16_t)__state.operands[0] - (int16_t)__state.operands[1]);
} }

View file

@ -27,6 +27,17 @@
#include "memory.h" #include "memory.h"
void opcodes_load(void) {
variableStore(ZPEEK(__state.pc++), ZPEEK((__state.operands[0] & 0xFF)));
}
void opcodes_loadb(void) {
uint16_t offset = __state.operands[0] + __state.operands[1];
variableStore(ZPEEK(__state.pc++), ZPEEK(offset));
}
void opcodes_loadw(void) { void opcodes_loadw(void) {
uint16_t offset = __state.operands[0] + (__state.operands[1] * 2); uint16_t offset = __state.operands[0] + (__state.operands[1] * 2);
variableStore(ZPEEK(__state.pc++), ZPEEKW(offset)); variableStore(ZPEEK(__state.pc++), ZPEEKW(offset));
@ -38,6 +49,11 @@ void opcodes_store(void) {
} }
void opcodes_storeb(void) {
ZPOKE(__state.operands[0] + __state.operands[1], __state.operands[2]);
}
void opcodes_storew(void) { void opcodes_storew(void) {
ZPOKEW(__state.operands[0] + (__state.operands[1] * 2), __state.operands[2]); ZPOKEW(__state.operands[0] + (__state.operands[1] * 2), __state.operands[2]);
} }

View file

@ -22,3 +22,21 @@
#include "oc_misc.h" #include "oc_misc.h"
#include "state.h"
#include "variable.h"
#include "portme.h"
void opcodes_nop(void) {
// Well this one is easy.
}
void opcodes_quit(void) {
__state.quit = true;
}
void opcodes_random(void) {
variableStore((__state.pc++), portRandomGet((int16_t)__state.operands[0]));
}

View file

@ -29,13 +29,133 @@
#include "portme.h" #include "portme.h"
#include "messages.h" #include "messages.h"
#include "object.h" #include "object.h"
#include "variable.h"
void opcodes_clear_attr(void) {
uint32_t ptr = objectPointerGet(__state.operands[0]);
uint16_t attrId = __state.operands[1];
// Zork 1 will trigger this on "go X" where "x" isn't a direction, so ignore it.
if (ptr == 0) return;
if (storyVersion() <= 3) {
ptr += (attrId / 8);
ZPOKE(ptr, ZPEEK(ptr) & ~(0x80 >> (attrId & 7)));
} else {
portDie(MSG_UNIMPLEMENTED);
}
}
void opcodes_get_child(void) {
uint16_t result = objectRelationGet(__state.operands[0], 6);
variableStore(ZPEEK(__state.pc++), result);
interpreterDoBranch(result != 0 ? 1 : 0);
}
void opcodes_get_next_prop(void) {
uint16_t objId = __state.operands[0];
bool firstProp = (__state.operands[1] == 0);
uint16_t result = 0;
uint8_t size = 0;
uint32_t ptr = objectPropertyGet(objId, firstProp ? 0xFFFFFFFF : __state.operands[1], &size);
if (ptr == 0) {
portDie(MSG_OP_OBJ_MISSING_PROPERTY);
}
if (storyVersion() <= 3) {
// 5 bits for the prop id.
result = ZPEEK(ptr + (firstProp ? -1 : (int8_t)size)) & 0x1f;
} else {
portDie(MSG_UNIMPLEMENTED);
}
variableStore(ZPEEK(__state.pc++), result);
}
void opcodes_get_parent(void) {
uint16_t result = objectRelationGet(__state.operands[0], 4);
variableStore(ZPEEK(__state.pc++), result);
interpreterDoBranch(result != 0 ? 1 : 0);
}
void opcodes_get_prop(void) {
uint16_t objId = __state.operands[0];
uint16_t propId = __state.operands[1];
uint16_t result = 0;
uint8_t size = 0;
uint32_t ptr = objectPropertyGet(objId, propId, &size);
if (ptr == 0) {
result = objectPropertyDefaultGet(propId);
} else {
result = ZPEEK(ptr);
}
variableStore(ZPEEK(__state.pc++), result);
}
void opcodes_get_prop_addr(void) {
uint16_t objId = __state.operands[0];
uint16_t propId = __state.operands[1];
variableStore(ZPEEK(__state.pc++), objectPropertyGet(objId, propId, NULL));
}
void opcodes_get_prop_len(void) {
uint16_t result = 0;
uint8_t info;
// This must return 0 if OP0 is zero, to avoid a bug in older Infocom games.
if (__state.operands[0] != 0) {
if (storyVersion() <= 3) {
info = ZPEEK(__state.operands[0] - 1);
result = ((info >> 5) & 0x7) + 1; // 3 bits for property size.
} else {
portDie(MSG_UNIMPLEMENTED);
}
}
variableStore(ZPEEK(__state.pc++), result);
}
void opcodes_get_sibling(void) {
uint16_t result = objectRelationGet(__state.operands[0], 5);
variableStore(ZPEEK(__state.pc++), result);
interpreterDoBranch(result != 0 ? 1 : 0);
}
void opcodes_insert_obj(void) {
uint32_t objPtr = objectPointerGet(__state.operands[0]);
uint32_t dstPtr = objectPointerGet(__state.operands[1]);
if (storyVersion() <= 3) {
// Take object out of tree.
objectUnparent(__state.operands[0]);
// Reinsert in right spot.
ZPOKE(objPtr + 4, __state.operands[1]);
ZPOKE(objPtr + 5, ZPEEK(dstPtr + 6));
ZPOKE(dstPtr + 6, __state.operands[0]);
} else {
portDie(MSG_UNIMPLEMENTED);
}
}
void opcodes_put_prop(void) { void opcodes_put_prop(void) {
uint8_t size = 0; uint8_t size = 0;
uint8_t ptr = objectPropertyGet(__state.operands[0], __state.operands[1], &size); uint8_t ptr = objectPropertyGet(__state.operands[0], __state.operands[1], &size);
if (ptr == 0) portDie(MSG_OP_VAR_MISSING_PROPERTY); if (ptr == 0) portDie(MSG_OP_OBJ_MISSING_PROPERTY);
if (size == 1) { if (size == 1) {
ZPOKE(ptr, (__state.operands[2] & 0xff)); ZPOKE(ptr, (__state.operands[2] & 0xff));
@ -45,6 +165,35 @@ void opcodes_put_prop(void) {
} }
void opcodes_remove_obj(void) {
uint16_t objId = __state.operands[0];
uint32_t objPtr = objectPointerGet(objId);
if (storyVersion() <= 3) {
// Remove object from tree.
objectUnparent(objId);
// Clear out object's relationships.
ZPOKE(objPtr + 4, 0); // Parent.
ZPOKE(objPtr + 5, 0); // Sibling.
} else {
portDie(MSG_UNIMPLEMENTED);
}
}
void opcodes_set_attr(void) {
uint32_t ptr = objectPointerGet(__state.operands[0]);
uint16_t attrId = __state.operands[1];
if (storyVersion() <= 3) {
ptr += (attrId / 8);
ZPOKE(ptr, ZPEEK(ptr) | 0x80 >> (attrId & 7));
} else {
portDie(MSG_UNIMPLEMENTED);
}
}
void opcodes_test_attr(void) { void opcodes_test_attr(void) {
uint32_t ptr = objectPointerGet(__state.operands[0]); uint32_t ptr = objectPointerGet(__state.operands[0]);
uint16_t attrId = __state.operands[1]; uint16_t attrId = __state.operands[1];

View file

@ -25,13 +25,81 @@
#include "state.h" #include "state.h"
#include "portme.h" #include "portme.h"
#include "zscii.h" #include "zscii.h"
#include "memory.h"
#include "story.h"
#include "object.h"
#include "messages.h"
#include "interpreter.h"
void opcodes_new_line(void) { void opcodes_new_line(void) {
portPrintChars("\n", 1); portCharsPrint("\n", 1);
} }
void opcodes_print(void) { void opcodes_print(void) {
__state.pc += zsciiPrint(__state.pc, 0); __state.pc += zsciiPrint(__state.pc, 0);
} }
void opcodes_print_addr(void) {
zsciiPrint(__state.operands[0], 0);
}
void opcodes_print_char(void) {
static char c[2] = { 0, 0 };
c[0] = zsciiDecodeChar(__state.operands[0]);
if (c[0]) portCharsPrint(c, 1);
}
static void opcodes_print_num_helper(int16_t val) {
static char c[2] = { 0, 0 };
if (val < 0) {
portCharsPrint("-", 1);
val = -val;
}
if (val > 9) {
opcodes_print_num_helper(val / 10);
}
c[0] = '0' + (val % 10);
portCharsPrint(c, 1);
}
void opcodes_print_num(void) {
opcodes_print_num_helper(__state.operands[0]);
}
void opcodes_print_obj(void) {
uint32_t ptr = objectPointerGet(__state.operands[0]);
uint32_t addr;
if (storyVersion() <= 3) {
// Skip to properties field.
ptr += 7;
// Dereference to get to property table.
addr = ZPEEKW(ptr);
zsciiPrint(addr + 1, 0);
} else {
portDie(MSG_UNIMPLEMENTED);
}
}
void opcodes_print_paddr(void) {
zsciiPrint(memoryUnpackAddress(__state.operands[0], MEMORY_PRINT), 0);
}
void opcodes_print_ret(void) {
__state.pc += zsciiPrint(__state.pc, 0);
portCharsPrint("\n", 1);
interpreterDoReturn(1);
}

View file

@ -22,3 +22,101 @@
#include "oc_save.h" #include "oc_save.h"
#include "interpreter.h"
#include "state.h"
#include "portme.h"
#include "story.h"
#include "memory.h"
void opcodes_save(void) {
uint32_t f;
bool ok;
uint16_t i;
uint8_t *b;
ok = portFileWriteOpen(&f, "save.dat");
// Write out PC.
b = (uint8_t *)&__state.pc;
ok &= portFileByteWrite(&f, b[0]);
ok &= portFileByteWrite(&f, b[1]);
ok &= portFileByteWrite(&f, b[2]);
ok &= portFileByteWrite(&f, b[3]);
// Write out SP.
b = (uint8_t *)&__state.sp;
ok &= portFileByteWrite(&f, b[0]);
ok &= portFileByteWrite(&f, b[1]);
// Write out BP.
b = (uint8_t *)&__state.sp;
ok &= portFileByteWrite(&f, b[0]);
ok &= portFileByteWrite(&f, b[1]);
// Write out dynamic memory.
for (i=0; i<storyStaticMemoryBaseAddress(); i++) {
ok &= portFileByteWrite(&f, ZPEEK(i));
}
// Write out stack.
for (i=0; i<__state.sp; i++) {
b = (uint8_t *)&__state.stack[i];
ok &= portFileByteWrite(&f, b[0]);
ok &= portFileByteWrite(&f, b[1]);
}
portFileClose(&f);
interpreterDoBranch(ok ? 1 : 0);
}
void opcodes_restart(void) {
stateReset();
portStoryLoad();
storySetup();
}
void opcodes_restore(void) {
uint32_t f;
bool ok;
uint16_t i;
uint8_t *b;
ok = portFileReadOpen(&f, "save.dat");
// Read PC.
b = (uint8_t *)&__state.pc;
b[0] = portFileByteRead(&f);
b[1] = portFileByteRead(&f);
b[2] = portFileByteRead(&f);
b[3] = portFileByteRead(&f);
// Read SP.
b = (uint8_t *)&__state.sp;
b[0] = portFileByteRead(&f);
b[1] = portFileByteRead(&f);
// Read BP.
b = (uint8_t *)&__state.bp;
b[0] = portFileByteRead(&f);
b[1] = portFileByteRead(&f);
// Read dynamic memory.
for (i=0; i<storyStaticMemoryBaseAddress(); i++) {
ZPOKE(i, portFileByteRead(&f));
}
// Read stack.
for (i=0; i<__state.sp; i++) {
b = (uint8_t *)&__state.stack[i];
b[0] = portFileByteRead(&f);
b[1] = portFileByteRead(&f);
}
portFileClose(&f);
interpreterDoBranch(ok ? 1 : 0);
}

View file

@ -54,78 +54,78 @@
void opcodesBuiltInitialTable(void) { void opcodesBuiltInitialTable(void) {
// 2-operand instructions... // 2-operand instructions...
OP(1, je); OP(1, je);
mOP(2, jl); OP(2, jl);
mOP(3, jg); OP(3, jg);
mOP(4, dec_chk); OP(4, dec_chk);
mOP(5, inc_chk); OP(5, inc_chk);
mOP(6, jin); OP(6, jin);
mOP(7, test); OP(7, test);
mOP(8, or); OP(8, or);
mOP(9, and); OP(9, and);
OP(10, test_attr); OP(10, test_attr);
mOP(11, set_attr); OP(11, set_attr);
mOP(12, clear_attr); OP(12, clear_attr);
OP(13, store); OP(13, store);
mOP(14, insert_obj); OP(14, insert_obj);
OP(15, loadw); OP(15, loadw);
mOP(16, loadb); OP(16, loadb);
mOP(17, get_prop); OP(17, get_prop);
mOP(18, get_prop_addr); OP(18, get_prop_addr);
mOP(19, get_next_prop); OP(19, get_next_prop);
OP(20, add); OP(20, add);
OP(21, sub); OP(21, sub);
mOP(22, mul); OP(22, mul);
mOP(23, div); OP(23, div);
mOP(24, mod); OP(24, mod);
// 1-operand instructions... // 1-operand instructions...
OP(128, jz); OP(128, jz);
mOP(129, get_sibling); OP(129, get_sibling);
mOP(130, get_child); OP(130, get_child);
mOP(131, get_parent); OP(131, get_parent);
mOP(132, get_prop_len); OP(132, get_prop_len);
mOP(133, inc); OP(133, inc);
mOP(134, dec); OP(134, dec);
mOP(135, print_addr); OP(135, print_addr);
mOP(137, remove_obj); OP(137, remove_obj);
mOP(138, print_obj); OP(138, print_obj);
OP(139, ret); OP(139, ret);
OP(140, jump); OP(140, jump);
mOP(141, print_paddr); OP(141, print_paddr);
mOP(142, load); OP(142, load);
mOP(143, not); mOP(143, not);
// 0-operand instructions... // 0-operand instructions...
mOP(176, rtrue); OP(176, rtrue);
mOP(177, rfalse); OP(177, rfalse);
OP(178, print); OP(178, print);
mOP(179, print_ret); OP(179, print_ret);
mOP(180, nop); OP(180, nop);
mOP(181, save); OP(181, save);
mOP(182, restore); OP(182, restore);
mOP(183, restart); OP(183, restart);
mOP(184, ret_popped); OP(184, ret_popped);
mOP(185, pop); mOP(185, pop);
mOP(186, quit); OP(186, quit);
OP(187, new_line); OP(187, new_line);
// variable operand instructions... // variable operand instructions...
OP(224, call); OP(224, call);
OP(225, storew); OP(225, storew);
mOP(226, storeb); OP(226, storeb);
OP(227, put_prop); OP(227, put_prop);
mOP(228, read); OP(228, read);
mOP(229, print_char); OP(229, print_char);
mOP(230, print_num); OP(230, print_num);
mOP(231, random); OP(231, random);
mOP(232, push); OP(232, push);
mOP(233, pull); OP(233, pull);
if (storyVersion() < 3) return; if (storyVersion() < 3) return;
mOP(188, show_status); mOP(188, show_status);
mOP(189, verify); OP(189, verify);
mOP(234, split_window); mOP(234, split_window);
mOP(235, set_window); mOP(235, set_window);

View file

@ -46,6 +46,14 @@ void portByteSet(uint16_t address, uint8_t value) {
} }
void portCharsPrint(char *chars, uint16_t len) {
uint16_t x;
for (x=0; x<len; x++) {
printf("%c", chars[x]);
}
}
void portDie(char *fmt, ...) { void portDie(char *fmt, ...) {
va_list ap; va_list ap;
@ -59,11 +67,36 @@ void portDie(char *fmt, ...) {
} }
void portPrintChars(char *chars, uint16_t len) { void portFileClose(uint32_t *handle) {
uint16_t x;
for (x=0; x<len; x++) { }
printf("%c", chars[x]);
}
byte portFileByteRead(uint32_t *handle) {
return 0;
}
bool portFileByteWrite(uint32_t *handle, byte value) {
return false;
}
bool portFileReadOpen(uint32_t *handle, char *name) {
return false;
}
bool portFileWriteOpen(uint32_t *handle, char *name) {
return false;
}
uint16_t portRandomGet(int16_t range) {
// If range is zero, randomize with "best" random seed.
// If range is negative, use the positive value to seed.
return 42;
} }

View file

@ -193,7 +193,7 @@ uint32_t zsciiPrint(uint32_t pc, bool abbr) {
ret = zsciiDecode(pc, abbr, __memoryBuffer, &decodedChars); ret = zsciiDecode(pc, abbr, __memoryBuffer, &decodedChars);
} }
portPrintChars(__memoryBuffer, decodedChars); portCharsPrint(__memoryBuffer, decodedChars);
return ret; return ret;
} }