Muddle Release 1 Beta 2!

This commit is contained in:
Scott Duensing 2024-02-10 17:38:04 -06:00
parent 62db64dcd5
commit 0b5699a5ca
18 changed files with 220 additions and 7478 deletions

View file

@ -26,12 +26,13 @@
#include <stdint.h> #include <stdint.h>
#include "mapper.h"
//#define DEBUGGING //#define DEBUGGING
#define MESSAGES
#define STACK_SIZE 512 //***TODO*** How big does this really need to be? Old games are 1024, new...?
#define STACK_SIZE 1024 //***TODO*** How big does this really need to be? Old games are 1024, new...?
#ifdef DEBUGGING #ifdef DEBUGGING

View file

@ -1,29 +0,0 @@
/*
Special mapper macros for the F256 + mos-llvm, so we can put code
anywhere in physical ram
Currently only blocks 8-23 are defined in the linker file
If you need to go beyond the 128k of extra code, just add more definitions
into f256.ld
*/
#if defined(__F256K__) && __F256K__ && 0
/*
$$JGA TODO, sort out how to mark an entire file
*/
#define CODE_BLOCK(index) __attribute__((noinline, section(".block"#index)))
#define DATA_BLOCK(index) __attribute__((section(".block"#index)))
#define PAGEIN(_function_BLOCK) POKE(SWAP_SLOT, _function_BLOCK)
#else
#define CODE_BLOCK(index)
#define DATA_BLOCK(index)
#define PAGEIN(_function_BLOCK)
#endif

View file

@ -40,6 +40,9 @@
#define ZPOKEW(a,v) portWordSet(a,v) #define ZPOKEW(a,v) portWordSet(a,v)
extern char __memoryBuffer[256];
uint32_t memoryUnpackAddress(uint32_t address, uint8_t type); uint32_t memoryUnpackAddress(uint32_t address, uint8_t type);

View file

@ -28,18 +28,18 @@
#include "common.h" #include "common.h"
#ifdef DEBUGGING #ifdef MESSAGES
#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!"
#define MSG_INT_OBJECT0_REF "Object 0 referenced!"
#define MSG_INT_OBJECT_BAD_ID "Invalid object ID!"
#define MSG_INT_PARSE_BUFFER_TOO_SMALL "Parse buffer too small for reading." #define MSG_INT_PARSE_BUFFER_TOO_SMALL "Parse buffer too small for reading."
#define MSG_INT_STACK_UNDERFLOW "Int Stack underflow!" #define MSG_INT_STACK_UNDERFLOW "Int Stack underflow!"
#define MSG_INT_UNIMPLEMENTED_OPCODE "Unimplemented opcode! %s %d" #define MSG_INT_UNIMPLEMENTED_OPCODE "Unimplemented opcode! %s %d"
#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_OBJ_OBJECT_BAD_ID "Invalid object ID!"
#define MSG_OBJ_OBJECT0_REF "Object 0 referenced!"
#define MSG_STA_CANNOT_ALLOCATE_STACK "Cannot allocate stack!" #define MSG_STA_CANNOT_ALLOCATE_STACK "Cannot allocate stack!"
#define MSG_VAR_REF_UNALLOCATED_LOCAL "Referenced unallocated local variable!" #define MSG_VAR_REF_UNALLOCATED_LOCAL "Referenced unallocated local variable!"
#define MSG_VAR_STACK_OVERFLOW "Var Stack overflow!" #define MSG_VAR_STACK_OVERFLOW "Var Stack overflow!"
@ -50,18 +50,18 @@
#define MSG_OP_OBJ_MISSING_PROPERTY "Missing object property." #define MSG_OP_OBJ_MISSING_PROPERTY "Missing object property."
#define MSG_OP_WIN_NO_SPLITTING "Window splitting is not supported." #define MSG_OP_WIN_NO_SPLITTING "Window splitting is not supported."
#define MSG_UI_CANNOT_ALLOCATE "Cannot allocate %l bytes!" #define MSG_UI_CANNOT_ALLOCATE "Cannot allocate %l bytes!"
#else // DEBUGGING #else // MESSAGES
#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 ""
#define MSG_INT_OBJECT0_REF ""
#define MSG_INT_OBJECT_BAD_ID ""
#define MSG_INT_PARSE_BUFFER_TOO_SMALL "" #define MSG_INT_PARSE_BUFFER_TOO_SMALL ""
#define MSG_INT_STACK_UNDERFLOW "" #define MSG_INT_STACK_UNDERFLOW ""
#define MSG_INT_UNIMPLEMENTED_OPCODE "" #define MSG_INT_UNIMPLEMENTED_OPCODE ""
#define MSG_INT_V12_SHIFT "" #define MSG_INT_V12_SHIFT ""
#define MSG_INT_V12_SHIFT_LOCK "" #define MSG_INT_V12_SHIFT_LOCK ""
#define MSG_MEM_BUFFER "" #define MSG_MEM_BUFFER ""
#define MSG_OBJ_OBJECT_BAD_ID ""
#define MSG_OBJ_OBJECT0_REF ""
#define MSG_STA_CANNOT_ALLOCATE_STACK "" #define MSG_STA_CANNOT_ALLOCATE_STACK ""
#define MSG_VAR_REF_UNALLOCATED_LOCAL "" #define MSG_VAR_REF_UNALLOCATED_LOCAL ""
#define MSG_VAR_STACK_OVERFLOW "" #define MSG_VAR_STACK_OVERFLOW ""
@ -72,7 +72,7 @@
#define MSG_OP_OBJ_MISSING_PROPERTY "" #define MSG_OP_OBJ_MISSING_PROPERTY ""
#define MSG_OP_WIN_NO_SPLITTING "" #define MSG_OP_WIN_NO_SPLITTING ""
#define MSG_UI_CANNOT_ALLOCATE "" #define MSG_UI_CANNOT_ALLOCATE ""
#endif // DEBUGGING #endif // MESSAGES
#endif // MESSAGES_H #endif // MESSAGES_H

