From d3713129e61a8953a61b8f15f7be6a3110197ed5 Mon Sep 17 00:00:00 2001 From: Ian C Date: Fri, 6 May 2016 16:12:42 +0100 Subject: Added simple library format. --- src/Makefile | 13 +++-- src/casm.c | 12 ++++ src/label.c | 107 ++++++++++++++++++++++++++++++++- src/label.h | 10 ++++ src/libout.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/libout.h | 68 +++++++++++++++++++++ src/output.c | 8 ++- src/output.h | 1 + src/test/lib1 | 14 +++++ src/test/lib2 | 15 +++++ src/test/link | 6 ++ 11 files changed, 433 insertions(+), 6 deletions(-) create mode 100644 src/libout.c create mode 100644 src/libout.h create mode 100644 src/test/lib1 create mode 100644 src/test/lib2 create mode 100644 src/test/link diff --git a/src/Makefile b/src/Makefile index af7befa..ea8c7a9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -46,7 +46,8 @@ SOURCE = casm.c \ t64out.c \ zx81out.c \ gbout.c \ - snesout.c + snesout.c \ + libout.c OBJECTS = casm.o \ expr.o \ @@ -70,7 +71,8 @@ OBJECTS = casm.o \ t64out.o \ zx81out.o \ gbout.o \ - snesout.o + snesout.o \ + libout.o $(TARGET): $(OBJECTS) $(CC) $(CLAGS) -o $(TARGET) $(OBJECTS) @@ -85,7 +87,8 @@ 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 t64out.h zx81out.h gbout.h z80.h 6502.h gbcpu.h 65c816.h + specout.h t64out.h zx81out.h gbout.h snesout.h libout.h z80.h 6502.h \ + gbcpu.h 65c816.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 @@ -95,12 +98,14 @@ gbout.o: gbout.c global.h basetype.h util.h state.h expr.h codepage.h \ parse.h cmd.h gbout.h label.o: label.c global.h basetype.h util.h state.h codepage.h parse.h \ cmd.h stack.h label.h +libout.o: libout.c global.h basetype.h util.h state.h libout.h parse.h \ + cmd.h listing.o: listing.c global.h basetype.h util.h state.h label.h macro.h \ cmd.h parse.h expr.h varchar.h listing.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 zx81out.h gbout.h + cmd.h rawout.h specout.h t64out.h zx81out.h gbout.h snesout.h libout.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 \ diff --git a/src/casm.c b/src/casm.c index fb50532..aadd8b3 100644 --- a/src/casm.c +++ b/src/casm.c @@ -506,6 +506,16 @@ static CommandStatus NULLCMD(const char *label, int argc, char *argv[], } +static CommandStatus IMPORT(const char *label, int argc, char *argv[], + int quoted[], char *err, size_t errsize) +{ + CMD_ARGC_CHECK(2); + + return LibLoad(argv[1], LibLoadAll, err, errsize) ? CMD_OK : CMD_FAILED; +} + + + static struct { const char *cmd; @@ -558,6 +568,8 @@ static struct {".alias", ALIAS}, {"nullcmd", NULLCMD}, {".nullcmd", NULLCMD}, + {"import", IMPORT}, + {".import", IMPORT}, {NULL} }; diff --git a/src/label.c b/src/label.c index 0807128..5fdc83e 100644 --- a/src/label.c +++ b/src/label.c @@ -57,8 +57,57 @@ static char namespace[MAX_LABEL_SIZE + 1]; static Stack *stack; -/* ---------------------------------------- PRIVATE FUNCTIONS INTERFACES +/* ---------------------------------------- PRIVATE FUNCTIONS */ + +static void WriteNumber(FILE *fp, int num) +{ + fprintf(fp, "%.11d", num); +} + + +static int ReadNumber(FILE *fp) +{ + char buff[12]; + int f; + + for(f= 0 ;f < 11; f++) + { + buff[f] = getc(fp); + } + + buff[f] = 0; + + return atoi(buff); +} + + +static void WriteName(FILE *fp, const char *name) +{ + fputs(name, fp); + putc(0, fp); +} + + +static char *ReadName(FILE *fp, char *name) +{ + int l = MAX_LABEL_SIZE; + int c; + char *p; + + p = name; + + while((c = getc(fp)) && (l--)) + { + *p++ = c; + } + + *p = 0; + + return name; +} + + static Label *FindLocal(const char *p, GlobalLabel *in) { int f; @@ -465,6 +514,62 @@ void LabelDump(FILE *fp, int dump_private) } } + +void LabelWriteBlob(FILE *fp) +{ + GlobalLabel *g = head; + int count; + int f; + + count = 0; + + while(g) + { + if (g->label.name[0] != '_') + { + count++; + } + + g = g->next; + } + + WriteNumber(fp, count); + + g = head; + + while(g) + { + if (g->label.name[0] != '_') + { + WriteName(fp, g->label.name); + WriteNumber(fp, g->label.value); + } + + g = g->next; + } +} + + +void LabelReadBlob(FILE *fp) +{ + int count; + int f; + + count = ReadNumber(fp); + + for(f = 0; f < count; f++) + { + char name[MAX_LABEL_SIZE + 1]; + int value; + + ReadName(fp, name); + value = ReadNumber(fp); + + LabelSet(name, value, GLOBAL_LABEL); + } +} + + /* vim: ai sw=4 ts=8 expandtab */ diff --git a/src/label.h b/src/label.h index faf841b..5b79d41 100644 --- a/src/label.h +++ b/src/label.h @@ -116,6 +116,16 @@ void LabelResetNamespace(void); void LabelDump(FILE *fp, int dump_private); +/* Dump a binary blob of information containing all the labels +*/ +void LabelWriteBlob(FILE *fp); + + +/* Read a binary blob of information containing all the labels +*/ +void LabelReadBlob(FILE *fp); + + #endif /* diff --git a/src/libout.c b/src/libout.c new file mode 100644 index 0000000..9303a2a --- /dev/null +++ b/src/libout.c @@ -0,0 +1,185 @@ +/* + + 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 . + + ------------------------------------------------------------------------- + + Various output type handlers. + +*/ +#include +#include +#include + +#include "global.h" +#include "libout.h" +#include "label.h" + + +/* Magic value for library file +*/ +#define CASM_LIBRARY_MAGIC "CASMLIBv1%" +#define CASM_LIBRARY_MAGIC_LEN 10 + + +/* ---------------------------------------- PRIVATE INTERFACES +*/ + +static void WriteNumber(FILE *fp, int num) +{ + fprintf(fp, "%.11d", num); +} + + +static int ReadNumber(FILE *fp) +{ + char buff[12]; + int f; + + for(f= 0 ;f < 11; f++) + { + buff[f] = getc(fp); + } + + buff[f] = 0; + + return atoi(buff); +} + + +/* ---------------------------------------- INTERFACES +*/ +const ValueTable *LibOutputOptions(void) +{ + return NULL; +} + +CommandStatus LibOutputSetOption(int opt, int argc, char *argv[], + int quoted[], char *error, size_t error_size) +{ + return CMD_NOT_KNOWN; +} + +int LibOutput(const char *filename, const char *filename_bank, + MemoryBank **bank, int count, char *error, size_t error_size) +{ + FILE *fp; + char buff[4096]; + int f; + + if (!(fp = fopen(filename, "wb"))) + { + snprintf(error, error_size, "Failed to open %s", filename); + return FALSE; + } + + fwrite(CASM_LIBRARY_MAGIC, 1, CASM_LIBRARY_MAGIC_LEN, fp); + + WriteNumber(fp, count); + + for(f = 0; f < count; f++) + { + const Byte *mem; + int min, max, len; + + mem = bank[f]->memory; + min = bank[f]->min_address_used; + max = bank[f]->max_address_used; + len = max - min + 1; + + WriteNumber(fp, (int)bank[f]->number); + WriteNumber(fp, min); + WriteNumber(fp, len); + + fwrite(mem + min, 1, len, fp); + } + + LabelWriteBlob(fp); + + fclose(fp); + + return TRUE; +} + + +int LibLoad(const char *filename, LibLoadOption opt, + char *error, size_t error_size) +{ + char magic[CASM_LIBRARY_MAGIC_LEN + 1] = {0}; + FILE *fp; + Byte buff[0x10000]; + int count; + int f; + + if (!(fp = fopen(filename, "rb"))) + { + snprintf(error, error_size, "Failed to open %s", filename); + return FALSE; + } + + fread(magic, 1, CASM_LIBRARY_MAGIC_LEN, fp); + + if (strcmp(magic, CASM_LIBRARY_MAGIC) != 0) + { + snprintf(error, error_size, "%s not a recognised library", filename); + fclose(fp); + return FALSE; + } + + count = ReadNumber(fp); + + for(f = 0; f < count; f++) + { + int bank; + int min; + int len; + int old_pc; + Byte *p; + + bank = ReadNumber(fp); + min = ReadNumber(fp); + len = ReadNumber(fp); + + SetAddressBank(bank); + + fread(buff, 1, len, fp); + + old_pc = PC(); + + SetPC(min); + p = buff; + + while(len-- > 0) + { + PCWrite(*p++); + } + + SetPC(old_pc); + } + + LabelReadBlob(fp); + + fclose(fp); + + return TRUE; +} + + +/* +vim: ai sw=4 ts=8 expandtab +*/ diff --git a/src/libout.h b/src/libout.h new file mode 100644 index 0000000..851a168 --- /dev/null +++ b/src/libout.h @@ -0,0 +1,68 @@ +/* + + 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 . + + ------------------------------------------------------------------------- + + LIB binary file output + +*/ + +#ifndef CASM_LIBOUT_H +#define CASM_LIBOUT_H + +#include "parse.h" +#include "state.h" +#include "cmd.h" + +typedef enum +{ + LibLoadAll, + LibLoadLabels, + LibLoadMemory +} LibLoadOption; + +/* ---------------------------------------- INTERFACES +*/ + + +/* LIB Output options +*/ +const ValueTable *LibOutputOptions(void); + +CommandStatus LibOutputSetOption(int opt, int argc, char *argv[], + int quoted[], char *error, size_t error_size); + + +/* LIB output of assembly. Returns TRUE if OK, FALSE for failure. +*/ +int LibOutput(const char *filename, const char *filename_bank, + MemoryBank **bank, int count, + char *error, size_t error_size); + + +/* Load a libray. Returns TRUE if OK, FALSE for failure and updates error. +*/ +int LibLoad(const char *filename, LibLoadOption opt, + char *error, size_t error_size); + +#endif + +/* +vim: ai sw=4 ts=8 expandtab +*/ diff --git a/src/output.c b/src/output.c index 71eb786..8a8d230 100644 --- a/src/output.c +++ b/src/output.c @@ -53,7 +53,8 @@ typedef enum T64, ZX81, GAMEBOY, - SNES + SNES, + LIBRARY } Format; static char output[4096] = "output"; @@ -69,6 +70,7 @@ static ValueTable format_table[] = {"zx81", ZX81}, {"gameboy", GAMEBOY}, {"snes", SNES}, + {"lib", LIBRARY}, {NULL} }; @@ -154,6 +156,10 @@ int OutputCode(void) return SNESOutput(output, output_bank, bank, count, error, sizeof error); + case LIBRARY: + return LibOutput(output, output_bank, bank, count, + error, sizeof error); + default: break; } diff --git a/src/output.h b/src/output.h index b894e88..2ae3ea5 100644 --- a/src/output.h +++ b/src/output.h @@ -37,6 +37,7 @@ #include "zx81out.h" #include "gbout.h" #include "snesout.h" +#include "libout.h" /* ---------------------------------------- INTERFACES */ diff --git a/src/test/lib1 b/src/test/lib1 new file mode 100644 index 0000000..8974fd5 --- /dev/null +++ b/src/test/lib1 @@ -0,0 +1,14 @@ + option output-file,lib1.lib + option output-format,lib + + org $8000 + +start_lib1: + ld hl,$1234 + call $bb5a +end_lib1: + +data1: + db "I'm data from lib1" + +var_lib1 equ $ffff diff --git a/src/test/lib2 b/src/test/lib2 new file mode 100644 index 0000000..a1c6224 --- /dev/null +++ b/src/test/lib2 @@ -0,0 +1,15 @@ + option output-file,lib2.lib + option output-format,lib + + org $8800 + +start_lib2: + ld hl,$4321 + call $0100 +end_lib2: + +data2: + db "I'm data from lib2" + +var_lib2 equ $7fff +var_lib1 equ $1234 diff --git a/src/test/link b/src/test/link new file mode 100644 index 0000000..ec09bd6 --- /dev/null +++ b/src/test/link @@ -0,0 +1,6 @@ + option output-file,"link.out" + option +list + option list-labels,all + + import "lib2.lib" + import "lib1.lib" -- cgit v1.2.3