1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-12-24 04:31:02 +00:00

Added Atari XL/XE platform target generating a simple XEX-file. Closes #499

This commit is contained in:
jespergravgaard 2020-08-06 10:57:27 +02:00
parent a7359f8395
commit 392ab7e442
9 changed files with 532 additions and 6 deletions

View File

@ -766,12 +766,6 @@ class AsmFragmentTemplateSynthesisRule {
// Rewrite (Z1),x to save Y to $FF and reload it into YY
synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuxx=(.*)", twoZM1, "stx $ff" , "vb$1aa=$2", "ldz $ff\nsta ({z1}),z", mapZM1));
// TODO: Rewrite (Z1),y assignment to use A
//synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuyy=(.*)", twoZM1+"|"+rvalYy, null , "vb$1aa=$2", "sta ({z1}),y", null, "yy"));
//if(targetCpu.getCpu65xx().hasRegisterZ())
// Rewrite (Z1),z assignment to use A
// synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuzz=(.*)", twoZM1+"|"+rvalZz, null , "vb$1aa=$2", "sta ({z1}),z", null, "zz"));
// Rewrite (Z1),a to use TAY prefix
synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuaa=(.*)", twoZM1+"|"+rvalYy, "tay" , "vb$1aa=$2", "sta ({z1}),y", mapZM1, "yy"));
if(targetCpu.getCpu65xx().hasRegisterZ())

View File

@ -0,0 +1,22 @@
// Atari XL/XE XEX file minimal file
// https://www.atarimax.com/jindroush.atari.org/afmtexe.html
.file [name="%O", type="bin", segments="XexFile"]
.segmentdef Program [segments="ProgramStart, Code, Data, ProgramEnd"]
.segmentdef ProgramStart [start=$2000]
.segmentdef Code [startAfter="ProgramStart"]
.segmentdef Data [startAfter="Code"]
.segmentdef ProgramEnd [startAfter="Data"]
.segment ProgramStart
ProgramStart:
.segment ProgramEnd
ProgramEnd:
.segmentdef XexFile
.segment XexFile
// Binary File Header
.byte $ff, $ff
// Program segment [start address, end address, data]
.word ProgramStart, ProgramEnd
.segmentout [ segments="Program" ]
// RunAd - Run Address Segment [start address, end address, data]
.word $02e0, $02e1
.word %E

View File

@ -0,0 +1,9 @@
{
"extension": "xex",
"link": "atarixl.ld",
"cpu": "MOS6502X",
"emulator": "65XEDebugger",
"defines": {
"__ATARIXL__": 1
}
}

View File

@ -192,6 +192,11 @@ public class TestPrograms {
compileAndCompare("examples/nes-demo/nes-demo.c");
}
@Test
public void testAtariXlHello() throws IOException, URISyntaxException {
compileAndCompare("examples/atarixl/helloxl.c");
}
@Test
public void testAtari2600Sprites() throws IOException, URISyntaxException {
compileAndCompare("examples/atari2600/atari2600-sprites.c");

View File

@ -0,0 +1,64 @@
// Hello World for Atari XL / XE
// XEX file format https://www.atarimax.com/jindroush.atari.org/afmtexe.html
// Minimal Hello World https://atariage.com/forums/topic/229742-help-with-hello-world-in-mads/
// Display Lists atariarchives.org/mapping/appendix8.php
#pragma target(atarixl)
// Direct Memory Access Control
// 7 6 5 4 3 2 1 0
// - - - - - - 0 0 No playfield
// - - - - - - 0 1 Narrow playfield (128 color clocks 32 characters)
// - - - - - - 1 0 Standard playfield (160 color clocks 40 characters) (default)
// - - - - - - 1 1 Wide playfield (192 color clocks 48 characters)
// - - - - - 1 - - Enable missle DMA
// - - - - 1 - - - Enable player DMA
// - - - 1 - - - - One line player resolution
// - - - 0 - - - - Two-line player resolution (default)
// - - 1 - - - - - Enable DMA for fetching the display list instructions (default)
// SHADOW: SDMCTL $022F
char * const ANTIC_DMACTL = 0xd400;
// OS Shadow ANTIC Direct Memory Access Control
char * const SDMCTL = 0x022f;
// Character Control
// 7 6 5 4 3 2 1 0
// - - - - - - - 1 Video Blank. Inverse video characters display as blanks spaces.
// - - - - - - 1 - Video Inverse. Inverse video characters appear as inverse video. (default)
// - - - - - 1 - - Video Reflect. All characters are displayed vertically mirrored.
// SHADOW: CHART $02F3
char * const ANTIC_CHACTL = 0xd401;
// OS Shadow ANTIC Character Control
char * const CHART = 0x02f3;
// Display List Pointer
// ANTIC begins executing the DisplayList pointed to by the 16-bit address in registers DLISTL/DLISTH
// SHADOW: SDLSTL/SDLSTH $0230/$0231
char ** const ANTIC_DLIST = 0xd402;
// OS Shadow ANTIC Display List Pointer
char ** const SDLST = 0x0230;
void main() {
// Enable DMA, Narrow Playfield into Shadow ANTIC Direct Memory Access Control
*SDMCTL = 0x21;
// Set Shadow ANTIC Display List Pointer
*SDLST = DISPLAY_LIST;
// Loop forever
while (1) ;
}
// Message to show
// Encoding: atari_internal
char TEXT[] = {'h'|0x20,'e'|0x20,'l'|0x20,'l'|0x20,'o'|0x20,0x0,'x'|0x60,'t'|0x60,0x0,'w'|0x20,'o'|0x20,'r'|0x20,'l'|0x20,'d'|0x20,0x41,0x0,0x0,0x0,0x0};
// ANTIC Display List Program
// https://en.wikipedia.org/wiki/ANTIC
char DISPLAY_LIST[] = {
0x70, 0x70, 0x70, // 3* BLK 8 (0x70) 8 blank lines
0x47, <TEXT, >TEXT, // LMS 7, TEXT (0x47) Load memory address and set to charmode 7 (16/20/24 chars wide, 16 lines per char)
0x41, <DISPLAY_LIST, >DISPLAY_LIST // JVB DISPLAY_LIST (0x41) jump and wait for VBLANK
};

View File

@ -0,0 +1,53 @@
// Hello World for Atari XL / XE
// XEX file format https://www.atarimax.com/jindroush.atari.org/afmtexe.html
// Minimal Hello World https://atariage.com/forums/topic/229742-help-with-hello-world-in-mads/
// Display Lists atariarchives.org/mapping/appendix8.php
// Atari XL/XE minimal XEX file
// https://www.atarimax.com/jindroush.atari.org/afmtexe.html
.file [name="helloxl.xex", type="bin", segments="XexFile"]
.segmentdef Program [segments="ProgramStart, Code, Data, ProgramEnd"]
.segmentdef ProgramStart [start=$2000]
.segmentdef Code [startAfter="ProgramStart"]
.segmentdef Data [startAfter="Code"]
.segmentdef ProgramEnd [startAfter="Data"]
.segment ProgramStart
ProgramStart:
.segment ProgramEnd
ProgramEnd:
.segmentdef XexFile
.segment XexFile
// Binary File Header
.byte $ff, $ff
// Program segment [start address, end address, data]
.word ProgramStart, ProgramEnd
.segmentout [ segments="Program" ]
// RunAd - Run Address Segment [start address, end address, data]
.word $02e0, $02e1
.word main
// OS Shadow ANTIC Direct Memory Access Control
.label SDMCTL = $22f
// OS Shadow ANTIC Display List Pointer
.label SDLST = $230
.segment Code
main: {
// *SDMCTL = 0x21
// Enable DMA, Narrow Playfield into Shadow ANTIC Direct Memory Access Control
lda #$21
sta SDMCTL
// *SDLST = DISPLAY_LIST
// Set Shadow ANTIC Display List Pointer
lda #<DISPLAY_LIST
sta SDLST
lda #>DISPLAY_LIST
sta SDLST+1
__b1:
// Loop forever
jmp __b1
}
.segment Data
// Message to show
// Encoding: atari_internal
TEXT: .byte 'h'|$20, 'e'|$20, 'l'|$20, 'l'|$20, 'o'|$20, 0, 'x'|$60, 't'|$60, 0, 'w'|$20, 'o'|$20, 'r'|$20, 'l'|$20, 'd'|$20, $41, 0, 0, 0, 0
// ANTIC Display List Program
// https://en.wikipedia.org/wiki/ANTIC
DISPLAY_LIST: .byte $70, $70, $70, $47, <TEXT, >TEXT, $41, <DISPLAY_LIST, >DISPLAY_LIST

View File

@ -0,0 +1,9 @@
(void()) main()
main: scope:[main] from
[0] *((const nomodify byte*) SDMCTL) ← (byte) $21
[1] *((const nomodify byte**) SDLST) ← (const byte*) DISPLAY_LIST
to:main::@1
main::@1: scope:[main] from main main::@1
[2] phi()
to:main::@1

View File

@ -0,0 +1,363 @@
Resolved forward reference DISPLAY_LIST to (const byte*) DISPLAY_LIST
CONTROL FLOW GRAPH SSA
(void()) main()
main: scope:[main] from __start
*((const nomodify byte*) SDMCTL) ← (number) $21
*((const nomodify byte**) SDLST) ← (const byte*) DISPLAY_LIST
to:main::@1
main::@1: scope:[main] from main main::@1
(bool~) main::$0 ← (number) 0 != (number) 1
if((bool~) main::$0) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
return
to:@return
(void()) __start()
__start: scope:[__start] from
call main
to:__start::@1
__start::@1: scope:[__start] from __start
to:__start::@return
__start::@return: scope:[__start] from __start::@1
return
to:@return
SYMBOL TABLE SSA
(const byte*) DISPLAY_LIST[] = { (byte) $70, (byte) $70, (byte) $70, (byte) $47, <(const byte*) TEXT, >(const byte*) TEXT, (byte) $41, <(const byte*) DISPLAY_LIST, >(const byte*) DISPLAY_LIST }
(const nomodify byte**) SDLST = (byte**)(number) $230
(const nomodify byte*) SDMCTL = (byte*)(number) $22f
(const byte*) TEXT[] = { (byte)(byte) 'h'|(number) $20, (byte)(byte) 'e'|(number) $20, (byte)(byte) 'l'|(number) $20, (byte)(byte) 'l'|(number) $20, (byte)(byte) 'o'|(number) $20, (byte) 0, (byte)(byte) 'x'|(number) $60, (byte)(byte) 't'|(number) $60, (byte) 0, (byte)(byte) 'w'|(number) $20, (byte)(byte) 'o'|(number) $20, (byte)(byte) 'r'|(number) $20, (byte)(byte) 'l'|(number) $20, (byte)(byte) 'd'|(number) $20, (byte) $41, (byte) 0, (byte) 0, (byte) 0, (byte) 0 }
(void()) __start()
(label) __start::@1
(label) __start::@return
(void()) main()
(bool~) main::$0
(label) main::@1
(label) main::@return
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $60 in
Adding number conversion cast (unumber) $60 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $20 in
Adding number conversion cast (unumber) $21 in *((const nomodify byte*) SDMCTL) ← (number) $21
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast *((const nomodify byte*) SDMCTL) ← (unumber)(number) $21
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 559
Simplifying constant pointer cast (byte**) 560
Simplifying constant integer cast $20
Simplifying constant integer cast $20
Simplifying constant integer cast $20
Simplifying constant integer cast $20
Simplifying constant integer cast $20
Simplifying constant integer cast $60
Simplifying constant integer cast $60
Simplifying constant integer cast $20
Simplifying constant integer cast $20
Simplifying constant integer cast $20
Simplifying constant integer cast $20
Simplifying constant integer cast $20
Simplifying constant integer cast $21
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $60
Finalized unsigned number type (byte) $60
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $20
Finalized unsigned number type (byte) $21
Successful SSA optimization PassNFinalizeNumberTypeConversions
Simple Condition (bool~) main::$0 [3] if((number) 0!=(number) 1) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
if() condition always true - replacing block destination [3] if((number) 0!=(number) 1) goto main::@1
Successful SSA optimization Pass2ConstantIfs
Removing unused block main::@return
Successful SSA optimization Pass2EliminateUnusedBlocks
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::@1
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
Simplifying constant integer cast (byte) 'h'|(byte) $20
Simplifying constant integer cast (byte) 'e'|(byte) $20
Simplifying constant integer cast (byte) 'l'|(byte) $20
Simplifying constant integer cast (byte) 'l'|(byte) $20
Simplifying constant integer cast (byte) 'o'|(byte) $20
Simplifying constant integer cast (byte) 'x'|(byte) $60
Simplifying constant integer cast (byte) 't'|(byte) $60
Simplifying constant integer cast (byte) 'w'|(byte) $20
Simplifying constant integer cast (byte) 'o'|(byte) $20
Simplifying constant integer cast (byte) 'r'|(byte) $20
Simplifying constant integer cast (byte) 'l'|(byte) $20
Simplifying constant integer cast (byte) 'd'|(byte) $20
Successful SSA optimization PassNCastSimplification
Adding NOP phi() at start of main::@1
CALL GRAPH
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Adding NOP phi() at start of main::@1
FINAL CONTROL FLOW GRAPH
(void()) main()
main: scope:[main] from
[0] *((const nomodify byte*) SDMCTL) ← (byte) $21
[1] *((const nomodify byte**) SDLST) ← (const byte*) DISPLAY_LIST
to:main::@1
main::@1: scope:[main] from main main::@1
[2] phi()
to:main::@1
VARIABLE REGISTER WEIGHTS
(void()) main()
Initial phi equivalence classes
Complete equivalence classes
INITIAL ASM
Target platform is atarixl / MOS6502X
// File Comments
// Hello World for Atari XL / XE
// XEX file format https://www.atarimax.com/jindroush.atari.org/afmtexe.html
// Minimal Hello World https://atariage.com/forums/topic/229742-help-with-hello-world-in-mads/
// Display Lists atariarchives.org/mapping/appendix8.php
// Upstart
// Atari XL/XE minimal XEX file
// https://www.atarimax.com/jindroush.atari.org/afmtexe.html
.file [name="helloxl.xex", type="bin", segments="XexFile"]
.segmentdef Program [segments="ProgramStart, Code, Data, ProgramEnd"]
.segmentdef ProgramStart [start=$2000]
.segmentdef Code [startAfter="ProgramStart"]
.segmentdef Data [startAfter="Code"]
.segmentdef ProgramEnd [startAfter="Data"]
.segment ProgramStart
ProgramStart:
.segment ProgramEnd
ProgramEnd:
.segmentdef XexFile
.segment XexFile
// Binary File Header
.byte $ff, $ff
// Program segment [start address, end address, data]
.word ProgramStart, ProgramEnd
.segmentout [ segments="Program" ]
// RunAd - Run Address Segment [start address, end address, data]
.word $02e0, $02e1
.word main
// Global Constants & labels
// OS Shadow ANTIC Direct Memory Access Control
.label SDMCTL = $22f
// OS Shadow ANTIC Display List Pointer
.label SDLST = $230
.segment Code
// main
main: {
// [0] *((const nomodify byte*) SDMCTL) ← (byte) $21 -- _deref_pbuc1=vbuc2
// Enable DMA, Narrow Playfield into Shadow ANTIC Direct Memory Access Control
lda #$21
sta SDMCTL
// [1] *((const nomodify byte**) SDLST) ← (const byte*) DISPLAY_LIST -- _deref_qbuc1=pbuc2
// Set Shadow ANTIC Display List Pointer
lda #<DISPLAY_LIST
sta SDLST
lda #>DISPLAY_LIST
sta SDLST+1
// [2] phi from main main::@1 to main::@1 [phi:main/main::@1->main::@1]
__b1_from_main:
__b1_from___b1:
jmp __b1
// Loop forever
// main::@1
__b1:
jmp __b1_from___b1
}
// File Data
.segment Data
// Message to show
// Encoding: atari_internal
TEXT: .byte 'h'|$20, 'e'|$20, 'l'|$20, 'l'|$20, 'o'|$20, 0, 'x'|$60, 't'|$60, 0, 'w'|$20, 'o'|$20, 'r'|$20, 'l'|$20, 'd'|$20, $41, 0, 0, 0, 0
// ANTIC Display List Program
// https://en.wikipedia.org/wiki/ANTIC
DISPLAY_LIST: .byte $70, $70, $70, $47, <TEXT, >TEXT, $41, <DISPLAY_LIST, >DISPLAY_LIST
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *((const nomodify byte*) SDMCTL) ← (byte) $21 [ ] ( [ ] { } ) always clobbers reg byte a
Statement [1] *((const nomodify byte**) SDLST) ← (const byte*) DISPLAY_LIST [ ] ( [ ] { } ) always clobbers reg byte a
REGISTER UPLIFT SCOPES
Uplift Scope [main]
Uplift Scope []
Uplifting [main] best 78 combination
Uplifting [] best 78 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Hello World for Atari XL / XE
// XEX file format https://www.atarimax.com/jindroush.atari.org/afmtexe.html
// Minimal Hello World https://atariage.com/forums/topic/229742-help-with-hello-world-in-mads/
// Display Lists atariarchives.org/mapping/appendix8.php
// Upstart
// Atari XL/XE minimal XEX file
// https://www.atarimax.com/jindroush.atari.org/afmtexe.html
.file [name="helloxl.xex", type="bin", segments="XexFile"]
.segmentdef Program [segments="ProgramStart, Code, Data, ProgramEnd"]
.segmentdef ProgramStart [start=$2000]
.segmentdef Code [startAfter="ProgramStart"]
.segmentdef Data [startAfter="Code"]
.segmentdef ProgramEnd [startAfter="Data"]
.segment ProgramStart
ProgramStart:
.segment ProgramEnd
ProgramEnd:
.segmentdef XexFile
.segment XexFile
// Binary File Header
.byte $ff, $ff
// Program segment [start address, end address, data]
.word ProgramStart, ProgramEnd
.segmentout [ segments="Program" ]
// RunAd - Run Address Segment [start address, end address, data]
.word $02e0, $02e1
.word main
// Global Constants & labels
// OS Shadow ANTIC Direct Memory Access Control
.label SDMCTL = $22f
// OS Shadow ANTIC Display List Pointer
.label SDLST = $230
.segment Code
// main
main: {
// [0] *((const nomodify byte*) SDMCTL) ← (byte) $21 -- _deref_pbuc1=vbuc2
// Enable DMA, Narrow Playfield into Shadow ANTIC Direct Memory Access Control
lda #$21
sta SDMCTL
// [1] *((const nomodify byte**) SDLST) ← (const byte*) DISPLAY_LIST -- _deref_qbuc1=pbuc2
// Set Shadow ANTIC Display List Pointer
lda #<DISPLAY_LIST
sta SDLST
lda #>DISPLAY_LIST
sta SDLST+1
// [2] phi from main main::@1 to main::@1 [phi:main/main::@1->main::@1]
__b1_from_main:
__b1_from___b1:
jmp __b1
// Loop forever
// main::@1
__b1:
jmp __b1_from___b1
}
// File Data
.segment Data
// Message to show
// Encoding: atari_internal
TEXT: .byte 'h'|$20, 'e'|$20, 'l'|$20, 'l'|$20, 'o'|$20, 0, 'x'|$60, 't'|$60, 0, 'w'|$20, 'o'|$20, 'r'|$20, 'l'|$20, 'd'|$20, $41, 0, 0, 0, 0
// ANTIC Display List Program
// https://en.wikipedia.org/wiki/ANTIC
DISPLAY_LIST: .byte $70, $70, $70, $47, <TEXT, >TEXT, $41, <DISPLAY_LIST, >DISPLAY_LIST
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __b1_from_main:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination
Relabelling long label __b1_from___b1 to __b1
Succesful ASM optimization Pass5RelabelLongLabels
FINAL SYMBOL TABLE
(const byte*) DISPLAY_LIST[] = { (byte) $70, (byte) $70, (byte) $70, (byte) $47, <(const byte*) TEXT, >(const byte*) TEXT, (byte) $41, <(const byte*) DISPLAY_LIST, >(const byte*) DISPLAY_LIST }
(const nomodify byte**) SDLST = (byte**) 560
(const nomodify byte*) SDMCTL = (byte*) 559
(const byte*) TEXT[] = { (byte) 'h'|(byte) $20, (byte) 'e'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'o'|(byte) $20, (byte) 0, (byte) 'x'|(byte) $60, (byte) 't'|(byte) $60, (byte) 0, (byte) 'w'|(byte) $20, (byte) 'o'|(byte) $20, (byte) 'r'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'd'|(byte) $20, (byte) $41, (byte) 0, (byte) 0, (byte) 0, (byte) 0 }
(void()) main()
(label) main::@1
FINAL ASSEMBLER
Score: 48
// File Comments
// Hello World for Atari XL / XE
// XEX file format https://www.atarimax.com/jindroush.atari.org/afmtexe.html
// Minimal Hello World https://atariage.com/forums/topic/229742-help-with-hello-world-in-mads/
// Display Lists atariarchives.org/mapping/appendix8.php
// Upstart
// Atari XL/XE minimal XEX file
// https://www.atarimax.com/jindroush.atari.org/afmtexe.html
.file [name="helloxl.xex", type="bin", segments="XexFile"]
.segmentdef Program [segments="ProgramStart, Code, Data, ProgramEnd"]
.segmentdef ProgramStart [start=$2000]
.segmentdef Code [startAfter="ProgramStart"]
.segmentdef Data [startAfter="Code"]
.segmentdef ProgramEnd [startAfter="Data"]
.segment ProgramStart
ProgramStart:
.segment ProgramEnd
ProgramEnd:
.segmentdef XexFile
.segment XexFile
// Binary File Header
.byte $ff, $ff
// Program segment [start address, end address, data]
.word ProgramStart, ProgramEnd
.segmentout [ segments="Program" ]
// RunAd - Run Address Segment [start address, end address, data]
.word $02e0, $02e1
.word main
// Global Constants & labels
// OS Shadow ANTIC Direct Memory Access Control
.label SDMCTL = $22f
// OS Shadow ANTIC Display List Pointer
.label SDLST = $230
.segment Code
// main
main: {
// *SDMCTL = 0x21
// [0] *((const nomodify byte*) SDMCTL) ← (byte) $21 -- _deref_pbuc1=vbuc2
// Enable DMA, Narrow Playfield into Shadow ANTIC Direct Memory Access Control
lda #$21
sta SDMCTL
// *SDLST = DISPLAY_LIST
// [1] *((const nomodify byte**) SDLST) ← (const byte*) DISPLAY_LIST -- _deref_qbuc1=pbuc2
// Set Shadow ANTIC Display List Pointer
lda #<DISPLAY_LIST
sta SDLST
lda #>DISPLAY_LIST
sta SDLST+1
// [2] phi from main main::@1 to main::@1 [phi:main/main::@1->main::@1]
__b1:
// Loop forever
// main::@1
jmp __b1
}
// File Data
.segment Data
// Message to show
// Encoding: atari_internal
TEXT: .byte 'h'|$20, 'e'|$20, 'l'|$20, 'l'|$20, 'o'|$20, 0, 'x'|$60, 't'|$60, 0, 'w'|$20, 'o'|$20, 'r'|$20, 'l'|$20, 'd'|$20, $41, 0, 0, 0, 0
// ANTIC Display List Program
// https://en.wikipedia.org/wiki/ANTIC
DISPLAY_LIST: .byte $70, $70, $70, $47, <TEXT, >TEXT, $41, <DISPLAY_LIST, >DISPLAY_LIST

View File

@ -0,0 +1,7 @@
(const byte*) DISPLAY_LIST[] = { (byte) $70, (byte) $70, (byte) $70, (byte) $47, <(const byte*) TEXT, >(const byte*) TEXT, (byte) $41, <(const byte*) DISPLAY_LIST, >(const byte*) DISPLAY_LIST }
(const nomodify byte**) SDLST = (byte**) 560
(const nomodify byte*) SDMCTL = (byte*) 559
(const byte*) TEXT[] = { (byte) 'h'|(byte) $20, (byte) 'e'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'o'|(byte) $20, (byte) 0, (byte) 'x'|(byte) $60, (byte) 't'|(byte) $60, (byte) 0, (byte) 'w'|(byte) $20, (byte) 'o'|(byte) $20, (byte) 'r'|(byte) $20, (byte) 'l'|(byte) $20, (byte) 'd'|(byte) $20, (byte) $41, (byte) 0, (byte) 0, (byte) 0, (byte) 0 }
(void()) main()
(label) main::@1