1
0

GBOXを実装,GCLSを実装,システム変数DATE$TIME$を実装,そのほか関数を実装,TRUE/FALSEを追加,小数点リテラルを実装.

This commit is contained in:
otya128
2015-08-20 15:28:02 +09:00
parent c9d6043fe4
commit b589766d47
8 changed files with 527 additions and 78 deletions

View File

@@ -207,11 +207,13 @@
<Folder name="SMILEBASIC">
<File path="builtinfunctions.d" />
<File path="compiler.d" />
<File path="draw.d" />
<File path="error.d" />
<File path="main.d" />
<File path="node.d" />
<File path="parser.d" />
<File path="petitcomputer.d" />
<File path="systemvariable.d" />
<File path="TEST.txt" />
<File path="token.d" />
<File path="type.d" />

View File

@@ -1,3 +1,15 @@
GOSUB@A
GOTO@B
'A=SIN(B)
'?Y2,SIN(DAY * 2 * 3.141 / BDAY),LINEH,LINEC
@A
Y2 = LINEC - SIN(DAY * 2 * 3 / BDAY) * LINEH
RETURN
@B
?DATE$, TIME$
DTREAD "2014/10/12" OUT Y,M,D
?Y,M,D
?SIN(1)
'COMMENT'
ASSERT__ 1, "TRUE"
A$="A"
@@ -80,14 +92,18 @@ DEF ONGOSUBTEST
@4
END
@DATA_1
DATA "A",1,2,3,4
DIM ARY[2]
DATA "A",1,2,3,4,5
READ DATA$,_1,_2
READ _3,_4
READ ARY[_1]
ASSERT__ DATA$=="A", "DATA"
ASSERT__ _1==1, "DATA"
ASSERT__ _2==2, "DATA"
ASSERT__ _3==3, "DATA"
ASSERT__ _4==4, "DATA"
ASSERT__ ARY[1]==5, "DATA"
?ARY[_1]
INPUT$="HELLO"
INPUT INPUT$,IN
?INPUT$,IN

View File

@@ -4,6 +4,7 @@ import otya.smilebasic.token;
import otya.smilebasic.error;
import otya.smilebasic.compiler;
import otya.smilebasic.petitcomputer;
import otya.smilebasic.systemvariable;
import std.uni;
import std.utf;
import std.conv;
@@ -17,6 +18,10 @@ struct VMVariable
this.index = index;
this.type = type;
}
this(int index)
{
this.index = index;
}
}
class VM
{
@@ -38,7 +43,8 @@ class VM
this.globalTable = globalTable;
foreach(wstring k, VMVariable v ; globalTable)
{
this.global[v.index] = Value(v.type);
if(v.index >= 0)
this.global[v.index] = Value(v.type);
}
this.functions = functions;
this.globalDataTable = gdt;
@@ -889,10 +895,16 @@ class CallBuiltinFunction : Code
else
{
arg = vm.stack[vm.stacki - argcount..vm.stacki];
result = vm.stack[vm.stacki - argcount..vm.stacki - argcount + outcount];//雑;
result = vm.stack[vm.stacki/* - argcount */+ 1..vm.stacki + 1/* - argcount */+ outcount];//雑;
}
func.func(vm.petitcomputer, arg, result);
vm.stacki -= func.argments.length - outcount;
vm.stacki -= func.argments.length;// - outcount;
////vm.stacki += outcount;
//vm.stacki = old;
for(int i = 0; i < result.length; i++)
{
vm.push(result[i]);
}
}
}
class IncCodeG : Code
@@ -1139,3 +1151,29 @@ class ReadCode : Code
}
}
}
class PushSystemVariable : Code
{
SystemVariable var;
this(SystemVariable var)
{
this.var = var;
}
override void execute(VM vm)
{
vm.push(var.value);
}
}
class PopSystemVariable : Code
{
SystemVariable var;
this(SystemVariable var)
{
this.var = var;
}
override void execute(VM vm)
{
Value v;
vm.pop(v);
var.value = v;
}
}

View File