View file

@ -48,7 +48,7 @@ uint32_t portFClose(void *stream);
void *portFOpen(char *pathname, char *mode); void *portFOpen(char *pathname, char *mode);
uint32_t portFRead(void *ptr, uint32_t size, uint32_t nmemb, void *stream); uint32_t portFRead(void *ptr, uint32_t size, uint32_t nmemb, void *stream);
uint32_t portFWrite(void *ptr, uint32_t size, uint32_t nmemb, void *stream); uint32_t portFWrite(void *ptr, uint32_t size, uint32_t nmemb, void *stream);
void portFileLister(void); void portFileLister(char *path);
void portFree(void *ptr); void portFree(void *ptr);
void *portMalloc(uint32_t size); void *portMalloc(uint32_t size);
uint16_t portRandomGet(int16_t range); uint16_t portRandomGet(int16_t range);

View file

@ -62,6 +62,8 @@ extern stateT __state;
void stateReset(void); void stateReset(void);
void stateShutdown(void);
void stateStartup(void);
#endif // STATE_H #endif // STATE_H

View file

@ -35,7 +35,7 @@
void uiFileAdd(char *filename, uint32_t size); void uiFileAdd(char *filename, uint32_t size);
void uiGameSelect(void); void uiGameSelect(char *path);
char *uiSaveGet(void); char *uiSaveGet(void);
void uiSizeGet(byte *w, byte *h); void uiSizeGet(byte *w, byte *h);
void uiSizeSet(byte w, byte h); void uiSizeSet(byte w, byte h);

File diff suppressed because it is too large Load diff

View file

