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.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);
}
}

View File

@ -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];
}
}
}