From 4db533d05512eb02d0d992d77ef167bb8fde4494 Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Wed, 22 Oct 2025 10:29:12 -0500 Subject: [PATCH] vcs: atari2600-ecs.cfg, better alignment for ecs critical fit sections --- src/common/ecs/ecs.ts | 28 +++++++++++++--------------- src/worker/builder.ts | 2 +- src/worker/tools/ecs.ts | 7 +++++-- test/ecs/bigdemo.txt | 18 +++++++++--------- test/ecs/kernel2.ecs | 2 +- test/ecs/kernel2.txt | 11 +++++++---- test/ecs/music.txt | 4 +++- test/ecs/score.txt | 15 ++++++--------- test/ecs/superman.txt | 11 +++++++---- test/ecs/titles.txt | 21 +++++++++------------ 10 files changed, 61 insertions(+), 58 deletions(-) diff --git a/src/common/ecs/ecs.ts b/src/common/ecs/ecs.ts index 8aed2cc8..41639607 100644 --- a/src/common/ecs/ecs.ts +++ b/src/common/ecs/ecs.ts @@ -386,24 +386,15 @@ export class Dialect_CA65 { return `${name}__Start`; } align(value: number) { - return `.align ${value}`; - } - alignSegmentStart() { - return this.label('__ALIGNORIGIN'); + return value > 0 ? `.align ${value}` : ''; } warningIfPageCrossed(startlabel: string) { return ` -.assert >(${startlabel}) = >(*), error, "${startlabel} crosses a page boundary!"` +.assert >(${startlabel}) = >(*), warning, "${startlabel} crosses a page boundary!"` } warningIfMoreThan(bytes: number, startlabel: string) { return ` -.assert (* - ${startlabel}) <= ${bytes}, error, .sprintf("${startlabel} does not fit in ${bytes} bytes, it took %d!", (* - ${startlabel}))` - } - alignIfLessThan(bytes: number) { - return ` -.if <(* - __ALIGNORIGIN) > 256-${bytes} -.align $100 -.endif` +.assert (* - ${startlabel}) <= ${bytes}, warning, .sprintf("${startlabel} does not fit in ${bytes} bytes, it took %d!", (* - ${startlabel}))` } segment(segtype: 'rodata' | 'bss' | 'code') { if (segtype == 'bss') { @@ -1725,10 +1716,7 @@ export class EntityScope implements SourceLocated { if (allsubs.length == 0) { allsubs = [ this.dialect.segment('rodata'), - this.dialect.alignSegmentStart() ] - } else if (stats.action.fitbytes) { - allsubs.push(this.dialect.alignIfLessThan(stats.action.fitbytes)); } let subcall = this.dialect.call(stats.labels[0]); for (let label of stats.labels) { @@ -1741,8 +1729,10 @@ export class EntityScope implements SourceLocated { } } let substart = stats.labels[0]; + let alignment = this.getAlignment(stats.action.fitbytes || 0); let sublines = [ this.dialect.segment('rodata'), + this.dialect.align(alignment), this.dialect.label(substart), stats.eventcode, this.dialect.return(), @@ -1759,6 +1749,14 @@ export class EntityScope implements SourceLocated { code += allsubs.join('\n'); return code; } + getAlignment(len: number) { + if (!len) return 0; + let align = 2; + while (align < len) { + align *= 2; + } + return align; + } showStats() { for (let inst of this.instances) { // TODO? diff --git a/src/worker/builder.ts b/src/worker/builder.ts index 51c7ec88..99787948 100644 --- a/src/worker/builder.ts +++ b/src/worker/builder.ts @@ -387,7 +387,7 @@ export function fixParamsWithDefines(path: string, params) { } } // find #defines and replace them - var re = /^[;]?#define\s+(\w+)\s+(\S+)/gmi; // TODO: empty string? + var re = /^[;/]?#define\s+(\w+)\s+(\S+)/gmi; // TODO: empty string? var m; while (m = re.exec(code)) { var ident = m[1]; diff --git a/src/worker/tools/ecs.ts b/src/worker/tools/ecs.ts index d7e0f487..0de10f5b 100644 --- a/src/worker/tools/ecs.ts +++ b/src/worker/tools/ecs.ts @@ -15,6 +15,9 @@ export function assembleECS(step: BuildStep): BuildStepResult { var destpath = step.prefix + '.ca65'; if (staleFiles(step, [destpath])) { let code = getWorkFileAsString(step.path); + // TODO + step.params.cfgfile = 'atari2600-ecs.cfg'; + step.params.extra_link_files.push('atari2600-ecs.cfg'); fixParamsWithDefines(step.path, step.params); // remove crt0.o from libargs step.params.libargs = step.params.libargs.filter((arg: string) => { @@ -36,9 +39,9 @@ export function assembleECS(step: BuildStep): BuildStepResult { if (name == 'start') break; compiler.addError(`... ${name}`, obj.$loc); // TODO? } - return { errors: compiler.errors }; + return { errors: compiler.errors, listings, debuginfo }; } else if (e instanceof CompileError) { - return { errors: compiler.errors }; + return { errors: compiler.errors, listings, debuginfo }; } else { throw e; } diff --git a/test/ecs/bigdemo.txt b/test/ecs/bigdemo.txt index d3d128a3..115f3920 100644 --- a/test/ecs/bigdemo.txt +++ b/test/ecs/bigdemo.txt @@ -707,8 +707,8 @@ VecBRK: .word __BRK ;;; end action Init__main_init__1 .rodata -__ALIGNORIGIN: .rodata +.align 32 SetHorizPos__SetHorizPos__20: ; SetHorizPos routine @@ -730,10 +730,11 @@ SetHorizPos__SetHorizPos__20: rts -.assert >(SetHorizPos__SetHorizPos__20) = >(*), error, "SetHorizPos__SetHorizPos__20 crosses a page boundary!" +.assert >(SetHorizPos__SetHorizPos__20) = >(*), warning, "SetHorizPos__SetHorizPos__20 crosses a page boundary!" -.assert (* - SetHorizPos__SetHorizPos__20) <= 22, error, .sprintf("SetHorizPos__SetHorizPos__20 does not fit in 22 bytes, it took %d!", (* - SetHorizPos__SetHorizPos__20)) +.assert (* - SetHorizPos__SetHorizPos__20) <= 22, warning, .sprintf("SetHorizPos__SetHorizPos__20 does not fit in 22 bytes, it took %d!", (* - SetHorizPos__SetHorizPos__20)) .rodata +.align 256 Kernel2Sprite__kernel__31: ldy #168 @@ -814,12 +815,11 @@ Kernel2Sprite__scanline__38__DoDraw2: rts -.assert >(Kernel2Sprite__kernel__31) = >(*), error, "Kernel2Sprite__kernel__31 crosses a page boundary!" +.assert >(Kernel2Sprite__kernel__31) = >(*), warning, "Kernel2Sprite__kernel__31 crosses a page boundary!" -.if <(* - __ALIGNORIGIN) > 256-72 -.align $100 -.endif +.assert (* - Kernel2Sprite__kernel__31) <= 256, warning, .sprintf("Kernel2Sprite__kernel__31 does not fit in 256 bytes, it took %d!", (* - Kernel2Sprite__kernel__31)) .rodata +.align 128 Kernel6Digit__kernel__45: ; Display the resulting 48x8 bitmap @@ -865,9 +865,9 @@ Kernel6Digit__kernel__47__Temp = Kernel6Digit__10__tmp+13 rts -.assert >(Kernel6Digit__kernel__45) = >(*), error, "Kernel6Digit__kernel__45 crosses a page boundary!" +.assert >(Kernel6Digit__kernel__45) = >(*), warning, "Kernel6Digit__kernel__45 crosses a page boundary!" -.assert (* - Kernel6Digit__kernel__45) <= 72, error, .sprintf("Kernel6Digit__kernel__45 does not fit in 72 bytes, it took %d!", (* - Kernel6Digit__kernel__45)) +.assert (* - Kernel6Digit__kernel__45) <= 72, warning, .sprintf("Kernel6Digit__kernel__45 does not fit in 72 bytes, it took %d!", (* - Kernel6Digit__kernel__45)) FontTable: ;;; start action FontTable__FontTable__82 diff --git a/test/ecs/kernel2.ecs b/test/ecs/kernel2.ecs index c3f4d0e9..432199d9 100644 --- a/test/ecs/kernel2.ecs +++ b/test/ecs/kernel2.ecs @@ -93,7 +93,7 @@ system Kernel2Sprite iny sty VDELP1 --- - on kernel do critical with [KernelSection] + on kernel do critical fit $100 with [KernelSection] --- ldy {{(SetHorizPos__SetHorizPos__20) = >(*), error, "SetHorizPos__SetHorizPos__20 crosses a page boundary!" +.assert >(SetHorizPos__SetHorizPos__20) = >(*), warning, "SetHorizPos__SetHorizPos__20 crosses a page boundary!" -.assert (* - SetHorizPos__SetHorizPos__20) <= 22, error, .sprintf("SetHorizPos__SetHorizPos__20 does not fit in 22 bytes, it took %d!", (* - SetHorizPos__SetHorizPos__20)) +.assert (* - SetHorizPos__SetHorizPos__20) <= 22, warning, .sprintf("SetHorizPos__SetHorizPos__20 does not fit in 22 bytes, it took %d!", (* - SetHorizPos__SetHorizPos__20)) .rodata +.align 256 Kernel2Sprite__kernel__28: ldy #192 @@ -583,6 +584,8 @@ Kernel2Sprite__scanline__35__DoDraw2: rts -.assert >(Kernel2Sprite__kernel__28) = >(*), error, "Kernel2Sprite__kernel__28 crosses a page boundary!" +.assert >(Kernel2Sprite__kernel__28) = >(*), warning, "Kernel2Sprite__kernel__28 crosses a page boundary!" + +.assert (* - Kernel2Sprite__kernel__28) <= 256, warning, .sprintf("Kernel2Sprite__kernel__28 does not fit in 256 bytes, it took %d!", (* - Kernel2Sprite__kernel__28)) .endscope Main__Start = Main::__Start \ No newline at end of file diff --git a/test/ecs/music.txt b/test/ecs/music.txt index 7a8a76cf..f69dafcd 100644 --- a/test/ecs/music.txt +++ b/test/ecs/music.txt @@ -247,8 +247,8 @@ VecBRK: .word __BRK ;;; end action Init__main_init__1 .rodata -__ALIGNORIGIN: .rodata + MusicPlayer__playmusic__10: lda #<^SampleMusic @@ -260,6 +260,7 @@ MusicPlayer__playmusic__10: rts .rodata + MusicPlayer__playmusic__13: lda #(Kernel6Digit__kernel__13) = >(*), error, "Kernel6Digit__kernel__13 crosses a page boundary!" +.assert >(Kernel6Digit__kernel__13) = >(*), warning, "Kernel6Digit__kernel__13 crosses a page boundary!" -.assert (* - Kernel6Digit__kernel__13) <= 72, error, .sprintf("Kernel6Digit__kernel__13 does not fit in 72 bytes, it took %d!", (* - Kernel6Digit__kernel__13)) - -.if <(* - __ALIGNORIGIN) > 256-98 -.align $100 -.endif +.assert (* - Kernel6Digit__kernel__13) <= 72, warning, .sprintf("Kernel6Digit__kernel__13 does not fit in 72 bytes, it took %d!", (* - Kernel6Digit__kernel__13)) .rodata +.align 128 Kernel2Digit__kernel__19: lda #7 @@ -470,9 +467,9 @@ Kernel2Digit__kernel__21__Loop: rts -.assert >(Kernel2Digit__kernel__19) = >(*), error, "Kernel2Digit__kernel__19 crosses a page boundary!" +.assert >(Kernel2Digit__kernel__19) = >(*), warning, "Kernel2Digit__kernel__19 crosses a page boundary!" -.assert (* - Kernel2Digit__kernel__19) <= 98, error, .sprintf("Kernel2Digit__kernel__19 does not fit in 98 bytes, it took %d!", (* - Kernel2Digit__kernel__19)) +.assert (* - Kernel2Digit__kernel__19) <= 98, warning, .sprintf("Kernel2Digit__kernel__19 does not fit in 98 bytes, it took %d!", (* - Kernel2Digit__kernel__19)) FontTable: ;;; start action FontTable__FontTable__53 diff --git a/test/ecs/superman.txt b/test/ecs/superman.txt index c8237ace..b641ee3d 100644 --- a/test/ecs/superman.txt +++ b/test/ecs/superman.txt @@ -1063,8 +1063,8 @@ VecBRK: .word __BRK ;;; end action Init__main_init__1 .rodata -__ALIGNORIGIN: .rodata +.align 32 SetHorizPos__SetHorizPos__20: ; SetHorizPos routine @@ -1086,10 +1086,11 @@ SetHorizPos__SetHorizPos__20: rts -.assert >(SetHorizPos__SetHorizPos__20) = >(*), error, "SetHorizPos__SetHorizPos__20 crosses a page boundary!" +.assert >(SetHorizPos__SetHorizPos__20) = >(*), warning, "SetHorizPos__SetHorizPos__20 crosses a page boundary!" -.assert (* - SetHorizPos__SetHorizPos__20) <= 22, error, .sprintf("SetHorizPos__SetHorizPos__20 does not fit in 22 bytes, it took %d!", (* - SetHorizPos__SetHorizPos__20)) +.assert (* - SetHorizPos__SetHorizPos__20) <= 22, warning, .sprintf("SetHorizPos__SetHorizPos__20 does not fit in 22 bytes, it took %d!", (* - SetHorizPos__SetHorizPos__20)) .rodata +.align 256 Kernel2Sprite__kernel__31: ldy #190 @@ -1206,6 +1207,8 @@ Kernel2Sprite__scanline__42__DoDraw2: rts -.assert >(Kernel2Sprite__kernel__31) = >(*), error, "Kernel2Sprite__kernel__31 crosses a page boundary!" +.assert >(Kernel2Sprite__kernel__31) = >(*), warning, "Kernel2Sprite__kernel__31 crosses a page boundary!" + +.assert (* - Kernel2Sprite__kernel__31) <= 256, warning, .sprintf("Kernel2Sprite__kernel__31 does not fit in 256 bytes, it took %d!", (* - Kernel2Sprite__kernel__31)) .endscope Main__Start = Main::__Start \ No newline at end of file diff --git a/test/ecs/titles.txt b/test/ecs/titles.txt index 74af5118..aa581596 100644 --- a/test/ecs/titles.txt +++ b/test/ecs/titles.txt @@ -797,8 +797,8 @@ JoyButton__postframe__72__NotPressed: ;;; end action FrameLoop__start__5 .rodata -__ALIGNORIGIN: .rodata +.align 64 Kernel48Pixel__kerneldraw__58: cpx #2+1 @@ -844,14 +844,11 @@ Kernel48Pixel__kerneldraw__59____skipxhi: rts -.assert >(Kernel48Pixel__kerneldraw__58) = >(*), error, "Kernel48Pixel__kerneldraw__58 crosses a page boundary!" +.assert >(Kernel48Pixel__kerneldraw__58) = >(*), warning, "Kernel48Pixel__kerneldraw__58 crosses a page boundary!" -.assert (* - Kernel48Pixel__kerneldraw__58) <= 63, error, .sprintf("Kernel48Pixel__kerneldraw__58 does not fit in 63 bytes, it took %d!", (* - Kernel48Pixel__kerneldraw__58)) - -.if <(* - __ALIGNORIGIN) > 256-63 -.align $100 -.endif +.assert (* - Kernel48Pixel__kerneldraw__58) <= 63, warning, .sprintf("Kernel48Pixel__kerneldraw__58 does not fit in 63 bytes, it took %d!", (* - Kernel48Pixel__kerneldraw__58)) .rodata +.align 64 Kernel48Pixel__kerneldraw__63: cpx #3+1 @@ -897,9 +894,9 @@ Kernel48Pixel__kerneldraw__64____skipxhi: rts -.assert >(Kernel48Pixel__kerneldraw__63) = >(*), error, "Kernel48Pixel__kerneldraw__63 crosses a page boundary!" +.assert >(Kernel48Pixel__kerneldraw__63) = >(*), warning, "Kernel48Pixel__kerneldraw__63 crosses a page boundary!" -.assert (* - Kernel48Pixel__kerneldraw__63) <= 63, error, .sprintf("Kernel48Pixel__kerneldraw__63 does not fit in 63 bytes, it took %d!", (* - Kernel48Pixel__kerneldraw__63)) +.assert (* - Kernel48Pixel__kerneldraw__63) <= 63, warning, .sprintf("Kernel48Pixel__kerneldraw__63 does not fit in 63 bytes, it took %d!", (* - Kernel48Pixel__kerneldraw__63)) .endscope Title__Start = Title::__Start .scope Title2 @@ -1474,8 +1471,8 @@ Colors__postframe__127____exit: ;;; end action FrameLoop__start__75 .rodata -__ALIGNORIGIN: .rodata +.align 64 Kernel48Pixel__kerneldraw__111: cpx #2+1 @@ -1521,9 +1518,9 @@ Kernel48Pixel__kerneldraw__112____skipxhi: rts -.assert >(Kernel48Pixel__kerneldraw__111) = >(*), error, "Kernel48Pixel__kerneldraw__111 crosses a page boundary!" +.assert >(Kernel48Pixel__kerneldraw__111) = >(*), warning, "Kernel48Pixel__kerneldraw__111 crosses a page boundary!" -.assert (* - Kernel48Pixel__kerneldraw__111) <= 63, error, .sprintf("Kernel48Pixel__kerneldraw__111 does not fit in 63 bytes, it took %d!", (* - Kernel48Pixel__kerneldraw__111)) +.assert (* - Kernel48Pixel__kerneldraw__111) <= 63, warning, .sprintf("Kernel48Pixel__kerneldraw__111 does not fit in 63 bytes, it took %d!", (* - Kernel48Pixel__kerneldraw__111)) .endscope Title2__Start = Title2::__Start .endscope