Beta 1 for F256!
This commit is contained in:
parent
52c03bb42c
commit
25f8ccc72d
18 changed files with 268 additions and 69 deletions
|
@ -28,6 +28,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
|
void portAttributeSet(byte attribute);
|
||||||
uint8_t portByteGet(uint32_t address);
|
uint8_t portByteGet(uint32_t address);
|
||||||
void portByteSet(uint32_t address, uint8_t value);
|
void portByteSet(uint32_t address, uint8_t value);
|
||||||
char portCharGet(void);
|
char portCharGet(void);
|
||||||
|
|
|
@ -40,6 +40,7 @@ typedef struct stateS {
|
||||||
uint8_t operandCount;
|
uint8_t operandCount;
|
||||||
uint16_t operands[8];
|
uint16_t operands[8];
|
||||||
char alphabetTable[78];
|
char alphabetTable[78];
|
||||||
|
uint16_t checksum;
|
||||||
char statusBar[256];
|
char statusBar[256];
|
||||||
byte statusBarLen;
|
byte statusBarLen;
|
||||||
byte currentWindow;
|
byte currentWindow;
|
||||||
|
@ -48,6 +49,7 @@ typedef struct stateS {
|
||||||
byte savedY;
|
byte savedY;
|
||||||
bool outputting;
|
bool outputting;
|
||||||
bool redirecting;
|
bool redirecting;
|
||||||
|
byte linesOut;
|
||||||
#ifdef DEBUGGING
|
#ifdef DEBUGGING
|
||||||
char *opcodesName[256];
|
char *opcodesName[256];
|
||||||
char *extOpcodesName[30];
|
char *extOpcodesName[30];
|
||||||
|
|
|
@ -118,6 +118,7 @@
|
||||||
#define storyHXTrueDefaultBackgroundColor() portWordGet(storyHeaderExtensionTableAddress() + 12)
|
#define storyHXTrueDefaultBackgroundColor() portWordGet(storyHeaderExtensionTableAddress() + 12)
|
||||||
|
|
||||||
|
|
||||||
|
void storyChecksumCalculate(void);
|
||||||
uint32_t storyLength(void);
|
uint32_t storyLength(void);
|
||||||
void storySetup(byte width, byte height);
|
void storySetup(byte width, byte height);
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef TEXT_H
|
#ifndef TEXT_ZIP_H
|
||||||
#define TEXT_H
|
#define TEXT_ZIP_H
|
||||||
|
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
@ -33,6 +33,12 @@
|
||||||
#define STREAM_OUTPUT_MEMORY 3
|
#define STREAM_OUTPUT_MEMORY 3
|
||||||
#define STREAM_OUTPUT_SCRIPT 4
|
#define STREAM_OUTPUT_SCRIPT 4
|
||||||
|
|
||||||
|
#define TEXT_ATTR_NORMAL 0
|
||||||
|
#define TEXT_ATTR_REVERSE 1
|
||||||
|
#define TEXT_ATTR_BOLD 2
|
||||||
|
#define TEXT_ATTR_EMPHASIS 4
|
||||||
|
#define TEXT_ATTR_FIXED_FONT 8
|
||||||
|
|
||||||
|
|
||||||
void textCharPrint(char c);
|
void textCharPrint(char c);
|
||||||
void textInput(uint32_t ramAddr, uint8_t length);
|
void textInput(uint32_t ramAddr, uint8_t length);
|
||||||
|
@ -43,4 +49,4 @@ void textStringPrint(char *s);
|
||||||
void textTimePrint(uint16_t hours, uint16_t minutes);
|
void textTimePrint(uint16_t hours, uint16_t minutes);
|
||||||
|
|
||||||
|
|
||||||
#endif // TEXT_H
|
#endif // TEXT_ZIP_H
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.12)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
|
|
||||||
project(zip LANGUAGES C)
|
project(dos-like-zip LANGUAGES C)
|
||||||
|
|
||||||
find_package(SDL2 REQUIRED)
|
find_package(SDL2 REQUIRED)
|
||||||
|
|
||||||
|
@ -30,8 +30,6 @@ set(HEADERS
|
||||||
variable.h
|
variable.h
|
||||||
window.h
|
window.h
|
||||||
zscii.h
|
zscii.h
|
||||||
# czech.z3.h
|
|
||||||
zork1.h
|
|
||||||
)
|
)
|
||||||
list(TRANSFORM HEADERS PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/../../include/")
|
list(TRANSFORM HEADERS PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/../../include/")
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,7 @@
|
||||||
#include "story.h"
|
#include "story.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
#include "text.h"
|
||||||
#include "zork1.h"
|
|
||||||
//#include "czech.z3.h"
|
|
||||||
|
|
||||||
#pragma push_macro("bool")
|
#pragma push_macro("bool")
|
||||||
#undef bool
|
#undef bool
|
||||||
|
@ -41,8 +39,38 @@
|
||||||
#pragma pop_macro("bool")
|
#pragma pop_macro("bool")
|
||||||
|
|
||||||
|
|
||||||
// The F256 has 512k of RAM. We use everything except the lower 64k.
|
static char *_storyFile = NULL;
|
||||||
static uint8_t _RAM[1024 * (512 - 64)];
|
static uint8_t *_RAM = NULL;
|
||||||
|
static uint8_t _attr = 7;
|
||||||
|
|
||||||
|
|
||||||
|
void portAttributeSet(byte attribute) {
|
||||||
|
switch (attribute) {
|
||||||
|
case TEXT_ATTR_NORMAL:
|
||||||
|
textbackground(1);
|
||||||
|
textcolor(7);
|
||||||
|
_attr = (1 << 4) + 7;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEXT_ATTR_REVERSE:
|
||||||
|
textbackground(7);
|
||||||
|
textcolor(1);
|
||||||
|
_attr = (7 << 4) + 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEXT_ATTR_BOLD:
|
||||||
|
textbackground(1);
|
||||||
|
textcolor(15);
|
||||||
|
_attr = (1 << 4) + 15;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEXT_ATTR_EMPHASIS:
|
||||||
|
textbackground(1);
|
||||||
|
textcolor(14);
|
||||||
|
_attr = (1 << 4) + 14;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t portByteGet(uint32_t address) {
|
uint8_t portByteGet(uint32_t address) {
|
||||||
|
@ -85,13 +113,17 @@ void portCharGetPos(byte *x, byte *y) {
|
||||||
|
|
||||||
|
|
||||||
void portCharPrint(char c) {
|
void portCharPrint(char c) {
|
||||||
char ch[2] = { 0, 0 };
|
char ch[2] = { 0, 0 };
|
||||||
|
uint16_t *p;
|
||||||
|
uint16_t v = (_attr << 8) + ' ';
|
||||||
|
byte x;
|
||||||
|
|
||||||
if ((wherex() >= screenwidth()) || (c == '\n')) {
|
if ((wherex() >= screenwidth()) || (c == '\n')) {
|
||||||
gotoxy(0, wherey() + 1);
|
gotoxy(0, wherey() + 1);
|
||||||
while (wherey() >= screenheight()) {
|
while (wherey() >= screenheight()) {
|
||||||
memmove(((uint16_t*)screenbuffer()), ((uint16_t*)screenbuffer()) + screenwidth(), screenwidth() * (screenheight() - 1) * sizeof(uint16_t));
|
memmove(((uint16_t*)screenbuffer()), ((uint16_t*)screenbuffer()) + screenwidth(), screenwidth() * (screenheight() - 1) * sizeof(uint16_t));
|
||||||
memset(((uint16_t*)screenbuffer()) + screenwidth() * (screenheight() - 1), 0, screenwidth() * sizeof(uint16_t));
|
p = (uint16_t *)screenbuffer() + (screenwidth() * (screenheight() - 1));
|
||||||
|
for (x=0; x<screenwidth(); x++) *p++ = v;
|
||||||
gotoxy(0, wherey() - 1);
|
gotoxy(0, wherey() - 1);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -177,14 +209,41 @@ uint16_t portRandomGet(int16_t range) {
|
||||||
// If range is zero, randomize with "best" random seed.
|
// If range is zero, randomize with "best" random seed.
|
||||||
// If range is negative, use the positive value to seed.
|
// If range is negative, use the positive value to seed.
|
||||||
|
|
||||||
return 42;
|
if (range <= 0) {
|
||||||
|
srandom(range < 0 ? -range : time(NULL));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (random() % range) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void portStoryLoad(void) {
|
void portStoryLoad(void) {
|
||||||
// For now, we just copy an embedded Zork 1 into RAM.
|
FILE *in;
|
||||||
memcpy(_RAM, zork1, zork1_len);
|
uint32_t length;
|
||||||
//memcpy(_RAM, czech_z3, czech_z3_len);
|
|
||||||
|
in = fopen(_storyFile, "rb");
|
||||||
|
if (!in) portDie("Unable to open %s!\n", _storyFile);
|
||||||
|
|
||||||
|
fseek(in, 0, SEEK_END);
|
||||||
|
length = ftell(in);
|
||||||
|
fseek(in, 0, SEEK_SET);
|
||||||
|
|
||||||
|
_RAM = (byte *)malloc(length);
|
||||||
|
if (!_RAM) {
|
||||||
|
fclose(in);
|
||||||
|
portDie("Unable to allocate %u bytes!\n", length);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fread(_RAM, length, 1, in) != 1) {
|
||||||
|
free(_RAM);
|
||||||
|
fclose(in);
|
||||||
|
portDie("Unable to read %s!\n", _storyFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(in);
|
||||||
|
|
||||||
|
storyChecksumCalculate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -201,12 +260,16 @@ void portWordSet(uint32_t address, uint16_t value) {
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
(void)argc;
|
if (argc != 2) portDie("Usage: %s [storyfile]\n", argv[0]);
|
||||||
(void)argv;
|
|
||||||
|
_storyFile = argv[1];
|
||||||
|
|
||||||
setvideomode(videomode_80x25_9x16);
|
setvideomode(videomode_80x25_9x16);
|
||||||
curson();
|
curson();
|
||||||
|
textbackground(1);
|
||||||
|
textcolor(7);
|
||||||
clrscr();
|
clrscr();
|
||||||
|
gotoxy(0, screenheight() - 1);
|
||||||
|
|
||||||
stateReset();
|
stateReset();
|
||||||
portStoryLoad();
|
portStoryLoad();
|
||||||
|
@ -214,5 +277,7 @@ int main(int argc, char *argv[]) {
|
||||||
storySetup(80, 25);
|
storySetup(80, 25);
|
||||||
interpreterRun();
|
interpreterRun();
|
||||||
|
|
||||||
|
free(_RAM);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.12)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
|
|
||||||
project(zip LANGUAGES C)
|
project(f256-zip LANGUAGES C)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
common.h
|
common.h
|
||||||
|
@ -64,4 +64,8 @@ add_executable(${CMAKE_PROJECT_NAME}
|
||||||
f256zip.c
|
f256zip.c
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../include)
|
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../../include
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../../../f256/include
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../../../f256/f256lib
|
||||||
|
)
|
||||||
|
|
|
@ -33,7 +33,7 @@ PATH=${LLVM}/bin:${PATH}
|
||||||
|
|
||||||
echo "__f256_start = ${START};" > ${SETTINGS}
|
echo "__f256_start = ${START};" > ${SETTINGS}
|
||||||
|
|
||||||
CLANG="mos-f256k-clang -I../../../include -I${F256}/include -I${F256}/f256lib -Os"
|
CLANG="mos-f256k-clang -I${F256}/include -I../../../include -I${F256}/f256lib -Os"
|
||||||
|
|
||||||
[[ -d .builddir ]] && rm -rf .builddir
|
[[ -d .builddir ]] && rm -rf .builddir
|
||||||
mkdir -p .builddir
|
mkdir -p .builddir
|
||||||
|
|
|
@ -42,12 +42,36 @@
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
#include "lib.h"
|
#include "../../include/text.h"
|
||||||
|
|
||||||
|
|
||||||
#define BASE_ADDRESS 0x10000
|
#define BASE_ADDRESS 0x10000
|
||||||
|
|
||||||
|
|
||||||
|
static char *_saveName = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void portAttributeSet(byte attribute) {
|
||||||
|
switch (attribute) {
|
||||||
|
case TEXT_ATTR_NORMAL:
|
||||||
|
textSetColor(7, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEXT_ATTR_REVERSE:
|
||||||
|
textSetColor(1, 7);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEXT_ATTR_BOLD:
|
||||||
|
textSetColor(15, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEXT_ATTR_EMPHASIS:
|
||||||
|
textSetColor(14, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t portByteGet(uint32_t address) {
|
uint8_t portByteGet(uint32_t address) {
|
||||||
return FAR_PEEK(BASE_ADDRESS + address);
|
return FAR_PEEK(BASE_ADDRESS + address);
|
||||||
}
|
}
|
||||||
|
@ -97,7 +121,7 @@ bool portFileRestore(void) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
byte b;
|
byte b;
|
||||||
|
|
||||||
in = fopen("save.dat", "rb");
|
in = fopen(_saveName, "rb");
|
||||||
if (in) {
|
if (in) {
|
||||||
ok = true;
|
ok = true;
|
||||||
|
|
||||||
|
@ -128,7 +152,7 @@ bool portFileSave(void) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
byte b;
|
byte b;
|
||||||
|
|
||||||
out = fopen("save.dat", "wb");
|
out = fopen(_saveName, "wb");
|
||||||
if (out) {
|
if (out) {
|
||||||
ok = true;
|
ok = true;
|
||||||
|
|
||||||
|
@ -154,7 +178,7 @@ bool portFileSave(void) {
|
||||||
|
|
||||||
|
|
||||||
char portCharGet(void) {
|
char portCharGet(void) {
|
||||||
#if 1
|
#if 0
|
||||||
static char playback[] = "open mailbox\ntake leaflet\nread leaflet\ndrop leaflet\n";
|
static char playback[] = "open mailbox\ntake leaflet\nread leaflet\ndrop leaflet\n";
|
||||||
static uint32_t pointer = 0;
|
static uint32_t pointer = 0;
|
||||||
|
|
||||||
|
@ -183,10 +207,13 @@ uint16_t portRandomGet(int16_t range) {
|
||||||
void portStoryLoad(void) {
|
void portStoryLoad(void) {
|
||||||
|
|
||||||
// On the F256, the story is loaded into RAM along with the ZIP.
|
// On the F256, the story is loaded into RAM along with the ZIP.
|
||||||
|
// ***TODO*** This likely breaks the "restart" command.
|
||||||
|
|
||||||
// Later, we probably want to see if the user has a memory expansion
|
// Later, we probably want to see if the user has a memory expansion
|
||||||
// installed. If they do, we can use it and then use the lower memory
|
// installed. If they do, we can use it and then use the lower memory
|
||||||
// for graphics and sound.
|
// for graphics and sound.
|
||||||
|
|
||||||
|
storyChecksumCalculate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -201,15 +228,54 @@ void portWordSet(uint32_t address, uint16_t value) {
|
||||||
|
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
byte c;
|
||||||
|
byte colors[16][3] = {
|
||||||
|
{ 0x00, 0x00, 0x00 },
|
||||||
|
{ 0x00, 0x00, 0xaa },
|
||||||
|
{ 0x00, 0xaa, 0x00 },
|
||||||
|
{ 0x00, 0xaa, 0xaa },
|
||||||
|
{ 0xaa, 0x00, 0x00 },
|
||||||
|
{ 0xaa, 0x00, 0xaa },
|
||||||
|
{ 0xaa, 0x55, 0x00 },
|
||||||
|
{ 0xaa, 0xaa, 0xaa },
|
||||||
|
{ 0x55, 0x55, 0x55 },
|
||||||
|
{ 0x55, 0x55, 0xff },
|
||||||
|
{ 0x55, 0xff, 0x55 },
|
||||||
|
{ 0x55, 0xff, 0xff },
|
||||||
|
{ 0xff, 0x55, 0x55 },
|
||||||
|
{ 0xff, 0x55, 0xff },
|
||||||
|
{ 0xff, 0xff, 0x55 },
|
||||||
|
{ 0xff, 0xff, 0xff }
|
||||||
|
};
|
||||||
|
|
||||||
|
_saveName = "zork1.sav";
|
||||||
|
|
||||||
f256Init();
|
f256Init();
|
||||||
|
|
||||||
textSetCursor(199);
|
// Load EGA palette into text CLUT.
|
||||||
|
for (c=0; c<16; c++) {
|
||||||
|
textDefineForegroundColor(c, colors[c][0], colors[c][1], colors[c][2]);
|
||||||
|
textDefineBackgroundColor(c, colors[c][0], colors[c][1], colors[c][2]);
|
||||||
|
}
|
||||||
|
textEnableBackgroundColors(true);
|
||||||
|
|
||||||
|
textSetColor(15, 0);
|
||||||
|
textPrint("Welcome to MUDDLE Beta 1, Another Z-Machine!\n\n");
|
||||||
|
textSetColor(7, 0);
|
||||||
|
textPrint("Copyright 2024 Scott Duensing, All Rights Reserved.\n");
|
||||||
|
textPrint("Kangaroo Punch Studios https://kangaroopunch.com\n\n\n");
|
||||||
|
textSetColor(8, 0);
|
||||||
|
textPrint("Thinking...");
|
||||||
|
|
||||||
stateReset();
|
stateReset();
|
||||||
portStoryLoad();
|
portStoryLoad();
|
||||||
opcodesSetup();
|
opcodesSetup();
|
||||||
storySetup(80, 30);
|
storySetup(80, 30);
|
||||||
|
|
||||||
|
textSetColor(7, 1);
|
||||||
|
textClear();
|
||||||
|
textSetCursor(199);
|
||||||
|
|
||||||
interpreterRun();
|
interpreterRun();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -64,7 +64,7 @@ void interpreterDoReturn(uint16_t r) {
|
||||||
|
|
||||||
if (__state.bp == 0) portDie(MSG_INT_STACK_UNDERFLOW);
|
if (__state.bp == 0) portDie(MSG_INT_STACK_UNDERFLOW);
|
||||||
|
|
||||||
#ifdef DEBUGGING
|
#ifdef DEBUGGINGx
|
||||||
printf("Returning: initial pc=%X, bp=%u, sp=%u\n", (unsigned int)__state.pc, __state.bp, __state.sp);
|
printf("Returning: initial pc=%X, bp=%u, sp=%u\n", (unsigned int)__state.pc, __state.bp, __state.sp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ 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
|
#ifdef DEBUGGINGx
|
||||||
printf("Returning: new pc=%X, bp=%u, sp=%u\n", (unsigned int)__state.pc, __state.bp, __state.sp);
|
printf("Returning: new pc=%X, bp=%u, sp=%u\n", (unsigned int)__state.pc, __state.bp, __state.sp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -136,6 +136,10 @@ void interpreterRun(void) {
|
||||||
opcodeT op;
|
opcodeT op;
|
||||||
bool eight;
|
bool eight;
|
||||||
|
|
||||||
|
__state.savedX = 1;
|
||||||
|
__state.savedY = storyScreenHeightLines();
|
||||||
|
portCharSetPos(__state.savedX, __state.savedY);
|
||||||
|
|
||||||
while (__state.quit == 0) {
|
while (__state.quit == 0) {
|
||||||
opcode = ZPEEK(__state.pc++);
|
opcode = ZPEEK(__state.pc++);
|
||||||
extended = ((opcode == 190) && (storyVersion() >= 5)) ? true : false;
|
extended = ((opcode == 190) && (storyVersion() >= 5)) ? true : false;
|
||||||
|
@ -183,7 +187,7 @@ void interpreterRun(void) {
|
||||||
|
|
||||||
if (op == 0) portDie(MSG_INT_UNIMPLEMENTED_OPCODE, extended ? "ext" : "", opcode);
|
if (op == 0) portDie(MSG_INT_UNIMPLEMENTED_OPCODE, extended ? "ext" : "", opcode);
|
||||||
|
|
||||||
#ifdef DEBUGGING
|
#ifdef DEBUGGINGx
|
||||||
printf("ins=%u pc=%X sp=%u bp=%u %sopcode=%u ('%s') [",
|
printf("ins=%u pc=%X sp=%u bp=%u %sopcode=%u ('%s') [",
|
||||||
__state.instructionsRun,
|
__state.instructionsRun,
|
||||||
(unsigned int)__state.pc,
|
(unsigned int)__state.pc,
|
||||||
|
@ -199,6 +203,7 @@ void interpreterRun(void) {
|
||||||
printf("%X", (unsigned int)__state.operands[i]);
|
printf("%X", (unsigned int)__state.operands[i]);
|
||||||
}
|
}
|
||||||
printf("]\n");
|
printf("]\n");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
if (__state.instructionsRun == 261) {
|
if (__state.instructionsRun == 261) {
|
||||||
printf("\n*** BREAKING ***\n");
|
printf("\n*** BREAKING ***\n");
|
||||||
|
@ -247,6 +252,7 @@ void interpreterTokenizeInput(void) {
|
||||||
|
|
||||||
#ifdef DEBUGGING
|
#ifdef DEBUGGING
|
||||||
printf("Max parse: %u\n", parseLen);
|
printf("Max parse: %u\n", parseLen);
|
||||||
|
printf("Parse Input: [");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (parseLen == 0) portDie(MSG_INT_PARSE_BUFFER_TOO_SMALL);
|
if (parseLen == 0) portDie(MSG_INT_PARSE_BUFFER_TOO_SMALL);
|
||||||
|
@ -260,7 +266,9 @@ void interpreterTokenizeInput(void) {
|
||||||
while (1) {
|
while (1) {
|
||||||
isSep = false;
|
isSep = false;
|
||||||
ch = ZPEEK(ptr);
|
ch = ZPEEK(ptr);
|
||||||
|
#ifdef DEBUGGING
|
||||||
|
printf("%c", ch);
|
||||||
|
#endif
|
||||||
if ((ch == ' ') || (ch == 0)) {
|
if ((ch == ' ') || (ch == 0)) {
|
||||||
isSep = true;
|
isSep = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -358,7 +366,9 @@ void interpreterTokenizeInput(void) {
|
||||||
} // while
|
} // while
|
||||||
|
|
||||||
#ifdef DEBUGGING
|
#ifdef DEBUGGING
|
||||||
|
printf("]\n");
|
||||||
printf("Tokenized %u tokens\n", (unsigned int)numToks);
|
printf("Tokenized %u tokens\n", (unsigned int)numToks);
|
||||||
|
fflush(stdout);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ZPOKE(__state.operands[1] + 1, numToks);
|
ZPOKE(__state.operands[1] + 1, numToks);
|
||||||
|
|
|
@ -46,7 +46,7 @@ void opcodes_call(void) {
|
||||||
} else {
|
} else {
|
||||||
routine = memoryUnpackAddress(__state.operands[0], MEMORY_ROUTINE);
|
routine = memoryUnpackAddress(__state.operands[0], MEMORY_ROUTINE);
|
||||||
numLocals = ZPEEK(routine++);
|
numLocals = ZPEEK(routine++);
|
||||||
#ifdef DEBUGGING
|
#ifdef DEBUGGINGx
|
||||||
printf("op0=%u routine=%X, numLocals=%d\n", __state.operands[0], (unsigned int)routine, numLocals);
|
printf("op0=%u routine=%X, numLocals=%d\n", __state.operands[0], (unsigned int)routine, numLocals);
|
||||||
#endif
|
#endif
|
||||||
if (numLocals > 15) portDie(MSG_OP_CALL_TOO_MANY_LOCALS, numLocals);
|
if (numLocals > 15) portDie(MSG_OP_CALL_TOO_MANY_LOCALS, numLocals);
|
||||||
|
|
|
@ -68,11 +68,15 @@ void opcodes_read(void) {
|
||||||
ZPOKE(i, ch);
|
ZPOKE(i, ch);
|
||||||
} else if ((ch == '\n') || (ch == '\r') || (ch == 0)) {
|
} else if ((ch == '\n') || (ch == '\r') || (ch == 0)) {
|
||||||
// End of line, end of input.
|
// End of line, end of input.
|
||||||
ch = 0;
|
ZPOKE(i, 0);
|
||||||
ZPOKE(i, ch);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
i++;
|
||||||
|
for (; i<input+inputLen; i++) ZPOKE(i, 0);
|
||||||
|
|
||||||
|
// Reset [MORE] counter.
|
||||||
|
__state.linesOut = 0;
|
||||||
|
|
||||||
interpreterTokenizeInput();
|
interpreterTokenizeInput();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,8 @@
|
||||||
#include "variable.h"
|
#include "variable.h"
|
||||||
#include "portme.h"
|
#include "portme.h"
|
||||||
#include "story.h"
|
#include "story.h"
|
||||||
#include "memory.h"
|
|
||||||
#include "interpreter.h"
|
#include "interpreter.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
|
||||||
void opcodes_nop(void) {
|
void opcodes_nop(void) {
|
||||||
|
@ -47,26 +47,10 @@ void opcodes_piracy(void) {
|
||||||
|
|
||||||
|
|
||||||
void opcodes_random(void) {
|
void opcodes_random(void) {
|
||||||
variableStore((__state.pc++), portRandomGet((int16_t)__state.operands[0]));
|
variableStore(ZPEEK(__state.pc++), portRandomGet((int16_t)__state.operands[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void opcodes_verify(void) {
|
void opcodes_verify(void) {
|
||||||
/*
|
interpreterDoBranch(__state.checksum == storyChecksum() ? 1 : 0);
|
||||||
uint16_t checksum = 0;
|
|
||||||
uint32_t i;
|
|
||||||
|
|
||||||
for (i=64; i<storyLength(); i++) checksum += ZPEEK(i);
|
|
||||||
|
|
||||||
checksum %= 0x10000;
|
|
||||||
|
|
||||||
#ifdef DEBUGGING
|
|
||||||
printf("\n\nChecksum = %u Header = %d\n\n", checksum, storyChecksum());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
interpreterDoBranch(checksum == storyChecksum() ? 1 : 0);
|
|
||||||
*/
|
|
||||||
|
|
||||||
// We lie. Everything passes.
|
|
||||||
interpreterDoBranch(1);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,23 +37,26 @@ void opcodes_save(void) {
|
||||||
|
|
||||||
|
|
||||||
void opcodes_restart(void) {
|
void opcodes_restart(void) {
|
||||||
byte width = ZPEEK(STORY_SCREEN_WIDTH_CHARACTERS);
|
byte width = ZPEEK(STORY_SCREEN_WIDTH_CHARACTERS);
|
||||||
byte height = ZPEEK(STORY_SCREEN_HEIGHT_LINES);
|
byte height = ZPEEK(STORY_SCREEN_HEIGHT_LINES);
|
||||||
|
uint16_t checksum = __state.checksum;
|
||||||
|
|
||||||
stateReset();
|
stateReset();
|
||||||
portStoryLoad();
|
portStoryLoad();
|
||||||
|
__state.checksum = checksum;
|
||||||
opcodesSetup();
|
opcodesSetup();
|
||||||
storySetup(width, height);
|
storySetup(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void opcodes_restore(void) {
|
void opcodes_restore(void) {
|
||||||
bool ok = portFileRestore();
|
bool ok = portFileRestore();
|
||||||
uint16_t oldLines = __state.statusWindowLineCount;
|
|
||||||
|
|
||||||
// Collapse upper window.
|
if (ok) {
|
||||||
__state.statusWindowLineCount = 0;
|
// Collapse upper window.
|
||||||
windowSplit(0);
|
__state.statusWindowLineCount = 0;
|
||||||
|
windowSplit(0);
|
||||||
|
}
|
||||||
|
|
||||||
interpreterDoBranch(ok ? 1 : 0);
|
interpreterDoBranch(ok ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
14
src/story.c
14
src/story.c
|
@ -26,6 +26,20 @@
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
|
|
||||||
|
void storyChecksumCalculate(void) {
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
__state.checksum = 0;
|
||||||
|
for (i=64; i<storyLength(); i++) __state.checksum += ZPEEK(i);
|
||||||
|
|
||||||
|
__state.checksum %= 0x10000;
|
||||||
|
|
||||||
|
#ifdef DEBUGGING
|
||||||
|
printf("\n\nChecksum = %u Header = %d\n\n", __state.checksum, storyChecksum());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t storyLength() {
|
uint32_t storyLength() {
|
||||||
uint32_t m = (uint32_t)storyFileSize() * 2;
|
uint32_t m = (uint32_t)storyFileSize() * 2;
|
||||||
|
|
||||||
|
|
41
src/text.c
41
src/text.c
|
@ -32,6 +32,10 @@
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void textMoreCheck(void);
|
||||||
|
static void textNumPrint_r(int32_t val);
|
||||||
|
|
||||||
|
|
||||||
void textCharPrint(char c) {
|
void textCharPrint(char c) {
|
||||||
static char lineBuffer[256];
|
static char lineBuffer[256];
|
||||||
static uint16_t lineWidth = 0;
|
static uint16_t lineWidth = 0;
|
||||||
|
@ -53,7 +57,7 @@ void textCharPrint(char c) {
|
||||||
if (!__state.outputting) return;
|
if (!__state.outputting) return;
|
||||||
|
|
||||||
// Do we need to word wrap?
|
// Do we need to word wrap?
|
||||||
if (lineWidth == width - 2) {
|
if (lineWidth == width - 1) {
|
||||||
// Are we printing a space or CR? If so, just go to next line.
|
// Are we printing a space or CR? If so, just go to next line.
|
||||||
if ((c == ' ') || (c == '\n')) {
|
if ((c == ' ') || (c == '\n')) {
|
||||||
c = '\n';
|
c = '\n';
|
||||||
|
@ -77,9 +81,11 @@ void textCharPrint(char c) {
|
||||||
}
|
}
|
||||||
// Wrap display.
|
// Wrap display.
|
||||||
portCharPrint('\n');
|
portCharPrint('\n');
|
||||||
|
__state.linesOut++;
|
||||||
// Move erased characters to front of buffer & redisplay.
|
// Move erased characters to front of buffer & redisplay.
|
||||||
portCharGetPos(&x, &y);
|
portCharGetPos(&x, &y);
|
||||||
portCharSetPos(1, y);
|
portCharSetPos(1, y);
|
||||||
|
textMoreCheck();
|
||||||
x = 0;
|
x = 0;
|
||||||
for (i=space; i<=lineWidth; i++) {
|
for (i=space; i<=lineWidth; i++) {
|
||||||
lineBuffer[x++] = lineBuffer[i];
|
lineBuffer[x++] = lineBuffer[i];
|
||||||
|
@ -97,12 +103,32 @@ void textCharPrint(char c) {
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
// New line.
|
// New line.
|
||||||
lineWidth = 0;
|
lineWidth = 0;
|
||||||
|
__state.linesOut++;
|
||||||
|
textMoreCheck();
|
||||||
} else {
|
} else {
|
||||||
lineBuffer[lineWidth++] = c;
|
lineBuffer[lineWidth++] = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void textMoreCheck(void) {
|
||||||
|
byte x;
|
||||||
|
byte y;
|
||||||
|
|
||||||
|
if (__state.linesOut >= storyScreenHeightLines() - __state.statusWindowLineCount - 1) {
|
||||||
|
// Display [MORE] prompt.
|
||||||
|
portCharGetPos(&x, &y);
|
||||||
|
textStringPrint("[MORE]");
|
||||||
|
textStringPrint(" ");
|
||||||
|
portCharGet();
|
||||||
|
portCharSetPos(x, y);
|
||||||
|
textStringPrint(" ");
|
||||||
|
portCharSetPos(x, y);
|
||||||
|
__state.linesOut = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void textNumPrint_r(int32_t val) {
|
static void textNumPrint_r(int32_t val) {
|
||||||
|
|
||||||
if (val > 9) {
|
if (val > 9) {
|
||||||
|
@ -212,5 +238,18 @@ void textStringPrint(char *s) {
|
||||||
|
|
||||||
|
|
||||||
void textTimePrint(uint16_t hours, uint16_t minutes) {
|
void textTimePrint(uint16_t hours, uint16_t minutes) {
|
||||||
|
bool PM = (hours < 12) ? false : true;
|
||||||
|
|
||||||
|
hours %= 12;
|
||||||
|
if (hours == 0) hours = 12;
|
||||||
|
|
||||||
|
if (hours < 10) textCharPrint(' ');
|
||||||
|
textNumPrint(hours);
|
||||||
|
|
||||||
|
textCharPrint(':');
|
||||||
|
|
||||||
|
if (minutes < 10) textCharPrint('0');
|
||||||
|
textNumPrint(minutes);
|
||||||
|
|
||||||
|
textStringPrint((PM ? " pm" : " am"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ uint8_t variableAddress(uint8_t var, bool writing) {
|
||||||
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
|
#ifdef DEBUGGINGx
|
||||||
printf("Push stack\n");
|
printf("Push stack\n");
|
||||||
#endif
|
#endif
|
||||||
return __state.sp++;
|
return __state.sp++;
|
||||||
|
@ -71,7 +71,7 @@ uint8_t variableAddress(uint8_t var, bool writing) {
|
||||||
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
|
#ifdef DEBUGGINGx
|
||||||
printf("Pop stack\n");
|
printf("Pop stack\n");
|
||||||
#endif
|
#endif
|
||||||
return --__state.sp;
|
return --__state.sp;
|
||||||
|
|
14
src/window.c
14
src/window.c
|
@ -130,9 +130,11 @@ void windowSplit(byte newLines) {
|
||||||
|
|
||||||
|
|
||||||
void windowUpdateStatusBar(void) {
|
void windowUpdateStatusBar(void) {
|
||||||
|
byte width = storyScreenWidthCharacters() - 1;
|
||||||
|
|
||||||
windowSet(WINDOW_STATUS);
|
windowSet(WINDOW_STATUS);
|
||||||
portCharSetPos(1, 1);
|
portCharSetPos(1, 1);
|
||||||
// Reverse attribute.
|
portAttributeSet(TEXT_ATTR_REVERSE);
|
||||||
textOutputStream(STREAM_OUTPUT_MEMORY, 0);
|
textOutputStream(STREAM_OUTPUT_MEMORY, 0);
|
||||||
|
|
||||||
windowPadStatus(1);
|
windowPadStatus(1);
|
||||||
|
@ -142,26 +144,26 @@ void windowUpdateStatusBar(void) {
|
||||||
|
|
||||||
if ((storyFlags() & STORY_STATUS_MASK) == STORY_STATUS_HOURS_MINUTES) {
|
if ((storyFlags() & STORY_STATUS_MASK) == STORY_STATUS_HOURS_MINUTES) {
|
||||||
// Timed game.
|
// Timed game.
|
||||||
windowPadStatus(storyScreenWidthCharacters() - 21);
|
windowPadStatus(width - 21);
|
||||||
textStringPrint(" Time: ");
|
textStringPrint(" Time: ");
|
||||||
textTimePrint(variableLoad(17), variableLoad(18));
|
textTimePrint(variableLoad(17), variableLoad(18));
|
||||||
} else {
|
} else {
|
||||||
// Scored game.
|
// Scored game.
|
||||||
windowPadStatus(storyScreenWidthCharacters() - 31);
|
windowPadStatus(width - 31);
|
||||||
textStringPrint(" Score: ");
|
textStringPrint(" Score: ");
|
||||||
textNumPrint(variableLoad(17));
|
textNumPrint(variableLoad(17));
|
||||||
windowPadStatus(storyScreenWidthCharacters() - 15);
|
windowPadStatus(width - 15);
|
||||||
textStringPrint(" Moves: ");
|
textStringPrint(" Moves: ");
|
||||||
textNumPrint(variableLoad(18));
|
textNumPrint(variableLoad(18));
|
||||||
}
|
}
|
||||||
|
|
||||||
windowPadStatus(storyScreenWidthCharacters());
|
windowPadStatus(width);
|
||||||
__state.statusBar[__state.statusBarLen] = 0;
|
__state.statusBar[__state.statusBarLen] = 0;
|
||||||
|
|
||||||
textOutputStream(-STREAM_OUTPUT_MEMORY, 0);
|
textOutputStream(-STREAM_OUTPUT_MEMORY, 0);
|
||||||
|
|
||||||
textStringPrint(__state.statusBar);
|
textStringPrint(__state.statusBar);
|
||||||
|
|
||||||
// Normal attribute.
|
portAttributeSet(TEXT_ATTR_NORMAL);
|
||||||
windowSet(WINDOW_TEXT);
|
windowSet(WINDOW_TEXT);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue