aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIan C <ianc@noddybox.co.uk>2016-05-06 16:12:42 +0100
committerIan C <ianc@noddybox.co.uk>2016-05-06 16:12:42 +0100
commitd3713129e61a8953a61b8f15f7be6a3110197ed5 (patch)
tree2b6bc2e0ca728dc17bb3fbcba7632b6a929797e4 /src
parent0b3c0e2a2e347db8af3f29d4dc8c86797981bc85 (diff)
Added simple library format.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile13
-rw-r--r--src/casm.c12
-rw-r--r--src/label.c107
-rw-r--r--src/label.h10
-rw-r--r--src/libout.c185
-rw-r--r--src/libout.h68
-rw-r--r--src/output.c8
-rw-r--r--src/output.h1
-rw-r--r--src/test/lib114
-rw-r--r--src/test/lib215
-rw-r--r--src/test/link6
11 files changed, 433 insertions, 6 deletions
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 <http://www.gnu.org/licenses/>.
+
+ -------------------------------------------------------------------------
+
+ Various output type handlers.
+
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#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 <http://www.gnu.org/licenses/>.
+
+ -------------------------------------------------------------------------
+
+ 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"