From d99a9070450157dd8fc3e5d6ad5172af4cc0be59 Mon Sep 17 00:00:00 2001
From: Ian C
The following directives are also recognised with an optional period (.) in
front of them, and are case insensitive. Directives can also be used to
@@ -412,7 +410,7 @@ word
-
In any of the directives above, where a value is defined, an expression can be entered.
@@ -604,7 +602,7 @@ Bitwise XOR. -The assembler has built-in support for a few different character sets. These can be set by using the options `charset` or `codepage`, i.e.
@@ -635,23 +633,85 @@ spectrum The character codes as used on the Sinclair ZX Spectrum. ++# + | ++The British Pound sign. |
-cbm +' | -PETSCII as used on the Commodore Business Machine's range from the -PET to the C128. See -https://en.wikipedia.org/wiki/PETSCII more details. +Inverse double quotes. + |
+\ + | ++Inverse slash. + |
+! + | ++Inverse question mark. |
+| + | ++Inverse space. + |
+~ + | ++Inverse minus sign. + |
+{ } + | ++Inverse round brackets. + |
+` + | ++The newline character. Note that the newline is actually a HALT opcode used to +terminate the line. + |
e.g.
@@ -678,7 +738,7 @@ https://en.wikipedia.org/wiki/PETSCII more details. -Macros can be defined in one of two ways; either parameterless or with named @@ -743,13 +803,14 @@ be replaced by using the following option, e.g.
-Note that this is enforced when the macro is *used*, not when it is *defined*. +Note that this is enforced when the macro is used not when it is +defined. Also the character must not be quoted, as that will be parsed as a string holding the character code of the character.
-+Generates a P-file for an emulator. A ZX81 .P file is simply a dump of memory +from the system variables onwards. +
+ +This format does not support memory blocks (the .P file is not a container +format) and so will only output anything in the first bank used, and using the +output-file for the filename. +
+ +The output file will be created as a BASIC program, containing a REM +statement holding the machine code, and a command to execute the code. As +such the output will fail if the code in Bank 0 does not start at address 16514. +Your code must also support being executed from this address. +
+ +Another important thing to note is about the display file. In the ZX81 +memory map the DFILE can move around depending on the size of the program. +The output driver will create a display file for you. The easiest way to +reference this is to read the DFILE system variable when your program starts. +
+ +Alternatively you can just as easily set up your own display file once +your program starts if you have special requirements, e.g. a display file for +pseudo hi-res. +
+ + +The ZX81 output driver supports the following settings that can be set via +an option command. +
+ +Option | +Description |
+option zx81-margin, <pal|ntsc> + | ++Sets the MARGIN system variable appropriately either for the PAL or NTSC +TV system. Defaults to PAL. + |
+option zx81-autorun, <on|off> + | ++Whether the ZX81 should auto run the machine code. Defaults to on. + |
+option zx81-collapse-dfile, <on|off> + | ++Whether the display file should be generated collapsed (e.g. for 1K mode). +Defaults to off. + |
@@ -876,7 +1002,7 @@ to start the machine code, e.g.
Any remaining blocks will be stored as-is without any basic loader.
-By default no output listing is generated. This can be controlled by the @@ -1088,14 +1214,14 @@ equivalent:
For the hidden OUT instruction using the flag register, $00 or $ff depending -on where you're reading, the following are all equivalent, where _value_ can -be any value at all: +on where you're reading, the following are all equivalent, where value +can be any value at all:
out (c) out (c),f - out (c),diff --git a/src/Makefile b/src/Makefile index 0812105..29ef34c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -41,7 +41,8 @@ SOURCE = casm.c \ z80.c \ rawout.c \ specout.c \ - t64out.c + t64out.c \ + zx81out.c OBJECTS = casm.o \ expr.o \ @@ -60,7 +61,8 @@ OBJECTS = casm.o \ z80.o \ rawout.o \ specout.o \ - t64out.o + t64out.o \ + zx81out.o $(TARGET): $(OBJECTS) $(CC) $(CLAGS) -o $(TARGET) $(OBJECTS) @@ -73,7 +75,7 @@ clean: alias.o: alias.c global.h basetype.h util.h state.h alias.h casm.o: casm.c global.h basetype.h util.h state.h expr.h label.h macro.h \ cmd.h parse.h codepage.h stack.h listing.h alias.h output.h rawout.h \ - specout.h z80.h 6502.h + specout.h t64out.h zx81out.h z80.h 6502.h codepage.o: codepage.c global.h basetype.h util.h state.h codepage.h \ parse.h cmd.h expr.o: expr.c global.h basetype.h util.h state.h expr.h label.h @@ -84,7 +86,7 @@ listing.o: listing.c global.h basetype.h util.h state.h label.h macro.h \ macro.o: macro.c global.h basetype.h util.h state.h codepage.h parse.h \ cmd.h varchar.h macro.h output.o: output.c global.h basetype.h util.h state.h output.h parse.h \ - cmd.h rawout.h specout.h t64out.h + cmd.h rawout.h specout.h t64out.h zx81out.h parse.o: parse.c global.h basetype.h util.h state.h codepage.h parse.h \ cmd.h rawout.o: rawout.c global.h basetype.h util.h state.h rawout.h parse.h \ @@ -100,3 +102,5 @@ varchar.o: varchar.c global.h basetype.h util.h state.h codepage.h \ parse.h cmd.h varchar.h z80.o: z80.c global.h basetype.h util.h state.h expr.h label.h parse.h \ cmd.h codepage.h varchar.h z80.h +zx81out.o: zx81out.c global.h basetype.h util.h state.h codepage.h \ + parse.h cmd.h zx81out.h diff --git a/src/casm.c b/src/casm.c index 7624978..bad07f1 100644 --- a/src/casm.c +++ b/src/casm.c @@ -40,10 +40,7 @@ #include "stack.h" #include "listing.h" #include "alias.h" - #include "output.h" -#include "rawout.h" -#include "specout.h" /* ---------------------------------------- PROCESSORS */ @@ -404,6 +401,14 @@ static CommandStatus OPTION(const char *label, int argc, char *argv[], { return SpecTAPOutputSetOption(entry->value, ac, args, q, err, errsize); } + else if ((entry = ParseTable(opt, T64OutputOptions()))) + { + return T64OutputSetOption(entry->value, ac, args, q, err, errsize); + } + else if ((entry = ParseTable(opt, ZX81OutputOptions()))) + { + return ZX81OutputSetOption(entry->value, ac, args, q, err, errsize); + } else if ((entry = ParseTable(opt, cpu->options()))) { return cpu->set_option(entry->value, ac, args, q, err, errsize); diff --git a/src/codepage.c b/src/codepage.c index 4cbc1bc..cecdf66 100644 --- a/src/codepage.c +++ b/src/codepage.c @@ -101,8 +101,8 @@ static CodepageDef cp_ascii[] = static CodepageDef cp_zx81[] = { - {' ', 0x00}, {'!', 0x00}, {'"', 0x0b}, {'#', 0x0c}, - {'$', 0x0d}, {'%', 0x00}, {'&', 0x00}, {'\'', 0x0b}, + {' ', 0x00}, {'!', 0x8f}, {'"', 0x0b}, {'#', 0x0c}, + {'$', 0x0d}, {'%', 0x00}, {'&', 0x00}, {'\'', 0x8b}, {'(', 0x10}, {')', 0x11}, {'*', 0x17}, {'+', 0x15}, {',', 0x1a}, {'-', 0x16}, {'.', 0x1b}, {'/', 0x24}, {'0', 0x1c}, {'1', 0x1d}, {'2', 0x1e}, {'3', 0x1f}, @@ -116,15 +116,15 @@ static CodepageDef cp_zx81[] = {'P', 0xb5}, {'Q', 0xb6}, {'R', 0xb7}, {'S', 0xb8}, {'T', 0xb9}, {'U', 0xba}, {'V', 0xbb}, {'W', 0xbc}, {'X', 0xbd}, {'Y', 0xbe}, {'Z', 0xbf}, {'[', 0x10}, - {'\\', 0x24}, {']', 0x11}, {'^', 0xde}, {'_', 0x80}, - {'`', 0x60}, {'a', 0x26}, {'b', 0x27}, {'c', 0x28}, + {'\\', 0x98}, {']', 0x11}, {'^', 0xde}, {'_', 0x80}, + {'`', 0x76}, {'a', 0x26}, {'b', 0x27}, {'c', 0x28}, {'d', 0x29}, {'e', 0x2a}, {'f', 0x2b}, {'g', 0x2c}, {'h', 0x2d}, {'i', 0x2e}, {'j', 0x2f}, {'k', 0x30}, {'l', 0x31}, {'m', 0x32}, {'n', 0x33}, {'o', 0x34}, {'p', 0x35}, {'q', 0x36}, {'r', 0x37}, {'s', 0x38}, {'t', 0x39}, {'u', 0x3a}, {'v', 0x3b}, {'w', 0x3c}, {'x', 0x3d}, {'y', 0x3e}, {'z', 0x3f}, {'{', 0x90}, - {'|', 0x00}, {'}', 0x91}, {'~', 0x96}, + {'|', 0x80}, {'}', 0x91}, {'~', 0x96}, {0, 0} }; diff --git a/src/example/Makefile b/src/example/Makefile index e9ddfce..7c53209 100644 --- a/src/example/Makefile +++ b/src/example/Makefile @@ -20,18 +20,24 @@ # Makefile for examples # -ALL = spectrum.tap c64.t64 # zx81.p +ALL = spectrum.tap c64.t64 zx81.p CASM = ../casm -all: $(ALL) +all: $(ALL) $(CASM) + +$(CASM): ../*.[ch] + cd .. ; make remake: clean all -spectrum.tap: spectrum.asm +spectrum.tap: spectrum.asm $(CASM) $(CASM) spectrum.asm -c64.t64: c64.asm +c64.t64: c64.asm $(CASM) $(CASM) c64.asm +zx81.p: zx81.asm $(CASM) + $(CASM) zx81.asm + clean: rm -f $(ALL) diff --git a/src/example/zx81.asm b/src/example/zx81.asm new file mode 100644 index 0000000..3a0021c --- /dev/null +++ b/src/example/zx81.asm @@ -0,0 +1,34 @@ + ; Simple example ZX81 code + ; + + option output-file,zx81.p + option output-format,zx81 + + option zx81-margin,pal + option zx81-autorun,on + option zx81-collapse-dfile,off + + option codepage,zx81 + +DFILE: equ 16396 + + org 16514 + + ld hl,(DFILE) + inc hl + ld de,hello +loop: + ld a,(de) + cp 255 + ret z + ld (hl),a + inc hl + inc de + + ld a,(hl) + cp $76 + jr nz,loop + inc hl + jr loop + +hello: db "HELLO|WORLD hello world (#69.99 well spent)",255 diff --git a/src/label.c b/src/label.c index c15627f..75270ef 100644 --- a/src/label.c +++ b/src/label.c @@ -277,17 +277,17 @@ int LabelExpand(const char *expr, int *result) { found = ParseBase(expr + 1, 16, result, '\0'); } - else if (last == 'h') + else if (last == 'h' || last == 'H') { - found = ParseBase(expr, 16, result, 'h'); + found = ParseBase(expr, 16, result, last); } else if (first == '%') { found = ParseBase(expr, 2, result, '\0'); } - else if (last == 'b') + else if (last == 'b' || last == 'B') { - found = ParseBase(expr, 2, result, 'b'); + found = ParseBase(expr, 2, result, last); } else if (first == '\'' && last == '\'' && len == 3) { diff --git a/src/output.c b/src/output.c index 4c03e4e..8476f9d 100644 --- a/src/output.c +++ b/src/output.c @@ -28,12 +28,6 @@ #include "global.h" #include "output.h" -#include "rawout.h" -#include "specout.h" -#include "t64out.h" -/* TODO #include "zx81out.h" */ - - /* ---------------------------------------- GLOBALS */ @@ -56,7 +50,8 @@ typedef enum { RAW, TAP, - T64 + T64, + ZX81 } Format; static char output[4096] = "output"; @@ -69,6 +64,7 @@ static ValueTable format_table[] = {"raw", RAW}, {"spectrum", TAP}, {"t64", T64}, + {"zx81", ZX81}, {NULL} }; @@ -142,6 +138,10 @@ int OutputCode(void) return T64Output(output, output_bank, bank, count, error, sizeof error); + case ZX81: + return ZX81Output(output, output_bank, bank, count, + error, sizeof error); + default: break; } diff --git a/src/output.h b/src/output.h index cb0e5ca..8ea1c1d 100644 --- a/src/output.h +++ b/src/output.h @@ -29,6 +29,13 @@ #include "parse.h" #include "cmd.h" +/* Pull in the output drivers +*/ +#include "rawout.h" +#include "specout.h" +#include "t64out.h" +#include "zx81out.h" + /* ---------------------------------------- INTERFACES */ diff --git a/src/rawout.c b/src/rawout.c index 35ff650..3f75b50 100644 --- a/src/rawout.c +++ b/src/rawout.c @@ -67,7 +67,7 @@ int RawOutput(const char *filename, const char *filename_bank, if (!(fp = fopen(name, "wb"))) { - snprintf(error, error_size, "Failed to open %s\n", name); + snprintf(error, error_size, "Failed to open %s", name); return FALSE; } diff --git a/src/specout.c b/src/specout.c index e5ed897..b29b6ba 100644 --- a/src/specout.c +++ b/src/specout.c @@ -81,7 +81,7 @@ int SpecTAPOutput(const char *filename, const char *filename_bank, if (!fp) { - snprintf(error, error_size, "Failed to create %s\n", filename); + snprintf(error, error_size, "Failed to create %s", filename); return FALSE; } diff --git a/src/t64out.c b/src/t64out.c index 0fd308f..6aa82f2 100644 --- a/src/t64out.c +++ b/src/t64out.c @@ -122,7 +122,7 @@ int T64Output(const char *filename, const char *filename_bank, if (!fp) { - snprintf(error, error_size, "Failed to create %s\n", filename); + snprintf(error, error_size, "Failed to create %s", filename); return FALSE; } diff --git a/src/t64out.h b/src/t64out.h index 2743d0e..b4c5103 100644 --- a/src/t64out.h +++ b/src/t64out.h @@ -43,7 +43,7 @@ CommandStatus T64OutputSetOption(int opt, int argc, char *argv[], size_t error_size); -/* Spectrum TAP output of assembly. Returns TRUE if OK, FALSE for failure. +/* C64 T64 tape output of assembly. Returns TRUE if OK, FALSE for failure. */ int T64Output(const char *filename, const char *filename_bank, MemoryBank **bank, int count, diff --git a/src/zx81out.c b/src/zx81out.c new file mode 100644 index 0000000..fe4d83c --- /dev/null +++ b/src/zx81out.c @@ -0,0 +1,268 @@ +/* + + casm - Simple, portable assembler + + Copyright (C) 2003-2015 Ian Cowburn (ianc@noddybox.demon.co.uk) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see+ out (c),value