diff --git a/src/emu.ts b/src/emu.ts index 3b7a45da..09bbcba3 100644 --- a/src/emu.ts +++ b/src/emu.ts @@ -50,7 +50,7 @@ export enum KeyFlags { KeyPress = 128, } -function _setKeyboardEvents(canvas:HTMLElement, callback:KeyboardCallback) { +export function _setKeyboardEvents(canvas:HTMLElement, callback:KeyboardCallback) { canvas.onkeydown = (e) => { callback(e.which, 0, KeyFlags.KeyDown|_metakeyflags(e)); }; diff --git a/src/platform/kim1.ts b/src/platform/kim1.ts new file mode 100644 index 00000000..9c88ef3c --- /dev/null +++ b/src/platform/kim1.ts @@ -0,0 +1,246 @@ +"use strict"; + +import { Platform, Base6502Platform, BaseMAMEPlatform, getOpcodeMetadata_6502, getToolForFilename_6502 } from "../baseplatform"; +import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap, dumpRAM, getMousePos, EmuHalt, KeyFlags, _setKeyboardEvents } from "../emu"; +import { hex, lzgmini, stringToByteArray, lpad, rpad, rgb2bgr } from "../util"; + +declare var jt; // for 6502 + +// http://www.6502.org/trainers/buildkim/kim.htm +// http://users.telenet.be/kim1-6502/ +// http://retro.hansotten.nl/uploads/6502docs/usrman.htm#F312 +// http://www.zimmers.net/anonftp/pub/cbm/documents/chipdata/6530.pdf +// http://archive.6502.org/datasheets/mos_6530_rriot_preliminary_aug_1975.pdf +// https://github.com/mamedev/mame/blob/master/src/mame/drivers/kim1.cpp +// https://github.com/mamedev/mame/blob/c5426f2fabc220be2efc2790ffca57bde108cbf2/src/devices/machine/mos6530.cpp + +var KIM1_PRESETS = [ + {id:'hello.dasm', name:'Hello World (ASM)'}, +]; + +const KIM1_KEYCODE_MAP = makeKeycodeMap([ +]); + +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; + +const cpuFrequency = 1000000; +const romLength = 0x1000; + +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]; } +} + +class KIM1Platform extends Base6502Platform implements Platform { + + mainElement : HTMLElement; + cpu; + ram : Uint8Array; + bios : Uint8Array; + bus; + timer : AnimationTimer; + inputs = new Uint8Array(16); + rriot1 : RRIOT_6530 = new RRIOT_6530(); + rriot2 : RRIOT_6530 = new RRIOT_6530(); + digits = []; + + constructor(mainElement : HTMLElement) { + super(); + this.mainElement = mainElement; + } + + getPresets() { + return KIM1_PRESETS; + } + + getKeyboardMap() { return null; /* TODO: KIM1_KEYCODE_MAP;*/ } + + getKeyboardFunction() { + return (key,code,flags) => { + //console.log(key,code,flags); + var keymap = KIM1_KEYMATRIX_NOSHIFT; + for (var i=0; i> 3; + let col = i & 7; + // is column selected? + if (flags & KeyFlags.KeyDown) { + this.inputs[KEYBOARD_ROW_0 + row] |= (1< { 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}), + }; + this.cpu.connectBus(this.bus); + this.timer = new AnimationTimer(60, this.nextFrame.bind(this)); + // create digits display + let div = $('
').appendTo(this.mainElement); + div[0].tabIndex = -1; // Make it focusable + for (let i=0; i<6; i++) { + let id = "kim_digit_" + i; + let el = $('0').attr('id',id).appendTo(div); + this.digits.push(el); + } + _setKeyboardEvents(div[0], this.getKeyboardFunction()); + } + + advance(novideo : boolean) { + var debugCond = this.getDebugCallback(); + for (var i=0; i