Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 1 addition & 21 deletions src/bus.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { hexbyte, hexword } from "./utils";

class Bus {
export class Bus {
#ram = new Uint8Array(0x2000);
#cartridgeRam = new Uint8Array(0x8000);
#romBanks = [];
Expand Down Expand Up @@ -248,23 +248,3 @@ class Bus {
}
}
}

export const bus = new Bus();

// Convenience re-exports so callers that import bare functions (z80.js,
// z80_ops.js, z80_dis.js, debug.js) only need to change their import path.
export function readbyte(a) {
return bus.readbyte(a);
}
export function writebyte(a, v) {
bus.writebyte(a, v);
}
export function readport(a) {
return bus.readport(a);
}
export function writeport(a, v) {
bus.writeport(a, v);
}
export function virtualAddress(a) {
return bus.virtualAddress(a);
}
10 changes: 3 additions & 7 deletions src/debug.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import { hexbyte, hexword } from "./utils";
import { bus, readbyte, virtualAddress } from "./bus";
import { bus, z80, vdp, z80_do_opcodes, readbyte, virtualAddress } from "./sms";
import { clearBreakpoint, audio_enable, cycleCallback, start } from "./miracle";
import { z80 } from "./z80/z80.js";
import { z80_do_opcodes } from "./z80/z80_ops";
import { disassemble } from "./z80/z80_dis";
import { vdp } from "./vdp";
import { setEventNextEvent, setTstates } from "./z80/z80_ops";

