#!/usr/bin/env python2 # tape emulation from symbols import * import loaders import loaders.t64 import loaders.prg tape_loader = loaders.t64.Loader() # public. set this from the main emu GUI. T_EOF = 0x40 WRITE_LEADER = 0x0A WRITE_BLOCK = 0x08 READ_BLOCK = 0x0E # SCAN_KEY = 0x0C err = 0 def get_tape_buffer(memory): return(memory.read_memory(0xB2, 1) | (memory.read_memory(0xB3, 1) << 8)) def get_file_name_length(memory): return(memory.read_memory(0xB7, 1)) def get_file_name_address(memory): return(memory.read_memory(0xBB, 1) | (memory.read_memory(0xBC) << 8)) def get_stop_location(memory): return(memory.read_memory(0xAE, 1) | (memory.read_memory(0xAF) << 8)) #def get_status(memory): # return(memory.read_memory(0x90, 1)) def set_status(memory, value): return(memory.write_memory(0x90, value, 1)) #def get_VERCKK(memory): # return(memory.read_memory(0x93, 1)) def set_VERCKK(memory, value): return(memory.write_memory(0x93, value, 1)) def set_IRQTMP(memory, value): # if = [$315] then end IO return(memory.write_memory(0x2A0, value, 1)) def get_start_location(memory): return(memory.read_memory(0xC1, 1) | (memory.read_memory(0xC2) << 8)) OFFSET_TYPE = 0 OFFSET_NAME = 5 OFFSET_START_ADDR = 1 OFFSET_STOP_ADDR = 3 def setup_tape_header(type, file_name, start_addr, stop_addr, memory): buffer_addr = get_tape_buffer(memory) file_name = (file_name + (b" "*16))[:16] for i in range(16): memory.write_memory(buffer_addr + OFFSET_NAME + i, ord(file_name[i]), 1) memory.write_memory(buffer_addr + OFFSET_TYPE, type, 1) memory.write_memory(buffer_addr + OFFSET_START_ADDR, start_addr, 2) memory.write_memory(buffer_addr + OFFSET_STOP_ADDR, stop_addr, 2) def get_file_name(memory): file_name_length = 0 # ShedSkin file_name_addr = 0 # ShedSkin file_name_addr = get_file_name_address(memory) file_name_length = get_file_name_length(memory) # TODO replace invalid (not in "0-9A-Za-z._") by "." return b"".join([chr(memory.read_memory(file_name_addr + i, 1)) for i in range(min(16, file_name_length))]) def find_header(CPU, memory): # read a block from tape """ trap 0xF72F, originally was [0x20, 0x41, 0xF8]. """ file_name = get_file_name(memory) start_addr = 0 # ShedSkin stop_addr = 0 # ShedSkin type_ = 3 # 1 relocatable program; 2 SEQ data block; 3 non-relocatable program; 4 SEQ file header; 5 End-of-tape file_name = "" # ShedSkin #type_, file_name, start_addr, stop_addr header = tape_loader.load_header(file_name) if header is None: print("umm... no file on tape?") set_status(memory, 0x30) # Checksum error and pass2 error. err = -1 else: setup_tape_header(type_, header.file_name, header.start_addr, header.end_addr, memory) set_status(memory, 0) err = 0 set_VERCKK(memory, 0) # FIXME do we have to set this? set_IRQTMP(memory, 0) if err == 0: CPU.CLC() else: CPU.SEC() CPU.clear_Z() # FIXME CPU.set_PC(0xF732) def write_header(CPU, memory): """ trap 0xF7BE, originally was [0x20, 0x6B, 0xF8]. """ CPU.set_PC(0xF7C1) return def transfer(CPU, memory): """ trap 0xF8A1, originally was [0x20, 0xBD, 0xFC]. """ err = 0 st = 0 X = CPU.read_register(S_X) if X == WRITE_LEADER: pass elif X == WRITE_BLOCK: pass elif X == READ_BLOCK: start = get_start_location(memory) end = get_stop_location(memory) size = end - start # !!!!! file_name = get_file_name(memory) data = "" # ShedSkin data = tape_loader.load_data(file_name) for i in range(size): memory.write_memory(start + i, ord(data[i]), 1) st |= T_EOF else: err = -1 set_IRQTMP(memory, 0) set_status(memory, st) # get_status(memory) | st) if err == 0: CPU.CLC() else: CPU.SEC() CPU.set_PC(0xFC93) def get_hooks(): return [0xF8A1, 0xF7BE, 0xF72F] """{0xF8A1: transfer, 0xF7BE: write_header, 0xF72F: find_header}.keys()""" def call_hook(CPU, memory, PC): #PC = CPU.read_register(S_PC) if PC == 0xF8A1: return(transfer(CPU, memory)) elif PC == 0xF7BE: return(write_header(CPU, memory)) elif PC == 0xF72F: return(find_header(CPU, memory)) else: pass def set_image_name(name, format): global tape_loader if format == "PRG": tape_loader = loaders.prg.Loader().parse(open(name, "rb"), name) else: tape_loader = loaders.t64.Loader().parse(open(name, "rb"), name)