Title is printing!
This commit is contained in:
parent
3a055f96f4
commit
c93327084b
18 changed files with 319 additions and 234 deletions
|
@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.12)
|
||||||
project(zip LANGUAGES C)
|
project(zip LANGUAGES C)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
|
common.h
|
||||||
interpreter.h
|
interpreter.h
|
||||||
memory.h
|
memory.h
|
||||||
messages.h
|
messages.h
|
||||||
|
|
31
include/common.h
Normal file
31
include/common.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Scott Duensing, scott@kangaroopunch.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef COMMON_H
|
||||||
|
#define COMMON_H
|
||||||
|
|
||||||
|
|
||||||
|
#define DEBUGGING
|
||||||
|
|
||||||
|
|
||||||
|
#endif // COMMON_H
|
|
@ -26,20 +26,23 @@
|
||||||
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "common.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
|
uint32_t interpreterDecodeZSCII(uint32_t zstr, bool abbr, char *buf, uint32_t *bufLenP);
|
||||||
uint32_t interpreterDecodeZSCII(uint32_t zstr, bool abbr, char *buf, uint32_t *bufLen);
|
|
||||||
char interpreterDecodeZSCIIChar(uint16_t z);
|
char interpreterDecodeZSCIIChar(uint16_t z);
|
||||||
void interpreterDoBranch(int32_t b);
|
void interpreterDoBranch(int32_t truth);
|
||||||
void interpreterDoReturn(uint16_t r);
|
void interpreterDoReturn(uint16_t r);
|
||||||
uint8_t interpreterGetObjectPointer(uint16_t objectId);
|
uint32_t interpreterGetObjectPointer(uint16_t objectId);
|
||||||
uint8_t interpreterGetObjectProperty(uint16_t objectId, uint32_t propertyId, uint8_t *size);
|
uint8_t interpreterGetObjectProperty(uint16_t objectId, uint32_t propertyId, uint8_t *size);
|
||||||
|
uint32_t interpreterGlobalVariableAddress(uint16_t var);
|
||||||
|
uint16_t interpreterLoadVariable(uint16_t var);
|
||||||
bool interpreterParseOperand(uint8_t opType, uint8_t operandId);
|
bool interpreterParseOperand(uint8_t opType, uint8_t operandId);
|
||||||
uint8_t interpreterParseVariableOperands(uint8_t index);
|
uint8_t interpreterParseVariableOperands(uint8_t index);
|
||||||
void interpreterPrintChars(char *chars, uint16_t len);
|
void interpreterPrintChars(char *chars, uint16_t len);
|
||||||
uint32_t interpreterPrintZSCII(uint32_t pc, bool abbr);
|
uint32_t interpreterPrintZSCII(uint32_t pc, bool abbr);
|
||||||
void interpreterRun(void);
|
void interpreterRun(void);
|
||||||
|
void interpreterStoreVariable(uint16_t var, uint16_t value);
|
||||||
uint8_t interpreterVariableAddress(uint8_t var, bool writing);
|
uint8_t interpreterVariableAddress(uint8_t var, bool writing);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
#define MEMORY_ROUTINE 0
|
#define MEMORY_ROUTINE 0
|
||||||
|
@ -40,9 +41,6 @@
|
||||||
#define PEEKW(a) memoryWord(a)
|
#define PEEKW(a) memoryWord(a)
|
||||||
#define POKEW(a,v) memorySetWord(a,v)
|
#define POKEW(a,v) memorySetWord(a,v)
|
||||||
|
|
||||||
// Stack access.
|
|
||||||
#define SPEEKD(a) ((uint32_t)*(uint32_t *)&__state.stack[a])
|
|
||||||
|
|
||||||
|
|
||||||
typedef unsigned char byte;
|
typedef unsigned char byte;
|
||||||
typedef unsigned char bool;
|
typedef unsigned char bool;
|
||||||
|
|
|
@ -24,10 +24,11 @@
|
||||||
#ifndef MESSAGES_H
|
#ifndef MESSAGES_H
|
||||||
#define MESSAGES_H
|
#define MESSAGES_H
|
||||||
|
|
||||||
#define MSG_USE_MESSAGES // Undef this to save memory.
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef MSG_USE_MESSAGES
|
#ifdef DEBUGGING
|
||||||
#define MSG_UNIMPLEMENTED "Unimplemented."
|
#define MSG_UNIMPLEMENTED "Unimplemented."
|
||||||
#define MSG_INT_INVALID_EXT_OPCODE "Invalid extended opcode!"
|
#define MSG_INT_INVALID_EXT_OPCODE "Invalid extended opcode!"
|
||||||
#define MSG_INT_NO_ABBR "No abbreviations in abbreviations!"
|
#define MSG_INT_NO_ABBR "No abbreviations in abbreviations!"
|
||||||
|
@ -43,7 +44,7 @@
|
||||||
#define MSG_OP_VAR_MISSING_PROPERTY "Missing object property."
|
#define MSG_OP_VAR_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 // MSG_USE_MESSAGES
|
#else // DEBUGGING
|
||||||
#define MSG_UNIMPLEMENTED ""
|
#define MSG_UNIMPLEMENTED ""
|
||||||
#define MSG_INT_INVALID_EXT_OPCODE ""
|
#define MSG_INT_INVALID_EXT_OPCODE ""
|
||||||
#define MSG_INT_NO_ABBR ""
|
#define MSG_INT_NO_ABBR ""
|
||||||
|
@ -59,7 +60,7 @@
|
||||||
#define MSG_OP_VAR_MISSING_PROPERTY ""
|
#define MSG_OP_VAR_MISSING_PROPERTY ""
|
||||||
#define MSG_OP_VAR_TOO_MANY_LOCALS ""
|
#define MSG_OP_VAR_TOO_MANY_LOCALS ""
|
||||||
#define MSG_OP_VAR_STACK_OVERFLOW ""
|
#define MSG_OP_VAR_STACK_OVERFLOW ""
|
||||||
#endif // MSG_USE_MESSAGES
|
#endif // DEBUGGING
|
||||||
|
|
||||||
|
|
||||||
#endif // MESSAGES_H
|
#endif // MESSAGES_H
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
#define OC_0OP_H
|
#define OC_0OP_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
void opcodes_new_line(void);
|
void opcodes_new_line(void);
|
||||||
void opcodes_print(void);
|
void opcodes_print(void);
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#define OC_1OP_H
|
#define OC_1OP_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
void opcodes_jump(void);
|
void opcodes_jump(void);
|
||||||
void opcodes_jz(void);
|
void opcodes_jz(void);
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
#define OC_2OP_H
|
#define OC_2OP_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
void opcodes_add(void);
|
void opcodes_add(void);
|
||||||
void opcodes_je(void);
|
void opcodes_je(void);
|
||||||
void opcodes_loadw(void);
|
void opcodes_loadw(void);
|
||||||
|
|
|
@ -24,4 +24,8 @@
|
||||||
#ifndef OC_EXT_H
|
#ifndef OC_EXT_H
|
||||||
#define OC_EXT_H
|
#define OC_EXT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
#endif // OC_EXT_H
|
#endif // OC_EXT_H
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#define OC_VAR_OP_H
|
#define OC_VAR_OP_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
void opcodes_call(void);
|
void opcodes_call(void);
|
||||||
void opcodes_put_prop(void);
|
void opcodes_put_prop(void);
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
#define OPCODES_H
|
#define OPCODES_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
typedef void (*opcodeT)(void);
|
typedef void (*opcodeT)(void);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
void portDie(char *fmt, ...);
|
void portDie(char *fmt, ...);
|
||||||
void portPrintChars(char *chars, uint16_t len);
|
void portPrintChars(char *chars, uint16_t len);
|
||||||
|
|
|
@ -25,13 +25,11 @@
|
||||||
#define STATE_H
|
#define STATE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "opcodes.h"
|
#include "opcodes.h"
|
||||||
|
|
||||||
|
|
||||||
#define DEBUGGING
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct stateS {
|
typedef struct stateS {
|
||||||
uint16_t stack[2048]; //***TODO*** How big does this really need to be? Old games are 1024, new...?
|
uint16_t stack[2048]; //***TODO*** How big does this really need to be? Old games are 1024, new...?
|
||||||
bool quit;
|
bool quit;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#define STORY_H
|
#define STORY_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
#include "portme.h"
|
#include "portme.h"
|
||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
|
@ -31,17 +32,16 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
uint32_t interpreterDecodeZSCII(uint32_t zstr, bool abbr, char *buf, uint32_t *bufLen) {
|
uint32_t interpreterDecodeZSCII(uint32_t zstr, bool abbr, char *buf, uint32_t *bufLenP) {
|
||||||
|
uint32_t bufLen = *bufLenP;
|
||||||
uint16_t code = 0;
|
uint16_t code = 0;
|
||||||
uint8_t alphabet = 0;
|
uint8_t alphabet = 0;
|
||||||
uint8_t useAbbrTable = 0;
|
uint8_t useAbbrTable = 0;
|
||||||
uint8_t zsciiCollector = 0;
|
uint8_t zsciiCollector = 0;
|
||||||
uint16_t zsciiCode = 0;
|
uint16_t zsciiCode = 0;
|
||||||
uint32_t decodedChars = 0;
|
uint32_t decodedChars = 0;
|
||||||
uint32_t bufPtr = 0;
|
|
||||||
uint32_t pc = zstr;
|
uint32_t pc = zstr;
|
||||||
char printVal = 0;
|
char printVal = 0;
|
||||||
uint32_t bufLenTemp;
|
|
||||||
uint32_t index;
|
uint32_t index;
|
||||||
uint32_t ptr;
|
uint32_t ptr;
|
||||||
uint16_t abbrAddr;
|
uint16_t abbrAddr;
|
||||||
|
@ -56,7 +56,10 @@ uint32_t interpreterDecodeZSCII(uint32_t zstr, bool abbr, char *buf, uint32_t *b
|
||||||
|
|
||||||
// Characters are 5 bits each, packed three to a 16-bit word.
|
// Characters are 5 bits each, packed three to a 16-bit word.
|
||||||
for (i=10; i>=0; i-=5) {
|
for (i=10; i>=0; i-=5) {
|
||||||
ch = ((code >> 1) & 0x1f);
|
|
||||||
|
newShift = 0;
|
||||||
|
printVal = 0;
|
||||||
|
ch = ((code >> i) & 0x1f);
|
||||||
|
|
||||||
if (zsciiCollector) {
|
if (zsciiCollector) {
|
||||||
if (zsciiCollector == 2) {
|
if (zsciiCollector == 2) {
|
||||||
|
@ -71,8 +74,9 @@ uint32_t interpreterDecodeZSCII(uint32_t zstr, bool abbr, char *buf, uint32_t *b
|
||||||
printVal = interpreterDecodeZSCIIChar(zsciiCode);
|
printVal = interpreterDecodeZSCIIChar(zsciiCode);
|
||||||
if (printVal) {
|
if (printVal) {
|
||||||
decodedChars++;
|
decodedChars++;
|
||||||
if (bufPtr < *bufLen) {
|
if (bufLen) {
|
||||||
buf[bufPtr++] = printVal;
|
*(buf++) = printVal;
|
||||||
|
bufLen--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
alphabet = 0;
|
alphabet = 0;
|
||||||
|
@ -89,19 +93,19 @@ uint32_t interpreterDecodeZSCII(uint32_t zstr, bool abbr, char *buf, uint32_t *b
|
||||||
index = ((32 * (((uint32_t)useAbbrTable) - 1)) + (uint32_t)ch);
|
index = ((32 * (((uint32_t)useAbbrTable) - 1)) + (uint32_t)ch);
|
||||||
ptr = storyAbbreviationTableAddress() + (index * 2);
|
ptr = storyAbbreviationTableAddress() + (index * 2);
|
||||||
abbrAddr = PEEKW(ptr);
|
abbrAddr = PEEKW(ptr);
|
||||||
|
ptr += 2;
|
||||||
|
|
||||||
abbrDecodedChars = *bufLen - bufPtr;
|
abbrDecodedChars = bufLen;
|
||||||
interpreterDecodeZSCII(abbrAddr * 2, 1, buf, &abbrDecodedChars);
|
interpreterDecodeZSCII(abbrAddr * 2, 1, buf, &abbrDecodedChars);
|
||||||
decodedChars += abbrDecodedChars;
|
decodedChars += abbrDecodedChars;
|
||||||
|
buf += (bufLen < abbrDecodedChars) ? bufLen : abbrDecodedChars;
|
||||||
bufLenTemp = *bufLen - bufPtr;
|
bufLen = (bufLen < abbrDecodedChars) ? 0 : (bufLen - abbrDecodedChars);
|
||||||
bufPtr += (bufLenTemp < abbrDecodedChars) ? bufLenTemp : abbrDecodedChars;
|
|
||||||
bufLenTemp = (bufLenTemp < abbrDecodedChars) ? 0 : (bufLenTemp - abbrDecodedChars);
|
|
||||||
*bufLen = *bufLen - bufLenTemp;
|
|
||||||
|
|
||||||
useAbbrTable = 0;
|
useAbbrTable = 0;
|
||||||
alphabet = 0; //***FIXME*** Version 3+ has no shift-lock but V1 needs it.
|
alphabet = 0; //***FIXME*** Version 3+ has no shift-lock but V1 needs it.
|
||||||
|
|
||||||
|
continue;
|
||||||
|
|
||||||
} // useAbbrTable
|
} // useAbbrTable
|
||||||
|
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
|
@ -147,8 +151,9 @@ uint32_t interpreterDecodeZSCII(uint32_t zstr, bool abbr, char *buf, uint32_t *b
|
||||||
|
|
||||||
if (printVal) {
|
if (printVal) {
|
||||||
decodedChars++;
|
decodedChars++;
|
||||||
if (bufPtr < *bufLen) {
|
if (bufLen) {
|
||||||
buf[bufPtr++] = printVal;
|
*(buf++) = printVal;
|
||||||
|
bufLen--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,9 +164,9 @@ uint32_t interpreterDecodeZSCII(uint32_t zstr, bool abbr, char *buf, uint32_t *b
|
||||||
// There is no NULL terminator, you look for a word with the top bit set.
|
// There is no NULL terminator, you look for a word with the top bit set.
|
||||||
} while ((code & (1 << 15)) == 0);
|
} while ((code & (1 << 15)) == 0);
|
||||||
|
|
||||||
*bufLen = decodedChars;
|
*bufLenP = decodedChars;
|
||||||
|
|
||||||
return pc;
|
return pc - zstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -182,14 +187,14 @@ char interpreterDecodeZSCIIChar(uint16_t z) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void interpreterDoBranch(int32_t b) {
|
void interpreterDoBranch(int32_t truth) {
|
||||||
uint8_t branch = __state.pc++;
|
uint8_t branch = PEEK(__state.pc++);
|
||||||
int32_t farJump = (branch & (1 << 6)) == 0;
|
int32_t farJump = (branch & (1 << 6)) == 0;
|
||||||
int32_t onTruth = (branch & (1 << 7)) ? 1 : 0;
|
int32_t onTruth = (branch & (1 << 7)) ? 1 : 0;
|
||||||
uint8_t byte2 = farJump ? __state.pc++ : 0;
|
uint8_t byte2 = farJump ? PEEK(__state.pc++) : 0;
|
||||||
int16_t offset;
|
int16_t offset;
|
||||||
|
|
||||||
if (onTruth == b) {
|
if (onTruth == truth) {
|
||||||
offset = (int16_t)(branch & 0x3f);
|
offset = (int16_t)(branch & 0x3f);
|
||||||
if (farJump) {
|
if (farJump) {
|
||||||
if (offset & (1 << 5)) offset |= 0xc0;
|
if (offset & (1 << 5)) offset |= 0xc0;
|
||||||
|
@ -208,11 +213,15 @@ void interpreterDoBranch(int32_t b) {
|
||||||
|
|
||||||
void interpreterDoReturn(uint16_t r) {
|
void interpreterDoReturn(uint16_t r) {
|
||||||
uint8_t storeId;
|
uint8_t storeId;
|
||||||
uint8_t store;
|
|
||||||
|
|
||||||
// Newer versions start in a real routine, but still aren't allowed to return from it.
|
//***TODO*** Newer versions start in a real routine, but still aren't allowed to return from it.
|
||||||
|
|
||||||
if (__state.bp == 0) portDie(MSG_INT_STACK_UNDERFLOW);
|
if (__state.bp == 0) portDie(MSG_INT_STACK_UNDERFLOW);
|
||||||
|
|
||||||
|
#ifdef DEBUGGING
|
||||||
|
printf("Returning: initial pc=%X, bp=%u, sp=%u\n", __state.pc, __state.bp, __state.sp);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Dump all locals and data pushed on stack during the routine.
|
// Dump all locals and data pushed on stack during the routine.
|
||||||
__state.sp = __state.bp;
|
__state.sp = __state.bp;
|
||||||
// Dump our copy of numLocals.
|
// Dump our copy of numLocals.
|
||||||
|
@ -226,14 +235,18 @@ void interpreterDoReturn(uint16_t r) {
|
||||||
|
|
||||||
// Pop the result storage location.
|
// Pop the result storage location.
|
||||||
storeId = (uint8_t)__state.stack[--__state.sp];
|
storeId = (uint8_t)__state.stack[--__state.sp];
|
||||||
|
|
||||||
|
#ifdef DEBUGGING
|
||||||
|
printf("Returning: new pc=%X, bp=%u, sp=%u\n", __state.pc, __state.bp, __state.sp);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Store the routine result.
|
// Store the routine result.
|
||||||
store = interpreterVariableAddress(storeId, 1);
|
interpreterStoreVariable(storeId, r);
|
||||||
POKEW(store, r);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t interpreterGetObjectPointer(uint16_t objectId) {
|
uint32_t interpreterGetObjectPointer(uint16_t objectId) {
|
||||||
uint8_t ptr;
|
uint32_t ptr;
|
||||||
|
|
||||||
if (objectId == 0) portDie(MSG_INT_OBJECT0_REF);
|
if (objectId == 0) portDie(MSG_INT_OBJECT0_REF);
|
||||||
if ((storyVersion() <= 3) && (objectId > 255)) portDie(MSG_INT_OBJECT_BAD_ID);
|
if ((storyVersion() <= 3) && (objectId > 255)) portDie(MSG_INT_OBJECT_BAD_ID);
|
||||||
|
@ -247,7 +260,7 @@ uint8_t interpreterGetObjectPointer(uint16_t objectId) {
|
||||||
|
|
||||||
|
|
||||||
uint8_t interpreterGetObjectProperty(uint16_t objectId, uint32_t propertyId, uint8_t *size) {
|
uint8_t interpreterGetObjectProperty(uint16_t objectId, uint32_t propertyId, uint8_t *size) {
|
||||||
uint8_t ptr = interpreterGetObjectPointer(objectId);
|
uint32_t ptr = interpreterGetObjectPointer(objectId);
|
||||||
uint16_t addr;
|
uint16_t addr;
|
||||||
uint8_t info;
|
uint8_t info;
|
||||||
uint16_t num;
|
uint16_t num;
|
||||||
|
@ -282,9 +295,20 @@ uint8_t interpreterGetObjectProperty(uint16_t objectId, uint32_t propertyId, uin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool interpreterParseOperand(uint8_t opType, uint8_t operandId) {
|
uint32_t interpreterGlobalVariableAddress(uint16_t var) {
|
||||||
uint8_t addr;
|
return storyGlobalVariableTableAddress() + ((var - 0x10) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t interpreterLoadVariable(uint16_t var) {
|
||||||
|
// Is it on the stack?
|
||||||
|
if (var < 16) return __state.stack[interpreterVariableAddress(var, 0)];
|
||||||
|
// Nope, global.
|
||||||
|
return PEEKW(interpreterGlobalVariableAddress(var));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool interpreterParseOperand(uint8_t opType, uint8_t operandId) {
|
||||||
switch(opType) {
|
switch(opType) {
|
||||||
// Large constant.
|
// Large constant.
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -299,8 +323,7 @@ bool interpreterParseOperand(uint8_t opType, uint8_t operandId) {
|
||||||
|
|
||||||
// Variable.
|
// Variable.
|
||||||
case 2:
|
case 2:
|
||||||
addr = interpreterVariableAddress(PEEK(__state.pc++), 0);
|
__state.operands[operandId] = interpreterLoadVariable(PEEK(__state.pc++));
|
||||||
__state.operands[operandId] = PEEKW(addr);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,6 +373,7 @@ void interpreterRun(void) {
|
||||||
uint8_t opcode;
|
uint8_t opcode;
|
||||||
bool extended;
|
bool extended;
|
||||||
opcodeT op;
|
opcodeT op;
|
||||||
|
bool eight;
|
||||||
|
|
||||||
while (__state.quit == 0) {
|
while (__state.quit == 0) {
|
||||||
opcode = PEEK(__state.pc++);
|
opcode = PEEK(__state.pc++);
|
||||||
|
@ -378,7 +402,8 @@ void interpreterRun(void) {
|
||||||
__state.operandCount = 0;
|
__state.operandCount = 0;
|
||||||
} else if (opcode > 191) {
|
} else if (opcode > 191) {
|
||||||
// Variable Opcodes
|
// Variable Opcodes
|
||||||
if ((opcode == 236) || (opcode == 250)) {
|
eight = (opcode == 236) || (opcode == 250);
|
||||||
|
if (!eight) {
|
||||||
// call_vs2 and call_vn2 take up to EIGHT arguments!
|
// call_vs2 and call_vn2 take up to EIGHT arguments!
|
||||||
__state.operandCount = interpreterParseVariableOperands(0);
|
__state.operandCount = interpreterParseVariableOperands(0);
|
||||||
} else {
|
} else {
|
||||||
|
@ -413,17 +438,38 @@ void interpreterRun(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void interpreterStoreVariable(uint16_t var, uint16_t value) {
|
||||||
|
uint32_t addr;
|
||||||
|
|
||||||
|
if (var < 16) {
|
||||||
|
// On stack.
|
||||||
|
addr = interpreterVariableAddress(var, 1);
|
||||||
|
__state.stack[addr] = value;
|
||||||
|
} else {
|
||||||
|
// Global.
|
||||||
|
addr = interpreterGlobalVariableAddress(var);
|
||||||
|
POKEW(addr, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t interpreterVariableAddress(uint8_t var, bool writing) {
|
uint8_t interpreterVariableAddress(uint8_t var, bool writing) {
|
||||||
uint16_t numLocals;
|
uint16_t numLocals;
|
||||||
|
|
||||||
if (var == 0) { // top of stack
|
if (var == 0) { // top of stack
|
||||||
if (writing) {
|
if (writing) {
|
||||||
if (__state.sp >= sizeof(__state.stack)) portDie(MSG_INT_STACK_OVERFLOW);
|
if (__state.sp >= sizeof(__state.stack)) portDie(MSG_INT_STACK_OVERFLOW);
|
||||||
|
#ifdef DEBUGGING
|
||||||
|
printf("Push stack\n");
|
||||||
|
#endif
|
||||||
return __state.sp++;
|
return __state.sp++;
|
||||||
} else {
|
} else {
|
||||||
if (__state.sp == 0) portDie(MSG_INT_STACK_UNDERFLOW);
|
if (__state.sp == 0) portDie(MSG_INT_STACK_UNDERFLOW);
|
||||||
numLocals = __state.bp ? __state.stack[__state.bp - 1] : 0;
|
numLocals = __state.bp ? __state.stack[__state.bp - 1] : 0;
|
||||||
if ((__state.bp + numLocals) >= sizeof(__state.stack)) portDie(MSG_INT_STACK_UNDERFLOW);
|
if ((__state.bp + numLocals) >= sizeof(__state.stack)) portDie(MSG_INT_STACK_UNDERFLOW);
|
||||||
|
#ifdef DEBUGGING
|
||||||
|
printf("Pop stack\n");
|
||||||
|
#endif
|
||||||
return --__state.sp;
|
return --__state.sp;
|
||||||
} // writing
|
} // writing
|
||||||
} // var
|
} // var
|
||||||
|
|
|
@ -87,7 +87,7 @@ void memoryLoadStory(void) {
|
||||||
// Alphabet A2
|
// Alphabet A2
|
||||||
*(p++) = 0;
|
*(p++) = 0;
|
||||||
if (storyVersion() != 1) *(p++) = '\n';
|
if (storyVersion() != 1) *(p++) = '\n';
|
||||||
for (i=0; i<10; i++) *(p++) = 'o' + i;
|
for (i=0; i<10; i++) *(p++) = '0' + i;
|
||||||
*(p++) = '.';
|
*(p++) = '.';
|
||||||
*(p++) = ',';
|
*(p++) = ',';
|
||||||
*(p++) = '!';
|
*(p++) = '!';
|
||||||
|
@ -112,8 +112,8 @@ void memorySetByte(uint16_t address, uint8_t value) {
|
||||||
|
|
||||||
|
|
||||||
void memorySetWord(uint16_t address, uint16_t value) {
|
void memorySetWord(uint16_t address, uint16_t value) {
|
||||||
_RAM[address] = (value & 0xff00) >> 8; // MSB first.
|
_RAM[address] = (value >> 8) & 0xff; // MSB first.
|
||||||
_RAM[address + 1] = value & 0x00ff;
|
_RAM[address + 1] = value & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
20
src/oc_2op.c
20
src/oc_2op.c
|
@ -31,8 +31,7 @@
|
||||||
|
|
||||||
|
|
||||||
void opcodes_add(void) {
|
void opcodes_add(void) {
|
||||||
uint8_t store = interpreterVariableAddress(PEEK(__state.pc++), 1);
|
interpreterStoreVariable(PEEK(__state.pc++), __state.operands[0] + __state.operands[1]);
|
||||||
POKEW(store, ((int16_t)__state.operands[0]) + ((int16_t)__state.operands[1]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,40 +40,39 @@ void opcodes_je(void) {
|
||||||
int8_t i;
|
int8_t i;
|
||||||
|
|
||||||
for (i=1; i<__state.operandCount; i++) {
|
for (i=1; i<__state.operandCount; i++) {
|
||||||
if (a == __state.operands[i]) interpreterDoBranch(1);
|
if (a == __state.operands[i]) {
|
||||||
|
interpreterDoBranch(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interpreterDoBranch(0);
|
interpreterDoBranch(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void opcodes_loadw(void) {
|
void opcodes_loadw(void) {
|
||||||
uint16_t store = interpreterVariableAddress(PEEK(__state.pc++), 1);
|
|
||||||
uint16_t offset = __state.operands[0] + (__state.operands[1] * 2);
|
uint16_t offset = __state.operands[0] + (__state.operands[1] * 2);
|
||||||
POKEW(store, PEEKW(offset));
|
interpreterStoreVariable(PEEK(__state.pc++), PEEKW(offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void opcodes_store(void) {
|
void opcodes_store(void) {
|
||||||
uint8_t store = interpreterVariableAddress((uint8_t)(__state.operands[0] & 0xFF), 1);
|
interpreterStoreVariable((__state.operands[0] & 0xFF), __state.operands[1]);
|
||||||
POKEW(store, __state.operands[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void opcodes_sub(void) {
|
void opcodes_sub(void) {
|
||||||
uint8_t store = interpreterVariableAddress(PEEK(__state.pc++), 1);
|
interpreterStoreVariable(PEEK(__state.pc++), __state.operands[0] - __state.operands[1]);
|
||||||
POKEW(store, ((int16_t)__state.operands[0]) - ((int16_t)__state.operands[1]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void opcodes_test_attr(void) {
|
void opcodes_test_attr(void) {
|
||||||
uint8_t ptr = interpreterGetObjectPointer(__state.operands[0]);
|
uint32_t ptr = interpreterGetObjectPointer(__state.operands[0]);
|
||||||
uint16_t attrId = __state.operands[1];
|
uint16_t attrId = __state.operands[1];
|
||||||
|
|
||||||
if (storyVersion() <= 3) {
|
if (storyVersion() <= 3) {
|
||||||
ptr += (attrId / 8);
|
ptr += (attrId / 8);
|
||||||
interpreterDoBranch((ptr & (0x80 >> (attrId & 7))) ? 1 : 0);
|
interpreterDoBranch((PEEK(ptr) & (0x80 >> (attrId & 7))) ? 1 : 0);
|
||||||
} else {
|
} else {
|
||||||
portDie(MSG_UNIMPLEMENTED);
|
portDie(MSG_UNIMPLEMENTED);
|
||||||
}
|
}
|
||||||
|
|
331
src/opcodes.c
331
src/opcodes.c
|
@ -34,226 +34,215 @@
|
||||||
|
|
||||||
// Macros to declare implemented opcodes.
|
// Macros to declare implemented opcodes.
|
||||||
#ifdef DEBUGGING
|
#ifdef DEBUGGING
|
||||||
#define OP(name) __state.opcodes[_nextOpcode] = opcodes_##name; __state.opcodesName[_nextOpcode++] = #name
|
#define OP(num, name) __state.opcodes[num] = opcodes_##name; __state.opcodesName[num] = #name
|
||||||
#define OPn(num, name) __state.opcodes[num] = opcodes_##name; __state.opcodesName[num] = #name
|
#define OPX(num, name) __state.extOpcodes[num] = opcodes_ext_##name; __state.extOpcodes[num] = #name
|
||||||
#define OPX(name) __state.extOpcodes[_nextOpcode] = opcodes_ext_##name; __state.extOpcodesName[_nextOpcode++] = #name
|
|
||||||
#define OPXn(num, name) __state.extOpcodes[num] = opcodes_ext_##name; __state.extOpcodes[num] = #name
|
|
||||||
#else
|
#else
|
||||||
#define OP(name) __state.opcodes[_nextOpcode++] = opcodes_##name
|
#define OP(num, name) __state.opcodes[num] = opcodes_##name
|
||||||
#define OPn(num, name) __state.opcodes[num] = opcodes_##name
|
#define OPX(num, name) __state.extOpcodes[num] = opcodes_ext_##name
|
||||||
#define OPX(name) __state.extOpcodes[_nextOpcode++] = opcodes_ext_##name
|
|
||||||
#define OPXn(num, name) __state.extOpcodes[num] = opcodes_ext_##name
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Macros to declare un-implemented opcodes.
|
// Macros to declare un-implemented opcodes.
|
||||||
#define mOP(name) _nextOpcode++
|
#define mOP(num, name)
|
||||||
#define mOPn(num, name)
|
#define mOPX(num, name)
|
||||||
#define mOPX(name) _nextOpcode++
|
|
||||||
#define mOPXn(num, name)
|
|
||||||
|
|
||||||
|
|
||||||
int16_t _nextOpcode;
|
|
||||||
|
|
||||||
|
|
||||||
void opcodesBuiltInitialTable(void) {
|
void opcodesBuiltInitialTable(void) {
|
||||||
// 2-operand instructions...
|
// 2-operand instructions...
|
||||||
_nextOpcode = 1;
|
OP(1, je);
|
||||||
OP(je);
|
mOP(2, jl);
|
||||||
mOP(jl);
|
mOP(3, jg);
|
||||||
mOP(jg);
|
mOP(4, dec_chk);
|
||||||
mOP(dec_chk);
|
mOP(5, inc_chk);
|
||||||
mOP(inc_chk);
|
mOP(6, jin);
|
||||||
mOP(jin);
|
mOP(7, test);
|
||||||
mOP(test);
|
mOP(8, or);
|
||||||
mOP(or);
|
mOP(9, and);
|
||||||
mOP(and);
|
OP(10, test_attr);
|
||||||
OP(test_attr);
|
mOP(11, set_attr);
|
||||||
mOP(set_attr);
|
mOP(12, clear_attr);
|
||||||
mOP(clear_attr);
|
OP(13, store);
|
||||||
OP(store);
|
mOP(14, insert_obj);
|
||||||
mOP(insert_obj);
|
OP(15, loadw);
|
||||||
OP(loadw);
|
mOP(16, loadb);
|
||||||
mOP(loadb);
|
mOP(17, get_prop);
|
||||||
mOP(get_prop);
|
mOP(18, get_prop_addr);
|
||||||
mOP(get_prop_addr);
|
mOP(19, get_next_prop);
|
||||||
mOP(get_next_prop);
|
OP(20, add);
|
||||||
OP(add);
|
OP(21, sub);
|
||||||
OP(sub);
|
mOP(22, mul);
|
||||||
mOP(mul);
|
mOP(23, div);
|
||||||
mOP(div);
|
mOP(24, mod);
|
||||||
mOP(mod); // oc# 24
|
|
||||||
|
|
||||||
// 1-operand instructions...
|
// 1-operand instructions...
|
||||||
_nextOpcode = 128;
|
OP(128, jz);
|
||||||
OP(jz);
|
mOP(129, get_sibling);
|
||||||
mOP(get_sibling);
|
mOP(130, get_child);
|
||||||
mOP(get_child);
|
mOP(131, get_parent);
|
||||||
mOP(get_parent);
|
mOP(132, get_prop_len);
|
||||||
mOP(get_prop_len);
|
mOP(133, inc);
|
||||||
mOP(inc);
|
mOP(134, dec);
|
||||||
mOP(dec); // oc# 135
|
mOP(135, print_addr);
|
||||||
|
|
||||||
_nextOpcode = 137;
|
mOP(137, remove_obj);
|
||||||
mOP(print_addr);
|
mOP(138, print_obj);
|
||||||
mOP(remove_obj);
|
OP(139, ret);
|
||||||
mOP(print_obj);
|
OP(140, jump);
|
||||||
OP(ret);
|
mOP(141, print_paddr);
|
||||||
OP(jump);
|
mOP(142, load);
|
||||||
mOP(print_paddr);
|
mOP(143, not);
|
||||||
mOP(load);
|
|
||||||
mOP(not); // oc# 143
|
|
||||||
|
|
||||||
// 0-operand instructions...
|
// 0-operand instructions...
|
||||||
_nextOpcode = 176;
|
mOP(176, rtrue);
|
||||||
mOP(rtrue);
|
mOP(177, rfalse);
|
||||||
mOP(rfalse);
|
OP(178, print);
|
||||||
OP(print);
|
mOP(179, print_ret);
|
||||||
mOP(print_ret);
|
mOP(180, nop);
|
||||||
mOP(nop);
|
mOP(181, save);
|
||||||
mOP(save);
|
mOP(182, restore);
|
||||||
mOP(restore);
|
mOP(183, restart);
|
||||||
mOP(restart);
|
mOP(184, ret_popped);
|
||||||
mOP(ret_popped);
|
mOP(185, pop);
|
||||||
mOP(pop);
|
mOP(186, quit);
|
||||||
mOP(quit);
|
OP(187, new_line);
|
||||||
OP(new_line); // oc# 187
|
|
||||||
|
|
||||||
// variable operand instructions...
|
// variable operand instructions...
|
||||||
_nextOpcode = 224;
|
OP(224, call);
|
||||||
OP(call);
|
OP(225, storew);
|
||||||
OP(storew);
|
mOP(226, storeb);
|
||||||
mOP(storeb);
|
OP(227, put_prop);
|
||||||
OP(put_prop);
|
mOP(228, read);
|
||||||
mOP(read);
|
mOP(229, print_char);
|
||||||
mOP(print_char);
|
mOP(230, print_num);
|
||||||
mOP(print_num);
|
mOP(231, random);
|
||||||
mOP(random);
|
mOP(232, push);
|
||||||
mOP(push);
|
mOP(233, pull);
|
||||||
mOP(pull); // oc# 233
|
|
||||||
|
|
||||||
if (storyVersion() < 3) return;
|
if (storyVersion() < 3) return;
|
||||||
|
|
||||||
_nextOpcode = 188;
|
mOP(188, show_status);
|
||||||
mOP(show_status);
|
mOP(189, verify);
|
||||||
mOP(verify); // oc# 189
|
|
||||||
|
|
||||||
_nextOpcode = 234;
|
mOP(234, split_window);
|
||||||
mOP(split_window);
|
mOP(235, set_window);
|
||||||
mOP(set_window); // oc# 235
|
|
||||||
|
|
||||||
_nextOpcode = 243;
|
mOP(243, output_stream);
|
||||||
mOP(output_stream);
|
mOP(244, input_stream);
|
||||||
mOP(input_stream);
|
mOP(245, sound_effect);
|
||||||
mOP(sound_effect); // oc# 245
|
|
||||||
|
|
||||||
if (storyVersion() < 4) return;
|
if (storyVersion() < 4) return;
|
||||||
|
|
||||||
// show_status is illegal in ver4+, but a build of Wishbringer
|
// show_status is illegal in ver4+, but a build of Wishbringer
|
||||||
// accidentally calls it, so always treat it as NOP instead.
|
// accidentally calls it, so always treat it as NOP instead.
|
||||||
mOPn(188, opcode_nop);
|
mOP(188, opcode_nop);
|
||||||
mOPn(25, call_2s);
|
|
||||||
mOPn(180, save_ver4);
|
|
||||||
mOPn(224, call_vs);
|
|
||||||
mOPn(228, sread_ver4);
|
|
||||||
|
|
||||||
_nextOpcode = 236;
|
mOP(25, call_2s);
|
||||||
mOP(call_vs2);
|
|
||||||
mOP(erase_window);
|
|
||||||
mOP(erase_line);
|
|
||||||
mOP(set_cursor);
|
|
||||||
mOP(get_cursor);
|
|
||||||
mOP(set_text_style);
|
|
||||||
mOP(buffer_mode); // oc# 242
|
|
||||||
|
|
||||||
_nextOpcode = 246;
|
mOP(180, save_ver4);
|
||||||
mOP(read_char);
|
|
||||||
mOP(scan_table); // oc# 247
|
mOP(224, call_vs);
|
||||||
|
|
||||||
|
mOP(228, sread_ver4);
|
||||||
|
|
||||||
|
mOP(236, call_vs2);
|
||||||
|
mOP(237, erase_window);
|
||||||
|
mOP(238, erase_line);
|
||||||
|
mOP(239, set_cursor);
|
||||||
|
mOP(240, get_cursor);
|
||||||
|
mOP(241, set_text_style);
|
||||||
|
mOP(242, buffer_mode);
|
||||||
|
|
||||||
|
mOP(246, read_char);
|
||||||
|
mOP(247, scan_table);
|
||||||
|
|
||||||
if (storyVersion() < 5) return;
|
if (storyVersion() < 5) return;
|
||||||
|
|
||||||
_nextOpcode = 26;
|
mOP(26, call_2n);
|
||||||
mOP(call_2n);
|
mOP(27, set_color);
|
||||||
mOP(set_colour);
|
mOP(28, throw);
|
||||||
mOP(throw);
|
|
||||||
|
|
||||||
mOPn(136, call_1s);
|
mOP(136, call_1s);
|
||||||
mOPn(143, call_1n);
|
|
||||||
mOPn(185, catch);
|
|
||||||
mOPn(191, piracy);
|
|
||||||
mOPn(228, aread);
|
|
||||||
mOPn(243, output_stream_ver5);
|
|
||||||
mOPn(245, sound_effect_ver5);
|
|
||||||
|
|
||||||
_nextOpcode = 248;
|
mOP(143, call_1n);
|
||||||
mOP(not_ver5);
|
|
||||||
mOP(call_vn);
|
mOP(185, catch);
|
||||||
mOP(call_vn2);
|
|
||||||
mOP(tokenise);
|
mOP(191, piracy);
|
||||||
mOP(encode_text);
|
|
||||||
mOP(copy_table);
|
mOP(228, aread);
|
||||||
mOP(print_table);
|
|
||||||
mOP(check_arg_count); // oc# 255
|
mOP(243, output_stream_ver5);
|
||||||
|
|
||||||
|
mOP(245, sound_effect_ver5);
|
||||||
|
|
||||||
|
mOP(248, not_ver5);
|
||||||
|
mOP(249, call_vn);
|
||||||
|
mOP(250, call_vn2);
|
||||||
|
mOP(251, tokenise);
|
||||||
|
mOP(252, encode_text);
|
||||||
|
mOP(253, copy_table);
|
||||||
|
mOP(254, print_table);
|
||||||
|
mOP(255, check_arg_count);
|
||||||
|
|
||||||
// this is the "save" and "restore" opcodes in ver1-4; illegal in ver5+.
|
// this is the "save" and "restore" opcodes in ver1-4; illegal in ver5+.
|
||||||
// in ver5+, they use extended opcodes 0 and 1 for these.
|
// in ver5+, they use extended opcodes 0 and 1 for these.
|
||||||
__state.opcodes[180] = 0;
|
__state.opcodes[180] = 0;
|
||||||
__state.opcodes[181] = 0;
|
__state.opcodes[181] = 0;
|
||||||
|
#ifdef DEBUGGING
|
||||||
|
__state.opcodesName[180] = 0;
|
||||||
|
__state.opcodesName[181] = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
// extended opcodes in ver5+ ...
|
// extended opcodes in ver5+ ...
|
||||||
_nextOpcode = 0;
|
mOPX(0, save_ext);
|
||||||
mOPX(save_ext);
|
mOPX(1, restore_ext);
|
||||||
mOPX(restore_ext);
|
mOPX(2, log_shift);
|
||||||
mOPX(log_shift);
|
mOPX(3, art_shift);
|
||||||
mOPX(art_shift);
|
mOPX(4, set_font);
|
||||||
mOPX(set_font); // xop# 4
|
|
||||||
|
|
||||||
_nextOpcode = 9;
|
mOPX(9, save_undo);
|
||||||
mOPX(save_undo);
|
mOPX(10, restore_undo);
|
||||||
mOPX(restore_undo);
|
mOPX(11, print_unicode);
|
||||||
mOPX(print_unicode);
|
mOPX(12, check_unicode);
|
||||||
mOPX(check_unicode);
|
mOPX(13, set_true_color);
|
||||||
mOPX(set_true_colour); // xop# 13
|
|
||||||
|
|
||||||
if (storyVersion() < 6) return;
|
if (storyVersion() < 6) return;
|
||||||
|
|
||||||
_nextOpcode = 27;
|
mOP(27, set_color_ver6);
|
||||||
mOP(set_colour_ver6);
|
mOP(28, throw_ver6);
|
||||||
mOP(throw_ver6); // op# 28
|
|
||||||
|
|
||||||
mOPn(185, catch_ver6);
|
mOP(185, catch_ver6);
|
||||||
mOPn(233, pull_ver6);
|
|
||||||
|
|
||||||
_nextOpcode = 238;
|
mOP(233, pull_ver6);
|
||||||
mOP(erase_line_ver6);
|
|
||||||
mOP(set_cursor_ver6); // op# 239
|
|
||||||
|
|
||||||
mOPn(243, output_stream_ver6);
|
mOP(238, erase_line_ver6);
|
||||||
mOPn(248, not_ver6);
|
mOP(239, set_cursor_ver6);
|
||||||
|
|
||||||
_nextOpcode = 4;
|
mOP(243, output_stream_ver6);
|
||||||
mOPX(set_font_ver6);
|
|
||||||
mOPX(draw_picture);
|
|
||||||
mOPX(picture_data);
|
|
||||||
mOPX(erase_picture);
|
|
||||||
mOPX(set_margins); // xop# 8
|
|
||||||
|
|
||||||
mOPXn(13, set_true_colour_ver6);
|
mOP(248, not_ver6);
|
||||||
|
|
||||||
_nextOpcode = 16;
|
mOPX(4, set_font_ver6);
|
||||||
mOPX(move_window);
|
mOPX(5, draw_picture);
|
||||||
mOPX(window_size);
|
mOPX(6, picture_data);
|
||||||
mOPX(window_style);
|
mOPX(7, erase_picture);
|
||||||
mOPX(get_wind_prop);
|
mOPX(8, set_margins); // xop# 8
|
||||||
mOPX(scroll_window);
|
|
||||||
mOPX(pop_stack);
|
mOPX(13, set_true_color_ver6);
|
||||||
mOPX(read_mouse);
|
|
||||||
mOPX(mouse_window);
|
mOPX(16, move_window);
|
||||||
mOPX(push_stack);
|
mOPX(17, window_size);
|
||||||
mOPX(put_wind_prop);
|
mOPX(18, window_style);
|
||||||
mOPX(print_form);
|
mOPX(19, get_wind_prop);
|
||||||
mOPX(make_menu);
|
mOPX(20, scroll_window);
|
||||||
mOPX(picture_table);
|
mOPX(21, pop_stack);
|
||||||
mOPX(buffer_screen); // xop# 29
|
mOPX(22, read_mouse);
|
||||||
|
mOPX(23, mouse_window);
|
||||||
|
mOPX(24, push_stack);
|
||||||
|
mOPX(25, put_wind_prop);
|
||||||
|
mOPX(26, print_form);
|
||||||
|
mOPX(27, make_menu);
|
||||||
|
mOPX(28, picture_table);
|
||||||
|
mOPX(29, buffer_screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue