aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIan C <ianc@noddybox.co.uk>2016-03-16 11:31:21 +0000
committerIan C <ianc@noddybox.co.uk>2016-03-16 11:31:21 +0000
commit4564c7906be89463b8f9637685e1785dd900f4b3 (patch)
treec80bcbcbca885485199ae77960570e973328c03a /src
parente23a3e98bf4afc6bc900a427c20c01feac476d1a (diff)
Updated banking to work with output.
Diffstat (limited to 'src')
-rw-r--r--src/casm.c23
-rw-r--r--src/output.c111
-rw-r--r--src/state.c68
-rw-r--r--src/state.h13
4 files changed, 144 insertions, 71 deletions
diff --git a/src/casm.c b/src/casm.c
index 9f685f8..1340eb7 100644
--- a/src/casm.c
+++ b/src/casm.c
@@ -139,6 +139,27 @@ static CommandStatus ORG(const char *label, int argc, char *argv[],
LabelSet(label, result, ANY_LABEL);
}
+ /* See if an optional bank was supplied
+ */
+ if (argc > 2)
+ {
+ CMD_EXPR(argv[2], result);
+ SetAddressBank(result);
+ }
+
+ return CMD_OK;
+}
+
+static CommandStatus BANK(const char *label, int argc, char *argv[],
+ int quoted[], char *err, size_t errsize)
+{
+ int result;
+
+ CMD_ARGC_CHECK(2);
+ CMD_EXPR(argv[1], result);
+
+ SetAddressBank(result);
+
return CMD_OK;
}
@@ -410,6 +431,8 @@ static struct
{".eq", EQU},
{"org", ORG},
{".org", ORG},
+ {"bank", BANK},
+ {".bank", BANK},
{"ds", DS},
{".ds", DS},
{"defs", DS},
diff --git a/src/output.c b/src/output.c
index ccad6af..13a7809 100644
--- a/src/output.c
+++ b/src/output.c
@@ -65,20 +65,43 @@ static ValueTable format_table[] =
/* ---------------------------------------- PRIVATE FUNCTIONS
*/
-static int OutputRawBinary(const Byte *mem, int min, int max)
+static int OutputRawBinary(MemoryBank **bank, int count)
{
- FILE *fp = fopen(output, "wb");
+ char buff[4096];
+ int f;
- if (!fp)
+ for(f = 0; f < count; f++)
{
- snprintf(error, sizeof error,"Failed to open %s\n", output);
- return FALSE;
+ FILE *fp;
+ const char *name;
+ const Byte *mem;
+ int min, max;
+
+ if (count == 1)
+ {
+ name = output;
+ }
+ else
+ {
+ snprintf(buff, sizeof buff, "%s.%u", output, bank[f]->number);
+ name = buff;
+ }
+
+ if (!(fp = fopen(name, "wb")))
+ {
+ snprintf(error, sizeof error,"Failed to open %s\n", name);
+ return FALSE;
+ }
+
+ mem = bank[f]->memory;
+ min = bank[f]->min_address_used;
+ max = bank[f]->max_address_used;
+
+ fwrite(mem + min, 1, max - min + 1, fp);
+
+ fclose(fp);
}
- fwrite(mem + min, 1, max - min + 1, fp);
-
- fclose(fp);
-
return TRUE;
}
@@ -110,11 +133,10 @@ static Byte TapString(FILE *fp, const char *p, int len, Byte chk)
}
-static int OutputSpectrumTap(const Byte *mem, int min, int max)
+static int OutputSpectrumTap(MemoryBank **bank, int count)
{
FILE *fp = fopen(output, "wb");
- Byte chk = 0;
- int len = max - min + 1;
+ int f;
if (!fp)
{
@@ -124,32 +146,44 @@ static int OutputSpectrumTap(const Byte *mem, int min, int max)
/* Output header
*/
- TapWord(fp, 19, 0);
+ for(f = 0; f < count; f++)
+ {
+ Byte chk = 0;
+ const Byte *mem;
+ int min, max, len;
- chk = TapByte(fp, 0, chk);
- chk = TapByte(fp, 3, chk);
- chk = TapString(fp, output, 10, chk);
- chk = TapWord(fp, len, chk);
- chk = TapWord(fp, min, chk);
- chk = TapWord(fp, 32768, chk);
+ mem = bank[f]->memory;
+ min = bank[f]->min_address_used;
+ max = bank[f]->max_address_used;
+ len = max - min + 1;
- TapByte(fp, chk, 0);
+ TapWord(fp, 19, 0);
- /* Output file data
- */
- TapWord(fp, len + 2, 0);
+ chk = TapByte(fp, 0, chk);
+ chk = TapByte(fp, 3, chk);
+ chk = TapString(fp, output, 10, chk);
+ chk = TapWord(fp, len, chk);
+ chk = TapWord(fp, min, chk);
+ chk = TapWord(fp, 32768, chk);
- chk = 0;
+ TapByte(fp, chk, 0);
- chk = TapByte(fp, 0xff, chk);
+ /* Output file data
+ */
+ TapWord(fp, len + 2, 0);
- while(min <= max)
- {
- chk = TapByte(fp, mem[min], chk);
- min++;
- }
+ chk = 0;
+
+ chk = TapByte(fp, 0xff, chk);
+
+ while(min <= max)
+ {
+ chk = TapByte(fp, mem[min], chk);
+ min++;
+ }
- TapByte(fp, chk, 0);
+ TapByte(fp, chk, 0);
+ }
fclose(fp);
@@ -193,30 +227,27 @@ CommandStatus OutputSetOption(int opt, int argc, char *argv[],
int OutputCode(void)
{
- const MemoryBank *bank = MemoryBanks();
+ MemoryBank **bank;
+ int count;
int min;
int max;
const Byte *mem;
+ bank = MemoryBanks(&count);
+
if (!bank)
{
fprintf(stderr, "Skipping output; no written memory to write\n");
return TRUE;
}
- /* TODO: Fix to pass banks proper
- */
- min = bank[0].min_address_used;
- max = bank[0].max_address_used;
- mem = bank[0].memory;
-
switch(format)
{
case Raw:
- return OutputRawBinary(mem, min, max);
+ return OutputRawBinary(bank, count);
case SpectrumTap:
- return OutputSpectrumTap(mem, min, max);
+ return OutputSpectrumTap(bank, count);
default:
break;
diff --git a/src/state.c b/src/state.c
index 32fa6b3..27225e5 100644
--- a/src/state.c
+++ b/src/state.c
@@ -38,40 +38,50 @@
static int pass = 1;
static int maxpass = 2;
static int pc = 0;
+static int num_banks = 0;
static unsigned currbank = 0;
static WordMode wmode = LSB_Word;
-static MemoryBank *bank;
+static MemoryBank **bank;
static MemoryBank *current;
/* ---------------------------------------- PRIVATE
*/
+static int SortBank(const void *a, const void *b)
+{
+ const MemoryBank *ma = a;
+ const MemoryBank *mb = b;
+
+ return (int)ma->number - (int)mb->number;
+}
+
+
static void RemoveBanks(void)
{
- while(bank)
- {
- MemoryBank *t = bank->next;
+ int f;
- free(bank);
- bank = t;
+ for(f = 0; f < num_banks; f++)
+ {
+ free(bank[f]);
}
- current = NULL;
+ free(bank);
+
currbank = 0;
+ bank = NULL;
+ current = NULL;
}
static MemoryBank *FindBank(unsigned n)
{
- MemoryBank *t = bank;
+ int f;
- while(t)
+ for(f = 0; f < num_banks; f++)
{
- if (t->number == n)
+ if (bank[f]->number == n)
{
- return t;
+ return bank[f];
}
-
- t = t->next;
}
return NULL;
@@ -79,28 +89,27 @@ static MemoryBank *FindBank(unsigned n)
static void ClearBankWriteMarkers(void)
{
- MemoryBank *t = bank;
+ int f;
- while(t)
+ for(f = 0; f < num_banks; f++)
{
- t->min_address_used = BANK_SIZE;
- t->max_address_used = -1;
- t = t->next;
+ bank[f]->min_address_used = BANK_SIZE;
+ bank[f]->max_address_used = -1;
}
}
static MemoryBank *AddBank(unsigned n)
{
- MemoryBank *t = Malloc(sizeof *t);
+ current = NULL;
+ num_banks++;
- t->min_address_used = BANK_SIZE;
- t->max_address_used = -1;
- t->number = n;
+ bank = Realloc(bank, (sizeof *bank) * num_banks);
+ bank[num_banks-1] = Malloc(sizeof **bank);
+ bank[num_banks-1]->number = n;
- t->next = bank;
- bank = t;
+ qsort(bank, num_banks, sizeof *bank, SortBank);
- return t;
+ return FindBank(n);
}
static MemoryBank *GetOrAddBank(unsigned n)
@@ -168,6 +177,7 @@ void SetNeededPasses(int n)
void SetAddressBank(unsigned b)
{
currbank = b;
+ current = NULL;
}
@@ -257,8 +267,9 @@ void PCWriteWordMode(int i, WordMode mode)
}
-const MemoryBank *MemoryBanks(void)
+MemoryBank **MemoryBanks(int *count)
{
+ *count = num_banks;
return bank;
}
@@ -267,6 +278,11 @@ Byte ReadByte(int addr)
{
Byte b = 0;
+ if (!current)
+ {
+ current = GetOrAddBank(currbank);
+ }
+
if (addr > -1 && addr < BANK_SIZE && current)
{
b = current->memory[addr];
diff --git a/src/state.h b/src/state.h
index e10463c..247124f 100644
--- a/src/state.h
+++ b/src/state.h
@@ -39,13 +39,12 @@ typedef enum
} WordMode;
-typedef struct mbnk
+typedef struct
{
unsigned number; /* The bank number, 0 .. n */
Byte memory[BANK_SIZE]; /* The memory in that bank */
int min_address_used; /* Will be BANK_SIZE if not used */
int max_address_used; /* Will be -1 if not used */
- struct mbnk *next; /* The next memory bank */
} MemoryBank;
/* ---------------------------------------- INTERFACES
@@ -119,10 +118,14 @@ void PCWriteWord(int i);
void PCWriteWordMode(int i, WordMode mode);
-/* Gets a list of the banks used. A NULL return means no memory was written
- to at all.
+/* Gets a list of the banks used as an array of pointers. A NULL return means
+ no memory was written to at all.
+
+ *count will be updated with the number of banks used, or zero if no memory
+ was written to. Note that banks may not be contiguously numbered, but will
+ be in ascending order.
*/
-const MemoryBank *MemoryBanks(void);
+MemoryBank **MemoryBanks(int *count);
/* Read a byte from the current bank.