mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-24 04:31:02 +00:00
Added #pragma resource() for resource files resource files not referenced in inline KickAsm (for instance in the linker file). Closes #664
This commit is contained in:
parent
9fc9d525cf
commit
5b7bec66e8
@ -45,6 +45,7 @@ public class CParser {
|
||||
public static final String PRAGMA_CONSTRUCTOR_FOR = "constructor_for";
|
||||
public static final String PRAGMA_INTERRUPT = "interrupt";
|
||||
public static final String PRAGMA_STRUCT_MODEL = "struct_model";
|
||||
public static final String PRAGMA_RESOURCE = "resource";
|
||||
|
||||
/** The Program. */
|
||||
private Program program;
|
||||
|
@ -294,6 +294,10 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
case CParser.PRAGMA_DATA_SEG:
|
||||
this.currentDataSegment = pragmaParamName(pragmaParamSingle(ctx));
|
||||
break;
|
||||
case CParser.PRAGMA_RESOURCE:
|
||||
String resourceFileName = pragmaParamString(pragmaParamSingle(ctx));
|
||||
addResourceFile(ctx, resourceFileName);
|
||||
break;
|
||||
case CParser.PRAGMA_START_ADDRESS:
|
||||
Number startAddress = pragmaParamNumber(pragmaParamSingle(ctx));
|
||||
program.getTargetPlatform().setStartAddress(startAddress);
|
||||
@ -777,22 +781,31 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
return new AsmDirectiveClobber(clobber);
|
||||
} else if("resource".equals(ctx.NAME().getText())) {
|
||||
TerminalNode resource = ctx.STRING();
|
||||
String resourceName = resource.getText();
|
||||
resourceName = resourceName.substring(1, resourceName.length() - 1);
|
||||
Path currentPath = cParser.getSourceFolderPath(ctx);
|
||||
File resourceFile = SourceLoader.loadFile(resourceName, currentPath, new ArrayList<>());
|
||||
if(resourceFile == null)
|
||||
throw new CompileError("File not found " + resourceName);
|
||||
if(!program.getAsmResourceFiles().contains(resourceFile.toPath()))
|
||||
program.addAsmResourceFile(resourceFile.toPath());
|
||||
if(program.getLog().isVerboseParse()) {
|
||||
program.getLog().append("Added resource " + resourceFile.getPath().replace('\\', '/'));
|
||||
}
|
||||
String resourceFileName = resource.getText();
|
||||
resourceFileName = resourceFileName.substring(1, resourceFileName.length() - 1);
|
||||
addResourceFile(ctx, resourceFileName);
|
||||
return null;
|
||||
}
|
||||
throw new CompileError("Unknown ASM directive '"+ctx.NAME().getText()+"'", new StatementSource(ctx));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a resource to the program.
|
||||
* @param ctx The parser context used for finding the folder containing the current source line.
|
||||
* @param resourceFileName The file name of the resource file.
|
||||
*/
|
||||
private void addResourceFile(ParserRuleContext ctx, String resourceFileName) {
|
||||
Path currentPath = cParser.getSourceFolderPath(ctx);
|
||||
File resourceFile = SourceLoader.loadFile(resourceFileName, currentPath, new ArrayList<>());
|
||||
if(resourceFile == null)
|
||||
throw new CompileError("File not found " + resourceFileName);
|
||||
if(!program.getAsmResourceFiles().contains(resourceFile.toPath()))
|
||||
program.addAsmResourceFile(resourceFile.toPath());
|
||||
if(program.getLog().isVerboseParse()) {
|
||||
program.getLog().append("Added resource " + resourceFile.getPath().replace('\\', '/'));
|
||||
}
|
||||
}
|
||||
|
||||
/** Information about a declared parameter. */
|
||||
static class ParameterDecl {
|
||||
final public String name;
|
||||
|
@ -3672,6 +3672,11 @@ public class TestProgramsFast extends TestPrograms {
|
||||
compileAndCompare("inline-kasm-data.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInlineKasmResource2() throws IOException {
|
||||
compileAndCompare("inline-kasm-resource-2.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInlineKasmResource() throws IOException {
|
||||
compileAndCompare("inline-kasm-resource.c");
|
||||
|
22
src/test/kc/inline-kasm-resource-2.c
Normal file
22
src/test/kc/inline-kasm-resource-2.c
Normal file
@ -0,0 +1,22 @@
|
||||
// Example of inline kickasm resource data - using #pramga resource()
|
||||
|
||||
#pragma resource("balloon.png")
|
||||
|
||||
__address(0x0c00) byte SPRITE[] = kickasm {{
|
||||
.var pic = LoadPicture("balloon.png", List().add($000000, $ffffff))
|
||||
.for (var y=0; y<21; y++)
|
||||
.for (var x=0;x<3; x++)
|
||||
.byte pic.getSinglecolorByte(x,y)
|
||||
}};
|
||||
|
||||
char* const SCREEN= (char*)0x400;
|
||||
char* const SPRITES_ENABLE = (char*)0xd015;
|
||||
char* const SPRITES_XPOS = (char*)0xd000;
|
||||
char* const SPRITES_YPOS = (char*)0xd001;
|
||||
|
||||
void main() {
|
||||
*(SCREEN+0x3f8) = (char)((unsigned int)SPRITE/$40);
|
||||
*SPRITES_ENABLE = 1;
|
||||
*SPRITES_XPOS = 100;
|
||||
*SPRITES_YPOS = 100;
|
||||
}
|
37
src/test/ref/inline-kasm-resource-2.asm
Normal file
37
src/test/ref/inline-kasm-resource-2.asm
Normal file
@ -0,0 +1,37 @@
|
||||
// Example of inline kickasm resource data - using #pramga resource()
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="inline-kasm-resource-2.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0801]
|
||||
.segmentdef Code [start=$80d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
.label SCREEN = $400
|
||||
.label SPRITES_ENABLE = $d015
|
||||
.label SPRITES_XPOS = $d000
|
||||
.label SPRITES_YPOS = $d001
|
||||
.segment Code
|
||||
main: {
|
||||
// *(SCREEN+0x3f8) = (char)((unsigned int)SPRITE/$40)
|
||||
lda #$ff&SPRITE/$40
|
||||
sta SCREEN+$3f8
|
||||
// *SPRITES_ENABLE = 1
|
||||
lda #1
|
||||
sta SPRITES_ENABLE
|
||||
// *SPRITES_XPOS = 100
|
||||
lda #$64
|
||||
sta SPRITES_XPOS
|
||||
// *SPRITES_YPOS = 100
|
||||
sta SPRITES_YPOS
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment Data
|
||||
.pc = $c00 "SPRITE"
|
||||
SPRITE:
|
||||
.var pic = LoadPicture("balloon.png", List().add($000000, $ffffff))
|
||||
.for (var y=0; y<21; y++)
|
||||
.for (var x=0;x<3; x++)
|
||||
.byte pic.getSinglecolorByte(x,y)
|
||||
|
11
src/test/ref/inline-kasm-resource-2.cfg
Normal file
11
src/test/ref/inline-kasm-resource-2.cfg
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] *(SCREEN+$3f8) = (char)(unsigned int)SPRITE/$40
|
||||
[1] *SPRITES_ENABLE = 1
|
||||
[2] *SPRITES_XPOS = $64
|
||||
[3] *SPRITES_YPOS = $64
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[4] return
|
||||
to:@return
|
229
src/test/ref/inline-kasm-resource-2.log
Normal file
229
src/test/ref/inline-kasm-resource-2.log
Normal file
@ -0,0 +1,229 @@
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
void main()
|
||||
main: scope:[main] from __start
|
||||
*(SCREEN+$3f8) = (char)(unsigned int)SPRITE/$40
|
||||
*SPRITES_ENABLE = 1
|
||||
*SPRITES_XPOS = $64
|
||||
*SPRITES_YPOS = $64
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
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
|
||||
__constant char * const SCREEN = (char *)$400
|
||||
__constant char SPRITE[] = kickasm {{ .var pic = LoadPicture("balloon.png", List().add($000000, $ffffff))
|
||||
.for (var y=0; y<21; y++)
|
||||
.for (var x=0;x<3; x++)
|
||||
.byte pic.getSinglecolorByte(x,y)
|
||||
}}
|
||||
__constant char * const SPRITES_ENABLE = (char *)$d015
|
||||
__constant char * const SPRITES_XPOS = (char *)$d000
|
||||
__constant char * const SPRITES_YPOS = (char *)$d001
|
||||
void __start()
|
||||
void main()
|
||||
|
||||
Adding number conversion cast (unumber) $40 in *(SCREEN+$3f8) = (char)(unsigned int)SPRITE/$40
|
||||
Adding number conversion cast (unumber) $3f8 in *(SCREEN+$3f8) = (char)(unsigned int)SPRITE/(unumber)$40
|
||||
Adding number conversion cast (unumber) 1 in *SPRITES_ENABLE = 1
|
||||
Adding number conversion cast (unumber) $64 in *SPRITES_XPOS = $64
|
||||
Adding number conversion cast (unumber) $64 in *SPRITES_YPOS = $64
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast *SPRITES_ENABLE = (unumber)1
|
||||
Inlining cast *SPRITES_XPOS = (unumber)$64
|
||||
Inlining cast *SPRITES_YPOS = (unumber)$64
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (char *) 1024
|
||||
Simplifying constant pointer cast (char *) 53269
|
||||
Simplifying constant pointer cast (char *) 53248
|
||||
Simplifying constant pointer cast (char *) 53249
|
||||
Simplifying constant integer cast $40
|
||||
Simplifying constant integer cast $3f8
|
||||
Simplifying constant integer cast 1
|
||||
Simplifying constant integer cast $64
|
||||
Simplifying constant integer cast $64
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (char) $40
|
||||
Finalized unsigned number type (unsigned int) $3f8
|
||||
Finalized unsigned number type (char) 1
|
||||
Finalized unsigned number type (char) $64
|
||||
Finalized unsigned number type (char) $64
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
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
|
||||
Finalized unsigned number type (unsigned int) $c00
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
CALL GRAPH
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] *(SCREEN+$3f8) = (char)(unsigned int)SPRITE/$40
|
||||
[1] *SPRITES_ENABLE = 1
|
||||
[2] *SPRITES_XPOS = $64
|
||||
[3] *SPRITES_YPOS = $64
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[4] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
void main()
|
||||
|
||||
Initial phi equivalence classes
|
||||
Complete equivalence classes
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [0] *(SCREEN+$3f8) = (char)(unsigned int)SPRITE/$40 [ ] ( [ ] { } ) always clobbers reg byte a
|
||||
Statement [1] *SPRITES_ENABLE = 1 [ ] ( [ ] { } ) always clobbers reg byte a
|
||||
Statement [2] *SPRITES_XPOS = $64 [ ] ( [ ] { } ) always clobbers reg byte a
|
||||
Statement [3] *SPRITES_YPOS = $64 [ ] ( [ ] { } ) always clobbers reg byte a
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 33 combination
|
||||
Uplifting [] best 33 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Example of inline kickasm resource data - using #pramga resource()
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="inline-kasm-resource-2.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0801]
|
||||
.segmentdef Code [start=$80d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.label SPRITES_ENABLE = $d015
|
||||
.label SPRITES_XPOS = $d000
|
||||
.label SPRITES_YPOS = $d001
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// [0] *(SCREEN+$3f8) = (char)(unsigned int)SPRITE/$40 -- _deref_pbuc1=vbuc2
|
||||
lda #$ff&SPRITE/$40
|
||||
sta SCREEN+$3f8
|
||||
// [1] *SPRITES_ENABLE = 1 -- _deref_pbuc1=vbuc2
|
||||
lda #1
|
||||
sta SPRITES_ENABLE
|
||||
// [2] *SPRITES_XPOS = $64 -- _deref_pbuc1=vbuc2
|
||||
lda #$64
|
||||
sta SPRITES_XPOS
|
||||
// [3] *SPRITES_YPOS = $64 -- _deref_pbuc1=vbuc2
|
||||
lda #$64
|
||||
sta SPRITES_YPOS
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [4] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
.segment Data
|
||||
.pc = $c00 "SPRITE"
|
||||
SPRITE:
|
||||
.var pic = LoadPicture("balloon.png", List().add($000000, $ffffff))
|
||||
.for (var y=0; y<21; y++)
|
||||
.for (var x=0;x<3; x++)
|
||||
.byte pic.getSinglecolorByte(x,y)
|
||||
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction lda #$64
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
__constant char * const SCREEN = (char *) 1024
|
||||
__constant char SPRITE[] = kickasm {{ .var pic = LoadPicture("balloon.png", List().add($000000, $ffffff))
|
||||
.for (var y=0; y<21; y++)
|
||||
.for (var x=0;x<3; x++)
|
||||
.byte pic.getSinglecolorByte(x,y)
|
||||
}}
|
||||
__constant char * const SPRITES_ENABLE = (char *) 53269
|
||||
__constant char * const SPRITES_XPOS = (char *) 53248
|
||||
__constant char * const SPRITES_YPOS = (char *) 53249
|
||||
void main()
|
||||
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 28
|
||||
|
||||
// File Comments
|
||||
// Example of inline kickasm resource data - using #pramga resource()
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="inline-kasm-resource-2.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0801]
|
||||
.segmentdef Code [start=$80d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.label SPRITES_ENABLE = $d015
|
||||
.label SPRITES_XPOS = $d000
|
||||
.label SPRITES_YPOS = $d001
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// *(SCREEN+0x3f8) = (char)((unsigned int)SPRITE/$40)
|
||||
// [0] *(SCREEN+$3f8) = (char)(unsigned int)SPRITE/$40 -- _deref_pbuc1=vbuc2
|
||||
lda #$ff&SPRITE/$40
|
||||
sta SCREEN+$3f8
|
||||
// *SPRITES_ENABLE = 1
|
||||
// [1] *SPRITES_ENABLE = 1 -- _deref_pbuc1=vbuc2
|
||||
lda #1
|
||||
sta SPRITES_ENABLE
|
||||
// *SPRITES_XPOS = 100
|
||||
// [2] *SPRITES_XPOS = $64 -- _deref_pbuc1=vbuc2
|
||||
lda #$64
|
||||
sta SPRITES_XPOS
|
||||
// *SPRITES_YPOS = 100
|
||||
// [3] *SPRITES_YPOS = $64 -- _deref_pbuc1=vbuc2
|
||||
sta SPRITES_YPOS
|
||||
// main::@return
|
||||
// }
|
||||
// [4] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
.segment Data
|
||||
.pc = $c00 "SPRITE"
|
||||
SPRITE:
|
||||
.var pic = LoadPicture("balloon.png", List().add($000000, $ffffff))
|
||||
.for (var y=0; y<21; y++)
|
||||
.for (var x=0;x<3; x++)
|
||||
.byte pic.getSinglecolorByte(x,y)
|
||||
|
||||
|
11
src/test/ref/inline-kasm-resource-2.sym
Normal file
11
src/test/ref/inline-kasm-resource-2.sym
Normal file
@ -0,0 +1,11 @@
|
||||
__constant char * const SCREEN = (char *) 1024
|
||||
__constant char SPRITE[] = kickasm {{ .var pic = LoadPicture("balloon.png", List().add($000000, $ffffff))
|
||||
.for (var y=0; y<21; y++)
|
||||
.for (var x=0;x<3; x++)
|
||||
.byte pic.getSinglecolorByte(x,y)
|
||||
}}
|
||||
__constant char * const SPRITES_ENABLE = (char *) 53269
|
||||
__constant char * const SPRITES_XPOS = (char *) 53248
|
||||
__constant char * const SPRITES_YPOS = (char *) 53249
|
||||
void main()
|
||||
|
Loading…
Reference in New Issue
Block a user