diff --git a/src/machine/atari8.ts b/src/machine/atari8.ts index 8d52ce91..f8f0026c 100644 --- a/src/machine/atari8.ts +++ b/src/machine/atari8.ts @@ -26,7 +26,7 @@ var ATARI8_KEYCODE_MAP = makeKeycodeMap([ [Keys.DOWN, 0, 0x2], [Keys.LEFT, 0, 0x4], [Keys.RIGHT, 0, 0x8], - [{c: 16, n: "Shift", plyr:0, button:0}, 2, 0x1], + [{ c: 16, n: "Shift", plyr: 0, button: 0 }, 2, 0x1], /* [Keys.P2_UP, 0, 0x10], [Keys.P2_DOWN, 0, 0x20], @@ -55,6 +55,7 @@ export class Atari800 extends BasicScanlineMachine { overscan = true; audioOversample = 4; sampleRate = this.numTotalScanlines * 60 * this.audioOversample; + run_address = -1; cpu: MOS6502; ram: Uint8Array; @@ -73,6 +74,7 @@ export class Atari800 extends BasicScanlineMachine { cart_a0 = false; xexdata = null; keyboard_active = true; + d500 = new Uint8Array(0x100); // TODO: save/load vars constructor() { @@ -90,11 +92,10 @@ export class Atari800 extends BasicScanlineMachine { this.audioadapter = new TssChannelAdapter(this.audio_pokey.pokey1, this.audioOversample, this.sampleRate); this.handler = newKeyboardHandler( this.inputs, ATARI8_KEYCODE_MAP, this.getKeyboardFunction(), true); - } + } newBus() { return { - // TODO: https://github.com/dmlloyd/atari800/blob/master/DOC/cart.txt read: newAddressDecoder([ [0x0000, 0x7fff, 0xffff, (a) => { return this.ram[a]; }], [0x8000, 0x9fff, 0xffff, (a) => { return this.cart_80 ? this.rom[a - 0x8000] : this.ram[a]; }], @@ -103,6 +104,7 @@ export class Atari800 extends BasicScanlineMachine { [0xd200, 0xd2ff, 0xf, (a) => { return this.readPokey(a); }], [0xd300, 0xd3ff, 0xf, (a) => { return this.readPIA(a); }], [0xd400, 0xd4ff, 0xf, (a) => { return this.antic.readReg(a); }], + [0xd500, 0xd5ff, 0xff, (a) => { return this.d500[a]; }], [0xd800, 0xffff, 0xffff, (a) => { return this.bios[a - 0xd800]; }], ]), write: newAddressDecoder([ @@ -125,7 +127,7 @@ export class Atari800 extends BasicScanlineMachine { this.antic.reset(); this.gtia.reset(); this.keycode = 0; - if (this.xexdata) this.cart_a0 = true; // TODO + //if (this.xexdata) this.cart_a0 = true; // TODO } read(a) { @@ -140,7 +142,7 @@ export class Atari800 extends BasicScanlineMachine { return v; } readConst(a) { - return a < 0xd000 || a >= 0xe000 ? this.bus.read(a) : 0xff; + return a < 0xd000 || a >= 0xd500 ? this.bus.read(a) : 0xff; } write(a, v) { this.bus.write(a, v); @@ -242,6 +244,8 @@ export class Atari800 extends BasicScanlineMachine { this.irq_pokey.loadState(state.pokey); this.lastdmabyte = state.lastdmabyte; this.keycode = state.keycode; + this.cart_80 = state.cart_80; + this.cart_a0 = state.cart_a0; } saveState() { return { @@ -253,6 +257,8 @@ export class Atari800 extends BasicScanlineMachine { inputs: this.inputs.slice(0), lastdmabyte: this.lastdmabyte, keycode: this.keycode, + cart_80: this.cart_80, + cart_a0: this.cart_a0, }; } loadControlsState(state) { @@ -283,7 +289,7 @@ export class Atari800 extends BasicScanlineMachine { return (o, key, code, flags) => { if (!this.keyboard_active) return false; if (flags & (KeyFlags.KeyDown | KeyFlags.KeyUp)) { - console.log(o, key, code, flags, hex(this.keycode)); + //console.log(o, key, code, flags, hex(this.keycode)); var keymap = ATARI8_KEYMATRIX_INTL_NOSHIFT; if (key == Keys.VK_F9.c) { this.irq_pokey.generateIRQ(0x80); // break IRQ @@ -314,19 +320,16 @@ export class Atari800 extends BasicScanlineMachine { } loadROM(rom: Uint8Array, title: string) { - // XEX file? - if (title && title.toLowerCase().endsWith('.xex') && rom[0] == 0xff && rom[1] == 0xff) { - // TODO: we fake a cartridge + if ((rom[0] == 0xff && rom[1] == 0xff) && !title?.endsWith('.rom')) { + // XEX file, chill out and wait for BIOS hook this.xexdata = rom; - let cart = new Uint8Array(0x1000); - cart.set([0x00, 0x01, 0x00, 0x04, 0x00, 0x01], 0xffa); - this.loadCartridge(cart); } else { this.loadCartridge(rom); } } loadCartridge(rom: Uint8Array) { + // TODO: https://github.com/dmlloyd/atari800/blob/master/DOC/cart.txt // strip off header if (rom[0] == 0x43 && rom[1] == 0x41 && rom[2] == 0x52 && rom[3] == 0x54) { rom = rom.slice(16); @@ -339,61 +342,67 @@ export class Atari800 extends BasicScanlineMachine { for (let i = 0; i <= rom2.length - rom.length; i += rom.length) { rom2.set(rom, i); } + this.run_address = rom2[0x7ffe] + rom2[0x7fff]*256; this.cart_a0 = true; // TODO this.cart_80 = rom.length == 0x4000; super.loadROM(rom2); } - writeMapper(addr:number, value:number) { + writeMapper(addr: number, value: number) { + // TODO if (addr == 0xff) { if (value == 0x80) this.cart_80 = false; if (value == 0xa0) this.cart_a0 = false; } } - // TODO loadXEX(rom: Uint8Array) { let ofs = 2; - let cart = this.ram; - let cartofs = 0x100; // stub routine in stack page + let stub = this.d500; + let stubofs = 0; // stub routine + var runaddr = -1; + // load segments into RAM while (ofs < rom.length) { - let start = rom[ofs+0] + rom[ofs+1] * 256; - let end = rom[ofs+2] + rom[ofs+3] * 256; - console.log('XEX', ofs, hex(start), hex(end)); + let start = rom[ofs + 0] + rom[ofs + 1] * 256; + let end = rom[ofs + 2] + rom[ofs + 3] * 256; + console.log('XEX', hex(ofs), hex(start), hex(end)); ofs += 4; - for (let i=start; i<=end; i++) { + for (let i = start; i <= end; i++) { this.ram[i] = rom[ofs++]; } - var runaddr = this.ram[0x2e0] + this.ram[0x2e1]*256; - var initaddr = this.ram[0x2e2] + this.ram[0x2e3]*256; - console.log('XEX run', hex(runaddr), 'init', hex(initaddr)); - if (initaddr) { - cart[cartofs++] = 0x20; - cart[cartofs++] = initaddr & 0xff; - cart[cartofs++] = initaddr >> 8; + if (start == 0x2e0 && end == 0x2e1) { + runaddr = this.ram[0x2e0] + this.ram[0x2e1] * 256; + console.log('XEX run', hex(runaddr)); + } + if (start == 0x2e2 && end == 0x2e3) { + var initaddr = this.ram[0x2e2] + this.ram[0x2e3] * 256; + console.log('XEX init', hex(initaddr)); + stub[stubofs++] = 0x20; + stub[stubofs++] = initaddr & 0xff; + stub[stubofs++] = initaddr >> 8; } if (ofs > rom.length) throw new Error("Bad .XEX file format"); } - if (runaddr) { - cart[cartofs++] = 0xa9; // lda #$a0 - cart[cartofs++] = 0xa0; - cart[cartofs++] = 0x8d; // sta $d5ff (disable cart) - cart[cartofs++] = 0xff; - cart[cartofs++] = 0xd5; - cart[cartofs++] = 0x4c; // jmp runaddr - cart[cartofs++] = runaddr & 0xff; - cart[cartofs++] = runaddr >> 8; + if (runaddr >= 0) { + // build stub routine at 0xd500 + stub[stubofs++] = 0xa9; // lda #$a0 + stub[stubofs++] = 0xa0; + stub[stubofs++] = 0x8d; // sta $d5ff (disable cart) + stub[stubofs++] = 0xff; + stub[stubofs++] = 0xd5; + stub[stubofs++] = 0x4c; // jmp runaddr + stub[stubofs++] = runaddr & 0xff; + stub[stubofs++] = runaddr >> 8; + // set DOSVEC to 0xd500 + this.ram[0xa] = 0x00; + this.ram[0xb] = 0xd5; + this.run_address = 0xd500; } -} + } initCartA() { - //console.log('init', hex(this.cpu.getPC())); - // disable cartridges and load XEX - if (this.cpu.getPC() == 0xf17f) { - if (this.xexdata) { - this.loadXEX(this.xexdata); - } - //this.cart_80 = this.cart_a0 = false; + if (this.cpu.getPC() == 0xf17f && this.xexdata) { + this.loadXEX(this.xexdata); } } diff --git a/src/machine/chips/antic.ts b/src/machine/chips/antic.ts index ab264676..1a8adb16 100644 --- a/src/machine/chips/antic.ts +++ b/src/machine/chips/antic.ts @@ -434,12 +434,20 @@ export class ANTIC { return v ? 4 : 0; } case 4: case 5: + { + let v = (this.pfbyte >> 6) & 3; + this.pfbyte <<= 2; + if (this.ch & 0x80) + return [0, 4, 5, 7][v]; + else + return [0, 4, 5, 6][v]; + } case 8: case 10: case 13: case 14: { let v = (this.pfbyte >> 6) & 3; this.pfbyte <<= 2; - return [0, 4, 5, 6][v]; // TODO: 5th color + return [0, 4, 5, 6][v]; } } }