// 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); }