atari8: fixes, xex load from cc65
This commit is contained in:
parent
5735135add
commit
9f1c5377b3
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue