moved vcs/nes/gb headers to src/worker/lib

This commit is contained in:
Steven Hugg committed 2026-09-29 09:27:02 +02:00
1 parent 1c3c24c765
commit 055b89cecd
66 files changed
+2180 -220

No files matched your search

+11 -7
View File
@@ -76,10 +76,13 @@ export function extractHeaders(workerDir: string, tool: string, platform: string
const fsName = getSharedFileSystemName(tool, platform);
if (fsName && fsName.startsWith('wasi:')) files.push(...readWASIZipPackage(workerDir, fsName.substring(5)));
else if (fsName) files.push(...readPreloadPackage(workerDir, fsName));
// subdirectories too: GBDK's headers are gb/gb.h and so on
const libDir = path.join(workerDir, 'lib', platform);
if (fs.existsSync(libDir)) {
for (const f of fs.readdirSync(libDir).filter((f) => /\.h$/i.test(f)))
files.push({ path: `/lib/${f}`, data: fs.readFileSync(path.join(libDir, f)) });
for (const f of fs.readdirSync(libDir, { recursive: true }) as string[]) {
if (/\.h$/i.test(f))
files.push({ path: `/lib/${f.split(path.sep).join('/')}`, data: fs.readFileSync(path.join(libDir, f)) });
}
}
const written: string[] = [];
for (const f of files) {
@@ -111,16 +114,17 @@ export function clangConfig(tool: string, platform: string, dirs: {
}): ClangConfig | undefined {
const params: any = (PLATFORM_PARAMS as any)[platform] || {};
const defines = ['__8BITWORKSHOP__', ...(params.define || [])];
const includeDirs = [dirs.sourceDir];
// -D and -I from extra_preproc_args; '.' is the platform's lib directory,
// which extractHeaders() puts in /lib
// the worker stages the platform's lib directory (extra_compile_files) in
// the build directory, next to the source; extractHeaders() puts it in /lib
const libDir = path.join(dirs.headerDir, 'lib');
const includeDirs = [dirs.sourceDir, libDir];
// -D and -I from extra_preproc_args; '.' is the build directory
const extra: string[] = params.extra_preproc_args || [];
for (let i = 0; i < extra.length - 1; i++) {
if (extra[i] === '-D') defines.push(extra[++i]);
else if (extra[i] === '-I') {
const dir = extra[++i];
includeDirs.push(dir === '.' ? path.join(dirs.headerDir, 'lib')
: dir.replace(/^\/share/, dirs.headerDir));
if (dir !== '.') includeDirs.push(dir.replace(/^\/share/, dirs.headerDir));
}
}
// the first of the tool's include dirs, as extractHeaders() wrote it
+9
View File
@@ -44,6 +44,11 @@ describe('clangConfig', function () {
assert.ok(coleco.includeDirs.includes('/h/include/coleco'));
});
it('always searches the lib directory, as the worker stages it', function () {
const c = clangConfig('cc65', 'nes', DIRS)!;
assert.ok(c.includeDirs.includes(path.join('/h', 'lib')));
});
it('uses gbz80 defines on the Game Boy', function () {
const c = clangConfig('sdcc', 'gb', DIRS)!;
assert.ok(c.defines.includes('__SDCC_gbz80'));
@@ -65,6 +70,10 @@ describe('extractHeaders', function () {
assert.ok(!/extern void \w+\[\]/.test(c64));
const lib = extractHeaders(WORKER, 'sdcc', 'msx-libcv', out);
assert.ok(lib.some((f) => f.endsWith(path.join('lib', 'cv.h'))));
const nes = extractHeaders(WORKER, 'cc65', 'nes', out);
assert.ok(nes.some((f) => f.endsWith(path.join('lib', 'neslib.h'))));
const gb = extractHeaders(WORKER, 'sdcc', 'gb', out);
assert.ok(gb.some((f) => f.endsWith(path.join('lib', 'gb', 'gb.h'))));
} finally {
fs.rmSync(out, { recursive: true, force: true });
}
-3
View File
@@ -10,11 +10,8 @@ the ROM size in the header. We pick an MBC5 mapper here;
the build defaults to MBC5 when a ROM has banks.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#link "bank1.c"
//#link "bank2.c"
//#resource "gb/global.sgb"
//#symbol ld GB_MAPPER=0x19
#include <stdint.h>
-4
View File
@@ -11,9 +11,6 @@
* Controls: D-pad move, Start = pause, A = start / continue.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include <string.h>
#include "gb/types.h"
@@ -128,7 +125,6 @@ byte sfx_vol;
byte sfx_busy; /* ch1 claimed by SFX */
byte hw_note[3]; /* last note pushed to hardware (avoid retrigger clicks) */
/*
* Level maps — exact NES Chase layouts (from levelN_nam.h metatiles).
* # wall * gem P player 1/2/3 enemies (space) void outside shape
-4
View File
@@ -25,10 +25,6 @@ Porting notes:
beeps.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include <string.h>
#include "gb/types.h"
-3
View File
@@ -13,9 +13,6 @@ Reading the clock is the same on real hardware:
The screen redraws only when the seconds change.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
//#symbol ld GB_MAPPER=0x10
#include <stdint.h>
-4
View File
@@ -33,10 +33,6 @@ Also uses fixed-point (fixed) positions/speeds, vsync, and the
interrupt enable/disable helpers.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include "gb/types.h"
#include "gb/hardware.h"
-61
View File
@@ -1,61 +0,0 @@
#ifndef __BCD_H_INCLUDE
#define __BCD_H_INCLUDE
#include "types.h"
#include <stdint.h>
/** @file bcd.h
Support for working with BCD (Binary Coded Decimal)
See the example BCD project for additional details.
*/
// macro for creating BCD constants
#define BCD_HEX(v) ((BCD)(v))
/** Converts an integer value into BCD format
A maximum of 8 digits may be used
*/
#define MAKE_BCD(v) BCD_HEX(0x ## v)
typedef uint32_t BCD;
/** Converts integer __i__ into BCD format (Binary Coded Decimal)
@param i Numeric value to convert
@param value Pointer to a BCD variable to store the converted result
*/
void uint2bcd(uint16_t i, BCD * value) OLDCALL;
/** Adds two numbers in BCD format: __sour__ += __value__
@param sour Pointer to a BCD value to add to (and where the result is stored)
@param value Pointer to the BCD value to add to __sour__
*/
void bcd_add(BCD * sour, const BCD * value) OLDCALL;
/** Subtracts two numbers in BCD format: __sour__ -= __value__
@param sour Pointer to a BCD value to subtract from (and where the result is stored)
@param value Pointer to the BCD value to subtract from __sour__
*/
void bcd_sub(BCD * sour, const BCD * value) OLDCALL;
/** Convert a BCD number into an asciiz (null terminated) string and return the length
@param bcd Pointer to BCD value to convert
@param tile_offset Optional per-character offset value to add (use 0 for none)
@param buffer Buffer to store the result in
Returns: Length in characters (always 8)
__buffer__ should be large enough to store the converted string
(9 bytes: 8 characters + 1 for terminator)
There are a couple different ways to use __tile_offset__.
For example:
\li It can be the Index of the Font Tile '0' in VRAM to
allow the buffer to be used directly with @ref set_bkg_tiles.
\li It can also be set to the ascii value for character '0'
so that the buffer is a normal string that can be passed to @ref printf.
*/
uint8_t bcd2text(const BCD * bcd, uint8_t tile_offset, uint8_t * buffer) OLDCALL;
#endif
-4
View File
@@ -15,10 +15,6 @@ _cpu to see which machine it is running on. On a CGB it:
On a monochrome Game Boy it falls back to the four-shade DMG palettes.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include "gb/types.h"
#include "gb/hardware.h"
-4
View File
@@ -12,10 +12,6 @@ gb_decompress() returns the decompressed size in bytes, and the
tile count is that divided by 16.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include "gb/types.h"
#include "gb/hardware.h"
-4
View File
@@ -6,10 +6,6 @@ then turn on the LCD.
Ported from presets/nes/hello.c, using GBDK (gb/gb.h).
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include "gb/types.h"
#include "gb/hardware.h"
-4
View File
@@ -12,10 +12,6 @@ much faster than the VBlank. Press START to remove both handlers, then
press it again to add them back.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include "gb/types.h"
#include "gb/hardware.h"
-4
View File
@@ -11,10 +11,6 @@ This demo waits for START, then moves a sprite with the d-pad while
counting A and B presses with edge detection.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include "gb/types.h"
#include "gb/hardware.h"
-4
View File
@@ -16,10 +16,6 @@ Notes on the port:
- The map/tile data lives in bigmap.h (generated with png2asset).
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include "gb/types.h"
#include "gb/hardware.h"
-4
View File
@@ -9,10 +9,6 @@ The Game Boy OAM holds 40 sprites, so 10 actors of 4 sprites each
fit on screen (the NES fits 16).
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include <stdlib.h>
#include "gb/types.h"
-3
View File
@@ -15,9 +15,6 @@
* exactly like the NES player routes low notes to the triangle.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include <string.h>
#include "gb/types.h"
-4
View File
@@ -11,10 +11,6 @@ switch_data(), which also saves the replaced tile so the menu can be
restored when it closes.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include <stddef.h>
#include "gb/types.h"
-3
View File
@@ -6,9 +6,6 @@
* Collect dots; power pellet makes the ghost edible.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include "gb/types.h"
#include "gb/hardware.h"
-4
View File
@@ -13,10 +13,6 @@ next interrupt. The table phase advances every two frames, so the wave travels
across the screen.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include "gb/types.h"
#include "gb/hardware.h"
-4
View File
@@ -8,10 +8,6 @@ view up and down through the whole map.
Ported from presets/nes/scroll.c, using GBDK (gb/gb.h).
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include "gb/types.h"
#include "gb/hardware.h"
-3
View File
@@ -23,9 +23,6 @@ Porting notes:
Controls: D-pad moves player 1, Start starts the game.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
-4
View File
@@ -6,10 +6,6 @@ then turn on the LCD.
Ported from presets/nes/hello.c, using GBDK (gb/gb.h).
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include "gb/types.h"
#include "gb/hardware.h"
-4
View File
@@ -9,10 +9,6 @@ is the same tile data the objects use, so we can point the
sprites at them too.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include <stdlib.h>
#include "gb/types.h"
-3
View File
@@ -15,9 +15,6 @@ pixel one row up at a time. This is slow, since each call to
plot_point() reads and writes a byte of pixel memory.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include <string.h>
#include "gb/types.h"
-3
View File
@@ -7,9 +7,6 @@ are the sub-pixel fraction, dropped with >> 4 when the sprite
is moved. Arrow keys apply thrust; holding A gives a jump burst.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include <string.h>
#include "gb/types.h"
-3
View File
@@ -1,7 +1,4 @@
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include <string.h>
#include "gb/types.h"
-4
View File
@@ -16,10 +16,6 @@ The font is the 8x8 text font from gbtext.h. Its tile numbers equal
ASCII codes, so the characters can go straight into the map.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include "gb/types.h"
#include "gb/hardware.h"
-4
View File
@@ -13,10 +13,6 @@ This demo exercises the low-level access helpers:
- hide_sprite() hides the objects outside a moving four-sprite window.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include "gb/types.h"
#include "gb/hardware.h"
-4
View File
@@ -10,10 +10,6 @@ a row of icons with set_win_submap(), then slides the whole bar in from
the left with scroll_win() while the background scrolls behind it.
*/
//#link "gb/sfr.sgb"
//#link "gb/crt0.sgb"
//#resource "gb/global.sgb"
#include <stdint.h>
#include <string.h>
#include "gb/types.h"
+3
View File
@@ -128,6 +128,9 @@ export interface WorkerMessage {
/** read a file from the preloaded filesystem package (path e.g. '/include/nes.h')
* requires preload_fs; result comes back as {output:Uint8Array} */
readshared?:string
/** read a header from the platform's library (one of its extra_compile_files,
* e.g. 'neslib.h'); requires platform; result comes back as {output:Uint8Array|null} */
readlib?:string
/** list files under a directory of the preloaded filesystem package
* requires preload_fs; result comes back as {output:string[]} */
listshared?:string
+31 -14
View File
@@ -1018,12 +1018,28 @@ export function getLanguageForFilename(fn: string): Extension | null {
return null;
}
// Look up an include file inside the toolchain's preload filesystem
// (e.g. /include/nes.h inside the cc65 package), via the worker.
// Results are cached per filesystem+filename.
// Look up an include file the build gets from outside the project, via the
// worker: first the platform's library (src/worker/lib, e.g. neslib.h or
// gb/gb.h), then the toolchain's preload filesystem (e.g. /include/nes.h
// inside the cc65 package). Results are cached per source+filename.
const sharedFileCache = new Map<string, Promise<string | null>>();
export function lookupSharedFileText(fn: string): Promise<string | null> {
async function queryWorkerText(msg: WorkerMessage): Promise<string | null> {
var result = await current_project.queryWorker(msg);
var output = result && (result as any).output;
return output instanceof Uint8Array && output.length > 0 ? new TextDecoder().decode(output) : null;
}
function lookupLibraryFileText(fn: string): Promise<string | null> {
const platform = current_project.platform_id;
const key = 'lib:' + platform + ':' + fn;
if (!sharedFileCache.has(key)) {
sharedFileCache.set(key, queryWorkerText({ platform, readlib: fn, updates: [], buildsteps: [] }));
}
return sharedFileCache.get(key);
}
function lookupToolchainFileText(fn: string): Promise<string | null> {
const tool = current_project.getToolForFilename(current_project.mainPath);
const fsName = getSharedFileSystemName(tool, current_project.platform_id);
const dirs = getIncludeDirs(tool, current_project.platform_id);
@@ -1036,12 +1052,8 @@ export function lookupSharedFileText(fn: string): Promise<string | null> {
// e.g. "headers/vcs.h")
var candidates = [...dirs.map(dir => dir + '/' + fn), fn];
for (var path of candidates) {
var msg = { preload_fs: fsName, readshared: path, updates: [], buildsteps: [] } as WorkerMessage;
var result = await current_project.queryWorker(msg);
var output = result && (result as any).output;
if (output instanceof Uint8Array && output.length > 0) {
return new TextDecoder().decode(output);
}
var text = await queryWorkerText({ preload_fs: fsName, readshared: path, updates: [], buildsteps: [] });
if (text != null) return text;
}
return null;
})());
@@ -1049,8 +1061,13 @@ export function lookupSharedFileText(fn: string): Promise<string | null> {
return sharedFileCache.get(key);
}
// Read-only viewer for toolchain include files (headers inside the tool's
// preload filesystem), opened by clicking the badge next to an #include line.
export async function lookupSharedFileText(fn: string): Promise<string | null> {
return (await lookupLibraryFileText(fn)) ?? lookupToolchainFileText(fn);
}
// Read-only viewer for include files from outside the project (the platform
// library in src/worker/lib, or the tool's preload filesystem), opened by
// clicking the badge next to an #include line.
// Project files are linked to their own editor windows instead.
// Each opened header gets its own window, id '#headerview/<filename>'.
export class HeaderView implements ProjectView {
@@ -1125,7 +1142,7 @@ export class HeaderView implements ProjectView {
this.setHeaderText(current_project.getFile(path) as string);
return;
}
// 2) toolchain preload filesystem (via worker)
// 2) platform library, then toolchain preload filesystem (via worker)
var text = await lookupSharedFileText(fn);
if (this.requestedFn !== fn) return; // a newer request superseded us
if (text != null) {
@@ -1137,7 +1154,7 @@ export class HeaderView implements ProjectView {
this.currentPath = fn;
this.setHeaderText('// ' + fn + ' was not found.\n'
+ '// Project include files are loaded during a build -- try building first.\n'
+ '// Toolchain headers are only available when the tool has a bundled filesystem.');
+ '// Library and toolchain headers are only available when the platform or tool bundles them.');
}
/** Jump to a line in the header (after content loads). */
+21 -1
View File
@@ -40,6 +40,7 @@ import { EmuTarget, VideoOutput, captureRejectionListeners, dropAbortHandlers, i
import { EmuHalt, PLATFORMS } from '../common/emu';
import { getSkeletonName, getToolMeta } from '../common/toolmeta';
import { getBasePlatform } from '../common/util';
import { PLATFORM_PARAMS } from '../worker/platforms';
import { c } from './cliformat';
const PRESETS_DIR = 'presets';
@@ -181,6 +182,24 @@ function listSkeletons(dir: string, platform: string, skelTools: { [name: string
// (.mame, .wasm, -defender) repeat their parent's list, so the same file can
// be named several times; it is built once, under the first platform that
// claims it.
/**
* Preset files that shadow a platform library file: the worker stages
* `extra_compile_files` from src/worker/lib/<platform>, so a same-named file in
* presets/<base platform> would be copied into new projects and win over it.
* Library files go in src/worker/lib only (doc/notes/sysroot.md, Tiers).
*/
export function libraryCollisions(presetsDir: string, params: { [platform: string]: any }): string[] {
const found = new Set<string>();
for (const id of Object.keys(params).sort()) {
for (const file of params[id].extra_compile_files || []) {
const relpath = getBasePlatform(id) + '/' + file;
if (fs.existsSync(path.join(presetsDir, relpath)))
found.add(`${presetsDir}/${relpath} shadows library file src/worker/lib/${relpath}`);
}
}
return [...found];
}
export async function listPresets(
filter?: string, platform?: string,
warn: (s: string) => void = () => { },
@@ -252,6 +271,7 @@ export async function listPresets(
for (const id of Object.keys(missing).sort()) {
err(`platform ${id}: ${missing[id]} preset(s) not in presets/${getBasePlatform(id)}/`);
}
for (const e of libraryCollisions(PRESETS_DIR, PLATFORM_PARAMS)) err(e);
found.sort((a, b) => a.preset < b.preset ? -1 : a.preset > b.preset ? 1 : 0);
return found;
}
@@ -662,7 +682,7 @@ async function main() {
for (const w of warnings) console.log(dim(`note: ${w}`));
for (const e of errors) console.log(red(`error: ${e}`));
if (errors.length) {
console.error(red(`aborting: ${errors.length} platform(s) list preset files that don't exist`));
console.error(red(`aborting: ${errors.length} problem(s) with the presets tree`));
}
console.log(bold(`${run ? 'building and running' : 'building'} ${presets.length} presets...`));
const results = await buildAllPresets({
+45 -26
View File
@@ -285,20 +285,27 @@ export function getWorkFileAsString(path: string): string {
return store.getFileAsString(path);
}
/** Create the directories above `path` (a/b/c.h -> a, a/b). */
function makeParentDirs(fs, path: string) {
var toks = path.split('/');
for (var i = 1; i < toks.length; i++) {
var dir = toks.slice(0, i).join('/');
try {
fs.mkdir(dir);
} catch (e) {
// emscripten's FS throws EEXIST, whose errno differs between builds
if (!(fs.analyzePath && fs.analyzePath(dir).exists)) throw e;
}
}
}
export function populateEntry(fs, path: string, entry: FileEntry, options: BuildOptions) {
var data = entry.data;
if (options && options.processFn) {
data = options.processFn(path, data);
}
data = fixLineEndings(data);
// create subfolders
var toks = path.split('/');
if (toks.length > 1) {
for (var i = 0; i < toks.length - 1; i++)
try {
fs.mkdir(toks[i]);
} catch (e) { }
}
makeParentDirs(fs, path);
// write file
fs.writeFile(path, data, { encoding: entry.encoding });
var time = new Date(entry.ts);
@@ -360,29 +367,41 @@ export function populateExtraFiles(step: BuildStep, fs, extrafiles) {
if (extrafiles) {
for (var i = 0; i < extrafiles.length; i++) {
var xfn = extrafiles[i];
makeParentDirs(fs, xfn);
// is this file cached?
if (store.workfs[xfn]) {
fs.writeFile(xfn, store.workfs[xfn].data, { encoding: 'binary' });
// may be the project's own file of that name, as text
fs.writeFile(xfn, store.workfs[xfn].data, { encoding: store.workfs[xfn].encoding });
continue;
}
// fetch from network
var xpath = "lib/" + getBasePlatform(step.platform) + "/" + xfn;
var xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.open("GET", PWORKER + xpath, false); // synchronous request
xhr.send(null);
if (xhr.response && xhr.status == 200) {
var data = new Uint8Array(xhr.response);
fs.writeFile(xfn, data, { encoding: 'binary' });
putWorkFile(xfn, data);
console.log(":::", xfn, data.length);
} else {
throw Error("Could not load extra file " + xpath);
}
var data = fetchLibraryFile(step.platform, xfn);
if (!data) throw Error("Could not load extra file lib/" + getBasePlatform(step.platform) + "/" + xfn);
fs.writeFile(xfn, data, { encoding: 'binary' });
putWorkFile(xfn, data);
console.log(":::", xfn, data.length);
}
}
}
/** A file from the platform's library, src/worker/lib/<base platform>/, or null. */
export function fetchLibraryFile(platform: string, name: string): Uint8Array | null {
var xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.open("GET", PWORKER + "lib/" + getBasePlatform(platform) + "/" + name, false); // synchronous request
xhr.send(null);
return xhr.response && xhr.status == 200 ? new Uint8Array(xhr.response) : null;
}
/**
* A header the platform's library provides (listed in extra_compile_files,
* which builds copy in), or null -- for the IDE's read-only header view.
*/
export function readLibraryHeader(platform: string, name: string): Uint8Array | null {
var params = PLATFORM_PARAMS[platform] || PLATFORM_PARAMS[getBasePlatform(platform)];
var listed: string[] = (params && params.extra_compile_files) || [];
return listed.includes(name) ? fetchLibraryFile(platform, name) : null;
}
// see if any target file compares to the inputs in the given direction
function targetCompare(step: BuildStep, targets: string[], isNewer: (inputts: number, targetts: number) => boolean) {
if (!step.maxts) throw Error("call populateFiles() first");
@@ -411,9 +430,9 @@ export function anyTargetChanged(step: BuildStep, targets: string[]) {
* interrupt vectors, so linking it against crt0.o (which has vectors of its
* own) and the bank-switched config its C programs use can only collide. A
* platform spells the difference out with asm_-prefixed copies of the link
* params -- asm_cfgfile, asm_libargs, asm_extra_link_files -- which the
* assembler applies when the project's main file is its own source, and which
* nothing else looks at. Runs before fixParamsWithDefines() so that a source
* params -- asm_cfgfile, asm_libargs, asm_extra_link_files, asm_startup_objs
* -- which the assembler (ca65, sdas) applies when the project's main file is
* its own source, and which nothing else looks at. Runs before fixParamsWithDefines() so that a source
* file's own directive (//#tooldef ... cfgfile=, or a legacy CFGFILE define)
* still has the last word.
*/
+23
View File
@@ -0,0 +1,23 @@
# Rebuild the GBDK runtime objects linked first into every Game Boy C
# program (startup_objs in src/worker/platforms.ts):
#
# crt0.rel - startup code, interrupt vectors, header (crt0.sgb, global.sgb)
# sfr.rel - hardware register symbols (sfr.sgb)
#
# The bundled sdasgb writes the XL3 format gb.lib uses; a system sdasgb
# (4.x) writes XL4, so build through 8bws. A project that links its own
# crt0.sgb replaces crt0.rel, which is how this build gets the sources in.
# Run npm run tsbuild first.
ROOT = ../../../..
all: crt0.rel sfr.rel
crt0.rel sfr.rel: crt0.sgb sfr.sgb global.sgb
set -e; tmp=$$(mktemp -d "$${TMPDIR:-/tmp}/gbrt.XXXXXX"); \
cp crt0.sgb sfr.sgb global.sgb $$tmp/; \
printf '//#link "sfr.sgb"\n//#link "crt0.sgb"\nvoid main(void) {}\n' > $$tmp/gbrt.c; \
saved=$$(cd $(ROOT) && node gen/tools/8bws.js build --json --platform gb --save $$tmp/gbrt.c -o $$tmp/gbrt.gb \
| node -e 'process.stdout.write(JSON.parse(require("fs").readFileSync(0)).data.saveDir)'); \
for f in crt0.rel crt0.lst sfr.rel sfr.lst; do cp "$$saved/$$f" .; done; \
rm -rf $$tmp "$$saved"
File diff suppressed because it is too large. Load diff
+642
View File
@@ -0,0 +1,642 @@
;!FILE crt0.sgb
XL3
H 22 areas 126 global symbols
M Runtime
S GB_CGB_FLAGS Ref000000
S l__DATA Ref000000
S _main Ref000000
S s__DATA Ref000000
S .refresh_OAM Ref000000
S .__.ABS. Def000000
S _shadow_OAM Ref000000
S GB_RAM_SIZE Ref000000
S .STACK Ref000000
S s__INITIALIZED Ref000000
S GB_MAPPER Ref000000
S l__INITIALIZER Ref000000
S GB_ROM_SIZE Ref000000
S s__INITIALIZER Ref000000
A _CODE size 0 flags 0
A _HEADER size 0 flags 8
A _HEADER0 size 1 flags 8
S A$crt0$21 Def000020
S .call_hl Def000020
A _HEADER1 size 5 flags 8
S .MemsetSmall Def000028
S A$crt0$25 Def000028
S A$crt0$26 Def000029
S A$crt0$27 Def00002A
S A$crt0$28 Def00002C
A _HEADER2 size 7 flags 8
S .MemcpySmall Def000030
S A$crt0$32 Def000030
S A$crt0$33 Def000031
S A$crt0$34 Def000032
S A$crt0$35 Def000033
S A$crt0$36 Def000034
S A$crt0$37 Def000036
A _HEADER3 size 8 flags 8
S A$crt0$44 Def000040
S A$crt0$45 Def000041
S A$crt0$46 Def000042
S A$crt0$47 Def000045
A _HEADER4 size 4E flags 8
S _refresh_OAM Def0000AC
S __standard_VBL_handler Def00009C
S A$crt0$100 Def0000A7
S A$crt0$110 Def0000B7
S A$crt0$101 Def0000A9
S A$crt0$120 Def0000C8
S A$crt0$111 Def0000B8
S A$crt0$102 Def0000AB
S A$crt0$121 Def0000C9
S A$crt0$112 Def0000B9
S A$crt0$122 Def0000CB
S A$crt0$113 Def0000BC
S A$crt0$123 Def0000CC
S A$crt0$114 Def0000BF
S A$crt0$105 Def0000AC
S A$crt0$124 Def0000CD
S A$crt0$106 Def0000B2
S A$crt0$116 Def0000C2
S A$crt0$107 Def0000B4
S A$crt0$117 Def0000C4
S A$crt0$118 Def0000C6
S A$crt0$119 Def0000C7
S A$crt0$70 Def000088
S A$crt0$80 Def000092
S A$crt0$71 Def000089
S A$crt0$62 Def000080
S A$crt0$81 Def000093
S A$crt0$72 Def00008A
S A$crt0$63 Def000081
S A$crt0$73 Def00008B
S A$crt0$92 Def00009C
S A$crt0$74 Def00008C
S A$crt0$65 Def000082
S A$crt0$93 Def00009F
S A$crt0$84 Def000094
S A$crt0$75 Def00008D
S A$crt0$66 Def000083
S A$crt0$94 Def0000A0
S A$crt0$67 Def000084
S A$crt0$95 Def0000A2
S A$crt0$86 Def00009A
S A$crt0$77 Def00008F
S A$crt0$68 Def000086
S A$crt0$96 Def0000A3
S A$crt0$87 Def00009B
S A$crt0$69 Def000087
S A$crt0$79 Def000091
S A$crt0$98 Def0000A4
S .int Def000080
S _wait_int_handler Def00008F
A _HEADER5 size 2 flags 8
S A$crt0$131 Def000100
A _HEADER6 size 30 flags 8
A _HEADER7 size 6 flags 8
A _HEADER8 size 1 flags 8
A _HEADER9 size 3 flags 8
A _HEADERa size 1 flags 8
A _HEADERb size 1 flags 8
A _HEADERc size 1 flags 8
A _HEADERd size 2 flags 8
A _HEADERe size 1 flags 8
A _HEADERf size 1 flags 8
A _HEADER10 size 2 flags 8
A _HEADER11 size 82 flags 8
S _reset Def000150
S .reset Def000150
S A$crt0$200 Def000159
S A$crt0$300 Def0001CC
S A$crt0$210 Def000161
S A$crt0$211 Def000164
S A$crt0$202 Def00015A
S .code_start Def000157
S A$crt0$302 Def0001CE
S A$crt0$221 Def000172
S A$crt0$212 Def000166
S A$crt0$303 Def0001CF
S A$crt0$240 Def00018B
S A$crt0$231 Def00017F
S A$crt0$213 Def000168
S A$crt0$204 Def00015D
S A$crt0$304 Def0001D1
S A$crt0$250 Def000197
S A$crt0$241 Def00018E
S A$crt0$232 Def000182
S A$crt0$223 Def000173
S A$crt0$214 Def000169
S _exit Def0001B7
S A$crt0$251 Def000199
S A$crt0$233 Def000185
S A$crt0$224 Def000175
S A$crt0$215 Def00016B
S A$crt0$261 Def0001A6
S A$crt0$234 Def000187
S A$crt0$225 Def000177
S A$crt0$216 Def00016C
S A$crt0$280 Def0001B8
S A$crt0$271 Def0001B0
S A$crt0$244 Def000191
S A$crt0$226 Def000179
S A$crt0$290 Def0001C3
S A$crt0$281 Def0001B9
S A$crt0$263 Def0001A8
S A$crt0$254 Def00019B
S A$crt0$227 Def00017B
S A$crt0$209 Def000160
S A$crt0$291 Def0001C5
S A$crt0$273 Def0001B3
S A$crt0$255 Def00019D
S A$crt0$237 Def000188
S A$crt0$228 Def00017D
S A$crt0$219 Def00016F
S A$crt0$192 Def000150
S A$crt0$265 Def0001A9
S A$crt0$256 Def00019F
S A$crt0$193 Def000153
S A$crt0$284 Def0001BB
S A$crt0$266 Def0001AC
S A$crt0$257 Def0001A0
S A$crt0$248 Def000193
S A$crt0$194 Def000154
S A$crt0$285 Def0001BC
S A$crt0$276 Def0001B4
S A$crt0$267 Def0001AD
S A$crt0$258 Def0001A2
S A$crt0$249 Def000195
S A$crt0$295 Def0001C6
S A$crt0$286 Def0001BE
S A$crt0$259 Def0001A4
S A$crt0$296 Def0001C8
S A$crt0$287 Def0001BF
S A$crt0$269 Def0001AE
S A$crt0$297 Def0001C9
S A$crt0$288 Def0001C1
S A$crt0$279 Def0001B7
S A$crt0$198 Def000157
S A$crt0$289 Def0001C2
S A$crt0$199 Def000158
S A$crt0$299 Def0001CA
S _set_interrupts Def0001BB
A _HEADER12 size 1 flags 8
S A$crt0$309 Def0001E0
A _HOME size 92 flags 0
S .add_int Def000049
S _add_VBL Def000087
S .wait_vbl_done Def000054
S A$crt0$400 Def00000E
S A$crt0$500 Def000063
S A$crt0$410 Def000019
S A$crt0$401 Def000010
S A$crt0$510 Def00006B
S A$crt0$420 Def000023
S A$crt0$411 Def00001A
S A$crt0$402 Def000012
S A$crt0$520 Def00007B
S A$crt0$511 Def00006D
S A$crt0$412 Def00001B
S A$crt0$403 Def000013
S A$crt0$530 Def000086
S A$crt0$440 Def00002F
S A$crt0$422 Def000025
S A$crt0$413 Def00001C
S A$crt0$404 Def000014
S .add_VBL Def000046
S A$crt0$540 Def000091
S A$crt0$513 Def00006F
S A$crt0$450 Def00003A
S A$crt0$441 Def000030
S A$crt0$414 Def00001D
S A$crt0$523 Def00007C
S A$crt0$514 Def000071
S A$crt0$505 Def000064
S A$crt0$460 Def000041
S A$crt0$442 Def000031
S A$crt0$433 Def000029
S A$crt0$415 Def00001E
S A$crt0$406 Def000015
S A$crt0$533 Def000087
S A$crt0$524 Def00007D
S A$crt0$515 Def000073
S A$crt0$506 Def000066
S A$crt0$461 Def000042
S A$crt0$443 Def000033
S A$crt0$434 Def00002A
S A$crt0$407 Def000016
S A$crt0$534 Def000088
S A$crt0$525 Def00007F
S A$crt0$507 Def000068
S A$crt0$480 Def000051
S A$crt0$462 Def000043
S A$crt0$444 Def000034
S A$crt0$435 Def00002B
S A$crt0$417 Def00001F
S A$crt0$408 Def000017
S A$crt0$390 Def000007
S A$crt0$535 Def00008A
S A$crt0$526 Def000080
S A$crt0$517 Def000075
S A$crt0$490 Def000058
S A$crt0$481 Def000052
S A$crt0$463 Def000044
S A$crt0$454 Def00003B
S A$crt0$445 Def000035
S A$crt0$436 Def00002C
S A$crt0$427 Def000026
S A$crt0$418 Def000020
S A$crt0$391 Def000008
S A$crt0$536 Def00008B
S A$crt0$527 Def000081
S A$crt0$518 Def000077
S A$crt0$509 Def000069
S A$crt0$491 Def000059
S A$crt0$482 Def000053
S A$crt0$473 Def000049
S A$crt0$455 Def00003C
S A$crt0$437 Def00002D
S A$crt0$419 Def000022
S A$crt0$383 Def000000
S A$crt0$537 Def00008C
S A$crt0$528 Def000082
S A$crt0$519 Def000079
S A$crt0$492 Def00005A
S A$crt0$474 Def00004A
S A$crt0$456 Def00003D
S A$crt0$447 Def000037
S A$crt0$438 Def00002E
S A$crt0$384 Def000001
S A$crt0$538 Def00008D
S A$crt0$529 Def000085
S A$crt0$475 Def00004B
S A$crt0$457 Def00003E
S A$crt0$448 Def000038
S A$crt0$385 Def000002
S .memcpy_simple Def000009
S .memset_simple Def000000
S A$crt0$539 Def000090
S A$crt0$494 Def00005C
S A$crt0$476 Def00004D
S A$crt0$458 Def00003F
S A$crt0$449 Def000039
S A$crt0$395 Def000009
S A$crt0$386 Def000003
S A$crt0$495 Def00005D
S A$crt0$477 Def00004E
S A$crt0$468 Def000046
S A$crt0$459 Def000040
S A$crt0$396 Def00000A
S A$crt0$387 Def000004
S A$crt0$496 Def00005E
S A$crt0$397 Def00000B
S A$crt0$388 Def000005
S A$crt0$488 Def000054
S A$crt0$479 Def000050
S A$crt0$389 Def000006
S .remove_int Def000029
S A$crt0$498 Def000060
S A$crt0$489 Def000056
S A$crt0$399 Def00000C
S A$crt0$499 Def000061
S _display_off Def000064
S _remove_VBL Def00007C
S _wait_vbl_done Def000054
S .display_off Def000064
S .remove_VBL Def000026
A _BASE size 0 flags 0
A _CODE_0 size 0 flags 0
A _LIT size 0 flags 0
A _INITIALIZER size 0 flags 0
A _GSINIT size C flags 0
S gsinit Def000000
S A$crt0$371 Def000000
S A$crt0$372 Def000003
S A$crt0$373 Def000006
S A$crt0$374 Def000009
A _GSFINAL size 1 flags 0
S A$crt0$377 Def000000
A _DATA size 19 flags 0
S __is_GBA Def000001
S __cpu Def000000
S _sys_time Def000003
S .mode Def000002
S .sys_time Def000003
S .int_0x40 Def000005
A _BSS size 0 flags 0
A _INITIALIZED size 0 flags 0
A _HEAP size 0 flags 0
A _HRAM size 0 flags 8
A _HRAM13 size 3 flags 8
S __shadow_OAM_base Def00FF92
S __current_bank Def00FF90
T 20 00 00
R 00 00 02 00
T 20 00 00
R 00 00 02 00
T 20 00 00 E9
R 00 00 02 00
T 28 00 00
R 00 00 03 00
T 28 00 00
R 00 00 03 00
T 28 00 00 22 0D 20 FC C9
R 00 00 03 00
T 30 00 00
R 00 00 04 00
T 30 00 00
R 00 00 04 00
T 30 00 00 1A 22 13 0D 20 FA C9
R 00 00 04 00
T 40 00 00
R 00 00 05 00
T 40 00 00
R 00 00 05 00
T 40 00 00 F5 E5 21 05 00 C3 80 00
R 00 00 05 00 00 06 1C 00 00 09 06 00
T 80 00 00
R 00 00 06 00
T 80 00 00
R 00 00 06 00
T 80 00 00 C5 D5
R 00 00 06 00
T 82 00 00
R 00 00 06 00
T 82 00 00 2A B6 28 0B E5 3A 6E 67 E7 E1 23 18 F3
R 00 00 06 00
T 8F 00 00
R 00 00 06 00
T 8F 00 00 E8 04
R 00 00 06 00
T 91 00 00
R 00 00 06 00
T 91 00 00 D1 C1 E1 F0 41 E6 02 20 FA F1 D9
R 00 00 06 00
T 9C 00 00
R 00 00 06 00
T 9C 00 00
R 00 00 06 00
T 9C 00 00 21 03 00 34 20 02 23 34
R 00 00 06 00 00 04 1C 00
T A4 00 00
R 00 00 06 00
T A4 00 00 CD 00 00 3E 01 E0 91 FF 00 C9
R 00 00 06 00 02 04 04 00 09 09 21 00
T AC 00 00
R 00 00 06 00
T AC 00 00 F0 41 E6 02 20 FA 3E 00 00 00 C3 04 00
R 00 00 06 00 8B 0A 06 00 02 0E 04 00
T B7 00 00
R 00 00 06 00
T B7 00 00 D5 AF 01 00 00 21 00 00 CD 00 00 3E
R 00 00 06 00 02 06 01 00 02 09 03 00 00 0C 15 00
T C3 00 00 00 00 00 E0 92 FF 00 67 AF 6F 0E A0 EF
R 00 00 06 00 8B 03 06 00 09 07 21 00
T CC 00 00 D1 C9
R 00 00 06 00
T 00 01 00
R 00 00 07 00
T 00 01 00
R 00 00 07 00
T 00 01 00 18 57 01 00
R 00 00 07 00 0D 04 13 00
T 04 01 00
R 00 00 08 00
T 04 01 00 CE ED 66 66 CC 0D 00 0B 03 73 00 83 00
R 00 00 08 00
T 11 01 00 0C 00 0D 00 08 11 1F 88 89 00 0E DC CC
R 00 00 08 00
T 1E 01 00 6E E6 DD DD D9 99 BB BB 67 63 6E 0E EC
R 00 00 08 00
T 2B 01 00 CC DD DC 99 9F BB B9 33 3E
R 00 00 08 00
T 34 01 00
R 00 00 09 00
T 34 01 00 54 69 74 6C 65 00
R 00 00 09 00
T 43 01 00
R 00 00 0A 00
T 43 01 00 00 00 00
R 00 00 0A 00 0B 03 00 00
T 44 01 00
R 00 00 0B 00
T 44 01 00 00 00 00
R 00 00 0B 00
T 47 01 00
R 00 00 0C 00
T 47 01 00 00 00 00
R 00 00 0C 00 0B 03 0A 00
T 48 01 00
R 00 00 0D 00
T 48 01 00 00 00 00
R 00 00 0D 00 0B 03 0C 00
T 49 01 00
R 00 00 0E 00
T 49 01 00 00 00 00
R 00 00 0E 00 0B 03 07 00
T 4A 01 00
R 00 00 0F 00
T 4A 01 00 00 00
R 00 00 0F 00
T 4C 01 00
R 00 00 10 00
T 4C 01 00 01
R 00 00 10 00
T 4D 01 00
R 00 00 11 00
T 4D 01 00 00
R 00 00 11 00
T 4E 01 00
R 00 00 12 00
T 4E 01 00 00 00
R 00 00 12 00
T 50 01 00
R 00 00 13 00
T 50 01 00
R 00 00 13 00
T 50 01 00
R 00 00 13 00
T 50 01 00 FA 01 00 47 FA 00 00
R 00 00 13 00 00 04 1C 00 00 08 1C 00
T 57 01 00
R 00 00 13 00
T 57 01 00 F3 57 58 31 00 00 CD B7 00 7A EA 00 00
R 00 00 13 00 02 07 08 00 00 0A 06 00 00 0E 1C 00
T 64 01 00 FE 11 20 07 AF CB 3B 17 EA 01 00
R 00 00 13 00 00 0C 1C 00
T 6F 01 00
R 00 00 13 00
T 6F 01 00 CD 64 00 AF E0 42 E0 43 E0 41 E0 4A 3E
R 00 00 13 00 00 04 15 00
T 7C 01 00 07 E0 4B 11 C6 01 21 00 00 0E 0C F7 CD
R 00 00 13 00 00 07 13 00 02 0A 04 00
T 89 01 00 00 00 01 9C 00 CD 46 00 3E E4 E0 47 E0
R 00 00 13 00 02 03 04 00 00 06 06 00 00 09 15 00
T 96 01 00 48 3E 1B E0 49 3E C0 E0 40 AF E0 0F 3E
R 00 00 13 00
T A3 01 00 01 E0 FF E0 90 FF 00 AF 21 03 00 22 77
R 00 00 13 00 09 07 21 00 00 0C 1C 00
T AE 01 00 E0 26 CD 00 00 FB CD 00 00
R 00 00 13 00 00 06 1A 00 02 0A 02 00
T B7 01 00
R 00 00 13 00
T B7 01 00
R 00 00 13 00
T B7 01 00 76 00 18 FC
R 00 00 13 00
T BB 01 00
R 00 00 13 00
T BB 01 00 F3 F8 02 AF E0 0F 7E FB E0 FF C9
R 00 00 13 00
T C6 01 00
R 00 00 13 00
T C6 01 00 F0 92 FF 00 B7 C8
R 00 00 13 00 09 04 21 00
T CA 01 00
R 00 00 13 00
T CA 01 00 E0 46 3E 28
R 00 00 13 00
T CE 01 00
R 00 00 13 00
T CE 01 00 3D 20 FD C9
R 00 00 13 00
T D2 01 00
R 00 00 13 00
T E0 01 00
R 00 00 14 00
T E0 01 00 C9
R 00 00 14 00
T 00 00 00
R 00 00 1C 00
T 00 00 00
R 00 00 1C 00
T 00 00 00
R 00 00 1C 00
T 01 00 00
R 00 00 1C 00
T 01 00 00
R 00 00 1C 00
T 02 00 00
R 00 00 1C 00
T 02 00 00
R 00 00 1C 00
T 03 00 00
R 00 00 1C 00
T 03 00 00
R 00 00 1C 00
T 03 00 00
R 00 00 1C 00
T 05 00 00
R 00 00 1C 00
T 05 00 00
R 00 00 1C 00
T 19 00 00
R 00 00 1C 00
T 90 FF 00
R 00 00 21 00
T 90 FF 00
R 00 00 21 00
T 90 FF 00
R 00 00 21 00
T 91 FF 00
R 00 00 21 00
T 91 FF 00
R 00 00 21 00
T 92 FF 00
R 00 00 21 00
T 92 FF 00
R 00 00 21 00
T 00 00 00
R 00 00 1A 00
T 00 00 00 01 00 00 21 00 00 11 00 00 CD
R 00 00 1A 00 02 04 0B 00 02 07 0D 00 02 0A 09 00
T 0A 00 00 09 00
R 00 00 1A 00 00 03 15 00
T 00 00 00 C9
R 00 00 1B 00
T 00 00 00
R 00 00 15 00
T 00 00 00 5F 78 B1 C8 73 0B 54 5D 13
R 00 00 15 00
T 09 00 00
R 00 00 15 00
T 09 00 00 78 B1 C8 CB 38 CB 19 30 03 2A 12 13
R 00 00 15 00
T 15 00 00
R 00 00 15 00
T 15 00 00 04 0C 18 06
R 00 00 15 00
T 19 00 00
R 00 00 15 00
T 19 00 00 2A 12 13 2A 12 13
R 00 00 15 00
T 1F 00 00
R 00 00 15 00
T 1F 00 00 0D 20 F7 05 20 F4
R 00 00 15 00
T 25 00 00
R 00 00 15 00
T 25 00 00 C9
R 00 00 15 00
T 26 00 00
R 00 00 15 00
T 26 00 00 21 05 00
R 00 00 15 00 00 04 1C 00
T 29 00 00
R 00 00 15 00
T 29 00 00
R 00 00 15 00
T 29 00 00 2A 5F 56 23 B2 C8 7B B9 20 F6 7A B8 20
R 00 00 15 00
T 36 00 00 F2 54 5D 1B 1B
R 00 00 15 00
T 3B 00 00
R 00 00 15 00
T 3B 00 00 2A 12 47 13 2A 12 13 B0 C8 18 F5
R 00 00 15 00
T 46 00 00
R 00 00 15 00
T 46 00 00 21 05 00
R 00 00 15 00 00 04 1C 00
T 49 00 00
R 00 00 15 00
T 49 00 00
R 00 00 15 00
T 49 00 00 2A B6 28 03 23 18 F9
R 00 00 15 00
T 50 00 00
R 00 00 15 00
T 50 00 00 78 32 71 C9
R 00 00 15 00
T 54 00 00
R 00 00 15 00
T 54 00 00
R 00 00 15 00
T 54 00 00 F0 40 E6 80 C8 AF E0 91 FF 00
R 00 00 15 00 09 0A 21 00
T 5C 00 00
R 00 00 15 00
T 5C 00 00 76 00 F0 91 FF 00 B7 28 F9 C9
R 00 00 15 00 09 06 21 00
T 64 00 00
R 00 00 15 00
T 64 00 00
R 00 00 15 00
T 64 00 00 F0 40 E6 80 C8
R 00 00 15 00
T 69 00 00
R 00 00 15 00
T 69 00 00 F0 44 FE 92 30 FA
R 00 00 15 00
T 6F 00 00
R 00 00 15 00
T 6F 00 00 F0 44 FE 91 38 FA F0 40 E6 7F E0 40 C9
R 00 00 15 00
T 7C 00 00
R 00 00 15 00
T 7C 00 00 C5 F8 04 2A 4F 46 CD 26 00 C1 C9
R 00 00 15 00 00 0A 15 00
T 87 00 00
R 00 00 15 00
T 87 00 00 C5 F8 04 2A 4F 46 CD 46 00 C1 C9
R 00 00 15 00 00 0A 15 00
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+111
View File
@@ -0,0 +1,111 @@
008000 1 __VRAM = 0x8000
008000 2 __VRAM8000 = 0x8000
008800 3 __VRAM8800 = 0x8800
009000 4 __VRAM9000 = 0x9000
009800 5 __SCRN0 = 0x9800
009C00 6 __SCRN1 = 0x9C00
00A000 7 __SRAM = 0xA000
00C000 8 __RAM = 0xC000
00D000 9 __RAMBANK = 0xD000
00FE00 10 __OAMRAM = 0xFE00
00FF00 11 __IO = 0xFF00
00FF30 12 __AUD3WAVERAM = 0xFF30
00FF80 13 __HRAM = 0xFF80
14
15 .globl __VRAM, __VRAM8000, __VRAM8800, __VRAM9000, __SCRN0, __SCRN1, __SRAM, __RAM, __RAMBANK, __OAMRAM, __IO, __AUD3WAVERAM, __HRAM
16
000000 17 _rRAMG = 0x0000
002000 18 _rROMB0 = 0x2000
003000 19 _rROMB1 = 0x3000
004000 20 _rRAMB = 0x4000
21
22 .globl _rRAMG, _rROMB0, _rROMB1, _rRAMB
23
00FF00 24 _P1_REG = 0xFF00 ; Joystick: 1.1.P15.P14.P13.P12.P11.P10
00FF01 25 _SB_REG = 0xFF01 ; Serial IO data buffer
00FF02 26 _SC_REG = 0xFF02 ; Serial IO control register
00FF04 27 _DIV_REG = 0xFF04 ; Divider register
00FF05 28 _TIMA_REG = 0xFF05 ; Timer counter
00FF06 29 _TMA_REG = 0xFF06 ; Timer modulo
00FF07 30 _TAC_REG = 0xFF07 ; Timer control
00FF0F 31 _IF_REG = 0xFF0F ; Interrupt flags: 0.0.0.JOY.SIO.TIM.LCD.VBL
00FF10 32 _NR10_REG = 0xFF10 ; Sound register
00FF11 33 _NR11_REG = 0xFF11 ; Sound register
00FF12 34 _NR12_REG = 0xFF12 ; Sound register
00FF13 35 _NR13_REG = 0xFF13 ; Sound register
00FF14 36 _NR14_REG = 0xFF14 ; Sound register
00FF16 37 _NR21_REG = 0xFF16 ; Sound register
00FF17 38 _NR22_REG = 0xFF17 ; Sound register
00FF18 39 _NR23_REG = 0xFF18 ; Sound register
00FF19 40 _NR24_REG = 0xFF19 ; Sound register
00FF1A 41 _NR30_REG = 0xFF1A ; Sound register
00FF1B 42 _NR31_REG = 0xFF1B ; Sound register
00FF1C 43 _NR32_REG = 0xFF1C ; Sound register
00FF1D 44 _NR33_REG = 0xFF1D ; Sound register
00FF1E 45 _NR34_REG = 0xFF1E ; Sound register
00FF20 46 _NR41_REG = 0xFF20 ; Sound register
00FF21 47 _NR42_REG = 0xFF21 ; Sound register
00FF22 48 _NR43_REG = 0xFF22 ; Sound register
00FF23 49 _NR44_REG = 0xFF23 ; Sound register
00FF24 50 _NR50_REG = 0xFF24 ; Sound register
00FF25 51 _NR51_REG = 0xFF25 ; Sound register
00FF26 52 _NR52_REG = 0xFF26 ; Sound register
00FF30 53 _PCM_SAMPLE = 0xFF30 ; PCM wave pattern
00FF30 54 _AUD3WAVE = 0xFF30 ; PCM wave pattern
00FF40 55 _LCDC_REG = 0xFF40 ; LCD control
00FF41 56 _STAT_REG = 0xFF41 ; LCD status
00FF42 57 _SCY_REG = 0xFF42 ; Scroll Y
00FF43 58 _SCX_REG = 0xFF43 ; Scroll X
00FF44 59 _LY_REG = 0xFF44 ; LCDC Y-coordinate
00FF45 60 _LYC_REG = 0xFF45 ; LY compare
00FF46 61 _DMA_REG = 0xFF46 ; DMA transfer
00FF47 62 _BGP_REG = 0xFF47 ; BG palette data
00FF48 63 _OBP0_REG = 0xFF48 ; OBJ palette 0 data
00FF49 64 _OBP1_REG = 0xFF49 ; OBJ palette 1 data
00FF4A 65 _WY_REG = 0xFF4A ; Window Y coordinate
00FF4B 66 _WX_REG = 0xFF4B ; Window X coordinate
00FF4D 67 _KEY1_REG = 0xFF4D ; CPU speed
00FF4F 68 _VBK_REG = 0xFF4F ; VRAM bank
00FF51 69 _HDMA1_REG = 0xFF51 ; DMA control 1
00FF52 70 _HDMA2_REG = 0xFF52 ; DMA control 2
00FF53 71 _HDMA3_REG = 0xFF53 ; DMA control 3
00FF54 72 _HDMA4_REG = 0xFF54 ; DMA control 4
00FF55 73 _HDMA5_REG = 0xFF55 ; DMA control 5
00FF56 74 _RP_REG = 0xFF56 ; IR port
00FF68 75 _BCPS_REG = 0xFF68 ; BG color palette specification
00FF69 76 _BCPD_REG = 0xFF69 ; BG color palette data
00FF6A 77 _OCPS_REG = 0xFF6A ; OBJ color palette specification
00FF6B 78 _OCPD_REG = 0xFF6B ; OBJ color palette data
00FF70 79 _SVBK_REG = 0xFF70 ; WRAM bank
00FF76 80 _PCM12_REG = 0xFF76 ; Sound channel 1&2 PCM amplitude (R)
00FF77 81 _PCM34_REG = 0xFF77 ; Sound channel 3&4 PCM amplitude (R)
00FFFF 82 _IE_REG = 0xFFFF ; Interrupt enable
83
84 .globl _P1_REG
85 .globl _SB_REG, _SC_REG
86 .globl _DIV_REG
87 .globl _TIMA_REG, _TMA_REG, _TAC_REG
88 .globl _IF_REG
89 .globl _NR10_REG, _NR11_REG, _NR12_REG, _NR13_REG, _NR14_REG
90 .globl _NR21_REG, _NR22_REG, _NR23_REG, _NR24_REG
91 .globl _NR30_REG, _NR31_REG, _NR32_REG, _NR33_REG, _NR34_REG
92 .globl _NR41_REG, _NR42_REG, _NR43_REG, _NR44_REG
93 .globl _NR50_REG, _NR51_REG, _NR52_REG
94 .globl _PCM_SAMPLE, _AUD3WAVE
95 .globl _LCDC_REG
96 .globl _STAT_REG
97 .globl _SCY_REG, _SCX_REG
98 .globl _LY_REG, _LYC_REG
99 .globl _DMA_REG
100 .globl _BGP_REG
101 .globl _OBP0_REG, _OBP1_REG
102 .globl _WY_REG, _WX_REG
103 .globl _KEY1_REG
104 .globl _VBK_REG
105 .globl _HDMA1_REG, _HDMA2_REG, _HDMA3_REG, _HDMA4_REG, _HDMA5_REG
106 .globl _RP_REG
107 .globl _BCPS_REG, _BCPD_REG
108 .globl _OCPS_REG, _OCPD_REG
109 .globl _SVBK_REG
110 .globl _PCM12_REG, _PCM34_REG
111 .globl _IE_REG
+80
View File
@@ -0,0 +1,80 @@
XL3
H 1 areas 4D global symbols
S _LY_REG Def00FF44
S _OCPD_REG Def00FF6B
S _BCPS_REG Def00FF68
S _LYC_REG Def00FF45
S __VRAM8800 Def008800
S _TIMA_REG Def00FF05
S _SCX_REG Def00FF43
S _WX_REG Def00FF4B
S _SCY_REG Def00FF42
S _WY_REG Def00FF4A
S _OCPS_REG Def00FF6A
S _SVBK_REG Def00FF70
S __IO Def00FF00
S _STAT_REG Def00FF41
S _NR10_REG Def00FF10
S _P1_REG Def00FF00
S _NR11_REG Def00FF11
S __AUD3WAVERAM Def00FF30
S __RAM Def00C000
S .__.ABS. Def000000
S _PCM12_REG Def00FF76
S _AUD3WAVE Def00FF30
S _NR30_REG Def00FF1A
S _NR21_REG Def00FF16
S _NR12_REG Def00FF12
S _PCM_SAMPLE Def00FF30
S _NR31_REG Def00FF1B
S _NR22_REG Def00FF17
S _NR13_REG Def00FF13
S _NR50_REG Def00FF24
S _NR41_REG Def00FF20
S _NR32_REG Def00FF1C
S _NR23_REG Def00FF18
S _NR14_REG Def00FF14
S _NR51_REG Def00FF25
S _NR42_REG Def00FF21
S _NR33_REG Def00FF1D
S _NR24_REG Def00FF19
S _PCM34_REG Def00FF77
S _NR52_REG Def00FF26
S _NR43_REG Def00FF22
S _NR34_REG Def00FF1E
S _NR44_REG Def00FF23
S __SCRN0 Def009800
S __SCRN1 Def009C00
S __HRAM Def00FF80
S _HDMA1_REG Def00FF51
S _HDMA2_REG Def00FF52
S _HDMA3_REG Def00FF53
S _IE_REG Def00FFFF
S _HDMA4_REG Def00FF54
S _HDMA5_REG Def00FF55
S _IF_REG Def00FF0F
S _OBP0_REG Def00FF48
S _OBP1_REG Def00FF49
S _DMA_REG Def00FF46
S _SB_REG Def00FF01
S _rROMB0 Def002000
S __SRAM Def00A000
S _LCDC_REG Def00FF40
S _SC_REG Def00FF02
S _rROMB1 Def003000
S _rRAMB Def004000
S _TAC_REG Def00FF07
S __VRAM Def008000
S _BCPD_REG Def00FF69
S _BGP_REG Def00FF47
S _KEY1_REG Def00FF4D
S _rRAMG Def000000
S __RAMBANK Def00D000
S __OAMRAM Def00FE00
S __VRAM8000 Def008000
S __VRAM9000 Def009000
S _RP_REG Def00FF56
S _TMA_REG Def00FF06
S _VBK_REG Def00FF4F
S _DIV_REG Def00FF04
A _CODE size 0 flags 0
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+12 -1
View File
@@ -37,6 +37,8 @@ export var PLATFORM_PARAMS = {
asm_cfgfile: 'atari2600-asm.cfg',
asm_libargs: [],
asm_extra_link_files: ['atari2600-asm.cfg'],
// DASM's standard headers, which dasm programs include
extra_compile_files: ['vcs.h', 'macro.h', 'xmacro.h'],
define: ['__ATARI2600__'],
},
'mw8080bw': {
@@ -205,6 +207,7 @@ export var PLATFORM_PARAMS = {
'-D', 'NES_MIRRORING=0', // horizontal mirroring
],
extra_link_files: ['crt0.o', 'neslib2.lib', 'neslib2.cfg', 'nesbanked.cfg'],
extra_compile_files: ['neslib.h'],
// source link symbol -> linker config (was hardcoded in fixParamsWithDefines)
symbolConfigs: { NES_MAPPER: { '4': 'nesbanked.cfg' } },
// iNES header and CHR data are not in CPU address space
@@ -396,7 +399,15 @@ export var PLATFORM_PARAMS = {
data_start: 0xc0a0,
data_size: 0x1f60,
stack_end: 0xe000,
extra_link_files: ['gbz80.lib', 'gb.lib'],
extra_link_files: ['gbz80.lib', 'gb.lib', 'sfr.rel', 'sfr.lst', 'crt0.rel', 'crt0.lst'],
// GBDK runtime, from crt0.sgb and sfr.sgb (see src/worker/lib/gb/Makefile)
startup_objs: ['sfr.rel', 'crt0.rel'],
// an assembly program (gingerbread.sgb) brings its own header and vectors
asm_startup_objs: [],
// GBDK 4.0.6 headers for gb.lib (#include "gb/gb.h")
extra_compile_files: ['gb/bgb_emu.h', 'gb/cgb.h', 'gb/crash_handler.h', 'gb/drawing.h',
'gb/emu_debug.h', 'gb/gb.h', 'gb/gbdecompress.h', 'gb/hardware.h', 'gb/isr.h',
'gb/metasprites.h', 'gb/sgb.h', 'gb/types.h'],
extra_link_args: [
'-l', 'gb',
'-g', '_shadow_OAM=0xC000',
+11 -8
View File
@@ -359,15 +359,18 @@ export async function compileCC65(step: BuildStep): Promise<BuildStepResult> {
var customArgs = params.extra_compiler_args || ['-T', '-g', '-Oirs', '-Cl', '-W', '-pointer-sign,-no-effect'];
args = args.concat(customArgs, args);
args.push(step.path);
const { wasi, errno, stderr } = await runCC65Tool(step, 'cc65', args, (fs) => populateFiles(step, fs, {
mainFilePath: step.path,
processFn: (path, code) => {
if (typeof code === 'string') {
code = processEmbedDirective(code);
const { wasi, errno, stderr } = await runCC65Tool(step, 'cc65', args, (fs) => {
populateFiles(step, fs, {
mainFilePath: step.path,
processFn: (path, code) => {
if (typeof code === 'string') {
code = processEmbedDirective(code);
}
return code;
}
return code;
}
}));
});
populateExtraFiles(step, fs, params.extra_compile_files);
});
stderr.forEach(makeErrorMatcher(errors, /(.*?):(\d+): (.+)/, 2, 3, step.path, 1));
checkExitCode('cc65', errno, stderr, errors);
if (errors.length) return { errors };
+3 -2
View File
@@ -1,9 +1,9 @@
import { WASIRunner } from "../../common/wasi/wasishim";
import { CodeListingMap, WorkerError } from "../../common/workertypes";
import { BuildStep, BuildStepResult, gatherFiles, putWorkFile, anyTargetChanged } from "../builder";
import { BuildStep, BuildStepResult, gatherFiles, putWorkFile, anyTargetChanged, populateExtraFiles } from "../builder";
import { msvcErrorMatcher, re_crlf, re_msvc } from "../listingutils";
import { loadWASMBinary } from "../wasmutils";
import { populateWASIFiles } from "../wasiutils";
import { populateWASIFiles, wasiFSAdapter } from "../wasiutils";
// DASM writes its listing (-l) in a fixed-column layout, with tabs padding out
// the columns. Once the tabs are expanded to 8-column stops the fields are:
@@ -348,6 +348,7 @@ export function assembleDASM(step: BuildStep): BuildStepResult {
const sympath = step.prefix + '.sym';
const wasi = new WASIRunner();
wasi.initSync(wasiModule);
populateExtraFiles(step, wasiFSAdapter(wasi), step.params.extra_compile_files);
populateWASIFiles(wasi, step);
wasi.setArgs(['dasm', step.path, '-f3',
"-l" + lstpath,
+17 -1
View File
@@ -1,7 +1,7 @@
import { Worker } from "node:worker_threads";
import { defineArgs, extraArgsFor, linkSymbolArgs } from "../../common/toolmeta";
import { CodeListingMap, WorkerError } from "../../common/workertypes";
import { BuildStep, BuildStepResult, gatherFiles, staleFiles, populateFiles, putWorkFile, populateExtraFiles, anyTargetChanged, getWorkFileAsString, fixParamsWithDefines } from "../builder";
import { BuildStep, BuildStepResult, gatherFiles, staleFiles, populateFiles, putWorkFile, populateExtraFiles, anyTargetChanged, getWorkFileAsString, fixParamsWithDefines, applyAsmProjectParams } from "../builder";
import { parseListing, parseSourceLines, msvcErrorMatcher } from "../listingutils";
import { EmscriptenModule, emglobal, execMain, loadNative, moduleInstFn, print_fn, setupFS, setupStdin } from "../wasmutils";
import { preprocessMCPP } from "./mcpp";
@@ -135,6 +135,10 @@ async function assembleSDAS(step: BuildStep, tool: 'sdasz80' | 'sdasgb'): Promis
gatherFiles(step, { mainFilePath: "main.asm" });
var objpath = step.prefix + ".rel";
var lstpath = step.prefix + ".lst";
// the link step reads these params, so settle them even when up to date
if (step.mainfile) {
applyAsmProjectParams(step.params); // an asm project, not a C one
}
if (staleFiles(step, [objpath, lstpath])) {
const match_asm_fn = errorMatcherSDASZ80(step.path, errors);
var AS: EmscriptenModule = emglobal[tool]({
@@ -240,6 +244,7 @@ export function linkSDLDZ80(step: BuildStep) {
if (banked.length && rest.length)
objargs = rest.slice(0, -1).concat(banked, rest.slice(-1));
}
objargs = withStartupObjects(params.startup_objs, objargs);
args.push.apply(args, objargs);
//console.log(args);
execMain(step, LDZ80, args);
@@ -347,6 +352,17 @@ export function fixBankedCalls(asm: string): string {
return asm;
}
/**
* The platform's startup objects (crt0), from its lib directory, go first:
* they set the area order. A project that links its own (by file name, so
* gb/crt0.rel replaces crt0.rel) keeps it instead.
*/
export function withStartupObjects(startup: string[] | undefined, objargs: string[]): string[] {
if (!startup) return objargs;
var own = new Set(objargs.map((fn) => fn.split('/').pop()));
return startup.filter((fn) => !own.has(fn)).concat(objargs);
}
export function compileSDCC(step: BuildStep): BuildStepResult {
gatherFiles(step, {
+5 -1
View File
@@ -1,7 +1,7 @@
import type { WorkerResult, WorkerMessage, WorkerError, SourceLine } from "../common/workertypes";
import { getSharedFileSystemName } from "../common/toolmeta";
import { store, builder, errorResult, getWorkFileAsString } from "./builder";
import { store, builder, errorResult, getWorkFileAsString, readLibraryHeader } from "./builder";
import { emglobal, fsMeta, loadFilesystem, listSharedFiles, readSharedFile, ensureFilesystem, readWasiSharedFile, listWasiSharedFiles, ensureWasiFilesystem } from "./wasmutils";
// shared FS names starting with 'wasi:' refer to a WASI filesystem zip
@@ -48,6 +48,10 @@ export async function handleMessage(data: WorkerMessage): Promise<WorkerResult>
: (ensureFilesystem(fs1.name), await readSharedFile(fs1.name, data.readshared));
return { output: contents, qid: data.qid } as WorkerResult;
}
// read a header from the platform's library (src/worker/lib)
if (data.readlib) {
return { output: readLibraryHeader(data.platform, data.readlib), qid: data.qid } as WorkerResult;
}
// list files in a filesystem package directory (shared code)
if (data.listshared != null) {
var fs2 = splitWasiFSName(data.preload_fs);
+14
View File
@@ -115,6 +115,20 @@ describe('Worker', function() {
assert.equal(msg.output, null);
assert.equal(msg.qid, 125);
});
it('should read a platform library header', async function() {
var msg = await queryWorker({platform:'nes', readlib:'neslib.h', updates:[], buildsteps:[], qid:140});
assert.ok(msg.output instanceof Uint8Array);
assert.ok(new TextDecoder().decode(msg.output).includes('ppu_on_all'));
assert.equal(msg.qid, 140);
msg = await queryWorker({platform:'gb.color', readlib:'gb/gb.h', updates:[], buildsteps:[], qid:141});
assert.ok(new TextDecoder().decode(msg.output).includes('wait_vbl_done'));
});
it('should return null for a file the platform library does not list', async function() {
var msg = await queryWorker({platform:'nes', readlib:'neslib2.lib', updates:[], buildsteps:[], qid:142});
assert.equal(msg.output, null);
msg = await queryWorker({platform:'nes', readlib:'nosuchfile.h', updates:[], buildsteps:[], qid:143});
assert.equal(msg.output, null);
});
it('should list shared files in WASI filesystem zip', async function() {
var msg = await queryWorker({preload_fs:'wasi:cc7800-fs.zip', listshared:'/headers', updates:[], buildsteps:[], qid:126});
assert.ok(Array.isArray(msg.output));
+26 -1
View File
@@ -1,6 +1,10 @@
import assert from "assert";
import { describe, it } from "mocha";
import { screenStats } from "../../src/tools/buildpresets";
import * as fs from "fs";
import * as os from "os";
import * as path from "path";
import { libraryCollisions, screenStats } from "../../src/tools/buildpresets";
import { PLATFORM_PARAMS } from "../../src/worker/platforms";
// buildpresets --run flags the frames that look like nothing drew: a blank
// (untouched) screen or one color covering everything. screenStats is the pure
@@ -48,3 +52,24 @@ describe('buildpresets screen check', function () {
assert.strictEqual(s.height, 6);
});
});
// Library headers live in src/worker/lib only; a preset copy would be copied
// into new projects and shadow the one the worker stages.
describe('buildpresets library collisions', function () {
it('finds none in the presets tree', function () {
assert.deepStrictEqual(libraryCollisions('presets', PLATFORM_PARAMS), []);
});
it('reports a preset that shadows a library file', function () {
const params = { nes: { extra_compile_files: ['neslib.h'] }, 'gb.color': { extra_compile_files: ['gb/gb.h'] } };
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'presets-'));
try {
fs.mkdirSync(path.join(dir, 'gb/gb'), { recursive: true });
fs.writeFileSync(path.join(dir, 'gb/gb/gb.h'), '');
assert.deepStrictEqual(libraryCollisions(dir, params),
[`${dir}/gb/gb/gb.h shadows library file src/worker/lib/gb/gb/gb.h`]);
} finally {
fs.rmSync(dir, { recursive: true });
}
});
});
+1 -1
View File
@@ -201,7 +201,7 @@ describe('DASM listing parser', function () {
const files = {};
files['fullgame.a'] = fs.readFileSync('./presets/vcs/examples/fullgame.a', 'utf8');
for (const inc of ['vcs.h', 'macro.h', 'xmacro.h']) {
files[inc] = fs.readFileSync('./presets/vcs/' + inc, 'utf8');
files[inc] = fs.readFileSync('./src/worker/lib/vcs/' + inc, 'utf8');
}
const run = runDASM(files, 'fullgame.a');
assert.strictEqual(run.errno, 0, run.stdout);
+61
View File
@@ -0,0 +1,61 @@
import assert from "assert";
import { describe, it } from "mocha";
import * as fs from "fs";
import * as os from "os";
import * as path from "path";
import { compileSourceFile, preload } from "../../src/tools/testlib";
import { withStartupObjects } from "../../src/worker/tools/sdcc";
// The Game Boy links GBDK's crt0 and sfr objects from src/worker/lib/gb
// ahead of the program's, unless the program links its own.
describe('sdcc startup objects', function () {
it('go first', function () {
assert.deepStrictEqual(withStartupObjects(['sfr.rel', 'crt0.rel'], ['main.rel', 'util.rel']),
['sfr.rel', 'crt0.rel', 'main.rel', 'util.rel']);
});
it('give way to the project\'s own, by file name', function () {
assert.deepStrictEqual(withStartupObjects(['sfr.rel', 'crt0.rel'], ['gb/sfr.rel', 'gb/crt0.rel', 'main.rel']),
['gb/sfr.rel', 'gb/crt0.rel', 'main.rel']);
assert.deepStrictEqual(withStartupObjects(['sfr.rel', 'crt0.rel'], ['crt0.rel', 'main.rel']),
['sfr.rel', 'crt0.rel', 'main.rel']);
});
it('leave other platforms alone', function () {
assert.deepStrictEqual(withStartupObjects(undefined, ['main.rel']), ['main.rel']);
assert.deepStrictEqual(withStartupObjects([], ['main.rel']), ['main.rel']);
});
});
describe('Game Boy C build', function () {
this.timeout(60000);
const MAIN = '#include "gb/types.h"\n#include "gb/hardware.h"\n#include "gb/gb.h"\n' +
'void main(void) { wait_vbl_done(); }\n';
let tmpdir: string;
before(async function () {
tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), "sdcclink-"));
await preload('sdcc', 'gb');
});
after(function () { fs.rmSync(tmpdir, { recursive: true, force: true }); });
function build(name: string, code: string) {
const p = path.join(tmpdir, name);
fs.writeFileSync(p, code);
return compileSourceFile('sdcc', 'gb', p);
}
it('links crt0 and the GBDK headers from the library', async function () {
const result = await build('plain.c', MAIN);
assert.deepStrictEqual(result.errors || [], []);
assert.strictEqual(result.output.length, 0x8000);
});
it('links the project\'s own crt0 instead, to the same ROM', async function () {
for (const f of ['crt0.sgb', 'sfr.sgb', 'global.sgb'])
fs.copyFileSync(path.join('src/worker/lib/gb', f), path.join(tmpdir, f));
const plain = await build('plain2.c', MAIN);
const own = await build('own.c', '//#link "sfr.sgb"\n//#link "crt0.sgb"\n' + MAIN);
assert.deepStrictEqual(own.errors || [], []);
assert.deepStrictEqual(Buffer.from(own.output), Buffer.from(plain.output));
});
});