atari8: fixed VSCROL, pokey freq, performance

This commit is contained in:
Steven Hugg 2022-09-04 11:15:40 -05:00
parent 9f1c5377b3
commit 30342d2618
6 changed files with 73 additions and 45 deletions

View File

@ -202,7 +202,7 @@ export var POKEYDeviceChannel = function() {
this.setSampleRate = function (rate) {
sampleRate = rate;
baseDelta = FREQ_17_EXACT / rate / 1.2; // TODO?
baseDelta = FREQ_17_EXACT / rate;
};
function updateValues(addr) {

View File

@ -61,7 +61,7 @@ const linesPerFrame = 262;
const numVisibleLines = 258-16;
const colorClocksPerLine = 454; // 456?
const colorClocksPreDMA = 28;
const audioOversample = 4;
const audioOversample = 2;
const audioSampleRate = linesPerFrame*60*audioOversample;
// TIA chip

View File

@ -53,7 +53,7 @@ export class Atari800 extends BasicScanlineMachine {
firstVisibleClock = (44 - 6) * 2; // ... to 215 * 2
defaultROMSize = 0x8000;
overscan = true;
audioOversample = 4;
audioOversample = 2;
sampleRate = this.numTotalScanlines * 60 * this.audioOversample;
run_address = -1;

View File

@ -73,6 +73,7 @@ export class ANTIC {
ch: number = 0; // char read
linesleft: number = 0; // # of lines left in mode
yofs: number = 0; // yofs fine
isfirstline: boolean = false;
v: number = 0; // vertical scanline #
h: number = 0; // horizontal color clock
@ -81,7 +82,7 @@ export class ANTIC {
dmaidx: number = 0;
output: number = 0;
dramrefresh = false;
vscroll = 0;
in_vscroll = 0;
constructor(readfn, nmifn) {
this.read = readfn; // bus read function
@ -159,23 +160,24 @@ export class ANTIC {
//console.log('scanaddr', hex(this.scanaddr));
}
this.startaddr = this.scanaddr;
}
// horiz scroll
let effwidth = this.regs[DMACTL] & 3;
let hscroll = (this.dliop & 0x10) ? (this.regs[HSCROL] & 15) >> 1 : 0;
if ((this.dliop & 0x10) && effwidth < 3) effwidth++;
this.left = PF_LEFT[effwidth] + hscroll;
this.right = PF_RIGHT[effwidth] + hscroll;
// vertical scroll
let vscrol = this.regs[VSCROL] & 0xf;
if ((this.dliop & 0x20) ^ this.vscroll) {
if (this.vscroll) {
this.linesleft -= vscrol;
} else {
this.linesleft -= vscrol;
this.yofs += vscrol;
// horiz scroll
let effwidth = this.regs[DMACTL] & 3;
let hscroll = (this.dliop & 0x10) ? (this.regs[HSCROL] & 15) >> 1 : 0;
if ((this.dliop & 0x10) && effwidth < 3) effwidth++;
this.left = PF_LEFT[effwidth] + hscroll;
this.right = PF_RIGHT[effwidth] + hscroll;
// vertical scroll
let vscrol = this.regs[VSCROL] & 0xf;
if ((this.dliop & 0x20) ^ this.in_vscroll) {
if (this.in_vscroll) {
this.linesleft = vscrol+1; // exiting
} else {
this.linesleft -= vscrol; // entering
this.yofs += vscrol;
}
this.linesleft &= 0xf;
this.in_vscroll ^= 0x20;
}
this.vscroll ^= 0x20;
}
}
@ -183,6 +185,7 @@ export class ANTIC {
if (this.linesleft > 0) {
this.linesleft--;
this.yofs++;
this.isfirstline = false;
if (this.mode >= 8 && this.linesleft) {
this.scanaddr = this.startaddr; // reset line addr
}
@ -254,6 +257,7 @@ export class ANTIC {
this.mode = op & 0xf;
this.dliop = op;
this.yofs = 0;
this.isfirstline = true;
did_dma = true;
}
break;
@ -265,7 +269,7 @@ export class ANTIC {
break;
case 6:
case 7:
if (this.isPlayfieldDMAEnabled() && this.yofs == 0 && (this.jmp || this.lms)) {
if (this.isPlayfieldDMAEnabled() && this.isfirstline && (this.jmp || this.lms)) {
if (this.h == 6) this.dlarg_lo = this.nextInsn();
if (this.h == 7) this.dlarg_hi = this.nextInsn();
did_dma = true;
@ -273,7 +277,7 @@ export class ANTIC {
break;
case 8:
// TODO? is this at cycle 8?
if (this.yofs == 0) {
if (this.isfirstline) {
this.processDLIEntry();
}
if (this.dliop & 0x80) { // TODO: what if DLI disabled?
@ -299,7 +303,7 @@ export class ANTIC {
if (this.h == this.left) { this.dmaclock |= 1; this.dmaidx = 0; }
if (this.h == this.right) { this.dmaclock &= ~1; this.dmaidx++; }
if (this.dmaclock & 1) {
if (this.mode < 8 && this.yofs == 0) { // only read chars on 1st line
if (this.mode < 8 && this.isfirstline) { // only read chars on 1st line
if (candma) {
this.linebuf[this.dmaidx] = this.nextScreen(); // read char name
} else {

View File

@ -65,7 +65,6 @@ export class GTIA {
regs = new Uint8Array(0x20);
readregs = new Uint8Array(0x20);
shiftregs = new Uint32Array(8);
priortab = new Uint8Array(12);
count = 0;
an = 0;
@ -159,20 +158,37 @@ export class GTIA {
return 0x100; // black
}
anySpriteActive() {
return this.shiftregs[0] | this.shiftregs[1] | this.shiftregs[2]
| this.shiftregs[3] | this.shiftregs[4] | this.shiftregs[5]
| this.shiftregs[6] | this.shiftregs[7];
return this.shiftregs[0] || this.shiftregs[1] || this.shiftregs[2]
|| this.shiftregs[3] || this.shiftregs[4] || this.shiftregs[5]
|| this.shiftregs[6] || this.shiftregs[7];
}
processPlayerMissile() {
// no p/m gfx, no collisions in blank area, but shift and trigger anyway
if (this.an == 2 || !this.anySpriteActive()) {
for (let i = 0; i < 8; i++) {
this.shiftObject(i);
}
// no p/m gfx, just evaluate horiz. triggers
if (!this.anySpriteActive()) {
this.evalTrigger(0);
this.evalTrigger(1);
this.evalTrigger(2);
this.evalTrigger(3);
this.evalTrigger(4);
this.evalTrigger(5);
this.evalTrigger(6);
this.evalTrigger(7);
this.pmcol = -1;
return;
}
// no collisions in blank area, but shift and trigger anyway
if (this.an == 2) {
this.shiftObject(0);
this.shiftObject(1);
this.shiftObject(2);
this.shiftObject(3);
this.shiftObject(4);
this.shiftObject(5);
this.shiftObject(6);
this.shiftObject(7);
this.pmcol = -1;
return;
}
// TODO: multiple color player enable
// TODO: gtia, hi-res mode collisions
// compute gfx and collisions for players/missiles
let priobias = (this.regs[PRIOR] & 15) << 4; // TODO
@ -203,7 +219,9 @@ export class GTIA {
this.readregs[M0PF + i] |= 1 << pfset;
}
this.readregs[M0PL + i] |= ppmask;
let prio = PRIOR_TABLE[i + priobias];
let prio = (this.regs[PRIOR] & 0x10)
? PRIOR_TABLE[priobias + 15]
: PRIOR_TABLE[i + priobias];
if (prio < topprio) {
topobj = i + 4;
topprio = prio;
@ -221,9 +239,7 @@ export class GTIA {
shiftObject(i: number) {
let bit = (this.shiftregs[i] & 0x80000000) != 0;
this.shiftregs[i] <<= 1;
if (this.regs[HPOSP0 + i] + this.hbias == this.count) {
this.triggerObject(i);
}
this.evalTrigger(i);
return bit;
}
getObjectColor(i: number) {
@ -233,6 +249,11 @@ export class GTIA {
return this.regs[COLPM0 + (i & 3)];
}
}
evalTrigger(i: number) {
if (this.regs[HPOSP0 + i] + this.hbias == this.count) {
this.triggerObject(i);
}
}
triggerObject(i: number) {
let size, data;
if (!(this.pmDebugMask & (1<<i))) return;
@ -246,7 +267,7 @@ export class GTIA {
}
if (size & 1) data = expandBits(data); else data <<= 8;
if (size == 3) data = expandBits(data); else data <<= 16;
this.shiftregs[i] = data;
this.shiftregs[i] |= data;
}
clockPulse1(): void {

View File

@ -369,14 +369,17 @@ describe('Platform Replay', () => {
it('Should run atari5200', async () => {
await testPlatform('atari8-5200', 'acid5200.rom', 1200, (platform, frameno) => {
if (frameno == 1199) {
let s = '';
for (let i=0; i<40; i++) {
let c = platform.readAddress(0x722+i-40) & 0x7f;
if (c < 0x40) c += 0x20;
s += String.fromCharCode(c);
for (let j=0; j<1024; j+=40) {
var s = '';
for (let i=0; i<38; i++) {
let c = platform.readAddress(0x402+j+i) & 0x7f;
if (c < 0x40) c += 0x20;
s += String.fromCharCode(c);
}
s = s.trim();
if (s.startsWith("Passed:")) break;
}
s = s.trim();
assert.equal(s, "Passed: 13 Failed: 33 Skipped: 1");
assert.equal(s, "Passed: 14 Failed: 32 Skipped: 1");
}
});
});