All files / src/lib/compiler buildArtifactParsers.ts

100% Statements 33/33
100% Branches 24/24
100% Functions 3/3
100% Lines 27/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69  4x                   4x 4x   4x         19x           4x                       4x 24x 24x 7x   17x 1x   16x     4x     13x 13x 13x 3528x 42x 42x 1x   41x 41x 41x   12x 1x   11x    
import type { CartType } from "shared/lib/resources/types";
import { ROM_BANK_SIZE } from "shared/lib/compiler/memoryLayout";
 
export type MemoryRegion = "bank0" | "bankedRom" | "wram" | "other";
 
export type RegionUsage = {
  bank0: number;
  wram: number;
  bankedRom: number;
};
 
export const BANK_0_SIZE = ROM_BANK_SIZE;
export const WRAM_SIZE = 8 * 1024;
 
const MAX_ROM_BANK: Record<CartType, number> = {
  mbc5: 255,
  mbc3: 127,
};
 
export const capacityForCartType = (cartType: CartType): RegionUsage => ({
  bank0: BANK_0_SIZE,
  wram: WRAM_SIZE,
  bankedRom: MAX_ROM_BANK[cartType] * BANK_0_SIZE,
});
 
const NAMED_AREA_REGIONS: Record<string, MemoryRegion> = {
  _CODE: "bank0",
  _HOME: "bank0",
  _GSINIT: "bank0",
  _GSFINAL: "bank0",
  _INITIALIZER: "bank0",
  _LIT: "bank0",
  _DATA: "wram",
  _BSS: "wram",
  _INITIALIZED: "wram",
};
 
export const classifyAreaName = (name: string): MemoryRegion => {
  const banked = /^_CODE_(\d+)$/.exec(name);
  if (banked) {
    return banked[1] === "0" ? "bank0" : "bankedRom";
  }
  if (name.startsWith("_HEADER") || name.startsWith("_CRASH")) {
    return "bank0";
  }
  return NAMED_AREA_REGIONS[name] ?? "other";
};
 
export const parseObjectAreaSizes = (
  source: string,
): Record<string, number> => {
  const sizes: Record<string, number> = {};
  let areaCount = 0;
  for (const line of source.split(/\r?\n/)) {
    if (!line.startsWith("A ")) continue;
    const match = /^A (\S+) size ([0-9A-Fa-f]+) flags/.exec(line);
    if (!match) {
      throw new Error(`Invalid object area: "${line}"`);
    }
    areaCount++;
    const size = parseInt(match[2], 16);
    if (size > 0) sizes[match[1]] = (sizes[match[1]] ?? 0) + size;
  }
  if (areaCount === 0) {
    throw new Error("Build artifact contains no area records");
  }
  return sizes;
};