aboutsummaryrefslogtreecommitdiff
path: root/src/t64out.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/t64out.c')
-rw-r--r--src/t64out.c102
1 files changed, 96 insertions, 6 deletions
diff --git a/src/t64out.c b/src/t64out.c
index 6509323..0fd308f 100644
--- a/src/t64out.c
+++ b/src/t64out.c
@@ -24,6 +24,7 @@
*/
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#include "global.h"
#include "codepage.h"
@@ -38,6 +39,31 @@
/* ---------------------------------------- PRIVATE FUNCTIONS
*/
+static int PokeB(Byte *mem, int addr, Byte b)
+{
+ mem[addr++] = b;
+ return (addr % 0x10000);
+}
+
+
+static int PokeW(Byte *mem, int addr, int w)
+{
+ addr = PokeB(mem, addr, w & 0xff);
+ return PokeB(mem, addr, (w & 0xff00) >> 8);
+}
+
+
+static int PokeS(Byte *mem, int addr, const char *str)
+{
+ while(*str)
+ {
+ addr = PokeB(mem, addr, CodeFromNative(CP_CBM, *str++));
+ }
+
+ return addr;
+}
+
+
static void WriteByte(FILE *fp, Byte b)
{
putc(b, fp);
@@ -106,11 +132,11 @@ int T64Output(const char *filename, const char *filename_bank,
/* Write directory header
*/
- WriteWord(fp, 0x1010);
+ WriteWord(fp, 0x200);
WriteWord(fp, count);
WriteWord(fp, count);
WriteWord(fp, NOT_USED);
- WriteString(fp, filename, 24, ' ', CP_CBM);
+ WriteString(fp, filename, 24, ' ', CP_ASCII);
/* Offset to tape data
*/
@@ -120,16 +146,53 @@ int T64Output(const char *filename, const char *filename_bank,
*/
for(f = 0; f < count; f++)
{
+ int min, max, len;
+
+ min = bank[f]->min_address_used;
+ max = bank[f]->max_address_used;
+
+ /* If this is the first bank, we're going to prepend some BASIC
+ */
+ if (f == 0)
+ {
+ if (min < 0x810)
+ {
+ snprintf(error, error_size, "First bank starts below a safe "
+ "area to add BASIC loader");
+
+ return FALSE;
+ }
+
+ min = 0x801; /* Start of BASIC */
+ }
+
+ len = max - min + 1;
+
WriteByte(fp, 1);
WriteByte(fp, 0x82);
- WriteWord(fp, bank[f]->min_address_used);
- WriteWord(fp, bank[f]->max_address_used);
+ WriteWord(fp, min);
+ WriteWord(fp, max + 1);
WriteWord(fp, NOT_USED);
WriteLong(fp, offset);
WriteWord(fp, NOT_USED);
WriteWord(fp, NOT_USED);
- offset += bank[f]->max_address_used - bank[f]->min_address_used + 1;
+ if (count == 1)
+ {
+ WriteString(fp, filename, 16, ' ', CP_CBM);
+ }
+ else
+ {
+ char fn[16];
+
+ snprintf(fn, sizeof fn, filename_bank, bank[f]->number);
+ WriteString(fp, fn, 16, ' ', CP_CBM);
+ }
+
+ /* +2 is to include the 2-byte PRG header
+ offset += len + 2;
+ */
+ offset += len;
}
/* Write actual contents
@@ -140,11 +203,38 @@ int T64Output(const char *filename, const char *filename_bank,
int min, max, len;
mem = bank[f]->memory;
+
min = bank[f]->min_address_used;
max = bank[f]->max_address_used;
+
+ /* If this is the first bank, we're going to prepend some BASIC.
+ Note that output drivers are allowed to manipulate memory directly.
+ */
+ if (f == 0)
+ {
+ char sys[16];
+ int a = 0x803;
+ int next;
+
+ snprintf(sys, sizeof sys, "%u", min);
+
+ a = PokeW(mem, a, 10);
+ a = PokeB(mem, a, 0x9e);
+ a = PokeS(mem, a, sys);
+ a = PokeB(mem, a, 0x00);
+
+ next = a;
+
+ a = PokeW(mem, a, 0x00);
+
+ PokeW(mem, 0x801, next);
+
+ min = 0x801;
+ }
+
len = max - min + 1;
- fwrite(mem, len, 1, fp);
+ fwrite(mem + min, len, 1, fp);
}
fclose(fp);