From 30342d2618c20e5731a6204572cdd57cc84098ee Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Sun, 4 Sep 2022 11:15:40 -0500 Subject: [PATCH] atari8: fixed VSCROL, pokey freq, performance --- src/common/audio.ts | 2 +- src/machine/atari7800.ts | 2 +- src/machine/atari8.ts | 2 +- src/machine/chips/antic.ts | 44 +++++++++++++++++--------------- src/machine/chips/gtia.ts | 51 +++++++++++++++++++++++++++----------- test/cli/testplatforms.js | 17 +++++++------ 6 files changed, 73 insertions(+), 45 deletions(-) diff --git a/src/common/audio.ts b/src/common/audio.ts index 2cc08be0..977f8ef9 100644 --- a/src/common/audio.ts +++ b/src/common/audio.ts @@ -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) { diff --git a/src/machine/atari7800.ts b/src/machine/atari7800.ts index 6cb1b2fd..6bb6be94 100644 --- a/src/machine/atari7800.ts +++ b/src/machine/atari7800.ts @@ -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 diff --git a/src/machine/atari8.ts b/src/machine/atari8.ts index f8f0026c..0869e893 100644 --- a/src/machine/atari8.ts +++ b/src/machine/atari8.ts @@ -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; diff --git a/src/machine/chips/antic.ts b/src/machine/chips/antic.ts index 1a8adb16..554fff79 100644 --- a/src/machine/chips/antic.ts +++ b/src/machine/chips/antic.ts @@ -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 { diff --git a/src/machine/chips/gtia.ts b/src/machine/chips/gtia.ts index 5bb52d58..af007f5c 100644 --- a/src/machine/chips/gtia.ts +++ b/src/machine/chips/gtia.ts @@ -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< { 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"); } }); });