diff options
author | Ian C <ianc@noddybox.co.uk> | 2016-09-14 22:03:40 +0100 |
---|---|---|
committer | Ian C <ianc@noddybox.co.uk> | 2016-09-14 22:03:40 +0100 |
commit | ace88543a32f2c6dfc6a3aa17bd9a35f55a0b1d8 (patch) | |
tree | 6ee71fcfa7dc4d38c846581ee303ce91945d7b14 /src | |
parent | b1aa1e289accb74e8de252cfeee86f1eed56eddb (diff) |
Added option for BASIC loader to Spectrum TAP file.
Diffstat (limited to 'src')
-rw-r--r-- | src/example/spectrum.asm | 4 | ||||
-rw-r--r-- | src/listing.c | 2 | ||||
-rw-r--r-- | src/specout.c | 220 |
3 files changed, 221 insertions, 5 deletions
diff --git a/src/example/spectrum.asm b/src/example/spectrum.asm index 01175f9..70cb6ea 100644 --- a/src/example/spectrum.asm +++ b/src/example/spectrum.asm @@ -8,8 +8,10 @@ option output-file,spectrum.tap option output-format,spectrum + option +spectrum-loader + option spectrum-start,start - org 32768 +start: org 32768 ld a,0 loop: diff --git a/src/listing.c b/src/listing.c index 13fcc2e..5bc6568 100644 --- a/src/listing.c +++ b/src/listing.c @@ -19,7 +19,7 @@ ------------------------------------------------------------------------- - Common utilities + Listing */ #include <stdlib.h> diff --git a/src/specout.c b/src/specout.c index dbb8684..3f6719e 100644 --- a/src/specout.c +++ b/src/specout.c @@ -24,13 +24,134 @@ */ #include <stdlib.h> #include <stdio.h> +#include <stdarg.h> #include "global.h" #include "specout.h" +#include "expr.h" + + +/* ---------------------------------------- PRIVATE TYPES +*/ +enum option_t +{ + OPT_LOADER, + OPT_START_ADDR, +}; + +static const ValueTable option_set[] = +{ + {"spectrum-loader", OPT_LOADER}, + {"spectrum-start", OPT_START_ADDR}, + {NULL} +}; + +typedef struct +{ + int loader; + int start_addr; +} Options; + + +/* ---------------------------------------- PRIVATE DATA +*/ + +/* Types for AddLine() +*/ +#define TYPE_END 0 +#define TYPE_TOKEN 1 +#define TYPE_STRING 2 + +/* Constants for some tokens +*/ +#define TOK_VAL 176 +#define TOK_QUOTE 34 +#define TOK_CODE 175 +#define TOK_USR 192 +#define TOK_LOAD 239 +#define TOK_RAND 249 +#define TOK_CLEAR 253 + + +static Options options = +{ + FALSE, + -1 +}; + +/* Buffers used for BASIC loader +*/ +static unsigned char basic[0x10000]; +static unsigned endptr = 0; +static unsigned line_no = 10; /* ---------------------------------------- PRIVATE FUNCTIONS */ +static void Poke(unsigned char b, int *len) +{ + if (len) + { + (*len)++; + } + + basic[endptr++]=b; +} + + +static void AddBASICLine(int type, ...) +{ + va_list va; + int len; + unsigned char *len_ptr; + + Poke(line_no>>8, NULL); + Poke(line_no&0xff, NULL); + line_no += 10; + + len_ptr = basic + endptr; + endptr += 2; + len = 0; + + va_start(va,type); + + while(type!=TYPE_END) + { + char *str; + + switch(type) + { + case TYPE_TOKEN: + Poke(va_arg(va,int), &len); + break; + + case TYPE_STRING: + str = va_arg(va,char *); + + Poke(TOK_QUOTE, &len); + + while(*str) + { + Poke(*str++, &len); + } + + Poke(TOK_QUOTE, &len); + + break; + + default: + break; + } + + type = va_arg(va,int); + } + + Poke(0x0d, &len); + + *len_ptr++ = len&0xff; + *len_ptr = len>>8; +} + static Byte TapByte(FILE *fp, Byte b, Byte chk) { @@ -59,18 +180,48 @@ static Byte TapString(FILE *fp, const char *p, int len, Byte chk) } +static unsigned char TapStream(FILE *fp, const unsigned char *p, + unsigned addr, unsigned len, unsigned char chk) +{ + while(len--) + { + chk = TapByte(fp, p[addr], chk); + addr = (addr + 1) & 0xffff; + } + + return chk; +} + /* ---------------------------------------- INTERFACES */ const ValueTable *SpecTAPOutputOptions(void) { - return NULL; + return option_set; } CommandStatus SpecTAPOutputSetOption(int opt, int argc, char *argv[], int quoted[], - char *error, size_t error_size) + char *err, size_t errsize) { - return CMD_NOT_KNOWN; + CommandStatus stat = CMD_OK; + + CMD_ARGC_CHECK(1); + + switch(opt) + { + case OPT_LOADER: + options.loader = ParseTrueFalse(argv[0], FALSE); + break; + + case OPT_START_ADDR: + CMD_EXPR(argv[0], options.start_addr); + break; + + default: + break; + } + + return stat; } int SpecTAPOutput(const char *filename, const char *filename_bank, @@ -85,6 +236,69 @@ int SpecTAPOutput(const char *filename, const char *filename_bank, return FALSE; } + /* First get the initial address is none defined + */ + if (options.loader && options.start_addr == -1) + { + options.start_addr = bank[0]->min_address_used; + } + + /* Output the BASIC loader if set + */ + if (options.loader) + { + char no[64]; + Byte chk = 0; + + snprintf(no, sizeof no, "%u", options.start_addr); + + /* CLEAR VAL "start_addr" + */ + AddBASICLine(TYPE_TOKEN, TOK_CLEAR, + TYPE_TOKEN, TOK_VAL, + TYPE_STRING, no, + TYPE_END); + + /* LOAD "" CODE + */ + for(f = 0; f < count; f++) + { + AddBASICLine(TYPE_TOKEN, TOK_LOAD, + TYPE_TOKEN, TOK_QUOTE, + TYPE_TOKEN, TOK_QUOTE, + TYPE_TOKEN, TOK_CODE, + TYPE_END); + } + + /* RANDOMIZE USR VAL "start_addr" + */ + AddBASICLine(TYPE_TOKEN, TOK_RAND, + TYPE_TOKEN, TOK_USR, + TYPE_TOKEN, TOK_VAL, + TYPE_STRING, no, + TYPE_END); + + TapWord(fp, 19, 0); + chk = TapByte(fp, 0, chk); + chk = TapByte(fp, 0, chk); + chk = TapString(fp, "LOADER.BAS", 10, chk); + chk = TapWord(fp, endptr, chk); + chk = TapWord(fp, 10, chk); + chk = TapWord(fp, endptr, chk); + + TapByte(fp, chk, 0); + + TapWord(fp, endptr + 2, 0); + + chk = 0; + + chk = TapByte(fp, 0xff, chk); + chk = TapStream(fp, basic, 0, endptr, chk); + TapByte(fp, chk, 0); + } + + /* Output the binary files + */ for(f = 0; f < count; f++) { Byte chk = 0; |