diff --git a/src/common/baseplatform.ts b/src/common/baseplatform.ts index 2fced0af..e80ecaf8 100644 --- a/src/common/baseplatform.ts +++ b/src/common/baseplatform.ts @@ -85,7 +85,7 @@ export interface Platform { getPresets?(): Preset[]; pause(): void; resume(): void; - loadROM(title: string, rom: any); // TODO: Uint8Array + loadROM(title: string, rom: any, origin?: number); // TODO: Uint8Array loadBIOS?(title: string, rom: Uint8Array); getROMExtension?(rom: FileData): string; @@ -869,8 +869,8 @@ export abstract class BaseMachinePlatform extends BaseDebugPl } } - loadROM(title, data) { - this.machine.loadROM(data, title); + loadROM(title, data, origin?: number) { + this.machine.loadROM(data, title, origin); this.reset(); } diff --git a/src/common/devices.ts b/src/common/devices.ts index d22848fe..70485c44 100644 --- a/src/common/devices.ts +++ b/src/common/devices.ts @@ -68,7 +68,7 @@ export interface SampledAudioSource { } export interface AcceptsROM { - loadROM(data: Uint8Array, title?: string): void; + loadROM(data: Uint8Array, title?: string, origin?: number): void; } export interface AcceptsBIOS { @@ -247,7 +247,7 @@ export abstract class BasicHeadlessMachine implements HasCPU, Bus, AcceptsROM, P reset() { this.cpu.reset(); } - loadROM(data: Uint8Array, title?: string): void { + loadROM(data: Uint8Array, title?: string, origin?: number): void { if (!this.rom) this.rom = new Uint8Array(this.defaultROMSize); if (data.length > this.rom.length) throw new Error(`ROM too big: ${data.length} > ${this.rom.length}`); diff --git a/src/common/workertypes.ts b/src/common/workertypes.ts index 8950af99..a7c5b78e 100644 --- a/src/common/workertypes.ts +++ b/src/common/workertypes.ts @@ -147,6 +147,7 @@ export interface WorkerOutputResult { params?: {} segments?: Segment[] debuginfo?: {} // optional info + origin?: number } export function isUnchanged(result: WorkerResult) : result is WorkerUnchangedResult { diff --git a/src/ide/ui.ts b/src/ide/ui.ts index 193da4ce..2f2b85f5 100644 --- a/src/ide/ui.ts +++ b/src/ide/ui.ts @@ -931,7 +931,7 @@ async function setCompileOutput(data: WorkerResult) { try { clearBreakpoint(); // so we can replace memory (TODO: change toolbar btn) _resetRecording(); - await platform.loadROM(getCurrentPresetTitle(), rom); + await platform.loadROM(getCurrentPresetTitle(), rom, data.origin); current_output = rom; if (!userPaused) _resume(); writeOutputROMFile(); diff --git a/src/machine/apple2.ts b/src/machine/apple2.ts index 75a35b6f..33d8dcff 100644 --- a/src/machine/apple2.ts +++ b/src/machine/apple2.ts @@ -166,7 +166,7 @@ export class AppleII extends BasicScanlineMachine implements AcceptsBIOS { } this.bios = Uint8Array.from(data); } - loadROM(data) { + loadROM(data, title?, origin?: number) { // is it a 16-sector 35-track disk image? if (data.length == 16 * 35 * 256) { var diskii = new DiskII(this, data); @@ -181,17 +181,17 @@ export class AppleII extends BasicScanlineMachine implements AcceptsBIOS { this.HDR_SIZE = 58; } else { // 4-byte DOS header? (TODO: hacky detection) - const origin = this.rom[0] | (this.rom[1] << 8); + const hdrOrigin = this.rom[0] | (this.rom[1] << 8); const size = this.rom[2] | (this.rom[3] << 8); - let isPlausible = origin < 0xc000 - && origin + size < 0x13000 - && (origin == 0x803 || (origin & 0xff) == 0); + let isPlausible = hdrOrigin < 0xc000 + && hdrOrigin + size < 0x13000 + && (hdrOrigin == 0x803 || (hdrOrigin & 0xff) == 0); if (size == data.length - 4 && isPlausible) { - this.LOAD_BASE = origin; + this.LOAD_BASE = hdrOrigin; this.HDR_SIZE = 4; } else { - // default = raw binary @ $803 - this.LOAD_BASE = 0x803; + // Load @ specified origin, fallback to $803 + this.LOAD_BASE = origin ?? 0x803; this.HDR_SIZE = 0; } } diff --git a/src/worker/tools/dasm.ts b/src/worker/tools/dasm.ts index 5a4cc9ad..96fc2d86 100644 --- a/src/worker/tools/dasm.ts +++ b/src/worker/tools/dasm.ts @@ -133,6 +133,24 @@ function parseSymbolMap(asym: string) { return symbolmap; } +// Determine likely origin address from listing +function getMinListingOffset(listings: CodeListingMap): number | undefined { + let minOffset: number | undefined; + for (let key in listings) { + let lst = listings[key]; + if (lst && lst.lines) { + for (let line of lst.lines) { + if (line.iscode && line.offset > 0) { + if (minOffset === undefined || line.offset < minOffset) { + minOffset = line.offset; + } + } + } + } + } + return minOffset; +} + export function assembleDASM(step: BuildStep): BuildStepResult { load("dasm"); var unresolved = {}; @@ -216,6 +234,7 @@ export function assembleDASM(step: BuildStep): BuildStepResult { listings: listings, errors: errors, symbolmap: symbolmap, + origin: getMinListingOffset(listings), }; } @@ -268,6 +287,7 @@ export function assembleDASM2(step: BuildStep): BuildStepResult { output, errors, listings, - symbolmap + symbolmap, + origin: getMinListingOffset(listings), }; }