diff --git a/presets/c64/image-c64.multi.lz4 b/presets/c64/image-c64.multi.lz4 new file mode 100644 index 00000000..309957c0 Binary files /dev/null and b/presets/c64/image-c64.multi.lz4 differ diff --git a/presets/c64/testlz4.c b/presets/c64/testlz4.c new file mode 100644 index 00000000..50a0e704 --- /dev/null +++ b/presets/c64/testlz4.c @@ -0,0 +1,49 @@ + +// sid config so we don't use stack above $8000 + +//#resource "c64-sid.cfg" +#define CFGFILE c64-sid.cfg + +#include "common.h" +//#link "common.c" + +#include "mcbitmap.h" +//#link "mcbitmap.c" + +#include + +// include the LZ4 binary data -> image_c64_multi_lz4[] + +//#incbin "image-c64.multi.lz4" + +/* +CharData equ . +ScreenData equ CharData+8000 +ColorData equ ScreenData+1000 +XtraData equ ColorData+1000 +*/ + +void main() { + char* const uncomp = (char*)0xb000; + char bgcolor; + + // setup VIC for multicolor bitmap + // colormap = $c000-$c7ff + // bitmap = $e000-$ffff + setup_bitmap_multi(); + // enable HIMEM so we can write to $c000-$ffff + ENABLE_HIMEM(); + // decompress into $8000-$a711 + decompress_lz4(image_c64_multi_lz4+11, uncomp, 10002); + // read background color + bgcolor = uncomp[10000]; + // copy data to destination areas + memcpy((void*)MCB_BITMAP, uncomp, 8000); + memcpy(COLOR_RAM, uncomp+9000, 1000); + memcpy((void*)MCB_COLORS, uncomp+8000, 1000); + DISABLE_HIMEM(); + // set background color + VIC.bgcolor0 = bgcolor; + // wait for key + cgetc(); +} diff --git a/src/common/util.ts b/src/common/util.ts index d2687958..db372cf6 100644 --- a/src/common/util.ts +++ b/src/common/util.ts @@ -424,6 +424,9 @@ export function clamp(minv:number, maxv:number, v:number) { } export function safeident(s : string) : string { + // if starts with non-alpha character, prefix with '_' + if (s.length == 0) return ''; + if (!s.match(/^[a-zA-Z_]/)) s = '_' + s; return s.replace(/\W+/g, "_"); } diff --git a/src/ide/project.ts b/src/ide/project.ts index 83b42ab0..c9451257 100644 --- a/src/ide/project.ts +++ b/src/ide/project.ts @@ -200,9 +200,9 @@ export class CodeProject { this.pushAllFiles(files, m[2]); } // for .c -- //#resource "file" (or ;resource or #resource) - let re3 = /^\s*([;']|[/][/])#resource\s+"(.+?)"/gm; + let re3 = /^\s*([;']|[/][/])#(resource|incbin)\s+"(.+?)"/gm; while (m = re3.exec(text)) { - this.pushAllFiles(files, m[2]); + this.pushAllFiles(files, m[3]); } // for XASM only (USE include.ext) // for merlin32 (ASM include.ext) diff --git a/src/platform/c64.ts b/src/platform/c64.ts index 0c4e5505..65847938 100644 --- a/src/platform/c64.ts +++ b/src/platform/c64.ts @@ -23,6 +23,7 @@ const C64_PRESETS = [ {id:'test_multispritelib.c', name:'Sprite Multiplexing Library'}, {id:'scrolling_text.c', name:'Big Scrolling Text'}, {id:'mcbitmap.c', name:'Multicolor Bitmap Mode'}, + {id:'testlz4.c', name:'LZ4 Bitmap Compression'}, //{id:'mandel.c', name:'Mandelbrot Fractal'}, {id:'musicplayer.c', name:'Music Player'}, //{id:'sidtune.dasm', name:'Tiny SID Tune (ASM)'}, diff --git a/src/worker/tools/cc65.ts b/src/worker/tools/cc65.ts index 460aa5fd..383225ae 100644 --- a/src/worker/tools/cc65.ts +++ b/src/worker/tools/cc65.ts @@ -1,5 +1,5 @@ -import { getFilenamePrefix, getRootBasePlatform } from "../../common/util"; +import { convertDataToUint8Array, getFilenamePrefix, getRootBasePlatform, safeident } from "../../common/util"; import { CodeListingMap, WorkerError } from "../../common/workertypes"; import { re_crlf, BuildStepResult, anyTargetChanged, execMain, gatherFiles, msvcErrorMatcher, populateEntry, populateExtraFiles, populateFiles, print_fn, putWorkFile, setupFS, staleFiles, BuildStep, emglobal, loadNative, moduleInstFn, fixParamsWithDefines, store, makeErrorMatcher, getWorkFileAsString } from "../workermain"; import { EmscriptenModule } from "../workermain" @@ -272,6 +272,27 @@ export function linkLD65(step: BuildStep): BuildStepResult { } } +function processIncbin(code: string) { + let re3 = /^\s*([;']|[/][/])#incbin\s+"(.+?)"/gm; + // find #incbin "filename.bin" and replace with C array declaration + return code.replace(re3, (m, m1, m2) => { + let filename = m2; + let filedata = store.getFileData(filename); + let bytes = convertDataToUint8Array(filedata); + if (!bytes) throw new Error('#incbin: file not found: "' + filename + '"'); + let out = ''; + let ident = safeident(filename); + console.log('#incbin', filename, ident, bytes.length); + out += 'const unsigned char ' + ident + '[' + bytes.length + '] = {'; + for (let i = 0; i < bytes.length; i++) { + out += bytes[i].toString() + ','; + } + out += '};'; + console.log('incbin', out); + return out; + }); +} + export function compileCC65(step: BuildStep): BuildStepResult { loadNative("cc65"); var params = step.params; @@ -303,7 +324,15 @@ export function compileCC65(step: BuildStep): BuildStepResult { }); var FS = CC65.FS; setupFS(FS, '65-' + getRootBasePlatform(step.platform)); - populateFiles(step, FS); + populateFiles(step, FS, { + mainFilePath: step.path, + processFn: (path, code) => { + if (typeof code === 'string') { + code = processIncbin(code); + } + return code; + } + }); fixParamsWithDefines(step.path, params); var args = [ '-I', '/share/include',