mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2026-04-20 00:17:04 +00:00
gb: wasmboy test
oscar64: emsdk build
This commit is contained in:
Generated
+46
-1
@@ -22,7 +22,8 @@
|
||||
"localforage": "^1.9.0",
|
||||
"mousetrap": "^1.6.5",
|
||||
"octokat": "^0.10.0",
|
||||
"split.js": "^1.6.2"
|
||||
"split.js": "^1.6.2",
|
||||
"wasmboy": "^0.7.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bootbox": "^5.1.3",
|
||||
@@ -986,6 +987,11 @@
|
||||
"node": ">= 4.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/audiobuffer-to-wav": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "git+ssh://git@github.com/torch2424/audiobuffer-to-wav.git#8878a20c5cc7e457b113dabfb1781ad4178f9c62",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/available-typed-arrays": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
|
||||
@@ -3186,6 +3192,12 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/idb": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/idb/-/idb-2.1.3.tgz",
|
||||
"integrity": "sha512-1He6QAuavrD38HCiJasi4lEEK87Y22ldFuM+ZHkp433n4Fd5jXjWKutClYFp8w4mgx3zgrjnWxL8dpjMzcQ+WQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
@@ -5795,6 +5807,12 @@
|
||||
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
|
||||
@@ -6112,6 +6130,15 @@
|
||||
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/raf": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
|
||||
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"performance-now": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
@@ -6364,6 +6391,12 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/responsive-gamepad": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/responsive-gamepad/-/responsive-gamepad-1.1.0.tgz",
|
||||
"integrity": "sha512-njsJuKvany9eYjywXm8iorTeXeAAPqwMNaRWOo8jlh0iQboXgGPf6Z6bLGntELrfU+vR94jTPJYRW0Zzb2gaRA==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/restore-cursor": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
|
||||
@@ -7317,6 +7350,18 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/wasmboy": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/wasmboy/-/wasmboy-0.7.1.tgz",
|
||||
"integrity": "sha512-qgA3bIFAqioYs8kYXtsanIvedgZlZQf382zs3gNlZHIItsAnRzV70/Vp6cJxbK4FyaiG58ah8/g7OW3orrs9Lg==",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"audiobuffer-to-wav": "git+https://github.com/torch2424/audiobuffer-to-wav.git#es-module-rollup",
|
||||
"idb": "^2.1.3",
|
||||
"raf": "^3.4.0",
|
||||
"responsive-gamepad": "1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wcwidth": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
|
||||
|
||||
+2
-1
@@ -23,7 +23,8 @@
|
||||
"localforage": "^1.9.0",
|
||||
"mousetrap": "^1.6.5",
|
||||
"octokat": "^0.10.0",
|
||||
"split.js": "^1.6.2"
|
||||
"split.js": "^1.6.2",
|
||||
"wasmboy": "^0.7.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bootbox": "^5.1.3",
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
|
||||
; Game Boy Background Example in Z80 Assembly (sdasgb syntax)
|
||||
; Hardware register definitions
|
||||
.equ LCDC, 0xFF40 ; LCD Control register
|
||||
.equ BGP, 0xFF47 ; Background palette register
|
||||
.equ LY, 0xFF44 ; LCD Y coordinate register
|
||||
|
||||
; VRAM addresses
|
||||
.equ VRAM_TILES, 0x9000 ; Tile data area
|
||||
.equ VRAM_MAP, 0x9800 ; Background tile map
|
||||
|
||||
; LCDC flags
|
||||
.equ LCDC_ON, 0x80 ; LCD enable
|
||||
.equ LCDC_BG_ON, 0x01 ; Background enable
|
||||
|
||||
.area _CODE
|
||||
|
||||
.globl _main
|
||||
|
||||
_main:
|
||||
; Disable interrupts
|
||||
di
|
||||
|
||||
; Turn off LCD
|
||||
ld a, #0x00
|
||||
ldh (LCDC), a
|
||||
|
||||
; Load tile data into VRAM
|
||||
; Copy tile data to VRAM tile 1 (tile 0 is blank by default)
|
||||
ld hl, #tile_data
|
||||
ld de, #(VRAM_TILES + 0x10) ; Tile 1 starts at offset 0x10
|
||||
ld bc, #16 ; 16 bytes per tile
|
||||
call memcpy
|
||||
|
||||
; Set up background map
|
||||
; Fill background map with tile index 1
|
||||
ld hl, #VRAM_MAP
|
||||
ld a, #0x01 ; Tile index 1
|
||||
ld bc, #(20*18) ; 20x18 tiles = 360 tiles
|
||||
fill_bg_loop:
|
||||
ld (hl), a
|
||||
inc hl
|
||||
dec bc
|
||||
ld a, b
|
||||
or c
|
||||
jr nz, fill_bg_loop
|
||||
|
||||
; Set background palette
|
||||
ld a, #0x12 ; 11 10 01 00 - darkest to lightest
|
||||
ldh (BGP), a
|
||||
|
||||
; Turn on LCD with background enabled
|
||||
ld a, #(LCDC_ON | LCDC_BG_ON)
|
||||
ldh (LCDC), a
|
||||
|
||||
; Main loop
|
||||
main_loop:
|
||||
call wait_vblank
|
||||
jr main_loop
|
||||
|
||||
; Wait for vertical blank
|
||||
wait_vblank:
|
||||
ldh a, (LY)
|
||||
cp #144 ; VBlank starts at line 144
|
||||
jr nz, wait_vblank
|
||||
ret
|
||||
|
||||
; Simple memory copy routine
|
||||
; hl = source, de = destination, bc = count
|
||||
memcpy:
|
||||
ld a, (hl)
|
||||
ld (de), a
|
||||
inc hl
|
||||
inc de
|
||||
dec bc
|
||||
ld a, b
|
||||
or c
|
||||
jr nz, memcpy
|
||||
ret
|
||||
|
||||
; Tile data
|
||||
tile_data:
|
||||
.db 1,2,4,8,0x10,0x20,0x40,0x80
|
||||
.db 0x80,0x40,0x20,0x10,8,4,2,1
|
||||
|
||||
; ROM header (required for Game Boy)
|
||||
.area _HEADER (ABS)
|
||||
.org 0x0100
|
||||
nop
|
||||
jp _main
|
||||
|
||||
.org 0x0104
|
||||
.db 0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B
|
||||
.db 0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D
|
||||
.db 0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E
|
||||
.db 0xDC, 0xCC, 0x6E, 0xE6, 0xDD, 0xDD, 0xD9, 0x99
|
||||
.db 0xBB, 0xBB, 0x67, 0x63, 0x6E, 0x0E, 0xEC, 0xCC
|
||||
.db 0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E
|
||||
|
||||
.org 0x0134
|
||||
.ascii "BGTEST" ; Title (11 bytes max)
|
||||
|
||||
.org 0x013F
|
||||
.db 0x00 ; New licensee code
|
||||
|
||||
.org 0x0147
|
||||
.db 0x00 ; Cartridge type (ROM only)
|
||||
.db 0x00 ; ROM size (32KB)
|
||||
.db 0x00 ; RAM size (none)
|
||||
.db 0x01 ; Destination (non-Japanese)
|
||||
.db 0x33 ; Old licensee code
|
||||
.db 0x00 ; ROM version
|
||||
|
||||
.org 0x014D
|
||||
.db 0x00 ; Header checksum (will be calculated)
|
||||
.db 0x00, 0x00 ; Global checksum (will be calculated)
|
||||
@@ -618,6 +618,7 @@ export function getToolForFilename_z80(fn:string) : string {
|
||||
if (fn.endsWith(".c")) return "sdcc";
|
||||
if (fn.endsWith(".h")) return "sdcc";
|
||||
if (fn.endsWith(".s")) return "sdasz80";
|
||||
if (fn.endsWith(".sgb")) return "sdasgb";
|
||||
if (fn.endsWith(".ns")) return "naken";
|
||||
if (fn.endsWith(".scc")) return "sccz80";
|
||||
if (fn.endsWith(".z")) return "zmac";
|
||||
|
||||
@@ -115,6 +115,7 @@ const TOOL_TO_SOURCE_STYLE = {
|
||||
'nesasm': '6502',
|
||||
'z80asm': 'z80',
|
||||
'sdasz80': 'z80',
|
||||
'sdasgb': 'z80',
|
||||
'sdcc': 'text/x-csrc',
|
||||
'verilator': 'verilog',
|
||||
'jsasm': 'z80',
|
||||
|
||||
@@ -14,6 +14,8 @@ export function importPlatform(name: string) : Promise<any> {
|
||||
case "devel": return import("../platform/devel");
|
||||
case "exidy": return import("../platform/exidy");
|
||||
case "galaxian": return import("../platform/galaxian");
|
||||
case "gb": return import("../platform/gb");
|
||||
case "gameboy": return import("../platform/gb");
|
||||
case "kim1": return import("../platform/kim1");
|
||||
case "markdown": return import("../platform/markdown");
|
||||
case "msx": return import("../platform/msx");
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
import { WasmBoy } from 'wasmboy';
|
||||
import { getToolForFilename_z80, Platform, Preset } from "../common/baseplatform";
|
||||
import { PLATFORMS, RasterVideo } from "../common/emu";
|
||||
|
||||
const GB_PRESETS: Preset[] = [
|
||||
{ id: 'hello.sgb', name: 'Hello (ASM)' },
|
||||
];
|
||||
|
||||
class GameBoyPlatform implements Platform {
|
||||
|
||||
mainElement;
|
||||
video;
|
||||
audioFrequency = 22050;
|
||||
frameIndex = 0;
|
||||
|
||||
machine = { cpuCyclesPerLine: 114 }; // TODO: adjust for GameBoy
|
||||
|
||||
constructor(mainElement) {
|
||||
//super();
|
||||
this.mainElement = mainElement;
|
||||
}
|
||||
|
||||
getPresets() { return GB_PRESETS; }
|
||||
|
||||
async start() {
|
||||
this.video = new RasterVideo(this.mainElement, 160, 144, { overscan: false });
|
||||
this.video.create();
|
||||
|
||||
// Initialize WasmBoy
|
||||
const config = {
|
||||
headless: false,
|
||||
useFrameSkip: false,
|
||||
audioBatchProcessing: false,
|
||||
timersBatchProcessing: false,
|
||||
audioAccumulateSamples: false,
|
||||
graphicsBatchProcessing: false,
|
||||
graphicsDisableScanlineRendering: false,
|
||||
tileRendering: true,
|
||||
tileCaching: true,
|
||||
};
|
||||
|
||||
await WasmBoy.config(config, this.video.canvas, this.audioFrequency);
|
||||
}
|
||||
|
||||
pollControls() {
|
||||
// WasmBoy handles controller polling internally
|
||||
// No need to implement this method
|
||||
}
|
||||
|
||||
advance(novideo: boolean): number {
|
||||
// WasmBoy handles frame timing internally
|
||||
return 70224; // Game Boy CPU cycles per frame
|
||||
}
|
||||
|
||||
async loadROM(title, data) {
|
||||
var romArray = new Uint8Array(data);
|
||||
await WasmBoy.loadROM(romArray);
|
||||
this.frameIndex = 0;
|
||||
}
|
||||
|
||||
reset() {
|
||||
WasmBoy.reset();
|
||||
}
|
||||
|
||||
isRunning() {
|
||||
return WasmBoy.isPlaying();
|
||||
}
|
||||
|
||||
pause() {
|
||||
WasmBoy.pause();
|
||||
}
|
||||
|
||||
resume() {
|
||||
WasmBoy.play();
|
||||
}
|
||||
|
||||
getOriginPC() {
|
||||
return 0x100; // GameBoy boot vector
|
||||
}
|
||||
|
||||
getDefaultExtension() {
|
||||
return ".c";
|
||||
}
|
||||
|
||||
getROMExtension() {
|
||||
return ".gb";
|
||||
}
|
||||
|
||||
getToolForFilename = (fn: string): string => {
|
||||
return getToolForFilename_z80(fn);
|
||||
}
|
||||
|
||||
getMemoryMap = function () {
|
||||
return {
|
||||
main: [
|
||||
{ name: 'ROM Bank 0', start: 0x0000, size: 0x4000, type: 'rom' },
|
||||
{ name: 'ROM Bank 1+', start: 0x4000, size: 0x4000, type: 'rom' },
|
||||
{ name: 'Video RAM', start: 0x8000, size: 0x2000, type: 'ram' },
|
||||
{ name: 'External RAM', start: 0xA000, size: 0x2000, type: 'ram' },
|
||||
{ name: 'Work RAM', start: 0xC000, size: 0x2000, type: 'ram' },
|
||||
{ name: 'OAM', start: 0xFE00, size: 0xA0, type: 'ram' },
|
||||
{ name: 'I/O Registers', start: 0xFF00, size: 0x80, type: 'io' },
|
||||
{ name: 'High RAM', start: 0xFF80, size: 0x7F, type: 'ram' },
|
||||
]
|
||||
};
|
||||
};
|
||||
|
||||
showHelp() {
|
||||
return "https://8bitworkshop.com/docs/platforms/gameboy/";
|
||||
}
|
||||
}
|
||||
|
||||
PLATFORMS['gb'] = GameBoyPlatform;
|
||||
PLATFORMS['gameboy'] = GameBoyPlatform;
|
||||
@@ -362,7 +362,15 @@ export var PLATFORM_PARAMS = {
|
||||
extra_link_files: ['crt0.c', 'libc.a'],
|
||||
extra_link_args: ['crt0.c', '-lc'],
|
||||
},
|
||||
};
|
||||
'gb': {
|
||||
arch: 'gbz80',
|
||||
code_start: 0x0,
|
||||
rom_size: 0x8000,
|
||||
data_start: 0xc000,
|
||||
data_size: 0x2000,
|
||||
stack_end: 0xe000,
|
||||
},
|
||||
};
|
||||
|
||||
PLATFORM_PARAMS['sms-sms-libcv'] = PLATFORM_PARAMS['sms-sg1000-libcv'];
|
||||
PLATFORM_PARAMS['sms-gg-libcv'] = PLATFORM_PARAMS['sms-sms-libcv'];
|
||||
|
||||
+27
-44
@@ -1,53 +1,36 @@
|
||||
import { WASIFilesystem, WASIMemoryFilesystem, WASIRunner } from "../../common/wasi/wasishim";
|
||||
import { BuildStep, BuildStepResult, gatherFiles, staleFiles, store, putWorkFile } from "../builder";
|
||||
import { makeErrorMatcher, msvcErrorMatcher } from "../listingutils";
|
||||
import { loadWASIFilesystemZip } from "../wasiutils";
|
||||
import { loadWASMBinary } from "../wasmutils";
|
||||
import { WorkerError, WorkerResult } from "../../common/workertypes";
|
||||
import { BuildStep, gatherFiles, populateExtraFiles, populateFiles, putWorkFile, staleFiles } from "../builder";
|
||||
import { makeErrorMatcher } from "../listingutils";
|
||||
import { emglobal, execMain, loadNative, moduleInstFn, print_fn, setupFS } from "../wasmutils";
|
||||
|
||||
let oscar64_fs: WASIFilesystem | null = null;
|
||||
let wasiModule: WebAssembly.Module | null = null;
|
||||
|
||||
export async function compileOscar64(step: BuildStep): Promise<BuildStepResult> {
|
||||
const errors = [];
|
||||
const rootDir = "/root/";
|
||||
export async function compileOscar64(step: BuildStep): Promise<WorkerResult> {
|
||||
loadNative("oscar64");
|
||||
var params = step.params;
|
||||
gatherFiles(step, { mainFilePath: "main.c" });
|
||||
const destpath = (step.path || "main.c").replace(/\.[^.]+$/, ".prg");
|
||||
console.log('destpath', destpath);
|
||||
var errors: WorkerError[] = [];
|
||||
|
||||
if (staleFiles(step, [destpath])) {
|
||||
if (!oscar64_fs) {
|
||||
oscar64_fs = await loadWASIFilesystemZip("oscar64-fs.zip", "/root/");
|
||||
}
|
||||
if (!wasiModule) {
|
||||
wasiModule = new WebAssembly.Module(loadWASMBinary("oscar64"));
|
||||
}
|
||||
const wasi = new WASIRunner();
|
||||
wasi.initSync(wasiModule);
|
||||
wasi.fs.setParent(oscar64_fs);
|
||||
for (let file of step.files) {
|
||||
wasi.fs.putFile(rootDir + file, store.getFileData(file));
|
||||
}
|
||||
//wasi.addPreopenDirectory("include");
|
||||
wasi.addPreopenDirectory("/root");
|
||||
wasi.setArgs(["oscar64", "-v", "-g", "-i=/root", step.path]);
|
||||
try {
|
||||
wasi.run();
|
||||
} catch (e) {
|
||||
errors.push(e);
|
||||
}
|
||||
// TODO
|
||||
let stdout = wasi.fds[1].getBytesAsString();
|
||||
let stderr = wasi.fds[2].getBytesAsString();
|
||||
console.log('stdout', stdout);
|
||||
console.log('stderr', stderr);
|
||||
// (58, 17) : error 3001: Could not open source file. 'stdlib.c'
|
||||
const matcher = makeErrorMatcher(errors, /\((\d+),\s+(\d+)\)\s+: error (\d+): (.+)/, 1, 4, step.path);
|
||||
for (let line of stderr.split('\n')) {
|
||||
matcher(line);
|
||||
}
|
||||
if (errors.length) {
|
||||
return { errors };
|
||||
}
|
||||
const output = wasi.fs.getFile(rootDir + destpath).getBytes();
|
||||
var oscar64: EmscriptenModule = await emglobal.Oscar64({
|
||||
instantiateWasm: moduleInstFn('oscar64'),
|
||||
noInitialRun: true,
|
||||
print: print_fn,
|
||||
printErr: matcher,
|
||||
});
|
||||
|
||||
var FS = (oscar64 as any).FS;
|
||||
//setupFS(FS, 'oscar64');
|
||||
populateFiles(step, FS);
|
||||
populateExtraFiles(step, FS, params.extra_compile_files);
|
||||
|
||||
var args = ["-v", "-g", "-i=/root", step.path];
|
||||
execMain(step, oscar64, args);
|
||||
if (errors.length)
|
||||
return { errors: errors };
|
||||
|
||||
var output = FS.readFile(destpath, { encoding: 'binary' });
|
||||
putWorkFile(destpath, output);
|
||||
return {
|
||||
output,
|
||||
|
||||
+81
-30
@@ -1,4 +1,5 @@
|
||||
import { CodeListingMap } from "../../common/workertypes";
|
||||
import { Worker } from "node:worker_threads";
|
||||
import { CodeListingMap, WorkerError } from "../../common/workertypes";
|
||||
import { BuildStep, BuildStepResult, gatherFiles, staleFiles, populateFiles, putWorkFile, populateExtraFiles, anyTargetChanged, getWorkFileAsString } from "../builder";
|
||||
import { parseListing, parseSourceLines, msvcErrorMatcher } from "../listingutils";
|
||||
import { EmscriptenModule, emglobal, execMain, loadNative, moduleInstFn, print_fn, setupFS, setupStdin } from "../wasmutils";
|
||||
@@ -43,38 +44,43 @@ function parseIHX(ihx, rom_start, rom_size, errors) {
|
||||
return output;
|
||||
}
|
||||
|
||||
function errorMatcherSDASZ80(path: string, errors: WorkerError[]) {
|
||||
//?ASxxxx-Error-<o> in line 1 of main.asm null
|
||||
// <o> .org in REL area or directive / mnemonic error
|
||||
// ?ASxxxx-Error-<q> in line 1627 of cosmic.asm
|
||||
// <q> missing or improper operators, terminators, or delimiters
|
||||
var match_asm_re1 = / in line (\d+) of (\S+)/; // TODO
|
||||
var match_asm_re2 = / <\w> (.+)/; // TODO
|
||||
var errline = 0;
|
||||
var errpath = path;
|
||||
var match_asm_fn = (s: string) => {
|
||||
var m = match_asm_re1.exec(s);
|
||||
if (m) {
|
||||
errline = parseInt(m[1]);
|
||||
errpath = m[2];
|
||||
} else {
|
||||
m = match_asm_re2.exec(s);
|
||||
if (m) {
|
||||
errors.push({
|
||||
line: errline,
|
||||
path: errpath,
|
||||
msg: m[1]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return match_asm_fn;
|
||||
}
|
||||
|
||||
export function assembleSDASZ80(step: BuildStep): BuildStepResult {
|
||||
loadNative("sdasz80");
|
||||
loadNative('sdasz80');
|
||||
var objout, lstout, symout;
|
||||
var errors = [];
|
||||
gatherFiles(step, { mainFilePath: "main.asm" });
|
||||
var objpath = step.prefix + ".rel";
|
||||
var lstpath = step.prefix + ".lst";
|
||||
if (staleFiles(step, [objpath, lstpath])) {
|
||||
//?ASxxxx-Error-<o> in line 1 of main.asm null
|
||||
// <o> .org in REL area or directive / mnemonic error
|
||||
// ?ASxxxx-Error-<q> in line 1627 of cosmic.asm
|
||||
// <q> missing or improper operators, terminators, or delimiters
|
||||
var match_asm_re1 = / in line (\d+) of (\S+)/; // TODO
|
||||
var match_asm_re2 = / <\w> (.+)/; // TODO
|
||||
var errline = 0;
|
||||
var errpath = step.path;
|
||||
var match_asm_fn = (s: string) => {
|
||||
var m = match_asm_re1.exec(s);
|
||||
if (m) {
|
||||
errline = parseInt(m[1]);
|
||||
errpath = m[2];
|
||||
} else {
|
||||
m = match_asm_re2.exec(s);
|
||||
if (m) {
|
||||
errors.push({
|
||||
line: errline,
|
||||
path: errpath,
|
||||
msg: m[1]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
const match_asm_fn = errorMatcherSDASZ80(step.path, errors);
|
||||
var ASZ80: EmscriptenModule = emglobal.sdasz80({
|
||||
instantiateWasm: moduleInstFn('sdasz80'),
|
||||
noInitialRun: true,
|
||||
@@ -101,6 +107,41 @@ export function assembleSDASZ80(step: BuildStep): BuildStepResult {
|
||||
//symout = FS.readFile("main.sym", {encoding:'utf8'});
|
||||
}
|
||||
|
||||
export async function assembleSDASGB(step: BuildStep): Promise<BuildStepResult> {
|
||||
loadNative('sdasgb');
|
||||
var objout, lstout, symout;
|
||||
var errors = [];
|
||||
gatherFiles(step, { mainFilePath: "main.asm" });
|
||||
var objpath = step.prefix + ".rel";
|
||||
var lstpath = step.prefix + ".lst";
|
||||
if (staleFiles(step, [objpath, lstpath])) {
|
||||
const match_asm_fn = errorMatcherSDASZ80(step.path, errors);
|
||||
var ASZ80: EmscriptenModule = await emglobal.sdasgb({
|
||||
instantiateWasm: moduleInstFn('sdasgb'),
|
||||
noInitialRun: true,
|
||||
//logReadFiles:true,
|
||||
print: match_asm_fn,
|
||||
printErr: match_asm_fn,
|
||||
});
|
||||
var FS = ASZ80.FS;
|
||||
populateFiles(step, FS);
|
||||
execMain(step, ASZ80, ['-plosgffwy', step.path]);
|
||||
if (errors.length) {
|
||||
return { errors: errors };
|
||||
}
|
||||
objout = FS.readFile(objpath, { encoding: 'utf8' });
|
||||
lstout = FS.readFile(lstpath, { encoding: 'utf8' });
|
||||
putWorkFile(objpath, objout);
|
||||
putWorkFile(lstpath, lstout);
|
||||
}
|
||||
return {
|
||||
linktool: "sdldz80",
|
||||
files: [objpath, lstpath],
|
||||
args: [objpath]
|
||||
};
|
||||
//symout = FS.readFile("main.sym", {encoding:'utf8'});
|
||||
}
|
||||
|
||||
export function linkSDLDZ80(step: BuildStep) {
|
||||
loadNative("sdldz80");
|
||||
var errors = [];
|
||||
@@ -206,6 +247,14 @@ export function linkSDLDZ80(step: BuildStep) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// gameboy: compute checksum
|
||||
if (step.params.arch === 'gbz80') {
|
||||
var checksum = 0;
|
||||
for (var address = 0x0134; address <= 0x014C; address++) {
|
||||
checksum = checksum - binout[address] - 1;
|
||||
}
|
||||
binout[0x14D] = checksum & 0xff;
|
||||
}
|
||||
return {
|
||||
output: binout,
|
||||
listings: listings,
|
||||
@@ -221,10 +270,11 @@ export function compileSDCC(step: BuildStep): BuildStepResult {
|
||||
gatherFiles(step, {
|
||||
mainFilePath: "main.c" // not used
|
||||
});
|
||||
var params = step.params;
|
||||
var isGBZ80 = step.params.arch === 'gbz80';
|
||||
var outpath = step.prefix + ".asm";
|
||||
if (staleFiles(step, [outpath])) {
|
||||
var errors = [];
|
||||
var params = step.params;
|
||||
loadNative('sdcc');
|
||||
var SDCC: EmscriptenModule = emglobal.sdcc({
|
||||
instantiateWasm: moduleInstFn('sdcc'),
|
||||
@@ -246,7 +296,8 @@ export function compileSDCC(step: BuildStep): BuildStepResult {
|
||||
// pipe file to stdin
|
||||
setupStdin(FS, code);
|
||||
setupFS(FS, 'sdcc');
|
||||
var args = ['--vc', '--std-sdcc99', '-mz80', //'-Wall',
|
||||
const machineFlags = isGBZ80 ? '-mgbz80' : '-mz80';
|
||||
var args = ['--vc', '--std-sdcc99', machineFlags, //'-Wall',
|
||||
'--c1mode',
|
||||
//'--debug',
|
||||
//'-S', 'main.c',
|
||||
@@ -266,7 +317,7 @@ export function compileSDCC(step: BuildStep): BuildStepResult {
|
||||
//'--noloopreverse',
|
||||
'-o', outpath];
|
||||
// if "#pragma opt_code" found do not disable optimziations
|
||||
if (!/^\s*#pragma\s+opt_code/m.exec(code)) {
|
||||
if (!isGBZ80 && !/^\s*#pragma\s+opt_code/m.exec(code)) {
|
||||
args.push.apply(args, [
|
||||
'--oldralloc',
|
||||
'--no-peep',
|
||||
@@ -287,7 +338,7 @@ export function compileSDCC(step: BuildStep): BuildStepResult {
|
||||
putWorkFile(outpath, asmout);
|
||||
}
|
||||
return {
|
||||
nexttool: "sdasz80",
|
||||
nexttool: isGBZ80 ? 'sdasgb' : 'sdasz80',
|
||||
path: outpath,
|
||||
args: [outpath],
|
||||
files: [outpath],
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -15,6 +15,7 @@ import * as acme from './tools/acme'
|
||||
import * as cc7800 from './tools/cc7800'
|
||||
import * as bataribasic from './tools/bataribasic'
|
||||
import * as oscar64 from './tools/oscar64'
|
||||
|
||||
import { PLATFORM_PARAMS } from "./platforms";
|
||||
|
||||
export const TOOLS = {
|
||||
@@ -26,6 +27,7 @@ export const TOOLS = {
|
||||
//'z80asm': assembleZ80ASM,
|
||||
//'sccz80': compileSCCZ80,
|
||||
'sdasz80': sdcc.assembleSDASZ80,
|
||||
'sdasgb': sdcc.assembleSDASGB,
|
||||
'sdldz80': sdcc.linkSDLDZ80,
|
||||
'sdcc': sdcc.compileSDCC,
|
||||
'xasm6809': m6809.assembleXASM6809,
|
||||
@@ -82,6 +84,7 @@ export const TOOL_PRELOADFS = {
|
||||
'cc65-exidy': '65-none',
|
||||
'ca65-exidy': '65-none',
|
||||
'sdasz80': 'sdcc',
|
||||
'sdasgb': 'sdcc',
|
||||
'sdcc': 'sdcc',
|
||||
'sccz80': 'sccz80',
|
||||
'bataribasic': '2600basic',
|
||||
|
||||
Reference in New Issue
Block a user