1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-06-18 10:29:37 +00:00

ecs: default field values

This commit is contained in:
Steven Hugg 2022-02-20 10:15:16 -06:00
parent a444de693b
commit 07c0ae2f9c
4 changed files with 46 additions and 7 deletions

View File

@ -143,6 +143,7 @@ banks need to duplicate code and/or rodata
- don't split critical code across banks - don't split critical code across banks
need bank trampoline macro need bank trampoline macro
nested scopes for game modes? (title / demo / play) nested scopes for game modes? (title / demo / play)
access parent data from child scope
critical data fields critical data fields
if accessed in critical section, make critical if accessed in critical section, make critical
@ -150,4 +151,8 @@ ignore arrays that aren't referenced
use DASM for multipass? use DASM for multipass?
default values for component fields processes
take up at least one byte if stateful
might need free list
need jump table?
you'd like to change "mode" from any event

View File

@ -139,7 +139,12 @@ export class ECSCompiler extends Tokenizer {
let lo = this.expectInteger(); let lo = this.expectInteger();
this.expectToken('..'); this.expectToken('..');
let hi = this.expectInteger(); let hi = this.expectInteger();
return { dtype: 'int', lo, hi } as IntType; // TODO: use default value?
let defvalue;
if (this.ifToken('default')) {
defvalue = this.expectInteger();
}
return { dtype: 'int', lo, hi, defvalue } as IntType;
} }
if (this.peekToken().str == '[') { if (this.peekToken().str == '[') {
return { dtype: 'ref', query: this.parseQuery() } as RefType; return { dtype: 'ref', query: this.parseQuery() } as RefType;
@ -392,8 +397,7 @@ export class ECSCompiler extends Tokenizer {
entname = this.expectIdent().str; entname = this.expectIdent().str;
} }
let etype = this.parseEntityArchetype(); let etype = this.parseEntityArchetype();
let entity = this.currentScope.newEntity(etype); let entity = this.currentScope.newEntity(etype, entname);
entity.name = entname;
let cmd2: string; let cmd2: string;
// TODO: remove init? // TODO: remove init?
while ((cmd2 = this.expectTokens(['const', 'init', 'var', 'decode', 'end']).str) != 'end') { while ((cmd2 = this.expectTokens(['const', 'init', 'var', 'decode', 'end']).str) != 'end') {

View File

@ -73,6 +73,24 @@ export class VCSSpriteDecoder extends LineDecoder {
} }
} }
export class VCSBitmapDecoder extends LineDecoder {
parse() {
let height = this.lines.length;
let bitmapdata = new Uint8Array(height);
for (let i=0; i<height; i++) {
this.curline = height - 1 - i;
let toks = this.lines[this.curline];
this.assertTokens(toks, 1);
bitmapdata[i] = this.decodeBits(toks[0], 8, true);
}
return {
properties: {
bitmapdata, height: height-1
}
}
}
}
export class VCSPlayfieldDecoder extends LineDecoder { export class VCSPlayfieldDecoder extends LineDecoder {
parse() { parse() {
let height = this.lines.length; let height = this.lines.length;
@ -178,6 +196,7 @@ export function newDecoder(name: string, text: string) : LineDecoder | undefined
const DECODERS = { const DECODERS = {
'vcs_sprite': VCSSpriteDecoder, 'vcs_sprite': VCSSpriteDecoder,
'vcs_bitmap': VCSBitmapDecoder,
'vcs_playfield': VCSPlayfieldDecoder, 'vcs_playfield': VCSPlayfieldDecoder,
'vcs_versatile': VCSVersatilePlayfieldDecoder, 'vcs_versatile': VCSVersatilePlayfieldDecoder,
'vcs_bitmap48': VCSBitmap48Decoder, 'vcs_bitmap48': VCSBitmap48Decoder,

View File

@ -156,6 +156,7 @@ export interface IntType {
dtype: 'int' dtype: 'int'
lo: number lo: number
hi: number hi: number
defvalue?: number
} }
export interface ArrayType { export interface ArrayType {
@ -1088,15 +1089,18 @@ export class EntityScope implements SourceLocated {
) { ) {
parent?.childScopes.push(this); parent?.childScopes.push(this);
} }
newEntity(etype: EntityArchetype): Entity { newEntity(etype: EntityArchetype, name: string): Entity {
// TODO: add parent ID? lock parent scope? // TODO: add parent ID? lock parent scope?
// TODO: name identical check? // TODO: name identical check?
if (name && this.getEntityByName(name))
throw new ECSError(`already an entity named "${name}"`);
let id = this.entities.length; let id = this.entities.length;
etype = this.em.addArchetype(etype); etype = this.em.addArchetype(etype);
let entity: Entity = { id, etype, consts: {}, inits: {} }; let entity: Entity = { id, etype, consts: {}, inits: {} };
for (let c of etype.components) { for (let c of etype.components) {
this.componentsInScope.add(c.name); this.componentsInScope.add(c.name);
} }
entity.name = name;
this.entities.push(entity); this.entities.push(entity);
return entity; return entity;
} }
@ -1172,7 +1176,14 @@ export class EntityScope implements SourceLocated {
} else { } else {
array.ehi = i; array.ehi = i;
} }
//console.log(i,e.name,array,cfname); // set default values for entity/field
if (ftype == 'init') {
if (f.dtype == 'int' && f.defvalue !== undefined) {
let ecfname = mkscopesymbol(this, c, f.name);
if (e.inits[ecfname] == null)
this.setInitValue(e, c, f, f.defvalue);
}
}
} }
} }
// TODO: cull unused entity fields // TODO: cull unused entity fields
@ -1323,7 +1334,7 @@ export class EntityScope implements SourceLocated {
let cfname = mksymbol(component, fieldName); let cfname = mksymbol(component, fieldName);
let ecfname = mkscopesymbol(this, component, fieldName); let ecfname = mkscopesymbol(this, component, fieldName);
if (e.consts[cfname] !== undefined) throw new ECSError(`"${fieldName}" is already defined as a constant`, e); if (e.consts[cfname] !== undefined) throw new ECSError(`"${fieldName}" is already defined as a constant`, e);
if (e.inits[ecfname] !== undefined) throw new ECSError(`"${fieldName}" is already defined as a`, e); if (e.inits[ecfname] !== undefined) throw new ECSError(`"${fieldName}" is already defined as a variable`, e);
if (type == 'const') e.consts[cfname] = value; if (type == 'const') e.consts[cfname] = value;
if (type == 'init') e.inits[ecfname] = value; if (type == 'init') e.inits[ecfname] = value;
this.fieldtypes[cfname] = type; this.fieldtypes[cfname] = type;