XSCREENとSPDEFとDISPLAY実�
This commit is contained in:
@@ -1,3 +1,8 @@
|
||||
ASSERT__ SUBST$("0123456789",0,"B")=="B","SUBST$"
|
||||
ASSERT__ SUBST$("0123456789",0,4,"B")=="B456789","SUBST$"
|
||||
ASSERT__ SUBST$("",0,4,"B")=="B","SUBST$"
|
||||
WHILE 1
|
||||
WEND
|
||||
FOR I=0TO 511'-500
|
||||
SPSET I,I'304'-I+304
|
||||
SPOFS I, (I*16) MOD 400, FLOOR((I*16)/400)*16
|
||||
|
||||
158
SMILEBASIC/VM.d
158
SMILEBASIC/VM.d
@@ -49,6 +49,10 @@ class VM
|
||||
this.functions = functions;
|
||||
this.globalDataTable = gdt;
|
||||
}
|
||||
Code getCurrent()
|
||||
{
|
||||
return code[pc];
|
||||
}
|
||||
void run()
|
||||
{
|
||||
bp = 0;//globalを実行なのでbaseは0(グローバル変数をスタックに取るようにしない限り)(挙動的にスタックに確保していなさそう)
|
||||
@@ -110,6 +114,38 @@ class VM
|
||||
{
|
||||
pc = code.length;
|
||||
}
|
||||
void dump()
|
||||
{
|
||||
foreach(i, c; code)
|
||||
writefln("%04X:%s", i, c.toString(this));
|
||||
}
|
||||
wstring getGlobalVarName(int index)
|
||||
{
|
||||
foreach(k, v; globalTable)
|
||||
{
|
||||
if(v.index == index) return k;
|
||||
}
|
||||
return "undefined variable";
|
||||
}
|
||||
Value readData()
|
||||
{
|
||||
Value value;
|
||||
this.globalDataTable.read(value, this);
|
||||
return value;
|
||||
}
|
||||
void restoreData(wstring label)
|
||||
{
|
||||
this.globalDataTable.dataIndex = this.globalDataTable.label[label];
|
||||
}
|
||||
int olddti;
|
||||
void pushDataIndex()
|
||||
{
|
||||
olddti = this.globalDataTable.dataIndex;
|
||||
}
|
||||
void popDataIndex()
|
||||
{
|
||||
this.globalDataTable.dataIndex = olddti;
|
||||
}
|
||||
}
|
||||
enum CodeType
|
||||
{
|
||||
@@ -135,6 +171,10 @@ abstract class Code
|
||||
{
|
||||
CodeType type;
|
||||
abstract void execute(VM vm);
|
||||
string toString(VM vm)
|
||||
{
|
||||
return super.toString();
|
||||
}
|
||||
}
|
||||
class PrintCode : Code
|
||||
{
|
||||
@@ -174,6 +214,10 @@ class PrintCode : Code
|
||||
}
|
||||
stdout.flush();
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "print";
|
||||
}
|
||||
}
|
||||
/*
|
||||
* スタックにPush
|
||||
@@ -190,6 +234,10 @@ class Push : Code
|
||||
{
|
||||
vm.push(imm);
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "push " ~ imm.toString;
|
||||
}
|
||||
}
|
||||
|
||||
class PushG : Code
|
||||
@@ -204,6 +252,10 @@ class PushG : Code
|
||||
{
|
||||
vm.push(vm.global[var]);
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "pushglobal " ~ vm.getGlobalVarName(var).to!string;
|
||||
}
|
||||
}
|
||||
class PopG : Code
|
||||
{
|
||||
@@ -239,6 +291,10 @@ class PopG : Code
|
||||
}
|
||||
vm.global[var] = v;
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "popglobal " ~ vm.getGlobalVarName(var).to!string;
|
||||
}
|
||||
}
|
||||
class PushL : Code
|
||||
{
|
||||
@@ -252,6 +308,10 @@ class PushL : Code
|
||||
{
|
||||
vm.push(vm.stack[vm.bp + var]);
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "pushlocal " ~ var.to!string;
|
||||
}
|
||||
}
|
||||
class PopL : Code
|
||||
{
|
||||
@@ -287,6 +347,10 @@ class PopL : Code
|
||||
}
|
||||
vm.stack[vm.bp + var] = v;
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "poplocal " ~ var.to!string;
|
||||
}
|
||||
}
|
||||
class Operate : Code
|
||||
{
|
||||
@@ -479,6 +543,10 @@ class Operate : Code
|
||||
l.doubleValue = ld;
|
||||
vm.push(l);
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "operate " ~ operator.to!string;
|
||||
}
|
||||
}
|
||||
class GotoAddr : Code
|
||||
{
|
||||
@@ -492,6 +560,10 @@ class GotoAddr : Code
|
||||
{
|
||||
vm.pc = address - 1;
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "goto " ~ address.to!string(16);
|
||||
}
|
||||
}
|
||||
class GotoS : Code
|
||||
{
|
||||
@@ -523,6 +595,10 @@ class GotoTrue : Code
|
||||
if(cond.boolValue)
|
||||
vm.pc = address - 1;
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "gototrue " ~ address.to!string(16);
|
||||
}
|
||||
}
|
||||
class GotoFalse : Code
|
||||
{
|
||||
@@ -539,6 +615,10 @@ class GotoFalse : Code
|
||||
if(!cond.boolValue)
|
||||
vm.pc = address - 1;
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "gotofalse " ~ address.to!string(16);
|
||||
}
|
||||
}
|
||||
class GosubAddr : Code
|
||||
{
|
||||
@@ -553,6 +633,10 @@ class GosubAddr : Code
|
||||
vm.push(Value(vm.pc));
|
||||
vm.pc = address - 1;
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "gosub " ~ address.to!string(16);
|
||||
}
|
||||
}
|
||||
class GosubS : Code
|
||||
{
|
||||
@@ -591,6 +675,10 @@ class ReturnSubroutine : Code
|
||||
}
|
||||
vm.pc = pc.integerValue;
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "returnsubroutine ";
|
||||
}
|
||||
}
|
||||
class EndVM : Code
|
||||
{
|
||||
@@ -601,6 +689,10 @@ class EndVM : Code
|
||||
{
|
||||
vm.end();
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "endvm";
|
||||
}
|
||||
}
|
||||
class NewArray : Code
|
||||
{
|
||||
@@ -652,6 +744,10 @@ class NewArray : Code
|
||||
}
|
||||
vm.push(array);
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "newarray " ~ dim.to!string;
|
||||
}
|
||||
}
|
||||
class PushArray : Code
|
||||
{
|
||||
@@ -712,6 +808,10 @@ class PushArray : Code
|
||||
}
|
||||
throw new TypeMismatch();
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "pusharray " ~ dim.to!string;
|
||||
}
|
||||
}
|
||||
class PopArray : Code
|
||||
{
|
||||
@@ -787,6 +887,10 @@ class PopArray : Code
|
||||
}
|
||||
throw new TypeMismatch();
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "poparray " ~ dim.to!string ~ ", " ~ var.to!string ~ ", " ~ local.to!string;
|
||||
}
|
||||
}
|
||||
class ReturnFunction : Code
|
||||
{
|
||||
@@ -823,6 +927,10 @@ class ReturnFunction : Code
|
||||
vm.pc = pc.integerValue;
|
||||
vm.bp = bp.integerValue;
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "returnfunc " ~ func.name.to!string;
|
||||
}
|
||||
}
|
||||
class CallFunctionCode : Code
|
||||
{
|
||||
@@ -846,15 +954,15 @@ class CallFunctionCode : Code
|
||||
Function func = vm.functions.get(name, null);
|
||||
if(!func)
|
||||
{
|
||||
throw new SyntaxError();
|
||||
throw new SyntaxError(name);
|
||||
}
|
||||
if(func.argCount != this.argCount)
|
||||
{
|
||||
throw new IllegalFunctionCall();
|
||||
throw new IllegalFunctionCall(name.to!string);
|
||||
}
|
||||
if(func.outArgCount != this.outArgCount)
|
||||
{
|
||||
throw new IllegalFunctionCall();
|
||||
throw new IllegalFunctionCall(name.to!string);
|
||||
}
|
||||
//TODO:args
|
||||
auto bp = vm.stacki;
|
||||
@@ -871,6 +979,10 @@ class CallFunctionCode : Code
|
||||
}
|
||||
}
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "callfunc " ~ name.to!string;
|
||||
}
|
||||
}
|
||||
import otya.smilebasic.builtinfunctions;
|
||||
class CallBuiltinFunction : Code
|
||||
@@ -914,6 +1026,10 @@ class CallBuiltinFunction : Code
|
||||
vm.push(result[i]);
|
||||
}
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "callbuiltin " ~ func.name.to!string;
|
||||
}
|
||||
}
|
||||
class IncCodeG : Code
|
||||
{
|
||||
@@ -952,6 +1068,10 @@ class IncCodeG : Code
|
||||
vm.global[var] = Value(l ~ r);
|
||||
}
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "incglobal " ~ var.to!string;
|
||||
}
|
||||
}
|
||||
class IncCodeL : Code
|
||||
{
|
||||
@@ -990,6 +1110,10 @@ class IncCodeL : Code
|
||||
*g = Value(l ~ r);
|
||||
}
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "inclocal " ~ var.to!string;
|
||||
}
|
||||
}
|
||||
class OnBase : Code
|
||||
{
|
||||
@@ -1043,6 +1167,10 @@ class OnGoto : OnBase
|
||||
if(index < 0) return;
|
||||
vm.pc = index - 1;
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "ongoto " ~ labels.to!string;
|
||||
}
|
||||
}
|
||||
class OnGosub : OnBase
|
||||
{
|
||||
@@ -1057,6 +1185,10 @@ class OnGosub : OnBase
|
||||
vm.push(Value(vm.pc));
|
||||
vm.pc = index - 1;
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "ongosub " ~ labels.to!string;
|
||||
}
|
||||
}
|
||||
import std.string;
|
||||
class InputCode : Code
|
||||
@@ -1141,6 +1273,10 @@ class InputCode : Code
|
||||
}
|
||||
} while(error);
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "input " ~ count.to!string;
|
||||
}
|
||||
}
|
||||
class ReadCode : Code
|
||||
{
|
||||
@@ -1158,6 +1294,10 @@ class ReadCode : Code
|
||||
vm.push(data);
|
||||
}
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "read " ~ count.to!string;
|
||||
}
|
||||
}
|
||||
class RestoreCodeS : Code
|
||||
{
|
||||
@@ -1185,6 +1325,10 @@ class RestoreCode : Code
|
||||
{
|
||||
datatable.dataIndex = label;
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "restore " ~ label.to!string;
|
||||
}
|
||||
}
|
||||
class PushSystemVariable : Code
|
||||
{
|
||||
@@ -1197,6 +1341,10 @@ class PushSystemVariable : Code
|
||||
{
|
||||
vm.push(var.value);
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "pushsysvar " ~ var.to!string;
|
||||
}
|
||||
}
|
||||
class PopSystemVariable : Code
|
||||
{
|
||||
@@ -1211,4 +1359,8 @@ class PopSystemVariable : Code
|
||||
vm.pop(v);
|
||||
var.value = v;
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "popsysvar " ~ var.to!string;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import otya.smilebasic.error;
|
||||
import otya.smilebasic.type;
|
||||
import otya.smilebasic.petitcomputer;
|
||||
import otya.smilebasic.sprite;
|
||||
import otya.smilebasic.vm;
|
||||
//プチコンの引数省略は特殊なので
|
||||
//LOCATE ,,0のように省略できる
|
||||
struct DefaultValue(T, bool skippable = true)
|
||||
@@ -52,14 +53,16 @@ class BuiltinFunction
|
||||
void function(PetitComputer, Value[], Value[]) func;
|
||||
int startskip;
|
||||
bool variadic;
|
||||
string name;
|
||||
this(BuiltinFunctionArgument[] argments, ValueType result, void function(PetitComputer, Value[], Value[]) func, int startskip,
|
||||
bool variadic)
|
||||
bool variadic, string name)
|
||||
{
|
||||
this.argments = argments;
|
||||
this.result = result;
|
||||
this.func = func;
|
||||
this.startskip = startskip;
|
||||
this.variadic = variadic;
|
||||
this.name = name;
|
||||
}
|
||||
bool hasSkipArgument()
|
||||
{
|
||||
@@ -99,6 +102,11 @@ class BuiltinFunction
|
||||
time.setDefaultValue(1);
|
||||
p.vsync(cast(int)time);
|
||||
}
|
||||
static void WAIT(PetitComputer p, DefaultValue!int time)
|
||||
{
|
||||
time.setDefaultValue(1);
|
||||
p.vsync(cast(int)time);
|
||||
}
|
||||
//TODO:プチコンのCLSには引数の個数制限がない
|
||||
static void CLS(PetitComputer p/*vaarg*/)
|
||||
{
|
||||
@@ -121,9 +129,13 @@ class BuiltinFunction
|
||||
}
|
||||
static void XSCREEN(PetitComputer p, int mode, DefaultValue!(int, false) a, DefaultValue!(int, false) b)
|
||||
{
|
||||
a.setDefaultValue(512);
|
||||
b.setDefaultValue(512);
|
||||
p.xscreen(mode, cast(int)a, cast(int)b);
|
||||
}
|
||||
static void DISPLAY(PetitComputer p, DefaultValue!(int, false) display)
|
||||
static void DISPLAY(PetitComputer p, int display)
|
||||
{
|
||||
p.display(display);
|
||||
}
|
||||
static void GCLS(PetitComputer p, DefaultValue!(int, false) color)
|
||||
{
|
||||
@@ -157,6 +169,11 @@ class BuiltinFunction
|
||||
static void GPRIO(PetitComputer p, int z)
|
||||
{
|
||||
}
|
||||
static void GPAGE(PetitComputer p, int showPage, int usePage)
|
||||
{
|
||||
p.showGRP = showPage;
|
||||
p.useGRP = usePage;
|
||||
}
|
||||
static void BGMPLAY(PetitComputer p, int music)
|
||||
{
|
||||
}
|
||||
@@ -181,7 +198,7 @@ class BuiltinFunction
|
||||
static int RND(int max)
|
||||
{
|
||||
import std.random;
|
||||
return uniform(0, max - 1);
|
||||
return uniform(0, max - 1 + 1);
|
||||
}
|
||||
static void DTREAD(DefaultValue!(wstring, false) date, out int Y, out int M, out int D/*W*/)
|
||||
{
|
||||
@@ -207,12 +224,19 @@ class BuiltinFunction
|
||||
}
|
||||
static double VAL(wstring str)
|
||||
{
|
||||
if(str[0..2] == "&H")
|
||||
try
|
||||
{
|
||||
return str[2..$].to!int(16);
|
||||
if(str[0..2] == "&H")
|
||||
{
|
||||
return str[2..$].to!int(16);
|
||||
}
|
||||
double val = str.to!double;
|
||||
return val;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
return 0;//toriaezu
|
||||
}
|
||||
double val = str.to!double;
|
||||
return val;
|
||||
}
|
||||
static double FLOOR(double val)
|
||||
{
|
||||
@@ -220,9 +244,63 @@ class BuiltinFunction
|
||||
}
|
||||
static wstring MID(wstring str, int i, int len)
|
||||
{
|
||||
if(i + len > str.length)
|
||||
{
|
||||
return "";//範囲外で空文字
|
||||
}
|
||||
//挙動未定
|
||||
return str[i..i + len];
|
||||
}
|
||||
//INSTRSUSBTLEFT
|
||||
static wstring LEFT(wstring str, int len)
|
||||
{
|
||||
return str[0..len];
|
||||
}
|
||||
static wstring SUBST(wstring str, int i, Value alen, DefaultValue!(Value,false) areplace)
|
||||
{
|
||||
int len = 1;
|
||||
wstring replace = "";
|
||||
if(alen.isNumber)
|
||||
{
|
||||
len = alen.castInteger;
|
||||
replace = areplace.castString;
|
||||
}
|
||||
else
|
||||
{
|
||||
replace = alen.castString;
|
||||
//省略されたらi以降の全文字を置換
|
||||
return str[0..i] ~ replace;
|
||||
}
|
||||
if(str.length <= i + len)
|
||||
{
|
||||
return str[0..i] ~ replace;
|
||||
}
|
||||
str.replaceInPlace(i, i + len, replace);
|
||||
return str;
|
||||
}
|
||||
static int INSTR(Value vstart, Value vstr1, DefaultValue!(wstring, false) vstr2)
|
||||
{
|
||||
import std.string;
|
||||
int start = 0;
|
||||
wstring str1, str2;
|
||||
if(!vstr2.isDefault)
|
||||
{
|
||||
start = vstart.castInteger;
|
||||
str1 = vstr1.castString;
|
||||
str2 = cast(wstring)vstr2;
|
||||
}
|
||||
else
|
||||
{
|
||||
str1 = vstart.castString;
|
||||
str2 = vstr1.castString;
|
||||
}
|
||||
int aaa = str1[start..$].indexOf(str2, CaseSensitive.no);
|
||||
return str1[start..$].indexOf(str2, CaseSensitive.no);
|
||||
}
|
||||
static int ASC(wstring str)
|
||||
{
|
||||
return cast(int)str[0];
|
||||
}
|
||||
static void SPSET(PetitComputer p, int id, int defno)
|
||||
{
|
||||
p.sprite.spset(id, defno);
|
||||
@@ -241,7 +319,7 @@ class BuiltinFunction
|
||||
}
|
||||
static void SPANIM(PetitComputer p, Value[] va_args)
|
||||
{
|
||||
writeln("NOTIMPL:SPANIM");
|
||||
//TODO:配列
|
||||
auto args = retro(va_args);
|
||||
int no = args[0].castInteger;
|
||||
double[] animdata = new double[args.length - 2];
|
||||
@@ -255,6 +333,79 @@ class BuiltinFunction
|
||||
if(args[1].isNumber)
|
||||
p.sprite.spanim(no, cast(SpriteAnimTarget)(args[1].castInteger), animdata);
|
||||
}
|
||||
static void SPDEF(PetitComputer p, Value[] va_args)
|
||||
{
|
||||
switch(va_args.length)
|
||||
{
|
||||
case 1://array
|
||||
{
|
||||
if(va_args[0].isNumberArray)
|
||||
{
|
||||
writeln("NOTIMPL:SPDEF ARRAY");
|
||||
//return;
|
||||
}
|
||||
if(va_args[0].isString)
|
||||
{
|
||||
VM vm = p.vm;
|
||||
vm.pushDataIndex();
|
||||
vm.restoreData(va_args[0].castString);
|
||||
auto count = vm.readData().castInteger;//読み込むスプライト数
|
||||
int defno = 0;//?
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
int U = vm.readData().castInteger;
|
||||
int V = vm.readData().castInteger;
|
||||
int W = vm.readData().castInteger;
|
||||
int H = vm.readData().castInteger;
|
||||
int HX = vm.readData().castInteger;
|
||||
int HY = vm.readData().castInteger;
|
||||
int ATTR = vm.readData().castInteger;
|
||||
p.sprite.SPDEFTable[defno] = SpriteDef(U, V, W, H, HX, HY, cast(SpriteAttr)ATTR);
|
||||
defno++;
|
||||
}
|
||||
vm.popDataIndex();
|
||||
return;
|
||||
}
|
||||
throw new IllegalFunctionCall("SPDEF");
|
||||
return;
|
||||
}
|
||||
default:
|
||||
}
|
||||
{
|
||||
int defno = va_args[0].castInteger;
|
||||
int U = va_args[1].castInteger;
|
||||
int V = va_args[2].castInteger;
|
||||
int W = 16, H = 16, HX = 0, HY = 0, ATTR = 1;
|
||||
if(va_args.length > 3)
|
||||
{
|
||||
W = va_args[3].castInteger;
|
||||
}
|
||||
if(va_args.length > 4)
|
||||
{
|
||||
H = va_args[4].castInteger;
|
||||
}
|
||||
if(va_args.length > 5)
|
||||
{
|
||||
HX = va_args[5].castInteger;
|
||||
}
|
||||
if(va_args.length > 6)
|
||||
{
|
||||
HY = va_args[6].castInteger;
|
||||
}
|
||||
if(va_args.length > 7)
|
||||
{
|
||||
ATTR = va_args[7].castInteger;
|
||||
}
|
||||
p.sprite.SPDEFTable[defno] = SpriteDef(U, V, W, H, HX, HY, cast(SpriteAttr)ATTR);
|
||||
}
|
||||
}
|
||||
static void SPCLR(PetitComputer p, DefaultValue!(int, false) i)
|
||||
{
|
||||
if(i.isDefault)
|
||||
p.sprite.spclr();
|
||||
else
|
||||
p.sprite.spclr(cast(int)i);
|
||||
}
|
||||
static void BGMSTOP(PetitComputer p)
|
||||
{
|
||||
writeln("NOTIMPL:BGMSTOP");
|
||||
@@ -341,6 +492,7 @@ class BuiltinFunction
|
||||
{
|
||||
return sqrt(a1);
|
||||
}
|
||||
//GalateaTalk利用面倒くさい...
|
||||
static void TALK(wstring a1)
|
||||
{
|
||||
}
|
||||
@@ -365,6 +517,7 @@ class BuiltinFunction
|
||||
mixin(AddFunc!(BuiltinFunction, name)),
|
||||
GetStartSkip!(BuiltinFunction, name),
|
||||
IsVariadic!(BuiltinFunction, name),
|
||||
name,
|
||||
);
|
||||
writeln(AddFunc!(BuiltinFunction, name));
|
||||
}
|
||||
@@ -384,6 +537,14 @@ template GetStartSkip(T, string N)
|
||||
{
|
||||
enum SkipSkip = I - is(P[0] : PetitComputer);
|
||||
}
|
||||
else static if(is(P[I] == DefaultValue!(wstring, false)))
|
||||
{
|
||||
enum SkipSkip = I - is(P[0] : PetitComputer);
|
||||
}
|
||||
else static if(is(P[I] == DefaultValue!(Value, false)))
|
||||
{
|
||||
enum SkipSkip = I - is(P[0] : PetitComputer);
|
||||
}
|
||||
else
|
||||
{
|
||||
enum SkipSkip = SkipSkip!(I + 1, P);
|
||||
@@ -419,7 +580,7 @@ template AddFunc(T, string N)
|
||||
{
|
||||
static if(is(ReturnType!(__traits(getMember, T, N)) == double) || is(ReturnType!(__traits(getMember, T, N)) == int))
|
||||
{
|
||||
const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){if(ret.length != 1){throw new IllegalFunctionCall();}ret[0] = Value(" ~ N ~ "(" ~
|
||||
const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){if(ret.length != 1){throw new IllegalFunctionCall(\"" ~ N ~ "\");}ret[0] = Value(" ~ N ~ "(" ~
|
||||
AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(T,N) - 1, 0, 0, 0, T, N
|
||||
, ParameterTypeTuple!(__traits(getMember, T, N))) ~ "));}";
|
||||
}
|
||||
@@ -427,13 +588,13 @@ template AddFunc(T, string N)
|
||||
{
|
||||
|
||||
pragma(msg, GetArgumentCount!(T,N));
|
||||
const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){/*if(ret.length != 0){throw new IllegalFunctionCall();}*/" ~ OutArgsInit!(T,N) ~ N ~ "(" ~
|
||||
const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){/*if(ret.length != 0){throw new IllegalFunctionCall(\"" ~ N ~ "\");}*/" ~ OutArgsInit!(T,N) ~ N ~ "(" ~
|
||||
AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(T,N) - 1, 0, 0, 0, T, N,
|
||||
ParameterTypeTuple!(__traits(getMember, T, N))) ~ ");}";
|
||||
}
|
||||
else static if(is(ReturnType!(__traits(getMember, T, N)) == wstring))
|
||||
{
|
||||
const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){if(ret.length != 1){throw new IllegalFunctionCall();}ret[0] = Value(" ~ N ~ "(" ~
|
||||
const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){if(ret.length != 1){throw new IllegalFunctionCall(\"" ~ N ~ "\");}ret[0] = Value(" ~ N ~ "(" ~
|
||||
AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(T,N) - 1, 0, 0, 0, T, N
|
||||
, ParameterTypeTuple!(__traits(getMember, T, N))) ~ "));}";
|
||||
}
|
||||
@@ -471,6 +632,20 @@ DefaultValue!(wstring, false) fromStringToSkip(Value v)
|
||||
else
|
||||
return DefaultValue!(wstring, false)(true);
|
||||
}
|
||||
DefaultValue!Value fromValueToDefault(Value v)
|
||||
{
|
||||
if(v.type != ValueType.Void)
|
||||
return DefaultValue!Value(v);
|
||||
else
|
||||
return DefaultValue!Value(true);
|
||||
}
|
||||
DefaultValue!(Value, false) fromValueToSkip(Value v)
|
||||
{
|
||||
if(v.type != ValueType.Void)
|
||||
return DefaultValue!(Value, false)(v);
|
||||
else
|
||||
return DefaultValue!(Value, false)(true);
|
||||
}
|
||||
template GetFunctionParamType(T, string N)
|
||||
{
|
||||
enum GetFunctionParamType = mixin("[" ~ Array!(ParameterTypeTuple!(__traits(getMember, T, N))) ~ "]");
|
||||
@@ -515,6 +690,14 @@ template GetFunctionParamType(T, string N)
|
||||
{
|
||||
const string arg = "";
|
||||
}
|
||||
else static if(is(P[0] == DefaultValue!(Value)) || is(P[0] == Value))
|
||||
{
|
||||
const string arg = "ValueType.Void, false";
|
||||
}
|
||||
else static if(is(P[0] == DefaultValue!(Value, false)))
|
||||
{
|
||||
const string arg = "ValueType.Void, true";
|
||||
}
|
||||
else static if(is(P[0] == PetitComputer))
|
||||
{
|
||||
static if(P.length != 0)
|
||||
@@ -602,10 +785,29 @@ template AddFuncArg(int L, int N, int M, int O, T, string NAME, P...)
|
||||
{
|
||||
const string arg = "arg";
|
||||
}
|
||||
else static if(is(P[0] == Value))
|
||||
{
|
||||
enum add = 1;
|
||||
enum outadd = 0;
|
||||
const string arg = "arg[" ~ I.to!string ~ "]";
|
||||
}
|
||||
else static if(is(P[0] == DefaultValue!Value))
|
||||
{
|
||||
enum add = 1;
|
||||
enum outadd = 0;
|
||||
const string arg = "fromValueToDefault(arg[" ~ I.to!string ~ "])";
|
||||
}
|
||||
else static if(is(P[0] == DefaultValue!(Value, false)))
|
||||
{
|
||||
enum add = 1;
|
||||
enum outadd = 0;
|
||||
const string arg = "fromValueToSkip(arg[" ~ I.to!string ~ "])";
|
||||
}
|
||||
else
|
||||
{
|
||||
enum add = 1;
|
||||
enum outadd = 0;
|
||||
pragma(msg, P[0]);
|
||||
static assert(false, "Invalid type");
|
||||
const string arg = "";
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
module otya.smilebasic.error;
|
||||
import std.exception;
|
||||
import std.string;
|
||||
import std.conv;
|
||||
class SmileBasicError : Exception
|
||||
{
|
||||
int errnum;
|
||||
int errline;
|
||||
int errprg;
|
||||
string message2;
|
||||
this(int slot, int line, string message)
|
||||
{
|
||||
super(format("%s in %d:%d", message, slot, line));
|
||||
@@ -18,6 +20,11 @@ class SmileBasicError : Exception
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
this(string message, string message2)
|
||||
{
|
||||
super(message);
|
||||
this.message2 = message2;
|
||||
}
|
||||
}
|
||||
class SyntaxError : SmileBasicError
|
||||
{
|
||||
@@ -26,13 +33,18 @@ class SyntaxError : SmileBasicError
|
||||
this.errnum = 3;
|
||||
super("Syntax error");
|
||||
}
|
||||
this(wstring func)
|
||||
{
|
||||
this();
|
||||
this.message2 = "Undefine function (" ~ func.to!string ~ ")";
|
||||
}
|
||||
}
|
||||
class IllegalFunctionCall : SmileBasicError
|
||||
{
|
||||
this()
|
||||
this(string func)
|
||||
{
|
||||
this.errnum = 4;
|
||||
super("Illegal function call");
|
||||
super("Illegal function call(" ~ func ~ ")");
|
||||
}
|
||||
}
|
||||
class TypeMismatch : SmileBasicError
|
||||
|
||||
@@ -142,7 +142,7 @@ class Lexical
|
||||
wstring iden;
|
||||
for(;i < code.length;i++)
|
||||
{
|
||||
c = code[i];
|
||||
c = cast(wchar)code[i].toUpper;;
|
||||
if(!c.isAlpha() && !c.isDigit() && c != '_')
|
||||
{
|
||||
break;
|
||||
|
||||
@@ -11,6 +11,7 @@ import std.c.stdio;
|
||||
import core.sync.mutex;
|
||||
import otya.smilebasic.parser;
|
||||
import otya.smilebasic.sprite;
|
||||
import otya.smilebasic.error;
|
||||
enum Button
|
||||
{
|
||||
NONE = 0,
|
||||
@@ -89,7 +90,7 @@ class PetitComputer
|
||||
{
|
||||
this()
|
||||
{
|
||||
new Test();
|
||||
//new Test();
|
||||
}
|
||||
static const string resourceDirName = "resources";
|
||||
static const string resourcePath = "./resources";
|
||||
@@ -99,10 +100,16 @@ class PetitComputer
|
||||
static const string fontTableFile = resourcePath ~ "/fonttable.txt";
|
||||
int screenWidth;
|
||||
int screenHeight;
|
||||
int screenWidthDisplay1;
|
||||
int screenHeightDisplay1;
|
||||
int fontWidth;
|
||||
int fontHeight;
|
||||
int consoleWidth;
|
||||
int consoleHeight;
|
||||
int consoleWidthDisplay1;
|
||||
int consoleHeightDisplay1;
|
||||
int consoleHeightC, consoleWidthC;
|
||||
ConsoleCharacter[][] consoleC;
|
||||
int[] consoleColor =
|
||||
[
|
||||
0x00000000,
|
||||
@@ -141,6 +148,7 @@ class PetitComputer
|
||||
}
|
||||
Button button;
|
||||
ConsoleCharacter[][] console;
|
||||
ConsoleCharacter[][] consoleDisplay1;
|
||||
bool visibleGRP = true;
|
||||
int showGRP;
|
||||
int useGRP;
|
||||
@@ -426,17 +434,41 @@ class PetitComputer
|
||||
writeln("OK");
|
||||
screenWidth = 400;
|
||||
screenHeight = 240;
|
||||
screenWidthDisplay1 = 320;
|
||||
screenHeightDisplay1 = 240;
|
||||
fontWidth = 8;
|
||||
fontHeight = 8;
|
||||
consoleWidth = screenWidth / fontWidth;
|
||||
consoleHeight = screenHeight / fontHeight;
|
||||
consoleWidthDisplay1 = screenWidthDisplay1 / fontWidth;
|
||||
consoleHeightDisplay1 = screenHeightDisplay1 / fontHeight;
|
||||
console = new ConsoleCharacter[][consoleHeight];
|
||||
consoleDisplay1 = new ConsoleCharacter[][consoleHeightDisplay1];
|
||||
consoleForeColor = 15;//#T_WHITE
|
||||
for(int i = 0; i < console.length; i++)
|
||||
{
|
||||
console[i] = new ConsoleCharacter[consoleWidth];
|
||||
console[i][] = ConsoleCharacter(0, consoleForeColor, consoleBackColor);
|
||||
}
|
||||
for(int i = 0; i < consoleDisplay1.length; i++)
|
||||
{
|
||||
consoleDisplay1[i] = new ConsoleCharacter[consoleWidthDisplay1];
|
||||
consoleDisplay1[i][] = ConsoleCharacter(0, consoleForeColor, consoleBackColor);
|
||||
}
|
||||
display(0);
|
||||
}
|
||||
void display(int number)
|
||||
{
|
||||
if(number)
|
||||
{
|
||||
consoleHeightC = consoleHeightDisplay1;
|
||||
consoleWidthC = consoleWidthDisplay1;
|
||||
consoleC = consoleDisplay1;
|
||||
return;
|
||||
}
|
||||
consoleHeightC = consoleHeight;
|
||||
consoleWidthC = consoleWidth;
|
||||
consoleC = console;
|
||||
}
|
||||
void cls()
|
||||
{
|
||||
@@ -470,6 +502,7 @@ class PetitComputer
|
||||
}
|
||||
Mutex grpmutex;
|
||||
otya.smilebasic.draw.Draw draw;
|
||||
bool displaynum;
|
||||
void renderGraphic()
|
||||
{
|
||||
//grpmutex.lock();
|
||||
@@ -504,6 +537,24 @@ class PetitComputer
|
||||
}
|
||||
Button[] buttonTable;
|
||||
Sprite sprite;
|
||||
int xscreenmode = 0;
|
||||
void xscreen(int mode, int sprite, int bg)
|
||||
{
|
||||
int mode2 = mode / 2;
|
||||
if(mode2 == 0)
|
||||
{
|
||||
SDL_SetWindowSize(window, 400, 240);
|
||||
}
|
||||
if(mode2 == 1)
|
||||
{
|
||||
SDL_SetWindowSize(window, 400, 480);
|
||||
}
|
||||
if(mode == 4)
|
||||
{
|
||||
SDL_SetWindowSize(window, 320, 240);
|
||||
}
|
||||
xscreenmode = mode2;
|
||||
}
|
||||
void render()
|
||||
{
|
||||
buttonTable = new Button[SDL_SCANCODE_SLEEP + 1];
|
||||
@@ -512,7 +563,7 @@ class PetitComputer
|
||||
buttonTable[SDL_SCANCODE_LEFT] = Button.LEFT;
|
||||
buttonTable[SDL_SCANCODE_RIGHT] = Button.RIGHT;
|
||||
buttonTable[SDL_SCANCODE_SPACE] = Button.A;
|
||||
bool renderprofile = true;
|
||||
bool renderprofile;// = true;
|
||||
try
|
||||
{
|
||||
version(Windows)
|
||||
@@ -556,7 +607,7 @@ class PetitComputer
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
draw = new otya.smilebasic.draw.Draw(this);
|
||||
// sprite.spset(0, 0);
|
||||
// sprite.spofs(0, 9, 8);
|
||||
// sprite.spofs(0, 9, 8);
|
||||
while(true)
|
||||
{
|
||||
auto profile = SDL_GetTicks();
|
||||
@@ -570,10 +621,18 @@ class PetitComputer
|
||||
loopcnt = 0;
|
||||
}
|
||||
}
|
||||
if(xscreenmode == 1)
|
||||
{
|
||||
glViewport(0, 240, 400, 240);
|
||||
}
|
||||
renderGraphic();
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
renderGraphicPage();
|
||||
renderConsoleGL();
|
||||
if(xscreenmode == 1)
|
||||
{
|
||||
glViewport(0, 240, 400, 240);
|
||||
}
|
||||
sprite.render();
|
||||
/* if(this.sprite.sprites[0].define)
|
||||
if(this.sprite.sprites[0].u == 0)
|
||||
@@ -653,6 +712,7 @@ class PetitComputer
|
||||
}
|
||||
}
|
||||
SDL_Window* window;
|
||||
otya.smilebasic.vm.VM vm;
|
||||
void run()
|
||||
{
|
||||
init();
|
||||
@@ -675,11 +735,12 @@ class PetitComputer
|
||||
//とりあえず
|
||||
auto parser = new Parser(
|
||||
//readText("./SYS/GAME6TALK.TXT").to!wstring
|
||||
readText("./SYS/GAME2RPG.TXT").to!wstring
|
||||
//readText("./SYS/GAME1DOTRC.TXT").to!wstring
|
||||
//readText(input("LOAD PROGRAM:", true).to!string).to!wstring
|
||||
//readText("./SYS/EX1TEXT.TXT").to!wstring
|
||||
//readText("FIZZBUZZ.TXT").to!wstring
|
||||
readText("TEST.TXT").to!wstring
|
||||
//readText("TEST.TXT").to!wstring
|
||||
/*"?ABS(-1)
|
||||
LOCATE 0,10
|
||||
COLOR 5
|
||||
@@ -722,6 +783,8 @@ class PetitComputer
|
||||
auto vm = parser.compile();
|
||||
bool running = true;
|
||||
vm.init(this);
|
||||
vm.dump;
|
||||
this.vm = vm;
|
||||
//gpset(0, 10, 10, 0xFF00FF00);
|
||||
//gline(0, 0, 0, 399, 239, RGB(0, 255, 0));
|
||||
//gfill(0, 78, 78, 40, 40, RGB(0, 255, 255));
|
||||
@@ -734,7 +797,11 @@ class PetitComputer
|
||||
{
|
||||
try
|
||||
{
|
||||
if(!vsyncFrame && running) running = vm.runStep();
|
||||
if(!vsyncFrame && running)
|
||||
{
|
||||
//writefln("%04X:%s", vm.pc, vm.getCurrent);
|
||||
running = vm.runStep();
|
||||
}
|
||||
}
|
||||
catch(SmileBasicError sbe)
|
||||
{
|
||||
@@ -786,6 +853,8 @@ class PetitComputer
|
||||
}
|
||||
wstring input(wstring prompt, bool useClipBoard)
|
||||
{
|
||||
auto olddisplay = displaynum;
|
||||
displaynum = 0;
|
||||
printConsole(prompt);
|
||||
clearKeyBuffer();
|
||||
wstring buffer;
|
||||
@@ -836,6 +905,7 @@ class PetitComputer
|
||||
}
|
||||
}
|
||||
showCursor = false;
|
||||
display = olddisplay;
|
||||
return buffer;
|
||||
}
|
||||
int CSRX;
|
||||
@@ -1028,6 +1098,55 @@ class PetitComputer
|
||||
glVertex3f((x * 8 + 8) / 200f - 1, 1 - (y * 8 + 8) / 120f, 0);
|
||||
}
|
||||
glEnd();
|
||||
if(xscreenmode != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//下画面
|
||||
glViewport(40, 0, 400, 240);
|
||||
glBindTexture(GL_TEXTURE_2D, GRPF.glTexture);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBegin(GL_QUADS);
|
||||
for(int y = 0; y < consoleHeightDisplay1; y++)
|
||||
for(int x = 0; x < consoleWidthDisplay1; x++)
|
||||
{
|
||||
auto back = consoleColorGL[consoleDisplay1[y][x].backColor];
|
||||
glColor4ubv(cast(ubyte*)&back);
|
||||
glVertex3f((x * 8) / 200f - 1, 1 - (y * 8 + 8) / 120f, 0.9f);
|
||||
glVertex3f((x * 8) / 200f - 1, 1 - (y * 8) / 120f, 0.9f);
|
||||
glVertex3f((x * 8 + 8) / 200f - 1, 1 - (y * 8) / 120f, 0.9f);
|
||||
glVertex3f((x * 8 + 8) / 200f - 1, 1 - (y * 8 + 8) / 120f, 0.9f);
|
||||
}
|
||||
if(showCursor && animationCursor)
|
||||
{
|
||||
glColor4ubv(cast(ubyte*)&consoleColorGL[15]);
|
||||
glVertex3f((CSRX * 8) / 200f - 1, 1 - (CSRY * 8 + 8) / 120f, -0.9f);
|
||||
glVertex3f((CSRX * 8) / 200f - 1, 1 - (CSRY * 8) / 120f, -0.9f);
|
||||
glVertex3f((CSRX * 8 + 2) / 200f - 1, 1 - (CSRY * 8) / 120f, -0.9f);
|
||||
glVertex3f((CSRX * 8 + 2) / 200f - 1, 1 - (CSRY * 8 + 8) / 120f, -0.9f);
|
||||
}
|
||||
glEnd();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
//glAlphaFunc(GL_GEQUAL, 0.5);
|
||||
//glEnable(GL_ALPHA_TEST);
|
||||
glBegin(GL_QUADS);
|
||||
for(int y = 0; y < consoleHeightDisplay1; y++)
|
||||
for(int x = 0; x < consoleWidthDisplay1; x++)
|
||||
{
|
||||
auto fore = consoleColorGL[consoleDisplay1[y][x].foreColor];
|
||||
auto rect = &fontTable[consoleDisplay1[y][x].character];
|
||||
glColor4ubv(cast(ubyte*)&fore);
|
||||
glTexCoord2f((rect.x) / 512f - 1 , (rect.y + 8) / 512f - 1);
|
||||
glVertex3f((x * 8) / 200f - 1, 1 - (y * 8 + 8) / 120f, 0);
|
||||
glTexCoord2f((rect.x) / 512f - 1, (rect.y) / 512f - 1);
|
||||
glVertex3f((x * 8) / 200f - 1, 1 - (y * 8) / 120f, 0);
|
||||
glTexCoord2f((rect.x + 8) / 512f - 1, (rect.y) / 512f - 1);
|
||||
glVertex3f((x * 8 + 8) / 200f - 1, 1 - (y * 8) / 120f, 0);
|
||||
glTexCoord2f((rect.x + 8) / 512f - 1, (rect.y +8) / 512f - 1);
|
||||
glVertex3f((x * 8 + 8) / 200f - 1, 1 - (y * 8 + 8) / 120f, 0);
|
||||
}
|
||||
glEnd();
|
||||
// glFlush();
|
||||
}
|
||||
void printConsole(T...)(T args)
|
||||
@@ -1039,115 +1158,39 @@ class PetitComputer
|
||||
}
|
||||
void printConsoleString(wstring text)
|
||||
{
|
||||
consolem.lock();
|
||||
scope(exit) consolem.unlock();
|
||||
//consolem.lock();
|
||||
//scope(exit) consolem.unlock();
|
||||
//write(text);
|
||||
foreach(wchar c; text)
|
||||
{
|
||||
if(CSRY >= consoleHeight)
|
||||
if(CSRY >= consoleHeightC)
|
||||
{
|
||||
CSRY = consoleHeight - 1;
|
||||
CSRY = consoleHeightC - 1;
|
||||
}
|
||||
if(c != '\r' && c != '\n')
|
||||
{
|
||||
console[CSRY][CSRX].character = c;
|
||||
console[CSRY][CSRX].foreColor = consoleForeColor;
|
||||
console[CSRY][CSRX].backColor = consoleBackColor;
|
||||
consoleC[CSRY][CSRX].character = c;
|
||||
consoleC[CSRY][CSRX].foreColor = consoleForeColor;
|
||||
consoleC[CSRY][CSRX].backColor = consoleBackColor;
|
||||
}
|
||||
CSRX++;
|
||||
if(CSRX >= consoleWidth || c == '\n' || c == '\r')
|
||||
if(CSRX >= consoleWidthC || c == '\n' || c == '\r')
|
||||
{
|
||||
CSRX = 0;
|
||||
CSRY++;
|
||||
}
|
||||
if(CSRY >= consoleHeight)
|
||||
if(CSRY >= consoleHeightC)
|
||||
{
|
||||
auto tmp = console[0];
|
||||
for(int i = 0; i < consoleHeight - 1; i++)
|
||||
auto tmp = consoleC[0];
|
||||
for(int i = 0; i < consoleHeightC - 1; i++)
|
||||
{
|
||||
console[i] = console[i + 1];
|
||||
consoleC[i] = consoleC[i + 1];
|
||||
}
|
||||
console[consoleHeight - 1] = tmp;
|
||||
consoleC[consoleHeightC - 1] = tmp;
|
||||
tmp[] = ConsoleCharacter(0, consoleForeColor, consoleBackColor);
|
||||
//assert(console[0] != console[2]);
|
||||
CSRY = consoleHeight - 1;
|
||||
CSRY = consoleHeightC - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
import std.typecons;
|
||||
import std.typetuple;
|
||||
import std.traits;
|
||||
import otya.smilebasic.error;
|
||||
import otya.smilebasic.type;
|
||||
static string func;
|
||||
class Test
|
||||
{
|
||||
import otya.smilebasic.type;
|
||||
int a;/*
|
||||
static Value abs(Value[] a)
|
||||
{
|
||||
return Value((a[0].castDouble < 0 ? -a[0].castDouble : a[0].castDouble));
|
||||
}*/
|
||||
static double ABS(double a)
|
||||
{
|
||||
return a < 0 ? -a : a;
|
||||
}
|
||||
wstring[] ah;
|
||||
void*[] ahe;
|
||||
alias void function(Value[], Value[]) BuiltinFunc;
|
||||
BuiltinFunc[] builtinFunctions;
|
||||
this()
|
||||
{
|
||||
foreach(name; __traits(derivedMembers, Test))
|
||||
{
|
||||
//writeln(name);
|
||||
ah ~= name;
|
||||
// foreach (t; __traits(getVirtualFunctions, Test, name))
|
||||
{
|
||||
static if(__traits(isStaticFunction, __traits(getMember, Test, name)))
|
||||
{
|
||||
ahe ~= cast(void*)&__traits(getMember, Test, name);
|
||||
writeln(name);
|
||||
auto m = typeid(typeof(__traits(getMember, Test, name)));
|
||||
writeln(m);
|
||||
writeln(AddFunc!(Test,name));
|
||||
builtinFunctions ~= mixin(AddFunc!(Test,name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
template AddFunc(T, string N)
|
||||
{
|
||||
static if(is(ReturnType!(__traits(getMember, T, N)) == double))
|
||||
{
|
||||
const string AddFunc = "function void(Value[] arg, Value[] ret){if(ret.length != 1){throw new IllegalFunctionCall();}ret[0] = Value(" ~ N ~ "(" ~
|
||||
AddFuncArg!(Tuple!(ParameterTypeTuple!(__traits(getMember, T, N))), 0) ~ "));}";
|
||||
}
|
||||
else
|
||||
{
|
||||
const string AddFunc = "";
|
||||
}
|
||||
}
|
||||
template AddFuncArg(P, int N = 0)
|
||||
{
|
||||
static if(is(typeof(P[N]) == double))
|
||||
{
|
||||
const string arg = "arg[" ~ N.to!string ~ "].castDouble";
|
||||
}
|
||||
else
|
||||
{
|
||||
const string arg = "";
|
||||
static assert(false, "Invalid type");
|
||||
}
|
||||
static if(N + 1 == P.length)
|
||||
{
|
||||
const string AddFuncArg = arg;
|
||||
}
|
||||
else
|
||||
{
|
||||
const string AddFuncArg = arg ~ ", " ~ AddFuncArg!(P, N + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import derelict.sdl2.sdl;
|
||||
import derelict.opengl3.gl;
|
||||
enum SpriteAttr
|
||||
{
|
||||
none = 0,
|
||||
show = 0b00001,
|
||||
rotate90 = 0b00010,
|
||||
rotate180 = 0b00100,
|
||||
@@ -113,7 +114,7 @@ struct SpriteAnimData
|
||||
this.data.var = data[i++];
|
||||
break;
|
||||
default:
|
||||
throw new IllegalFunctionCall();
|
||||
throw new IllegalFunctionCall("SPANIM");
|
||||
}
|
||||
return i;
|
||||
}
|
||||
@@ -179,6 +180,10 @@ struct SpriteData
|
||||
this.anim[sat] = anim;
|
||||
isAnim = true;
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
this.define = false;
|
||||
}
|
||||
}
|
||||
struct SpriteDef
|
||||
{
|
||||
@@ -284,7 +289,6 @@ class Sprite
|
||||
}
|
||||
if(sprite.attr & SpriteAttr.show)
|
||||
{
|
||||
glLoadIdentity();
|
||||
int x = cast(int)sprite.x - sprite.homex;
|
||||
int y = cast(int)sprite.y - sprite.homey;
|
||||
int w = sprite.w;
|
||||
@@ -327,6 +331,7 @@ class Sprite
|
||||
glTexCoord2f(u2 / 512f - 1, v / 512f - 1);
|
||||
glVertex3f(sprite.w / 200f, 0, z);//4
|
||||
glEnd();
|
||||
glLoadIdentity();
|
||||
continue;
|
||||
}
|
||||
if((sprite.attr & SpriteAttr.rotate270) == SpriteAttr.rotate270)
|
||||
@@ -340,6 +345,7 @@ class Sprite
|
||||
glTexCoord2f(u2 / 512f - 1, v2 / 512f - 1);//4
|
||||
glVertex3f(w / 200f, 0, z);//4
|
||||
glEnd();
|
||||
glLoadIdentity();
|
||||
continue;
|
||||
}
|
||||
if((sprite.attr & SpriteAttr.rotate90) == SpriteAttr.rotate90)
|
||||
@@ -353,6 +359,7 @@ class Sprite
|
||||
glTexCoord2f(u / 512f - 1, v / 512f - 1);//1
|
||||
glVertex3f(w / 200f, 0, z);//4
|
||||
glEnd();
|
||||
glLoadIdentity();
|
||||
continue;
|
||||
}
|
||||
if((sprite.attr & SpriteAttr.rotate180) == SpriteAttr.rotate180)
|
||||
@@ -366,9 +373,11 @@ class Sprite
|
||||
glTexCoord2f(u / 512f - 1 , v2 / 512f - 1);//2
|
||||
glVertex3f(w / 200f, 0, z);//4
|
||||
glEnd();
|
||||
glLoadIdentity();
|
||||
continue;
|
||||
}
|
||||
glEnd();
|
||||
glLoadIdentity();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -430,4 +439,15 @@ class Sprite
|
||||
}
|
||||
sprites[id].setAnimation(animdata, target);
|
||||
}
|
||||
void spclr(int id)
|
||||
{
|
||||
sprites[id].clear;
|
||||
}
|
||||
void spclr()
|
||||
{
|
||||
for(int i = 0; i < sprites.length; i++)
|
||||
{
|
||||
spclr(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,10 @@ struct Value
|
||||
return this.type == ValueType.IntegerArray || this.type == ValueType.DoubleArray ||
|
||||
this.type == ValueType.StringArray || this.type == ValueType.String;
|
||||
}
|
||||
bool isNumberArray()
|
||||
{
|
||||
return this.type == ValueType.IntegerArray || this.type == ValueType.DoubleArray;
|
||||
}
|
||||
bool isNumber()
|
||||
{
|
||||
return this.type == ValueType.Integer || this.type == ValueType.Double;
|
||||
|
||||
Reference in New Issue
Block a user