1 module dengapi
is aliced
;
19 // ////////////////////////////////////////////////////////////////////////// //
20 private extern (C
) void _d_print_throwable (Throwable t
);
23 // ////////////////////////////////////////////////////////////////////////// //
28 // ////////////////////////////////////////////////////////////////////////// //
31 enum PLK_DOWN
= (1<<1);
32 enum PLK_LEFT
= (1<<2);
33 enum PLK_RIGHT
= (1<<3);
34 enum PLK_FIRE
= (1<<4);
35 enum PLK_JUMP
= (1<<5);
36 enum PLK_USE
= (1<<6);
39 __gshared
uint plrKeysLast
;
40 __gshared
uint plrKeyState
;
43 public void plrKeyDown (uint plidx
, uint mask
) {
44 if (mask
== 0 || plidx
> 0) return;
50 public void plrKeyUp (uint plidx
, uint mask
) {
51 if (mask
== 0 || plidx
> 0) return;
56 public void plrKeyUpDown (uint plidx
, uint mask
, bool down
) {
57 if (down
) plrKeyDown(plidx
, mask
); else plrKeyUp(plidx
, mask
);
61 void plrKeysFix (uint plidx
) {
62 if (plidx
> 0) return;
63 //conwritefln!"plrKeyState=0x%02x; plrKeysLast=0x%02x"(plrKeyState, plrKeysLast);
64 foreach (uint n
; 0..12) {
65 if ((plrKeyState
&(1<<n
)) == 0) plrKeysLast
&= ~(1<<n
);
70 // ////////////////////////////////////////////////////////////////////////// //
71 void updateActorClasses (int iteration
) {
72 foreach (string ctype
; dacsClassTypes(iteration
)) {
73 foreach (auto mod
; dacsClassModules(ctype
, iteration
)) {
74 auto adef
= registerActorDef(mod
.rmoduletype
.classtype
, mod
.rmoduletype
.classname
);
75 conwriteln("found info for actor '", adef
.fullname
, "'");
77 auto animInitFn
= FuncPool
.findByFQMG(mod
.name
~".initializeAnim", ":void");
78 if (animInitFn
!is null) adef
.setAnimInitFunc(animInitFn
);
81 auto initFn
= FuncPool
.findByFQMG(mod
.name
~".initialize", ":void:Actor");
82 if (initFn
!is null) adef
.setInitFunc(initFn
);
85 auto thinkFn
= FuncPool
.findByFQMG(mod
.name
~".think", ":void:Actor");
86 if (thinkFn
!is null) adef
.setThinkFunc(thinkFn
);
89 auto onTouchFn
= FuncPool
.findByFQMG(mod
.name
~".onTouch", ":void:Actor:Actor");
90 if (onTouchFn
!is null) adef
.setOnTouchFunc(onTouchFn
);
97 // ////////////////////////////////////////////////////////////////////////// //
98 private string
modLoader (string modname
) {
99 static string
getTextFile (string fname
) {
101 auto res
= loadTextFile(fname
);
102 conwriteln("loading DACS module file '", fname
, "' (", res
.length
, " bytes)");
103 if (res
is null) res
= "";
105 } catch (Exception
) {}
111 //res = getTextFile(modname~".dacs");
112 //if (res !is null) return res;
114 res
= getTextFile("scripts/"~modname
~".dacs");
115 if (res
!is null) return res
;
118 string
[] parts
= ["scripts"];
120 while (mn
.length
> 0) {
122 if (mn
[0] >= 'A' && mn
[0] <= 'Z') ++pos
;
123 while (pos
< mn
.length
&& (mn
[pos
] < 'A' || mn
[pos
] > 'Z')) ++pos
;
124 if (mn
[0] >= 'A' && mn
[0] <= 'Z') {
125 parts
~= cast(char)(mn
[0]+32)~mn
[1..pos
];
132 import std
.array
: join
;
133 string path
= parts
.join("/")~".dacs";
134 res
= getTextFile(path
);
135 if (res
!is null) return res
;
139 throw new Exception("module '"~modname
~"' not found");
143 __gshared
int modIteration
= 0;
145 public void loadWadScripts () {
146 if (moduleLoader
is null) moduleLoader
= (string modname
) => modLoader(modname
);
149 import std
.array
: split
;
150 auto t
= loadTextFile("scripts/dacsmain.txt");
151 foreach (string line
; t
.split('\n')) {
152 while (line
.length
&& line
[0] <= ' ') line
= line
[1..$];
153 if (line
.length
== 0 || line
[0] == ';') continue;
154 while (line
.length
&& line
[$-1] <= ' ') line
= line
[0..$-1];
157 } catch (Exception e
) { return; }
159 //conwriteln("loading main DACS module '", mainmod, "'");
160 auto iter
= modIteration
++;
161 conwriteln("iteration=", iter
);
162 foreach (string mod
; mainmods
) {
163 parseModule(mod
, iter
);
165 conwriteln("calling parseComplete; iteration=", iter
);
167 updateActorClasses(iter
);
168 } catch (CompilerException e
) {
169 _d_print_throwable(e
);
170 conwriteln("PARSE ERROR: ", e
.file
, " at ", e
.line
);
171 conwriteln(e
.toString
);
177 public void scriptLoadingComplete () {
179 dacsFinalizeCompiler();
183 // ////////////////////////////////////////////////////////////////////////// //
184 public __gshared LevelMap map
;
185 //public __gshared DACSVM dvm;
186 public __gshared
uint prngSyncSeed
= 0x29a;
187 public __gshared
uint prngSeed
= 0x29a; // unsynced
190 // ////////////////////////////////////////////////////////////////////////// //
191 // Park-Miller-Carta Pseudo-Random Number Generator, based on David G. Carta paper
192 // 31 bit of randomness
193 // seed is previous result, as usual
194 public uint prngR31next (uint seed
) {
195 if (seed
== 0) seed
= 0x29a;
196 uint lo
= 16807*(seed
&0xffff);
197 uint hi
= 16807*(seed
>>16);
198 lo
+= (hi
&0x7fff)<<16;
200 //if (lo > 0x7fffffff) lo -= 0x7fffffff; // should be >=, actually
201 lo
= (lo
&0x7FFFFFFF)+(lo
>>31); // same as previous code, but branch-less
206 // "synced" random, using common seed for all players
207 public uint syncrandu31 () {
208 pragma(inline
, true);
209 return (prngSyncSeed
= prngR31next(prngSyncSeed
));
213 // ////////////////////////////////////////////////////////////////////////// //
214 version(dacs_use_vm
) {
215 // this is VAT function, argument order is reversed
216 void doWrite(bool donl
) (FuncPool
.FuncInfo fi
, DACSVM vm
) {
218 auto count
= vm
.popInt();
219 while (count
-- > 0) {
220 auto type
= vm
.popInt();
221 switch (cast(VATArgType
)type
) {
222 case VATArgType
.Int
: write(vm
.popInt()); break;
223 case VATArgType
.Uint
: write(vm
.popUint()); break;
224 case VATArgType
.Float
: write(vm
.popFloat()); break;
225 case VATArgType
.StrId
: write(StrId(vm
.popUint()).get
); break;
226 case VATArgType
.ActorId
: write("<actor>"); vm
.popUint(); break; //TODO
227 default: write("<invalid-type>"); vm
.popUint(); break; //TODO
230 static if (donl
) writeln();
231 // push dummy return value
235 extern(C
) void doWrite(bool donl
) (uint argc
, ...) {
238 mainloop
: while (argc
>= 2) {
240 int tp
= va_arg
!int(_argptr
);
243 auto v
= va_arg
!int(_argptr
);
246 case VATArgType
.Uint
:
247 auto v
= va_arg
!uint(_argptr
);
250 case VATArgType
.Float
:
251 auto v
= va_arg
!float(_argptr
);
254 case VATArgType
.StrId
:
255 auto v
= StrId(va_arg
!uint(_argptr
)).get
;
258 case VATArgType
.ActorId
:
259 auto v
= ActorId(va_arg
!uint(_argptr
));
260 //write("<actor:", v.valid, ":", v.id, ">");
263 default: write("<invalid-type>"); break mainloop
;
266 static if (donl
) writeln();
271 // ////////////////////////////////////////////////////////////////////////// //
272 void animClearFrames (StrId classtype
, StrId classname
, StrId state
) {
273 auto adef
= findActorDef(classtype
.get
, classname
.get
);
274 if (adef
is null) throw new Exception("animClearFrames: actor '"~classtype
.get
~":"~classname
.get
~"' not found!");
275 adef
.clearFrames(state
);
279 void animAddFrame (StrId classtype
, StrId classname
, StrId state
, uint dir
, StrId sprname
) {
280 auto adef
= findActorDef(classtype
.get
, classname
.get
);
281 if (adef
is null) throw new Exception("animAddFrame: actor '"~classtype
.get
~":"~classname
.get
~"' not found!");
282 if (dir
!= 0) dir
= 1; //TODO: process mirror flag here
283 adef
.addFrame(state
, dir
, sprname
);
287 // ////////////////////////////////////////////////////////////////////////// //
289 conwriteln("setting up D API");
291 FuncPool
["write"] = &doWrite
!false;
292 FuncPool
["writeln"] = &doWrite
!true;
294 FuncPool
["syncrandu31"] = &syncrandu31
;
296 FuncPool
["animClearFrames"] = &animClearFrames
;
297 FuncPool
["animAddFrame"] = &animAddFrame
;
299 FuncPool
["actorSetAnimation"] = function void (ActorId me
, StrId state
) {
300 if (!me
.valid
) return;
301 if (auto adef
= findActorDef(me
.classtype
!string
, me
.classname
!string
)) {
302 me
.zAnimstate
= state
;
307 FuncPool
["getPlayer"] = function ActorId () { assert(0); };
309 FuncPool
["getPlayerButtons"] = function uint (uint pidx
) { return (pidx
== 0 ? plrKeysLast
: 0); };
311 FuncPool
["mapGetTypeTile"] = function int (int x
, int y
) {
312 return (map
!is null && x
>= 0 && y
>= 0 && x
< map
.width
&& y
< map
.height ? map
.tiles
.ptr
[LevelMap
.Type
].ptr
[y
*map
.width
+x
] : 0);
315 FuncPool
["mapGetTile"] = function int (uint layer
, int x
, int y
) {
316 return (map
!is null && x
>= 0 && y
>= 0 && x
< map
.width
&& y
< map
.height
&& layer
>= 0 && layer
<= 1 ? map
.tiles
.ptr
[LevelMap
.Front
+layer
].ptr
[y
*map
.width
+x
] : 0);
319 FuncPool
["getMapViewHeight"] = function int () {
320 import xmain_d2d
: vlWidth
, vlHeight
, scale
;
321 return vlHeight
/scale
;
324 FuncPool
["setMapViewPos"] = function void (int x
, int y
) {
325 import xmain_d2d
: setMapViewPos
;
330 public void registerAPI () {
331 conwriteln("actor size is ", Actor
.actorSize
, " bytes");
333 version(dacs_use_vm
) FuncPool
.vm
= new DACSVM();
334 //dvm = new DACSVM();
336 // initialize actor animation
337 foreach (ActorDef adef
; actordefs
.byValue
) {
341 conwriteln("API registered");
345 // ////////////////////////////////////////////////////////////////////////// //
346 __gshared ActorId
[2] players
;
348 public void loadMapMonsters () {
349 assert(map
!is null);
350 players
[] = ActorId(0);
351 //conwriteln(players[0].valid, "; ", players[0].id);
352 foreach (ref thing
; map
.things
) {
353 if (thing
.dmonly
) continue;
354 if (auto did
= thing
.type
in d2dactordefsById
) {
355 //if (did.classtype == "item") continue;
356 if (did
.classtype
== "playerstart") {
357 if (thing
.type
== 1 || thing
.type
== 2) {
358 int pnum
= thing
.type
-1;
359 if (!players
[pnum
].valid
) {
360 auto aid
= Actor
.alloc
;
361 aid
.classtype
= StrPool
.intern("monster");
362 aid
.classname
= StrPool
.intern("Player");
363 aid
.plrnum
= cast(uint)pnum
;
364 aid
.state
= StrPool
.MNST_SLEEP
;
365 aid
.x
= cast(int)thing
.x
;
366 aid
.y
= cast(int)thing
.y
;
367 aid
.dir
= cast(uint)(thing
.right ?
1 : 0);
368 auto adef
= findD2DActorDef(thing
.type
);
369 if (adef
is null) assert(0);
372 conwriteln("player #", pnum
+1, " aid is ", aid
.id
);
375 import xmain_d2d
: setMapViewPos
;
376 setMapViewPos(aid
.x
!int, aid
.y
!int);
383 auto adef
= findD2DActorDef(thing
.type
);
385 if (auto did
= thing
.type
in d2dactordefsById
) {
386 conwriteln("ignoring D2D thing '", did
.fullname
, "'");
388 conwriteln("ignoring unknown D2D thing with mapid ", thing
.type
);
392 // load graphics (we'll load all graphics)
393 //adef.loadGraphics();
394 // create actor and initialize it
395 auto aid
= Actor
.alloc
;
396 aid
.classtype
= StrPool
.intern(adef
.classtype
);
397 aid
.classname
= StrPool
.intern(adef
.classname
);
398 //conwriteln("found '", aid.classtype.get, ":", aid.classname.get, "'");
399 if (auto did
= thing
.type
in d2dactordefsById
) {
400 assert(did
.classtype
== adef
.classtype
);
401 assert(did
.classname
== adef
.classname
);
402 conwriteln("mapid=", thing
.type
, "; ", adef
.classtype
, ":", adef
.classname
, "; id=", aid
.id
);
403 assert(aid
.classtype
!string
== adef
.classtype
);
404 assert(aid
.classname
!string
== adef
.classname
);
408 aid
.state
= StrPool
.MNST_SLEEP
;
409 aid
.x
= cast(int)thing
.x
;
410 aid
.y
= cast(int)thing
.y
;
411 aid
.dir
= cast(uint)(thing
.right ?
1 : 0);
415 foreach (ActorDef adef
; actordefs
.byValue
) {
416 conwriteln("loading graphics for '", adef
.fullname
, "'");
419 //Actor.dumpActors();
421 conwriteln("initial snapshot size: ", Actor
.snapshotSize
, " bytes");
425 // ////////////////////////////////////////////////////////////////////////// //
426 public void doActorsThink () {
427 Actor
.forEach((ActorId me
) {
428 // `act` is always valid here
429 if (auto adef
= findActorDef(me
.classtype
!string
, me
.classname
!string
)) {
431 int aidx
= me
.zAnimidx
!int;
432 int nidx
= adef
.nextAnimIdx(me
.zAnimstate
!StrId
, me
.dir
!uint, aidx
);
433 //conwriteln("actor ", me.id, " (", me.classtype!string, me.classname!string, "): state=", me.zAnimstate!string, "; aidx=", aidx, "; nidx=", nidx);
435 assert(me
.zAnimidx
!int == nidx
);
439 //{ import std.stdio : stdout; stdout.writeln("========================================="); }
440 //Actor.dumpActors();