@ -31,6 +31,7 @@
#include "story.h" #include "story.h"
#include "text.h" #include "text.h"
#include "ui.h" #include "ui.h"
#include "lib.h"
#pragma push_macro("bool") #pragma push_macro("bool")
#undef bool #undef bool
@ -39,6 +40,26 @@
#pragma pop_macro("bool") #pragma pop_macro("bool")
#ifdef MESSAGES
#define MSG_PORT_UNABLE_TO_ALLOCATE_PATH "Unable to allocate path %d."
#define MSG_PORT_UNABLE_TO_ALLOCATE_STORY "Unable to allocate story %d."
#define MSG_PORT_UNABLE_TO_OPEN_STORY "Unable to open %s!"
#define MSG_PORT_UNABLE_TO_READ_STORY "Unable to read %s!"
#else
#define MSG_PORT_UNABLE_TO_ALLOCATE_PATH ""
#define MSG_PORT_UNABLE_TO_ALLOCATE_STORY ""
#define MSG_PORT_UNABLE_TO_OPEN_STORY ""
#define MSG_PORT_UNABLE_TO_READ_STORY ""
#endif
#ifdef _WIN32
#define PS '\\'
#else
#define PS '/'
#endif
static uint8_t *_RAM = NULL; static uint8_t *_RAM = NULL;
static uint8_t _attr = 0; static uint8_t _attr = 0;
@ -137,7 +158,7 @@ void portCharSetPos(byte x, byte y) {
void portColorSet(byte f, byte b) { void portColorSet(byte f, byte b) {
textcolor(f); textcolor(f);
textbackground(b); textbackground(b);
_attr = (f << 4) + b; _attr = (b << 4) + f;
} }
@ -183,19 +204,29 @@ uint32_t portFWrite(void *ptr, uint32_t size, uint32_t nmemb, void *stream) {
} }
void portFileLister(void) { void portFileLister(char *path) {
DIR *dir; DIR *dir;
struct dirent *dirent; struct dirent *dirent;
uint32_t l; uint32_t l;
FILE *in; FILE *in;
byte x;
byte y;
byte i;
if ((dir = opendir("."))) { if ((dir = opendir(path))) {
for (;;) { for (;;) {
if ((dirent = readdir(dir))) { if ((dirent = readdir(dir))) {
// Is this a file or symlink? // Is this a file or symlink?
if ((dirent->d_type == DT_REG) || (dirent->d_type == DT_LNK)) { if ((dirent->d_type == DT_REG) || (dirent->d_type == DT_LNK)) {
// Combine path and filename.
x = 0;
y = libStrLen(path);
for (i=0; i<y; i++) __memoryBuffer[x++] = path[i];
y = libStrLen(dirent->d_name);
for (i=0; i<y; i++) __memoryBuffer[x++] = dirent->d_name[i];
__memoryBuffer[x] = 0;
// Get it's length. // Get it's length.
in = fopen(dirent->d_name, "rb"); in = fopen(__memoryBuffer, "rb");
if (in) { if (in) {
fseek(in, 0, SEEK_END); fseek(in, 0, SEEK_END);
l = ftell(in); l = ftell(in);
@ -247,18 +278,18 @@ void portStoryLoad(char *story, uint32_t *length) {
uint32_t i; uint32_t i;
in = fopen(story, "rb"); in = fopen(story, "rb");
if (!in) portDie("Unable to open %s!\n", story); if (!in) portDie(MSG_PORT_UNABLE_TO_OPEN_STORY, story);
_RAM = (byte *)malloc(*length); _RAM = (byte *)malloc(*length);
if (!_RAM) { if (!_RAM) {
fclose(in); fclose(in);
portDie("Unable to allocate %u bytes!\n", *length); portDie(MSG_PORT_UNABLE_TO_ALLOCATE_STORY, *length);
} }
if (fread(_RAM, *length, 1, in) != 1) { if (fread(_RAM, *length, 1, in) != 1) {
free(_RAM); free(_RAM);
fclose(in); fclose(in);
portDie("Unable to read %s!\n", story); portDie(MSG_PORT_UNABLE_TO_READ_STORY, story);
} }
fclose(in); fclose(in);
@ -291,16 +322,48 @@ void portWordSet(uint32_t address, uint16_t value) {
} }
#include "unistd.h"
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
chdir("/home/scott/code/zip/stories"); byte x;
byte l;
char *noPath = "./";
char *path = NULL;
// One argumet, the program name. Use same path as binary.
if (argc == 1) {
// Remove executable name from path.
l = libStrLen(argv[0]);
for (x=l; x>0; x--) {
if (argv[0][x] == PS) break; // Path separator.
}
if (x > 0) {
path = (char *)malloc(x + 1);
if (path == 0) portDie(MSG_PORT_UNABLE_TO_ALLOCATE_PATH, 0);
for (l=0; l<=x; l++) path[l] = argv[0][l];
path[l] = 0;
} else {
path = noPath;
}
}
// User provided at least one command line argument. Use first one.
if (argc > 1) {
// Does it end with a '/' or '\'?
l = libStrLen(argv[1]);
if (argv[1][l-1] != PS) l++; // Add space for a slash.
path = (char *)malloc(l);
if (path == 0) portDie(MSG_PORT_UNABLE_TO_ALLOCATE_PATH, 1);
for (x=0; x<l; x++) path[x] = argv[1][x];
path[x-1] = PS;
path[x] = 0;
}
setvideomode(videomode_80x25_9x16); setvideomode(videomode_80x25_9x16);
uiSizeSet(80, 25); uiSizeSet(80, 25);
uiGameSelect(); uiGameSelect(path);
free(_RAM); free(_RAM);
if (path != noPath) free(path);
return 0; return 0;
} }

View file

@ -1,12 +1,11 @@
cmake_minimum_required(VERSION 3.12) cmake_minimum_required(VERSION 3.12)
project(f256-zip LANGUAGES C) project(muddle LANGUAGES C)
set(HEADERS set(HEADERS
common.h common.h
interpreter.h interpreter.h
lib.h lib.h
mapper.h
memory.h memory.h
messages.h messages.h
object.h object.h

View file

@ -23,7 +23,7 @@
# #
PROJECT=f256zip PROJECT=muddle
F256=$(pwd)/../../../f256 F256=$(pwd)/../../../f256
LLVM=${F256}/llvm-mos LLVM=${F256}/llvm-mos
@ -40,12 +40,12 @@ ${F256}/overlayhelper ../f256zip.c >> overlay.ld
${CLANG} -c ${F256}/f256lib/f256.c ${CLANG} -c ${F256}/f256lib/f256.c
${CLANG} -c ../../zip.c ${CLANG} -c ../../zip.c
${CLANG} -c ../${PROJECT}.c ${CLANG} -c ../f256zip.c
${CLANG} -T../f256.ld -o ${PROJECT} zip.o f256.o ${PROJECT}.o ${CLANG} -T../f256.ld -o ${PROJECT} zip.o f256.o f256zip.o
llvm-nm ${PROJECT}.elf > ${PROJECT}.lst llvm-nm ${PROJECT}.elf > ${PROJECT}.lst
llvm-objdump -d --print-imm-hex ${PROJECT}.elf > ${PROJECT}.lst llvm-objdump -d --print-imm-hex ${PROJECT}.elf > ${PROJECT}.lst
python ${F256}/pgz-thunk.py f256zip python ${F256}/pgz-thunk.py ${PROJECT}
mv -f ${PROJECT} ../${PROJECT}.pgz mv -f ${PROJECT} ../${PROJECT}.pgz

View file

@ -1,120 +0,0 @@
/* F256 Banking Linker Script
*/
/* fake C Stack */
PROVIDE(__stack = 0xA000);
/* entry point to my program */
PROVIDE(__f256_start = 0x300);
/* page size of a block of memory */
PROVIDE(__BLOCK_SIZE = 0x2000);
/* swappable block address */
PROVIDE(__SLOT_ADDR = 0xA000);
/* f256k uses first 16 bytes of ZP for mmu control? */
__rc0 = 0x10;
INCLUDE imag-regs.ld
ASSERT(__rc0 == 0x10, "Inconsistent zero page map.")
ASSERT(__rc31 == 0x2f, "Inconsistent zero page map.")
MEMORY {
/* kernel uses 0xf0-0xff for parameter passing */
zp : ORIGIN = __rc31 + 1, LENGTH = 0xF0 - (__rc31 + 1)
ram (rw) : ORIGIN = __f256_start, LENGTH = 0xA000-__f256_start
}
/* LMAs */
__block8_lma = ( 8<<24)|__SLOT_ADDR;
__block9_lma = ( 9<<24)|__SLOT_ADDR;
__block10_lma = (10<<24)|__SLOT_ADDR;
__block11_lma = (11<<24)|__SLOT_ADDR;
__block12_lma = (12<<24)|__SLOT_ADDR;
__block13_lma = (13<<24)|__SLOT_ADDR;
__block14_lma = (14<<24)|__SLOT_ADDR;
__block15_lma = (15<<24)|__SLOT_ADDR;
__block16_lma = (16<<24)|__SLOT_ADDR;
__block17_lma = (17<<24)|__SLOT_ADDR;
__block18_lma = (18<<24)|__SLOT_ADDR;
__block19_lma = (19<<24)|__SLOT_ADDR;
__block20_lma = (20<<24)|__SLOT_ADDR;
__block21_lma = (21<<24)|__SLOT_ADDR;
__block22_lma = (22<<24)|__SLOT_ADDR;
__block23_lma = (23<<24)|__SLOT_ADDR;
MEMORY {
block8 : ORIGIN = __block8_lma, LENGTH = __BLOCK_SIZE
block9 : ORIGIN = __block9_lma, LENGTH = __BLOCK_SIZE
block10 : ORIGIN = __block10_lma, LENGTH = __BLOCK_SIZE
block11 : ORIGIN = __block11_lma, LENGTH = __BLOCK_SIZE
block12 : ORIGIN = __block12_lma, LENGTH = __BLOCK_SIZE
block13 : ORIGIN = __block13_lma, LENGTH = __BLOCK_SIZE
block14 : ORIGIN = __block14_lma, LENGTH = __BLOCK_SIZE
block15 : ORIGIN = __block15_lma, LENGTH = __BLOCK_SIZE
block16 : ORIGIN = __block16_lma, LENGTH = __BLOCK_SIZE
block17 : ORIGIN = __block17_lma, LENGTH = __BLOCK_SIZE
block18 : ORIGIN = __block18_lma, LENGTH = __BLOCK_SIZE
block19 : ORIGIN = __block19_lma, LENGTH = __BLOCK_SIZE
block20 : ORIGIN = __block20_lma, LENGTH = __BLOCK_SIZE
block21 : ORIGIN = __block21_lma, LENGTH = __BLOCK_SIZE
block22 : ORIGIN = __block22_lma, LENGTH = __BLOCK_SIZE
block23 : ORIGIN = __block23_lma, LENGTH = __BLOCK_SIZE
}
REGION_ALIAS("c_writeable", ram)
/* REGION_ALIAS("c_readonly", fixed) */
/* I want to use the lower 40k */
REGION_ALIAS("c_readonly", ram)
SECTIONS {
INCLUDE c.ld
.binarydata : { *(.binarydata .binarydata.*) } >binarydata end_binarydata = .;
.block8 : { *(.block8 .block8.*) } >block8 end_block8 = .;
.block9 : { *(.block9 .block9.*) } >block9 end_block9 = .;
.block10 : { *(.block10 .block10.*) } >block10 end_block10 = .;
.block11 : { *(.block11 .block11.*) } >block11 end_block11 = .;
.block12 : { *(.block12 .block12.*) } >block12 end_block12 = .;
.block13 : { *(.block13 .block13.*) } >block13 end_block13 = .;
.block14 : { *(.block14 .block14.*) } >block14 end_block14 = .;
.block15 : { *(.block15 .block15.*) } >block15 end_block15 = .;
.block16 : { *(.block16 .block16.*) } >block16 end_block16 = .;
.block17 : { *(.block17 .block17.*) } >block17 end_block17 = .;
.block18 : { *(.block18 .block18.*) } >block18 end_block18 = .;
.block19 : { *(.block19 .block19.*) } >block19 end_block19 = .;
.block20 : { *(.block20 .block20.*) } >block20 end_block20 = .;
.block21 : { *(.block21 .block21.*) } >block21 end_block21 = .;
.block22 : { *(.block22 .block22.*) } >block22 end_block22 = .;
.block23 : { *(.block23 .block23.*) } >block23 end_block23 = .;
}
/* Trick linker into exposing symbols with values larger than 16 bits */
INCLUDE overlay.ld
/* OUTPUT_FORMAT { FULL(cart_rom) } */
OUTPUT_FORMAT {
BYTE(0x5A) /* pgZ */
/* ram segment */
SHORT(ORIGIN(ram)) /* where to load it, 24 bits */
BYTE(0x00)
SHORT(__bss_start-ORIGIN(ram)) /* size to load */
BYTE(0x00)
TRIM(ram)
/* block8 */
SHORT(8*0x2000)
BYTE(8/8) /* block#/8 = the actual system high byte */
SHORT(end_block8 - __block8_lma)
BYTE(0x00)
TRIM(block8)
/* Launch the program, at _start */
SHORT(_start)
LONG(0)
}

View file

@ -36,14 +36,23 @@
#define WITHOUT_GRAPHICS #define WITHOUT_GRAPHICS
#define WITHOUT_MATH
#include "f256.h" #include "f256.h"
#include "portme.h" #include "portme.h"
#include "lib.h"
#include "../../include/text.h" #include "../../include/text.h"
#ifdef MESSAGES
#define MSG_PORT_UNABLE_TO_OPEN_STORY "Unable to open %s!"
#define MSG_PORT_UNABLE_TO_ALLOCATE_PATH "Unable to allocate path %d."
#else
#define MSG_PORT_UNABLE_TO_OPEN_STORY ""
#define MSG_PORT_UNABLE_TO_ALLOCATE_PATH ""
#endif
#define BASE_ADDRESS 0x10000 #define BASE_ADDRESS 0x10000
@ -70,6 +79,7 @@ void portAttributeSet(byte attribute) {
uint8_t portByteGet(uint32_t address) { uint8_t portByteGet(uint32_t address) {
uint8_t r = FAR_PEEK(BASE_ADDRESS + address); uint8_t r = FAR_PEEK(BASE_ADDRESS + address);
// libf256 leaves slot 5 wherever it lands - we need it put back because there is code there.
POKE(MMU_MEM_BANK_5, SWAP_SLOT - 8); POKE(MMU_MEM_BANK_5, SWAP_SLOT - 8);
return r; return r;
} }
@ -142,6 +152,9 @@ void portCursorShow(bool s) {
void portDie(char *fmt, ...) { void portDie(char *fmt, ...) {
#ifdef DEBUGGING #ifdef DEBUGGING
printf("%s\n", fmt); // Yeah, this isn't right. printf("%s\n", fmt); // Yeah, this isn't right.
#else
textPrint("\n\n");
textPrint(fmt);
#endif #endif
exit(1); exit(1);
} }
@ -167,12 +180,12 @@ uint32_t portFWrite(void *ptr, uint32_t size, uint32_t nmemb, void *stream) {
} }
CODE_BLOCK(8) void portFileLister(void) { void portFileLister(char *path) {
DIR *dir; DIR *dir;
struct dirent *dirent; struct dirent *dirent;
uint32_t l; uint32_t l;
if ((dir = opendir("0:"))) { if ((dir = opendir(path))) {
for (;;) { for (;;) {
dirent = readdir(dir); dirent = readdir(dir);
if (dirent == 0) break; if (dirent == 0) break;
@ -223,13 +236,9 @@ void portStoryLoad(char *story, uint32_t *length) {
uint32_t i; uint32_t i;
byte j; byte j;
byte r; byte r;
char *buffer;
buffer = (char *)malloc(255);
if (buffer == 0) portDie("M0");
in = fopen(story, "rb"); in = fopen(story, "rb");
if (!in) portDie("Unable to open %s!\n", story); if (!in) portDie(MSG_PORT_UNABLE_TO_OPEN_STORY, story);
// The F256 only returns file sizes in blocks of 256. // The F256 only returns file sizes in blocks of 256.
// We load what we can until we get an error and then // We load what we can until we get an error and then
@ -237,19 +246,17 @@ void portStoryLoad(char *story, uint32_t *length) {
i = 0; i = 0;
do { do {
r = fread(buffer, 1, 255, in); r = fread(__memoryBuffer, 1, 255, in);
if (r > 0) { if (r > 0) {
for (j=0; j<r; j++) { for (j=0; j<r; j++) {
storyAddToChecksum(i, buffer[j]); storyAddToChecksum(i, __memoryBuffer[j]);
ZPOKE(i++, buffer[j]); ZPOKE(i++, __memoryBuffer[j]);
} }
} }
} while (r == 255); } while (r == 255);
fclose(in); fclose(in);
free(buffer);
// Update story length. // Update story length.
*length = i; *length = i;
} }
@ -290,7 +297,7 @@ void portWordSet(uint32_t address, uint16_t value) {
} }
int main(void) { int main(int argc, char *argv[]) {
byte c; byte c;
byte colors[16][3] = { byte colors[16][3] = {
{ 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00 },
@ -310,8 +317,45 @@ int main(void) {
{ 0xff, 0xff, 0x55 }, { 0xff, 0xff, 0x55 },
{ 0xff, 0xff, 0xff } { 0xff, 0xff, 0xff }
}; };
byte x;
byte l;
char *noPath = "0:";
char *path = 0;
f256Init(); // No arguments provided. Assume drive 0:.
if (argc == 0) {
path = noPath;
}
// One argumet, the program name. Use same path as PGZ.
if (argc == 1) {
// Remove PGZ name from path.
l = libStrLen(argv[0]);
for (x=l; x>0; x--) {
if ((x == 1) && (argv[0][x] == ':')) break; // Drive number.
if (argv[0][x] == '/') break; // Path separator.
}
if (x > 0) {
path = (char *)malloc(x + 1);
if (path == 0) portDie(MSG_PORT_UNABLE_TO_ALLOCATE_PATH, 0);
for (l=0; l<=x; l++) path[l] = argv[0][l];
path[l] = 0;
} else {
path = noPath;
}
}
// User provided at least one command line argument. Use first one.
if (argc > 1) {
// Does it end with a '/'?
l = libStrLen(argv[1]);
if (argv[1][l-1] != '/') l++; // Add space for a slash.
path = (char *)malloc(l);
if (path == 0) portDie(MSG_PORT_UNABLE_TO_ALLOCATE_PATH, 1);
for (x=0; x<l; x++) path[x] = argv[1][x];
path[x-1] = '/';
path[x] = 0;
}
// Load EGA palette into text CLUT. // Load EGA palette into text CLUT.
for (c=0; c<16; c++) { for (c=0; c<16; c++) {
@ -321,6 +365,7 @@ int main(void) {
textEnableBackgroundColors(true); textEnableBackgroundColors(true);
/* /*
// Ugly font dump.
uint16_t b; uint16_t b;
c = 0; c = 0;
char ch[2] = {0,0}; char ch[2] = {0,0};
@ -342,9 +387,10 @@ int main(void) {
portCharGet(); portCharGet();
*/ */
PAGEIN(8);
uiSizeSet(80, 30); uiSizeSet(80, 30);
uiGameSelect(); uiGameSelect(path);
if (path != noPath) free(path);
return 0; return 0;
} }

View file

@ -31,7 +31,6 @@
#include "variable.h" #include "variable.h"
#include "memory.h" #include "memory.h"
#include "lib.h" #include "lib.h"
#include "text.h"
void interpreterDoBranch(int32_t truth) { void interpreterDoBranch(int32_t truth) {

View file

@ -25,6 +25,9 @@
#include "story.h" #include "story.h"
char __memoryBuffer[256];
uint32_t memoryUnpackAddress(uint32_t address, uint8_t type) { uint32_t memoryUnpackAddress(uint32_t address, uint8_t type) {
if (storyVersion() <= 3) return address * 2; if (storyVersion() <= 3) return address * 2;

View file

@ -31,8 +31,8 @@
uint32_t objectPointerGet(uint16_t objectId) { uint32_t objectPointerGet(uint16_t objectId) {
uint32_t ptr; uint32_t ptr;
if (objectId == 0) portDie(MSG_INT_OBJECT0_REF); if (objectId == 0) portDie(MSG_OBJ_OBJECT0_REF);
if ((storyVersion() <= 3) && (objectId > 255)) portDie(MSG_INT_OBJECT_BAD_ID); if ((storyVersion() <= 3) && (objectId > 255)) portDie(MSG_OBJ_OBJECT_BAD_ID);
ptr = storyObjectTableAddress(); ptr = storyObjectTableAddress();
ptr += 31 * 2; // Skip properties defaults table. ptr += 31 * 2; // Skip properties defaults table.

View file

@ -29,17 +29,9 @@
stateT __state; stateT __state;
static bool _stackAllocated = false;
void stateReset(void) { void stateReset(void) {
if (!_stackAllocated) {
__state.stack = (uint16_t *)portMalloc(sizeof(uint16_t) * STACK_SIZE);
if (__state.stack == 0) portDie(MSG_STA_CANNOT_ALLOCATE_STACK);
_stackAllocated = true;
}
// Zero out all state data, skipping stack address. // Zero out all state data, skipping stack address.
libMemSet((byte *)&__state + sizeof(uint16_t *), 0, sizeof(stateT)); libMemSet((byte *)&__state + sizeof(uint16_t *), 0, sizeof(stateT));
// Zero out stack. // Zero out stack.
@ -47,3 +39,14 @@ void stateReset(void) {
__state.outputting = true; __state.outputting = true;
} }
void stateShutdown(void) {
portFree(__state.stack);
}
void stateStartup(void) {
__state.stack = (uint16_t *)portMalloc(sizeof(uint16_t) * STACK_SIZE);
if (__state.stack == 0) portDie(MSG_STA_CANNOT_ALLOCATE_STACK);
}

View file

@ -59,7 +59,7 @@ static fileListT *_selected = 0;
static uint16_t _gameCount = 0; static uint16_t _gameCount = 0;
CODE_BLOCK(8) static void uiBox(byte x, byte y, byte w, byte h) { static void uiBox(byte x, byte y, byte w, byte h) {
byte i; byte i;
byte j; byte j;
char *b = portSymbolsGet(); char *b = portSymbolsGet();
@ -83,25 +83,25 @@ CODE_BLOCK(8) static void uiBox(byte x, byte y, byte w, byte h) {
} }
CODE_BLOCK(8) static void uiCenter(char *m) { static void uiCenter(char *m) {
byte x; byte x;
byte y; byte y;
byte w = 80; byte w = 80;
byte l = libStrLen(m); byte l = libStrLen(m);
portCharGetPos(&x, &y); portCharGetPos(&x, &y);
portCharSetPos((w - l) * 0.5, y); portCharSetPos((w - l) / 2, y);
for (x=0; x<l; x++) portCharPrint(m[x]); for (x=0; x<l; x++) portCharPrint(m[x]);
portCharSetPos(1, y + 1); portCharSetPos(1, y + 1);
} }
CODE_BLOCK(8) static void uiDialog(byte fc, byte bc, byte tc, byte y, char *message) { static void uiDialog(byte fc, byte bc, byte tc, byte y, char *message) {
byte l; byte l;
byte x; byte x;
l = libStrLen(message); l = libStrLen(message);
x = (_screenWidth - l) * 0.5 - 1; x = (_screenWidth - l) / 2 - 2;
portColorSet(fc, bc); portColorSet(fc, bc);
uiBox(x - 1, y, l + 4, 5); uiBox(x - 1, y, l + 4, 5);
portColorSet(tc, bc); portColorSet(tc, bc);
@ -109,7 +109,7 @@ CODE_BLOCK(8) static void uiDialog(byte fc, byte bc, byte tc, byte y, char *mess
} }
CODE_BLOCK(8) void uiFileAdd(char *filename, uint32_t size) { void uiFileAdd(char *filename, uint32_t size) {
uint32_t l; uint32_t l;
byte v; byte v;
fileListT *newGame; fileListT *newGame;
@ -154,7 +154,7 @@ CODE_BLOCK(8) void uiFileAdd(char *filename, uint32_t size) {
} }
CODE_BLOCK(8) void uiGameSelect(void) { void uiGameSelect(char *path) {
byte x; byte x;
byte y; byte y;
byte h; byte h;
@ -174,7 +174,7 @@ CODE_BLOCK(8) void uiGameSelect(void) {
portCharGetPos(&x, &y); portCharGetPos(&x, &y);
y += 2; y += 2;
portFileLister(); portFileLister(path);
// No games? // No games?
if (_games == 0) { if (_games == 0) {
@ -193,7 +193,7 @@ CODE_BLOCK(8) void uiGameSelect(void) {
} }
// Draw chooser window. // Draw chooser window.
x = (_screenWidth - _longestName - 4) * 0.5; x = (_screenWidth - _longestName - 4) / 2;
w = _longestName + 4; w = _longestName + 4;
h = _screenHeight - y; h = _screenHeight - y;
portColorSet(15, 1); portColorSet(15, 1);
@ -253,15 +253,6 @@ CODE_BLOCK(8) void uiGameSelect(void) {
// Loading dialog. // Loading dialog.
uiDialog(15, 8, 15, y + 3, " Loading story! "); uiDialog(15, 8, 15, y + 3, " Loading story! ");
// Generate save game name.
_saveName = (char *)portMalloc(_selected->filenameLen + 2);
if (_saveName == 0) portDie(MSG_UI_CANNOT_ALLOCATE, _selected->filenameLen + 2);
for (i=0; i<_selected->filenameLen; i++) _saveName[i] = _selected->filename[i];
_saveName[_selected->filenameLen - 2] = 's';
_saveName[_selected->filenameLen - 1] = 'a';
_saveName[_selected->filenameLen ] = 'v';
_saveName[_selected->filenameLen + 1] = 0;
// Dump game list, except selected game. // Dump game list, except selected game.
g = _games; g = _games;
while (g) { while (g) {
@ -275,9 +266,38 @@ CODE_BLOCK(8) void uiGameSelect(void) {
} }
} }
// Get ready. // Generate full story name (destroys x & y from above).
x = 0;
y = libStrLen(path);
for (i=0; i<y; i++) __memoryBuffer[x++] = path[i];
for (i=0; i<_selected->filenameLen; i++) __memoryBuffer[x++] = _selected->filename[i];
__memoryBuffer[x] = 0;
// Generate save game name (relies on x and __memoryBuffer from above).
_saveName = (char *)portMalloc(x + 2);
if (_saveName == 0) portDie(MSG_UI_CANNOT_ALLOCATE, x + 2);
for (i=0; i<x; i++) _saveName[i] = __memoryBuffer[i];
_saveName[x - 2] = 's';
_saveName[x - 1] = 'a';
_saveName[x ] = 'v';
_saveName[x + 1] = 0;
/*
uiStringPrint("\nstory = [");
uiStringPrint(__memoryBuffer);
uiStringPrint("]");
uiStringPrint("\nsave = [");
uiStringPrint(_saveName);
uiStringPrint("]\n");
portCharGet();
*/
// Get ready (relies on __memoryBuffer from above).
stateStartup();
stateReset(); stateReset();
portStoryLoad(_selected->filename, &_selected->filesize); portStoryLoad(__memoryBuffer, &_selected->filesize);
storyChecksumCalculate(); storyChecksumCalculate();
opcodesSetup(); opcodesSetup();
storySetup(); storySetup();
@ -293,6 +313,9 @@ CODE_BLOCK(8) void uiGameSelect(void) {
// Start the game! // Start the game!
interpreterRun(); interpreterRun();
// Shutdown.
stateShutdown();
// Free selected game info. // Free selected game info.
portFree(_selected->filename); portFree(_selected->filename);
portFree(_selected); portFree(_selected);
@ -311,7 +334,7 @@ void uiSizeGet(byte *w, byte *h) {
} }
CODE_BLOCK(8) void uiSizeSet(byte w, byte h) { void uiSizeSet(byte w, byte h) {
_screenWidth = w; _screenWidth = w;
_screenHeight = h; _screenHeight = h;
} }
@ -327,13 +350,13 @@ uint32_t uiStorySizeGet(void) {
} }
CODE_BLOCK(8) static void uiStringPrint(char *s) { static void uiStringPrint(char *s) {
byte i = 0; byte i = 0;
while (s[i] != 0) portCharPrint(s[i++]); while (s[i] != 0) portCharPrint(s[i++]);
} }
CODE_BLOCK(8) static void uiTitleDraw(void) { static void uiTitleDraw(void) {
portColorSet(9, 0); portColorSet(9, 0);
portScreenClear(); portScreenClear();