1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-06-08 08:33:32 +00:00

atari8: fixes, xex load from cc65

This commit is contained in:
Steven Hugg 2022-09-03 15:48:07 -05:00
parent 5735135add
commit 9f1c5377b3
2 changed files with 62 additions and 45 deletions

View File

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

View File

@ -434,12 +434,20 @@ export class ANTIC {
return v ? 4 : 0; return v ? 4 : 0;
} }
case 4: case 5: 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 8: case 10:
case 13: case 14: case 13: case 14:
{ {
let v = (this.pfbyte >> 6) & 3; let v = (this.pfbyte >> 6) & 3;
this.pfbyte <<= 2; this.pfbyte <<= 2;
return [0, 4, 5, 6][v]; // TODO: 5th color return [0, 4, 5, 6][v];
} }
} }
} }