63 lines
2.2 KiB
JavaScript
63 lines
2.2 KiB
JavaScript
/**
|
|
* Z80 minimal "Hello" via BDOS — verifies the BDOS+OUT capture path
|
|
* works before we tackle the much heavier ZEXDOC ROM.
|
|
*/
|
|
import { describe, it, expect } from 'vitest';
|
|
import { BoardHarness } from '../src/BoardHarness.js';
|
|
import { chipWasmExists } from '../src/helpers.js';
|
|
|
|
const CHIP = 'z80';
|
|
const skip = !chipWasmExists(CHIP);
|
|
const CLOCK_NS = 250;
|
|
|
|
function fullPinMapZ80() {
|
|
const m = {
|
|
M1: 'M1', MREQ: 'MREQ', IORQ: 'IORQ', RD: 'RD', WR: 'WR', RFSH: 'RFSH',
|
|
HALT: 'HALT', WAIT: 'WAIT', INT: 'INT', NMI: 'NMI', RESET: 'RESET',
|
|
BUSREQ: 'BUSREQ', BUSACK: 'BUSACK', CLK: 'CLK',
|
|
VCC: 'VCC', GND: 'GND',
|
|
};
|
|
for (let i = 0; i < 16; i++) m[`A${i}`] = `A${i}`;
|
|
for (let i = 0; i < 8; i++) m[`D${i}`] = `D${i}`;
|
|
return m;
|
|
}
|
|
|
|
describe('Z80 BDOS-style output capture', () => {
|
|
it.skipIf(skip)('Z80 OUT (0x01) emits a byte detectable by the test harness', async () => {
|
|
// Minimal Z80 program: LD A, 0x48 ('H') ; OUT (0x01), A ; HLT.
|
|
// Expected: harness sees byte 0x48 written to port 0x01.
|
|
const program = new Uint8Array(0x10000);
|
|
program[0x0000] = 0x3E; program[0x0001] = 0x48; // LD A, 0x48
|
|
program[0x0002] = 0xD3; program[0x0003] = 0x01; // OUT (0x01), A
|
|
program[0x0004] = 0x76; // HALT
|
|
|
|
const board = new BoardHarness();
|
|
await board.addChip(CHIP, fullPinMapZ80());
|
|
const ram = board.installFakeRam(0x10000, {
|
|
addrPrefix: 'A', addrWidth: 16, dataPrefix: 'D', dataWidth: 8,
|
|
rd: 'RD', rdActiveLow: true, wr: 'WR', cs: 'MREQ', baseAddr: 0,
|
|
});
|
|
for (let i = 0; i < program.length; i++) ram.poke(i, program[i]);
|
|
|
|
const out = [];
|
|
board.watchNet('WR', (state) => {
|
|
if (state !== false) return;
|
|
if (board.getNet('IORQ') !== false) return;
|
|
const port = board.readBus('A', 8);
|
|
if (port === 0x01) out.push(board.readBus('D', 8));
|
|
});
|
|
|
|
board.setNet('WAIT', true);
|
|
board.setNet('INT', true);
|
|
board.setNet('NMI', true);
|
|
board.setNet('BUSREQ', true);
|
|
board.setNet('RESET', false);
|
|
board.advanceNanos(CLOCK_NS * 4);
|
|
board.setNet('RESET', true);
|
|
for (let i = 0; i < 200; i++) board.advanceNanos(CLOCK_NS);
|
|
|
|
expect(out).toEqual([0x48]);
|
|
board.dispose();
|
|
});
|
|
});
|