diff --git a/SMILEBASIC/SMILEBASIC.visualdproj b/SMILEBASIC/SMILEBASIC.visualdproj
index 9a1754c..b0a0ef1 100644
--- a/SMILEBASIC/SMILEBASIC.visualdproj
+++ b/SMILEBASIC/SMILEBASIC.visualdproj
@@ -72,7 +72,7 @@
0
0
-
+ NDirectMode
0
0
0
diff --git a/SMILEBASIC/parser.d b/SMILEBASIC/parser.d
index 3c0d6b4..86bd828 100644
--- a/SMILEBASIC/parser.d
+++ b/SMILEBASIC/parser.d
@@ -6,16 +6,16 @@ import otya.smilebasic.compiler;
import std.ascii;
import std.stdio;
import std.conv;
+import std.range;
class Lexical
{
- TokenType[] table;
- TokenType[wstring] reserved;
+ static TokenType[] table;
+ static TokenType[wstring] reserved;
wstring code;
int index;
int line;
- this(wstring input)
+ static this()
{
- this.code = input;
table = new TokenType[256];
for(int i = 0;i<256;i++)
{
@@ -75,6 +75,10 @@ class Lexical
reserved["TRUE"] = TokenType.True;
reserved["FALSE"] = TokenType.False;
reserved.rehash();
+ }
+ this(wstring input)
+ {
+ this.code = input;
line = 1;
}
bool empty()
@@ -88,10 +92,17 @@ class Lexical
SourceLocation location;
Token token;
private int pos;
+ bool isEmpty;
void popFront()
{
- if(empty())
- {
+ if(index >= code.length)
+ {/*
+ if(!isEmpty)
+ {
+ //token = Token(TokenType.NewLine);
+ isEmpty = true;
+ //return;
+ }*/
token = Token(TokenType.Unknown);
return;
}
@@ -509,7 +520,7 @@ class Parser
{
lex.popFront();
auto statements = new Statements(lex.location);
- while(!lex.empty())
+ do
{
auto token = lex.front();
Statement statement;
@@ -525,7 +536,7 @@ class Parser
{
statements.addStatement(statement);
}
- }
+ } while(!lex.empty());
return statements;
}
bool isFuncReturnExpr = false;
diff --git a/SMILEBASIC/petitcomputer.d b/SMILEBASIC/petitcomputer.d
index 13d381b..a456b16 100644
--- a/SMILEBASIC/petitcomputer.d
+++ b/SMILEBASIC/petitcomputer.d
@@ -134,6 +134,19 @@ version(Windows)
alias extern (Windows) void* function(void*, void*) ImmAssociateContext;
alias extern (Windows) int function(int) ImmDisableIME;
}
+import std.container;
+struct Slot
+{
+ DList!wstring program;
+ void load(wstring data)
+ {
+ import std.algorithm;
+ foreach(l; splitter(data, "\n"))
+ {
+ program.insertBack(l);
+ }
+ }
+}
class PetitComputer
{
this()
@@ -458,11 +471,37 @@ class PetitComputer
Mutex keybuffermutex;
int keybufferpos;
int keybufferlen;
+ enum KeyOp
+ {
+ KEY,
+ COPY,
+ PASTE,
+ UNDO,
+ REDO,
+ }
+ struct Key
+ {
+ wchar key;
+ KeyOp op;
+ this(wchar k)
+ {
+ key = k;
+ op = KeyOp.KEY;
+ }
+ this(KeyOp o)
+ {
+ op = o;
+ }
+ }
//解析した結果キー入力のバッファは127くらい
- wchar[] keybuffer;// = new wchar[128];//Linuxだとこうやって確保した場合書き込むとSEGV
+ Key[] keybuffer;// = new wchar[128];//Linuxだとこうやって確保した場合書き込むとSEGV
void sendKey(wchar key)
{
- keybuffer[keybufferpos] = cast(wchar)key;
+ sendKey(Key(key));
+ }
+ void sendKey(Key key)
+ {
+ keybuffer[keybufferpos] = key;
keybufferlen++;
if(keybufferlen > keybuffer.length)
keybufferlen = cast(int)keybuffer.length;
@@ -908,16 +947,12 @@ class PetitComputer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
version(test) glLoadIdentity();
version(test) glRotatef(rot_test_deg, rot_test_x, rot_test_y, rot_test_z);
+ renderConsoleGL();
+
if(xscreenmode == 1)
{
chScreen(0, 240, 400, 240);
}
- if(xscreenmode == 1)
- {
- chScreen(0, 240, 400, 240);
- }
- version(test) glLoadIdentity();
- version(test) glRotatef(rot_test_deg, rot_test_x, rot_test_y, rot_test_z);
if(xscreenmode == 2)
{
renderGraphicPage(0, 320, 480);
@@ -936,7 +971,6 @@ class PetitComputer
{
chScreen(0, 0, 320, 480);
}
- renderConsoleGL();
if(xscreenmode == 1)
{
chScreen(0, 240, 400, 240);
@@ -1001,6 +1035,14 @@ class PetitComputer
{
auto key = event.key.keysym.sym;
button |= buttonTable[event.key.keysym.scancode];
+ if(key == SDLK_v)
+ {
+ auto mod = event.key.keysym.mod;
+ if((mod & 0xC0))
+ {
+ sendKey(Key(KeyOp.PASTE));
+ }
+ }
if(Button.START & buttonTable[event.key.keysym.scancode])
{
stop();
@@ -1053,9 +1095,24 @@ class PetitComputer
running = false;
stopflg = true;
}
+ void printInformation()
+ {
+ printConsole("otyaSMILEBASIC ver ", otya.smilebasic.systemvariable.Version.VERSIONSTRING, "\n");
+ printConsole("(C)2015-2016 otya\n");
+ printConsole("8327164 bytes free\n");
+ printConsole("\n");
+ printPrompt();
+ }
+ void printPrompt()
+ {
+ //printConsole("[","]");
+ printConsole("OK\n");
+ }
+ Slot[] slot;
void run()
{
- keybuffer = new wchar[128];
+ slot = new Slot[5];
+ keybuffer = new Key[128];
init();
consolem = new Mutex();
keybuffermutex = new Mutex();
@@ -1070,17 +1127,42 @@ class PetitComputer
Parser parser;
otya.smilebasic.vm.VM vm;
bool directMode = false;
+ bool isRunningDirectMode = false;
+ int oldpc;
+ void runSlot(int lot)
+ {
+ parser = new Parser(std.algorithm.reduce!("a ~ b")(slot[lot].program.opSlice));
+ try
+ {
+ vm = parser.compile();
+ vm.init(this);
+ running = true;
+ }
+ catch(SmileBasicError sbe)
+ {
+ printConsole(sbe.getErrorMessage, "\n");
+ if(sbe.getErrorMessage2.length) printConsole(sbe.getErrorMessage2, "\n");
+ writeln(sbe.to!string);
+ writeln(sbe.getErrorMessage2);
+ }
+ catch(Throwable t)
+ {
+ writeln(t);
+ }
+ }
//デバッグ用
version(NDirectMode)
{
- parser = new Parser(
+ slot[0].load(readText("./SYS/EX8TECDEMO.TXT").to!wstring);
+ version(none)
+ parser = new Parser(
//readText("./SYS/GAME6TALK.TXT").to!wstring
//readText("./SYS/GAME7EXPAD.TXT").to!wstring
//readText("./SYS/GAME4SHOOTER.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/EX8TECDEMO.TXT").to!wstring
+ //readText("./SYS/EX8TECDEMO.TXT").to!wstring
//readText("./SYS/EX1TEXT.TXT").to!wstring
//readText("FIZZBUZZ.TXT").to!wstring
//readText("TEST.TXT").to!wstring
@@ -1123,27 +1205,11 @@ class PetitComputer
CL=(CL+1) MOD 16 : VSYNC 1
GOTO @LOOP`*/
);
- try
- {
- vm = parser.compile();
- vm.init(this);
- running = true;
- }
- catch(SmileBasicError sbe)
- {
- printConsole(sbe.getErrorMessage, "\n");
- printConsole(sbe.getErrorMessage2, "\n");
- //printConsole(sbe.to!string);
- writeln(sbe.to!string);
- writeln(sbe.getErrorMessage2);
- }
- catch(Throwable t)
- {
- writeln(t);
- }
+ runSlot(0);
}
else
{
+ printInformation();
directMode = true;
/*vm.code.append(parser.compiler.compileProgram());*/
version(none)
@@ -1194,51 +1260,87 @@ class PetitComputer
vm = (new Parser("")).compile;
vm.init(this);
}
+ else
+ {
+ printPrompt();
+ }
auto prg = input("", true);
- parser = new Parser(prg);
- try
+ auto lex = new Lexical(prg);
+ lex.popFront();
+ auto token = lex.front();
+ if(token.type == otya.smilebasic.token.TokenType.Iden && token.value.stringValue == "RUN")
{
- auto cc = parser.compiler;
- cc.compileDirectMode(vm);
+ lex.popFront();
+ token = lex.front();
+ int slot;
+ bool empty = lex.empty();
+ if(!empty)
+ {
+ if(token.type != otya.smilebasic.token.TokenType.Integer)
+ {
+ printConsole("Illegal function call", "\n");
+ continue;
+ }
+ else
+ {
+ slot = token.value.castInteger;
+ }
+ }
+ isRunningDirectMode = false;
+ runSlot(slot);
}
- catch(SmileBasicError sbe)
+ else if(token.type == otya.smilebasic.token.TokenType.Iden && token.value.stringValue == "CONT")
{
+ vm.pc = oldpc;
+ isRunningDirectMode = false;
+ directMode = false;
+ }
+ else
+ {
+ isRunningDirectMode = true;
+ parser = new Parser(prg);
try
{
- printConsole(sbe.getErrorMessage, "\n");
- if(sbe.getErrorMessage2.length) printConsole(sbe.getErrorMessage2, "\n");
- //printConsole(sbe.to!string);
- writeln(sbe.to!string);
- writeln(sbe.getErrorMessage2);
- auto loc = vm.currentLocation;
- printConsole(loc.line, ":", loc.pos, ":", parser.getLine(loc));
+ auto cc = parser.compiler;
+ cc.compileDirectMode(vm);
+ }
+ catch(SmileBasicError sbe)
+ {
+ try
+ {
+ printConsole(sbe.getErrorMessage, "\n");
+ if(sbe.getErrorMessage2.length) printConsole(sbe.getErrorMessage2, "\n");
+ writeln(sbe.to!string);
+ writeln(sbe.getErrorMessage2);
+ auto loc = vm.currentLocation;
+ printConsole(loc.line, ":", loc.pos, ":", parser.getLine(loc));
+ }
+ catch(Throwable t)
+ {
+ writeln(t);
+ }
+ continue;
}
catch(Throwable t)
{
- writeln(t);
+ try
+ {
+ printConsole(t.to!string);
+ writeln(t);
+ printConsole(parser.getLine(vm.currentLocation));
+ }
+ catch(Throwable t)
+ {
+ writeln(t);
+ }
+ continue;
}
- continue;
}
- catch(Throwable t)
- {
- try
- {
- printConsole(t.to!string);
- writeln(t);
- printConsole(parser.getLine(vm.currentLocation));
- }
- catch(Throwable t)
- {
- writeln(t);
- }
- continue;
- }
- vm.dump();
running = true;
}
//vm.dump;
this.vm = vm;
- bg[0].put(0,0,1);
+ //bg[0].put(0,0,1);
//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));
@@ -1305,6 +1407,9 @@ class PetitComputer
loc = vm.currentLocation;
printConsole("Break on ", vm.currentSlotNumber, ":", loc.line, "\n");
stopflg = false;
+ directMode = true;
+ if(!isRunningDirectMode)
+ oldpc = vm.pc;
}
if(directMode) break;
}
@@ -1362,26 +1467,42 @@ class PetitComputer
wchar k;
//文字入力中はカーソルを表示する
animationCursor = true;
- foreach(key; keybuffer[oldpos..kbp])
+ foreach(key1; keybuffer[oldpos..kbp])
{
- if(key == 8)
+ wchar key = key1.key;
+ wstring ks;
+ if(key1.op == KeyOp.KEY)
{
- k = key;
- if(!buffer.length) continue;
- buffer = buffer[0..$ - 1];
- CSRX--;
- printConsoleString(" ");
- CSRX--;
- continue;
+ if(key == 8)
+ {
+ k = key;
+ if(!buffer.length) continue;
+ buffer = buffer[0..$ - 1];
+ CSRX--;
+ printConsoleString(" ");
+ CSRX--;
+ continue;
+ }
+ if(key == '\r')
+ {
+ k = key;
+ printConsole("\n");
+ break;
+ }
+ immutable(wchar[1]) a = key;
+ ks = a[];
}
- if(key == '\r')
+ else if(key1.op == KeyOp.PASTE)
{
- k = key;
- printConsole("\n");
- break;
+ if(SDL_HasClipboardText())
+ {
+ char* cl = SDL_GetClipboardText();
+ string an = cast(string)(cl[0..std.c.string.strlen(cl)]);
+ ks = an.to!wstring;
+ }
}
- printConsole(key);
- buffer ~= key;
+ printConsole(ks);
+ buffer ~= ks;
}
clearKeyBuffer();
if(k == '\r')
diff --git a/SMILEBASIC/sprite.d b/SMILEBASIC/sprite.d
index abea887..9ad3ea8 100644
--- a/SMILEBASIC/sprite.d
+++ b/SMILEBASIC/sprite.d
@@ -678,8 +678,8 @@ class Sprite
}
sprite.linkx = x;
sprite.linky = y;
- auto homex2 = ((sprite.w / 2 ) - sprite.homex);
- auto homey2 = ((sprite.h / 2 ) - sprite.homey);
+ auto homex2 = ((sprite.w / 2f ) - sprite.homex);
+ auto homey2 = ((sprite.h / 2f ) - sprite.homey);
int w = sprite.w;
int h = sprite.h;
@@ -710,25 +710,26 @@ class Sprite
glTranslatef((flipx2),
((flipy2)), 0);
//glTranslatef((flipx2) / dish - 1,1 - ((flipy2) / dish), 0);
- glScalef(flipx, flipy, 1f);
//アスペクト比を調節しないといけないらしい
//https://groups.google.com/forum/#!topic/android-group-japan/45mjecPSY4s
//http://www.tnksoft.com/blog/?p=2889
//glScalef(1.0f / aspect, 1.0f, 1.0f);
glRotatef(360 - sprite.r, 0.0f, 0.0f, 1.0f );
//glScalef(flipx * aspect, flipy, 1f);
+ glScalef(flipx, flipy, 1f);
glBegin(GL_QUADS);
glColor4ubv(cast(ubyte*)&sprite.color);
if((sprite.attr& 0b111) == SpriteAttr.show)
{
glTexCoord2f(u / 512f - 1, v / 512f - 1);
- glVertex3f(-((sprite.w / 2) - homex2) , -((sprite.h / 2) - homey2), z);//1
+ auto kbc= (-((sprite.w / 2f) - homex2));
+ glVertex3f(-((sprite.w / 2f) - homex2) , -((sprite.h / 2f) - homey2), z);//1
glTexCoord2f(u / 512f - 1 , v2 / 512f - 1);
- glVertex3f(-((sprite.w / 2) - homex2), ((sprite.h / 2) + homey2), z);//2
+ glVertex3f(-((sprite.w / 2f) - homex2), ((sprite.h / 2f) + homey2), z);//2
glTexCoord2f(u2 / 512f - 1, v2 / 512f - 1);
- glVertex3f((sprite.w / 2) + homex2, ((sprite.h / 2) + homey2), z);//3//y+--+x--++
+ glVertex3f((sprite.w / 2f) + homex2, ((sprite.h / 2f) + homey2), z);//3//y+--+x--++
glTexCoord2f(u2 / 512f - 1, v / 512f - 1);
- glVertex3f((sprite.w / 2) + homex2, -((sprite.h / 2) - homey2), z);//4
+ glVertex3f((sprite.w / 2f) + homex2, -((sprite.h / 2f) - homey2), z);//4
glEnd();
glLoadIdentity();
continue;
diff --git a/SMILEBASIC/systemvariable.d b/SMILEBASIC/systemvariable.d
index 650a2d5..add7821 100644
--- a/SMILEBASIC/systemvariable.d
+++ b/SMILEBASIC/systemvariable.d
@@ -92,10 +92,12 @@ class TabStep : SystemVariable
}
class Version : SystemVariable
{
+ static VERSIONSTRING = "3.1.0";
+ static VERSION = 0x3010000;
@property
override Value value()
{
- return Value(0x3010000);
+ return Value(VERSION);
}
}
class FreeMem : SystemVariable