aboutsummaryrefslogtreecommitdiff
path: root/c64/tape.c
diff options
context:
space:
mode:
Diffstat (limited to 'c64/tape.c')
-rw-r--r--c64/tape.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/c64/tape.c b/c64/tape.c
new file mode 100644
index 0000000..725bf2f
--- /dev/null
+++ b/c64/tape.c
@@ -0,0 +1,172 @@
+// tape.c
+//
+// 20060803 Markku Alén
+
+#include "tape.h"
+#include "cpu.h"
+#include "mem.h"
+
+#include "prg_file.h"
+
+#define STATUS (ram[0x90])
+#define VERCKK (ram[0x93])
+
+#define EAL (ram[0xae] | (ram[0xaf] << 8))
+
+#define TBUFFR (ram[0xb2] | (ram[0xb3] << 8))
+
+#define FNLEN (ram[0xb7])
+#define FNADR (ram[0xbb] | (ram[0xbc] << 8))
+
+#define STAL (ram[0xc1] | (ram[0xc2] << 8))
+
+#define IRQTMP (ram[0x2a0])
+
+#define OFFSET_TYPE 0
+#define OFFSET_START_ADDR 1
+#define OFFSET_END_ADDR 3
+#define OFFSET_NAME 5
+
+#define TYPE_PRG 1 /* Binary Program */
+#define TYPE_BAS 3 /* Relocatable Program */
+#define TYPE_DATA 4 /* Data Record */
+#define TYPE_EOF 5 /* End of Tape marker */
+
+#define FIND_RET 0xF732
+#define WRITE_RET 0xF7C1
+#define TRANSFER_RET 0xFC93
+
+#define WRITE_LEADER 0x0a
+#define WRITE_BLOCK 0x08
+#define READ_BLOCK 0x0e
+
+#define EOF 0x40
+
+static void copy_to_ram(int addr, int len, const void *buf)
+{
+ while(len-- > 0)
+ ram[addr + len] = ((char *)buf)[len];
+}
+
+static void setup_tape_hdr(int type, const char *filename, int start_addr, int stop_addr)
+{
+ int i;
+ char c, *p;
+ p = &ram[TBUFFR];
+ for(i = 0;i < 16;i++)
+ {
+ c = *filename;
+ if(c != '\0')
+ filename++;
+ p[OFFSET_NAME + i] = c;
+ }
+ p[OFFSET_TYPE] = type;
+ p[OFFSET_START_ADDR + 0] = start_addr % 256;
+ p[OFFSET_START_ADDR + 1] = start_addr / 256;
+ p[OFFSET_END_ADDR + 0] = stop_addr % 256;
+ p[OFFSET_END_ADDR + 1] = stop_addr / 256;
+}
+
+static char filename[15 + 1];
+
+static void get_filename(void)
+{
+ int i;
+ char c, *p;
+ p = &ram[FNADR];
+ for(i = 0;i < (sizeof(filename) - 1);i++)
+ {
+ c = *(p++);
+ if(c < '0' || c > '9')
+ {
+ if(c < 'A' || c > 'Z')
+ {
+ if(c < 'a' || c > 'z')
+ {
+ if(c != '.' && c != '_')
+ c = '.';
+ }
+ }
+ }
+ filename[i] = c;
+ }
+ if(i > FNLEN)
+ i = FNLEN;
+ filename[i] = '\0';
+}
+
+static int find_header(void)
+{
+ int err;
+ err = 0;
+ get_filename();
+ if(prg_load(filename) != 0)
+ err = -1;
+ if(err == 0)
+ setup_tape_hdr(TYPE_BAS, filename, prg_addr, prg_addr + prg_len);
+ STATUS = 0x00;
+ VERCKK = 0x00;
+ IRQTMP = 0x00;
+ set_c_flag(err != 0);
+ set_z_flag(0);
+ set_pc(FIND_RET);
+ return 0;
+}
+
+static int write_header(void)
+{
+ int i;
+ i=0;
+}
+
+static int tape_transfer(void)
+{
+ int i;
+ int err;
+ int start, end, len;
+ int st;
+ err = 0;
+ start = STAL;
+ end = EAL;
+ len = end - start;
+ st = 0x00;
+ switch(get_x())
+ {
+ case WRITE_LEADER:
+ break;
+ case WRITE_BLOCK:
+// if (fwrite(ram + start, len, 1, tape->FileDs) == 1) {
+// st |= 0x40; /* EOF */
+// }
+// else {
+// st |= 0xB4; /* All possible errors... */
+//
+// fprintf(stderr, "Error: Tape write failed.\n");
+// }
+// break;
+ i=0;
+ case READ_BLOCK:
+ copy_to_ram(start, len, prg_data);
+ st |= EOF;
+ break;
+ default:
+ err = -1;
+ }
+ IRQTMP = 0x00;
+ STATUS |= st;
+ set_c_flag(err != 0);
+ set_pc(TRANSFER_RET);
+ return 0;
+}
+
+static trap_t traps[] =
+{
+ TRAP_INIT(0xF72F, 0x20, 0x41, 0xF8, &find_header),
+ TRAP_INIT(0xF7BE, 0x20, 0x6B, 0xF8, &write_header),
+ TRAP_INIT(0xF8A1, 0x20, 0xBD, 0xFC, &tape_transfer),
+};
+
+void init_tape(void)
+{
+ install_traps(sizeof(traps) / sizeof(traps[0]), traps, &poke, &peek);
+}