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:
parent
b00d43d1ea
commit
37167a2202
@ -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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user