mirror of
https://github.com/Ed94/pikuma_ps1.git
synced 2026-08-06 23:58:49 +00:00
wip: cube_g4_face is bugged
This commit is contained in:
@@ -50,14 +50,32 @@ WORD_COUNT(mac_load_tri_verts, 18)
|
|||||||
/* Words: 11; Correctly inserts a primitive into the Ordering Table linked list.
|
/* Words: 11; Correctly inserts a primitive into the Ordering Table linked list.
|
||||||
* Hardcoded for Poly_F3 (5 words). For Poly_G4, use ac_insert_ot_tag_g4. */
|
* Hardcoded for Poly_F3 (5 words). For Poly_G4, use ac_insert_ot_tag_g4. */
|
||||||
#define mac_insert_ot_tag_f3(...) \
|
#define mac_insert_ot_tag_f3(...) \
|
||||||
shift_lright(R_AT, R_AT, S_(polytag_len_bits))
|
shift_lleft( R_T1, R_T1, S_(U4)/2) /* T1 = otz * S_(U4) (otz arg is implicit R_T1) */ \
|
||||||
WORD_COUNT(mac_insert_ot_tag_f3, 1)
|
, add_u_self( R_T1, R_OtBase) /* T1 = & OrderingTable[OTZ] */ \
|
||||||
|
, load_word( R_AT, R_T1, O_(PolyTag,bf_addr_len)) /* AT = old_ot_head */ \
|
||||||
|
, load_upper_i(R_V0, (S_(Poly_F3)/S_(U4) - S_(PolyTag)/S_(U4)) << polytag_len_bits) /* V0 = (5 - 1) << 24 = 4 << 24 */ \
|
||||||
|
, mask_upper( R_AT, R_AT, S_(polytag_len_bits)) /* Strip upper 8 bits (length from prev cell) → keep only low 24 */ \
|
||||||
|
, or_u( R_AT, R_AT, R_V0) /* Merge length */ \
|
||||||
|
, store_word( R_AT, R_PrimCursor, O_(PolyTag,bf_addr_len)) /* prim->tag = packed(prim_length, old_addr) */ \
|
||||||
|
, shift_lleft( R_AT, R_PrimCursor, S_(polytag_len_bits)) /* AT = (prim_length << 24) | old_addr */ \
|
||||||
|
, shift_lright(R_AT, R_AT, S_(polytag_len_bits)) \
|
||||||
|
, store_word( R_AT, R_T1, O_(PolyTag,bf_addr_len)) /* OrderingTable[OTZ] = PrimCursor */
|
||||||
|
WORD_COUNT(mac_insert_ot_tag_f3, 10)
|
||||||
|
|
||||||
/* Words: 11; Correctly inserts a primitive into the Ordering Table linked list.
|
/* Words: 11; Correctly inserts a primitive into the Ordering Table linked list.
|
||||||
* Hardcoded for Poly_G4 (9 words). For Poly_F3, use ac_insert_ot_tag_f3. */
|
* Hardcoded for Poly_G4 (9 words). For Poly_F3, use ac_insert_ot_tag_f3. */
|
||||||
#define mac_insert_ot_tag_g4(...) \
|
#define mac_insert_ot_tag_g4(...) \
|
||||||
shift_lright(R_AT, R_AT, S_(polytag_len_bits))
|
shift_lleft( R_T1, R_T1, S_(U4)/2) /* T1 = otz * S_(U4) (otz arg is implicit R_T1) */ \
|
||||||
WORD_COUNT(mac_insert_ot_tag_g4, 1)
|
, add_u_self( R_T1, R_OtBase) /* T1 = & OrderingTable[OTZ] */ \
|
||||||
|
, load_word( R_AT, R_T1, O_(PolyTag,bf_addr_len)) /* AT = old_ot_head */ \
|
||||||
|
, load_upper_i(R_V0, (S_(Poly_G4)/S_(U4) - S_(PolyTag)/S_(U4)) << polytag_len_bits) /* V0 = (9 - 1) << 24 = 8 << 24 */ \
|
||||||
|
, mask_upper( R_AT, R_AT, S_(polytag_len_bits)) /* Strip upper 8 bits (length from prev cell) → keep only low 24 */ \
|
||||||
|
, or_u( R_AT, R_AT, R_V0) /* Merge length */ \
|
||||||
|
, store_word( R_AT, R_PrimCursor, O_(PolyTag,bf_addr_len)) /* prim->tag = packed(prim_length, old_addr) */ \
|
||||||
|
, shift_lleft( R_AT, R_PrimCursor, S_(polytag_len_bits)) /* AT = (prim_length << 24) | old_addr */ \
|
||||||
|
, shift_lright(R_AT, R_AT, S_(polytag_len_bits)) \
|
||||||
|
, store_word( R_AT, R_T1, O_(PolyTag,bf_addr_len)) /* OrderingTable[OTZ] = PrimCursor */
|
||||||
|
WORD_COUNT(mac_insert_ot_tag_g4, 10)
|
||||||
|
|
||||||
#define mac_pack_color_word(off, code, r, g, b) \
|
#define mac_pack_color_word(off, code, r, g, b) \
|
||||||
load_upper_i(R_AT, (code) << 8 | (b)) \
|
load_upper_i(R_AT, (code) << 8 | (b)) \
|
||||||
@@ -70,9 +88,7 @@ WORD_COUNT(mac_pack_color_word, 3)
|
|||||||
WORD_COUNT(mac_format_f3_color, 1)
|
WORD_COUNT(mac_format_f3_color, 1)
|
||||||
|
|
||||||
/* Words: 3; Stores the 3 transformed (V2_S2 screen) vertices to the F3.
|
/* 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).
|
* PIPELINE: post-RTPT (SXY0=v0.screen, SXY1=v1.screen, SXY2=v2.screen). */
|
||||||
* The macro name declares the pipeline position; check #6 (GTE state-
|
|
||||||
* machine validation) verifies the call site matches the declaration. */
|
|
||||||
#define mac_gte_store_f3_post_rtpt(...) \
|
#define mac_gte_store_f3_post_rtpt(...) \
|
||||||
gte_sw(C2_SXY0, R_PrimCursor, O_(Poly_F3,p0)) \
|
gte_sw(C2_SXY0, R_PrimCursor, O_(Poly_F3,p0)) \
|
||||||
, gte_sw(C2_SXY1, R_PrimCursor, O_(Poly_F3,p1)) \
|
, gte_sw(C2_SXY1, R_PrimCursor, O_(Poly_F3,p1)) \
|
||||||
@@ -105,14 +121,7 @@ WORD_COUNT(mac_gte_store_g4_p012_post_rtpt_pre_rtps, 3)
|
|||||||
* single-vertex result to SXY2; SXY0 still holds v0.screen from the
|
* single-vertex result to SXY2; SXY0 still holds v0.screen from the
|
||||||
* earlier RTPT — DO NOT read SXY0 here, that's the bug this name
|
* earlier RTPT — DO NOT read SXY0 here, that's the bug this name
|
||||||
* prevents).
|
* prevents).
|
||||||
* The macro name declares the pipeline position; check #6 (GTE state-
|
*/
|
||||||
* machine validation) verifies the call site matches the declaration.
|
|
||||||
*
|
|
||||||
* History: this macro was named `mac_gte_store_g4_p3` until 2026-07-09
|
|
||||||
* when it was discovered to be reading C2_SXY0 (which held v0.screen)
|
|
||||||
* instead of C2_SXY2 (which holds v3.screen after RTPS). The rename
|
|
||||||
* encodes the pipeline position in the name so the next bug of this
|
|
||||||
* class is impossible. */
|
|
||||||
#define mac_gte_store_g4_p3_post_rtps(...) \
|
#define mac_gte_store_g4_p3_post_rtps(...) \
|
||||||
gte_sw(C2_SXY2, R_PrimCursor, O_(Poly_G4,p3))
|
gte_sw(C2_SXY2, R_PrimCursor, O_(Poly_G4,p3))
|
||||||
WORD_COUNT(mac_gte_store_g4_p3_post_rtps, 1)
|
WORD_COUNT(mac_gte_store_g4_p3_post_rtps, 1)
|
||||||
|
|||||||
+18
-29
@@ -28,9 +28,8 @@ typedef Slice_MipsCode MipsAtom;
|
|||||||
// FI_ MipsAtom ac_X(args) { MipsCode ac_X[] align_(4) = { body }; return slice_from_array(MipsCode, ac_X); }
|
// FI_ MipsAtom ac_X(args) { MipsCode ac_X[] align_(4) = { body }; return slice_from_array(MipsCode, ac_X); }
|
||||||
#define MipsAtomComp_Proc_(sym, ...) { MipsCode sym [] align_(4) = __VA_ARGS__; return slice_from_array(MipsCode, sym); }
|
#define MipsAtomComp_Proc_(sym, ...) { MipsCode sym [] align_(4) = __VA_ARGS__; return slice_from_array(MipsCode, sym); }
|
||||||
|
|
||||||
// Auto-generated component macros (build/gen/<dir>/<dir>.components.h)
|
// Auto-generated component macros (<module>/gen/<dir>/<dir>.macs.h)
|
||||||
// are included manually by the unity build. The metaprogram puts them
|
// are included manually by the unity build. The metaprogram puts them
|
||||||
// under ./build/gen/ (not in the code dirs) so the source tree stays clean.
|
|
||||||
|
|
||||||
/* Register aliases (moved up from the Tape Drive region below so that
|
/* Register aliases (moved up from the Tape Drive region below so that
|
||||||
* mac_yield's body and the Mips Atom Builder functions can reference
|
* mac_yield's body and the Mips Atom Builder functions can reference
|
||||||
@@ -137,9 +136,9 @@ MipsAtomComp_(ac_load_tri_verts) {
|
|||||||
/* Words: 11; Correctly inserts a primitive into the Ordering Table linked list.
|
/* Words: 11; Correctly inserts a primitive into the Ordering Table linked list.
|
||||||
* Hardcoded for Poly_F3 (5 words). For Poly_G4, use ac_insert_ot_tag_g4. */
|
* Hardcoded for Poly_F3 (5 words). For Poly_G4, use ac_insert_ot_tag_g4. */
|
||||||
MipsAtomComp_(ac_insert_ot_tag_f3) {
|
MipsAtomComp_(ac_insert_ot_tag_f3) {
|
||||||
shift_lleft( R_T1, R_T1, S_(U4)/2) /* T1 = otz * S_(U4) (otz arg is implicit R_T1) */
|
shift_lleft( R_T1, R_T1, S_(U4)/2) // T1 = otz * S_(U4) (otz arg is implicit R_T1)
|
||||||
, add_u_self( R_T1, R_OtBase) /* T1 = & OrderingTable[OTZ] */
|
, add_u_self( R_T1, R_OtBase) // T1 = & OrderingTable[OTZ]
|
||||||
, load_word( R_AT, R_T1, O_(PolyTag,bf_addr_len)) /* AT = old_ot_head */
|
, load_word( R_AT, R_T1, O_(PolyTag,bf_addr_len)) // AT = old_ot_head
|
||||||
, load_upper_i(R_V0, (S_(Poly_F3)/S_(U4) - S_(PolyTag)/S_(U4)) << polytag_len_bits) /* V0 = (5 - 1) << 24 = 4 << 24 */
|
, load_upper_i(R_V0, (S_(Poly_F3)/S_(U4) - S_(PolyTag)/S_(U4)) << polytag_len_bits) /* V0 = (5 - 1) << 24 = 4 << 24 */
|
||||||
, mask_upper( R_AT, R_AT, S_(polytag_len_bits)) /* Strip upper 8 bits (length from prev cell) → keep only low 24 */
|
, mask_upper( R_AT, R_AT, S_(polytag_len_bits)) /* Strip upper 8 bits (length from prev cell) → keep only low 24 */
|
||||||
, or_u( R_AT, R_AT, R_V0) /* Merge length */
|
, or_u( R_AT, R_AT, R_V0) /* Merge length */
|
||||||
@@ -177,17 +176,14 @@ MipsAtomComp_Proc_(ac_pack_color_word, {
|
|||||||
|
|
||||||
/* Words: 3; Emits the F3 command+color word (cmd byte | BLUE | GREEN | RED)
|
/* Words: 3; Emits the F3 command+color word (cmd byte | BLUE | GREEN | RED)
|
||||||
* Args: _r, _g, _b are 8-bit RGB byte values (not raw 16-bit fields).
|
* Args: _r, _g, _b are 8-bit RGB byte values (not raw 16-bit fields).
|
||||||
* Migrated from hello_gte_tape.c; takes RGB form per the Phase 3
|
* Migrated from hello_gte_tape.c; takes RGB form per the Phase 3 convention. */
|
||||||
* convention. */
|
|
||||||
FI_ MipsAtom ac_format_f3_color(U1 r, U1 g, U1 b)
|
FI_ MipsAtom ac_format_f3_color(U1 r, U1 g, U1 b)
|
||||||
MipsAtomComp_Proc_(ac_format_f3_color, {
|
MipsAtomComp_Proc_(ac_format_f3_color, {
|
||||||
mac_pack_color_word(O_(Poly_F3,color), gp0_cmd_poly_f3, r, g, b)
|
mac_pack_color_word(O_(Poly_F3,color), gp0_cmd_poly_f3, r, g, b)
|
||||||
})
|
})
|
||||||
|
|
||||||
/* Words: 3; Stores the 3 transformed (V2_S2 screen) vertices to the F3.
|
/* 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).
|
* PIPELINE: post-RTPT (SXY0=v0.screen, SXY1=v1.screen, SXY2=v2.screen). */
|
||||||
* The macro name declares the pipeline position; check #6 (GTE state-
|
|
||||||
* machine validation) verifies the call site matches the declaration. */
|
|
||||||
MipsAtomComp_(ac_gte_store_f3_post_rtpt) {
|
MipsAtomComp_(ac_gte_store_f3_post_rtpt) {
|
||||||
gte_sw(C2_SXY0, R_PrimCursor, O_(Poly_F3,p0))
|
gte_sw(C2_SXY0, R_PrimCursor, O_(Poly_F3,p0))
|
||||||
, gte_sw(C2_SXY1, R_PrimCursor, O_(Poly_F3,p1))
|
, gte_sw(C2_SXY1, R_PrimCursor, O_(Poly_F3,p1))
|
||||||
@@ -196,7 +192,8 @@ MipsAtomComp_(ac_gte_store_f3_post_rtpt) {
|
|||||||
|
|
||||||
/* Words: 12; Emits the four (code|color) words of a Poly_G4.
|
/* Words: 12; Emits the four (code|color) words of a Poly_G4.
|
||||||
* Args: rN,gN,bN are 8-bit RGB byte values for each of the 4 vertices. */
|
* Args: rN,gN,bN are 8-bit RGB byte values for each of the 4 vertices. */
|
||||||
FI_ MipsAtom ac_format_g4_color(U1 r0, U1 g0, U1 b0,
|
FI_ MipsAtom ac_format_g4_color(
|
||||||
|
U1 r0, U1 g0, U1 b0,
|
||||||
U1 r1, U1 g1, U1 b1,
|
U1 r1, U1 g1, U1 b1,
|
||||||
U1 r2, U1 g2, U1 b2,
|
U1 r2, U1 g2, U1 b2,
|
||||||
U1 r3, U1 g3, U1 b3)
|
U1 r3, U1 g3, U1 b3)
|
||||||
@@ -226,14 +223,7 @@ MipsAtomComp_(ac_gte_store_g4_p012_post_rtpt_pre_rtps) {
|
|||||||
* single-vertex result to SXY2; SXY0 still holds v0.screen from the
|
* single-vertex result to SXY2; SXY0 still holds v0.screen from the
|
||||||
* earlier RTPT — DO NOT read SXY0 here, that's the bug this name
|
* earlier RTPT — DO NOT read SXY0 here, that's the bug this name
|
||||||
* prevents).
|
* prevents).
|
||||||
* The macro name declares the pipeline position; check #6 (GTE state-
|
*/
|
||||||
* machine validation) verifies the call site matches the declaration.
|
|
||||||
*
|
|
||||||
* History: this macro was named `mac_gte_store_g4_p3` until 2026-07-09
|
|
||||||
* when it was discovered to be reading C2_SXY0 (which held v0.screen)
|
|
||||||
* instead of C2_SXY2 (which holds v3.screen after RTPS). The rename
|
|
||||||
* encodes the pipeline position in the name so the next bug of this
|
|
||||||
* class is impossible. */
|
|
||||||
MipsAtomComp_(ac_gte_store_g4_p3_post_rtps) {
|
MipsAtomComp_(ac_gte_store_g4_p3_post_rtps) {
|
||||||
gte_sw(C2_SXY2, R_PrimCursor, O_(Poly_G4,p3))
|
gte_sw(C2_SXY2, R_PrimCursor, O_(Poly_G4,p3))
|
||||||
};
|
};
|
||||||
@@ -277,7 +267,6 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Flushes the Instruction Cache (PSX A-function 0x44 via BIOS stub at 0xA0).
|
/* Flushes the Instruction Cache (PSX A-function 0x44 via BIOS stub at 0xA0).
|
||||||
*
|
|
||||||
* Sequence (per MIPS ABI; arguments in arg registers, RA pushed to stack):
|
* Sequence (per MIPS ABI; arguments in arg registers, RA pushed to stack):
|
||||||
* 1. sp -= 8; sw $ra, 4($sp) ; save RA
|
* 1. sp -= 8; sw $ra, 4($sp) ; save RA
|
||||||
* 2. $a0 = bios_flushcache (arg0)
|
* 2. $a0 = bios_flushcache (arg0)
|
||||||
@@ -288,15 +277,15 @@ enum {
|
|||||||
* 6. sp += 8
|
* 6. sp += 8
|
||||||
*/
|
*/
|
||||||
internal MipsAtom_(mips_flush_icache) {
|
internal MipsAtom_(mips_flush_icache) {
|
||||||
add_ui(rstack_ptr, rstack_ptr, -MipsStackAlignment) /* sp -= 8 */
|
add_ui(rstack_ptr, rstack_ptr, -MipsStackAlignment) // sp -= 8
|
||||||
, store_word(rret_addr, rstack_ptr, S_(U4)) /* sw $ra, 4($sp) */
|
, store_word(rret_addr, rstack_ptr, S_(U4)) // sw $ra, 4($sp)
|
||||||
, add_ui(rret_0, rdiscard, bios_flushcache) /* addiu $a0, $0, 0x44 */
|
, add_ui(rret_0, rdiscard, bios_flushcache) // addiu $a0, $0, 0x44
|
||||||
, add_ui(rtmp_0, rdiscard, bios_table_addr) /* addiu $t0, $0, 0xA0 */
|
, add_ui(rtmp_0, rdiscard, bios_table_addr) // addiu $t0, $0, 0xA0
|
||||||
, jump_link(rtmp_0, rret_addr) /* jalr $t0, $ra */
|
, jump_link(rtmp_0, rret_addr) // jalr $t0, $ra
|
||||||
, nop /* BD slot */
|
, nop // BD slot
|
||||||
, load_word(rret_addr, rstack_ptr, S_(U4)) /* lw $ra, 4($sp) */
|
, load_word(rret_addr, rstack_ptr, S_(U4)) // lw $ra, 4($sp)
|
||||||
, jump_reg(rret_addr) /* jr $ra */
|
, jump_reg(rret_addr) // jr $ra
|
||||||
, add_ui(rstack_ptr, rstack_ptr, MipsStackAlignment) /* sp += 8 (BD) */
|
, add_ui(rstack_ptr, rstack_ptr, MipsStackAlignment) // sp += 8 (BD)
|
||||||
, mac_yield()
|
, mac_yield()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
#pragma region hello_gte_tape
|
#pragma region hello_gte_tape
|
||||||
|
|
||||||
|
|
||||||
// --- atom: cube_g4_face (44 words) ---
|
// --- atom: cube_g4_face (42 words) ---
|
||||||
|
|
||||||
#define _atom_offset_cull_cube_g4_face_exit 25
|
#define _atom_offset_cull_cube_g4_face_exit 26
|
||||||
#define _atom_offset_bounds_chk_cube_g4_face_exit 2
|
#define _atom_offset_bounds_chk_cube_g4_face_exit 2
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -15,9 +15,9 @@ enum {
|
|||||||
atom_offset_bounds_chk_cube_g4_face_exit = _atom_offset_bounds_chk_cube_g4_face_exit,
|
atom_offset_bounds_chk_cube_g4_face_exit = _atom_offset_bounds_chk_cube_g4_face_exit,
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- atom: floor_f3_face (30 words) ---
|
// --- atom: floor_f3_face (47 words) ---
|
||||||
|
|
||||||
#define _atom_offset_culling_floor_f3_face_exit 15
|
#define _atom_offset_culling_floor_f3_face_exit 14
|
||||||
#define _atom_offset_bounds_chk_floor_f3_face_exit 3
|
#define _atom_offset_bounds_chk_floor_f3_face_exit 3
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
# include "tape_atom.metadata.h"
|
# include "tape_atom.metadata.h"
|
||||||
# include "gen/gte_hello.offsets.h"
|
# include "gen/gte_hello.offsets.h"
|
||||||
#include "hello_gte.h"
|
#include "hello_gte.h"
|
||||||
|
|
||||||
#include "hello_gte_tape.c"
|
#include "hello_gte_tape.c"
|
||||||
|
|
||||||
typedef U4 OrderingTable_Buffer[OrderingTbl_Len];
|
typedef U4 OrderingTable_Buffer[OrderingTbl_Len];
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
# include "duffle/atom_dsl.h"
|
# include "duffle/atom_dsl.h"
|
||||||
# include "duffle/lottes_tape.h"
|
# include "duffle/lottes_tape.h"
|
||||||
# include "tape_atom.metadata.h"
|
# include "tape_atom.metadata.h"
|
||||||
|
# include "gen/gte_hello.offsets.h"
|
||||||
# include "hello_gte.h"
|
# include "hello_gte.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -345,7 +345,10 @@ function M.split_top_level_commas(body)
|
|||||||
token_start = i
|
token_start = i
|
||||||
else
|
else
|
||||||
local nx = M.skip_str_or_cmt(body, i)
|
local nx = M.skip_str_or_cmt(body, i)
|
||||||
if nx > i then i = nx; token_start = nx else i = i + 1 end
|
-- 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.
|
||||||
|
if nx > i then i = nx else i = i + 1 end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local last = body:sub(token_start)
|
local last = body:sub(token_start)
|
||||||
|
|||||||
@@ -432,7 +432,29 @@ local function main(args)
|
|||||||
os.exit(1)
|
os.exit(1)
|
||||||
end
|
end
|
||||||
local word_counts = load_word_counts(args[1])
|
local word_counts = load_word_counts(args[1])
|
||||||
for i = 2, #args do process_source(args[i], word_counts) end
|
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
|
||||||
|
for name, count in pairs(mc) do
|
||||||
|
word_counts[name] = count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
process_source(source_path, word_counts)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
main({...})
|
main({...})
|
||||||
@@ -588,12 +588,12 @@ end
|
|||||||
|
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
-- Find the args of the function declaration that immediately precedes
|
-- Find the args of the function declaration that immediately precedes
|
||||||
-- a MipsAtomComponent_ invocation of the given name. Returns the
|
-- a MipsAtomComp_Proc_ invocation of the given name. Returns the
|
||||||
-- args string (e.g., "U4 off, U4 code, U1 r, U1 g, U1 b") or nil
|
-- args string (e.g., "U4 off, U4 code, U1 r, U1 g, U1 b") or nil
|
||||||
-- if no function declaration is found.
|
-- if no function declaration is found.
|
||||||
--
|
--
|
||||||
-- Convention: function form is
|
-- Convention: function form is
|
||||||
-- FI_ MipsAtom ac_X(args) MipsAtomComponent_(ac_X, { body })
|
-- FI_ MipsAtom ac_X(args) MipsAtomComp_Proc_(ac_X, { body })
|
||||||
-- We find the LAST occurrence of "ac_X(" before before_pos and
|
-- We find the LAST occurrence of "ac_X(" before before_pos and
|
||||||
-- extract the args from inside the parens.
|
-- extract the args from inside the parens.
|
||||||
--
|
--
|
||||||
@@ -644,7 +644,7 @@ end
|
|||||||
-- `source`. Returns the comment text (with the `/* */` or `//` markers
|
-- `source`. Returns the comment text (with the `/* */` or `//` markers
|
||||||
-- preserved) or an empty string if no comment is adjacent.
|
-- preserved) or an empty string if no comment is adjacent.
|
||||||
-- Used to copy signature comments from the source declaration
|
-- Used to copy signature comments from the source declaration
|
||||||
-- (`MipsAtomComponent_` / function decl) over to the generated
|
-- (`MipsAtomComp_` / `MipsAtomComp_Proc_` / function decl) over to the generated
|
||||||
-- `mac_X` macro, so LSP/IntelliSense displays the args doc.
|
-- `mac_X` macro, so LSP/IntelliSense displays the args doc.
|
||||||
-- No regex (per the no_regex constraint).
|
-- No regex (per the no_regex constraint).
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
@@ -759,10 +759,10 @@ local function extract_arg_names(args_str)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
-- Find every MipsAtomComponent_(ac_<X>) { body } declaration in source.
|
-- Find every MipsAtomComp_(ac_<X>) { body } declaration in source.
|
||||||
-- Supports BOTH the bare form and the function form:
|
-- Supports BOTH the bare form and the function form:
|
||||||
-- Bare: MipsAtomComponent_(ac_X) { body }
|
-- Bare: MipsAtomComp_(ac_X) { body }
|
||||||
-- Function: MipsAtomComponent_(ac_X, { body }) (with a preceding
|
-- Function: MipsAtomComp_Proc_(ac_X, { body }) (with a preceding
|
||||||
-- "FI_ MipsAtom ac_X(args)" function declaration)
|
-- "FI_ MipsAtom ac_X(args)" function declaration)
|
||||||
-- Returns: {line, name, body, args} where args is the function-args
|
-- Returns: {line, name, body, args} where args is the function-args
|
||||||
-- string (or nil for the bare form).
|
-- string (or nil for the bare form).
|
||||||
@@ -853,10 +853,45 @@ end
|
|||||||
|
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
-- Emit a per-directory generated header with mac_X(...) macros
|
-- Emit a per-directory generated header with mac_X(...) macros
|
||||||
-- derived from MipsAtomComponent_ declarations + auto word-counts.
|
-- derived from MipsAtomComp_ declarations + auto word-counts.
|
||||||
-- Output: <source_dir>/gen/<dir_basename>.components.h
|
-- Output: <source_dir>/gen/<dir_basename>.components.h
|
||||||
-- ============================================================
|
-- ============================================================
|
||||||
|
|
||||||
|
-- Convert `//` line comments to `/* */` block comments in a token.
|
||||||
|
-- C macros use `\` line-continuations; a `//` comment before `\` would
|
||||||
|
-- consume the continuation, breaking the macro. We convert `//` to
|
||||||
|
-- `/* */` so the multi-line macro structure is preserved.
|
||||||
|
-- Skips `//` sequences that are inside string or character literals
|
||||||
|
-- (a rough heuristic — sufficient for component bodies which don't
|
||||||
|
-- have those constructs).
|
||||||
|
local function convert_line_comments_to_block(s)
|
||||||
|
local result = s
|
||||||
|
local i = 1
|
||||||
|
while i <= #result do
|
||||||
|
local c = result:byte(i)
|
||||||
|
if c == 47 and i + 1 <= #result and result:byte(i + 1) == 47 then
|
||||||
|
-- Found `//`. Find end of line.
|
||||||
|
local eol = i
|
||||||
|
while eol <= #result and result:byte(eol) ~= 10 do
|
||||||
|
eol = eol + 1
|
||||||
|
end
|
||||||
|
local before = result:sub(1, i - 1)
|
||||||
|
local comment = result:sub(i + 2, eol - 1) -- skip the `//`
|
||||||
|
local after
|
||||||
|
if eol <= #result and result:byte(eol) == 10 then
|
||||||
|
after = " */" .. result:sub(eol) -- keep the newline
|
||||||
|
else
|
||||||
|
after = " */"
|
||||||
|
end
|
||||||
|
result = before .. "/*" .. comment .. after
|
||||||
|
i = #before + 2 + #comment + 3 -- skip past converted comment
|
||||||
|
else
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
local function emit_component_macros_h(source_path, components)
|
local function emit_component_macros_h(source_path, components)
|
||||||
if #components == 0 then return end
|
if #components == 0 then return end
|
||||||
|
|
||||||
@@ -894,7 +929,7 @@ local function emit_component_macros_h(source_path, components)
|
|||||||
|
|
||||||
for _, c in ipairs(components) do
|
for _, c in ipairs(components) do
|
||||||
-- Emit the signature comment (if any) above the macro.
|
-- Emit the signature comment (if any) above the macro.
|
||||||
-- This is the same comment that preceded the MipsAtomComponent_
|
-- This is the same comment that preceded the MipsAtomComp_
|
||||||
-- declaration in the source; LSP/IntelliSense shows it on the
|
-- declaration in the source; LSP/IntelliSense shows it on the
|
||||||
-- generated mac_X macro.
|
-- generated mac_X macro.
|
||||||
if c.comment and c.comment ~= "" then
|
if c.comment and c.comment ~= "" then
|
||||||
@@ -922,6 +957,14 @@ local function emit_component_macros_h(source_path, components)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if n > 0 then
|
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
|
||||||
|
tokens[j] = convert_line_comments_to_block(tokens[j])
|
||||||
|
end
|
||||||
-- Emit the mac_<X>(<sig>) macro
|
-- Emit the mac_<X>(<sig>) macro
|
||||||
lines[#lines + 1] = "#define mac_" .. c.name .. "(" .. sig .. ") \\"
|
lines[#lines + 1] = "#define mac_" .. c.name .. "(" .. sig .. ") \\"
|
||||||
lines[#lines + 1] = "\t" .. tokens[1] .. " \\"
|
lines[#lines + 1] = "\t" .. tokens[1] .. " \\"
|
||||||
@@ -1431,8 +1474,8 @@ local function main(args)
|
|||||||
-- emitted ones, if any, get pruned below.
|
-- emitted ones, if any, get pruned below.
|
||||||
local has_atoms = #result.atoms > 0
|
local has_atoms = #result.atoms > 0
|
||||||
|
|
||||||
print(string.format("[pass] %s%s", source_path,
|
-- print(string.format("[pass] %s%s", source_path,
|
||||||
has_atoms and "" or " (no atoms - skip report)"))
|
-- has_atoms and "" or " (no atoms - skip report)"))
|
||||||
|
|
||||||
if has_atoms then
|
if has_atoms then
|
||||||
ensure_dir(out_dir)
|
ensure_dir(out_dir)
|
||||||
@@ -1471,7 +1514,7 @@ local function main(args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Emit the per-directory component-macros header (gen/<dir>.components.h)
|
-- Emit the per-directory component-macros header (gen/<dir>.components.h)
|
||||||
-- if this source has any MipsAtomComponent_ declarations. Independent of
|
-- if this source has any MipsAtomComp_ declarations. Independent of
|
||||||
-- has_atoms: a header can have components without having full atoms.
|
-- has_atoms: a header can have components without having full atoms.
|
||||||
-- (TODO: pass source text into validate() to avoid the double-read.)
|
-- (TODO: pass source text into validate() to avoid the double-read.)
|
||||||
local source_text = duffle.read_file(source_path)
|
local source_text = duffle.read_file(source_path)
|
||||||
|
|||||||
Reference in New Issue
Block a user