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:
parent
5735135add
commit
9f1c5377b3
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user