import { MOS6502, MOS6502State } from "../common/cpu/MOS6502"; import { BasicHeadlessMachine } from "../common/devices"; import { padBytes, Keys, KeyFlags, newAddressDecoder } from "../common/emu"; // TODO import { hex, stringToByteArray, lzgmini } from "../common/util"; const KIM1_KEYMATRIX_NOSHIFT = [ Keys.VK_DELETE, Keys.VK_ENTER, Keys.VK_RIGHT, Keys.VK_F7, Keys.VK_F1, Keys.VK_F3, Keys.VK_F5, Keys.VK_DOWN, Keys.VK_3, Keys.VK_W, Keys.VK_A, Keys.VK_4, Keys.VK_Z, Keys.VK_S, Keys.VK_E, Keys.VK_SHIFT, Keys.VK_5, Keys.VK_R, Keys.VK_D, Keys.VK_6, Keys.VK_C, Keys.VK_F, Keys.VK_T, Keys.VK_X, Keys.VK_7, Keys.VK_Y, Keys.VK_G, Keys.VK_8, Keys.VK_B, Keys.VK_H, Keys.VK_U, Keys.VK_V, Keys.VK_9, Keys.VK_I, Keys.VK_J, Keys.VK_0, Keys.VK_M, Keys.VK_K, Keys.VK_O, Keys.VK_N, null/*Keys.VK_PLUS*/, Keys.VK_P, Keys.VK_L, Keys.VK_MINUS, Keys.VK_PERIOD, null/*Keys.VK_COLON*/, null/*Keys.VK_AT*/, Keys.VK_COMMA, null/*Keys.VK_POUND*/, null/*TIMES*/, Keys.VK_SEMICOLON, Keys.VK_HOME, Keys.VK_SHIFT/*right*/, Keys.VK_EQUALS, Keys.VK_TILDE, Keys.VK_SLASH, Keys.VK_1, Keys.VK_LEFT, Keys.VK_CONTROL, Keys.VK_2, Keys.VK_SPACE, Keys.VK_ALT, Keys.VK_Q, null/*STOP*/, ]; const KEYBOARD_ROW_0 = 0; class RRIOT_6530 { regs = new Uint8Array(16); ina : number = 0; inb : number = 0; read(a:number) : number { //console.log('read', hex(a), hex(this.regs[a])); return this.regs[a]; } write(a:number,v:number) { this.regs[a] = v; //console.log('write', hex(a), hex(v)); } input_a() { return this.ina & ~this.regs[1]; } input_b() { return this.inb & ~this.regs[1]; } output_a() { return (this.regs[0] ^ 0xff) | this.regs[1]; } output_b() { return (this.regs[2] ^ 0xff) | this.regs[3]; } } export class KIM1 extends BasicHeadlessMachine { cpuFrequency = 1000000; defaultROMSize = 0x1000; cpu = new MOS6502(); ram = new Uint8Array(0x1800); bios : Uint8Array; rriot1 : RRIOT_6530 = new RRIOT_6530(); rriot2 : RRIOT_6530 = new RRIOT_6530(); digits = []; constructor() { super(); this.bios = new lzgmini().decode(stringToByteArray(atob(KIM1_BIOS_LZG))); this.connectCPUMemoryBus(this); } read = newAddressDecoder([ [0x1700, 0x173f, 0x000f, (a) => { return this.readIO_1(a); }], [0x1740, 0x177f, 0x000f, (a) => { return this.readIO_2(a); }], [0x0000, 0x17ff, 0x1fff, (a) => { return this.ram[a]; }], [0x1800, 0x1fff, 0x07ff, (a) => { return this.bios[a]; }], ], {gmask:0x1fff}); write = newAddressDecoder([ [0x1700, 0x173f, 0x000f, (a,v) => { return this.writeIO_1(a,v); }], [0x1740, 0x177f, 0x000f, (a,v) => { return this.writeIO_2(a,v); }], [0x0000, 0x17ff, 0x1fff, (a,v) => { this.ram[a] = v; }], ], {gmask:0x1fff}); readConst(a:number) : number { return this.read(a); } readIO_1(a:number) : number { return this.rriot1.read(a); } writeIO_1(a:number, v:number) { this.rriot1.write(a,v); } readIO_2(a:number) : number { switch (a & 0xf) { case 0x0: let cols = 0; for (let i=0; i<8; i++) if ((this.rriot2.regs[0] & (1<> 3; let col = i & 7; // is column selected? if (flags & KeyFlags.KeyDown) { this.inputs[KEYBOARD_ROW_0 + row] |= (1<