@@ -15,12 +15,12 @@ struct DefaultValue(T, bool skippable = true)
{
T value;
bool isDefault;
this(int v, bool f)
this(T v, bool f)
{
value = v;
isDefault = f;
}
this(int v)
this(T v)
{
value = v;
isDefault = false;
@@ -67,6 +67,10 @@ class BuiltinFunction
return a < 0 ? -a : a;
}*/
static double function(double) ABS = &abs!double;
static double SIN(double arg1)
{
return sin(arg1);
}
//static ABS = function double(double x) => abs(this.result == ValueType.Double ? 1 : 0);
static void LOCATE(PetitComputer p, DefaultValue!int x, DefaultValue!int y, DefaultValue!(int, false) z)
{
@@ -115,16 +119,84 @@ class BuiltinFunction
static void DISPLAY(PetitComputer p, DefaultValue!(int, false) display)
{
}
static void GCLS(PetitComputer p, DefaultValue!(int, false) display)
static void GCLS(PetitComputer p, DefaultValue!(int, false) color)
{
color.setDefaultValue(p.gcolor);
p.gfill(p.useGRP, 0, 0, 511, 511, cast(int)color);
}
static void GPSET(PetitComputer p, int x, int y, DefaultValue!(int, false) color)
{
//p.gpset(p.useGRP, x, y, );
color.setDefaultValue(p.gcolor);
p.gpset(p.useGRP, x, y, cast(int)color);
}
static void GLINE(PetitComputer p, int x, int y, int x2, int y2, DefaultValue!(int, false) color)
{
color.setDefaultValue(p.gcolor);
p.gline(p.useGRP, x, y, x2, y2, cast(int)color);
}
static void GBOX(PetitComputer p, int x, int y, int x2, int y2, DefaultValue!(int, false) color)
{
color.setDefaultValue(p.gcolor);
p.gbox(p.useGRP, x, y, x2, y2, cast(int)color);
}
static void GFILL(PetitComputer p, int x, int y, int x2, int y2, DefaultValue!(int, false) color)
{
color.setDefaultValue(p.gcolor);
p.gfill(p.useGRP, x, y, x2, y2, cast(int)color);
}
static void GCOLOR(PetitComputer p, int color)
{
p.gcolor = color;
}
static void BEEP(PetitComputer p, DefaultValue!(int, false) display)
{
}
static int RGB(int R, int G, int B, DefaultValue!(int, false) _)
{
if(!_.isDefault)
{
//やや強引なオーバーロード
return PetitComputer.RGB(cast(ubyte)R, cast(ubyte)G, cast(ubyte)B, cast(ubyte)_);
}
return PetitComputer.RGB(cast(ubyte)R, cast(ubyte)G, cast(ubyte)B);
}
static int RND(int max)
{
import std.random;
return uniform(0, max - 1);
}
static void DTREAD(DefaultValue!(wstring, false) date, out int Y, out int M, out int D/*W*/)
{
import std.datetime;
auto currentTime = Clock.currTime();
if(date.isDefault)
{
Y = currentTime.year;
M = currentTime.month;
D = currentTime.day;
}
else
{
import std.format;
auto v = date.value;
formattedRead(v, "%d/%d/%d", &Y, &M, &D);
}
}
//hairetuha?
static int LEN(wstring str)
{
return str.length;
}
static double VAL(wstring str)
{
double val = str.to!double;
return val;
}
static wstring MID(wstring str, int i, int len)
{
//挙動未定
return str[i..i + len];
}
//alias void function(PetitComputer, Value[], Value[]) BuiltinFunc;
static BuiltinFunction[wstring] builtinFunctions;
static this()
@@ -134,7 +206,13 @@ class BuiltinFunction
writeln(name);
static if(/*__traits(isStaticFunction, __traits(getMember, BuiltinFunction, name)) && */name[0].isUpper)
{
builtinFunctions[name] = new BuiltinFunction(
pragma(msg, AddFunc!(BuiltinFunction, name));
wstring suffix = "";
if(is(ReturnType!(__traits(getMember, BuiltinFunction, name)) == wstring))
{
suffix = "$";
}
builtinFunctions[name ~ suffix] = new BuiltinFunction(
GetFunctionParamType!(BuiltinFunction, name),
GetFunctionReturnType!(BuiltinFunction, name),
mixin(AddFunc!(BuiltinFunction, name)),
@@ -179,6 +257,10 @@ template GetFunctionReturnType(T, string N)
{
enum GetFunctionReturnType = ValueType.Void;
}
else static if(is(ReturnType!(__traits(getMember, T, N)) == wstring))
{
enum GetFunctionReturnType = ValueType.String;
}
else
{
enum GetFunctionReturnType = ValueType.Void;
@@ -190,12 +272,22 @@ 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 ~ "(" ~
AddFuncArg!(ParameterTypeTuple!(__traits(getMember, T, N)).length - 1, 0, 0, ParameterTypeTuple!(__traits(getMember, T, 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)) == void))
{
const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){if(ret.length != 0){throw new IllegalFunctionCall();}" ~ N ~ "(" ~
AddFuncArg!(ParameterTypeTuple!(__traits(getMember, T, N)).length - 1, 0, 0, ParameterTypeTuple!(__traits(getMember, T, 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 ~ "(" ~
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 ~ "(" ~
AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(T,N) - 1, 0, 0, 0, T, N
, ParameterTypeTuple!(__traits(getMember, T, N))) ~ "));}";
}
else
{
@@ -217,6 +309,20 @@ DefaultValue!(int, false) fromIntToSkip(Value v)
else
return DefaultValue!(int, false)(true);
}
DefaultValue!wstring fromStringToDefault(Value v)
{
if(v.type == ValueType.String)
return DefaultValue!wstring(v.castString());
else
return DefaultValue!wstring(true);
}
DefaultValue!(wstring, false) fromStringToSkip(Value v)
{
if(v.type == ValueType.String)
return DefaultValue!(wstring, false)(v.castString());
else
return DefaultValue!(wstring, false)(true);
}
template GetFunctionParamType(T, string N)
{
enum GetFunctionParamType = mixin("[" ~ Array!(ParameterTypeTuple!(__traits(getMember, T, N))) ~ "]");
@@ -249,6 +355,14 @@ template GetFunctionParamType(T, string N)
{
const string arg = "ValueType.Integer, true";
}
else static if(is(P[0] == DefaultValue!(wstring)))
{
const string arg = "ValueType.String, false";
}
else static if(is(P[0] == DefaultValue!(wstring, false)))
{
const string arg = "ValueType.String, true";
}
else static if(is(P[0] == PetitComputer))
{
static if(P.length != 0)
@@ -271,42 +385,71 @@ template GetFunctionParamType(T, string N)
}
}
}
template AddFuncArg(int L, int N, int M, P...)
template AddFuncArg(int L, int N, int M, int O, T, string NAME, P...)
{
enum I = L - N;
enum storage = ParameterStorageClassTuple!(__traits(getMember, T, NAME))[M];
static if(is(P[0] == double))
{
enum add = 1;
enum outadd = 0;
const string arg = "arg[" ~ I.to!string ~ "].castDouble";
}
else static if(is(P[0] == PetitComputer))
{
enum add = 0;
enum outadd = 0;
const string arg = "p";
}
else static if(is(P[0] == int))
{
enum add = 1;
const string arg = "arg[" ~ I.to!string ~ "].castInteger";
static if(storage & ParameterStorageClass.out_)
{
enum add = 0;
enum outadd = 1;
const string arg = "ret[" ~ O.to!string ~ "].integerValue";
}
else
{
enum add = 1;
enum outadd = 0;
const string arg = "arg[" ~ I.to!string ~ "].castInteger";
}
}
else static if(is(P[0] == wstring))
{
enum add = 1;
enum outadd = 0;
const string arg = "arg[" ~ I.to!string ~ "].castString";
}
else static if(is(P[0] == DefaultValue!int))
{
enum add = 1;
enum outadd = 0;
const string arg = "fromIntToDefault(arg[" ~ I.to!string ~ "])";
}
else static if(is(P[0] == DefaultValue!(int, false)))
{
enum add = 1;
enum outadd = 0;
const string arg = "fromIntToSkip(arg[" ~ I.to!string ~ "])";
}
else static if(is(P[0] == DefaultValue!wstring))
{
enum add = 1;
enum outadd = 0;
const string arg = "fromStringToDefault(arg[" ~ I.to!string ~ "])";
}
else static if(is(P[0] == DefaultValue!(wstring, false)))
{
enum add = 1;
enum outadd = 0;
const string arg = "fromStringToSkip(arg[" ~ I.to!string ~ "])";
}
else
{
enum add = 1;
enum outadd = 0;
static assert(false, "Invalid type");
const string arg = "";
}
@@ -316,6 +459,62 @@ template AddFuncArg(int L, int N, int M, P...)
}
else
{
const string AddFuncArg = arg ~ ", " ~ AddFuncArg!(L - !add, N + add, M + 1, P[1..$]);
const string AddFuncArg = arg ~ ", " ~ AddFuncArg!(L - !add, N + add, M + 1, O + outadd, T, NAME, P[1..$]);
}
}
template OutArgsInit(T, string N, int I = 0, int J = 0)
{
enum tuple = ParameterStorageClassTuple!(__traits(getMember, T, N))[I];
alias param = ParameterTypeTuple!(__traits(getMember, T, N));
static if(tuple & ParameterStorageClass.out_)
{
enum add = 1;
enum ret1 = "ret[" ~ J.to!string ~ "].type = ";
static if(is(param[I] == int))
{
enum ret2 = "ValueType.Integer;";
}
enum result = ret1 ~ ret2;
}
else
{
enum add = 0;
enum result = "";
}
static if(param.length > I + 1)
{
enum OutArgsInit = result ~ OutArgsInit!(T, N, I + 1, J + add);
}
else
{
enum OutArgsInit = result;
}
}
template GetArgumentCount(T, string N, int I = 0)
{
enum tuple = ParameterStorageClassTuple!(__traits(getMember, T, N))[I];
alias param = ParameterTypeTuple!(__traits(getMember, T, N));
static if(is(param[I] == PetitComputer))
{
enum add = 0 + 1;
}
else
{
static if(tuple & ParameterStorageClass.out_)
{
enum add = 0;
}
else
{
enum add = 1;
}
}
static if(param.length > I + 1)
{
enum GetArgumentCount = add + GetArgumentCount!(T, N, I + 1);
}
else
{
enum GetArgumentCount = add;
}
}

View File

@@ -4,6 +4,7 @@ import otya.smilebasic.token;
import otya.smilebasic.vm;
import otya.smilebasic.type;
import otya.smilebasic.error;
import otya.smilebasic.systemvariable;
import std.stdio;
class Scope
{
@@ -145,6 +146,7 @@ class Compiler
case '%':
return ValueType.Integer;
default:
return ValueType.Double;//非DEFINT時
return ValueType.Integer;//DEFINT時
}
}
@@ -153,8 +155,13 @@ class Compiler
{
this.statements = statements;
code = new Code[0];
global["DATE$"] = VMVariable(-1);
sysVariable["DATE$"] = new Date();
global["TIME$"] = VMVariable(-1);
sysVariable["TIME$"] = new Time();
}
SystemVariable[wstring] sysVariable;
Code[] code;
VMVariable[wstring] global;
int[wstring] globalLabel;
@@ -176,6 +183,19 @@ class Compiler
{
code ~= new PopG(ind);
}
SystemVariable getSystemVariable(wstring name)
{
auto var = sysVariable.get(name, null);
return var;
}
void genCodePushSysVar(wstring name)
{
code ~= new PushSystemVariable(getSystemVariable(name));
}
void genCodePopSysVar(wstring name)
{
code ~= new PopSystemVariable(getSystemVariable(name));
}
void genCodePushVar(wstring name, Scope sc)
{
auto global = hasGlobalVarIndex(name);
@@ -186,6 +206,11 @@ class Compiler
}
if(global)
{
if(global < 0)
{
genCodePushSysVar(name);
return;
}
code ~= new PushG(global);
return;
}
@@ -201,6 +226,11 @@ class Compiler
}
if(global)
{
if(global < 0)
{
genCodePopSysVar(name);
return;
}
code ~= new PopG(global);
return;
}
@@ -371,13 +401,17 @@ class Compiler
case NodeType.CallFunction:
{
auto func = cast(CallFunction)exp;
writeln(func.name);
auto bfun = otya.smilebasic.builtinfunctions.BuiltinFunction.builtinFunctions.get(func.name, null);
if(bfun)
{
auto k = bfun.argments.length - func.args.length;
foreach(l;0..k)
if(bfun.argments.length >= func.args.length)
{
genCodeImm(Value(ValueType.Void));
auto k = bfun.argments.length - func.args.length;
foreach(l;0..k)
{
genCodeImm(Value(ValueType.Void));
}
}
}
foreach_reverse(Expression i ; func.args)
@@ -418,10 +452,11 @@ class Compiler
case NodeType.Variable:
{
auto var = cast(Variable)expr;
int index;
bool local;
getVarIndex(var.name, sc, index, local);
genCode(local ? new PopL(index) : new PopG(index));
genCodePopVar(var.name, sc);
//int index;
//bool local;
//getVarIndex(var.name, sc, index, local);
//genCode(local ? new PopL(index) : new PopG(index));
}
break;
case NodeType.BinaryOperator:

View File

@@ -5,6 +5,7 @@ import otya.smilebasic.node;
import otya.smilebasic.compiler;
import std.ascii;
import std.stdio;
import std.conv;
class Lexical
{
TokenType[] table;
@@ -60,6 +61,7 @@ class Lexical
reserved["DIM"] = TokenType.Var;
reserved["DEF"] = TokenType.Def;
reserved["OUT"] = TokenType.Out;
reserved["out"] = TokenType.Out;//ekkitou
reserved["WHILE"] = TokenType.While;
reserved["WEND"] = TokenType.WEnd;
reserved["INC"] = TokenType.Inc;
@@ -69,6 +71,8 @@ class Lexical
reserved["RESTORE"] = TokenType.Restore;
reserved["ON"] = TokenType.On;
reserved["INPUT"] = TokenType.Input;
reserved["TRUE"] = TokenType.True;
reserved["FALSE"] = TokenType.False;
reserved.rehash();
line = 1;
}
@@ -103,19 +107,34 @@ class Lexical
token = Token(TokenType.NewLine);
break;
}
if(c.isDigit())
if(c.isDigit() || c == '.')
{
int num;
bool dot;
int start = i;
double num;
for(;i < code.length;i++)
{
c = code[i];
if(!c.isDigit())
if(c == '.')
{
if(dot) break;
dot = true;
}
if(!c.isDigit() && c != '.')
{
break;
}
num = num * 10 + (c - '0');
}
token = Token(TokenType.Integer, Value(num));
wstring numstr = code[start..i];
num = numstr.to!double;
if(num <= int.max && num >= int.min && !dot)
{
token = Token(TokenType.Integer, Value(cast(int)num));
}
else
{
token = Token(TokenType.Integer, Value(num));
}
break;
}
if(c.isAlpha() || c == '_')
@@ -138,6 +157,17 @@ class Lexical
else//変数が予約語であることはありえない
{
auto r = reserved.get(iden, TokenType.Unknown);
//TRUE/FALSEは3.1でもDATAに使える定数
if(r == TokenType.True)
{
token = Token(TokenType.Integer, Value(1));
break;
}
if(r == TokenType.False)
{
token = Token(TokenType.Integer, Value(0));
break;
}
if(r != TokenType.Unknown)
{
token = Token(r);
@@ -628,6 +658,20 @@ class Parser
}
}
lex.popFront();
auto token = lex.front;
if(token.type == TokenType.Iden)
{
//NEXT I[,J[,K...]]プチコン3号だと無視
lex.popFront();
token = lex.front;
while(token.type == TokenType.Comma)
{
lex.popFront();
token = lex.front;
if(token.type != TokenType.Iden) break;
lex.popFront();
}
}
return statements;
}
Statements whileStatements()
@@ -655,6 +699,7 @@ class Parser
{
auto token = lex.front();
Statement node = null;
writeln(token.type);
switch(token.type)
{
case TokenType.Print:
@@ -694,6 +739,7 @@ class Parser
if(expr)
func.addArg(expr);
}
if(lex.front().type == TokenType.Out) break;
if(lex.front().type != TokenType.Comma) break;
lex.popFront();
}
@@ -753,8 +799,7 @@ class Parser
node = if_();
return node;
case TokenType.For:
node = forStatement();
break;
return forStatement();
case TokenType.Return:
lex.popFront();
if(isFuncReturnExpr)

View File

@@ -123,6 +123,8 @@ class PetitComputer
ConsoleCharacter[][] console;
bool visibleGRP = true;
int showGRP;
int useGRP;
uint gcolor;
GraphicPage[] GRP;
GraphicPage GRPF;
GraphicPage[] GRPFColor;
@@ -261,6 +263,19 @@ class PetitComputer
}
return new GraphicPage(surface);
}
GraphicPage createEmptyPage()
{
auto surface = SDL_CreateRGBSurface(0, 512, 512, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0xff);
auto pixels = (cast(uint*)surface.pixels);
for(int x = 0; x < surface.w; x++)
{
for(int y = 0; y < surface.h; y++)
{
*pixels++ = 0;
}
}
return new GraphicPage(surface);
}
struct Point
{
int x, y;
@@ -382,7 +397,7 @@ class PetitComputer
GRP = new GraphicPage[6];
for(int i = 0; i < 4; i++)
{
GRP[i] = new GraphicPage(SDL_CreateRGBSurface(0, 512, 512, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0xff));
GRP[i] = createEmptyPage();
}
GRP[4] = createGRPF(spriteFile);
GRP[5] = createGRPF(BGFile);
@@ -431,9 +446,43 @@ class PetitComputer
keybufferlen = keybuffer.length;
keybufferpos = (keybufferpos + 1) % keybuffer.length;
}
Mutex grpmutex;
otya.smilebasic.draw.Draw draw;
void renderGraphic()
{
//grpmutex.lock();
//scope(exit)
// grpmutex.unlock();
drawflag = true;
//betuni kouzoutai demo sonnnani sokudo kawaranasasou
auto len = drawMessageLength;
drawMessageLength = 0;
for(int i = 0; i < len; i++)
{
DrawMessage dm = drawMessageQueue[i];
switch(dm.type)
{
case DrawType.PSET:
draw.gpset(dm.page, dm.x, dm.y ,dm.color);
break;
case DrawType.LINE:
draw.gline(dm.page, dm.x, dm.y ,dm.x2, dm.y2, dm.color);
break;
case DrawType.FILL:
draw.gfill(dm.page, dm.x, dm.y ,dm.x2, dm.y2, dm.color);
break;
case DrawType.BOX:
draw.gbox(dm.page, dm.x, dm.y ,dm.x2, dm.y2, dm.color);
break;
default:
}
}
drawflag = false;
}
void render()
{
bool renderprofile = true;
bool renderprofile;
try
{
version(Windows)
@@ -471,8 +520,12 @@ class PetitComputer
g.createTexture(renderer);
}
//GRP[0] = GRPF;
gpset(0, 10, 10, 0xFF00FF00);
gline(0, 0, 0, 399, 239, RGB(0, 255, 0));
//glEnable(GL_BLEND);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glAlphaFunc(GL_GEQUAL, 0.5);
glEnable(GL_ALPHA_TEST);
draw = new otya.smilebasic.draw.Draw(this);
while(true)
{
auto profile = SDL_GetTicks();
@@ -486,9 +539,10 @@ class PetitComputer
loopcnt = 0;
}
}
renderGraphic();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//renderConsoleGL();
renderGraphicPage();
renderConsoleGL();
SDL_GL_SwapWindow(window);
auto renderticks = (SDL_GetTicks() - profile);
if(renderprofile) writeln(renderticks);
@@ -528,9 +582,18 @@ class PetitComputer
break;
}
}
long delay = (1000/60) - cast(long)(SDL_GetTicks() - profile);
if(delay > 0)
SDL_Delay(cast(uint)delay);
while(true)
{
long delay = (1000/60) - cast(long)(SDL_GetTicks() - profile);
if(delay > 0)
SDL_Delay(cast(uint)delay);
break;
if(delay < 0) break;
renderGraphic();
SDL_Delay(1);
//if(delay > 0)
// SDL_Delay(cast(uint)delay);
}
}
}
catch(Throwable t)
@@ -553,11 +616,13 @@ class PetitComputer
consolem = new Mutex();
keybuffermutex = new Mutex();
grpmutex = new Mutex();
core.thread.Thread thread = new core.thread.Thread(&render);
thread.start();
auto startTicks = SDL_GetTicks();
//とりあえず
auto parser = new Parser(readText(input("LOAD PROGRAM:", true).to!string).to!wstring
auto parser = new Parser(readText("./SYS/EX5BIORHYTHM.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
@@ -603,6 +668,10 @@ class PetitComputer
auto vm = parser.compile();
bool running = true;
vm.init(this);
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));
gbox(0, 78, 78, 40, 40, RGB(255, 255, 0));
while (true)
{
uint elapse;
@@ -712,7 +781,7 @@ class PetitComputer
bool animationCursor;
Mutex consolem;
//プチコン内部表現はRGB5_A1
uint toGLColor(GLenum format, ubyte r, ubyte g, ubyte b, ubyte a)
static uint toGLColor(GLenum format, ubyte r, ubyte g, ubyte b, ubyte a)
{
if(format == GL_BGRA)
{
@@ -724,7 +793,7 @@ class PetitComputer
}
throw new Exception("unsuport enviroment");
}
uint toGLColor(GLenum format, uint petitcolor)
static uint toGLColor(GLenum format, uint petitcolor)
{
if(format == GL_BGRA)
{
@@ -737,7 +806,7 @@ class PetitComputer
throw new Exception("unsuport enviroment");
}
//プチコンと違って[A,]R,G,Bじゃない
void RGBRead(uint color, out ubyte r, out ubyte g, out ubyte b, out ubyte a)
static void RGBRead(uint color, out ubyte r, out ubyte g, out ubyte b, out ubyte a)
{
//エンディアン関係ない
a = color >> 24;
@@ -745,62 +814,107 @@ class PetitComputer
g = color >> 8 & 0xFF;
b = color& 0xFF;
}
uint RGB(ubyte r, ubyte g, ubyte b)
static uint RGB(ubyte r, ubyte g, ubyte b)
{
return 0xFF000000 | r << 16 | g << 8 | b;
}
uint RGB(ubyte a, ubyte r, ubyte g, ubyte b)
static uint RGB(ubyte a, ubyte r, ubyte g, ubyte b)
{
return a << 24 | r << 16 | g << 8 | b;
}
enum DrawType
{
CLEAR,
PSET,
LINE,
FILL,
BOX,
CIRCLE,
TRI,
}
struct DrawMessage
{
DrawType type;
byte page;
short x;
short y;
short x2;
short y2;
uint color;
//
}
static const int dmqqueuelen = 8192;
DrawMessage[] drawMessageQueue = new DrawMessage[dmqqueuelen];
int drawMessageLength;
bool drawflag;
void sendDrawMessage(DrawType type, byte page, short x, short y, uint color)
{
//grpmutex.lock();
//scope(exit)
// grpmutex.unlock();
if(drawMessageLength >= dmqqueuelen)
{
while(drawMessageLength)
{
SDL_Delay(1);
}
}
while(drawflag){}
drawMessageQueue[drawMessageLength].type = type;
drawMessageQueue[drawMessageLength].page = page;
drawMessageQueue[drawMessageLength].x = x;
drawMessageQueue[drawMessageLength].y = y;
drawMessageQueue[drawMessageLength].color = color;
drawMessageLength++;
}
void sendDrawMessage(DrawType type, byte page, short x, short y, short x2, short y2, uint color)
{
grpmutex.lock();
scope(exit)
grpmutex.unlock();
drawMessageQueue[drawMessageLength].type = type;
drawMessageQueue[drawMessageLength].page = page;
drawMessageQueue[drawMessageLength].x = x;
drawMessageQueue[drawMessageLength].y = y;
drawMessageQueue[drawMessageLength].x2 = x2;
drawMessageQueue[drawMessageLength].y2 = y2;
drawMessageQueue[drawMessageLength].color = color;
drawMessageLength++;
}
//TODO:範囲チェック
void gpset(int page, int x, int y, uint color)
{
color = toGLColor(GRP[page].textureFormat, color);
glBindTexture(GL_TEXTURE_2D, GRP[page].glTexture);
glTexSubImage2D(GL_TEXTURE_2D , 0, x, y, 1, 1, GRP[page].textureFormat, GL_UNSIGNED_BYTE, &color);
sendDrawMessage(DrawType.PSET, cast(byte)page, cast(short)x, cast(short)y, color);
}
void gline(int page, int x, int y, int x2, int y2, uint color)
{
import std.math;
int dx = abs(x2 - x);
int dy = abs(y2 - y);
int sx, sy;
if(x < x2) sx = 1; else sx = -1;
if(y < y2) sy = 1; else sy = -1;
int err = dx - dy;
while(true)
{
gpset(page, x, y, color);
if(x == x2 && y == y2)break;
int e2 = 2*err;
if(e2 > -dy)
{
err = err - dy;
x = x + sx;
}
if(e2 < dx)
{
err = err + dx;
y = y + sy ;
}
}
sendDrawMessage(DrawType.LINE, cast(byte)page, cast(short)x, cast(short)y, cast(short)x2, cast(short)y2, color);
}
void gbox(int page, int x, int y, int x2, int y2, uint color)
{
sendDrawMessage(DrawType.BOX, cast(byte)page, cast(short)x, cast(short)y, cast(short)x2, cast(short)y2, color);
}
void gfill(int page, int x, int y, int x2, int y2, uint color)
{
sendDrawMessage(DrawType.FILL, cast(byte)page, cast(short)x, cast(short)y, cast(short)x2, cast(short)y2, color);
}
void renderGraphicPage()
{
float z = 0.01f;
glColor3f(1.0, 1.0, 1.0);
glBindTexture(GL_TEXTURE_2D, GRP[showGRP].glTexture);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0 / 512f - 1 , 240 / 512f - 1);
glVertex3f(0 / 200f - 1, 1 - 240 / 120f, 0);
glVertex3f(0 / 200f - 1, 1 - 240 / 120f, z);
glTexCoord2f(0 / 512f - 1, 0 / 512f - 1);
glVertex3f(0 / 200f - 1, 1 - 0 / 120f, 0);
glVertex3f(0 / 200f - 1, 1 - 0 / 120f, z);
glTexCoord2f(400 / 512f - 1, 0 / 512f - 1);
glVertex3f(400 / 200f - 1, 1 - 0 / 120f, 0);
glVertex3f(400 / 200f - 1, 1 - 0 / 120f, z);
glTexCoord2f(400 / 512f - 1, 240 / 512f - 1);
glVertex3f(400 / 200f - 1, 1 - 240 / 120f, 0);
glVertex3f(400 / 200f - 1, 1 - 240 / 120f, z);
glEnd();
glFlush();
//glFlush();
}
void renderConsoleGL()
{
@@ -829,8 +943,6 @@ class PetitComputer
}
glEnd();
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//glAlphaFunc(GL_GEQUAL, 0.5);
//glEnable(GL_ALPHA_TEST);
@@ -851,7 +963,7 @@ class PetitComputer
glVertex3f((x * 8 + 8) / 200f - 1, 1 - (y * 8 + 8) / 120f, 0);
}
glEnd();
glFlush();
// glFlush();
}
void printConsole(T...)(T args)
{

View File

@@ -63,6 +63,8 @@ enum TokenType
Restore,
On,
Input,
True,
False,
}
struct Token