mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-02-22 12:29:06 +00:00
vcs: changed .cfg file for TigerVision (3E) mapper
vcs: mappers 3E/3F don't correct bank offsets, so banks must not overlap ca65: parse .proc symbols
This commit is contained in:
parent
2e2996bd73
commit
73c74c519e
@ -837,7 +837,7 @@ export class CharmapEditor extends PixNode {
|
||||
chooser.width = this.fmt.w || 1;
|
||||
chooser.height = this.fmt.h || 1;
|
||||
chooser.recreate(agrid, (index, viewer) => {
|
||||
var yscale = Math.ceil(192 / this.fmt.w);
|
||||
var yscale = Math.ceil(256 / this.fmt.w); // TODO: variable scale?
|
||||
var xscale = yscale * (this.fmt.aspect || 1.0);
|
||||
var editview = this.createEditor(aeditor, viewer, xscale, yscale);
|
||||
this.context.setCurrentEditor(aeditor, $(viewer.canvas), this);
|
||||
|
@ -2442,8 +2442,9 @@ export function getPlatformAndRepo() {
|
||||
qs.repo = repo_id;
|
||||
if (repo.platform_id && !qs.platform)
|
||||
qs.platform = platform_id = repo.platform_id;
|
||||
if (!qs.file && repo.mainPath)
|
||||
if (repo.mainPath && !qs.file)
|
||||
qs.file = repo.mainPath;
|
||||
// TODO: update repo definition if new main file compiles successfully
|
||||
//requestPersistPermission(true, true);
|
||||
}
|
||||
} else {
|
||||
|
@ -60,7 +60,9 @@ function getToolForFilename_vcs(fn: string) {
|
||||
if (fn.endsWith(".wiz")) return "wiz";
|
||||
if (fn.endsWith(".bb") || fn.endsWith(".bas")) return "bataribasic";
|
||||
if (fn.endsWith(".ca65")) return "ca65";
|
||||
//if (fn.endsWith(".inc")) return "ca65";
|
||||
if (fn.endsWith(".c")) return "cc65";
|
||||
//if (fn.endsWith(".h")) return "cc65";
|
||||
if (fn.endsWith(".ecs")) return "ecs";
|
||||
return "dasm";
|
||||
}
|
||||
@ -222,11 +224,13 @@ class VCSPlatform extends BasePlatform {
|
||||
return state;
|
||||
}
|
||||
fixState(state) {
|
||||
var ofs = (state.ca && state.ca.bo) || 0;
|
||||
if (state.ca && state.ca.fo && (state.c.PC & 0xfff) >= 2048)
|
||||
ofs = state.ca.fo; // 3E/3F fixed-slice formats
|
||||
// TODO: for batari BASIC
|
||||
state.c.EPC = state.c.PC + ofs; // EPC = effective PC for ROM
|
||||
// TODO: DASM listing prevents us from using RORG offset
|
||||
// TODO: how to handle 1000/3000/etc vs overlapping addresses?
|
||||
if (state.ca.f != '3E' && state.ca.f != '3F') {
|
||||
var ofs = (state.ca && state.ca.bo) || 0;
|
||||
// TODO: for batari BASIC
|
||||
state.c.EPC = state.c.PC + ofs; // EPC = effective PC for ROM
|
||||
}
|
||||
}
|
||||
loadState(state) {
|
||||
return Javatari.room.console.loadState(state);
|
||||
@ -294,7 +298,8 @@ class VCSPlatform extends BasePlatform {
|
||||
}
|
||||
}
|
||||
bankSwitchStateToString(state) {
|
||||
return (state.ca && state.ca.bo !== undefined) ? "BankOffset "+hex(state.ca.bo,4)+"\n" : "";
|
||||
if (state.ca?.ro >= 0) return "RAMOffset "+hex(state.ca.ro,4)+"\n";
|
||||
return (state.ca?.bo >= 0) ? "BankOffset "+hex(state.ca.bo,4)+"\n" : "";
|
||||
}
|
||||
piaStateToLongString(p) {
|
||||
return "Timer " + p.t + "/" + p.c + "\nINTIM $" + hex(p.IT,2) + " (" + p.IT + ")\nINSTAT $" + hex(p.IS,2) + "\n";
|
||||
|
60
src/test/testanalysis.ts
Normal file
60
src/test/testanalysis.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { describe } from "mocha";
|
||||
import { OpcodeMetadata, Platform } from "../common/baseplatform";
|
||||
import { CodeAnalyzer_vcs } from "../common/analysis";
|
||||
import { MOS6502 } from "../common/cpu/MOS6502";
|
||||
import assert from "assert";
|
||||
|
||||
class Test6502Platform implements Platform {
|
||||
cpu = new MOS6502();
|
||||
ram = new Uint8Array(65536);
|
||||
|
||||
start(): void | Promise<void> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
reset(): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
isRunning(): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getToolForFilename(s: string): string {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getDefaultExtension(): string {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
pause(): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
resume(): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
loadROM(title: string, rom: any) {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getOpcodeMetadata?(opcode: number, offset: number): OpcodeMetadata {
|
||||
return this.cpu.cpu.getOpcodeMetadata(opcode, offset);
|
||||
}
|
||||
getOriginPC(): number {
|
||||
return 0;
|
||||
}
|
||||
readAddress?(addr:number) : number {
|
||||
return this.ram[addr] || 0;
|
||||
}
|
||||
}
|
||||
|
||||
describe('6502 analysis', function () {
|
||||
it('Should analyze 6502', function () {
|
||||
let platform = new Test6502Platform();
|
||||
platform.ram.set([0xea,0x85,0x02,0xa9,0x60,0x20,0x04,0x00,0xea,0x4c,0x01,0x00]);
|
||||
let analysis = new CodeAnalyzer_vcs(platform);
|
||||
analysis.showLoopTimingForPC(0x0);
|
||||
console.log(analysis);
|
||||
assert.equal(analysis.pc2minclocks[0x0], 304);
|
||||
assert.equal(analysis.pc2maxclocks[0x0], 304);
|
||||
assert.equal(analysis.pc2minclocks[0x1], 19);
|
||||
assert.equal(analysis.pc2maxclocks[0x0], 304);
|
||||
assert.equal(analysis.pc2minclocks[0x3], 0);
|
||||
assert.equal(analysis.pc2maxclocks[0x3], 0);
|
||||
});
|
||||
});
|
@ -1,20 +1,41 @@
|
||||
# Linker config file for targeting the Atari 2600.
|
||||
# From http://wiki.cc65.org/doku.php?id=cc65:atari_2600
|
||||
# Modified for TigerVision (3E) mapper
|
||||
|
||||
MEMORY {
|
||||
RAM: start = $80, size=$80, type = rw, define = yes;
|
||||
ROM: start = $F000, size=$1000, type = ro, file = %O, define = yes;
|
||||
RAM: start = $80, size=$70, type = rw, define = yes;
|
||||
TIA: start = $00, size=$40, type = rw, define = yes;
|
||||
RIOT: start = $280, size=$20, type = rw, define = yes;
|
||||
ROM0: start = $1000, size=$800, type=ro, file=%O, define=yes, fill=yes, bank=0;
|
||||
ROM1: start = $3000, size=$800, type=ro, file=%O, define=yes, fill=yes, bank=1;
|
||||
ROM2: start = $5000, size=$800, type=ro, file=%O, define=yes, fill=yes, bank=2;
|
||||
ROM3: start = $7000, size=$800, type=ro, file=%O, define=yes, fill=yes, bank=3;
|
||||
ROM4: start = $9000, size=$800, type=ro, file=%O, define=yes, fill=yes, bank=4;
|
||||
ROM5: start = $b000, size=$800, type=ro, file=%O, define=yes, fill=yes, bank=5;
|
||||
ROM6: start = $d000, size=$800, type=ro, file=%O, define=yes, fill=yes, bank=6;
|
||||
ROM7: start = $f000, size=$800, type=ro, file=%O, define=yes, fill=yes, bank=7;
|
||||
RAM0: start = $f000, size=$400, type=rw, define=yes;
|
||||
PERM: start = $f800, size=$800, type=ro, file=%O, define=yes, fill=yes;
|
||||
}
|
||||
|
||||
SEGMENTS {
|
||||
RODATA: load=ROM, type=ro, align=$100;
|
||||
STARTUP: load=ROM, type=ro, optional=yes;
|
||||
CODE: load=ROM, type=ro, define=yes;
|
||||
DATA: load=ROM, run=RAM, type=rw, define=yes;
|
||||
ROM0: load=ROM0, type=ro, align=$100, optional=yes;
|
||||
ROM1: load=ROM1, type=ro, align=$100, optional=yes;
|
||||
ROM2: load=ROM2, type=ro, align=$100, optional=yes;
|
||||
ROM3: load=ROM3, type=ro, align=$100, optional=yes;
|
||||
ROM4: load=ROM4, type=ro, align=$100, optional=yes;
|
||||
ROM5: load=ROM5, type=ro, align=$100, optional=yes;
|
||||
ROM6: load=ROM6, type=ro, align=$100, optional=yes;
|
||||
ROM7: load=ROM7, type=ro, align=$100, optional=yes;
|
||||
|
||||
RODATA: load=PERM, type=ro, align=$100;
|
||||
STARTUP: load=PERM, type=ro, optional=yes;
|
||||
CODE: load=PERM, type=ro, define=yes;
|
||||
DATA: load=ROM0, run=RAM, type=rw, define=yes;
|
||||
BSS: load=RAM, type=bss, define=yes;
|
||||
VECTORS: load=ROM, type=ro, start=$FFFA;
|
||||
VECTORS: load=PERM, type=ro, start=$FFFA;
|
||||
XDATA: load=ROM0, run=RAM0, type=rw, define=yes, optional=yes;
|
||||
|
||||
ZEROPAGE: load=RAM, type=zp;
|
||||
TIA: load=TIA, type=rw, define = yes, optional = yes;
|
||||
RIOT: load=RIOT, type=rw, define = yes, optional = yes;
|
||||
|
@ -62,30 +62,41 @@ function parseCA65Listing(asmfn: string, code: string, symbols, segments, params
|
||||
insns: null
|
||||
});
|
||||
}
|
||||
var linem = insnLineMatch.exec(line);
|
||||
var topfile = linem && linem[3] == '1';
|
||||
if (topfile) linenum++;
|
||||
if (topfile && linem[1]) {
|
||||
var offset = parseInt(linem[1], 16);
|
||||
var insns = linem[4].trim();
|
||||
if (insns.length) {
|
||||
//console.log(curpath, linenum, offset, segofs, insns);
|
||||
if (!dbg) {
|
||||
lines.push({
|
||||
path: curpath,
|
||||
line: linenum,
|
||||
offset: offset + segofs,
|
||||
insns: insns,
|
||||
iscode: true // TODO: can't really tell unless we parse it
|
||||
});
|
||||
}
|
||||
} else {
|
||||
var sym = linem[5];
|
||||
if (sym.endsWith(':') && !sym.startsWith('@')) {
|
||||
var symofs = symbols[sym.substring(0, sym.length - 1)];
|
||||
if (typeof symofs === 'number') {
|
||||
segofs = symofs - offset;
|
||||
//console.log(sym, segofs, symofs, '-', offset);
|
||||
let linem = insnLineMatch.exec(line);
|
||||
let topfile = linem && linem[3] == '1';
|
||||
if (topfile) {
|
||||
let insns = linem[4]?.trim() || '';
|
||||
// skip extra insns for macro expansions
|
||||
if (!(insns != '' && linem[5] == '')) {
|
||||
linenum++;
|
||||
}
|
||||
if (linem[1]) {
|
||||
var offset = parseInt(linem[1], 16);
|
||||
if (insns.length) {
|
||||
//console.log(dbg, curpath, linenum, offset, segofs, insns);
|
||||
if (!dbg) {
|
||||
lines.push({
|
||||
path: curpath,
|
||||
line: linenum,
|
||||
offset: offset + segofs,
|
||||
insns: insns,
|
||||
iscode: true // TODO: can't really tell unless we parse it
|
||||
});
|
||||
}
|
||||
} else {
|
||||
var sym = null;
|
||||
var label = linem[5];
|
||||
if (label?.endsWith(':')) {
|
||||
sym = label.substring(0, label.length-1);
|
||||
} else if (label?.toLowerCase().startsWith('.proc')) {
|
||||
sym = label.split(' ')[1];
|
||||
}
|
||||
if (sym && !sym.startsWith('@')) {
|
||||
var symofs = symbols[sym];
|
||||
if (typeof symofs === 'number') {
|
||||
segofs = symofs - offset;
|
||||
//console.log(sym, segofs, symofs, '-', offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -224,7 +235,7 @@ export function linkLD65(step: BuildStep): BuildStepResult {
|
||||
lstout = lstout.split('\n\n')[1] || lstout; // remove header
|
||||
putWorkFile(fn, lstout);
|
||||
//const asmpath = fn.replace(/\.lst$/, '.ca65'); // TODO! could be .s
|
||||
let isECS = step.debuginfo?.entities != null; // TODO
|
||||
let isECS = step.debuginfo?.systems?.Init != null; // TODO
|
||||
if (isECS) {
|
||||
var asmlines = [];
|
||||
var srclines = parseCA65Listing(fn, lstout, symbolmap, segments, params, true, listings);
|
||||
|
Loading…
x
Reference in New Issue
Block a user