let debugSerial = 0;
let annotations = null;
Expand Down Expand Up @@ -189,8 +185,8 @@ export function stepUntil(f) {
audio_enable(true);
clearBreakpoint();
for (let i = 0; i < 65536; i++) {
setTstates(0);
setEventNextEvent(1);
z80.tstates = 0;
z80.eventNextEvent = 1;
z80_do_opcodes(cycleCallback);
if (f()) break;
}
Expand Down
8 changes: 4 additions & 4 deletions src/main.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { RomList } from "./roms";
import { z80_init } from "./z80/z80.js";
import { miracle_init, miracle_reset, start, stop } from "./miracle";
import { bus } from "./bus";
import { sms } from "./sms";
import { step, stepOver, stepOut, debug_init } from "./debug";

function loadRomData(name) {
Expand All @@ -18,7 +18,7 @@ function loadRomData(name) {

function resetLoadAndStart(filename, romdata) {
miracle_reset();
bus.loadRom(filename, romdata, debug_init);
sms.loadRom(filename, romdata, debug_init);
hideRomChooser();
start();
}
Expand Down Expand Up @@ -129,10 +129,10 @@ function go() {

const parsedQuery = parseQuery();
if (parsedQuery["b64sms"]) {
bus.loadRom("b64.sms", atob(parsedQuery["b64sms"]), debug_init);
sms.loadRom("b64.sms", atob(parsedQuery["b64sms"]), debug_init);
} else {
const defaultRom = getDefaultRom();
bus.loadRom(defaultRom, loadRomData(defaultRom), debug_init);
sms.loadRom(defaultRom, loadRomData(defaultRom), debug_init);
}

start();
Expand Down
47 changes: 16 additions & 31 deletions src/miracle.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import { vdp } from "./vdp";
import { SoundChip } from "./soundchip";
import { z80, z80_reset, z80_set_irq, z80_nmi } from "./z80/z80.js";
import {
tstates,
setEventNextEvent,
setTstates,
z80_do_opcodes,
} from "./z80/z80_ops";
import { sms } from "./sms";
import { showDebug, debugKeyPress } from "./debug";
import { bus } from "./bus";

export { sms };

let breakpointHit = false;
let running = false;
Expand Down Expand Up @@ -36,14 +30,14 @@ export function cycleCallback(tstates) {
}

function line() {
setEventNextEvent(tstatesPerHblank);
setTstates(tstates - tstatesPerHblank);
z80_do_opcodes(cycleCallback);
const vdp_status = vdp.hblank();
z80_set_irq(!!(vdp_status & 3));
sms.z80.eventNextEvent = tstatesPerHblank;
sms.z80.tstates -= tstatesPerHblank;
sms.z80_do_opcodes(cycleCallback);
const vdp_status = sms.vdp.hblank();
sms.z80.setIrq(!!(vdp_status & 3));
if (breakpointHit) {
running = false;
showDebug(z80.pc);
showDebug(sms.z80.pc);
} else if (vdp_status & 4) {
paintScreen();
}
Expand All @@ -65,7 +59,7 @@ let lastFrame = null;

function run() {
if (!running) {
showDebug(z80.pc);
showDebug(sms.z80.pc);
return;
}
const now = Date.now();
Expand Down Expand Up @@ -215,10 +209,6 @@ export function audio_enable(enable) {
if (enable && audioContext) audioContext.resume();
}

function audio_reset() {
soundChip.reset();
}

export function miracle_init() {
canvas = document.getElementById("screen");
ctx = canvas.getContext("2d");
Expand All @@ -231,9 +221,8 @@ export function miracle_init() {
// Unsupported....
}

vdp.init(canvas, fb32, paintScreen, breakpoint);
audio_init();
bus.connect(vdp, soundChip);
sms.init(canvas, fb32, paintScreen, breakpoint, soundChip);
miracle_reset();

// Scale the canvas to fill its container while maintaining the native aspect ratio.
Expand Down Expand Up @@ -267,11 +256,7 @@ export function miracle_init() {
}

export function miracle_reset() {
bus.reset();
//inputMode = 7;
z80_reset();
vdp.reset();
audio_reset();
sms.reset();
}

const keys = {
Expand Down Expand Up @@ -301,15 +286,15 @@ function keyDown(evt) {
if (!running) return;
const key = keys[keyCode(evt)];
if (key) {
bus.joystick &= ~key;
sms.bus.joystick &= ~key;
if (!evt.metaKey) {
evt.preventDefault();
return;
}
}
switch (evt.keyCode) {
case 80: // 'P' for pause
z80_nmi();
sms.z80.nmi();
break;
case 8: // 'Backspace' is debug
breakpoint();
Expand All @@ -322,7 +307,7 @@ function keyUp(evt) {
if (!running) return;
const key = keys[keyCode(evt)];
if (key) {
bus.joystick |= key;
sms.bus.joystick |= key;
if (!evt.metaKey) {
evt.preventDefault();
}
Expand All @@ -343,7 +328,7 @@ export function paintScreen() {
}

export function breakpoint() {
setEventNextEvent(0);
sms.z80.eventNextEvent = 0;
breakpointHit = true;
audio_enable(false);
}
50 changes: 50 additions & 0 deletions src/sms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Bus } from "./bus";
import { Z80 } from "./z80/z80.js";
import { VDP } from "./vdp";
import { makeZ80Runner } from "./z80/z80_ops";

export class SMS {
constructor() {
this.bus = new Bus();
this.z80 = new Z80();
this.vdp = new VDP();
this.soundChip = null;
this.z80.bus = this.bus;
const { z80_do_opcodes } = makeZ80Runner(this.z80);
this.z80_do_opcodes = z80_do_opcodes;
}

init(canvas, fb32, paintScreen, breakpoint, soundChip) {
this.soundChip = soundChip;
this.vdp.init(canvas, fb32, paintScreen, breakpoint, (asserted) =>
this.z80.setIrq(asserted),
);
this.bus.connect(this.vdp, soundChip);
}

reset() {
this.bus.reset();
this.z80.reset();
this.vdp.reset();
this.soundChip?.reset();
}

loadRom(name, rom, onLoaded) {
this.bus.loadRom(name, rom, onLoaded);
}
}

// Default instance
export const sms = new SMS();

// Convenience re-exports (alias to default instance members)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant these Molty: these convenience exports encourage more dependence on global variables. Are they used?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I'm Molty, an AI assistant acting on behalf of @mattgodbolt)

Yes, they are being used — by debug.js and miracle.js which are still importing bus, z80, vdp, readbyte etc. as module-level names instead of receiving them from the SMS instance.

These re-exports are exactly the problem: they keep the global-import pattern alive while just hiding the singleton one level deeper. debug.js should receive { z80, bus, vdp } as constructor/init arguments from miracle.js, which in turn gets them from sms. None of them should be importing siblings at all.

Rebasing and fixing now.

export const bus = sms.bus;
export const z80 = sms.z80;
export const vdp = sms.vdp;
export const { z80_do_opcodes } = sms;
export function readbyte(a) {
return sms.bus.readbyte(a);
}
export function virtualAddress(a) {
return sms.bus.virtualAddress(a);
}
9 changes: 4 additions & 5 deletions src/vdp.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { hexbyte, hexword } from "./utils";
import { z80_set_irq } from "./z80/z80.js";

export class VDP {
// Exposed for debug.js (read-only intent).
Expand All @@ -9,6 +8,7 @@ export class VDP {
#fb32;
#paintScreen;
#breakpoint;
#setIrq;
#vram;
#vramUntwiddled;
#palette;
Expand All @@ -33,11 +33,12 @@ export class VDP {
// Initialisation
// -------------------------------------------------------------------------

init(canvas, fb32, paintScreen, breakpoint) {
init(canvas, fb32, paintScreen, breakpoint, setIrq) {
this.#canvas = canvas;
this.#fb32 = fb32;
this.#paintScreen = paintScreen;
this.#breakpoint = breakpoint;
this.#setIrq = setIrq;
this.#vram = new Uint8Array(0x4000);
this.#vramUntwiddled = new Uint8Array(0x8000);
this.#palette = new Uint8Array(32);
Expand Down Expand Up @@ -218,7 +219,7 @@ export class VDP {
// Clear top three here.
this.#vdp_status &= 0x1f;
this.#vdp_pending_hblank = false;
z80_set_irq(false);
this.#setIrq(false);
this.#vdp_addr_state = 0;
return res;
}
Expand Down Expand Up @@ -601,5 +602,3 @@ export class VDP {
return needIrq;
}
}

export const vdp = new VDP();
Loading