Skip to content

Commit

Permalink
fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
adamdruppe committed Apr 19, 2020
1 parent 41f8150 commit dafa152
Show file tree
Hide file tree
Showing 8 changed files with 345 additions and 48 deletions.
158 changes: 155 additions & 3 deletions declarativeloader.d
Expand Up @@ -21,6 +21,10 @@ struct Tagged(alias field) {}
auto Tag(T)(T t) {
return TagStruct!T(t);
}
/// For example `@presentIf("version >= 2") int addedInVersion2;`
struct presentIf { string code; }


struct TagStruct(T) { T t; }
struct MustBeStruct(T) { T t; }
/// The marked field is not in the actual file
Expand Down Expand Up @@ -66,14 +70,25 @@ union N(ty) {
ubyte[ty.sizeof] bytes;
}

static bool fieldPresent(alias field, T)(T t) {
bool p = true;
static foreach(attr; __traits(getAttributes, field)) {
static if(is(typeof(attr) == presentIf)) {
bool p2 = false;
with(t) p2 = mixin(attr.code);
p = p && p2;
}
}
return p;
}

/// input range of ubytes...
int loadFrom(T, Range)(ref T t, auto ref Range r, bool assumeBigEndian = false) {
int bytesConsumed;
string currentItem;

import std.conv;
scope(failure)
throw new Exception(T.stringof ~ "." ~ currentItem ~ " trouble " ~ to!string(t));
try {

ubyte next() {
if(r.empty)
Expand All @@ -90,7 +105,8 @@ int loadFrom(T, Range)(ref T t, auto ref Range r, bool assumeBigEndian = false)
static if(is(typeof(__traits(getMember, T, memberName)))) {
alias f = __traits(getMember, T, memberName);
alias ty = typeof(f);
static if(fieldSaved!f) {
static if(fieldSaved!f)
if(fieldPresent!f(t)) {
endianness = bigEndian!f(endianness);
// FIXME VariableLength
static if(is(ty : ulong) || is(ty : double)) {
Expand Down Expand Up @@ -200,5 +216,141 @@ int loadFrom(T, Range)(ref T t, auto ref Range r, bool assumeBigEndian = false)
}
}}

} catch(Exception e) {
throw new Exception(T.stringof ~ "." ~ currentItem ~ " trouble " ~ to!string(t), e.file, e.line, e);
}

return bytesConsumed;
}

int saveTo(T, Range)(ref T t, ref Range r, bool assumeBigEndian = false) {
int bytesWritten;
string currentItem;

import std.conv;
try {

void write(ubyte b) {
bytesWritten++;
static if(is(Range == ubyte[]))
r ~= b;
else
r.put(b);
}

bool endianness = bigEndian!T(assumeBigEndian);
static foreach(memberName; __traits(allMembers, T)) {{
currentItem = memberName;
static if(is(typeof(__traits(getMember, T, memberName)))) {
alias f = __traits(getMember, T, memberName);
alias ty = typeof(f);
static if(fieldSaved!f)
if(fieldPresent!f(t)) {
endianness = bigEndian!f(endianness);
// FIXME VariableLength
static if(is(ty : ulong) || is(ty : double)) {
N!ty n;
n.member = __traits(getMember, t, memberName);
if(endianness) {
foreach(i; 0 .. ty.sizeof) {
version(BigEndian)
write(n.bytes[i]);
else
write(n.bytes[$ - 1 - i]);
}
} else {
foreach(i; 0 .. ty.sizeof) {
version(BigEndian)
write(n.bytes[$ - 1 - i]);
else
write(n.bytes[i]);
}
}

// FIXME: MustBe
} else static if(is(ty == struct)) {
bytesWritten += saveTo(__traits(getMember, t, memberName), r, endianness);
} else static if(is(ty == union)) {
static foreach(attr; __traits(getAttributes, ty))
static if(is(attr == Tagged!Field, alias Field))
enum tagField = __traits(identifier, Field);
static assert(is(typeof(tagField)), "Unions need a Tagged UDA on the union type (not the member) indicating the field that identifies the union");

auto tag = __traits(getMember, t, tagField);
// find the child of the union matching the tag...
bool found = false;
static foreach(um; __traits(allMembers, ty)) {
if(tag == getTag!(__traits(getMember, ty, um))) {
bytesWritten += saveTo(__traits(getMember, __traits(getMember, t, memberName), um), r, endianness);
found = true;
}
}
if(!found) {
import std.format;
throw new Exception(format("found unknown union tag %s at %s", tag, t));
}
} else static if(is(ty == E[], E)) {

// the numBytesRemaining / numElementsRemaining thing here ASSUMING the
// arrays are already the correct size. the struct itself could invariant that maybe

foreach(item; __traits(getMember, t, memberName)) {
static if(is(typeof(item) == struct)) {
bytesWritten += saveTo(item, r, endianness);
} else {
static struct dummy {
typeof(item) i;
}
dummy d = dummy(item);
bytesWritten += saveTo(d, r, endianness);
}
}

} else static assert(0, ty.stringof);
}
}
}}

} catch(Exception e) {
throw new Exception(T.stringof ~ "." ~ currentItem ~ " save trouble " ~ to!string(t), e.file, e.line, e);
}

return bytesWritten;
}

unittest {
static struct A {
int a;
@presentIf("a > 5") int b;
int c;
@NumElements!c ubyte[] d;
}

A a;
a.loadFrom(cast(ubyte[]) [1, 1, 0, 0, 7, 0, 0, 0, 3, 0, 0, 0, 6, 7, 8]);

assert(a.a == 257);
assert(a.b == 7);
assert(a.c == 3);
assert(a.d == [6,7,8]);

a = A.init;

a.loadFrom(cast(ubyte[]) [0, 0, 0, 0, 7, 0, 0, 0,1,2,3,4,5,6,7]);
assert(a.b == 0);
assert(a.c == 7);
assert(a.d == [1,2,3,4,5,6,7]);

a.a = 44;
a.c = 3;
a.d = [5,4,3];

ubyte[] saved;

a.saveTo(saved);

A b;
b.loadFrom(saved);

assert(a == b);
}
17 changes: 9 additions & 8 deletions gamehelpers.d
Expand Up @@ -234,10 +234,10 @@ void runGame(T : GameHelperBase)(T game, int maxUpdateRate = 20, int maxRedrawRa
if(update.buttonWasJustPressed(l1)) game.snes[L] = true;
if(update.buttonWasJustPressed(r1)) game.snes[R] = true;
// note: no need to check analog stick here cuz joystick.d already does it for us (per old playstation tradition)
if(update.axisChange(Axis.horizontalDpad) < 0 && update.axisPosition(Axis.horizontalDpad) < -20000) game.snes[Left] = true;
if(update.axisChange(Axis.horizontalDpad) > 0 && update.axisPosition(Axis.horizontalDpad) > 20000) game.snes[Right] = true;
if(update.axisChange(Axis.verticalDpad) < 0 && update.axisPosition(Axis.verticalDpad) < -20000) game.snes[Up] = true;
if(update.axisChange(Axis.verticalDpad) > 0 && update.axisPosition(Axis.verticalDpad) > 20000) game.snes[Down] = true;
if(update.axisChange(Axis.horizontalDpad) < 0 && update.axisPosition(Axis.horizontalDpad) < -8) game.snes[Left] = true;
if(update.axisChange(Axis.horizontalDpad) > 0 && update.axisPosition(Axis.horizontalDpad) > 8) game.snes[Right] = true;
if(update.axisChange(Axis.verticalDpad) < 0 && update.axisPosition(Axis.verticalDpad) < -8) game.snes[Up] = true;
if(update.axisChange(Axis.verticalDpad) > 0 && update.axisPosition(Axis.verticalDpad) > 8) game.snes[Down] = true;

if(update.buttonWasJustReleased(square)) game.snes[Y] = false;
if(update.buttonWasJustReleased(triangle)) game.snes[X] = false;
Expand All @@ -247,14 +247,15 @@ void runGame(T : GameHelperBase)(T game, int maxUpdateRate = 20, int maxRedrawRa
if(update.buttonWasJustReleased(start)) game.snes[Start] = false;
if(update.buttonWasJustReleased(l1)) game.snes[L] = false;
if(update.buttonWasJustReleased(r1)) game.snes[R] = false;
if(update.axisChange(Axis.horizontalDpad) > 0 && update.axisPosition(Axis.horizontalDpad) > -20000) game.snes[Left] = false;
if(update.axisChange(Axis.horizontalDpad) < 0 && update.axisPosition(Axis.horizontalDpad) < 20000) game.snes[Right] = false;
if(update.axisChange(Axis.verticalDpad) > 0 && update.axisPosition(Axis.verticalDpad) > -20000) game.snes[Up] = false;
if(update.axisChange(Axis.verticalDpad) < 0 && update.axisPosition(Axis.verticalDpad) < 20000) game.snes[Down] = false;
if(update.axisChange(Axis.horizontalDpad) > 0 && update.axisPosition(Axis.horizontalDpad) > -8) game.snes[Left] = false;
if(update.axisChange(Axis.horizontalDpad) < 0 && update.axisPosition(Axis.horizontalDpad) < 8) game.snes[Right] = false;
if(update.axisChange(Axis.verticalDpad) > 0 && update.axisPosition(Axis.verticalDpad) > -8) game.snes[Up] = false;
if(update.axisChange(Axis.verticalDpad) < 0 && update.axisPosition(Axis.verticalDpad) < 8) game.snes[Down] = false;

}

} else static if(__traits(isSame, Button, XBox360Buttons)) {
static assert(0);
// XBox style mapping
// the reason this exists is if the programmer wants to use the xbox details, but
// might also want the basic controller in here. joystick.d already does translations
Expand Down
4 changes: 4 additions & 0 deletions joystick.d
Expand Up @@ -117,6 +117,10 @@ version(Windows) {
WindowsXInput wxi;
}

version(OSX) {
struct JoystickState {}
}

JoystickState[4] joystickState;

version(linux) {
Expand Down
23 changes: 21 additions & 2 deletions jsvar.d
Expand Up @@ -617,7 +617,13 @@ struct var {
// if it is var, we'll just blit it over
public var opAssign(T)(T t) if(!is(T == var)) {
static if(__traits(compiles, this = t.toArsdJsvar())) {
this = t.toArsdJsvar();
static if(__traits(compiles, t is null)) {
if(t is null)
this = null;
else
this = t.toArsdJsvar();
} else
this = t.toArsdJsvar();
} else static if(isFloatingPoint!T) {
this._type = Type.Floating;
this._payload._floating = t;
Expand Down Expand Up @@ -943,7 +949,15 @@ struct var {
auto pl = this._payload._array;
static if(isSomeString!T) {
return to!string(pl);
} else static if(isArray!T) {
} else static if(is(T == E[N], E, size_t N)) {
T ret;
foreach(i; 0 .. N) {
if(i >= pl.length)
break;
ret[i] = pl[i].get!E;
}
return ret;
} else static if(is(T == E[], E)) {
T ret;
static if(is(ElementType!T == void)) {
static assert(0, "try wrapping the function to get rid of void[] args");
Expand Down Expand Up @@ -1366,6 +1380,11 @@ struct var {
return var.fromJsonValue(decoded);
}

static var fromJsonFile(string filename) {
import std.file;
return var.fromJson(readText(filename));
}

static var fromJsonValue(JSONValue v) {
var ret;

Expand Down

0 comments on commit dafa152

Please sign in to comment.