From cb1b9bece1d82a567e381c42aeaaacfb5ffaab52 Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Mon, 22 Jun 2020 00:07:59 +0200 Subject: [PATCH] Implemented support for __address() on arrays. Removed support for pc parameter on inline kickasm. Closes #480. Closes #479 --- .../kickc/model/VariableBuilder.java | 38 +++-- .../model/iterator/ProgramValueIterator.java | 4 +- .../kickc/model/symbols/Variable.java | 14 ++ .../Pass0GenerateStatementSequence.java | 1 + .../kickc/passes/Pass4CodeGeneration.java | 57 +++++++- .../dk/camelot64/kickc/test/TestPrograms.java | 10 ++ src/test/kc/arrays-init-kasm-1.c | 13 ++ src/test/kc/complex/tetris/test-sprites.c | 5 +- src/test/kc/complex/tetris/tetris-data.c | 26 +++- src/test/kc/complex/tetris/tetris-render.c | 5 - src/test/kc/complex/tetris/tetris-sprites.c | 17 --- src/test/kc/examples/3d/3d.c | 5 +- .../kc/examples/krillload/install-c64.prg | Bin 0 -> 6888 bytes src/test/kc/examples/krillload/krill.c | 62 ++++++++ src/test/kc/examples/krillload/krillload.c | 49 +++++++ src/test/kc/examples/krillload/krillload.ld | 13 ++ src/test/kc/examples/krillload/loader-c64.prg | Bin 0 -> 497 bytes src/test/kc/examples/krillload/sprite.png | Bin 0 -> 1323 bytes .../examples/multiplexer/simple-multiplexer.c | 5 +- src/test/kc/examples/music/music.c | 21 ++- src/test/kc/examples/music/music_irq.c | 25 ++-- src/test/kc/examples/rotate/rotate.c | 5 +- src/test/kc/examples/scrolllogo/scrolllogo.c | 5 +- src/test/kc/examples/showlogo/showlogo.c | 6 +- src/test/kc/inline-kasm-data.c | 6 +- src/test/kc/inline-kasm-resource.c | 5 +- src/test/kc/test-kasm-pc.c | 7 +- src/test/ref/examples/rotate/rotate.asm | 11 +- .../ref/examples/scrolllogo/scrolllogo.asm | 132 +++++++++--------- src/test/ref/examples/showlogo/showlogo.asm | 7 +- 30 files changed, 383 insertions(+), 171 deletions(-) create mode 100644 src/test/kc/arrays-init-kasm-1.c create mode 100644 src/test/kc/examples/krillload/install-c64.prg create mode 100755 src/test/kc/examples/krillload/krill.c create mode 100644 src/test/kc/examples/krillload/krillload.c create mode 100644 src/test/kc/examples/krillload/krillload.ld create mode 100644 src/test/kc/examples/krillload/loader-c64.prg create mode 100644 src/test/kc/examples/krillload/sprite.png diff --git a/src/main/java/dk/camelot64/kickc/model/VariableBuilder.java b/src/main/java/dk/camelot64/kickc/model/VariableBuilder.java index d9777f941..021cfad2a 100644 --- a/src/main/java/dk/camelot64/kickc/model/VariableBuilder.java +++ b/src/main/java/dk/camelot64/kickc/model/VariableBuilder.java @@ -71,23 +71,23 @@ public class VariableBuilder { } variable.setMemoryArea(this.getMemoryArea()); variable.setMemoryAlignment(this.getAlignment()); + variable.setMemoryAddress(this.getAddress()); variable.setDeclarationOnly(this.isDeclarationOnly()); - // Check if the symbol has already been declared Symbol declaredSymbol = scope.getLocalSymbol(varName); - if(declaredSymbol!=null && !declaredSymbol.getFullName().equals(variable.getFullName())) + if(declaredSymbol != null && !declaredSymbol.getFullName().equals(variable.getFullName())) // We found another symbol! declaredSymbol = null; - if(declaredSymbol!=null) { + if(declaredSymbol != null) { if(!(declaredSymbol instanceof Variable)) - throw new CompileError("Error! Conflicting declarations for: "+variable.getFullName()); + throw new CompileError("Error! Conflicting declarations for: " + variable.getFullName()); Variable declaredVar = (Variable) declaredSymbol; if(!declaredVar.isDeclarationOnly() && !variable.isDeclarationOnly()) - throw new CompileError("Error! Redefinition of variable: "+variable.getFullName()); + throw new CompileError("Error! Redefinition of variable: " + variable.getFullName()); if(!SymbolTypeConversion.variableDeclarationMatch(declaredVar, variable)) - throw new CompileError("Error! Conflicting declarations for: "+variable.getFullName()); + throw new CompileError("Error! Conflicting declarations for: " + variable.getFullName()); // Update the variable with the definition if(!variable.isDeclarationOnly()) { @@ -249,6 +249,7 @@ public class VariableBuilder { /** * Declared but not defined. ( "extern" keyword) + * * @return true if the variable is declared but not defined. */ public boolean isDeclarationOnly() { @@ -282,7 +283,7 @@ public class VariableBuilder { VariableBuilderConfig.Scope scope = VariableBuilderConfig.getScope(isScopeGlobal(), isScopeLocal(), isScopeParameter(), isScopeMember()); VariableBuilderConfig.Type type = VariableBuilderConfig.getType(isTypeInteger(), isArray(), isTypePointer(), isTypeStruct()); VariableBuilderConfig.Setting setting = config.getSetting(scope, type); - if(setting!=null && VariableBuilderConfig.Optimization.MA.equals(setting.optimization)) + if(setting != null && VariableBuilderConfig.Optimization.MA.equals(setting.optimization)) return false; else return true; @@ -328,7 +329,7 @@ public class VariableBuilder { VariableBuilderConfig.Scope scope = VariableBuilderConfig.getScope(isScopeGlobal(), isScopeLocal(), isScopeParameter(), isScopeMember()); VariableBuilderConfig.Type type = VariableBuilderConfig.getType(isTypeInteger(), isArray(), isTypePointer(), isTypeStruct()); VariableBuilderConfig.Setting setting = config.getSetting(scope, type); - if(setting!=null && VariableBuilderConfig.MemoryArea.MEM.equals(setting.memoryArea)) + if(setting != null && VariableBuilderConfig.MemoryArea.MEM.equals(setting.memoryArea)) return Variable.MemoryArea.MAIN_MEMORY; else return Variable.MemoryArea.ZEROPAGE_MEMORY; @@ -353,12 +354,32 @@ public class VariableBuilder { return null; } + /** + * Get any memory-address of the variables data + * + * @return The memory alignment + */ + public Long getAddress() { + Directive.Address addressDirective = findDirective(Directive.Address.class, directives); + if(addressDirective != null) { + if(isArray()) { + return addressDirective.address; + } + } + return null; + } + /** * Get any hard-coded register allocation. * * @return Hard-coded register allocation. Null if not hard-coded. */ public Registers.Register getRegister() { + + if(isArray()) + // Arrays are not put into registers + return null; + Directive.Address addressDirective = findDirective(Directive.Address.class, directives); if(addressDirective != null) { Variable.MemoryArea memoryArea = (addressDirective.address < 0x100) ? Variable.MemoryArea.ZEROPAGE_MEMORY : Variable.MemoryArea.MAIN_MEMORY; @@ -394,6 +415,7 @@ public class VariableBuilder { private boolean hasDirective(Class directiveClass) { return findDirective(directiveClass, directives) != null; } + /** * Examines whether a specific directive is present in the source * diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java index b14dd2ef7..4ebde251e 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java @@ -148,11 +148,11 @@ public class ProgramValueIterator { if(location != null) { execute(new ProgramValue.ProgramValueKickAsmLocation(statementKickAsm), handler, statement, statementsIt, block); } - RValue bytes = statementKickAsm.getLocation(); + RValue bytes = statementKickAsm.getBytes(); if(bytes != null) { execute(new ProgramValue.ProgramValueKickAsmBytes(statementKickAsm), handler, statement, statementsIt, block); } - RValue cycles = statementKickAsm.getLocation(); + RValue cycles = statementKickAsm.getCycles(); if(cycles != null) { execute(new ProgramValue.ProgramValueKickAsmCycles(statementKickAsm), handler, statement, statementsIt, block); } diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java b/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java index 86cd91663..9853a2ca3 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java @@ -94,6 +94,9 @@ public class Variable implements Symbol { /** Specifies that the variable must be aligned in memory. Only allowed for arrays & strings. [Only Variables in memory and arrays] */ private Integer memoryAlignment; + /** Specifies that the variable must be placed at an absolute address in memory. Only allowed for arrays & strings. [Only Variables in memory and arrays] */ + private Long memoryAddress; + /** The data segment to put the variable into (if it is allocated in memory). [Only variables stored in memory and arrays] */ private String dataSegment; @@ -193,6 +196,7 @@ public class Variable implements Symbol { throw new InternalError("Cannot version non-PHI variable " + phiMaster.toString()); Variable version = new Variable(phiMaster.getName() + "#" + versionNum, Kind.PHI_VERSION, phiMaster.getType(), phiMaster.getScope(), phiMaster.getMemoryArea(), phiMaster.getDataSegment(), phiMaster.getArraySpec(), null); version.setMemoryAlignment(phiMaster.getMemoryAlignment()); + version.setMemoryAddress(phiMaster.getMemoryAddress()); version.setOptimize(phiMaster.isOptimize()); version.setNoModify(phiMaster.isNoModify()); version.setRegister(phiMaster.getRegister()); @@ -239,6 +243,7 @@ public class Variable implements Symbol { public static Variable createConstant(Variable variable, ConstantValue constantValue) { Variable constVar = new Variable(variable.getName(), Kind.CONSTANT, variable.getType(), variable.getScope(), MemoryArea.MAIN_MEMORY, variable.getDataSegment(), variable.getArraySpec(), constantValue); constVar.setMemoryAlignment(variable.getMemoryAlignment()); + constVar.setMemoryAddress(variable.getMemoryAddress()); constVar.setOptimize(variable.isOptimize()); constVar.setNoModify(variable.isNoModify()); constVar.setRegister(variable.getRegister()); @@ -261,6 +266,7 @@ public class Variable implements Symbol { public static Variable createCopy(String name, Scope scope, Variable original) { Variable copy = new Variable(name, original.getKind(), original.getType(), scope, original.getMemoryArea(), original.getDataSegment(), original.getArraySpec(), original.getInitValue()); copy.setMemoryAlignment(original.getMemoryAlignment()); + copy.setMemoryAddress(original.getMemoryAddress()); copy.setOptimize(original.isOptimize()); copy.setNoModify(original.isNoModify()); copy.setPermanent(original.isPermanent()); @@ -576,6 +582,14 @@ public class Variable implements Symbol { this.memoryAlignment = memoryAlignment; } + public Long getMemoryAddress() { + return memoryAddress; + } + + public void setMemoryAddress(Long memoryAddress) { + this.memoryAddress = memoryAddress; + } + /** * Is the variable a struct that should be unwound to member variables * diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 3e72fab50..4880af3ef 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -453,6 +453,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor scopeConstants = scope.getAllConstants(false); + Set added = new LinkedHashSet<>(); + // Add all constants arrays incl. strings with data + for(Variable constantVar : scopeConstants) { + if(hasData(constantVar)) { + // Skip if already added + String asmName = constantVar.getAsmName() == null ? constantVar.getLocalName() : constantVar.getAsmName(); + if(added.contains(asmName)) { + continue; + } + // Skip if address is not absolute + if(constantVar.getMemoryAddress()==null) + continue; + // Set segment + setCurrentSegment(constantVar.getDataSegment(), asm); + // Set absolute address + asm.addLine(new AsmSetPc(asmName, AsmFormat.getAsmNumber(constantVar.getMemoryAddress()))); + // Add any comments + generateComments(asm, constantVar.getComments()); + // Add any alignment + Integer declaredAlignment = constantVar.getMemoryAlignment(); + if(declaredAlignment != null) { + String alignment = AsmFormat.getAsmNumber(declaredAlignment); + asm.addDataAlignment(alignment); + } + ConstantValue constantValue = constantVar.getInitValue(); + if(constantValue instanceof ConstantArray || constantValue instanceof ConstantString || constantValue instanceof ConstantStructValue) { + AsmDataChunk asmDataChunk = new AsmDataChunk(); + addChunkData(asmDataChunk, constantValue, constantVar.getType(), constantVar.getArraySpec(), scopeRef); + asmDataChunk.addToAsm(AsmFormat.asmFix(asmName), asm); + } else { + throw new InternalError("Constant Variable not handled " + constantVar.toString(program)); + } + added.add(asmName); + } + } + + } + + /** + * Add constants with data and memory variables with data for a scope. + * Added after the the code of the scope. + * + * @param asm The ASM program + * @param scopeRef The scope + */ private void addData(AsmProgram asm, ScopeRef scopeRef) { Scope scope = program.getScope().getScope(scopeRef); Collection scopeConstants = scope.getAllConstants(false); @@ -507,6 +557,9 @@ public class Pass4CodeGeneration { if(added.contains(asmName)) { continue; } + // Skip if address is absolute + if(constantVar.getMemoryAddress()!=null) + continue; // Set segment setCurrentSegment(constantVar.getDataSegment(), asm); // Add any comments diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index e960d1182..b2c9f404a 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -660,6 +660,11 @@ public class TestPrograms { compileAndCompare("examples/kernalload/kernalload.c"); } + @Test + public void testKrillLoad() throws IOException, URISyntaxException { + compileAndCompare("examples/krillload/krillload.c"); + } + @Test public void testConstantWithPrePost() throws IOException, URISyntaxException { assertError("constant-prepost.c", "Constant value contains a pre/post-modifier"); @@ -1268,6 +1273,11 @@ public class TestPrograms { compileAndCompare("arrays-init-kasm-0.c"); } + @Test + public void testArraysInitKasm1() throws IOException, URISyntaxException { + compileAndCompare("arrays-init-kasm-1.c"); + } + @Test public void testScreenCenterAngle() throws IOException, URISyntaxException { compileAndCompare("screen-center-angle.c"); diff --git a/src/test/kc/arrays-init-kasm-1.c b/src/test/kc/arrays-init-kasm-1.c new file mode 100644 index 000000000..22ecb72ad --- /dev/null +++ b/src/test/kc/arrays-init-kasm-1.c @@ -0,0 +1,13 @@ +// Test initializing array using KickAssembler +// Place array at hardcoded address + +// Sinus table at an absolute address in memory +__address(0x1000) char SINTAB[256] = kickasm {{ + .fill 256, 128 + 128*sin(i*2*PI/256) +}}; + +char* SCREEN = 0x400; + +void main() { + SCREEN[0] = SINTAB[0]; +} \ No newline at end of file diff --git a/src/test/kc/complex/tetris/test-sprites.c b/src/test/kc/complex/tetris/test-sprites.c index 8922502de..352ed7cc0 100644 --- a/src/test/kc/complex/tetris/test-sprites.c +++ b/src/test/kc/complex/tetris/test-sprites.c @@ -7,10 +7,9 @@ char SIN[256] = kickasm {{ } }}; -char* SIN_SPRITE = 0x2800; -kickasm(pc SIN_SPRITE) {{ +__address(0x3800) char SIN_SPRITE[0x40] = kickasm {{ .fill $40, $ff -}} +}}; char sin_idx = 0; diff --git a/src/test/kc/complex/tetris/tetris-data.c b/src/test/kc/complex/tetris/tetris-data.c index 27cf39500..4fd56ed7e 100644 --- a/src/test/kc/complex/tetris/tetris-data.c +++ b/src/test/kc/complex/tetris/tetris-data.c @@ -9,10 +9,30 @@ char* const PLAYFIELD_SCREEN_2 = 0x2c00; char* const PLAYFIELD_SPRITE_PTRS_1 = (PLAYFIELD_SCREEN_1+SPRITE_PTRS); // Screen Sprite pointers on screen 2 char* const PLAYFIELD_SPRITE_PTRS_2 = (PLAYFIELD_SCREEN_2+SPRITE_PTRS); -// Address of the sprites covering the playfield -char* const PLAYFIELD_SPRITES = 0x3000; + +// Sprites covering the playfield +__address(0x3000) char PLAYFIELD_SPRITES[30*64] = kickasm(resource "playfield-sprites.png") {{ + .var sprites = LoadPicture("playfield-sprites.png", List().add($010101, $000000)) + // Put the sprites into memory + .for(var sy=0;sy<10;sy++) { + .var sprite_gfx_y = sy*20 + .for(var sx=0;sx<3;sx++) { + .for (var y=0;y<21; y++) { + .var gfx_y = sprite_gfx_y + mod(2100+y-sprite_gfx_y,21) + .for (var c=0; c<3; c++) { + .byte sprites.getSinglecolorByte(sx*3+c,gfx_y) + } + } + .byte 0 + } + } +}}; + // Address of the charset -char* const PLAYFIELD_CHARSET = 0x2800; +__address(0x2800) char PLAYFIELD_CHARSET[] = kickasm(resource "playfield-screen.imap") {{ + .fill 8,$00 // Place a filled char at the start of the charset + .import binary "playfield-screen.imap" +}}; // The size of the playfield const char PLAYFIELD_LINES = 22; diff --git a/src/test/kc/complex/tetris/tetris-render.c b/src/test/kc/complex/tetris/tetris-render.c index e6e3d717c..75a64bb63 100644 --- a/src/test/kc/complex/tetris/tetris-render.c +++ b/src/test/kc/complex/tetris/tetris-render.c @@ -5,11 +5,6 @@ #include "tetris-data.c" #include "tetris-pieces.c" -kickasm(pc PLAYFIELD_CHARSET, resource "playfield-screen.imap") {{ - .fill 8,$00 // Place a filled char at the start of the charset - .import binary "playfield-screen.imap" -}} - // Address of the original playscreen chars const char PLAYFIELD_SCREEN_ORIGINAL_WIDTH=32; const char PLAYFIELD_SCREEN_ORIGINAL[] = kickasm(resource "playfield-screen.iscr", resource "playfield-extended.col" ) {{ diff --git a/src/test/kc/complex/tetris/tetris-sprites.c b/src/test/kc/complex/tetris/tetris-sprites.c index fa035df7a..cdf12f64b 100644 --- a/src/test/kc/complex/tetris/tetris-sprites.c +++ b/src/test/kc/complex/tetris/tetris-sprites.c @@ -3,23 +3,6 @@ #include #include "tetris-data.c" -kickasm(pc PLAYFIELD_SPRITES, resource "playfield-sprites.png") {{ - .var sprites = LoadPicture("playfield-sprites.png", List().add($010101, $000000)) - // Put the sprites into memory - .for(var sy=0;sy<10;sy++) { - .var sprite_gfx_y = sy*20 - .for(var sx=0;sx<3;sx++) { - .for (var y=0;y<21; y++) { - .var gfx_y = sprite_gfx_y + mod(2100+y-sprite_gfx_y,21) - .for (var c=0; c<3; c++) { - .byte sprites.getSinglecolorByte(sx*3+c,gfx_y) - } - } - .byte 0 - } - } -}} - // Setup the sprites void sprites_init() { *SPRITES_ENABLE = %00001111; diff --git a/src/test/kc/examples/3d/3d.c b/src/test/kc/examples/3d/3d.c index 00e25d7fc..e09379938 100644 --- a/src/test/kc/examples/3d/3d.c +++ b/src/test/kc/examples/3d/3d.c @@ -438,13 +438,12 @@ void mulf_init() { */ // A single sprite -char* SPRITE = $3000; -kickasm(pc SPRITE, resource "balloon.png") {{ +__address(0x3000) char SPRITE[] = kickasm(resource "balloon.png") {{ .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) -}} +}}; // Perspective multiplication table containing (d/(z0-z)[z] for each z-value signed char align(0x100) PERSP_Z[0x100] = kickasm {{ diff --git a/src/test/kc/examples/krillload/install-c64.prg b/src/test/kc/examples/krillload/install-c64.prg new file mode 100644 index 0000000000000000000000000000000000000000..e304c7e0a26a475bba2f3a5fca348415b9045f34 GIT binary patch literal 6888 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 Vi{KA_mfx^wk^QUB4UTW3{{lRs=<)yn literal 0 HcmV?d00001 diff --git a/src/test/kc/examples/krillload/krill.c b/src/test/kc/examples/krillload/krill.c new file mode 100755 index 000000000..8905d1d78 --- /dev/null +++ b/src/test/kc/examples/krillload/krill.c @@ -0,0 +1,62 @@ +// Krill's Loader for C64 v184 +// https://csdb.dk/release/?id=189130 +// Uses Install/Loader files built using the following command. +// > make PLATFORM=c64 prg INSTALL=3400 RESIDENT=3000 ZP=e8 +// To place the loader routines elsewhere in memory: re-make the krill loader, update the 2 prg-files and update the __address() below. + +// Reserve the zero-page addresses used by the Krill routines +#pragma zp_reserve(0xe8..0xfd) + +// The Krill loader routine that can load files. +__address(0x3000) char KRILL_LOADER[] = kickasm(resource "loader-c64.prg") {{ + .import c64 "loader-c64.prg" +}}; + +// The Krill Install routine that can install the drive-side code +__address(0x3400) char KRILL_INSTALL[] = kickasm(resource "install-c64.prg") {{ + .import c64 "install-c64.prg" +}}; + +// Status returned from the Krill functions +enum KrillStatus { + KRILL_OK = 0x00, + KRILL_DEVICE_INCOMPATIBLE = 0xfb, + KRILL_TOO_MANY_DEVICES = 0xfc, + KRILL_GENERIC_KERNAL_ERROR = 0xfd, + KRILL_DEVICE_NOT_PRESENT = 0xfe, + KRILL_FILE_NOT_FOUND = 0xff +}; + +// Install drive-side code portion(s) must be installed in the active drive. +// Before the loader can operate, its drive-side code portion(s) must be installed in the drive(s). +// The drive-side portion remains resident in the drive. After successful +// installation, the install routine is not needed any more and may be overwritten. +// The KERNAL ROM may be disabled and zeropage variables clobbered. +// Returns the status of the installation +enum KrillStatus krill_install() { + enum KrillStatus* const status = 0xff; + asm(clobbers "AXY") { + jsr KRILL_INSTALL + sta status + } + return *status; +} + +// Load a file from the active drive without decompression. +// While loading using filenames with wildcards ("?" and "*") is not possible, +// subsequent files following the previously-loaded file can be loaded via a +// zero-length filename +// - filename - The name of the file to load (zero-terminated in petscii encoding) +// Returns the status of the load +enum KrillStatus krill_loadraw(char* filename) { + enum KrillStatus* const status = 0xff; + char** const fname = 0xfe; + *fname = filename; + asm(clobbers "AXY") { + ldx fname + ldy fname+1 + jsr KRILL_LOADER + sta status + } + return *status; +} diff --git a/src/test/kc/examples/krillload/krillload.c b/src/test/kc/examples/krillload/krillload.c new file mode 100644 index 000000000..92f2ea897 --- /dev/null +++ b/src/test/kc/examples/krillload/krillload.c @@ -0,0 +1,49 @@ +// Tests Krill Loader +// Load a file to memory using the Krill loader +// The krillload.ld link file creates a D64 disk image containing the executable and the sprite. +// To execute the program succesfully you must mount the D64 disk image and execute the krillload.PRG program +#pragma link("krillload.ld") +#pragma extension("d64") + +// Encoding needed for filename +#pragma encoding(petscii_mixed) + +#include "krill.c" +#include + +// Sprite file +#pragma data_seg(Sprite) +// The sprite data +export __address(0x2040) char SPRITE[0x40] = kickasm(resource "sprite.png") {{ + .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff)) + .for (var y=0; y<21; y++) + .for (var x=0;x<3; x++) + .byte pic.getSinglecolorByte(x,y) +}}; + +// Program file +#pragma data_seg(Data) + +char* const SCREEN = 0x0400; +char* const SPRITES_PTR = SCREEN+SPRITE_PTRS; + +void main() { + // Install the Krill drive code + char status = krill_install(); + if(status!=KRILL_OK) { + VICII->BORDER_COLOR = 0x02; + return; + } + // Load sprite file from disk + status = krill_loadraw("sprite"); + if(status!=KRILL_OK) { + VICII->BORDER_COLOR = 0x02; + return; + } + // Show the loaded sprite on screen + VICII->SPRITES_ENABLE = %00000001; + SPRITES_PTR[0] = toSpritePtr(SPRITE); + SPRITES_COLOR[0] = GREEN; + SPRITES_XPOS[0] = 0x15; + SPRITES_YPOS[0] = 0x33; +} diff --git a/src/test/kc/examples/krillload/krillload.ld b/src/test/kc/examples/krillload/krillload.ld new file mode 100644 index 000000000..c06e25d01 --- /dev/null +++ b/src/test/kc/examples/krillload/krillload.ld @@ -0,0 +1,13 @@ +// Create a D64 disk containing the program and a sprite file +.disk [filename="%O", name="DISK", id=1] { + [name="KRILLLOAD", type="prg", segments="Program"], + [name="SPRITE", type="prg", segments="Sprite"] +} +.segmentdef Program [segments="Basic, Code, Data"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$080d] +.segmentdef Data [startAfter="Code"] +.segmentdef Sprite +.segment Basic +:BasicUpstart(%E) +.segment Code \ No newline at end of file diff --git a/src/test/kc/examples/krillload/loader-c64.prg b/src/test/kc/examples/krillload/loader-c64.prg new file mode 100644 index 0000000000000000000000000000000000000000..38a5e2814e77fbb27b06468382176523dad405de GIT binary patch literal 497 zcmW+zziZo25Pp8Pv7OdMLkA5FJZJ`&r0_&333SM+x*0;qAD~4b4243MPNjpM2qAXm z&F&;b>_<+-{vZWRP6~S~?V}(XLfe>-k3{MNX4GdpYj=?!NE1JAlzTMz66x@1`V{ zeyx@8XpJ#KYvyLro}foBfB|UQ1Ro?dGQiOqRs(frJ*h%(19-c0E$oD%nJbIpC+I!; zZNmch9I>LJ^teCPCb@JJn)$}LKbI1X*-7Xv)?+hWgPvsFEKSaV$4!lAN6Td^tK*O8I_dr+PiUA6AP3 z%WC(8lAb4HZQ`h-1FKoRD{R>h%4KtNwfl?BuT;$K_jiQHz+<2QngD#fe7OV;EwZ-l z;u7pkF)yKg!QMCy+}t3Ljsr>^x_U-!-@1{_J!0QYt!~* zsLjkHg1+lHrgWSWcKdPn90sKGrRqvPeo9CG3uKX#J{(IASm?@+di}}l?o-=)F3E6 zwD^Ni=!>T7nL9I?X}YoAW$t|Qo$sD|?zw001?ah|SeB6#0T!CBEf+H4bBB+JJu8re zhoBb*p;u8ID_yBf0ya+zcePvJL&AGs+11_tpRKn>9TgyPA7ZoSs0)aX0r00)%XR^J z`jH<$>RKN5V(7OqK*TS4xZz{h!*f1C3ECFkK$#7nA@pGN!$;%jYv zwjAKwmYb0gKL(K8-kPtb5${A?tlI~wzMrJ6wTdBr=Y%%%EaEMQ&o}4FQ^DA)s*}Z> z!FI&AHCpoWI|RUqx?7s@$8!5^Q=anY%X@i5{QA6kNcMelpE>R6eCYFpmMsVT zrI(b06~u#xf1yS}_UGdMvD``!0~u->P=lA4?YN`hilQ z|3tHka)7T{2CGqwjZfMwx$5irQN_*|e4l)UHmiYuz74Yp1t^#>hrJ3-SOXDcC_o0^ z7T9R1gAN8V6s;5)ieI5-7aQlmJn}lUna#nz!j%5V$X|o`xX!dHWQRV27P1=rj;t2b zW$~+pTw@bIek?ZvKPDL<64`^#UNTAck#RBsB6*5DP4<%UA_FqU$I>2EH_cM;u)Q~SI+rg`Rn{L z_AC5qq~L$#SMj%U$6Cz0vP{G5Y*=%5RT^yu;}-DInZ=349rJPVM6C3K^oO)8y(fJr{l>k`ead~!ea?NsT>_Ci%bnxC;Vy6= zb6>{xYV#Ue-+LB$7`JEXmTRm^AtP)R9u{)KHsMiWGV&)32xCG~*nyU<>-!d;FP=Re z4r3qYr~6#KE>;1F`>_J_P5xC?ROxV(DIHdCO*p$HRQI@7^PwV@Pvuf+ z5K}u-6REM(K@W$srgorh0{i?O)v0c>QtHxU-hBdD(>iYJ4b2sIOVX2K8m~4gmYVA5 zh^QEb$V`rCQ-|7ZS{nuL-t>?3n=-o(6I(7vocj#GzCZEo`!3>+v;dYIfPu#&ZWzzX z2i^rZ^Mu;6+rb@?NPG+6)c5T6zxpzGe*M(x+{AON=PiJ>H#?ob-|uwRK0yDg0B4PV z0id6JRRdfL?*IS*%}GQ-R5%gMQ_%_oF$`+Q{{NS|`5**Ob1mFpg`-Jh)C6vhG1m8s zXRTbGbH+XvfUpc5F`IdJLN9{qeL{}D4sQjj7-P8XoD!$^Wkt>ni1|(t=9Q4O`u48L zPV9)gzU>u}1TLLZ*7d%u2mt4jq^^b@))CjUy`n^1$y|KAB1h7_MS(Q3lHK8~0GhCp zyXGC76{s$gNP4fmh@$}A0iE_b}KBJTZa&la<*0WSm5?n*V%) h{}9l1Xs&Ci`3Is1J4vY+Soi<{002ovPDHLkV1n&siSGaa literal 0 HcmV?d00001 diff --git a/src/test/kc/examples/multiplexer/simple-multiplexer.c b/src/test/kc/examples/multiplexer/simple-multiplexer.c index 40872a727..acf71ceea 100644 --- a/src/test/kc/examples/multiplexer/simple-multiplexer.c +++ b/src/test/kc/examples/multiplexer/simple-multiplexer.c @@ -13,13 +13,12 @@ char align(0x100) YSIN[0x100] = kickasm {{ .byte round(min+(ampl/2)+(ampl/2)*sin(toRadians(360*i/256))) }}; -char* SPRITE = $2000; -kickasm(pc SPRITE, resource "balloon.png") {{ +__address(0x2000) char SPRITE[] = kickasm(resource "balloon.png") {{ .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) -}} +}}; void main() { asm { sei } diff --git a/src/test/kc/examples/music/music.c b/src/test/kc/examples/music/music.c index 6e1f66323..08aec61b0 100755 --- a/src/test/kc/examples/music/music.c +++ b/src/test/kc/examples/music/music.c @@ -1,29 +1,26 @@ // A simple SID music player playing music in the main loop. #include -char* const MUSIC = $1000; - -// Load the SID -kickasm(resource "toiletrensdyr.sid") {{ +// SID tune at an absolute address +__address(0x1000) char MUSIC[] = kickasm(resource "toiletrensdyr.sid") {{ .const music = LoadSid("toiletrensdyr.sid") -}} - -// Place the SID into memory -kickasm(pc MUSIC) {{ .fill music.size, music.getData(i) -}} - +}}; +// Pointer to the music init routine +void()* musicInit = (void()*) MUSIC; +// Pointer to the music play routine +void()* musicPlay = (void()*) MUSIC+3; // Play the music void main() { // Initialize the music - asm { jsr music.init } + (*musicInit)(); do { // Wait for the RASTER do {} while (VICII->RASTER != $fd); (VICII->BORDER_COLOR)++; // Play the music - asm { jsr music.play } + (*musicPlay)(); (VICII->BORDER_COLOR)--; } while (true); } \ No newline at end of file diff --git a/src/test/kc/examples/music/music_irq.c b/src/test/kc/examples/music/music_irq.c index 99de81648..99008fa92 100755 --- a/src/test/kc/examples/music/music_irq.c +++ b/src/test/kc/examples/music/music_irq.c @@ -1,25 +1,20 @@ // A simple SID music player using RASTER IRQ #include -char* const MUSIC = $1000; - -// Load the SID -kickasm(resource "toiletrensdyr.sid") {{ +// SID tune at an absolute address +__address(0x1000) char MUSIC[] = kickasm(resource "toiletrensdyr.sid") {{ .const music = LoadSid("toiletrensdyr.sid") -}} - -// Place the SID into memory -kickasm(pc MUSIC) {{ .fill music.size, music.getData(i) -}} - +}}; +// Pointer to the music init routine +void()* musicInit = (void()*) MUSIC; +// Pointer to the music play routine +void()* musicPlay = (void()*) MUSIC+3; // Setup Raster IRQ and initialize SID player void main() { - asm { - sei - jsr music.init - } + asm { sei } + (*musicInit)(); // Disable CIA 1 Timer IRQ CIA1->INTERRUPT = CIA_INTERRUPT_CLEAR; // Set raster line to $fd @@ -36,7 +31,7 @@ void main() { interrupt(kernel_keyboard) void irq_play() { (VICII->BORDER_COLOR)++; // Play SID - asm { jsr music.play } + (*musicPlay)(); // Acknowledge the IRQ VICII->IRQ_STATUS = IRQ_RASTER; (VICII->BORDER_COLOR)--; diff --git a/src/test/kc/examples/rotate/rotate.c b/src/test/kc/examples/rotate/rotate.c index 7c64544df..868f907d2 100644 --- a/src/test/kc/examples/rotate/rotate.c +++ b/src/test/kc/examples/rotate/rotate.c @@ -76,10 +76,9 @@ void anim() { } // A single sprite -char* SPRITE = $3000; -kickasm(pc SPRITE, resource "balloon.png") {{ +__address(0x3000) char SPRITE[] = kickasm(resource "balloon.png") {{ .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) -}} +}}; diff --git a/src/test/kc/examples/scrolllogo/scrolllogo.c b/src/test/kc/examples/scrolllogo/scrolllogo.c index 3a446d5d4..10ee81fa9 100644 --- a/src/test/kc/examples/scrolllogo/scrolllogo.c +++ b/src/test/kc/examples/scrolllogo/scrolllogo.c @@ -3,14 +3,13 @@ #include char* SCREEN = $400; -char* LOGO = $2000; -kickasm(resource "logo.png", pc LOGO, bytes 6*40*8) {{ +__address(0x2000) char LOGO[6*40*8] = kickasm(resource "logo.png") {{ .var logoPic = LoadPicture("logo.png", List().add($444444, $808080, $000000, $ffffff)) .for (var y=0; y<6 ; y++) .for (var x=0;x<40; x++) .for(var cp=0; cp<8; cp++) .byte logoPic.getMulticolorByte(x,cp+y*8) -}} +}}; const unsigned int XSIN_SIZE = 512; diff --git a/src/test/kc/examples/showlogo/showlogo.c b/src/test/kc/examples/showlogo/showlogo.c index 877d57ac7..1f2ac1e85 100644 --- a/src/test/kc/examples/showlogo/showlogo.c +++ b/src/test/kc/examples/showlogo/showlogo.c @@ -2,15 +2,13 @@ #include char* SCREEN = $400; -char* LOGO = $2000; - -kickasm(resource "logo.png", pc LOGO, bytes 6*40*8 ) {{ +__address(0x2000) char LOGO[6*40*8] = kickasm(resource "logo.png") {{ .var logoPic = LoadPicture("logo.png", List().add($444444, $808080, $000000, $ffffff)) .for (var y=0; y<6 ; y++) .for (var x=0;x<40; x++) .for(var cp=0; cp<8; cp++) .byte logoPic.getMulticolorByte(x,cp+y*8) -}} +}}; void main() { VICII->BORDER_COLOR = WHITE; diff --git a/src/test/kc/inline-kasm-data.c b/src/test/kc/inline-kasm-data.c index d05804978..b3f117168 100644 --- a/src/test/kc/inline-kasm-data.c +++ b/src/test/kc/inline-kasm-data.c @@ -1,10 +1,8 @@ // Example of inline kickasm data -byte* const sintab = $1000; -kickasm(pc sintab) {{ +__address(0x1000) char sintab[] = kickasm {{ .fill 25, 20 + 20*sin(toRadians(i*360/25)) -}} - +}}; void main() { byte* screen = $400; diff --git a/src/test/kc/inline-kasm-resource.c b/src/test/kc/inline-kasm-resource.c index 9fe561e37..7dd17bfe8 100644 --- a/src/test/kc/inline-kasm-resource.c +++ b/src/test/kc/inline-kasm-resource.c @@ -1,12 +1,11 @@ // Example of inline kickasm resource data -byte* const SPRITE = $0c00; -kickasm(pc SPRITE, resource "balloon.png") {{ +__address(0x0c00) byte SPRITE[] = kickasm(resource "balloon.png") {{ .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) -}} +}}; byte* const SCREEN= $400; byte* const SPRITES_ENABLE = $d015; diff --git a/src/test/kc/test-kasm-pc.c b/src/test/kc/test-kasm-pc.c index abccaeba3..262bb5274 100644 --- a/src/test/kc/test-kasm-pc.c +++ b/src/test/kc/test-kasm-pc.c @@ -1,6 +1,8 @@ // Test inline KickAssembler code with PC location specification -byte* TABLE = $2000; +__address(0x2000) byte TABLE[] = kickasm {{ + .byte 1, 2, 3 +}}; void main() { byte* BORDER_COLOR = $d020; @@ -10,6 +12,3 @@ void main() { } } -kickasm(pc TABLE) {{ - .byte 1, 2, 3 -}} \ No newline at end of file diff --git a/src/test/ref/examples/rotate/rotate.asm b/src/test/ref/examples/rotate/rotate.asm index 34a020e9e..54e7c7d6a 100644 --- a/src/test/ref/examples/rotate/rotate.asm +++ b/src/test/ref/examples/rotate/rotate.asm @@ -28,9 +28,6 @@ .label CIA2_TIMER_AB = $dd04 .label SCREEN = $400 .label COS = SIN+$40 - // A single sprite - .label SPRITE = $3000 - // kickasm // sin(x) = cos(x+PI/2) main: { // asm @@ -459,7 +456,7 @@ init: { ldx #0 __b1: // sprites_ptr[i] = (char)(SPRITE/$40) - lda #SPRITE/$40 + lda #$ff&SPRITE/$40 sta sprites_ptr,x // SPRITES_COLOR[i] = GREEN lda #GREEN @@ -635,8 +632,10 @@ SIN: // Positions to rotate xs: .byte -$46, -$46, -$46, 0, 0, $46, $46, $46 ys: .byte -$46, 0, $46, -$46, $46, -$46, 0, $46 -.pc = SPRITE "SPRITE" - .var pic = LoadPicture("balloon.png", List().add($000000, $ffffff)) +.pc = $3000 "SPRITE" +// A single 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) diff --git a/src/test/ref/examples/scrolllogo/scrolllogo.asm b/src/test/ref/examples/scrolllogo/scrolllogo.asm index 6b63a71dc..7c294f071 100644 --- a/src/test/ref/examples/scrolllogo/scrolllogo.asm +++ b/src/test/ref/examples/scrolllogo/scrolllogo.asm @@ -29,11 +29,8 @@ // Color Ram .label COLS = $d800 .label SCREEN = $400 - .label LOGO = $2000 - // Remainder after unsigned 16-bit division - .label rem16u = $12 - .label xsin_idx = 2 - // kickasm + .label rem16u = $1d + .label xsin_idx = $27 main: { .const toD0181_return = (>(SCREEN&$3fff)*4)|(>LOGO)/4&$f // asm @@ -86,9 +83,9 @@ main: { rts } loop: { - .label __2 = $18 - .label __7 = $18 - .label xpos = $18 + .label __2 = $16 + .label __7 = $16 + .label xpos = $16 lda #<0 sta.z xsin_idx sta.z xsin_idx+1 @@ -145,13 +142,13 @@ loop: { dec VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR jmp __b1 } -// render_logo(signed word zp($18) xpos) +// render_logo(signed word zp($16) xpos) render_logo: { - .label __2 = $1a - .label xpos = $18 - .label x_char = $1c - .label logo_idx = 4 - .label logo_idx_1 = 5 + .label __2 = $1d + .label xpos = $16 + .label x_char = $18 + .label logo_idx = 2 + .label logo_idx_1 = 3 // (char)xpos&7 lda.z xpos and #7 @@ -318,19 +315,19 @@ render_logo: { // Generate signed int sinus table - with values in the range min-max. // sintab - the table to generate into // wavelength - the number of sinus points in a total sinus wavelength (the size of the table) -// sin16s_gen2(signed word* zp($18) sintab) +// sin16s_gen2(signed word* zp($14) sintab) sin16s_gen2: { .const min = -$140 .const max = $140 .label ampl = max-min - .label __6 = $a - .label __8 = $29 - .label step = $1d - .label sintab = $18 + .label __6 = 8 + .label __8 = $1d + .label step = $19 + .label sintab = $14 // u[4.28] // Iterate over the table - .label x = 6 - .label i = $16 + .label x = 4 + .label i = $27 // div32u16u(PI2_u4f28, wavelength) jsr div32u16u // div32u16u(PI2_u4f28, wavelength) @@ -418,13 +415,13 @@ sin16s_gen2: { } // Multiply of two signed ints to a signed long // Fixes offsets introduced by using unsigned multiplication -// mul16s(signed word zp($14) a) +// mul16s(signed word zp($12) a) mul16s: { - .label __6 = $25 - .label __11 = $25 - .label m = $a - .label return = $a - .label a = $14 + .label __6 = $23 + .label __11 = $23 + .label m = 8 + .label return = 8 + .label a = $12 // mul16u((unsigned int)a, (unsigned int) b) lda.z a sta.z mul16u.a @@ -463,13 +460,13 @@ mul16s: { rts } // Perform binary multiplication of two unsigned 16-bit unsigned ints into a 32-bit unsigned long -// mul16u(word zp($29) a, word zp($12) b) +// mul16u(word zp($10) a, word zp($1d) b) mul16u: { - .label mb = $e - .label a = $29 - .label res = $a - .label return = $a - .label b = $12 + .label mb = $c + .label a = $10 + .label res = 8 + .label return = 8 + .label b = $1d // mb = b lda.z b sta.z mb @@ -527,20 +524,20 @@ mul16u: { // Calculate signed int sinus sin(x) // x: unsigned long input u[4.28] in the interval $00000000 - PI2_u4f28 // result: signed int sin(x) s[0.15] - using the full range -$7fff - $7fff -// sin16s(dword zp($e) x) +// sin16s(dword zp($c) x) sin16s: { - .label __4 = $21 - .label x = $e - .label return = $14 - .label x1 = $25 - .label x2 = $1a - .label x3 = $1a - .label x3_6 = $27 - .label usinx = $14 - .label x4 = $1a - .label x5 = $27 - .label x5_128 = $27 - .label sinx = $14 + .label __4 = $1f + .label x = $c + .label return = $12 + .label x1 = $23 + .label x2 = $16 + .label x3 = $16 + .label x3_6 = $25 + .label usinx = $12 + .label x4 = $16 + .label x5 = $25 + .label x5_128 = $25 + .label sinx = $12 // if(x >= PI_u4f28 ) lda.z x+3 cmp #>PI_u4f28>>$10 @@ -738,14 +735,14 @@ sin16s: { } // Calculate val*val for two unsigned int values - the result is 16 selected bits of the 32-bit result. // The select parameter indicates how many of the highest bits of the 32-bit result to skip -// mulu16_sel(word zp($1a) v1, word zp($12) v2, byte register(X) select) +// mulu16_sel(word zp($16) v1, word zp($1d) v2, byte register(X) select) mulu16_sel: { - .label __0 = $a - .label __1 = $a - .label v1 = $1a - .label v2 = $12 - .label return = $27 - .label return_1 = $1a + .label __0 = 8 + .label __1 = 8 + .label v1 = $16 + .label v2 = $1d + .label return = $25 + .label return_1 = $16 // mul16u(v1, v2) lda.z v1 sta.z mul16u.a @@ -775,9 +772,9 @@ mulu16_sel: { // Divide unsigned 32-bit unsigned long dividend with a 16-bit unsigned int divisor // The 16-bit unsigned int remainder can be found in rem16u after the division div32u16u: { - .label quotient_hi = $27 - .label quotient_lo = $14 - .label return = $1d + .label quotient_hi = $25 + .label quotient_lo = $12 + .label return = $19 // divr16u(>dividend, divisor, 0) lda #>$10 sta.z divr16u.dividend @@ -817,12 +814,12 @@ div32u16u: { // Returns the quotient dividend/divisor. // The final remainder will be set into the global variable rem16u // Implemented using simple binary division -// divr16u(word zp($29) dividend, word zp($12) rem) +// divr16u(word zp($10) dividend, word zp($1d) rem) divr16u: { - .label rem = $12 - .label dividend = $29 - .label quotient = $14 - .label return = $14 + .label rem = $1d + .label dividend = $10 + .label quotient = $12 + .label return = $12 ldx #0 txa sta.z quotient @@ -881,11 +878,11 @@ divr16u: { rts } // Copies the character c (an unsigned char) to the first num characters of the object pointed to by the argument str. -// memset(void* zp($16) str, byte register(X) c) +// memset(void* zp($14) str, byte register(X) c) memset: { - .label end = $29 - .label dst = $16 - .label str = $16 + .label end = $27 + .label dst = $14 + .label str = $14 // end = (char*)str + num lda.z str clc @@ -918,8 +915,9 @@ memset: { } .align $100 xsin: .fill 2*XSIN_SIZE, 0 -.pc = LOGO "LOGO" - .var logoPic = LoadPicture("logo.png", List().add($444444, $808080, $000000, $ffffff)) +.pc = $2000 "LOGO" +LOGO: +.var logoPic = LoadPicture("logo.png", List().add($444444, $808080, $000000, $ffffff)) .for (var y=0; y<6 ; y++) .for (var x=0;x<40; x++) .for(var cp=0; cp<8; cp++) diff --git a/src/test/ref/examples/showlogo/showlogo.asm b/src/test/ref/examples/showlogo/showlogo.asm index e4f78fc7b..cbbb51ff9 100644 --- a/src/test/ref/examples/showlogo/showlogo.asm +++ b/src/test/ref/examples/showlogo/showlogo.asm @@ -21,8 +21,6 @@ // Color Ram .label COLS = $d800 .label SCREEN = $400 - .label LOGO = $2000 - // kickasm main: { .const toD0181_return = (>(SCREEN&$3fff)*4)|(>LOGO)/4&$f // VICII->BORDER_COLOR = WHITE @@ -108,8 +106,9 @@ memset: { !: jmp __b2 } -.pc = LOGO "LOGO" - .var logoPic = LoadPicture("logo.png", List().add($444444, $808080, $000000, $ffffff)) +.pc = $2000 "LOGO" +LOGO: +.var logoPic = LoadPicture("logo.png", List().add($444444, $808080, $000000, $ffffff)) .for (var y=0; y<6 ; y++) .for (var x=0;x<40; x++) .for(var cp=0; cp<8; cp++)