"use strict"; // http://www.computerarcheology.com/Arcade/SpaceInvaders/Hardware.html var SPACEINV_PRESETS = [ ]; // TODO: global??? window.buildZ80({ applyContention: false }); var SpaceInvadersPlatform = function(mainElement) { var self = this; this.__proto__ = new BaseZ80Platform(); var cpu, ram, membus, iobus, rom; var video, audio, timer, pixels, displayPCs; var inputs = [0xe,0x8,0x0]; var bitshift_offset = 0; var bitshift_register = 0; var watchdog_counter; var cpuFrequency = 1996800; var cpuCyclesPerLine = Math.round(cpuFrequency/(60*224)); // TODO var INITIAL_WATCHDOG = 256; var PIXEL_ON = 0xffeeeeee; var PIXEL_OFF = 0xff000000; var KEYCODE_MAP = { 32:{i:1,b:4}, // space bar (P1) 37:{i:1,b:5}, // left arrow (P1) 39:{i:1,b:6}, // right arrow (P1) 0x53:{i:2,b:4}, // S (P2) 0x41:{i:2,b:5}, // A (P2) 0x44:{i:2,b:6}, // D (P2) 53:{i:1,b:0}, // 5 49:{i:1,b:2}, // 1 50:{i:1,b:1}, // 2 } this.getOpcodeMetadata = function() { return { opcode:0, mnenomic:'?', minCycles:0, maxCycles:0, insnlength:1 }; } this.getPresets = function() { return SPACEINV_PRESETS; } this.start = function() { ram = new RAM(0x2000); displayPCs = new Uint16Array(new ArrayBuffer(0x2000*2)); membus = { read: function(address) { if (address < 0x2000) { return rom ? rom[address] : 0; } else { address &= 0x1fff; return ram.mem[address]; } }, write: function(address, value) { //console.log("write", hex(address,4), hex(value,2)); if (address >= 0x2000) { address &= 0x1fff; value &= 0xff; ram.mem[address] = value; if (address >= 0x400) { // TODO: dirty flags var ofs = (address - 0x400)*8; for (var i=0; i<8; i++) pixels[ofs+i] = (value & (1<> (8-bitshift_offset)) & 0xff; } return 0; }, write: function(addr, val) { addr &= 0x7; val &= 0xff; //console.log('IO write', hex(addr,4), hex(val,2)); switch (addr) { case 2: bitshift_offset = val & 0x7; break; case 3: case 5: // TODO: sound break; case 4: bitshift_register = (bitshift_register >> 8) | (val << 8); break; case 6: watchdog_counter = INITIAL_WATCHDOG; break; } } }; cpu = window.Z80({ display: {}, memory: membus, ioBus: iobus }); video = new RasterVideo(mainElement,256,224,{rotate:-90}); audio = new SampleAudio(cpuFrequency); video.create(); $(video.canvas).click(function(e) { var x = Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width()); var y = Math.floor(e.offsetY * video.canvas.height / $(video.canvas).height()); var addr = (x>>3) + (y*32) + 0x400; console.log(x, y, hex(addr,4), "PC", hex(displayPCs[addr],4)); }); var idata = video.getFrameData(); video.setKeyboardEvents(function(key,code,flags) { var o = KEYCODE_MAP[key]; if (o) { if (flags & 1) { inputs[o.i] |= (1<