mirror of
https://github.com/Ed94/pikuma_ps1.git
synced 2026-07-31 20:00:14 +00:00
wip
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
#pragma once
|
||||
#endif
|
||||
// Auto-generated by tape_atom_annotation_pass.lua — DO NOT EDIT
|
||||
// Source: C:\projects\Pikuma\ps1\code\duffle\lottes_tape.h
|
||||
// Source: C:/projects/Pikuma/ps1/code/duffle/lottes_tape.h
|
||||
// Component atoms (MipsAtomComp_(ac_*)) -> macro variants (mac_*)
|
||||
// + auto word-counts (so tape_atom.metadata.h stays manual-only
|
||||
// for encoding macros).
|
||||
@@ -85,7 +85,7 @@ WORD_COUNT(mac_pack_color_word, 3)
|
||||
|
||||
#define mac_format_f3_color(r, g, b) \
|
||||
mac_pack_color_word(O_(Poly_F3,color), gp0_cmd_poly_f3, r, g, b)
|
||||
WORD_COUNT(mac_format_f3_color, 1)
|
||||
WORD_COUNT(mac_format_f3_color, 3)
|
||||
|
||||
/* Words: 3; Stores the 3 transformed (V2_S2 screen) vertices to the F3.
|
||||
* PIPELINE: post-RTPT (SXY0=v0.screen, SXY1=v1.screen, SXY2=v2.screen). */
|
||||
@@ -100,7 +100,7 @@ WORD_COUNT(mac_gte_store_f3_post_rtpt, 3)
|
||||
, mac_pack_color_word(O_(Poly_G4,c1), 0, r1,g1,b1) \
|
||||
, mac_pack_color_word(O_(Poly_G4,c2), 0, r2,g2,b2) \
|
||||
, mac_pack_color_word(O_(Poly_G4,c3), 0, r3,g3,b3)
|
||||
WORD_COUNT(mac_format_g4_color, 4)
|
||||
WORD_COUNT(mac_format_g4_color, 12)
|
||||
|
||||
/* Words: 3; Stores the 3 transformed (V2_S2 screen) vertices of the
|
||||
* G4 triangle portion to p0/p1/p2.
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
typedef U4 const MipsCode;
|
||||
typedef Slice_(MipsCode);
|
||||
typedef Slice_MipsCode MipsAtom;
|
||||
|
||||
#define MipsAtom_(sym) MipsCode tmpl(code,sym) [] align_(4) =
|
||||
|
||||
// Bare form: file-scope declaration with hardcoded body.
|
||||
// Used for components with no args (e.g., ac_load_tri_indices) or
|
||||
// identifier-args (hardcoded register names).
|
||||
@@ -21,6 +23,7 @@ typedef Slice_MipsCode MipsAtom;
|
||||
// expands to:
|
||||
// MipsCode ac_X[] align_(4) = { body };
|
||||
#define MipsAtomComp_(sym) MipsCode sym [] align_(4) =
|
||||
|
||||
// Function form: function-body block that returns a MipsAtom slice.
|
||||
// Used for components with value-args (e.g., ac_format_f3_color).
|
||||
// FI_ MipsAtom ac_X(args) MipsAtomComp_Proc_(ac_X, { body })
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// Auto-generated by tape_atom_offset_gen.meta.lua — DO NOT EDIT
|
||||
// Source: C:\projects\Pikuma\ps1\code\gte_hello\hello_gte_tape.c
|
||||
// Source: C:/projects/Pikuma/ps1/code/gte_hello/hello_gte_tape.c
|
||||
#pragma once
|
||||
|
||||
#pragma region hello_gte_tape
|
||||
|
||||
|
||||
// --- atom: cube_g4_face (42 words) ---
|
||||
// --- atom: cube_g4_face (50 words) ---
|
||||
|
||||
#define _atom_offset_cull_cube_g4_face_exit 26
|
||||
#define _atom_offset_cull_cube_g4_face_exit 34
|
||||
#define _atom_offset_bounds_chk_cube_g4_face_exit 2
|
||||
|
||||
enum {
|
||||
|
||||
+5
-4
@@ -336,9 +336,9 @@ function M.split_top_level_commas(body)
|
||||
local token_start = 1
|
||||
while i <= #body do
|
||||
local c = body:byte(i)
|
||||
if c == 40 then local _, a = M.read_parens(body, i); i = a -- '('
|
||||
elseif c == 123 then local _, a = M.read_braces(body, i); i = a -- '{'
|
||||
elseif c == 91 then local _, a = M.read_brackets(body, i); i = a -- '['
|
||||
if c == 40 then local _, a = M.read_parens(body, i); i = a
|
||||
elseif c == 123 then local _, a = M.read_braces(body, i); i = a
|
||||
elseif c == 91 then local _, a = M.read_brackets(body, i); i = a
|
||||
elseif c == 44 then -- ','
|
||||
tokens[#tokens + 1] = body:sub(token_start, i - 1)
|
||||
i = i + 1
|
||||
@@ -347,7 +347,8 @@ function M.split_top_level_commas(body)
|
||||
local nx = M.skip_str_or_cmt(body, i)
|
||||
-- Don't advance token_start on skip: a trailing `/* ... */` after
|
||||
-- a macro call is part of the current entry's chunk, not the
|
||||
-- start of the next one.
|
||||
-- start of the next one. This keeps comments merged into the
|
||||
-- next entry's chunk (so they don't inflate the word count).
|
||||
if nx > i then i = nx else i = i + 1 end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -208,6 +208,7 @@ local function scan_atom_body(body, word_counts)
|
||||
local pos = 0
|
||||
local labels = {}
|
||||
local branches = {}
|
||||
local _dbg_count = 0
|
||||
for _, tok in ipairs(split_top_level_commas(body)) do
|
||||
local k = 1
|
||||
local tlen = #tok
|
||||
@@ -426,33 +427,60 @@ end
|
||||
-- Main
|
||||
-- ============================================================
|
||||
|
||||
-- Scan a directory recursively for files matching a pattern.
|
||||
-- No regex (per the no_regex constraint) — uses plain byte matching.
|
||||
local function scan_dir(dir, suffix)
|
||||
local results = {}
|
||||
local p = io.popen('dir /b /s "' .. dir .. '\\' .. suffix .. '" 2>nul')
|
||||
if not p then return results end
|
||||
for raw_line in p:lines() do
|
||||
-- dir /b outputs paths with backslashes; normalize to forward.
|
||||
local path = raw_line:gsub("\\", "/")
|
||||
results[#results + 1] = path
|
||||
end
|
||||
p:close()
|
||||
return results
|
||||
end
|
||||
|
||||
local function main(args)
|
||||
if #args < 2 then
|
||||
print("Usage: luajit gen_atom_offsets.lua <metadata.h> <source1> [source2 ...]")
|
||||
os.exit(1)
|
||||
end
|
||||
local word_counts = load_word_counts(args[1])
|
||||
for i = 2, #args do
|
||||
local source_path = args[i]
|
||||
-- Also load the auto-generated <dir>.macs.h for this source's
|
||||
-- directory (if it exists). The metaprogram emits
|
||||
-- WORD_COUNT(mac_X, N) entries there for the MipsAtomComp_
|
||||
-- declarations in the source. Merging ensures the offset
|
||||
-- computation has the right word counts (no "unknown macro"
|
||||
-- warnings for the auto-generated components).
|
||||
local source_dir = dirname(source_path)
|
||||
-- dirname() keeps the trailing separator; basename_no_ext()
|
||||
-- on a path with a trailing separator returns "". Strip it.
|
||||
if #source_dir > 0 and (source_dir:sub(-1) == "/" or source_dir:sub(-1) == "\\") then
|
||||
source_dir = source_dir:sub(1, -2)
|
||||
end
|
||||
local macs_path = source_dir .. "/gen/" .. basename_no_ext(source_dir) .. ".macs.h"
|
||||
local ok, mc = pcall(load_word_counts, macs_path)
|
||||
if ok then
|
||||
-- Find the project root (parent of the metadata file's dir).
|
||||
local meta_dir = dirname(args[1])
|
||||
if #meta_dir > 0 and (meta_dir:sub(-1) == "/" or meta_dir:sub(-1) == "\\") then
|
||||
meta_dir = meta_dir:sub(1, -2)
|
||||
end
|
||||
local project_root = dirname(meta_dir)
|
||||
-- Scan the project for all *.macs.h files and load their WORD_COUNT
|
||||
-- entries as the source of truth. The metaprogram's recursive
|
||||
-- counting (which accounts for macro-in-macro expansion) gives
|
||||
-- the correct values; the metadata file's manually-maintained
|
||||
-- entries are NOT loaded here (they may be wrong for recursive cases).
|
||||
local word_counts = {}
|
||||
local macs_files = scan_dir(project_root, "*.macs.h")
|
||||
for _, macs_path in ipairs(macs_files) do
|
||||
-- Convert forward slashes to backslashes for Windows file open.
|
||||
local win_path = macs_path:gsub("/", "\\")
|
||||
local ok, mc = pcall(load_word_counts, win_path)
|
||||
if ok and type(mc) == "table" then
|
||||
for name, count in pairs(mc) do
|
||||
word_counts[name] = count
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Also load the metadata's encoding-macro entries (which are NOT
|
||||
-- in the macs.h, since the macs.h is component-only). These are
|
||||
-- the regular 1-word-per-macro entries like load_word, add_ui, etc.
|
||||
local meta_counts = load_word_counts(args[1])
|
||||
for name, count in pairs(meta_counts) do
|
||||
if not word_counts[name] then
|
||||
word_counts[name] = count
|
||||
end
|
||||
end
|
||||
for i = 2, #args do
|
||||
local source_path = args[i]
|
||||
process_source(source_path, word_counts)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -892,6 +892,62 @@ local function convert_line_comments_to_block(s)
|
||||
return result
|
||||
end
|
||||
|
||||
-- Compute the word count of a component body, accounting for
|
||||
-- macro expansion. Each comma-separated entry in the body is a
|
||||
-- "slot" that contributes its own word count. For most entries
|
||||
-- (regular MIPS instructions) the count is 1. For `mac_Y(...)`
|
||||
-- calls, the count is the word count of mac_Y (recursive lookup).
|
||||
--
|
||||
-- The component list passed in is the full set of components in the
|
||||
-- source, so we can resolve any `mac_X` call to its definition.
|
||||
local function compute_component_word_count(c, components)
|
||||
-- Build a lookup table: mac_X_name -> component
|
||||
local comp_by_name = {}
|
||||
for _, cc in ipairs(components) do
|
||||
comp_by_name[cc.name] = cc
|
||||
end
|
||||
-- Cache to avoid infinite recursion (if components cycle).
|
||||
local cache = {}
|
||||
local function rec(name)
|
||||
if cache[name] then return cache[name] end
|
||||
cache[name] = 0 -- mark as in-progress
|
||||
local cc = comp_by_name[name]
|
||||
local n
|
||||
if cc then
|
||||
local body_tokens = {}
|
||||
for _, t in ipairs(duffle.split_top_level_commas(cc.body)) do
|
||||
local trimmed = duffle.trim(t)
|
||||
if trimmed ~= "" then body_tokens[#body_tokens + 1] = trimmed end
|
||||
end
|
||||
n = 0
|
||||
for _, t in ipairs(body_tokens) do
|
||||
-- Read the first identifier from the token.
|
||||
local ident, after = duffle.read_ident(t, 1)
|
||||
-- Components are stored without the `mac_` prefix
|
||||
-- (e.g. "format_f3_color"). The token has `mac_format_f3_color(...)`,
|
||||
-- so strip the `mac_` prefix to look up the component.
|
||||
local comp_name = ident
|
||||
if comp_name and comp_name:sub(1, 4) == "mac_" then
|
||||
comp_name = comp_name:sub(5)
|
||||
end
|
||||
if comp_name and comp_by_name[comp_name] then
|
||||
-- It's a `mac_X(...)` call. Recurse.
|
||||
n = n + rec(comp_name)
|
||||
else
|
||||
-- Regular instruction (or some other token): 1 word.
|
||||
n = n + 1
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Not a known component: assume 1 word (regular instruction).
|
||||
n = 1
|
||||
end
|
||||
cache[name] = n
|
||||
return n
|
||||
end
|
||||
return rec(c.name)
|
||||
end
|
||||
|
||||
local function emit_component_macros_h(source_path, components)
|
||||
if #components == 0 then return end
|
||||
|
||||
@@ -956,19 +1012,36 @@ local function emit_component_macros_h(source_path, components)
|
||||
sig = "..."
|
||||
end
|
||||
|
||||
-- Compute the word count of the component body, accounting for
|
||||
-- macro expansion. Each comma-separated entry in the body is one
|
||||
-- "instruction slot", but a `mac_Y(...)` call expands to Y's
|
||||
-- word count. The offset_gen and the metadata's WORD_COUNT table
|
||||
-- both use this resolved count.
|
||||
--
|
||||
-- We compute it once per component (not per token) and emit
|
||||
-- the value in the WORD_COUNT entry. The lookup table `counts_by_name`
|
||||
-- is built from the components list (which find_component_atoms
|
||||
-- already populated) and falls back to 1 for non-mac tokens.
|
||||
local counts_by_name = {}
|
||||
for _, cc in ipairs(components) do
|
||||
local cc_count = compute_component_word_count(cc, components)
|
||||
counts_by_name["mac_" .. cc.name] = cc_count
|
||||
end
|
||||
local n = compute_component_word_count(c, components)
|
||||
|
||||
if n > 0 then
|
||||
-- Convert `//` line comments to `/* */` block comments in each
|
||||
-- token. C macros use `\` line-continuations; if a `//` comment
|
||||
-- appears before a `\`, the rest of the line (including the
|
||||
-- continuation) is consumed by the `//`, breaking the macro.
|
||||
-- Converting to `/* */` preserves the macro structure.
|
||||
for j = 1, n do
|
||||
for j = 1, #tokens do
|
||||
tokens[j] = convert_line_comments_to_block(tokens[j])
|
||||
end
|
||||
-- Emit the mac_<X>(<sig>) macro
|
||||
lines[#lines + 1] = "#define mac_" .. c.name .. "(" .. sig .. ") \\"
|
||||
lines[#lines + 1] = "\t" .. tokens[1] .. " \\"
|
||||
for j = 2, n do
|
||||
for j = 2, #tokens do
|
||||
lines[#lines + 1] = ",\t" .. tokens[j] .. " \\"
|
||||
end
|
||||
-- Strip the trailing line-continuation on the last body line.
|
||||
|
||||
Reference in New Issue
Block a user