1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2025-02-20 14:29:16 +00:00

ecs init values

This commit is contained in:
Steven Hugg 2022-01-26 21:12:11 -06:00
parent b00d43d1ea
commit 37167a2202

View File

@ -18,11 +18,15 @@
function mksymbol(c: ComponentType, fieldName: string) { function mksymbol(c: ComponentType, fieldName: string) {
return c.name + '_' + fieldName; return c.name + '_' + fieldName;
} }
function mkscopesymbol(s: EntityScope, c: ComponentType, fieldName: string) {
return s.name + '_' + c.name + '_' + fieldName;
}
export interface Entity { export interface Entity {
id: number; id: number;
etype: EntityArchetype; etype: EntityArchetype;
consts: {[name: string]: DataValue}; consts: {[component_field: string]: DataValue};
inits: {[scope_component_field: string]: DataValue};
} }
export interface EntityConst { export interface EntityConst {
@ -191,6 +195,21 @@ class Segment {
getFieldRange(component: ComponentType, fieldName: string) { getFieldRange(component: ComponentType, fieldName: string) {
return this.fieldranges[mksymbol(component, fieldName)]; return this.fieldranges[mksymbol(component, fieldName)];
} }
getSegmentByteOffset(component: ComponentType, fieldName: string, bitofs: number, entityID: number) {
let range = this.getFieldRange(component, fieldName);
if (range && range.access) {
let a = range.access[0]; // TODO: bitofs
let ofs = this.symbols[a.symbol];
if (ofs !== undefined) {
return ofs + entityID - range.elo;
}
}
}
getOriginSymbol() {
let a = this.ofs2sym.get(0);
if (!a) throw new Error('getOriginSymbol');
return a[0];
}
} }
function getFieldBits(f: IntType) { function getFieldBits(f: IntType) {
@ -241,7 +260,7 @@ export class EntityScope {
newEntity(etype: EntityArchetype) : Entity { newEntity(etype: EntityArchetype) : Entity {
// TODO: add parent ID? lock parent scope? // TODO: add parent ID? lock parent scope?
let id = this.entities.length; let id = this.entities.length;
let entity : Entity = {id, etype, consts:{}}; let entity : Entity = {id, etype, consts:{}, inits:{}};
this.em.archtypes.add(etype); this.em.archtypes.add(etype);
for (let c of etype.components) { for (let c of etype.components) {
this.componentsInScope.add(c.name); this.componentsInScope.add(c.name);
@ -326,10 +345,41 @@ export class EntityScope {
} }
//console.log(segment.initdata) //console.log(segment.initdata)
} }
allocateInitData(segment: Segment) {
let initbytes = new Uint8Array(segment.size);
let iter = this.iterateFields();
for (var o=iter.next(); o.value; o=iter.next()) {
let {i,e,c,f,v} = o.value;
let scfname = mkscopesymbol(this, c, f.name);
let initvalue = e.inits[scfname];
if (initvalue !== undefined) {
let offset = segment.getSegmentByteOffset(c, f.name, 0, e.id);
if (offset !== undefined && typeof initvalue === 'number') {
initbytes[offset] = initvalue; // TODO: > 8 bits?
} else {
throw new Error(`cannot access ${scfname}`);
}
}
}
// build the final init buffer
// TODO: compress 0s?
let bufsym = this.name + '__INITDATA';
let bufofs = this.rodata.allocateInitData(bufsym, initbytes);
let code = INITFROMARRAY;
//TODO: function to repalce from dict?
code = code.replace('%{nbytes}', initbytes.length.toString())
code = code.replace('%{src}', bufsym);
code = code.replace('%{dest}', segment.getOriginSymbol());
return code;
}
setConstValue(e: Entity, component: ComponentType, fieldName: string, value: DataValue) { setConstValue(e: Entity, component: ComponentType, fieldName: string, value: DataValue) {
// TODO: check to make sure component exists // TODO: check to make sure component exists
e.consts[mksymbol(component, fieldName)] = value; e.consts[mksymbol(component, fieldName)] = value;
} }
setInitValue(e: Entity, component: ComponentType, fieldName: string, value: DataValue) {
// TODO: check to make sure component exists
e.inits[mkscopesymbol(this, component, fieldName)] = value;
}
generateCodeForEvent(event: string): string { generateCodeForEvent(event: string): string {
// find systems that respond to event // find systems that respond to event
// and have entities in this scope // and have entities in this scope
@ -341,6 +391,7 @@ export class EntityScope {
//s += `\n; event ${event}\n`; //s += `\n; event ${event}\n`;
let emitcode : {[event: string] : string} = {}; let emitcode : {[event: string] : string} = {};
for (let sys of systems) { for (let sys of systems) {
// TODO: does this work if multiple actions?
if (sys.tempbytes) this.allocateTempBytes(sys.tempbytes); if (sys.tempbytes) this.allocateTempBytes(sys.tempbytes);
if (sys.emits) { if (sys.emits) {
for (let emit of sys.emits) { for (let emit of sys.emits) {
@ -434,7 +485,7 @@ export class EntityScope {
} }
// TODO: offset > 0? // TODO: offset > 0?
//let range = this.bss.getFieldRange(component, fieldName); //let range = this.bss.getFieldRange(component, fieldName);
return `${component.name}_${fieldName}_b${bitofs},x` return `${component.name}_${fieldName}_b${bitofs},x` // TODO? ,x?
} }
entitiesMatching(atypes: ArchetypeMatch[]) { entitiesMatching(atypes: ArchetypeMatch[]) {
let result = []; let result = [];
@ -483,8 +534,11 @@ export class EntityScope {
} }
generateCode() { generateCode() {
this.tempOffset = this.maxTempBytes = 0; this.tempOffset = this.maxTempBytes = 0;
let init = this.generateCodeForEvent('init'); this.code.addCodeFragment(TEMPLATE_INIT);
this.code.addCodeFragment(init); let initcode = this.allocateInitData(this.bss);
this.code.addCodeFragment(initcode);
let start = this.generateCodeForEvent('start');
this.code.addCodeFragment(start);
for (let sub of Array.from(this.subroutines.values())) { for (let sub of Array.from(this.subroutines.values())) {
let code = this.generateCodeForEvent(sub); let code = this.generateCodeForEvent(sub);
this.code.addCodeFragment(code); this.code.addCodeFragment(code);
@ -576,7 +630,6 @@ const FOOTER = `
const TEMPLATE_INIT = ` const TEMPLATE_INIT = `
Start: Start:
CLEAN_START CLEAN_START
%{!start}
` `
const TEMPLATE1 = ` const TEMPLATE1 = `
@ -622,23 +675,36 @@ const TEMPLATE1 = `
`; `;
// TODO: two sticks? // TODO: two sticks?
const TEMPLATE2 = ` const TEMPLATE2_a = `
;#ifdef EVENT_joyleft lda SWCHA
lda #%01000000 ;Left? sta %{$0}
bit SWCHA `
bne %{.SkipMoveLeft} const TEMPLATE2_b = `
asl %{$0}
bcs %{.SkipMoveRight}
%{!joyright}
%{.SkipMoveRight}
asl %{$0}
bcs %{.SkipMoveLeft}
%{!joyleft} %{!joyleft}
%{.SkipMoveLeft} %{.SkipMoveLeft}
;#endif asl %{$0}
bcs %{.SkipMoveDown}
%{!joydown}
%{.SkipMoveDown}
asl %{$0}
bcs %{.SkipMoveUp}
%{!joyup}
%{.SkipMoveUp}
`; `;
const TEMPLATE3_L = ` const TEMPLATE3_L = `
lda %{<xpos} lda %{<xpos}
sec sec
sbc #1 sbc #1
bcc %{.noclip} bcc %{.nomove}
sta %{<xpos} sta %{<xpos}
%{.noclip} %{.nomove}
`; `;
const TEMPLATE3_R = ` const TEMPLATE3_R = `
@ -646,49 +712,64 @@ const TEMPLATE3_R = `
clc clc
adc #1 adc #1
cmp #160 cmp #160
bcc %{.noclip} bcs %{.nomove}
sta %{<xpos} sta %{<xpos}
%{.noclip} %{.nomove}
`; `;
const TEMPLATE4_S = ` const TEMPLATE4_S = `
txa ; TODO ldy hasbitmap_bitmap_b0+0
asl
tya
lda %{<bitmap} ; bitmap address
tay
lda bitmap_bitmapdata_b0,y lda bitmap_bitmapdata_b0,y
sta %{$0},y sta %{$0}
lda bitmap_bitmapdata_b8,y lda bitmap_bitmapdata_b8,y
sta %{$1},y sta %{$1}
ldy hascolormap_colormap_b0+0
lda colormap_colormapdata_b0,y lda colormap_colormapdata_b0,y
sta %{$2},y sta %{$2}
lda colormap_colormapdata_b8,y
sta %{$3}
lda sprite_height_b0+0
sta %{$4}
lda ypos_ypos_b0+0
sta %{$5}
ldy hasbitmap_bitmap_b0+1
lda bitmap_bitmapdata_b0,y
sta %{$6}
lda bitmap_bitmapdata_b8,y
sta %{$7}
ldy hascolormap_colormap_b0+1
lda colormap_colormapdata_b0,y lda colormap_colormapdata_b0,y
sta %{$3},y sta %{$8}
lda sprite_height_b0,y lda colormap_colormapdata_b8,y
sta %{$4},y sta %{$9}
lda ypos_ypos_b0,y lda sprite_height_b0+1
sta %{$5},y sta %{$10}
lda ypos_ypos_b0+1
sta %{$11}
` `
// https://atariage.com/forums/topic/75982-skipdraw-and-graphics/?tab=comments#comment-928232
// https://atariage.com/forums/topic/129683-advice-on-a-masking-kernel/
// https://atariage.com/forums/topic/128147-having-trouble-with-2-free-floating-player-graphics/?tab=comments#comment-1547059
const TEMPLATE4_K = ` const TEMPLATE4_K = `
ldx #192 ; lines in kernel ldx #192 ; lines in kernel
LVScan LVScan
txa ; X -> A txa ; X -> A
sec ; set carry for subtract sec ; set carry for subtract
sbc %{$5} ; local coordinate sbc %{$5} ; local coordinate
cmp %{$4} ; in sprite? (height) cmp %{$4} ; in sprite? (height)
bcc InSprite ; yes, skip over next bcc InSprite ; yes, skip over next
lda #0 ; not in sprite, load 0 lda #0 ; not in sprite, load 0
InSprite InSprite
tay ; local coord -> Y tay ; local coord -> Y
lda (%{$0}),y ; lookup color lda (%{$0}),y ; lookup color
sta WSYNC ; sync w/ scanline sta WSYNC ; sync w/ scanline
sta GRP0 ; store bitmap sta GRP0 ; store bitmap
lda (%{$2}),y ; lookup color lda (%{$2}),y ; lookup color
sta COLUP0 ; store color sta COLUP0 ; store color
dex ; decrement X dex ; decrement X
bne LVScan ; repeat until 192 lines bne LVScan ; repeat until 192 lines
`; `;
const SET_XPOS = ` const SET_XPOS = `
@ -714,9 +795,43 @@ DivideLoop
asl asl
sta RESP0,y ; fix coarse position sta RESP0,y ; fix coarse position
sta HMP0,y ; set fine offset sta HMP0,y ; set fine offset
sta WSYNC
sta HMOVE
rts ; return to caller rts ; return to caller
` `
const INITFROMSPARSE = `
MemSrc equ $80
MemDest equ $82
InitMemory
ldy #0
lda (MemSrc),y
beq .done
tax
iny
lda (MemSrc),y
sta MemDest
iny
lda (MemSrc),y
sta MemDest+1
.loop
iny
lda (MemSrc),y
sta (MemDest),y
dex
bne .loop
.done rts
`
const INITFROMARRAY = `
ldy #%{nbytes}
.loop
lda %{src}-1,y
sta %{dest}-1,y
dey
bne .loop
`
function test() { function test() {
let em = new EntityManager(); let em = new EntityManager();
@ -767,7 +882,7 @@ function test() {
include:['sprite','hasbitmap','hascolormap','ypos'], include:['sprite','hasbitmap','hascolormap','ypos'],
}, },
actions:[ actions:[
{ text:TEMPLATE4_S, event:'preframe', iterate:'each' }, { text:TEMPLATE4_S, event:'preframe', iterate:'once' },
{ text:TEMPLATE4_K, event:'kernel', iterate:'once' }, { text:TEMPLATE4_K, event:'kernel', iterate:'once' },
] ]
}) })
@ -785,17 +900,8 @@ function test() {
// TODO: easy stagger of system update? // TODO: easy stagger of system update?
// TODO: easy lookup tables // TODO: easy lookup tables
// TODO: how to init? // TODO: how to init?
// https://docs.unity3d.com/Packages/com.unity.entities@0.17/manual/ecs_systems.html // https://docs.unity3d.com/Packages/com.unity.entities@0.17/manual/ecs_systems.html
em.defineSystem({
name:'init',
emits:['start'],
query:{
include:[], // ???
},
actions:[
{ text:TEMPLATE_INIT, event:'init', iterate:'once' }
]
})
em.defineSystem({ em.defineSystem({
name:'frameloop', name:'frameloop',
emits:['preframe','kernel','postframe'], emits:['preframe','kernel','postframe'],
@ -811,9 +917,11 @@ function test() {
query:{ query:{
include:['player'] include:['player']
}, },
tempbytes:1,
emits:['joyup','joydown','joyleft','joyright','joybutton'], emits:['joyup','joydown','joyleft','joyright','joybutton'],
actions:[ actions:[
{ text:TEMPLATE2, event:'postframe', iterate:'each' } { text:TEMPLATE2_a, event:'postframe', iterate:'once' },
{ text:TEMPLATE2_b, event:'postframe', iterate:'each' }
] ]
}); });
em.defineSystem({ em.defineSystem({
@ -828,7 +936,7 @@ function test() {
}); });
em.defineSystem({ em.defineSystem({
name:'SetHorizPos', name:'SetHorizPos',
query:{ include:[] }, query:{ include:[] }, // TODO?
actions:[ actions:[
{ text:SETHORIZPOS, event:'SetHorizPos', iterate:'once' }, // TODO: event source? { text:SETHORIZPOS, event:'SetHorizPos', iterate:'once' }, // TODO: event source?
] ]
@ -848,7 +956,15 @@ function test() {
let ea_playerSprite = {components:[c_sprite,c_hasbitmap,c_hascolormap,c_xpos,c_ypos,c_player]}; let ea_playerSprite = {components:[c_sprite,c_hasbitmap,c_hascolormap,c_xpos,c_ypos,c_player]};
let e_player0 = root.newEntity(ea_playerSprite); let e_player0 = root.newEntity(ea_playerSprite);
root.setInitValue(e_player0, c_sprite, 'plyrindex', 0);
root.setInitValue(e_player0, c_sprite, 'height', 8);
root.setInitValue(e_player0, c_xpos, 'xpos', 50);
root.setInitValue(e_player0, c_ypos, 'ypos', 50);
let e_player1 = root.newEntity(ea_playerSprite); let e_player1 = root.newEntity(ea_playerSprite);
root.setInitValue(e_player1, c_sprite, 'plyrindex', 1);
root.setInitValue(e_player1, c_sprite, 'height', 8);
root.setInitValue(e_player1, c_xpos, 'xpos', 100);
root.setInitValue(e_player1, c_ypos, 'ypos', 60);
let src = new SourceFileExport(); let src = new SourceFileExport();
root.analyzeEntities(); root.analyzeEntities();
@ -857,4 +973,6 @@ function test() {
console.log(src.toString()); console.log(src.toString());
} }
// TODO: files in markdown?
test(); test();