From 4615bf4b669af244f7a2aa71af60cb363b08c472 Mon Sep 17 00:00:00 2001 From: Ian C Date: Tue, 21 Sep 2021 21:15:08 +0100 Subject: Imported V1.8 --- README.md | 3 +- src/casm.c | 2 +- src/cpcout.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++-- src/example/cpc.asm | 3 +- 4 files changed, 122 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7983730..5d074fe 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,9 @@ Currently **casm** supports the following output drivers: * ZX81 P file * Gameboy ROM * SNES ROM -* A simple library format for larger projects. +* A simple library format for larger projects * NES ROM +* Amstrad CPC CDT tape file ## Latest changes diff --git a/src/casm.c b/src/casm.c index c747ad9..10c1725 100644 --- a/src/casm.c +++ b/src/casm.c @@ -59,7 +59,7 @@ */ static const char *casm_usage = -"Version 1.7\n" +"Version 1.8\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" diff --git a/src/cpcout.c b/src/cpcout.c index 6e37a1c..b21700a 100644 --- a/src/cpcout.c +++ b/src/cpcout.c @@ -42,20 +42,23 @@ enum option_t { OPT_START_ADDR, + OPT_LOADER }; static const ValueTable option_set[] = { - {"cpc-start", OPT_START_ADDR}, + {"cpc-start", OPT_START_ADDR}, + {"cpc-loader", OPT_LOADER}, {NULL} }; typedef struct { int start_addr; + int loader; } Options; -static Options options = {-1}; +static Options options = {-1, 0}; typedef struct { @@ -71,6 +74,7 @@ static void InitStream(Stream *s) s->length = 0; } + static void AddStreamByte(Stream *s, Byte b) { s->length++; @@ -78,6 +82,7 @@ static void AddStreamByte(Stream *s, Byte b) s->stream[s->length - 1] = b; } + static void AddStreamMem(Stream *s, Byte *mem, size_t len) { while(len--) @@ -87,6 +92,13 @@ static void AddStreamMem(Stream *s, Byte *mem, size_t len) } +static void AddStreamWord(Stream *s, int w) +{ + AddStreamByte(s, LO_BYTE(w)); + AddStreamByte(s, HI_BYTE(w)); +} + + static void FreeStream(Stream *s) { if (s->stream) @@ -236,6 +248,10 @@ CommandStatus CPCOutputSetOption(int opt, int argc, char *argv[], int quoted[], CMD_EXPR(argv[0], options.start_addr); break; + case OPT_LOADER: + options.loader = ParseTrueFalse(argv[0], FALSE); + break; + default: break; } @@ -269,6 +285,104 @@ int CPCOutput(const char *filename, const char *filename_bank, WriteByte(fp, 1); WriteByte(fp, 0x14); + /* Output the basic loader if defined + */ + if (options.loader) + { + Stream basic; + Stream stream; + Byte header[256] = {0}; + Word crc; + + InitStream(&basic); + + /* Line 10 MEMORY &xxxx + */ + AddStreamWord(&basic, 2 + 2 + 1 + 3 + 1); + AddStreamWord(&basic, 10); + AddStreamByte(&basic, 0xaa); + AddStreamByte(&basic, 0x1c); + AddStreamWord(&basic, bank[0]->min_address_used); + AddStreamByte(&basic, 0); + + /* Line 20 LOAD "" + */ + AddStreamWord(&basic, 2 + 2 + 1 + 3 + 1); + AddStreamWord(&basic, 20); + AddStreamByte(&basic, 0xa8); + AddStreamByte(&basic, CodeFromNative(CP_ASCII, '"')); + AddStreamByte(&basic, CodeFromNative(CP_ASCII, '!')); + AddStreamByte(&basic, CodeFromNative(CP_ASCII, '"')); + AddStreamByte(&basic, 0); + + /* Line 30 CALL &xxxx + */ + AddStreamWord(&basic, 2 + 2 + 1 + 3 + 1); + AddStreamWord(&basic, 30); + AddStreamByte(&basic, 0x83); + AddStreamByte(&basic, 0x1c); + AddStreamWord(&basic, options.start_addr); + AddStreamByte(&basic, 0); + + /* End of program + */ + AddStreamWord(&basic, 0); + + /* Create header + */ + WriteStringMem(header, 0, "LOADER.BAS", 16, 0, CP_ASCII); + + header[16] = 1; + header[17] = 255; + header[18] = 0; + WriteWordMem(header, 19, basic.length); + WriteWordMem(header, 21, 0x170); + header[23] = 255; + WriteWordMem(header, 24, basic.length); + + crc = CRC(header, 256); + + /* Output header block + */ + InitStream(&stream); + + AddStreamByte(&stream, 0x2c); + AddStreamMem(&stream, header, 256); + AddStreamByte(&stream, HIBYTE(crc)); + AddStreamByte(&stream, LOBYTE(crc)); + AddStreamByte(&stream, 0xff); + AddStreamByte(&stream, 0xff); + AddStreamByte(&stream, 0xff); + AddStreamByte(&stream, 0xff); + + OutputTZXTurboBlock(fp, &stream); + + FreeStream(&stream); + + /* Output basic data block + */ + InitStream(&stream); + + memset(header, 0, 256); + memcpy(header, basic.stream, basic.length); + crc = CRC(header, 256); + + AddStreamByte(&stream, 0x16); + AddStreamMem(&stream, header, 256); + AddStreamByte(&stream, HIBYTE(crc)); + AddStreamByte(&stream, LOBYTE(crc)); + AddStreamByte(&stream, 0xff); + AddStreamByte(&stream, 0xff); + AddStreamByte(&stream, 0xff); + AddStreamByte(&stream, 0xff); + + OutputTZXTurboBlock(fp, &stream); + + FreeStream(&stream); + + FreeStream(&basic); + } + for(f = 0; f < count; f++) { const Byte *mem; @@ -355,7 +469,7 @@ int CPCOutput(const char *filename, const char *filename_bank, crc = CRC(header, 256); - /* Write CSW data + /* Write header data */ AddStreamByte(&stream, 0x2c); AddStreamMem(&stream, header, 256); diff --git a/src/example/cpc.asm b/src/example/cpc.asm index 5a37702..e1f00bc 100644 --- a/src/example/cpc.asm +++ b/src/example/cpc.asm @@ -7,12 +7,13 @@ option output-file,cpc.cdt option output-format,cpc option cpc-start,start + option cpc-loader,true start: org $8000 ld hl,msg call print - jp $ + ret org $8400 print: -- cgit v1.2.3