From 999aed9cb4ba092b357d673b09307860f265561a Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Wed, 9 Feb 2022 11:45:40 -0600 Subject: [PATCH] ecs: data , 48 pixel decoder --- presets/vcs/vcs-ca65.h | 13 ++++++++ src/common/ecs/decoder.ts | 29 ++++++++++++++++ src/common/ecs/ecs.ts | 69 ++++++++++++++++++++++++++------------- test/ecs/vcs1.txt | 16 ++++----- 4 files changed, 96 insertions(+), 31 deletions(-) diff --git a/presets/vcs/vcs-ca65.h b/presets/vcs/vcs-ca65.h index 87a4b7d5..9a8fc374 100644 --- a/presets/vcs/vcs-ca65.h +++ b/presets/vcs/vcs-ca65.h @@ -266,3 +266,16 @@ LINESD12 = 16 SLEEP cycles .endif .endmacro + +;----------------------------------------------------------- +; SLEEPH - sleep macro that uses PHA/PLA for 12 cycle delays + +.macro SLEEPH cycles +.if cycles >= 9 || cycles = 7 + pha + pla + SLEEPH (cycles-7) +.else + SLEEP cycles +.endif +.endmacro diff --git a/src/common/ecs/decoder.ts b/src/common/ecs/decoder.ts index 8f2a8617..7af1feef 100644 --- a/src/common/ecs/decoder.ts +++ b/src/common/ecs/decoder.ts @@ -103,6 +103,34 @@ export class VCSVersatilePlayfieldDecoder extends LineDecoder { } } +export class VCSBitmap48Decoder extends LineDecoder { + parse() { + let height = this.lines.length; + let bitmap0 = new Uint8Array(height); + let bitmap1 = new Uint8Array(height); + let bitmap2 = new Uint8Array(height); + let bitmap3 = new Uint8Array(height); + let bitmap4 = new Uint8Array(height); + let bitmap5 = new Uint8Array(height); + for (let i=0; i 1) { + // TODO: when to ignore if entities.length == 1 and not in for loop? + if (action.select == 'with') { code = this.wrapCodeInFilter(code); } - if (action.select == 'if' && entities.length > 1) { + if (action.select == 'if') { code = this.wrapCodeInFilter(code); } if (action.select == 'foreach' && entities.length > 1) { @@ -678,15 +689,24 @@ class ActionEval { let bitofs = parseInt(args[1] || '0'); return this.generateCodeForField(fieldName, bitofs, canwrite); } - __base(args: string[]) { - // TODO: refactor into generateCode.. + parseFieldArgs(args: string[]) { let fieldName = args[0]; let bitofs = parseInt(args[1] || '0'); let component = this.em.singleComponentWithFieldName(this.qr.atypes, fieldName, this.action); let field = component.fields.find(f => f.name == fieldName); if (field == null) throw new ECSError(`no field named "${fieldName}" in component`, this.action); + return { component, field, bitofs }; + } + __base(args: string[]) { + let { component, field, bitofs } = this.parseFieldArgs(args); return this.dialect.fieldsymbol(component, field, bitofs); } + __data(args: string[]) { + let { component, field, bitofs } = this.parseFieldArgs(args); + if (this.qr.entities.length != 1) throw new ECSError(`data command operates on exactly one entity`); // TODO? + let eid = this.qr.entities[0].id; // TODO? + return this.dialect.datasymbol(component, field, eid, bitofs); + } __index(args: string[]) { // TODO: check select type and if we actually have an index... let ident = args[0]; @@ -798,6 +818,7 @@ class ActionEval { if (!range) throw new ECSError(`couldn't find field for ${component.name}:${fieldName}, maybe no entities?`); // TODO // TODO: dialect let eidofs = qr.entities.length && qr.entities[0].id - range.elo; // TODO: negative? + // TODO: array field baseoffset? if (baseLookup) { return this.dialect.absolute(ident); } else if (entities.length == 1) { @@ -983,11 +1004,13 @@ export class EntityScope implements SourceLocated { // this is not a constant // is it a bounded array? (TODO) if (f.dtype == 'array' && f.index) { - let datasym = this.dialect.datasymbol(c, f, e.id); + let datasym = this.dialect.datasymbol(c, f, e.id, 0); let databytes = getFieldLength(f.index); let offset = this.bss.allocateBytes(datasym, databytes); + // TODO? this.allocatePointerArray(c, f, datasym, entcount); let ptrlosym = this.dialect.fieldsymbol(c, f, 0); let ptrhisym = this.dialect.fieldsymbol(c, f, 8); + // TODO: what if we don't need a pointer array? let loofs = segment.allocateBytes(ptrlosym, entcount); let hiofs = segment.allocateBytes(ptrhisym, entcount); if (f.baseoffset) datasym = `(${datasym}+${f.baseoffset})`; @@ -997,8 +1020,9 @@ export class EntityScope implements SourceLocated { } else { // this is a constant // is it a byte array? + //TODO? if (ArrayBuffer.isView(v) && f.dtype == 'array') { if (v instanceof Uint8Array && f.dtype == 'array') { - let datasym = this.dialect.datasymbol(c, f, e.id); + let datasym = this.dialect.datasymbol(c, f, e.id, 0); segment.allocateInitData(datasym, v); let ptrlosym = this.dialect.fieldsymbol(c, f, 0); let ptrhisym = this.dialect.fieldsymbol(c, f, 8); @@ -1007,7 +1031,6 @@ export class EntityScope implements SourceLocated { if (f.baseoffset) datasym = `(${datasym}+${f.baseoffset})`; segment.initdata[loofs + e.id - range.elo] = { symbol: datasym, bitofs: 0 }; segment.initdata[hiofs + e.id - range.elo] = { symbol: datasym, bitofs: 8 }; - // TODO: } else if (v instanceof Uint16Array) { } else if (typeof v === 'number') { // more than 1 entity, add an array if (entcount > 1) { @@ -1020,7 +1043,8 @@ export class EntityScope implements SourceLocated { } // TODO: what if mix of var, const, and init values? } else { - throw new ECSError(`unhandled constant ${e.id}:${cfname}`); + // TODO: bad error message - should say "wrong type, should be array" + throw new ECSError(`unhandled constant ${e.id}:${cfname} -- ${typeof v}`); } } } @@ -1044,8 +1068,8 @@ export class EntityScope implements SourceLocated { initbytes[offset] = (initvalue >> a.bit) & ((1 << a.width) - 1); } } else if (initvalue instanceof Uint8Array) { - // TODO??? - let datasym = this.dialect.datasymbol(c, f, e.id); + // TODO: 16/32... + let datasym = this.dialect.datasymbol(c, f, e.id, 0); let ofs = this.bss.symbols[datasym]; initbytes.set(initvalue, ofs); } else { @@ -1095,13 +1119,12 @@ export class EntityScope implements SourceLocated { //s += `\n; event ${event}\n`; systems = systems.filter(s => this.systems.includes(s)); for (let sys of systems) { - let tmplabel = this.dialect.tempLabel(sys); for (let action of sys.actions) { if (action.event == event) { // TODO: use Tokenizer so error msgs are better // TODO: keep event tree let codeeval = new ActionEval(this, sys, action); - codeeval.tmplabel = tmplabel; + codeeval.tmplabel = this.dialect.tempLabel(sys); codeeval.begin(); s += this.dialect.comment(`start action ${sys.name} ${event}`); // TODO s += codeeval.codeToString(); diff --git a/test/ecs/vcs1.txt b/test/ecs/vcs1.txt index aba14e40..082244e5 100644 --- a/test/ecs/vcs1.txt +++ b/test/ecs/vcs1.txt @@ -83,10 +83,10 @@ FrameLoop__start__2__NextFrame: ;;; start action StaticKernel kernelsetup cpx #0+2 - bcs StaticKernel__kernelsetup__5____skipxhi + jcs StaticKernel__kernelsetup__5____skipxhi cpx #0 - bcc StaticKernel__kernelsetup__5____skipxlo + jcc StaticKernel__kernelsetup__5____skipxlo lda PFColor_pfcolor_b0,x sta COLUPF @@ -100,10 +100,10 @@ StaticKernel__kernelsetup__5____skipxhi: ;;; start action StaticKernel kernelsetup cpx #0+4 - bcs StaticKernel__kernelsetup__6____skipxhi + jcs StaticKernel__kernelsetup__6____skipxhi cpx #0 - bcc StaticKernel__kernelsetup__6____skipxlo + jcc StaticKernel__kernelsetup__6____skipxlo lda Playfield_pf_b0,x sta PF0 @@ -142,10 +142,10 @@ StaticKernel__kernel__7____each: ;;; start action StaticKernel kernelsetup cpx #5+2 - bcs StaticKernel__kernelsetup__9____skipxhi + jcs StaticKernel__kernelsetup__9____skipxhi cpx #5 - bcc StaticKernel__kernelsetup__9____skipxlo + jcc StaticKernel__kernelsetup__9____skipxlo lda PFColor_pfcolor_b0-5,x sta COLUPF @@ -159,7 +159,7 @@ StaticKernel__kernelsetup__9____skipxhi: ;;; start action StaticKernel kernelsetup cpx #4 - bcc StaticKernel__kernelsetup__10____skipxlo + jcc StaticKernel__kernelsetup__10____skipxlo lda Playfield_pf_b0-4,x sta PF0 @@ -182,7 +182,7 @@ StaticKernel__kernel__7__loop: inx cpx #8 - bne StaticKernel__kernel__7____each + jne StaticKernel__kernel__7____each StaticKernel__kernel__7____exit: ;;; end action StaticKernel kernel