0 || y > 199 ) {
- if( x<0 ) { throw "@pixel x<0"; }
- else if( y<0 ) { throw "@pixel y<0"; }
- else if( y>199 ) { throw "@pixel y>199"; }
+ if (x < 0 || y > 0 || y > 199) {
+ if (x < 0) { throw "@pixel x<0"; }
+ else if (y < 0) { throw "@pixel y<0"; }
+ else if (y > 199) { throw "@pixel y>199"; }
}
- if( this.console.isMultiColor() ) {
- if( x>159) { throw "@pixel x>159"; }
- this._setPixelMC(x,y, colRecord, index );
+ if (this.console.isMultiColor()) {
+ if (x > 159) { throw "@pixel x>159"; }
+ this._setPixelMC(x, y, colRecord, index);
}
else {
- if( x>319) { throw "@pixel x>159"; }
- this._setPixelMono(x,y, colRecord, index );
+ if (x > 319) { throw "@pixel x>159"; }
+ this._setPixelMono(x, y, colRecord, index);
}
}
- _setPixelMono(x,y, colRecord, index ) {
+ _setPixelMono(x, y, colRecord, index) {
var base = this.console.getBitmapAddress();
- var colX = Math.floor(x>>3);
- var rowY = Math.floor(y>>3); //>>3 == /8
- var Xremainder = x-(colX<<3);
- var Yremainder = y-(rowY<<3); //<<3 == *8
+ var colX = Math.floor(x >> 3);
+ var rowY = Math.floor(y >> 3); //>>3 == /8
+ var Xremainder = x - (colX << 3);
+ var Yremainder = y - (rowY << 3); //<<3 == *8
var byteAddr = base +
- (colX*8) +
- (rowY*(40*8)) +
- Yremainder;
- var oldValue = this.peek( byteAddr );
- var mask = Math.pow(2,7-Xremainder);
+ (colX * 8) +
+ (rowY * (40 * 8)) +
+ Yremainder;
+ var oldValue = this.peek(byteAddr);
+ var mask = Math.pow(2, 7 - Xremainder);
var newValue;
- if( index == 1 ) {
- newValue = oldValue | mask;
+ if (index == 1) {
+ newValue = oldValue | mask;
this.setColorCellModified(
- colX,rowY, -1, colRecord.c1, -1 );
+ colX, rowY, -1, colRecord.c1, -1);
}
else {
- newValue = oldValue & (255 - mask);
+ newValue = oldValue & (255 - mask);
this.setColorCellModified(
- colX,rowY, colRecord.c0, -1, -1 );
+ colX, rowY, colRecord.c0, -1, -1);
}
this.poke(byteAddr, newValue);
}
- _setPixelMC(x,y, colRecord, index ) {
+ _setPixelMC(x, y, colRecord, index) {
var base = this.console.getBitmapAddress();
- var colX = Math.floor(x>>2); //>>2 == /4
- var rowY = Math.floor(y>>3); //>>3 == /8
- var Xremainder = x-(colX<<2); //<<2 == *4
- var Yremainder = y-(rowY<<3); //<<3 == *8
+ var colX = Math.floor(x >> 2); //>>2 == /4
+ var rowY = Math.floor(y >> 3); //>>3 == /8
+ var Xremainder = x - (colX << 2); //<<2 == *4
+ var Yremainder = y - (rowY << 3); //<<3 == *8
var byteAddr = base +
- (colX*8) +
- (rowY*(40*8)) +
- Yremainder;
+ (colX * 8) +
+ (rowY * (40 * 8)) +
+ Yremainder;
- var oldValue = this.peek( byteAddr );
- var maskSubPix1 = Math.pow(2,7-(Xremainder*2));
- var maskSubPix2 = maskSubPix1>>1;
+ var oldValue = this.peek(byteAddr);
+ var maskSubPix1 = Math.pow(2, 7 - (Xremainder * 2));
+ var maskSubPix2 = maskSubPix1 >> 1;
var newValue;
- if( index == 1 ) {
- newValue = oldValue & (255 - maskSubPix1);
- newValue = newValue | maskSubPix2;
+ if (index == 1) {
+ newValue = oldValue & (255 - maskSubPix1);
+ newValue = newValue | maskSubPix2;
this.setColorCellModified(
- colX,rowY, colRecord.c0, -1, -1 );
+ colX, rowY, colRecord.c0, -1, -1);
}
- else if( index == 2 ) {
- newValue = oldValue | maskSubPix1;
- newValue = newValue & (255 - maskSubPix2);
+ else if (index == 2) {
+ newValue = oldValue | maskSubPix1;
+ newValue = newValue & (255 - maskSubPix2);
this.setColorCellModified(
- colX,rowY, -1, colRecord.c1, -1 );
+ colX, rowY, -1, colRecord.c1, -1);
}
- else if( index == 3) {
- newValue = oldValue | maskSubPix1;
- newValue = newValue | maskSubPix2;
+ else if (index == 3) {
+ newValue = oldValue | maskSubPix1;
+ newValue = newValue | maskSubPix2;
this.setColorCellModified(
- colX,rowY, -1, -1, colRecord.c2 );
+ colX, rowY, -1, -1, colRecord.c2);
}
else { //0
- newValue = oldValue & (255 - maskSubPix1);
- newValue = newValue & (255 - maskSubPix2);
+ newValue = oldValue & (255 - maskSubPix1);
+ newValue = newValue & (255 - maskSubPix2);
this.setColorCellModified(
- colX,rowY, -1, -1, -1 );
+ colX, rowY, -1, -1, -1);
}
this.poke(byteAddr, newValue);
@@ -961,186 +961,186 @@ class BasicContext {
}
- getPixel(x,y, selector) {
+ getPixel(x, y, selector) {
- if( ! this.console.isBitMapMode() ) { throw "@bitmap mode"; }
+ if (!this.console.isBitMapMode()) { throw "@bitmap mode"; }
- if( this.console.isMultiColor() ) {
- this._getPixelMC(x,y, selector );
+ if (this.console.isMultiColor()) {
+ this._getPixelMC(x, y, selector);
}
else {
- this._getPixelMono(x,y, selector );
+ this._getPixelMono(x, y, selector);
}
}
- _getPixelMono(x,y, selector) {
+ _getPixelMono(x, y, selector) {
var base = this.console.getBitmapAddress();
- var colX = Math.floor(x>>3);
- var rowY = Math.floor(y>>3); //>>3 == /8
- var Xremainder = x-(colX<<3);
- var Yremainder = y-(rowY<<3); //<<3 == *8
+ var colX = Math.floor(x >> 3);
+ var rowY = Math.floor(y >> 3); //>>3 == /8
+ var Xremainder = x - (colX << 3);
+ var Yremainder = y - (rowY << 3); //<<3 == *8
var byteAddr = base +
- (colX*8) +
- (rowY*(40*8)) +
- Yremainder;
- var oldValue = this.peek( byteAddr );
- var mask = Math.pow(2,7-Xremainder);
+ (colX * 8) +
+ (rowY * (40 * 8)) +
+ Yremainder;
+ var oldValue = this.peek(byteAddr);
+ var mask = Math.pow(2, 7 - Xremainder);
var pixelValue = oldValue & (mask);
- if( ( selector === undefined ) || selector == 0 ) {
- if( pixelValue != 0) {
- return 1;
- }
- else {
- return 0;
- }
+ if ((selector === undefined) || selector == 0) {
+ if (pixelValue != 0) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
- else if( selector == 1 ) {
- var charCol = this.console.getChar( colX, rowY );
- var hiVal = (charCol & 240)>>4
- var loVal = charCol & 15;
+ else if (selector == 1) {
+ var charCol = this.console.getChar(colX, rowY);
+ var hiVal = (charCol & 240) >> 4
+ var loVal = charCol & 15;
- if( pixelValue != 0) {
- return loVal;
- }
- else {
- return hiVal;
- }
+ if (pixelValue != 0) {
+ return loVal;
+ }
+ else {
+ return hiVal;
+ }
}
}
- _getPixelMC(x,y, selector) {
-//TODO
+ _getPixelMC(x, y, selector) {
+ //TODO
var base = this.console.getBitmapAddress();
- var colX = Math.floor(x>>2); //>>2 == /4
- var rowY = Math.floor(y>>3); //>>3 == /8
- var Xremainder = x-(colX<<2); //<<2 == *4
- var Yremainder = y-(rowY<<3); //<<3 == *8
+ var colX = Math.floor(x >> 2); //>>2 == /4
+ var rowY = Math.floor(y >> 3); //>>3 == /8
+ var Xremainder = x - (colX << 2); //<<2 == *4
+ var Yremainder = y - (rowY << 3); //<<3 == *8
var byteAddr = base +
- (colX*8) +
- (rowY*(40*8)) +
- Yremainder;
-
- var xr2 = Xremainder*2;
- var byteValue = this.peek( byteAddr );
- var maskSubPix1 = Math.pow(2,7-(xr2));
- var maskSubPix2 = maskSubPix1>>1;
- var shiftResultRight = 6-xr2;
+ (colX * 8) +
+ (rowY * (40 * 8)) +
+ Yremainder;
+
+ var xr2 = Xremainder * 2;
+ var byteValue = this.peek(byteAddr);
+ var maskSubPix1 = Math.pow(2, 7 - (xr2));
+ var maskSubPix2 = maskSubPix1 >> 1;
+ var shiftResultRight = 6 - xr2;
var pixelValue = byteValue & (maskSubPix1 + maskSubPix2);
var pixelValue2 = pixelValue >> shiftResultRight;
- if( ( selector === undefined ) || selector == 0 ) {
- return pixelValue2;
+ if ((selector === undefined) || selector == 0) {
+ return pixelValue2;
}
- else if( selector == 1 ) {
- if( pixelValue2 == 0) {
- return this.peek(53281);
- }
- else if( pixelValue2== 1 || pixelValue2==2) {
- var charCol = this.console.getChar( colX, rowY );
- var hiVal = (charCol & 240)>>4
- var loVal = charCol & 15;
+ else if (selector == 1) {
+ if (pixelValue2 == 0) {
+ return this.peek(53281);
+ }
+ else if (pixelValue2 == 1 || pixelValue2 == 2) {
+ var charCol = this.console.getChar(colX, rowY);
+ var hiVal = (charCol & 240) >> 4
+ var loVal = charCol & 15;
- if( pixelValue2 == 1) {
- return loVal;
- }
- else if( pixelValue2 == 1) {
- return hiVal;
- }
+ if (pixelValue2 == 1) {
+ return loVal;
}
- else {
- return this.console.getCharCol( colX,rowY);
+ else if (pixelValue2 == 1) {
+ return hiVal;
}
+ }
+ else {
+ return this.console.getCharCol(colX, rowY);
+ }
}
}
- setTextChar(x,y,c,col) {
- this.poke(1024+x+(y*40),c);
- if( col === undefined ) {
+ setTextChar(x, y, c, col) {
+ this.poke(1024 + x + (y * 40), c);
+ if (col === undefined) {
return;
}
- this.poke(55296+x+(y*40),col);
+ this.poke(55296 + x + (y * 40), col);
}
- getTextChar(x,y) {
- return this.peek(1024+x+(y*40));
+ getTextChar(x, y) {
+ return this.peek(1024 + x + (y * 40));
}
- getTextColor(x,y) {
- return this.peek(55296+x+(y*40));
+ getTextColor(x, y) {
+ return this.peek(55296 + x + (y * 40));
}
- sendChars( s, newline ) {
+ sendChars(s, newline) {
- for( var i=0; i< s.length; i++) {
- var c=s.charCodeAt( i );
+ for (var i = 0; i < s.length; i++) {
+ var c = s.charCodeAt(i);
- if( c<32 || (c>128 && c<160)) {
- var col = this.code2colMap[ c ];
- if( !(col===undefined)) {
+ if (c < 32 || (c > 128 && c < 160)) {
+ var col = this.code2colMap[c];
+ if (!(col === undefined)) {
this.console.setColor(col);
}
- else if( c==0x12 ) {
+ else if (c == 0x12) {
//this.console.setColor(8); Set reverse
this.reverseOn = true;
}
- else if( c==0x92 ) {
+ else if (c == 0x92) {
//this.console.setColor(8); Set reverse
this.reverseOn = false;
}
- else if( c==0x13 ) {
+ else if (c == 0x13) {
this.console.cursorHome();
}
- else if( c==0x93 ) {
+ else if (c == 0x93) {
this.console.clearScreen()
}
- else if( c==29 ) {
+ else if (c == 29) {
var xy = this.console.getCursorPos();
- if(xy[0]<39) {
- this.console.setCursorX( xy[0] + 1);
+ if (xy[0] < 39) {
+ this.console.setCursorX(xy[0] + 1);
}
}
- else if( c==157 ) {
+ else if (c == 157) {
var xy = this.console.getCursorPos();
- if(xy[0]>0) {
- this.console.setCursorX( xy[0] - 1);
+ if (xy[0] > 0) {
+ this.console.setCursorX(xy[0] - 1);
}
}
- else if( c==17 ) {
+ else if (c == 17) {
var xy = this.console.getCursorPos();
- if(xy[1]<24) {
- this.console.setCursorY( xy[1] + 1);
+ if (xy[1] < 24) {
+ this.console.setCursorY(xy[1] + 1);
}
}
- else if( c==145 ) {
+ else if (c == 145) {
var xy = this.console.getCursorPos();
- if(xy[1]>0) {
- this.console.setCursorY( xy[1] - 1);
+ if (xy[1] > 0) {
+ this.console.setCursorY(xy[1] - 1);
}
}
}
else {
- if( this.reverseOn ) {
- this.console.writeCharRev( String.fromCharCode(c) );
+ if (this.reverseOn) {
+ this.console.writeCharRev(String.fromCharCode(c));
}
else {
- this.console.writeChar( String.fromCharCode(c) );
+ this.console.writeChar(String.fromCharCode(c));
}
}
}
- if( newline ) {
- this.console.writeString( "", true );
+ if (newline) {
+ this.console.writeString("", true);
}
}
@@ -1149,80 +1149,80 @@ class BasicContext {
return xy[0];
}
- sendCharsSimple( s, newline ) {
+ sendCharsSimple(s, newline) {
- for( var i=0; i< s.length; i++) {
- var c=s.charCodeAt( i );
+ for (var i = 0; i < s.length; i++) {
+ var c = s.charCodeAt(i);
- if( this.reverseOn ) {
- this.console.writeCharRev( String.fromCharCode(c) );
+ if (this.reverseOn) {
+ this.console.writeCharRev(String.fromCharCode(c));
}
else {
- this.console.writeChar( String.fromCharCode(c) );
+ this.console.writeChar(String.fromCharCode(c));
}
}
- if( newline ) {
- this.console.writeString( "", true );
+ if (newline) {
+ this.console.writeString("", true);
}
}
- setCursLongXPos( p ) {
+ setCursLongXPos(p) {
var c = this.console;
- var x = this.console.getCursorX( p );
+ var x = this.console.getCursorX(p);
var start = x;
- for( var i=start; i"+line0 );
- console.log( "l1>"+line1 );
+ else if (this.lineMarkers[this.yPos] == 2) {
+ var line0 = this.console.getLine(this.yPos - 1)
+ var line1 = this.console.getLine(this.yPos);
+ console.log("l0>" + line0);
+ console.log("l1>" + line1);
return line0 + line1;
}
- else if ( this.lineMarkers[ this.yPos ] == 1 ) {
- var line0 = this.console.getLine( this.yPos )
- var line1 = this.console.getLine( this.yPos + 1 );
- console.log( "l0>"+line0 );
- console.log( "l1>"+line1 );
+ else if (this.lineMarkers[this.yPos] == 1) {
+ var line0 = this.console.getLine(this.yPos)
+ var line1 = this.console.getLine(this.yPos + 1);
+ console.log("l0>" + line0);
+ console.log("l1>" + line1);
return line0 + line1;
}
}
@@ -1360,10 +1360,10 @@ class BasicContext {
//this.console.setCallbacks( this.consoleCallBacks );
this.hideDebug();
this.updateYPos();
- if ( this.lineMarkers[ this.yPos ] == 0 || this.lineMarkers[ this.yPos ] == 2 ) {
+ if (this.lineMarkers[this.yPos] == 0 || this.lineMarkers[this.yPos] == 2) {
this.printLine("");
}
- else if ( this.lineMarkers[ this.yPos ] == 1 ) {
+ else if (this.lineMarkers[this.yPos] == 1) {
this.printLine("");
this.printLine("");
}
@@ -1374,47 +1374,48 @@ class BasicContext {
}
passDeleteChar() {
this.hideDebug();
- this.console.deleteChar(); this.updateYPos(); }
+ this.console.deleteChar(); this.updateYPos();
+ }
cbLineOverFlow() {
this.updateYPos();
- if( this.yPos<24 ) {
- if ( this.lineMarkers[ this.yPos ] == 0 ) {
- for( var y=23; y>this.yPos; y-- ) {
- this.lineMarkers[ y+1 ] = this.lineMarkers[ y ];
- this.lineCopy( y, y+1 );
+ if (this.yPos < 24) {
+ if (this.lineMarkers[this.yPos] == 0) {
+ for (var y = 23; y > this.yPos; y--) {
+ this.lineMarkers[y + 1] = this.lineMarkers[y];
+ this.lineCopy(y, y + 1);
}
- this.lineMarkers[ this.yPos ] = 1;
- this.lineMarkers[ this.yPos+1 ] = 2;
+ this.lineMarkers[this.yPos] = 1;
+ this.lineMarkers[this.yPos + 1] = 2;
}
}
else {
- for( var y=0; y<24; y++) {
+ for (var y = 0; y < 24; y++) {
this.lineMarkers[y] = this.lineMarkers[y + 1];
}
- this.lineMarkers[ 23 ] = 1;
- this.lineMarkers[ 24 ] = 2;
+ this.lineMarkers[23] = 1;
+ this.lineMarkers[24] = 2;
}
}
- lineCopy( src, dst ) {
+ lineCopy(src, dst) {
var c = this.console;
var ls = [], lsc = [];
- for( var x=0; x<40; x++) {
- var ch = c.getChar( x, src );
- var co = c.getCharCol( x, src );
+ for (var x = 0; x < 40; x++) {
+ var ch = c.getChar(x, src);
+ var co = c.getCharCol(x, src);
- c.setChar( x, dst , ch );
- c.setCharCol( x, dst , co );
+ c.setChar(x, dst, ch);
+ c.setCharCol(x, dst, co);
}
}
cbClearScreen() {
- for( var y=0; y<=24; y++) {
+ for (var y = 0; y <= 24; y++) {
this.lineMarkers[y] = 0;
}
@@ -1422,65 +1423,65 @@ class BasicContext {
cbScroll() {
- for( var y=0; y<24; y++) {
+ for (var y = 0; y < 24; y++) {
this.lineMarkers[y] = this.lineMarkers[y + 1];
}
- this.lineMarkers[ 24 ] = 0;
- this.lineMarkers[ 0 ] = 0;
+ this.lineMarkers[24] = 0;
+ this.lineMarkers[0] = 0;
}
- passPetsciiChar( pC ) {
+ passPetsciiChar(pC) {
this.hideDebug();
- var xy = this.console.writePetsciiChar( pC );
+ var xy = this.console.writePetsciiChar(pC);
}
- passChars( chs, nl ) {
+ passChars(chs, nl) {
this.hideDebug();
- var xy = this.sendChars( chs, nl );
+ var xy = this.sendChars(chs, nl);
}
- passString( x ) {
+ passString(x) {
this.hideDebug();
- var xy = this.console.writeString( x );
+ var xy = this.console.writeString(x);
- }
+ }
- setEditModeCallBacks( type ) {
- if( type == "edit" ) {
- this.console.setCallbacks( this.consoleCallBacksAll );
+ setEditModeCallBacks(type) {
+ if (type == "edit") {
+ this.console.setCallbacks(this.consoleCallBacksAll);
}
- else if( type == "print" ) {
- this.console.setCallbacks( this.consoleCallBacksClScr );
+ else if (type == "print") {
+ this.console.setCallbacks(this.consoleCallBacksClScr);
}
- else {
+ else {
this.console.clearCallbacks();
}
}
- clearScreen( ) {
+ clearScreen() {
this.console.clearScreen();
}
- compressPGMText( pgmTxt ) {
+ compressPGMText(pgmTxt) {
- var p = new Parser( this.commands, this.extendedcommands );
+ var p = new Parser(this.commands, this.extendedcommands);
p.init();
var kws = p.getKeyWordCodes();
var txt2 = pgmTxt;
- for( var i=0; i=94 ) {
- var symdef = this.symbolTableBM[ c ];
- if( ! ( symdef === undefined ) ) {
- dst += "{" + symdef + "}";
+ for (var i = 0; i < txt.length; i++) {
+ var c = txt.charCodeAt(i);
+ if (c < 31 || c == 92 || c >= 94) {
+ var symdef = this.symbolTableBM[c];
+ if (!(symdef === undefined)) {
+ dst += "{" + symdef + "}";
}
else {
- dst += "{"+c+"}"
+ dst += "{" + c + "}"
}
}
else {
- dst += txt.charAt( i );
+ dst += txt.charAt(i);
}
}
return dst.toLowerCase();
}
- replaceAll( src, str1, str2 ) {
+ replaceAll(src, str1, str2) {
var rv = src;
- while( rv.indexOf( str1 ) > -1 ) {
- rv = rv.replace( str1, str2 );
+ while (rv.indexOf(str1) > -1) {
+ rv = rv.replace(str1, str2);
}
return rv;
}
- rebuildNoPETSCIILineString( raw )
- {
+ rebuildNoPETSCIILineString(raw) {
- var p = new Parser( this.commands, this.extendedcommands );
+ var p = new Parser(this.commands, this.extendedcommands);
p.init();
- var noPetsciiLine = this.prepareLineForExportNoPETSCII( raw, false );
- var rec = p.parseLine( noPetsciiLine );
+ var noPetsciiLine = this.prepareLineForExportNoPETSCII(raw, false);
+ var rec = p.parseLine(noPetsciiLine);
return rec;
}
- prepareLineForExportNoPETSCII( txt0, toLower ) {
+ prepareLineForExportNoPETSCII(txt0, toLower) {
var txt;
txt = txt0.trim();
var dst = "";
- var last= "";
+ var last = "";
- for( var i=0; i=94 ) {
+ for (var i = 0; i < txt.length; i++) {
+ var c = txt.charCodeAt(i);
+ var cc = txt.charAt(i);
+ if (c < 31 || c == 92 || c >= 94) {
- var prevCharIsQuote = false, nextCharIsQuote=false;
- if( (i+1)tpthentp=s
-//
- if( prevCharIsQuote && !nextCharIsQuote ) {
- dst = dst.substr( 0, dst.length-1 );
- dst += "CHR$("+c+");\"";
+ //
+ //7 print"{home}{white}":print spc(9);"game over sc:";s;" top:";tp:ifs>tpthentp=s
+ //
+ if (prevCharIsQuote && !nextCharIsQuote) {
+ dst = dst.substr(0, dst.length - 1);
+ dst += "CHR$(" + c + ");\"";
}
- else if( prevCharIsQuote && nextCharIsQuote ) {
- dst = dst.substr( 0, dst.length-1 );
- dst += "CHR$("+c+")";
- i++;
+ else if (prevCharIsQuote && nextCharIsQuote) {
+ dst = dst.substr(0, dst.length - 1);
+ dst += "CHR$(" + c + ")";
+ i++;
}
- else if( !prevCharIsQuote && nextCharIsQuote ) {
- dst += "\";CHR$("+c+")";
- i++;
+ else if (!prevCharIsQuote && nextCharIsQuote) {
+ dst += "\";CHR$(" + c + ")";
+ i++;
}
else {
- dst += "\";CHR$("+c+");\"";
+ dst += "\";CHR$(" + c + ");\"";
}
}
else {
- dst += txt.charAt( i );
+ dst += txt.charAt(i);
}
last = cc;
}
- var dst2= this.replaceAll( dst, ";\"\";",";");
+ var dst2 = this.replaceAll(dst, ";\"\";", ";");
- if( toLower ) { return dst2.toLowerCase(); }
+ if (toLower) { return dst2.toLowerCase(); }
return dst2;
}
- ResolveStringSymbolToCode( x ) {
+ ResolveStringSymbolToCode(x) {
- if(this.symbolTable[x]) {
+ if (this.symbolTable[x]) {
return this.symbolTable[x];
}
@@ -1623,49 +1621,49 @@ class BasicContext {
}
- prepareLineForImport( txt0 ) {
+ prepareLineForImport(txt0) {
var txt;
txt = txt0.trim().toUpperCase();
var dst = "";
- var i=0; while( i= 0) {
+ else if (("" + p.data).indexOf(".") >= 0) {
val = parseFloat(p.data);
}
else {
val = parseInt(p.data);
}
}
- else if( p.type=="str" ) {
+ else if (p.type == "str") {
val = p.data;
}
- else if( p.type=="var" ) {
- if(p.data.startsWith("TI")) {
+ else if (p.type == "var") {
+ if (p.data.startsWith("TI")) {
val = this.getJiffyTime();
- if(p.data.endsWith("$")) {
+ if (p.data.endsWith("$")) {
val = this.getTime();
val = "" +
this.padZeros2(val[0]) +
@@ -1728,63 +1726,63 @@ class BasicContext {
}
}
else {
- val = this.vars[ p.data ];
+ val = this.vars[p.data];
}
- if( val == undefined ) {
+ if (val == undefined) {
val = 0;
}
}
- else if( p.type=="array" ) {
+ else if (p.type == "array") {
var varIntName = "@array_" + p.data;
- var arr = this.vars[ varIntName ];
+ var arr = this.vars[varIntName];
- if( arr === undefined ) {
+ if (arr === undefined) {
throw "@no such array";
}
- if( arr.getIndexCount() != p.indices.length ) {
- throw "@bad subscript";
+ if (arr.getIndexCount() != p.indices.length) {
+ throw "@bad subscript";
}
var indices = [];
- for( var ai=0; ai" ) {
- if( val > (this.evalExpressionPart( p ) ) ) {
+ else if (p.op == ">") {
+ if (val > (this.evalExpressionPart(p))) {
val = -1;
} else {
val = 0;
}
}
- else if( p.op == "=" ) {
- if( val == (this.evalExpressionPart( p ) ) ) {
+ else if (p.op == "=") {
+ if (val == (this.evalExpressionPart(p))) {
val = -1;
} else {
val = 0;
}
}
- else if( p.op == "<>" ) {
- if( val != (this.evalExpressionPart( p ) ) ) {
+ else if (p.op == "<>") {
+ if (val != (this.evalExpressionPart(p))) {
val = -1;
} else {
val = 0;
}
}
- else if( p.op == "<=" ) {
- if( val <= (this.evalExpressionPart( p ) ) ) {
+ else if (p.op == "<=") {
+ if (val <= (this.evalExpressionPart(p))) {
val = -1;
} else {
val = 0;
}
}
- else if( p.op == ">=" ) {
- if( val >= (this.evalExpressionPart( p ) ) ) {
+ else if (p.op == ">=") {
+ if (val >= (this.evalExpressionPart(p))) {
val = -1;
} else {
val = 0;
@@ -1921,15 +1919,15 @@ class BasicContext {
}
else {
- throw "@unknown op '"+p.op+"'";
+ throw "@unknown op '" + p.op + "'";
}
}
- if( expr.negate ) {
+ if (expr.negate) {
return -val;
}
- if( expr.binaryNegate ) {
- if( val == 0 ) {
+ if (expr.binaryNegate) {
+ if (val == 0) {
return -1;
}
return 0;
@@ -1939,13 +1937,13 @@ class BasicContext {
panicIfStopped() {
- if( !this.runFlag && this.exitMode == "panic") {
+ if (!this.runFlag && this.exitMode == "panic") {
var bitmap = this.console.isBitMapMode();
this.resetVic();
- if( bitmap ) {
- this.setCursor(0,22);
+ if (bitmap) {
+ this.setCursor(0, 22);
this.printLine("");
this.printLine("");
this.printLine("");
@@ -1960,44 +1958,44 @@ class BasicContext {
this.inputFlag = false;
- var l = this.program[ this.runPointer ];
+ var l = this.program[this.runPointer];
var cmds = l[1];
//console.log(cmds);
- if( this.runPointer > -1 ) {
+ if (this.runPointer > -1) {
- var l=this.program[this.runPointer];
- //console.log( l[0] + "after input >>(" + this.runPointer + ":" + this.runPointer2 +")");
+ var l = this.program[this.runPointer];
+ //console.log( l[0] + "after input >>(" + this.runPointer + ":" + this.runPointer2 +")");
}
this.runPointer2++;
- if( this.runPointer > -1 ) {
+ if (this.runPointer > -1) {
- var l=this.program[this.runPointer];
- //console.log( l[0] + "after input >>>(" + this.runPointer + ":" + this.runPointer2 +")");
+ var l = this.program[this.runPointer];
+ //console.log( l[0] + "after input >>>(" + this.runPointer + ":" + this.runPointer2 +")");
}
- if( this.runPointer2 >= cmds.length ) {
+ if (this.runPointer2 >= cmds.length) {
this.runPointer2 = 0;
this.runPointer++;
- if( this.runPointer > -1 ) {
+ if (this.runPointer > -1) {
- var l=this.program[this.runPointer];
- //console.log( l[0] + "after input >>>>(" + this.runPointer + ":" + this.runPointer2 +")");
+ var l = this.program[this.runPointer];
+ //console.log( l[0] + "after input >>>>(" + this.runPointer + ":" + this.runPointer2 +")");
}
- if( this.runPointer >= p.length ) {
+ if (this.runPointer >= p.length) {
- if( this.runPointer > -1 ) {
+ if (this.runPointer > -1) {
- var l=this.program[this.runPointer];
- //console.log( l[0] + "after input >>>>>(" + this.runPointer + ":" + this.runPointer2 +")");
+ var l = this.program[this.runPointer];
+ //console.log( l[0] + "after input >>>>>(" + this.runPointer + ":" + this.runPointer2 +")");
}
this.runFlag = false;
@@ -2034,98 +2032,97 @@ class BasicContext {
try {
- if( !this.runFlag ||
- this.menuFocus ||
- this.inputFlag ||
- this.listFlag
- ) {
+ if (!this.runFlag ||
+ this.menuFocus ||
+ this.inputFlag ||
+ this.listFlag
+ ) {
- if( this.listFlag ) {
- if( this.listPointer < this.list.length ) {
- this.listCodeLine( this.list[ this.listPointer ] );
- this.listPointer++;
- }
- else {
- this.listFlag = false;
- this.printLine("ready.");
- }
+ if (this.listFlag) {
+ if (this.listPointer < this.list.length) {
+ this.listCodeLine(this.list[this.listPointer]);
+ this.listPointer++;
+ }
+ else {
+ this.listFlag = false;
+ this.printLine("ready.");
+ }
}
- if(this.cursorCount++>this.cursorCountMax) {
+ if (this.cursorCount++ > this.cursorCountMax) {
this.cursorCount = 0;
- if( !this.menuFocus && !this.listFlag )
- {
- c.blinkCursor();
- }
+ if (!this.menuFocus && !this.listFlag) {
+ c.blinkCursor();
+ }
}
}
else {
- if(this.debugFlag) console.log("START CYCLE------------------------------" );
+ if (this.debugFlag) console.log("START CYCLE------------------------------");
var p = this.program;
while (true) {
- if( this.breakCycleFlag ) {
+ if (this.breakCycleFlag) {
this.breakCycleFlag = false;
break;
}
- if(this.debugFlag) console.log("START CYCLE LOOP-------------" );
- var l = p[ this.runPointer ];
+ if (this.debugFlag) console.log("START CYCLE LOOP-------------");
+ var l = p[this.runPointer];
var bf = this.runPointer2;
- if(this.debugFlag) console.log(" this.runPointer = " + this.runPointer, " this.runPointer2 = " + this.runPointer2 );
- if(this.debugFlag) console.log(" cmdCount = " + cmdCount);
+ if (this.debugFlag) console.log(" this.runPointer = " + this.runPointer, " this.runPointer2 = " + this.runPointer2);
+ if (this.debugFlag) console.log(" cmdCount = " + cmdCount);
/****************************
*
The actual execution of commands is done by the command below
*
****************************/
- var rv = this.runCommands( l[1], cmdCount );
+ var rv = this.runCommands(l[1], cmdCount);
- var af = rv[ 1 ];
+ var af = rv[1];
- if( rv[0] == MIDLINE_INTERUPT) {
+ if (rv[0] == MIDLINE_INTERUPT) {
this.runPointer2 = af;
}
var executedCount = rv[2];
- if(this.debugFlag) console.log(" bf = " + bf, " af = " + af);
- if(this.debugFlag) console.log(" executedCount = " + executedCount);
- if(this.debugFlag) console.log(" rv = " + rv);
+ if (this.debugFlag) console.log(" bf = " + bf, " af = " + af);
+ if (this.debugFlag) console.log(" executedCount = " + executedCount);
+ if (this.debugFlag) console.log(" rv = " + rv);
cmdCount = cmdCount - executedCount;
- if( rv[0]<=0 ) {
- if(this.debugFlag) console.log(" PGM END!!!!" );
+ if (rv[0] <= 0) {
+ if (this.debugFlag) console.log(" PGM END!!!!");
this.runFlag = false;
this.printLine("");
this.printLine("ready.");
this.panicIfStopped();
- if( rv[0] == END_W_ERROR ) {
+ if (rv[0] == END_W_ERROR) {
var e = null;
- if( rv.length >= 4 ) {
+ if (rv.length >= 4) {
e = rv[3];
}
- console.log("ERROR: ", e, " LINE ", this.retreiveRuntimeLine() );
- console.log("PARAMETER DUMP:", this.vars );
- console.log("FUNCTION DUMP:", this.functions );
+ console.log("ERROR: ", e, " LINE ", this.retreiveRuntimeLine());
+ console.log("PARAMETER DUMP:", this.vars);
+ console.log("FUNCTION DUMP:", this.functions);
}
- if(this.debugFlag) console.log("CYCLE RETURN END");
+ if (this.debugFlag) console.log("CYCLE RETURN END");
return;
}
- else if( rv[0] == LINE_FINISHED ) {
- this.runPointer ++;
+ else if (rv[0] == LINE_FINISHED) {
+ this.runPointer++;
this.runPointer2 = 0;
- if(this.debugFlag) console.log(" new this.runPointer = " + this.runPointer, " this.runPointer2 = " + this.runPointer2 );
+ if (this.debugFlag) console.log(" new this.runPointer = " + this.runPointer, " this.runPointer2 = " + this.runPointer2);
- if( this.runPointer >= p.length ) {
- if(this.debugFlag) console.log( "end program");
+ if (this.runPointer >= p.length) {
+ if (this.debugFlag) console.log("end program");
this.runFlag = false;
this.panicIfStopped();
c.clearCursor();
@@ -2133,29 +2130,29 @@ class BasicContext {
break;
}
}
- else if( rv[0] == TERMINATE_W_JUMP ) {
+ else if (rv[0] == TERMINATE_W_JUMP) {
- if(this.debugFlag) console.log(" jump to new this.runPointer = " + this.runPointer, " this.runPointer2 = " + this.runPointer2 );
+ if (this.debugFlag) console.log(" jump to new this.runPointer = " + this.runPointer, " this.runPointer2 = " + this.runPointer2);
}
- else if( rv[0] == PAUSE_F_INPUT ) {
+ else if (rv[0] == PAUSE_F_INPUT) {
this.runPointer2 = af;
//console.log("CYCLE PAUSE 4 INPUT");
//console.log("CYCLE PAUSE 4 INPUT" + this.runPointer + "," + this.runPointer2);
- if(this.debugFlag) console.log("CYCLE PAUSE 4 INPUT" + this.runPointer + "," + this.runPointer2);
+ if (this.debugFlag) console.log("CYCLE PAUSE 4 INPUT" + this.runPointer + "," + this.runPointer2);
break;
}
- if( cmdCount<=0 ) {
- if(this.debugFlag) console.log("Breaking cmdCount=" + cmdCount)
+ if (cmdCount <= 0) {
+ if (this.debugFlag) console.log("Breaking cmdCount=" + cmdCount)
break;
}
}
- if(this.debugFlag) console.log(" this.runPointer = " + this.runPointer, " this.runPointer2 = " + this.runPointer2 );
+ if (this.debugFlag) console.log(" this.runPointer = " + this.runPointer, " this.runPointer2 = " + this.runPointer2);
}
@@ -2163,9 +2160,9 @@ class BasicContext {
catch (e) {
c.clearCursor();
- if( this.erh.isSerializedError( e ) ) {
- var err = this.erh.fromSerializedError( e );
- this.printError( err.clazz );
+ if (this.erh.isSerializedError(e)) {
+ var err = this.erh.fromSerializedError(e);
+ this.printError(err.clazz);
}
else {
this.printError("unexpected");
@@ -2174,9 +2171,9 @@ class BasicContext {
this.printLine("ready.");
this.runFlag = false;
this.panicIfStopped();
- console.log("ERROR: ", e, " LINE ", this.retreiveRuntimeLine() );
- console.log("PARAMETER DUMP:", this.vars );
- console.log("FUNCTION DUMP:", this.functions );
+ console.log("ERROR: ", e, " LINE ", this.retreiveRuntimeLine());
+ console.log("PARAMETER DUMP:", this.vars);
+ console.log("FUNCTION DUMP:", this.functions);
}
@@ -2187,89 +2184,89 @@ class BasicContext {
doReturn() {
var oldPointers = this.gosubReturn.pop();
- if( oldPointers === undefined ) {
+ if (oldPointers === undefined) {
throw "@return without gosub";
}
- this.runPointer2 = oldPointers[ 1 ];
- this.runPointer = oldPointers[ 0 ];
+ this.runPointer2 = oldPointers[1];
+ this.runPointer = oldPointers[0];
//this.goto( oldLine );
}
- gosub( line, runPointer2 ) {
+ gosub(line, runPointer2) {
var pgm = this.program;
- var len=this.program.length;
+ var len = this.program.length;
var retLine = null;
var retCmd = null;
this.runPointer2 = runPointer2;
- if( ( this.runPointer2 + 1) < this.program[ this.runPointer ][1].length ) {
+ if ((this.runPointer2 + 1) < this.program[this.runPointer][1].length) {
retCmd = this.runPointer2 + 1;
retLine = this.runPointer;
}
else {
- if( (this.runPointer+1) < len ) {
- retCmd=0;
- retLine = this.runPointer+1 ;
+ if ((this.runPointer + 1) < len) {
+ retCmd = 0;
+ retLine = this.runPointer + 1;
}
else {
- retCmd=9999;
+ retCmd = 9999;
retLine = this.runPointer;
}
}
- this.gosubReturn.push( [ retLine, retCmd ] );
- this.goto( line );
+ this.gosubReturn.push([retLine, retCmd]);
+ this.goto(line);
}
- goto( line ) {
+ goto(line) {
var pgm = this.program;
- var len=this.program.length;
+ var len = this.program.length;
var found = false;
- for( var i=0; i= this.data.length ) {
+ if (this.dataPointer >= this.data.length) {
return undefined;
}
- var result = this.data[ this.dataPointer ];
+ var result = this.data[this.dataPointer];
this.dataPointer++;
return result;
}
- printLineVisibleChars( rawLine ) {
+ printLineVisibleChars(rawLine) {
- for( var i=0; i1 ) {
- if( tokens[i].type == "num" &&
- tokens[i-1].type == "pad" &&
- tokens[i-2].type == "name" && tokens[i-2].data == "THEN" ) {
+ if (i > 1) {
+ if (tokens[i].type == "num" &&
+ tokens[i - 1].type == "pad" &&
+ tokens[i - 2].type == "name" && tokens[i - 2].data == "THEN") {
foundGoto = true;
}
- else if( tokens[i].type == "num" && tokens[i-1].type == "name" && tokens[i-1].data == "THEN" ) {
+ else if (tokens[i].type == "num" && tokens[i - 1].type == "name" && tokens[i - 1].data == "THEN") {
foundGoto = true;
}
}
}
- if( tokens[i].type == "num" && foundGoto ) {
- var newLine = renumbering[ "old_" + tokens[i].data ];
- if( newLine == undefined ) { newLine = 99999;}
- tokens[i].data =newLine;
+ if (tokens[i].type == "num" && foundGoto) {
+ var newLine = renumbering["old_" + tokens[i].data];
+ if (newLine == undefined) { newLine = 99999; }
+ tokens[i].data = newLine;
foundGoto = false;
}
}
@@ -2377,39 +2373,39 @@ class BasicContext {
var newString;
newString = nr;
- if( removePadding ) {
- newString = nr + " " ;
- }
- for( var i = 1 ; i< tokens.length; i++) {
- if( removePadding ) {
- if( tokens[i].type == "pad" ) {
- continue;
- }
- }
-
- if( shortenKeywords ) {
- if( tokens[i].type == "name" && tokens[i].data == "PRINT" ) {
- tokens[i].data = "?";
- }
- }
- else {
- if( tokens[i].type == "name" && tokens[i].data == "?" ) {
- tokens[i].data = "PRINT";
- }
- }
-
- if( tokens[i].type == "str" ) {
+ if (removePadding) {
+ newString = nr + " ";
+ }
+ for (var i = 1; i < tokens.length; i++) {
+ if (removePadding) {
+ if (tokens[i].type == "pad") {
+ continue;
+ }
+ }
+
+ if (shortenKeywords) {
+ if (tokens[i].type == "name" && tokens[i].data == "PRINT") {
+ tokens[i].data = "?";
+ }
+ }
+ else {
+ if (tokens[i].type == "name" && tokens[i].data == "?") {
+ tokens[i].data = "PRINT";
+ }
+ }
+
+ if (tokens[i].type == "str") {
newString += "\"" + tokens[i].data + "\"";
}
- else if( tokens[i].type == "name" && addSmartPadding == true) {
+ else if (tokens[i].type == "name" && addSmartPadding == true) {
newString += tokens[i].data + " ";
}
- else if( tokens[i].type == "num" && addSmartPadding == true) {
- if( tokens[i].data.length == 1 ) {
- newString += " " + tokens[i].data;
+ else if (tokens[i].type == "num" && addSmartPadding == true) {
+ if (tokens[i].data.length == 1) {
+ newString += " " + tokens[i].data;
}
else {
- newString += tokens[i].data;
+ newString += tokens[i].data;
}
}
else {
@@ -2418,16 +2414,16 @@ class BasicContext {
}
- var rec = p.parseLine( newString );
+ var rec = p.parseLine(newString);
return rec;
}
- lineIsData( line ) {
- console.log( line );
- if( line[1].length == 1 ) {
- if( ! ( line[1][0].controlKW === undefined) ) {
- if( line[1][0].controlKW.toUpperCase() == "DATA" ) {
+ lineIsData(line) {
+ console.log(line);
+ if (line[1].length == 1) {
+ if (!(line[1][0].controlKW === undefined)) {
+ if (line[1][0].controlKW.toUpperCase() == "DATA") {
return true;
}
}
@@ -2435,16 +2431,16 @@ class BasicContext {
return false;
}
- lineIsRem( line ) {
- console.log( line );
- if( line[1].length == 1 ) {
- if( ! ( line[1][0].controlKW === undefined) ) {
- if( line[1][0].controlKW.toUpperCase() == "REM" ) {
+ lineIsRem(line) {
+ console.log(line);
+ if (line[1].length == 1) {
+ if (!(line[1][0].controlKW === undefined)) {
+ if (line[1][0].controlKW.toUpperCase() == "REM") {
var remIndex = line[2].indexOf("REM");
- if( remIndex == -1 ) { console.log( "warning: invalid rem statement on line " + line[0]); return false ; }
+ if (remIndex == -1) { console.log("warning: invalid rem statement on line " + line[0]); return false; }
- var checkline = line[2].substring( remIndex + 3 ).trim();
- if( checkline.startsWith( "-" ) ) {
+ var checkline = line[2].substring(remIndex + 3).trim();
+ if (checkline.startsWith("-")) {
return true;
}
}
@@ -2453,7 +2449,7 @@ class BasicContext {
return false;
}
- renumberProgram( start, gap ) {
+ renumberProgram(start, gap) {
var p = this.program;
@@ -2463,114 +2459,114 @@ class BasicContext {
var method = this.renumMode;
- if( method == "plain" ) {
- for( var i=0; i 0) {
+ if (this.program.length > 0) {
this.runFlag = true;
this.inputFlag = false;
c.clearCursor();
@@ -2659,38 +2655,40 @@ class BasicContext {
}
- doForInit( from, to, step, varName, cmdPointer, cmdArrayLen, linePointersLen ) {
+ doForInit(from, to, step, varName, cmdPointer, cmdArrayLen, linePointersLen) {
var ctx = this.forContext;
- if( this.vars[ varName ] === undefined ) {
- this.vars[ varName ] = 0;
+ if (this.vars[varName] === undefined) {
+ this.vars[varName] = 0;
}
- this.vars[ varName ] = this.evalExpression( from );
+ this.vars[varName] = this.evalExpression(from);
- ctx.default.push( varName );
+ ctx.default.push(varName);
ctx[varName] = {};
var ctxv = ctx[varName];
- ctxv.to = this.evalExpression( to );
+ ctxv.to = this.evalExpression(to);
- if( step == null ) {
- ctxv.step = 1;
+ if (step == null) {
+ ctxv.step = 1;
}
else {
- ctxv.step = this.evalExpression( step );
+ ctxv.step = this.evalExpression(step);
}
ctxv.jumpTo =
- { line: this.runPointer,
- cmdPointer: cmdPointer+1 }
- if( ctxv.jumpTo.cmdPointer >= cmdArrayLen ) {
+ {
+ line: this.runPointer,
+ cmdPointer: cmdPointer + 1
+ }
+ if (ctxv.jumpTo.cmdPointer >= cmdArrayLen) {
- if( this.runPointer == -1) {
+ if (this.runPointer == -1) {
throw "@Cannot find command after for";
}
else {
- if( ( this.runPointer + 1) >= linePointersLen ) {
+ if ((this.runPointer + 1) >= linePointersLen) {
throw "@cannot find command after for, on next line";
}
ctxv.jumpTo.line++;
@@ -2700,30 +2698,30 @@ class BasicContext {
}
- doForNext( nextVarName ) {
+ doForNext(nextVarName) {
var ctx = this.forContext;
- if( ctx.default.length == 0 ) {
+ if (ctx.default.length == 0) {
throw "@next without for";
}
- var varName = ctx.default[ctx.default.length-1];
- if( nextVarName != null ) {
+ var varName = ctx.default[ctx.default.length - 1];
+ if (nextVarName != null) {
varName = nextVarName;
}
var ctxv = ctx[varName];
- this.vars[ varName ] += ctxv.step;
- if( ctxv.step > 0) {
- if(this.vars[ varName ]<=ctxv.to) {
+ this.vars[varName] += ctxv.step;
+ if (ctxv.step > 0) {
+ if (this.vars[varName] <= ctxv.to) {
return ctxv.jumpTo;
}
}
- else if( ctxv.step == 0) {
+ else if (ctxv.step == 0) {
return ctxv.jumpTo;
}
else {
- if(this.vars[ varName ]>=ctxv.to) {
+ if (this.vars[varName] >= ctxv.to) {
return ctxv.jumpTo;
}
}
@@ -2735,14 +2733,14 @@ class BasicContext {
onLineStr() {
var line = this.retreiveLine();
- if( line == -1 || line == "") { return ""; }
+ if (line == -1 || line == "") { return ""; }
return " in " + line;
}
retreiveRuntimeLine() {
- if( this.runPointer > -1 ) {
+ if (this.runPointer > -1) {
var line = this.program[this.runPointer];
return line[0];
}
@@ -2751,34 +2749,34 @@ class BasicContext {
retreiveLine() {
- if( this.runFlag ) {
+ if (this.runFlag) {
return this.retreiveRuntimeLine();
}
else {
- if( this["parseLineNumber"] === undefined ) {
+ if (this["parseLineNumber"] === undefined) {
return -1;
}
- if( this.parseLineNumber == -1) { return ""; }
+ if (this.parseLineNumber == -1) { return ""; }
return this.parseLineNumber;
}
return -1;
}
- commandToString( cmd ) {
- if( cmd.type == "control" ) {
+ commandToString(cmd) {
+ if (cmd.type == "control") {
return cmd.controlKW.toUpperCase();
}
- else if( cmd.type == "call" ) {
+ else if (cmd.type == "call") {
return cmd.statementName;
}
- else if( cmd.type == "assignment" ) {
+ else if (cmd.type == "assignment") {
return "assign ->" + cmd.var;
}
return "????";
}
- runCommands( cmds, limit ) {
+ runCommands(cmds, limit) {
/* return values
false -> error or end program
true -> executed ok
@@ -2803,10 +2801,10 @@ class BasicContext {
var PAUSE_F_INPUT = 40;
var end = cmds.length;
- var i=this.runPointer2;
- var cnt=0;
+ var i = this.runPointer2;
+ var cnt = 0;
- if(!(limit == undefined )) {
+ if (!(limit == undefined)) {
//nothing
}
else {
@@ -2815,107 +2813,107 @@ class BasicContext {
- while( i -1 ) {
// console.log( l[0] + "(" + this.runPointer + ":" + i +")" + this.commandToString( cmd ) );
//}
- if( cmd.type == "control" ) {
+ if (cmd.type == "control") {
var cn = cmd.controlKW;
- if( cn == "goto" ) {
- this.goto( cmd.params[0] );
- return [TERMINATE_W_JUMP,i+1,cnt+1];
+ if (cn == "goto") {
+ this.goto(cmd.params[0]);
+ return [TERMINATE_W_JUMP, i + 1, cnt + 1];
}
- else if( cn == "run" ) {
+ else if (cn == "run") {
this.runPGM();
- return [TERMINATE_W_JUMP,i+1,cnt+1];
+ return [TERMINATE_W_JUMP, i + 1, cnt + 1];
}
- else if( cn == "end" ) {
- return [TERMINATE_PROGRAM,i+1,cnt+1];
+ else if (cn == "end") {
+ return [TERMINATE_PROGRAM, i + 1, cnt + 1];
}
- else if( cn == "stop" ) {
+ else if (cn == "stop") {
this.printInfo("break");
- return [TERMINATE_PROGRAM,i+1,cnt+1];
- }
- else if( cn == "gosub" ) {
- this.gosub( cmd.params[0], i );
- return [TERMINATE_W_JUMP,i+1,cnt+1];
- }
- else if( cn == "on" ) {
- var onCommand = cmd.params[ 0 ];
- var onExpr = cmd.params[ 1 ];
- var onLineNrs = cmd.params[ 2 ];
-
- var value = this.evalExpression( onExpr );
- if( (value-1)>=0 && (value-1)= 0 && (value - 1) < onLineNrs.length) {
+ if (onCommand == "goto") {
+ this.goto(onLineNrs[(value - 1)]);
+ return [TERMINATE_W_JUMP, i + 1, cnt + 1];
}
- else if( onCommand == "gosub" ) {
- this.gosub( onLineNrs[ (value-1) ], i );
- return [TERMINATE_W_JUMP,i+1,cnt+1];
+ else if (onCommand == "gosub") {
+ this.gosub(onLineNrs[(value - 1)], i);
+ return [TERMINATE_W_JUMP, i + 1, cnt + 1];
}
}
//if not jumping, do nothing
}
- else if( cn == "return" ) {
+ else if (cn == "return") {
this.doReturn();
- return [TERMINATE_W_JUMP,i+1,cnt+1];
+ return [TERMINATE_W_JUMP, i + 1, cnt + 1];
}
- else if( cn == "if" ) {
+ else if (cn == "if") {
var IF_ERROR = -1;
var IF_TRUE = 1;
var IF_FALSE = 0;
- var ifresult = this.evalExpression( cmd.params[0] );
- if( ifresult != IF_FALSE ) {
- //return [MIDLINE_INTERUPT,i+1];
+ var ifresult = this.evalExpression(cmd.params[0]);
+ if (ifresult != IF_FALSE) {
+ //return [MIDLINE_INTERUPT,i+1];
}
- else {
- return [LINE_FINISHED,i+1,cnt+1];
+ else {
+ return [LINE_FINISHED, i + 1, cnt + 1];
}
}
- else if( cn == "data" ) {
+ else if (cn == "data") {
//Nothing
}
- else if( cn == "rem" ) {
- return [LINE_FINISHED,i+1,cnt+1];
+ else if (cn == "rem") {
+ return [LINE_FINISHED, i + 1, cnt + 1];
}
- else if( cn == "for:init" ) {
- this.doForInit( cmd.params[0], cmd.params[1], cmd.params[2], cmd.variable, i, cmds.length );
+ else if (cn == "for:init") {
+ this.doForInit(cmd.params[0], cmd.params[1], cmd.params[2], cmd.variable, i, cmds.length);
}
- else if( cn == "for:next" ) {
+ else if (cn == "for:next") {
- var jump = this.doForNext( cmd.nextVar );
+ var jump = this.doForNext(cmd.nextVar);
- if( !(jump === -1 ) ) {
+ if (!(jump === -1)) {
- if( jump.line != -1 ) {
- if( this.runPointer == jump.line ) {
- i = jump.cmdPointer;
- cnt++;
- continue;
- }
- else {
- this.runPointer = jump.line;
- this.runPointer2 = jump.cmdPointer;
- }
- return [TERMINATE_W_JUMP,i+1,cnt+1];
+ if (jump.line != -1) {
+ if (this.runPointer == jump.line) {
+ i = jump.cmdPointer;
+ cnt++;
+ continue;
+ }
+ else {
+ this.runPointer = jump.line;
+ this.runPointer2 = jump.cmdPointer;
+ }
+ return [TERMINATE_W_JUMP, i + 1, cnt + 1];
}
else {
i = jump.cmdPointer;
@@ -2924,184 +2922,184 @@ class BasicContext {
}
}
}
- else if( cn == "dim" ) {
+ else if (cn == "dim") {
var vars = this.vars;
- for( var ix=0; ix -1) {
+ if (varName.indexOf("$") > -1) {
varType = "str";
}
- values.push( { type: "var", value: varName, varType: varType } );
+ values.push({ type: "var", value: varName, varType: varType });
}
else { /*RAW*/
//values.push( cmd.params[j].parts );
- values.push( cmd.params[j] );
+ values.push(cmd.params[j]);
}
}
try {
//var stc = ;
- if( stc === undefined ) {
+ if (stc === undefined) {
this.printError("syntax");
- return [END_W_ERROR,i+1,cnt+1];
+ return [END_W_ERROR, i + 1, cnt + 1];
}
else {
- mycommands[ "_stat_" + cmd.statementName.toLowerCase()]( values );
- if( this.inputFlag ) {
- return [PAUSE_F_INPUT,i+1,cnt+1];
- }
+ mycommands["_stat_" + cmd.statementName.toLowerCase()](values);
+ if (this.inputFlag) {
+ return [PAUSE_F_INPUT, i + 1, cnt + 1];
+ }
}
}
- catch ( e ) {
+ catch (e) {
console.log(e);
- if( this.erh.isSerializedError( e ) ) {
- var err = this.erh.fromSerializedError( e );
- this.printError( err.clazz );
+ if (this.erh.isSerializedError(e)) {
+ var err = this.erh.fromSerializedError(e);
+ this.printError(err.clazz);
}
- else if( this.erh.isError( e ) ) {
+ else if (this.erh.isError(e)) {
var err = e;
- this.printError( err.clazz );
+ this.printError(err.clazz);
}
else {
- this.printError("unexpected " + e );
+ this.printError("unexpected " + e);
}
- return [END_W_ERROR,i+1,cnt, e ];
+ return [END_W_ERROR, i + 1, cnt, e];
}
}
- else if( cmd.type == "assignment" ) {
- if( cmd.arrayAssignment ) {
+ else if (cmd.type == "assignment") {
+ if (cmd.arrayAssignment) {
var varIntName = "@array_" + cmd.var;
- if( this.vars[ varIntName ] === undefined ) {
+ if (this.vars[varIntName] === undefined) {
this.printError("bad subscript");
- return [END_W_ERROR,i+1,cnt];
+ return [END_W_ERROR, i + 1, cnt];
}
- var arr = this.vars[ varIntName ];
- if( cmd.indices.length != arr.getIndexCount() ) {
+ var arr = this.vars[varIntName];
+ if (cmd.indices.length != arr.getIndexCount()) {
this.printError("bad subscript");
- return [END_W_ERROR,i+1,cnt];
+ return [END_W_ERROR, i + 1, cnt];
}
var indices = [];
- for( var ai=0;ai 80 ) { TODO move this check into the parser
- // throw "Line to long " + line;
- //}
- var l = p.parseLine( line );
- if( l == null ) {
- continue;
- }
- if( l.lineNumber != -1 ) {
- if( l.commands.length > 0) {
- this.insertPgmLineLocal( l.lineNumber, l.commands, l.raw, myProgram);
- //this.program[ l.lineNumber ] = [l.commands,l.raw];
+ var lineText = "???";
+ var errorsFound = "";
+ try {
+
+ for (var i = 0; i < lines.length; i++) {
+
+ if( myProgram.length == 1 ) {
+ var l0 = myProgram[0];
+ if( l0[0] == 0 ) {
+ if( l0[1].length == 1 ) {
+ var c0 = l0[1][0];
+ if( c0.lineNumber == 0 && c0.statementName.toUpperCase() == "XON" ){
+ this.extendedcommands.enable( true );
+ }
+ }
+ }
}
- else {
- throw "Error, no commands on line " + l.lineNumber;
+ try {
+ var line = this.prepareLineForImport(lines[i]);
+ lineText = line;
+ var p = new Parser(this.commands, this.extendedcommands);
+ p.init();
+
+ var l = p.parseLine(line);
+ if (l == null) {
+ continue;
+ }
+ if (l.lineNumber != -1) {
+ if (l.commands.length > 0) {
+ this.insertPgmLineLocal(l.lineNumber, l.commands, l.raw, myProgram);
+
+ }
+ else {
+ throw "Error, no commands on line " + l.lineNumber;
+ }
+ }
+ else {
+ throw "Error, command must start with number to be part of program";
+ }
+
+ if (this.debugFlag) {
+ console.log("program:", myProgram);
+ console.log("Line: ", l);
+ }
+ }
+ catch (e) {
+ //insert as rem statement
+ //parse line number (keep reading numeric chars untill any other char encountered)
+ var lineNr = 0;
+ var lineNrStr = "";
+
+ for (var j = 0; j < lineText.length; j++) {
+ if (lineText[j] >= '0' && lineText[j] <= '9') {
+ lineNrStr += lineText[j];
+ }
+ else {
+ break;
+ }
+ }
+
+ if (lineNrStr.length > 0) {
+ lineNr = parseInt(lineNrStr);
+ if( errorsFound.length > 0 ) {
+ errorsFound += ", ";
+ }
+ errorsFound += lineNr;
+ }
+
+ try {
+ var l = p.parseLine( lineNr + " REM ERR " + lineText.substring(lineNrStr.length) );
+ this.insertPgmLineLocal(l.lineNumber, l.commands, l.raw, myProgram);
+ }
+ catch (e) {
+ if (this.erh.isError(e)) {
+ e.lineText = lineText;
+ }
+ throw (e);
+ }
}
}
+
+ if( errorsFound.length > 0 ) {
+ this.errorsInParsing = ("Errors in lines: " + errorsFound).toUpperCase();
+ }
else {
- throw "Error, command must start with number to be part of program";
+ this.errorsInParsing = false;
}
-
- if( this.debugFlag ) {
- console.log("program:",myProgram);
- console.log("Line: ", l );
+ return myProgram;
+ }
+ catch (e) {
+ if (this.erh.isError(e)) {
+ e.lineText = lineText;
}
+ throw (e);
}
- return myProgram;
}
printReady() {
@@ -3489,98 +3552,98 @@ class BasicContext {
}
- startConsoleDataInput( vars ) {
+ startConsoleDataInput(vars) {
- if( this.debugFlag ) {
- console.log("inputvars=",vars);
+ if (this.debugFlag) {
+ console.log("inputvars=", vars);
}
this.inputFlag = true;
this.inputVars = vars;
this.inputVarsPointer = 0;
- this.sendChars( "? " , false);
+ this.sendChars("? ", false);
}
- handleLineInput( str, isInputCommand ) {
+ handleLineInput(str, isInputCommand) {
- if( this.debugFlag ) {
+ if (this.debugFlag) {
console.log("handleLineInput: start debug / isInputCommand=" + isInputCommand + " -------------");
}
- if( isInputCommand ) {
+ if (isInputCommand) {
- var input=str;
- var qMark = input.indexOf("?");
- while( qMark > -1 ) {
- input = input.substr(qMark+2);
- qMark = input.indexOf("?");
- }
+ var input = str;
+ var qMark = input.indexOf("?");
+ while (qMark > -1) {
+ input = input.substr(qMark + 2);
+ qMark = input.indexOf("?");
+ }
- if( this.debugFlag ) {
- console.log("handleLineInput: start debug / input, name -------------");
- console.log( "InputVarsPointer:" , this.inputVarsPointer );
- console.log( "InputVars:" , this.inputVars );
+ if (this.debugFlag) {
+ console.log("handleLineInput: start debug / input, name -------------");
+ console.log("InputVarsPointer:", this.inputVarsPointer);
+ console.log("InputVars:", this.inputVars);
- console.log( "Input String:" ,input );
- console.log( "Input Vars[current]:" ,this.inputVars[ this.inputVarsPointer ] );
- }
+ console.log("Input String:", input);
+ console.log("Input Vars[current]:", this.inputVars[this.inputVarsPointer]);
+ }
- var vName = this.inputVars[ this.inputVarsPointer ];
- if( vName.indexOf("$") >-1 ) {
- this.setVar( this.inputVars[ this.inputVarsPointer ], input.trim() );
- }
- else {
- var num = parseFloat( input.trim() );
+ var vName = this.inputVars[this.inputVarsPointer];
+ if (vName.indexOf("$") > -1) {
+ this.setVar(this.inputVars[this.inputVarsPointer], input.trim());
+ }
+ else {
+ var num = parseFloat(input.trim());
- if( isNaN( num ) ) {
- this.printLine("?redo from start");
- this.sendChars( "? " , false);
- return;
- }
- this.setVar( this.inputVars[ this.inputVarsPointer ], num );
+ if (isNaN(num)) {
+ this.printLine("?redo from start");
+ this.sendChars("? ", false);
+ return;
}
+ this.setVar(this.inputVars[this.inputVarsPointer], num);
+ }
- this.inputVarsPointer++;
- if( this.inputVarsPointer >= this.inputVars.length ) {
+ this.inputVarsPointer++;
+ if (this.inputVarsPointer >= this.inputVars.length) {
- this.exitInputState();
- }
- else {
- this.sendChars( "?? " , false);
- }
+ this.exitInputState();
+ }
+ else {
+ this.sendChars("?? ", false);
+ }
- if( this.debugFlag ) {
- console.log("handleLineInput: end debug -------------");
- }
- return;
+ if (this.debugFlag) {
+ console.log("handleLineInput: end debug -------------");
+ }
+ return;
}
this.executeLineFlag = true;
- if( this.debugFlag ) {
- console.log( str );
+ if (this.debugFlag) {
+ console.log(str);
}
- var p = new Parser( this.commands, this.extendedcommands );
+ var p = new Parser(this.commands, this.extendedcommands);
p.init();
try {
- var l = p.parseLine( str );
+ var l = p.parseLine(str);
}
- catch( e ) {
+ catch (e) {
this.parseLineNumber = -1;
- if( this.erh.isError( e ) ) {
+ if (this.erh.isError(e)) {
this.parseLineNumber = e.lineNr;
- this.printError( e.clazz, true );
+ this.printError(e.clazz, true);
}
else {
- this.printError( "syntax", true );
+ this.printError("syntax", true);
}
this.printLine("ready.");
}
- if( l == null ) {
- if( this.debugFlag ) {
+ if (l == null) {
+ if (this.debugFlag) {
console.log("handleLineInput: end debug -------------");
}
@@ -3588,12 +3651,12 @@ class BasicContext {
return;
}
- if( l.lineNumber != -1 ) {
- if( l.commands.length > 0) {
- this.insertPgmLine( l.lineNumber, l.commands, l.raw);
+ if (l.lineNumber != -1) {
+ if (l.commands.length > 0) {
+ this.insertPgmLine(l.lineNumber, l.commands, l.raw);
}
else {
- this.removePgmLine( l.lineNumber );
+ this.removePgmLine(l.lineNumber);
}
}
else {
@@ -3601,30 +3664,30 @@ class BasicContext {
this.runPointer2 = 0;
try {
- this.runCommands( l.commands );
+ this.runCommands(l.commands);
}
- catch( e ) {
+ catch (e) {
this.parseLineNumber = -1;
- if( this.erh.isSerializedError( e ) ) {
- var err = this.erh.fromSerializedError( e );
+ if (this.erh.isSerializedError(e)) {
+ var err = this.erh.fromSerializedError(e);
this.parseLineNumber = err.lineNr;
- this.printError( err.clazz );
+ this.printError(err.clazz);
}
- else if( this.erh.isError( e ) ) {
+ else if (this.erh.isError(e)) {
var err = e;
- this.printError( err.clazz );
+ this.printError(err.clazz);
this.parseLineNumber = err.lineNr;
}
else {
- this.printError("unexpected " + e );
+ this.printError("unexpected " + e);
}
this.runFlag = false;
}
- if( ! this.runFlag && ! this.listFlag) {
+ if (!this.runFlag && !this.listFlag) {
this.printLine("ready.");
}
@@ -3632,9 +3695,9 @@ class BasicContext {
this.executeLineFlag = false;
- if( this.debugFlag ) {
- console.log("program:",this.program);
- console.log("Line: ", l );
+ if (this.debugFlag) {
+ console.log("program:", this.program);
+ console.log("Line: ", l);
console.log("handleLineInput: end debug -------------");
}
diff --git a/emulator/res/script/basicparser.js b/emulator/res/script/basicparser.js
index b66205f..d3f3718 100644
--- a/emulator/res/script/basicparser.js
+++ b/emulator/res/script/basicparser.js
@@ -419,7 +419,7 @@ class Parser {
var tokens = context.tokens;
if( tokens.length == 0) {
- return undefined;
+ return [ { type: "num", data: 0 }, undefined ];
}
var token, returnValue=undefined;
@@ -431,7 +431,7 @@ class Parser {
endLoop = this.isEndToken( token, endTokens );
if( endLoop ) {
- this.throwError( context, "empty simple expression");
+ return [{ type: "num", data: 0 }, token]; /* no value is same as "0", this is for DATA ,,, */
}
@@ -1298,9 +1298,8 @@ parseArrayAssignment( context, preTokens, commands, command, nameToken, token0
var expr1 = pair[0];
-
if( expr1 === undefined ) {
- throw "data expected data";
+ break;
}
dataArray.push( expr1 );
diff --git a/emulator/res/script/c64basicpgm.js b/emulator/res/script/c64basicpgm.js
new file mode 100644
index 0000000..73af624
--- /dev/null
+++ b/emulator/res/script/c64basicpgm.js
@@ -0,0 +1,200 @@
+//const fs = require('fs');
+//const path = require('path');
+
+class C64BasicProgram {
+ constructor() {
+
+ this.tokens = [];
+ var tokens = this.tokens;
+
+ tokens[0x80] = 'END';
+ tokens[0x81] = 'FOR';
+ tokens[0x82] = 'NEXT';
+ tokens[0x83] = 'DATA';
+ tokens[0x84] = 'INPUT#';
+ tokens[0x85] = 'INPUT';
+ tokens[0x86] = 'DIM';
+ tokens[0x87] = 'READ';
+ tokens[0x88] = 'LET';
+ tokens[0x89] = 'GOTO';
+ tokens[0x8A] = 'RUN';
+ tokens[0x8B] = 'IF';
+ tokens[0x8C] = 'RESTORE';
+ tokens[0x8D] = 'GOSUB';
+ tokens[0x8E] = 'RETURN';
+ tokens[0x8F] = 'REM';
+ tokens[0x90] = 'STOP';
+ tokens[0x91] = 'ON';
+ tokens[0x92] = 'WAIT';
+ tokens[0x93] = 'LOAD';
+ tokens[0x94] = 'SAVE';
+ tokens[0x95] = 'VERIFY';
+ tokens[0x96] = 'DEF';
+ tokens[0x97] = 'POKE';
+ tokens[0x98] = 'PRINT#';
+ tokens[0x99] = 'PRINT';
+ tokens[0x9A] = 'CONT';
+ tokens[0x9B] = 'LIST';
+ tokens[0x9C] = 'CLR';
+ tokens[0x9D] = 'CMD';
+ tokens[0x9E] = 'SYS';
+ tokens[0x9F] = 'OPEN';
+ tokens[0xA0] = 'CLOSE';
+ tokens[0xA1] = 'GET';
+ tokens[0xA2] = 'NEW';
+ tokens[0xA3] = 'TAB(';
+ tokens[0xA4] = 'TO';
+ tokens[0xA5] = 'FN';
+ tokens[0xA6] = 'SPC(';
+ tokens[0xA7] = 'THEN';
+ tokens[0xA8] = 'NOT';
+ tokens[0xA9] = 'STEP';
+ tokens[0xAA] = '+';
+ tokens[0xAB] = '-';
+ tokens[0xAC] = '*';
+ tokens[0xAD] = '/';
+ tokens[0xAE] = '^';
+ tokens[0xAF] = 'AND';
+ tokens[0xB0] = 'OR';
+ tokens[0xB1] = '>';
+ tokens[0xB2] = '=';
+ tokens[0xB3] = '<';
+ tokens[0xB4] = 'SGN';
+ tokens[0xB5] = 'INT';
+ tokens[0xB6] = 'ABS';
+ tokens[0xB7] = 'USR';
+ tokens[0xB8] = 'FRE';
+ tokens[0xB9] = 'POS';
+ tokens[0xBA] = 'SQR';
+ tokens[0xBB] = 'RND';
+ tokens[0xBC] = 'LOG';
+ tokens[0xBD] = 'EXP';
+ tokens[0xBE] = 'COS';
+ tokens[0xBF] = 'SIN';
+ tokens[0xC0] = 'TAN';
+ tokens[0xC1] = 'ATN';
+ tokens[0xC2] = 'PEEK';
+ tokens[0xC3] = 'LEN';
+ tokens[0xC4] = 'STR$';
+ tokens[0xC5] = 'VAL';
+ tokens[0xC6] = 'ASC';
+ tokens[0xC7] = 'CHR$';
+ tokens[0xC8] = 'LEFT$';
+ tokens[0xC9] = 'RIGHT$';
+ tokens[0xCA] = 'MID$';
+ tokens[0xCB] = 'GO';
+
+ }
+
+
+ // Parse BASIC lines
+ parseBasicProgram(data) {
+ let offset = 2; // Start after the load address
+ let lines = [];
+ this.lines = lines;
+
+ if (!(data[0] === 0x01 && data[1] === 0x08)) {
+ throw ('This is not a BASIC program');
+ }
+
+ while (offset < data.length) {
+
+ const nextLineAddr = data[offset] + (data[offset + 1] << 8);
+ const lineNumber = data[offset+2] + (data[offset + 3] << 8);
+
+ if( nextLineAddr == 0) break;
+
+ offset += 4; // Move past the pointer and line number
+
+ let symbols = [];
+ while (data[offset] !== 0x00 && offset < data.length) { // 0x00 marks the end of a line
+ symbols.push(data[offset]);
+ offset++;
+ }
+
+ lines.push({ nextLineAddr, lineNumber, symbols });
+ offset++; // Move past the 0x00 byte
+ }
+ }
+
+ convertLines(lines, escapePetscii = false) {
+ var tokens = this.tokens;
+
+ var printedLines = lines.map(line => {
+ const lineNumberStr = line.lineNumber.toString();
+ const next = line.nextLineAddr.toString();
+ let inString = false; // Flag to track if we are inside a string
+ const symbolsStr = line.symbols.map(symbol => {
+ // Check if we're entering or exiting a string
+ if (symbol === 0x22) { // 0x22 is the ASCII code for "
+ inString = !inString;
+ return '"';
+ }
+
+ // If we're inside a string, or the symbol is unknown, convert to ASCII character
+ if (inString || !tokens[symbol]) {
+ if (inString && (symbol < 32 || symbol > 127)) {
+ if( escapePetscii ) {
+ return `\\x${symbol.toString(16).padStart(2, '0')}`;
+ }
+ return String.fromCharCode(symbol);
+ //return String.fromCharCode(symbol);
+ }
+ return String.fromCharCode(symbol);
+ }
+
+ // If it's a known token and we're not in a string, convert to the token representation
+ return tokens[symbol];
+ }).join('');
+
+ return `${lineNumberStr} ${symbolsStr}`;
+ });
+
+
+ return printedLines;
+ }
+
+ // Print the program
+ getTextProgramLines( escapePetscii = false) {
+
+ var printedLines =
+ this.convertLines(this.lines, escapePetscii );
+
+ return printedLines;
+ }
+
+
+}
+
+
+
+
+// Add more tokens as needed...
+
+// Load and parse the PRG file
+function loadPrgFile(filePath, action) {
+ fs.readFile(filePath, (err, data) => {
+ if (err) {
+ console.error('Error reading the file:', err);
+ return;
+ }
+
+ action(data);
+ // Check if it's a BASIC program
+
+ });
+}
+
+/*
+var pgm = new C64BasicProgram();
+
+// Replace 'your-program.prg' with the path to your actual PRG file
+loadPrgFile(path.join(__dirname, 'bombardement.prg')
+ , (data) => {
+ pgm.parseBasicProgram(data);
+
+ pgm.printProgram(pgm.printedLines);
+ }
+);
+*/
+
diff --git a/emulator/res/script/extendedcommands.js b/emulator/res/script/extendedcommands.js
index 9c02997..0857ae4 100644
--- a/emulator/res/script/extendedcommands.js
+++ b/emulator/res/script/extendedcommands.js
@@ -19,6 +19,10 @@ class ExtendedCommands {
}
+ enable( flag ) {
+ this.enabled = flag;
+ }
+
_intGetColorRecord() {
return {
c0: this.g_col0,
diff --git a/emulator/res/script/g1/core/blockfont.js b/emulator/res/script/g1/core/blockfont.js
index 38fa2d8..faea36d 100644
--- a/emulator/res/script/g1/core/blockfont.js
+++ b/emulator/res/script/g1/core/blockfont.js
@@ -74,7 +74,6 @@ class BlockFont {
}
}
-
this.iconCanvas = null;
this.iconContext = null;
this.img = null;
diff --git a/emulator/res/script/menu.js b/emulator/res/script/menu.js
index 02a0853..391d8eb 100644
--- a/emulator/res/script/menu.js
+++ b/emulator/res/script/menu.js
@@ -1,32 +1,91 @@
class Uploader {
- setCallback ( callbackC, callbackM ) {
+ constructor(element) {
+ this.debugFlag = false;
+ this.element = element;
+ this.callbackC = null;
+ this.callbackM = null;
+ this.isBinary = false;
+ }
+
+ setCallback(callbackC, callbackM, binary) {
this.callbackC = callbackC;
this.callbackM = callbackM;
this.debugFlag = false;
+ this.isBinary = binary;
+ }
+
+ start( filetypes, isBinary = false) {
+ this.element.accept = filetypes;
+ this.isBinary = isBinary;
+ this.element.click();
+
}
handleEvent(evt) {
- if( this.debugFlag ) {
+ if (this.debugFlag) {
console.log("handleEvent " + evt.type);
}
- switch(evt.type) {
- case "change":
- if( this.debugFlag ) {
- console.log("--------------handle upload event");
- console.log(evt);
+ switch (evt.type) {
+ case "change":
+ if (this.debugFlag) {
+ console.log("--------------handle upload event");
+ console.log(evt);
+ }
+ if( !this.isBinary ) {
+ this.handleUpload(evt);
+ }
+ else {
+ this.handleBinaryUpload(evt);
+ }
+
+
+ break;
+ }
+ }
+
+ handleBinaryUpload(e) {
+
+ if (this.debugFlag) {
+ console.log("handleBinaryUpload " + e);
+ }
+
+ var reader = new FileReader();
+
+ var thisFileName = e.target.files[0].name;
+ var _this = this;
+
+ reader.onload = function (event) {
+
+ if (this.debugFlag) {
+ console.log("reader onload " + thisFileName);
+ }
+
+ var blob = event.target.result;
+
+ if (this.debugFlag) {
+ console.log(blob);
}
- this.handleUpload( evt );
- break;
+ _this.callbackC[_this.callbackM](blob, thisFileName, null);
+
}
+
+ if (this.debugFlag) {
+ console.log("read " + e.target.files[0]);
+ console.log(e.target.files[0]);
+ }
+
+ reader.readAsArrayBuffer(e.target.files[0]);
+
}
- handleUpload(e){
- if( this.debugFlag ) {
- console.log("handleUpload " + e);
+ handleUpload(e) {
+
+ if (this.debugFlag) {
+ console.log("handleUpload " + e);
}
var reader = new FileReader();
@@ -34,22 +93,22 @@ class Uploader {
var thisFileName = e.target.files[0].name;
var _this = this;
- reader.onload = function(event){
+ reader.onload = function (event) {
- if( this.debugFlag ) {
- console.log("reader onload " + thisFileName);
- }
+ if (this.debugFlag) {
+ console.log("reader onload " + thisFileName);
+ }
- var text = event.target.result ;
- if( this.debugFlag ) {
- console.log( text );
- }
+ var text = event.target.result;
+ if (this.debugFlag) {
+ console.log(text);
+ }
- _this.callbackC[ _this.callbackM ]( text, thisFileName );
+ _this.callbackC[_this.callbackM](text, thisFileName);
}
- if( this.debugFlag ) {
+ if (this.debugFlag) {
console.log("read " + e.target.files[0]);
console.log(e.target.files[0]);
}
@@ -62,197 +121,194 @@ class Uploader {
class Menu {
- constructor( screen, context ) {
+ constructor(screen, context) {
this.debugFlag = false;
- this.console = screen;
- this.context = context;
- this.erh = new ErrorHandler();
+ this.console = screen;
+ this.context = context;
+ this.erh = new ErrorHandler();
+
+ var uploadElement = document.getElementById("imageLoader");
- this.uploader = new Uploader( );
+ this.uploader = new Uploader( uploadElement );
- var uploadElement = document.getElementById( "imageLoader" );
- this.runImportedPGMFlag = false;
- this.uploader.setCallback( this, "notset" );
+ this.runImportedPGMFlag = false;
+ this.uploader.setCallback(this, "notset");
uploadElement.addEventListener('change', this.uploader, true);
- this.menuvmState = "main";
+ this.menuvmState = "main";
this.listSelector = false;
- this.optSelect = 0;
-
- this.options = {};
- this.menus = {};
- this.menuOffset = {};
-
- this.stateMemory = new Uint8Array( 256 * 256 );
-
- var opts = [];
- //opts.push({opt: "status", display: "Status" });
- //opts.push({opt: "loadsave", display: "Load/Save" });
-
- opts.push({opt: "basicMenu", display: "Basic" });
- opts.push({opt: "diskMenu", display: "Virtual Disk" });
- opts.push({opt: "exportMenu", display: "Import" });
- opts.push({opt: "clipboardMenu", display: "Clipboard" });
- opts.push({opt: "docsSettingsMenu", display: "Settings and docs" });
- opts.push({opt: "toolsMenu", display: "Tools" });
- opts.push({opt: "reset", display: "Reset" });
-
- this.options["main"] = opts;
- this.menus["main"] = "main";
- this.menuOffset["main"] = 10;
-
- opts = [];
- opts.push({opt: "copyPGMtoClip", display: "Copy program" });
- opts.push({opt: "pastePGMFromClip", display: "Paste Program" });
- opts.push({opt: "pastePGMFromClipAppend", display: "Paste and Merge" });
- this.options["clipboard"] = opts;
- this.menus["clipboard"] = "clipboard";
- this.menuOffset["clipboard"] = 10;
+ this.optSelect = 0;
+
+ this.options = {};
+ this.menus = {};
+ this.menuOffset = {};
+
+ this.stateMemory = new Uint8Array(256 * 256);
+
+ var opts = [];
+ //opts.push({opt: "status", display: "Status" });
+ //opts.push({opt: "loadsave", display: "Load/Save" });
+
+ opts.push({ opt: "basicMenu", display: "Basic" });
+ opts.push({ opt: "diskMenu", display: "Virtual Disk" });
+ opts.push({ opt: "exportMenu", display: "Import" });
+ opts.push({ opt: "clipboardMenu", display: "Clipboard" });
+ opts.push({ opt: "docsSettingsMenu", display: "Settings and docs" });
+ opts.push({ opt: "toolsMenu", display: "Tools" });
+ opts.push({ opt: "reset", display: "Reset" });
+
+ this.options["main"] = opts;
+ this.menus["main"] = "main";
+ this.menuOffset["main"] = 10;
+
+ opts = [];
+ opts.push({ opt: "copyPGMtoClip", display: "Copy program" });
+ opts.push({ opt: "pastePGMFromClip", display: "Paste Program" });
+ opts.push({ opt: "pastePGMFromClipAppend", display: "Paste and Merge" });
+ this.options["clipboard"] = opts;
+ this.menus["clipboard"] = "clipboard";
+ this.menuOffset["clipboard"] = 10;
+
+ opts = [];
+ opts.push({ opt: "generatePGMUrl", display: "Generate Program URL" });
+ opts.push({ opt: "copyPGMURLtoClip", display: "Generate Inline Program URL" });
+ this.options["tools"] = opts;
+ this.menus["tools"] = "tools";
+ this.menuOffset["tools"] = 3;
+
+ opts = [];
+ opts.push({ opt: "list", display: "List" });
+ opts.push({ opt: "renumber", display: "Renumber Basic Program" });
+ opts.push({ opt: "compress", display: "Remove Spaces" });
+ opts.push({ opt: "compress2", display: "Compress" });
+ opts.push({ opt: "PETSCIIreplace", display: "Strip PETSCII Chars" });
+ opts.push({ opt: "normalize", display: "Normalize Spaces" });
+ this.options["basic"] = opts;
+ this.menus["basic"] = "basic";
+ this.menuOffset["basic"] = 4;
opts = [];
- opts.push({opt: "generatePGMUrl", display: "Generate Program URL" });
- opts.push({opt: "copyPGMURLtoClip", display: "Generate Inline Program URL" });
- this.options["tools"] = opts;
- this.menus["tools"] = "tools";
- this.menuOffset["tools"] = 3;
-
- opts = [];
- opts.push({opt: "list", display: "List" });
- opts.push({opt: "renumber", display: "Renumber Basic Program" });
- opts.push({opt: "compress", display: "Remove Spaces" });
- opts.push({opt: "compress2", display: "Compress" });
- opts.push({opt: "PETSCIIreplace", display: "Strip PETSCII Chars" });
- opts.push({opt: "normalize", display: "Normalize Spaces" });
- this.options["basic"] = opts;
- this.menus["basic"] = "basic";
- this.menuOffset["basic"] = 4;
-
- opts = [];
- opts.push({opt: "importBas", display: "Import Basic Program" });
- opts.push({opt: "importBasRun", display: "Import/Run Basic Program" });
- opts.push({opt: "exportBas", display: "Export Basic Program" });
- opts.push({opt: "exportBasNoPETSCII", display: "Export Basic Program:nopet" });
- opts.push({opt: "importSnapshot", display: "Import Snapshot" });
- opts.push({opt: "exportSnapshot", display: "Export Snapshot" });
- opts.push({opt: "importVDisk", display: "Import Virtual Disk" });
- opts.push({opt: "exportVDisk", display: "Export Virtual Disk" });
-
- this.options["export"] = opts;
- this.menus["export"] = "export";
- this.menuOffset["export"] = 5;
-
-
- opts = [];
- opts.push({opt: "changeExitMode", display: "exit mode" });
- opts.push({opt: "changeImmersiveMode", display: "immersive mode" });
- opts.push({opt: "changeClock", display: "clock mode" });
- opts.push({opt: "changeTurbo", display: "turbo mode" });
- opts.push({opt: "changeRenum", display: "renumber mode" });
- opts.push({opt: "changeExtended", display: "Extended commands" });
- opts.push({opt: "changeDisplay", display: "Display" });
- opts.push({opt: "changeTheme", display: "Change Menu Theme" });
- opts.push({opt: "documentation", display: "documentation" });
- this.options["docssettings"] = opts;
- this.menus["docssettings"] = "docs & settings";
- this.menuOffset["docssettings"] = 9;
-
- opts = [];
- opts.push({opt: "listDirectory", display: "Load File" });
- opts.push({opt: "formatDisk", display: "Format Disk", confirm: true });
- opts.push({opt: "listDisks", display: "Swap Disks" });
- opts.push({opt: "createDisk", display: "Create new Disk", confirm: true });
-
-// opts.push({opt: "listDirectory", display: "Save" });
- opts.push({opt: "saveSnapshot", display: "Save Snapshot" });
-// opts.push({opt: "listDirectory", display: "Format" });
-// opts.push({opt: "listDirectory", display: "Disk Swap" });
-// opts.push({opt: "listDirectory", display: "Rename Disk" });
-
- this.options["disk"] = opts;
- this.menus["disk"] = "disk";
- this.menuOffset["disk"] = 12;
-
- this.themes = [];
+ opts.push({ opt: "importBas", display: "Import Basic Program" });
+ opts.push({ opt: "importBasRun", display: "Import/Run Basic Program" });
+ opts.push({ opt: "exportBas", display: "Export Basic Program" });
+ opts.push({ opt: "exportBasNoPETSCII", display: "Export Basic Program:nopet" });
+ opts.push({ opt: "importPRGBas", display: "Import Basic PRG File" });
+ opts.push({ opt: "importSnapshot", display: "Import Snapshot" });
+ opts.push({ opt: "exportSnapshot", display: "Export Snapshot" });
+ opts.push({ opt: "importVDisk", display: "Import Virtual Disk" });
+ opts.push({ opt: "exportVDisk", display: "Export Virtual Disk" });
+
+ this.options["export"] = opts;
+ this.menus["export"] = "export";
+ this.menuOffset["export"] = 5;
+
+
+ opts = [];
+ opts.push({ opt: "changeExitMode", display: "exit mode" });
+ opts.push({ opt: "changeImmersiveMode", display: "immersive mode" });
+ opts.push({ opt: "changeClock", display: "clock mode" });
+ opts.push({ opt: "changeTurbo", display: "turbo mode" });
+ opts.push({ opt: "changeRenum", display: "renumber mode" });
+ opts.push({ opt: "changeExtended", display: "Extended commands" });
+ opts.push({ opt: "changeDisplay", display: "Display" });
+ opts.push({ opt: "changeTheme", display: "Change Menu Theme" });
+ opts.push({ opt: "documentation", display: "documentation" });
+ this.options["docssettings"] = opts;
+ this.menus["docssettings"] = "docs & settings";
+ this.menuOffset["docssettings"] = 9;
+
+ opts = [];
+ opts.push({ opt: "listDirectory", display: "Load File" });
+ opts.push({ opt: "formatDisk", display: "Format Disk", confirm: true });
+ opts.push({ opt: "listDisks", display: "Swap Disks" });
+ opts.push({ opt: "createDisk", display: "Create new Disk", confirm: true });
+ opts.push({ opt: "saveSnapshot", display: "Save Snapshot" });
+
+ this.options["disk"] = opts;
+ this.menus["disk"] = "disk";
+ this.menuOffset["disk"] = 12;
+
+ this.themes = [];
this.themes.push(
- {
- bg: 2,
- border: 2,
- fg: 0,
- hl: 7,
- logorows: [8,8,7,4],
- splotches: [[36,2,7],[36,3,7]]
- }
- );
+ {
+ bg: 2,
+ border: 2,
+ fg: 0,
+ hl: 7,
+ logorows: [8, 8, 7, 4],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
this.themes.push(
- {
- bg: 6,
- border: 6,
- fg: 14,
- hl: 1,
- logorows: [3,3,3,3],
- splotches: [[36,2,7],[36,3,7]]
- }
- );
-
- this.themes.push(
- {
- bg: 6,
- border: 6,
- fg: 14,
- hl: 1,
- logorows: [8,8,8,8],
- splotches: [[36,2,7],[36,3,7]]
- }
- );
-
- this.themes.push(
- {
- bg: 6,
- border: 6,
- fg: 14,
- hl: 1,
- logorows: [14,14,14,14],
- splotches: [[36,2,7],[36,3,7]]
- }
- );
-
- this.themes.push(
- {
- bg: 0,
- border: 0,
- fg: 8,
- hl: 7,
- logorows: [8,8,8,8],
- splotches: [[36,2,7],[36,3,7]]
- }
- );
-
- this.themes.push(
- {
- bg: 0,
- border: 0,
- fg: 14,
- hl: 1,
- logorows: [6,6,6,6],
- splotches: [[36,2,14],[36,3,14]]
- }
- );
-
- this.themes.push(
- {
- bg: 0,
- border: 0,
- fg: 5,
- hl: 13,
- logorows: [5,5,5,5],
- splotches: [[36,2,13],[36,3,13]]
- }
- );
+ {
+ bg: 6,
+ border: 6,
+ fg: 14,
+ hl: 1,
+ logorows: [3, 3, 3, 3],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
+
+ this.themes.push(
+ {
+ bg: 6,
+ border: 6,
+ fg: 14,
+ hl: 1,
+ logorows: [8, 8, 8, 8],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
+
+ this.themes.push(
+ {
+ bg: 6,
+ border: 6,
+ fg: 14,
+ hl: 1,
+ logorows: [14, 14, 14, 14],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
+
+ this.themes.push(
+ {
+ bg: 0,
+ border: 0,
+ fg: 8,
+ hl: 7,
+ logorows: [8, 8, 8, 8],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
+
+ this.themes.push(
+ {
+ bg: 0,
+ border: 0,
+ fg: 14,
+ hl: 1,
+ logorows: [6, 6, 6, 6],
+ splotches: [[36, 2, 14], [36, 3, 14]]
+ }
+ );
+
+ this.themes.push(
+ {
+ bg: 0,
+ border: 0,
+ fg: 5,
+ hl: 13,
+ logorows: [5, 5, 5, 5],
+ splotches: [[36, 2, 13], [36, 3, 13]]
+ }
+ );
this.themes.push(
{
@@ -260,176 +316,176 @@ class Menu {
border: 11,
fg: 12,
hl: 1,
- logorows: [0,0,0,0],
- splotches: [[36,2,7],[36,3,7]]
+ logorows: [0, 0, 0, 0],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
+
+ this.themes.push(
+ {
+ bg: 11,
+ border: 12,
+ fg: 12,
+ hl: 1,
+ logorows: [0, 0, 0, 0],
+ splotches: [[36, 2, 1], [36, 3, 1]]
}
);
- this.themes.push(
- {
- bg: 11,
- border: 12,
- fg: 12,
- hl: 1,
- logorows: [0,0,0,0],
- splotches: [[36,2,1],[36,3,1]]
- }
- );
+ this.themes.push(
+ {
+ bg: 14,
+ border: 6,
+ fg: 6,
+ hl: 0,
+ logorows: [0, 6, 3, 1],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
this.themes.push(
- {
- bg: 14,
- border: 6,
- fg: 6,
- hl: 0,
- logorows: [0,6,3,1],
- splotches: [[36,2,7],[36,3,7]]
- }
- );
+ {
+ bg: 0,
+ border: 5,
+ fg: 13,
+ hl: 1,
+ logorows: [1, 1, 7, 13],
+ splotches: [[36, 2, 8], [36, 3, 8]]
+ }
+ );
this.themes.push(
- {
- bg: 0,
- border: 5,
- fg: 13,
- hl: 1,
- logorows: [1,1,7,13],
- splotches: [[36,2,8],[36,3,8]]
- }
- );
-
- this.themes.push(
- {
- bg: 6,
- border: 14,
- fg: 14,
- hl: 1,
- logorows: [5,5,3,5],
- splotches: [[36,2,7],[36,3,7]]
- }
- );
- this.themes.push(
- {
- bg: 6,
- border: 14,
- fg: 14,
- hl: 1,
- logorows: [4,4,8,4],
- splotches: [[36,2,7],[36,3,7]]
- }
- );
- this.themes.push(
- {
- bg: 6,
- border: 14,
- fg: 14,
- hl: 1,
- logorows: [7,7,1,7],
- splotches: [[36,2,7],[36,3,7]]
- }
- );
- this.themes.push(
- {
- bg: 6,
- border: 14,
- fg: 14,
- hl: 1,
- logorows: [1,1,1,1],
- splotches: [[36,2,7],[36,3,7]]
- }
- );
-
- this.theme = 0;
-
- var menuSettings = localStorage.getItem( "BJ64_Menu" );
- if( menuSettings != null ) {
- menuSettings = JSON.parse( menuSettings );
- this.theme = menuSettings.theme;
- }
-
- //this.initLogo();
- }
-
- initLogo() {
-
- var context = this.context;
-
- var logo = getMenuLogo();
- this.logo = logo;
-
- context.poke( 53265, 27 );
- context.poke( 53272, 12 );
- context.poke( 1, 0 );
- for( var i=0; i<(64*8); i++) {
- context.poke(12288+i, context.peek(53248+i));
- }
- context.poke( 1, 255 );
-
- for( var i=0; i 0 ) {
- t.pad( offX, "..." );
- t.nl();
+ if (offset > 0) {
+ t.pad(offX, "...");
+ t.nl();
}
else {
- t.pad( offX, "" );
- t.nl();
+ t.pad(offX, "");
+ t.nl();
}
var first = true;
- for( var i=0; i= maxPrintCount ) {
- more = true;
- break;
- }
+ if (printCount >= maxPrintCount) {
+ more = true;
+ break;
+ }
- if( i == this.optSelect ) {
- t.console.setColor(hlColor);
- }
- else {
- t.console.setColor(txtColor);
- }
- if( this.showNumbers) {
- t.padSave( this.listOffset , " " +(i+1)+ " - " + this.listItems[i].name );
- }
- else {
- t.printCodeLine( this.listItems[i].name );
- }
+ if (i == this.optSelect) {
+ t.console.setColor(hlColor);
+ }
+ else {
+ t.console.setColor(txtColor);
+ }
+ if (this.showNumbers) {
+ t.padSave(this.listOffset, " " + (i + 1) + " - " + this.listItems[i].name);
+ }
+ else {
+ t.printCodeLine(this.listItems[i].name);
+ }
- if( skiplineInList ) {
- t.nl();
- }
+ if (skiplineInList) {
+ t.nl();
+ }
- this.curs.push( t.console.getCursorPos() );
+ this.curs.push(t.console.getCursorPos());
- printCount++;
+ printCount++;
}
- if( more ) {
- t.pad( offX, "..." );
+ if (more) {
+ t.pad(offX, "...");
}
}
- }
+ }
- color(x) {
- this.console.setColor(x);
- }
+ color(x) {
+ this.console.setColor(x);
+ }
- nl() {
- this.context.printLine("");
- }
+ nl() {
+ this.context.printLine("");
+ }
- pad( pad, txt ) {
+ pad(pad, txt) {
- var padStr = "";
- for(var i=0; i" + e.detail);
+ if( e.lineText ) {
+ this.context.sendCharsSimple( ">" + e.lineText, true);
+ }
+ this.context.printLine("ready.");
+ }
+
+ }
+
+
+ endMenuWithMessage(m, detailError) {
+ this.context.endMenu();
+ this.stop();
+ this.context.printLine("");
+ if (!(detailError === undefined)) {
this.message(m);
- this.context.printLine( "" );
- this.context.printLine( "?" + detailError.typeError );
- this.context.printLine( "!" + detailError.detailError );
+ this.context.printLine("");
+ this.context.printLine("?" + detailError.typeError);
+ this.context.printLine("!" + detailError.detailError);
}
- else {
+ else {
this.message(m);
}
- }
-
- endMenuWithError( m, extra ) {
- this.context.endMenu();
- this.stop();
- this.context.printLine( "" );
- this.errorMessage(m, extra);
+ }
- }
+ endMenuWithError(m, extra) {
+ this.context.endMenu();
+ this.stop();
+ this.context.printLine("");
+ this.errorMessage(m, extra);
+ this.context.printLine( "ready" );
+ }
- handleKey( evt ) {
+ handleKey(evt) {
- if( evt.key == "Enter") {
+ if (evt.key == "Enter") {
- if( this.selectList == true ) {
+ if (this.selectList == true) {
- var listIndex = this.optSelect;
+ var listIndex = this.optSelect;
- if( this.debugFlag ) {
- console.log("List selected " + listIndex );
- console.log("List selected item " + this.listItems[listIndex].id );
- }
+ if (this.debugFlag) {
+ console.log("List selected " + listIndex);
+ console.log("List selected item " + this.listItems[listIndex].id);
+ }
- if( this.listAtExit != "stay" ) {
+ if (this.listAtExit != "stay") {
- this.selectList = false;
- this.optSelect = this.oldOptSelect;
+ this.selectList = false;
+ this.optSelect = this.oldOptSelect;
- }
+ }
- this.rendervmStateText();
+ this.rendervmStateText();
- this[ this.listCallback ]( this.listItems[listIndex].id,
- {
- ixFrom: this.page_first,
- ixTo: this.page_last
- });
+ this[this.listCallback](this.listItems[listIndex].id,
+ {
+ ixFrom: this.page_first,
+ ixTo: this.page_last
+ });
- }
+ }
else {
- var options = this.options[ this.menuvmState ];
+ var options = this.options[this.menuvmState];
- if( this.debugFlag ) {
- console.log( this.optSelect );
+ if (this.debugFlag) {
+ console.log(this.optSelect);
}
- var opt = options[ this.optSelect ];
+ var opt = options[this.optSelect];
- if( ! opt.confirm ) {
- this[ "do_" + opt.opt ]();
+ if (!opt.confirm) {
+ this["do_" + opt.opt]();
}
- else {
- this.chooseYesOrNo( opt.display , "do_" + opt.opt);
+ else {
+ this.chooseYesOrNo(opt.display, "do_" + opt.opt);
}
}
- }
- if( evt.key == "Escape") {
+ }
+ if (evt.key == "Escape") {
- if( this.selectList == true ) {
- this.selectList = false;
+ if (this.selectList == true) {
+ this.selectList = false;
this.optSelect = this.oldOptSelect;
this.rendervmStateText();
- }
- else if( this.menuvmState == "main" ) {
- this.endMenu();
- }
- else {
- this.do_mainMenu();
- }
-
- }
- else if( evt.key == "Pause" && evt.ctrlKey) {
- }
- else if( evt.key == "ArrowUp") {
- //var options = this.options[ this.menuvmState ];
- if( (this.optSelect) >0 ) {
- this.optSelect--;
- this.rendervmStateText();
- evt.preventDefault();
- }
- }
- else if( evt.key == "ArrowDown") {
-
- if( this.selectList == true ) {
- if( (this.optSelect+1) < this.listItems.length ) {
- this.optSelect++;
- this.rendervmStateText();
- }
}
- else
- {
- var options = this.options[ this.menuvmState ];
- if( (this.optSelect+1) < options.length ) {
- this.optSelect++;
- this.rendervmStateText();
- }
+ else if (this.menuvmState == "main") {
+ this.endMenu();
+ }
+ else {
+ this.do_mainMenu();
+ }
+
+ }
+ else if (evt.key == "Pause" && evt.ctrlKey) {
+ }
+ else if (evt.key == "ArrowUp") {
+ //var options = this.options[ this.menuvmState ];
+ if ((this.optSelect) > 0) {
+ this.optSelect--;
+ this.rendervmStateText();
+ evt.preventDefault();
+ }
+ }
+ else if (evt.key == "ArrowDown") {
+
+ if (this.selectList == true) {
+ if ((this.optSelect + 1) < this.listItems.length) {
+ this.optSelect++;
+ this.rendervmStateText();
+ }
+ }
+ else {
+ var options = this.options[this.menuvmState];
+ if ((this.optSelect + 1) < options.length) {
+ this.optSelect++;
+ this.rendervmStateText();
+ }
}
evt.preventDefault();
- }
- else if( evt.key == "F1" || evt.key == "1") {
- this.executeOption( 0 );
- evt.preventDefault();
- }
- else if( evt.key == "F2" || evt.key == "2") {
- this.executeOption( 1 );
- evt.preventDefault();
- }
- else if( evt.key == "F3" || evt.key == "3") {
- this.executeOption( 2 );
- evt.preventDefault();
- }
- else if( evt.key == "F4" || evt.key == "4") {
- this.executeOption( 3 );
- evt.preventDefault();
- }
- else if( evt.key == "F5" || evt.key == "5") {
- this.executeOption( 4 );
- evt.preventDefault();
- }
- else if( evt.key == "F6" || evt.key == "6") {
- this.executeOption( 5 );
- evt.preventDefault();
- }
- else if( evt.key == "F7" || evt.key == "7") {
- this.executeOption( 6 );
- evt.preventDefault();
- }
- else if( evt.key == "F8" || evt.key == "8") {
- this.executeOption( 7 );
- evt.preventDefault();
- }
- }
-
- executeOption( no ) {
- var options = this.options[ this.menuvmState ];
-
- if( (no+1) <= options.length ) {
-
- this.optSelect = no;
-
- if( this.debugFlag ) {
- console.log( this.optSelect );
+ }
+ else if (evt.key == "F1" || evt.key == "1") {
+ this.executeOption(0);
+ evt.preventDefault();
+ }
+ else if (evt.key == "F2" || evt.key == "2") {
+ this.executeOption(1);
+ evt.preventDefault();
+ }
+ else if (evt.key == "F3" || evt.key == "3") {
+ this.executeOption(2);
+ evt.preventDefault();
+ }
+ else if (evt.key == "F4" || evt.key == "4") {
+ this.executeOption(3);
+ evt.preventDefault();
+ }
+ else if (evt.key == "F5" || evt.key == "5") {
+ this.executeOption(4);
+ evt.preventDefault();
+ }
+ else if (evt.key == "F6" || evt.key == "6") {
+ this.executeOption(5);
+ evt.preventDefault();
+ }
+ else if (evt.key == "F7" || evt.key == "7") {
+ this.executeOption(6);
+ evt.preventDefault();
+ }
+ else if (evt.key == "F8" || evt.key == "8") {
+ this.executeOption(7);
+ evt.preventDefault();
+ }
+ }
+
+ executeOption(no) {
+ var options = this.options[this.menuvmState];
+
+ if ((no + 1) <= options.length) {
+
+ this.optSelect = no;
+
+ if (this.debugFlag) {
+ console.log(this.optSelect);
}
- var opt = options[ this.optSelect ];
+ var opt = options[this.optSelect];
- if( this.debugFlag ) {
- console.log( opt );
+ if (this.debugFlag) {
+ console.log(opt);
}
- this[ "do_" + opt.opt ]();
+ this["do_" + opt.opt]();
- }
+ }
- }
+ }
- do_docsSettingsMenu() {
- this.menuvmState = "docssettings";
- this.optSelect = 0
- this.rendervmState();
- }
+ do_docsSettingsMenu() {
+ this.menuvmState = "docssettings";
+ this.optSelect = 0
+ this.rendervmState();
+ }
- do_exportMenu() {
- this.menuvmState = "export";
- this.optSelect = 0
- this.rendervmState();
- }
+ do_exportMenu() {
+ this.menuvmState = "export";
+ this.optSelect = 0
+ this.rendervmState();
+ }
- do_diskMenu() {
- this.menuvmState = "disk";
- this.optSelect = 0
- this.rendervmState();
- }
+ do_diskMenu() {
+ this.menuvmState = "disk";
+ this.optSelect = 0
+ this.rendervmState();
+ }
do_toolsMenu() {
- this.menuvmState = "tools";
- this.optSelect = 0
- this.rendervmState();
- }
-
- do_clipboardMenu() {
- this.menuvmState = "clipboard";
- this.optSelect = 0
- this.rendervmState();
- }
-
- do_mainMenu() {
- this.menuvmState = "main";
- this.optSelect = 0
- this.rendervmState();
- }
-
- do_basicMenu() {
- this.menuvmState = "basic";
- this.optSelect = 0
- this.rendervmState();
- }
+ this.menuvmState = "tools";
+ this.optSelect = 0
+ this.rendervmState();
+ }
+
+ do_clipboardMenu() {
+ this.menuvmState = "clipboard";
+ this.optSelect = 0
+ this.rendervmState();
+ }
+
+ do_mainMenu() {
+ this.menuvmState = "main";
+ this.optSelect = 0
+ this.rendervmState();
+ }
+
+ do_basicMenu() {
+ this.menuvmState = "basic";
+ this.optSelect = 0
+ this.rendervmState();
+ }
do_copyPGMURLtoClip() {
@@ -914,152 +986,152 @@ class Menu {
var text = this.context.getProgramAsText();
var url = window.location +
- "?pgm=" +
- encodeURIComponent(btoa( text ));
+ "?pgm=" +
+ encodeURIComponent(btoa(text));
- if( this.debugFlag ) {
- console.log( url );
- console.log( btoa( text ) );
+ if (this.debugFlag) {
+ console.log(url);
+ console.log(btoa(text));
- console.log( atob( btoa( text ) ) );
+ console.log(atob(btoa(text)));
}
- navigator.clipboard.writeText( url );
+ navigator.clipboard.writeText(url);
this.endMenuWithMessage("url to clip");
}
do_generatePGMUrl() {
- registerClipboardCallback( this, "do_generatePGMUrlCallBack" );
- enableConvertLinkWidget();
- this.runImportedPGMFlag = false;
- }
+ registerClipboardCallback(this, "do_generatePGMUrlCallBack");
+ enableConvertLinkWidget();
+ this.runImportedPGMFlag = false;
+ }
- do_generatePGMUrlCallBack( text ) {
+ do_generatePGMUrlCallBack(text) {
- var encodedLink = encodeURIComponent( text );
- setLinkCallbackText( document.URL + "?linkpgm=" + encodedLink );
- }
+ var encodedLink = encodeURIComponent(text);
+ setLinkCallbackText(document.URL + "?linkpgm=" + encodedLink);
+ }
- do_copyPGMtoClip() {
- navigator.clipboard.writeText( this.context.getProgramAsText() );
+ do_copyPGMtoClip() {
+ navigator.clipboard.writeText(this.context.getProgramAsText());
- this.endMenuWithMessage("copied to clip");
- }
+ this.endMenuWithMessage("copied to clip");
+ }
do_pastePGMFromClipAppend() {
- registerClipboardCallback( this, "do_pastePGMFromClipAppendCallback" );
- enableClipBoardWidget();
- this.runImportedPGMFlag = false;
- }
+ registerClipboardCallback(this, "do_pastePGMFromClipAppendCallback");
+ enableClipBoardWidget();
+ this.runImportedPGMFlag = false;
+ }
- do_pastePGMFromClip() {
+ do_pastePGMFromClip() {
- registerClipboardCallback( this, "do_pastePGMFromClipCallback" );
- enableClipBoardWidget();
- this.runImportedPGMFlag = false;
- }
+ registerClipboardCallback(this, "do_pastePGMFromClipCallback");
+ enableClipBoardWidget();
+ this.runImportedPGMFlag = false;
+ }
- do_pastePGMFromClipAppendCallback( text ) {
+ do_pastePGMFromClipAppendCallback(text) {
- if( this.debugFlag ) {
- console.log("callback3");
+ if (this.debugFlag) {
+ console.log("callback3");
}
- var lines = text.split(/\r?\n/);
+ var lines = text.split(/\r?\n/);
- try {
- var bas = this.context.textLinesToBas( lines );
- this.context.appendProgram( bas );
+ try {
+ var bas = this.context.textLinesToBas(lines);
+ this.context.appendProgram(bas);
- this.endMenuWithMessage("paste ok");
- this.context.printLine("list");
+ this.endMenuWithMessage("paste ok");
+ this.context.printLine("list");
- var pgm = this.context.getProgramLines();
- for (const l of pgm )
- {
- this.context.listCodeLine( l[2] );
+ var pgm = this.context.getProgramLines();
+ for (const l of pgm) {
+ this.context.listCodeLine(l[2]);
- if( this.debugFlag ) {
- console.log(l[2]);
- }
- }
+ if (this.debugFlag) {
+ console.log(l[2]);
+ }
+ }
- }
+ }
catch (e) {
this.endMenuWithMessage("parse error on import", detailError);
- var detailError = this.handleImportError( e );
- console.log( e );
+ var detailError = this.handleImportError(e);
+ console.log(e);
return;
}
- }
+ }
- do_pastePGMFromClipCallback( text ) {
+ do_pastePGMFromClipCallback(text) {
- if( this.debugFlag ) {
- console.log("callback2");
+ if (this.debugFlag) {
+ console.log("callback2");
}
- var lines = text.split(/\r?\n/);
+ var lines = text.split(/\r?\n/);
- try {
- var bas = this.context.textLinesToBas( lines );
- this.context.setProgram( bas );
+ try {
+ var bas = this.context.textLinesToBas(lines);
+ this.context.setProgram(bas);
- this.endMenuWithMessage("paste ok");
- this.context.printLine("list");
+ this.endMenuWithMessage("paste ok");
+ this.context.printLine("list");
- var pgm = this.context.getProgramLines();
- for (const l of pgm ) {
- this.context.listCodeLine( l[2] );
- if( this.debugFlag ) {
- console.log(l[2]);
- }
- }
- }
+ var pgm = this.context.getProgramLines();
+ for (const l of pgm) {
+ this.context.listCodeLine(l[2]);
+ if (this.debugFlag) {
+ console.log(l[2]);
+ }
+ }
+ }
catch (e) {
+ var detailError = this.handleImportError(e);
this.endMenuWithMessage("parse error on import", detailError);
- var detailError = this.handleImportError( e );
- console.log( e );
+
+ console.log(e);
return;
}
- }
+ }
do_listDisks() {
- if( !this.context.confirmCookies() ) {
- return;
- }
+ if (!this.context.confirmCookies()) {
+ return;
+ }
var list = { title: "Select Disk", items: [] };
var disks = this.context.getDisks();
- for( var i=0; i0 && i 0 && i < pgm.length; i++) {
+ var l = pgm[i];
+ if (id == i) {
+ this.console.setColor(col2);
+ this.context.listCodeLine(l[2]);
+ this.console.setColor(col1);
+ }
+ else {
+ this.context.listCodeLine(l[2]);
+ }
- if( l[2].length > 38 ) {
- max-=2;
- }
- else {
- max-=1;
- }
+ if (l[2].length > 38) {
+ max -= 2;
+ }
+ else {
+ max -= 1;
+ }
}
}
@@ -1306,10 +1385,11 @@ class Menu {
do_list() {
- var list = { title: "Basic Listing", showNum: false, offset:0, items: []
-// { name: "compatible", id: "compat"},
-// { name: "synchronized with host", id: "clocksync"}
- };
+ var list = {
+ title: "Basic Listing", showNum: false, offset: 0, items: []
+ // { name: "compatible", id: "compat"},
+ // { name: "synchronized with host", id: "clocksync"}
+ };
list.callback = "select_List";
@@ -1317,316 +1397,319 @@ class Menu {
//var basicList = [];
- for( var i=0; i 35 ) {
- display = l[2].substr(0,34)+"..";
- }
- list.items.push({name: display, id: i});
- // basicList.push({name: display, id: i});
+ for (var i = 0; i < pgm.length; i++) {
+ var l = pgm[i];
+ var display = l[2].trim();
+ if (display.length > 35) {
+ display = l[2].substr(0, 34) + "..";
+ }
+ list.items.push({ name: display, id: i });
+ // basicList.push({name: display, id: i});
- if( this.debugFlag ) {
- console.log(l[2]);
- }
+ if (this.debugFlag) {
+ console.log(l[2]);
+ }
}
list.hideLogo = true;
- this.startList( list );
+ this.startList(list);
}
do_changeExitMode() {
- if( !this.context.confirmCookies() ) {
+ if (!this.context.confirmCookies()) {
return;
}
- var list = { title: "when program exists:", items: [
- { name: "stay in current graphics mode", id: "stay"},
- { name: "return to text mode", id: "panic"}
- ] };
+ var list = {
+ title: "when program exists:", items: [
+ { name: "stay in current graphics mode", id: "stay" },
+ { name: "return to text mode", id: "panic" }
+ ]
+ };
list.callback = "select_ExitMode";
- this.startList( list );
+ this.startList(list);
}
do_changeImmersiveMode() {
- if( !this.context.confirmCookies() ) {
+ if (!this.context.confirmCookies()) {
return;
}
- var list = { title: "immersive mode:", items: [
- { name: "on", id: "immersive"},
- { name: "off", id: "off"}
- ] };
+ var list = {
+ title: "immersive mode:", items: [
+ { name: "on", id: "immersive" },
+ { name: "off", id: "off" }
+ ]
+ };
list.callback = "select_ImmersiveMode";
- this.startList( list );
+ this.startList(list);
}
do_changeClock() {
- if( !this.context.confirmCookies() ) {
+ if (!this.context.confirmCookies()) {
return;
}
- var list = { title: "Clock Mode", items: [
- { name: "compatible", id: "compat"},
- { name: "synchronized with host", id: "clocksync"}
- ] };
+ var list = {
+ title: "Clock Mode", items: [
+ { name: "compatible", id: "compat" },
+ { name: "synchronized with host", id: "clocksync" }
+ ]
+ };
list.callback = "select_Clock";
- this.startList( list );
+ this.startList(list);
}
do_changeRenum() {
- if( !this.context.confirmCookies() ) {
+ if (!this.context.confirmCookies()) {
return;
}
- var list = { title: "Renumber Mode", items: [
- { name: "plain", id: "plain"},
- { name: "data", id: "data"},
- { name: "rem", id: "rem"}
- ] };
+ var list = {
+ title: "Renumber Mode", items: [
+ { name: "plain", id: "plain" },
+ { name: "data", id: "data" },
+ { name: "rem", id: "rem" }
+ ]
+ };
list.callback = "select_RenumberMode";
- if( this.debugFlag ) {
+ if (this.debugFlag) {
console.log("list options");
}
- this.startList( list );
+ this.startList(list);
}
do_changeTurbo() {
- if( !this.context.confirmCookies() ) {
+ if (!this.context.confirmCookies()) {
return;
}
- var list = { title: "Turbo Mode", items: [
- { name: "on at startup", id: "on"},
- { name: "'turbo' command to enable", id: "manual"}
- ] };
+ var list = {
+ title: "Turbo Mode", items: [
+ { name: "on at startup", id: "on" },
+ { name: "'turbo' command to enable", id: "manual" }
+ ]
+ };
list.callback = "select_Extended";
- if( this.debugFlag ) {
+ if (this.debugFlag) {
console.log("list options");
}
- this.startList( list );
+ this.startList(list);
}
- select_File( id ) {
+ select_File(id) {
this.endMenu();
- if( this.debugFlag ) {
- console.log( id );
+ if (this.debugFlag) {
+ console.log(id);
}
- this.context.load( id );
+ this.context.load(id);
this.context.printLine("list");
var pgm = this.context.getProgramLines();
- for (const l of pgm )
- {
- this.context.listCodeLine( l[2] );
- if( this.debugFlag ) {
- console.log(l[2]);
- }
+ for (const l of pgm) {
+ this.context.listCodeLine(l[2]);
+ if (this.debugFlag) {
+ console.log(l[2]);
}
+ }
}
- do_listDirectory() {
+ do_listDirectory() {
- if( !this.context.confirmCookies() ) {
- return;
- }
+ if (!this.context.confirmCookies()) {
+ return;
+ }
- var list = { title: "Directory", showNum: true, items: [], offset:0 };
+ var list = { title: "Directory", showNum: true, items: [], offset: 0 };
var dir = this.context.getDir();
var row;
- for( var i=0; i" + e.detail );
- this.context.printLine( "ready." );
+ if( error != null ) {
+ this.endMenuWithError("import", error);
+ return;
}
- }
+ var pgm = new C64BasicProgram();
+ try {
+ pgm.parseBasicProgram( new Uint8Array( blob) );
+ }
+ catch(e) {
+ this.endMenuWithError("import", e );
+ return;
+ }
+
+ var lines = pgm.getTextProgramLines( false );
- do_importBasCallBack( text, fName ) {
+ var pgmText = "";
+ for (var i = 0; i < lines.length; i++) {
+ if (i > 0) {
+ pgmText += "\n";
+ }
+ var patchedLine = this.patchLine( lines[i] );
+ pgmText += patchedLine;
- var lines = text.split(/\r?\n/);
+ }
+
+ var lines2 = pgmText.split(/\r?\n/);
try {
- var bas = this.context.textLinesToBas( lines );
+ var bas = this.context.textLinesToBas(lines2);
}
catch (e) {
- this.endMenuWithMessage("parse error on import", detailError);
- var detailError = this.handleImportError( e );
- console.log( e );
+
+ this.endMenuWithMessage("parse error on import" );
+ this.handleImportError(e);
+
+ console.log(e);
return;
}
try {
- this.context.setProgram( bas );
+ this.context.setProgram(bas);
+ if( this.context.errorsInParsing ) {
+ this.endMenuWithError("import", this.context.errorsInParsing );
+ return;
+ }
}
catch (e) {
this.endMenuWithMessage("setpgm error on import");
- console.log( e );
- console.log( text );
+ console.log(e);
+ console.log(text);
return;
}
- if( this.runImportedPGMFlag ) {
- this.runImportedPGMFlag = false;
- this.endMenu();
- this.context.printLine("run");
- this.context.runPGM();
-
- }
- else {
- this.endMenuWithMessage("import ok");
- this.context.printLine("list");
-
- var pgm = this.context.getProgramLines();
- for (const l of pgm )
- {
- this.context.listCodeLine( l[2] );
- if( this.debugFlag ) {
- console.log(l[2]);
- }
- }
- }
-
- }
-
- do_exportSnapshot() {
- var data = JSON.stringify( this.vmState );
+ if (this.runImportedPGMFlag) {
+ this.runImportedPGMFlag = false;
+ this.endMenu();
+ this.context.printLine("run");
+ this.context.runPGM();
- var blob = new Blob( [data] , {
- type: 'text/plain'
- });
+ }
+ else {
+ this.endMenuWithMessage("import ok");
+ this.context.printLine("list");
- var objectUrl = URL.createObjectURL(blob);
+ var pgm = this.context.getProgramLines();
+ for (const l of pgm) {
+ this.context.listCodeLine(l[2]);
+ if (this.debugFlag) {
+ console.log(l[2]);
+ }
+ }
+ }
- var link = document.getElementById( "imageSaver" );
- link.download = "basic64js.snap64";
- link.href = objectUrl;
- link.click();
+ }
- }
- do_importSnapshot() {
+ do_importBasCallBack(text, fName) {
- var uploadElement = document.getElementById( "imageLoader" );
- this.runImportedPGMFlag = false;
+ var lines = text.split(/\r?\n/);
+ try {
+ var bas = this.context.textLinesToBas(lines);
+ }
+ catch (e) {
- this.uploader.setCallback( this, "do_importSnapshotCallBack" );
+ this.endMenuWithMessage("parse error on import", detailError);
+ var detailError = this.handleImportError(e);
+ console.log(e);
+ return;
+ }
- uploadElement.click();
- if( this.debugFlag ) {
- console.log( "clicked" );
+ try {
+ this.context.setProgram(bas);
+ }
+ catch (e) {
+ this.endMenuWithMessage("setpgm error on import");
+ console.log(e);
+ console.log(text);
+ return;
}
- }
+ if (this.runImportedPGMFlag) {
+ this.runImportedPGMFlag = false;
+ this.endMenu();
+ this.context.printLine("run");
+ this.context.runPGM();
- do_importSnapshotCallBack( text, fName ) {
+ }
+ else {
+ this.endMenuWithMessage("import ok");
+ this.context.printLine("list");
- if( this.debugFlag ) {
- console.log("Import Snapshot");
+ var pgm = this.context.getProgramLines();
+ for (const l of pgm) {
+ this.context.listCodeLine(l[2]);
+ if (this.debugFlag) {
+ console.log(l[2]);
+ }
+ }
}
- this.endMenuWithMessage("snapshot restore");
+ }
- this.context.loadContainer(
- {
- type: "snp",
- data: text
- });
- }
+ do_exportSnapshot() {
+ var data = JSON.stringify(this.vmState);
- do_saveSnapshot() {
+ var blob = new Blob([data], {
+ type: 'text/plain'
+ });
- var data = JSON.stringify(this.vmState);
+ var objectUrl = URL.createObjectURL(blob);
+
+ var link = document.getElementById("imageSaver");
+ link.download = "basic64js.snap64";
+ link.href = objectUrl;
+ link.click();
- this.context.saveSerializedData( "SNAPSHOT", data, "snp", 65536 );
+ }
- this.endMenuWithMessage("snapshot saved");
- }
+ do_importSnapshot() {
- do_reset() {
- this.endMenu();
- this.context.reset( true );
- }
+ var uploadElement = document.getElementById("imageLoader");
+ this.runImportedPGMFlag = false;
- do_changeTheme() {
- this.theme++;
- if( this.theme > (this.themes.length - 1) ) {
- this.theme = 0;
- }
+ this.uploader.setCallback(this, "do_importSnapshotCallBack");
+ this.uploader.start(".snap64");
- if( this.context.confirmCookies() ) {
- localStorage.setItem( "BJ64_Menu", JSON.stringify( { theme: this.theme } ) );
- }
+ if (this.debugFlag) {
+ console.log("clicked");
+ }
- this.rendervmState();
- }
+ }
+ do_importSnapshotCallBack(text, fName) {
- do_documentation() {
- window.open("https://github.com/JoystickAndCursorKeys/basic64-js/wiki",'_blank');
+ if (this.debugFlag) {
+ console.log("Import Snapshot");
+ }
- this.endMenuWithMessage("opened docs");
- }
+ this.endMenuWithMessage("snapshot restore");
-/*
+ this.context.loadContainer(
+ {
+ type: "snp",
+ data: text
+ });
+ }
-Keyboard
+ do_saveSnapshot() {
- Special Chars
+ var data = JSON.stringify(this.vmState);
- PC - Commodore
- ----------------
- F9 - Power Menu Toggle
- F1 - F1
- F2 - F2
- F3 - F3
- F4 - F4
- F5 - Shift F1
- F6 - Shift F2
- F7 - Shift F3
- F8 - Shift F4
- CTRL/PAUSE - Run/Stop + Restore
- ESCAPE - Stop (RUN/STOP)
- ALT 1-8 - Colors
- ALT 9 - Reverse on
- ALT 0 - Reverse off
+ this.context.saveSerializedData("SNAPSHOT", data, "snp", 65536);
+ this.endMenuWithMessage("snapshot saved");
+ }
+ do_reset() {
+ this.endMenu();
+ this.context.reset(true);
+ }
+ do_changeTheme() {
+ this.theme++;
+ if (this.theme > (this.themes.length - 1)) {
+ this.theme = 0;
+ }
+ if (this.context.confirmCookies()) {
+ localStorage.setItem("BJ64_Menu", JSON.stringify({ theme: this.theme }));
+ }
+ this.rendervmState();
+ }
+ do_documentation() {
+ window.open("https://github.com/JoystickAndCursorKeys/basic64-js/wiki", '_blank');
+ this.endMenuWithMessage("opened docs");
+ }
-*/
+ /*
+
+ Keyboard
+
+ Special Chars
+
+ PC - Commodore
+ ----------------
+ F9 - Power Menu Toggle
+ F1 - F1
+ F2 - F2
+ F3 - F3
+ F4 - F4
+ F5 - Shift F1
+ F6 - Shift F2
+ F7 - Shift F3
+ F8 - Shift F4
+ CTRL/PAUSE - Run/Stop + Restore
+ ESCAPE - Stop (RUN/STOP)
+ ALT 1-8 - Colors
+ ALT 9 - Reverse on
+ ALT 0 - Reverse off
+
+
+
+
+
+
+
+
+
+ */
}
diff --git a/index.html b/index.html
index 05b613d..877cf17 100644
--- a/index.html
+++ b/index.html
@@ -152,9 +152,9 @@
Tips
- - Use F9 or TAB to enter the power menu
- - Use the menu settings to auto enable extended behaviour.
- - Don't PANIC, just type PANIC instead :)
+ - Use F9 or TAB to enter the power menu
+ - Use the menu settings to auto enable extended behaviour.
+ - Don't PANIC, just type PANIC instead :)
@@ -214,6 +214,8 @@
+Version 0.8 - Patch 4
+Version 0.8 - Patch 3
Version 0.8 - Patch 2
Version 0.8 - Patch 1
Version 0.8
diff --git a/versions/0.8p5/doc/examples.json b/versions/0.8p5/doc/examples.json
new file mode 100644
index 0000000..db84353
--- /dev/null
+++ b/versions/0.8p5/doc/examples.json
@@ -0,0 +1,18 @@
+[
+ {
+ "section": "text",
+ "list": ["guessing.bas", "fireworks.bas", "tictactoe.bas", "simplesnake.bas"]
+ },
+ {
+ "section": "extended graphics",
+ "list": ["mandelbrot.bas", "screensaver1.bas"]
+ },
+ {
+ "section": "extended sprite",
+ "list": ["spriteanim.bas", "spriteanim2.bas"]
+ },
+ {
+ "section": "short",
+ "list": ["10liner_fsnake.bas"]
+ }
+]
diff --git a/versions/0.8p5/index.html b/versions/0.8p5/index.html
new file mode 100644
index 0000000..def9cf6
--- /dev/null
+++ b/versions/0.8p5/index.html
@@ -0,0 +1,390 @@
+
+
+
+ Basic-64/js
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/versions/0.8p5/res/bas/test/unit1.bas b/versions/0.8p5/res/bas/test/unit1.bas
new file mode 100644
index 0000000..25945db
--- /dev/null
+++ b/versions/0.8p5/res/bas/test/unit1.bas
@@ -0,0 +1,76 @@
+1 xon :cls
+10 gosub 1010:gosub 500
+11 gosub 1020:gosub 500
+12 gosub 1030:gosub 500
+13 gosub 1040:gosub 500
+14 gosub 1050:gosub 500
+15 gosub 1060:gosub 500
+16 gosub 1070:gosub 500
+17 gosub 1080:gosub 500
+18 gosub 1090:gosub 500
+19 gosub 1100:gosub 500
+20 gosub 1110:gosub 500
+21 gosub 1120:gosub 500
+22 gosub 1130:gosub 500
+499 end
+500 print "{5}testcase ";tc ;" ";
+505 if i = 1then print "ignore":return
+510 if r =e then re$ ="{30}ok"
+520 if r <>e then re$ ="{28}error"
+530 ? re$ ;"{144}";tc$
+534 if r <>e then print "{28}";
+535 if r <>e then print "r(";r ;")<>";
+536 if r <>e then print "e(";e ;")"
+1010 rem testcase 1---
+1011 tc = 1:tc$ ="addition":i = 0
+1012 r =100+100
+1019 e =200:return
+1020 rem testcase 2---
+1021 tc = 2:tc$ ="substraction":i = 0
+1022 r =100-100
+1029 e = 0:return
+1030 rem testcase 3---
+1031 tc = 3:tc$ ="multiplication":i = 0
+1032 r =100/100
+1039 e = 1:return
+1040 rem testcase 4---
+1041 tc = 4:tc$ ="division":i = 0
+1042 r =100/100
+1049 e = 1:return
+1050 rem testcase 5---
+1051 tc = 5:tc$ ="add&multiply":i = 0
+1052 r =15+15*16+17
+1059 e =272:return
+1060 rem testcase 6---
+1061 tc = 6:tc$ ="add&multiply2":i = 0
+1062 r =15*15+16*17
+1069 e =497:return
+1070 rem testcase 7---
+1071 tc = 7:tc$ ="sub&multiply":i = 0
+1072 r =15*15-16*17
+1079 e =-47:return
+1080 rem testcase 8---
+1081 tc = 8:tc$ ="sub&multiply2":i = 0
+1082 r =15-15*16-17
+1089 e =-242:return
+1090 rem testcase 7---
+1091 tc = 7:tc$ ="sub&div":i = 1
+1092 r =15/15-16/17
+1099 e =-47:return
+1100 rem testcase 8---
+1101 tc = 8:tc$ ="sub&div2":i = 1
+1102 r =15-15/16-17
+1109 e =-242:return
+1110 rem testcase 9---
+1111 tc = 9:tc$ ="sub&div2":i = 0
+1112 r =15-33/ 3-17
+1119 e =-13:return
+1120 rem testcase 10---
+1121 tc =10:tc$ ="add+pow":i = 0
+1122 r =15+15{94} 2+13{94} 3
+1129 e =2437:return
+1130 rem testcase 11---
+1131 tc =11:tc$ ="def fn":i = 0
+1132 def fn f11 (x )=3.5*x
+1135 r =fn f11 (15)
+1139 e =52.5:return
diff --git a/versions/0.8p5/res/img/fav.png b/versions/0.8p5/res/img/fav.png
new file mode 100644
index 0000000..a826866
Binary files /dev/null and b/versions/0.8p5/res/img/fav.png differ
diff --git a/versions/0.8p5/res/img/kb/commodore-white.png b/versions/0.8p5/res/img/kb/commodore-white.png
new file mode 100644
index 0000000..c30d19a
Binary files /dev/null and b/versions/0.8p5/res/img/kb/commodore-white.png differ
diff --git a/versions/0.8p5/res/img/menu/arrow.png b/versions/0.8p5/res/img/menu/arrow.png
new file mode 100644
index 0000000..3460793
Binary files /dev/null and b/versions/0.8p5/res/img/menu/arrow.png differ
diff --git a/versions/0.8p5/res/script/basicarray.js b/versions/0.8p5/res/script/basicarray.js
new file mode 100644
index 0000000..3f2e67f
--- /dev/null
+++ b/versions/0.8p5/res/script/basicarray.js
@@ -0,0 +1,72 @@
+class BasicArray {
+
+ constructor( name, indices, defaultValue ) {
+ this.name = name;
+ this.indices = indices;
+ this.buffer = null;
+ this.defaultValue = defaultValue;
+ }
+
+ getIndexCount() {
+ return this.indices.length;
+ }
+
+ _check( indices ) {
+ if( indices.length != this.indices.length ) {
+ throw "00:index dimension mismatch for array " + this.name;
+ }
+ for( var i=0; i this.indices[ i ]) {
+ throw "01:index " + indices[i] + " out of bounds for array " + this.name + " for index " + i;
+ }
+ else if ( indices[i] < 0) {
+ throw "02:index smaller then zero for array " + this.name;
+ }
+
+ }
+ }
+
+ set( indices, val ) {
+ this._check( indices );
+ if( this.buffer == null ) {
+ this.buffer = [];
+ }
+ var ptr = this.buffer;
+ var last = indices.length - 1;
+ for( var i=0; i<=last; i++) {
+
+ if( i == last ) {
+ ptr[ indices[ i ]] = val;
+ }
+ else {
+ if( (ptr [ indices[i] ] === undefined )) {
+ ptr[ indices[ i ]] = [];
+ }
+ ptr = ptr[ indices[ i ]];
+ }
+ }
+ }
+
+ get( indices ) {
+ this._check( indices );
+
+ if( this.buffer == null ) {
+ return this.defaultValue;
+ }
+ var ptr = this.buffer;
+ var last = indices.length - 1;
+ for( var i=0; i<=last; i++) {
+
+ if( i == last ) {
+ return ptr[ indices[ i ]];
+ }
+ else {
+ if( (ptr [ indices[i] ] === undefined )) {
+ return this.defaultValue;
+ }
+ ptr = ptr[ indices[ i ]];
+ }
+ }
+ }
+
+}
diff --git a/versions/0.8p5/res/script/basiccommands.js b/versions/0.8p5/res/script/basiccommands.js
new file mode 100644
index 0000000..b6f1d90
--- /dev/null
+++ b/versions/0.8p5/res/script/basiccommands.js
@@ -0,0 +1,536 @@
+class BasicCommands {
+
+ constructor( context ) {
+ this.console = context.console;
+ this.context = context;
+ this.cmds = {};
+ this.func = {};
+ this.statementList = null;
+ this.erh = new ErrorHandler();
+
+ this.randnrs = [];
+ for(var i=0; i<10000;i++) {
+ this.randnrs.push( Math.random() );
+ }
+ this.randIndex = 0;
+ this.randStep = 1;
+
+ }
+
+ getStatements() {
+
+ //if( this.statementList != null ) {
+ // return this.statementList;
+ //}
+
+ var stats = Object.getOwnPropertyNames( BasicCommands.prototype );
+
+ var stats2 = [];
+
+ for( var i=0;i=0 ) {
+ start = parts[0].data;
+ end = parts[0].data;
+ }
+ else if( parts.length == 1 && parts[0].type == "num" && parts[0].data <0 ) {
+ /*NOTE, this will stop working if RAW changes to return uniop + posnum */
+ end = -parts[0].data;
+ }
+ else if( parts.length == 2
+ && parts[0].type == "num"
+ && parts[1].type == "num"
+ && parts[1].op == "-"
+ ) {
+ start = parts[0].data;
+ end = parts[1].data;
+
+ }
+ else if( parts.length == 2
+ && parts[0].type == "num"
+ && parts[1].type == "uniop"
+ && parts[1].op == "-"
+ ) {
+ start = parts[0].data;
+ }
+
+ var context = this.context;
+ var list = [];
+ for (const l of context.program)
+ {
+
+ var lineNr = parseInt(l[0]);
+ if( l[0] == null || (lineNr>= start && lineNr<= end) ) {
+ list.push( l[2] );
+ }
+ }
+
+ this.context.enterListMode( list );
+ }
+
+ _if_get() {
+ var EXPR = 0, PAR = 1, RAW=2;
+ return [PAR];
+ }
+
+ _if_read() {
+ var EXPR = 0, PAR = 1, RAW=2;
+ return [PAR];
+ }
+
+ _if_input() {
+ var EXPR = 0, PAR = 1, RAW=2;
+ return [RAW, RAW, RAW, RAW, RAW, RAW, RAW, RAW, RAW, RAW];
+ }
+
+ _if_list() {
+ var EXPR = 0, PAR = 1, RAW=2;
+ return [RAW];
+ }
+
+ _stat_read( pars ) {
+ var p0 = pars[ 0 ];
+ if( p0.type != "var" ) {
+ this.erh.throwError( "not a var", "parameter 0" );
+ }
+
+ var data = this.context.readData();
+ if( data === undefined ) { this.erh.throwError( "out of data" ); }
+ else {
+ if( data.type =="num" ) {
+ this.context.setVar(
+ p0.value, parseInt( data.data ) );
+ }
+ else {
+ this.context.setVar(
+ p0.value, data.data );
+ }
+ }
+ }
+
+ _stat_get( pars ) {
+ var p0 = pars[ 0 ];
+
+ if( p0.type != "var" ) {
+ this.erh.throwError( "not a var", "parameter 0" );
+ }
+
+ var k = this.context.pullKeyBuffer();
+ if( k<0 ) { this.context.setVar(p0.value, ""); }
+ else { this.context.setVar(p0.value, String.fromCharCode( k ) ); }
+ }
+
+ _stat_input( pars ) {
+
+ var vars = [];
+
+ for( var i=0; i= 0 ) {
+ return " " + x;
+ }
+ }
+ return "" + x;
+ }
+
+ _stat_print( pars ) {
+
+
+ var context = this.context;
+ if( pars.length == 0 ) {
+ context.sendChars( "", true );
+ return;
+ }
+ else if( pars.length == 1 ) {
+ if( pars[0].parts.length == 0 ) {
+ context.sendChars( "", true );
+ return;
+ }
+ }
+
+ var newLine = true;
+ var value;
+ for( var i=0; i0) { context.sendChars( " " , false ); }
+
+ var exparts = pars[i];
+ var exparts2=
+ { parts: [],
+ binaryNegate: exparts.binaryNegate,
+ negate: exparts.negate };
+
+ for( var j=0; j=0) {
+ return " " + pars[0].value;
+ }
+ return "" + pars[0].value;
+ }
+
+ _fun_abs( pars ) {
+ if( pars[0].value < 0 ) {
+ return -pars[0].value;
+ }
+ return pars[0].value;
+ }
+
+ _fun_len( pars ) {
+ return pars[0].value.length;
+ }
+
+ _fun_asc( pars ) {
+ return pars[0].value.charCodeAt(0);
+ }
+
+ _fun_val( pars ) {
+ return parseInt( pars[0].value );
+ }
+
+ _fun_exp( pars ) {
+ return Math.exp( pars[0].value );
+ }
+
+ intGetNextRand() {
+ this.randIndex = (this.randIndex + this.randStep) % this.randnrs.length;
+ return this.randnrs[ this.randIndex ];
+ }
+
+ intSeedRand( x ) {
+ var base = Math.floor( x * 11 );
+ this.randIndex= base % this.randnrs.length;
+ this.randStep = 1+(base % 7);
+ }
+
+
+ _fun_rnd( pars ) {
+
+ if( pars.length <1) {
+ this.erh.throwError( "syntax", "missing parameter 0" );
+ }
+
+ if( pars[0].value < 0) {
+ this.intSeedRand( -pars[0].value );
+ }
+
+ return this.intGetNextRand();
+ }
+
+ _fun_sqr( pars ) {
+ return Math.sqrt( pars[0].value);
+ }
+
+ _fun_log( pars ) {
+ return Math.log( pars[0].value);
+ }
+
+ _fun_pos( pars ) {
+ return this.context.getLinePos();
+ }
+
+ _fun_left_DLR_( pars ) {
+ //? LEFT$(A$,8)
+ var s = pars[0].value;
+
+ if( (typeof s) != "string") {
+ throw "@type mismatch";
+ }
+ return s.substr(0,pars[1].value);
+ }
+
+ _fun_right_DLR_( pars ) {
+ //? RIGHT$(A$,8)
+ var s = pars[0].value;
+
+ if( (typeof s) != "string") {
+ throw "@type mismatch";
+ }
+ return s.substr( s.length - pars[1].value );
+ }
+
+ _fun_mid_DLR_( pars ) {
+ //? RIGHT$(A$,8)
+ var s = pars[0].value;
+
+ if( (typeof s) != "string") {
+ throw "@type mismatch";
+ }
+ if( pars.length == 3) {
+ return s.substr( pars[1].value-1, pars[2].value );
+ }
+ else if( pars.length == 2) {
+ return s.substr( pars[1].value-1 );
+ }
+ }
+
+ _fun_fre( pars ) {
+ return -26627;
+ }
+
+ _fun_sin( pars ) {
+ return Math.sin( pars[0].value);
+ }
+
+ _fun_tan( pars ) {
+ return Math.tan( pars[0].value);
+ }
+
+ _fun_atn( pars ) {
+ return Math.atan( pars[0].value);
+ }
+
+ _fun_cos( pars ) {
+ return Math.cos( pars[0].value);
+ }
+
+ _fun_spc( pars ) {
+ var out="";
+ for( var i=0; i 255 ) {
+ this.erh.throwError( "illegal quantity", "value must be in-between 0 and 255" );
+ }
+ context.setCursLongXPos( pars[0].value );
+ return "";
+ }
+
+ _fun_sgn( pars ) {
+ var x = pars[0].value;
+
+ if( x<0 ) { return -1; }
+ else if( x>0 ) { return 1; }
+ return 0;
+ }
+
+ _fun_peek( pars ) {
+
+ var context = this.context;
+ return context.peek( Math.floor( pars[0].value ) );
+
+ }
+
+ _fun_jiffies( pars ) {
+ return this.context.getJiffyTime( );
+ }
+}
diff --git a/versions/0.8p5/res/script/basiccontext.js b/versions/0.8p5/res/script/basiccontext.js
new file mode 100644
index 0000000..8af3e89
--- /dev/null
+++ b/versions/0.8p5/res/script/basiccontext.js
@@ -0,0 +1,3706 @@
+class BasicContext {
+
+ constructor(_console) {
+
+ this.debugFlag = false;
+ this.console = _console;
+ this.menu = new Menu(_console, this);
+ this.menuFocus = false;
+ this.borderChangedFlag = false;
+ this.program = [];
+ this.cursorCount = 0;
+ this.runFlag = false;
+ this.executeLineFlag = false;
+ this.goPlayExampleFlag = false;
+ this.breakCycleFlag;
+ this.inputFlag = false;
+ this.listFlag = false;
+ this.immersiveFlag = false;
+ this.gosubReturn = [];
+ this.nullTime = new Date().getTime();
+ this.cursorCountMaxNormal = 15;
+ this.cursorCountMaxTurbo = 7;
+ this.cursorCountMax = this.cursorCountMaxNormal;
+
+ this.turboMode = false;
+ this.renumMode = "rem";
+ this.cmdCountPerCycleDefault = 5;
+ this.cmdCountPerCycleTurbo = 1000;
+ this.cmdCountPerCycle = this.cmdCountPerCycleDefault;
+
+ var ctx = this.context;
+ var c = this.console;
+ this.commands = new BasicCommands(this);
+ this.extendedcommands = new ExtendedCommands(this);
+ this.erh = new ErrorHandler();
+ this.vars = [];
+ this.functions = [];
+ this.data = [];
+ this.kbBuffer = [];
+
+ this.yPos = -1;
+ this.lineMarkers = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+ this.SHORTLINE = 0;
+ this.LONGLINESTART = 1;
+ this.LONGLINEEND = 2;
+
+ this.forContext = { default: [] }
+
+ this.vDisks = new VDisk();
+
+ this.consoleCallBacksAll = {
+ lineOverFlow: { clazz: this, method: "cbLineOverFlow" },
+ scroll: { clazz: this, method: "cbScroll" },
+ clearScreen: { clazz: this, method: "cbClearScreen" }
+ }
+
+ this.consoleCallBacksClScr = {
+ lineOverFlow: undefined,
+ scroll: { clazz: this, method: "cbScroll" },
+ clearScreen: { clazz: this, method: "cbClearScreen" }
+ }
+
+ var json = localStorage.getItem('BJ64_Settings');
+ if (json != null) {
+ this.settings = JSON.parse(json);
+ }
+ else {
+ this.settings = {}
+ this.settings.cookies = false;
+ }
+
+ var commandsExtended = localStorage.getItem("BJ64_Extended");
+ if (commandsExtended != null) {
+ commandsExtended = JSON.parse(commandsExtended);
+ commandsExtended = commandsExtended.extended;
+
+ if (commandsExtended == "on") {
+ this.enableExtended(true);
+ }
+ }
+
+ var turbo = localStorage.getItem("BJ64_Turbo");
+ if (turbo != null) {
+ turbo = JSON.parse(turbo);
+ turbo = turbo.turbo;
+
+ if (turbo == "on") {
+ this.setTurbo(true);
+ }
+ }
+
+ var renumMode = localStorage.getItem("BJ64_Renum");
+ if (renumMode != null) {
+ renumMode = JSON.parse(renumMode);
+ renumMode = renumMode.renumMode;
+
+ this.renumMode = renumMode;
+
+ }
+
+ var clock = localStorage.getItem("BJ64_Clock");
+ if (clock != null) {
+ clock = JSON.parse(clock);
+ clock = clock.synchronized;
+
+ if (clock == "clocksync") {
+ this.synchClock();
+ }
+ }
+
+ this.exitMode = "stay";
+ var exitMode = localStorage.getItem("BJ64_ExitMode");
+ if (exitMode != null) {
+ exitMode = JSON.parse(exitMode);
+ exitMode = exitMode.exitmode;
+
+ if (exitMode == "panic") {
+ this.setExitMode("panic");
+ }
+ }
+
+ this.initScale = "2.5";
+ var scale = localStorage.getItem("BJ64_Zoom");
+ if (scale != null) {
+ scale = JSON.parse(scale);
+ scale = scale.zoom;
+
+ this.initScale = scale;
+ this.setScale(scale);
+ }
+
+
+ this.showSideBorders = true;
+ var show = localStorage.getItem("BJ64_SideBorder");
+ if (show != null) {
+ show = JSON.parse(show);
+ show = show.sideborder;
+
+ this.showSideBorders = show;
+ this.setShowSideBorders(show);
+ }
+
+
+ this.immersiveFlag = false;
+ var immersiveMode = localStorage.getItem("BJ64_ImmersiveMode");
+ if (immersiveMode != null) {
+ immersiveMode = JSON.parse(immersiveMode);
+ immersiveMode = immersiveMode.immersive;
+
+ if (immersiveMode == "immersive") {
+ this.immersiveFlag = true;
+ this.setBorderChangedFlag();
+ }
+ }
+
+ this.code2colMap = [];
+ var km = this.code2colMap;
+
+ km[0x90] = 0;
+ km[0x05] = 1;
+ km[0x1c] = 2;
+ km[0x9f] = 3;
+ km[0x9c] = 4;
+ km[0x1e] = 5;
+ km[0x1f] = 6;
+ km[0x9e] = 7;
+
+ km[0x81] = 8;
+ km[0x95] = 9;
+ km[0x96] = 10;
+ km[0x97] = 11;
+ km[0x98] = 12;
+ km[0x99] = 13;
+ km[0x9a] = 14;
+ km[0x9b] = 15;
+
+ this.symbolTable = {};
+
+ this.symbolTable.up = 0x91;
+ this.symbolTable.down = 0x11;
+ this.symbolTable.left = 157;
+ this.symbolTable.right = 29;
+ this.symbolTable["reverse on"] = 0x12;
+ this.symbolTable["reverse off"] = 0x92;
+ this.symbolTable["clear"] = 0x93;
+ this.symbolTable["home"] = 0x13;
+ this.symbolTable.black = 144;
+ this.symbolTable.white = 5;
+ this.symbolTable.red = 28;
+ this.symbolTable.cyan = 159;
+ this.symbolTable.purple = 156;
+ this.symbolTable.green = 30;
+ this.symbolTable.blue = 31;
+ this.symbolTable.yellow = 158;
+ this.symbolTable.orange = 129;
+ this.symbolTable.brown = 149;
+ this.symbolTable.pink = 150; // light red
+ this.symbolTable.grey1 = 151; //dark grey
+ this.symbolTable.grey2 = 152;
+ this.symbolTable["light green"] = 153;
+ this.symbolTable["light blue"] = 154;
+ this.symbolTable.grey3 = 155; //light grey
+
+
+ var backmap = []
+ var mapInfo = Object.entries(this.symbolTable);
+ for (var i = 0; i < mapInfo.length; i++) {
+ backmap[mapInfo[i][1]] = mapInfo[i][0];
+ }
+ this.symbolTableBM = backmap;
+
+
+ /*for( var ii=0; ii<256; ii++) {
+
+ var bits = this._getByteBits( ii );
+ var byte2 = this._setByteBits( bits );
+ var bits2 = this._getByteBits( byte2 );
+
+ console.log( "byte: ", ii );
+ console.log( "bits: ", bits );
+ console.log( "byte2: ", byte2 );
+ console.log( "bits2: ", bits2 );
+
+ }*/
+
+ }
+
+ toggleSideBorders() {
+ this.showSideBorders = !this.showSideBorders;
+ this.console.setSideBorders(this.showSideBorders);
+
+ }
+
+ getSideBordersFlag() {
+
+ return this.showSideBorders;
+
+ }
+
+
+ setShowSideBorders(flag) {
+ this.showSideBorders = flag;
+ this.console.setSideBorders(this.showSideBorders);
+ }
+
+
+ getPlayExampleFlag() {
+ if (this.goPlayExampleFlag) {
+ this.goPlayExampleFlag = false;
+ return true;
+ }
+ return false;
+ }
+
+ setImmersiveFlag(v) {
+ this.immersiveFlag = v;
+ }
+
+ enterListMode(list) {
+ this.listFlag = true;
+ this.list = list;
+ this.listPointer = 0;
+ }
+
+ setExitMode(v) {
+ this.exitMode = v;
+ }
+
+ synchClock() {
+
+ //var clock = new Date().getTime();
+ var nullClock = new Date();
+ nullClock.setHours(0);
+ nullClock.setSeconds(0);
+ nullClock.setMinutes(0);
+ nullClock.setMilliseconds(0);
+
+ this.nullTime = nullClock;
+
+ }
+
+ setRenumMode(mode) {
+ this.renumMode = mode;
+ }
+
+ setTurbo(on) {
+ if (on) {
+ this.cmdCountPerCycle = this.cmdCountPerCycleTurbo;
+ this.turboMode = true;
+ this.cursorCountMax = this.cursorCountMaxTurbo;
+ return;
+ }
+ this.cmdCountPerCycle = this.cmdCountPerCycleDefault;
+ this.turboMode = false;
+ this.cursorCountMax = this.cursorCountMaxNormal;
+ }
+
+ setProgram(pgm) {
+ this.program = pgm;
+ this.runFlag = false;
+ this.panicIfStopped();
+
+ this.inputFlag = false;
+ this.listFlag = false;
+ this.console.clearCursor();
+ }
+
+ appendProgram(pgm) {
+
+ for (var i = 0; i < pgm.length; i++) {
+ var exists = -1;
+
+ for (var j = 0; j < this.program.length; j++) {
+ if (this.program[j][0] == pgm[i][0]) {
+ exists = j;
+ }
+ }
+
+ if (exists > -1) {
+ this.program[exists] = pgm[i];
+ }
+ else {
+ this.program.push(pgm[i]);
+ }
+ }
+
+ var sortF = function compare(a, b) {
+ return a[0] - b[0];
+ }
+
+ this.program.sort(sortF);
+
+ this.runFlag = false;
+ this.panicIfStopped();
+
+ this.inputFlag = false;
+ this.listFlag = false;
+ this.console.clearCursor();
+ }
+
+ getProgram() {
+ return this.program;
+ }
+
+ setBorderChangedFlag() {
+ this.borderChangedFlag = true;
+ }
+
+ getBorderChangedFlag() {
+ if (this.borderChangedFlag) {
+ this.borderChangedFlag = false;
+ return true;
+ }
+ return false;
+ }
+
+ getImmersiveFlag() {
+ return this.immersiveFlag;
+ }
+
+ getProgramState() {
+ return {
+ runFlag: this.runFlag,
+ inputFlag: this.inputFlag,
+ vars: this.vars,
+ functions: this.functions,
+ forContext: this.forContext,
+ runPointer: this.runPointer,
+ runPointer2: this.runPointer2
+ }
+ }
+
+ setProgramState(pgmState) {
+ this.runFlag = pgmState.runFlag;
+ this.panicIfStopped();
+ this.inputFlag = pgmState.inputFlag;
+ this.vars = pgmState.vars;
+ this.functions = pgmState.functions;
+ this.forContext = pgmState.forContext;
+ this.runPointer = pgmState.runPointer;
+ this.runPointer2 = pgmState.runPointer2;
+ }
+
+ firstTimeAccessStorage() {
+ this.settings.cookies = true;
+ this.vDisks.initialize();
+
+ localStorage.setItem("BJ64_Settings", JSON.stringify(this.settings));
+ }
+
+ confirmCookies() {
+
+ if (this.settings.cookies == false) {
+ if (confirm('Settings and Virtual Storage require localstorage and cookies, \nEnable?')) {
+ this.firstTimeAccessStorage();
+ return true;
+ } else {
+ // Do nothing!
+ return false;
+ }
+ }
+ else {
+ if (!this.vDisks.ready()) {
+ this.vDisks.initialize();
+ }
+ return true;
+ }
+
+ }
+
+ isMenu() {
+ return this.menuFocus;
+ }
+
+ updateEditMode() {
+
+ if (this.menuFocus) {
+ this.setEditModeCallBacks("none");
+ return;
+ }
+
+ if (!this.runFlag && !this.listFlag && !this.executeLineFlag) {
+ this.setEditModeCallBacks("edit");
+ return;
+ }
+ else if (this.listFlag) {
+ this.setEditModeCallBacks("edit");
+ return;
+ }
+ else if (this.runFlag && this.inputFlag) {
+ this.setEditModeCallBacks("edit");
+ return;
+ }
+ else if (this.runFlag || this.executeLineFlag) {
+ this.setEditModeCallBacks("print");
+ return;
+ }
+ }
+
+ toggleMenu() {
+ if (!this.menuFocus) {
+ this.listStop();
+ this.updateEditMode();
+ this.menu.start();
+ }
+ else {
+ this.menu.stop();
+ this.updateEditMode();
+ }
+ this.menuFocus = !this.menuFocus;
+ }
+
+ endMenu() {
+
+ this.menuFocus = false;
+ }
+
+ handleMenuKey(keyEvent) {
+ this.menu.handleKey(keyEvent);
+ }
+
+ vpoke(a, b) { this.console.vpoke(a - 53248, b % 256); }
+ /* todo remove vpoke */
+
+
+
+ _setByteBits(bits) {
+
+ var byte = 0b00000000;
+
+ for (var i = 0; i < 8; i++) {
+ if (i > 0) {
+ byte = byte >> 1;
+ }
+ if (bits[i]) {
+ byte = byte | 128;
+ }
+ }
+ return byte;
+ }
+
+ _getByteBits(byte) {
+ var masks = [
+ 0b00000001, 0b00000010, 0b00000100, 0b00001000,
+ 0b00010000, 0b00100000, 0b01000000, 0b10000000
+ ];
+
+ var results = [false, false, false, false, false, false, false, false];
+
+ for (var i = 0; i < 8; i++) {
+
+ results[i] = (byte & masks[i]) > 0;
+
+ }
+
+ return results;
+ }
+
+
+ poke(a, b0, noVicFlush) {
+
+ var b = Math.floor(b0) % 256;
+
+ if (isNaN(b)) { b = 0; }
+
+ if (a == 1) { //Bank Switching
+
+ this.console.poke(a, b);
+
+ //%0xx: Character ROM visible at $D000-$DFFF. (Except for the value %000, see above.)
+ //%1xx: I/O area visible at $D000-$DFFF. (Except for the value %100, see above.)
+ //https://sta.c64.org/cbm64mem.html
+ var bits = this._getByteBits(b);
+
+
+ if (bits[0] == false) {
+ this.console.setCharRomVisible(true);
+ }
+ else {
+ this.console.setCharRomVisible(false);
+ }
+
+ }
+ else if (a == 646) {
+ this.console.setColor(b % 16);
+ }
+ else if (a > 53247 && a < 53295) { //VIC registers
+
+ if (this.console.getCharRomVisible() == false) {
+ this.console.vpoke(a - 53248, b % 256);
+ if (noVicFlush === undefined) {
+ this.console.pokeFlush();
+ }
+ }
+ else {
+ //Can't poke in ROM
+ //Since now VIC registers are hidden, and char rom is showed here
+ }
+
+ }
+ else if (a > 1023 && a < 2024) {
+ var v = a - 1024;
+ var y = Math.floor(v / 40);
+ var x = v % 40;
+ var c = b % 256;
+
+ this.console.setChar(x, y, c);
+ }
+ else if (a >= 2040 && a < 2048) {
+
+ this.console.poke(a, b);
+
+ var sn = a - 2040;
+ var addr = b * 64;
+
+ this.console.setSpriteAddress(sn, addr);
+
+ }
+ else if (a > 55295 && a < 56296) {
+ var v = a - 55296;
+ var y = Math.floor(v / 40);
+ var x = v % 40;
+ var c = b % 256;
+
+ this.console.setCharCol(x, y, c % 16);
+ }
+
+ this.console.poke(a, b);
+ }
+
+ peek(a) {
+
+ if (this.console.getCharRomVisible()) {
+ if (a > 53247 && a < (53248 + 2048)) {
+ return this.console.charRomPeek(a - 53248)
+ }
+ }
+ else {
+ if (a > 53247 && a < 53295) {
+
+ return this.console.vpeek(a - 53248)
+
+ }
+ }
+
+
+ if (a > 1023 && a < 2024) {
+ var v = a - 1024;
+ var y = Math.floor(v / 40);
+ var x = v % 40;
+
+ return this.console.getChar(x, y);
+ }
+ else if (a > 55295 && a < 56296) {
+ var v = a - 55296;
+ var y = Math.floor(v / 40);
+ var x = v % 40;
+
+ return this.console.getCharCol(x, y);
+ }
+ else {
+ return this.console.peek(a);
+ }
+ }
+
+ pushKeyBuffer(k) {
+ this.kbBuffer.push(k);
+ }
+
+ pullKeyBuffer(k) {
+ if (this.kbBuffer.length > 0) {
+
+ return this.kbBuffer.shift();
+
+ }
+ return -1;
+ }
+
+ printError(s, supressLine, explicitline) {
+
+ if (explicitline) {
+ this.console.writeString(("?" + s + " error in " + explicitline).toUpperCase(), true);
+ return;
+ }
+ if (supressLine) {
+ this.console.writeString(("?" + s + " error").toUpperCase(), true);
+ return;
+ }
+ this.console.writeString(("?" + s + " error" + this.onLineStr()).toUpperCase(), true);
+
+ }
+
+ printInfo(s) {
+
+ this.console.writeString((s + this.onLineStr()).toUpperCase(), true);
+
+ }
+
+ printLine(s) {
+ this.sendChars(s.toUpperCase(), true);
+ this.reverseOn = false;
+ }
+
+ print(s) {
+ this.sendChars(s.toUpperCase(), false);
+ this.reverseOn = false;
+ }
+
+ spriteColor(s, c) {
+ var base = 53287 + s;
+
+ this.poke(base, c);
+
+ }
+
+
+ spritePos(s, x, y) {
+ var base = 53248 + (2 * s);
+
+ var lbx = x & 255;
+ var hbx = (x & 256) >> 8;
+
+ this.poke(base, lbx, true); //TODO most significant bit
+ var ohbx = this.peek(53264);
+ if (hbx > 0) {
+ this.poke(53264, ohbx | (1 << s), true); //TODO most significant bit
+ }
+ else {
+ this.poke(53264, ohbx & (255 - (1 << s)), true); //TODO most significant bit
+ }
+
+ this.poke(base + 1, y, true);
+
+ this.console.pokeFlush();
+
+ }
+
+ spriteFrame(s, f) {
+
+ var addr = 2040 + s;
+ this.poke(addr, f);
+
+ }
+
+ spriteFrameCopy(f1, f2) {
+ var baddr1 = f1 * 64;
+ var baddr2 = f2 * 64;
+
+ for (var i = 0; i < 64; i++) {
+ this.poke(baddr2 + i, this.peek(baddr1 + i));
+ }
+ }
+
+ spriteFrameSet(f1, data) {
+ var baddr1 = f1 * 64;
+
+ for (var i = 0; i < 64; i++) {
+
+ this.poke(baddr1 + i, data[i]);
+ }
+ }
+
+ spriteFrameGet(f1) {
+ var baddr1 = f1 * 64;
+ var data = [];
+
+ for (var i = 0; i < 64; i++) {
+ data.push(this.peek(baddr1 + i));
+ }
+
+ return data;
+ }
+
+ spriteFramePoke(f, a, v) {
+
+ var baddr = f * 64;
+ this.poke(baddr + (a % 64), v);
+
+ }
+
+ spriteDouble(s, xflag, yflag) {
+ var mask = 1 << s;
+ var old = this.peek(53277);
+ if (xflag == 1) {
+ this.poke(53277, old | mask);
+ }
+ else {
+ this.poke(53277, old & (255 - mask));
+ }
+
+ old = this.peek(53271);
+ if (yflag == 1) {
+ this.poke(53271, old | mask);
+ }
+ else {
+ this.poke(53271, old & (255 - mask));
+ }
+ }
+
+ spriteEnable(s, flag) {
+ var mask = 1 << s;
+ var old = this.peek(53269);
+ if (flag == 1) {
+ this.poke(53269, old | mask);
+ }
+ else {
+ this.poke(53269, old & (255 - mask));
+ }
+ }
+
+ spriteMultiCol(s, flag) {
+ var mask = 1 << s;
+ var old = this.peek(53276);
+ if (flag == 1) {
+ this.poke(53276, old | mask);
+ }
+ else {
+ this.poke(53276, old & (255 - mask));
+ }
+ }
+
+ clearScreen() {
+ this.console.clearScreen();
+ this.console.cursorHome();
+ }
+
+ setColorCellModified(x, y, col0, col1, col2) {
+ /*
+ Sets the 3 colors for a multicolor hires 8x8 cell
+ if the colors parameters are > -1
+ otherwise just set the modified flag on the color cell
+ so the pixel drawn in this color cell will be visible
+
+ col0 = low color in char ram
+ col1 = high color in char ram
+ col2 = color in color ram
+ */
+
+ if (col0 == -1 && col1 == -1 && col2 == -1) {
+ this.console.setCellModified(x, y);
+ return;
+ }
+
+ if (col0 > -1 && col1 > -1) {
+ this.console.setChar(x, y, col1 + (col0 * 16));
+ }
+ else if (col0 > -1 && col1 == -1) {
+
+ var charCol = this.console.getChar(x, y);
+ //var hiVal = (charCol & 240)>>4
+ var loVal = charCol & 15;
+ this.console.setChar(x, y, loVal + (col0 * 16));
+ }
+ else if (col0 == -1 && col1 > -1) {
+ var charCol = this.console.getChar(x, y);
+ var hiVal = (charCol & 240);
+ //var loVal = charCol & 15;
+ this.console.setChar(x, y, hiVal + col1);
+ }
+
+ if (col2 > -1) {
+ this.console.setCharCol(x, y, col2);
+ }
+
+ }
+
+ clearGFXScreen(col0, col1, col2) {
+
+ if (this.console.isBitMapMode()) {
+
+ var mem = this.console.getMemory();
+ var bmaddr = this.console.getBitmapAddress();
+
+ for (var i = 0; i < 8000; i++) {
+ mem[bmaddr + i] = 0;
+ }
+ }
+
+ for (var y = 0; y < 25; y++) {
+ for (var x = 0; x < 40; x++) {
+ this.setColorCellModified(
+ x, y, col0, col1, col2);
+ }
+ }
+ }
+
+ setCursor(x, y) {
+ this.console.setCursorX(x);
+ this.console.setCursorY(y);
+ }
+
+ setTextCol(x, y, col) {
+ this.poke(55296 + x + (y * 40), col);
+ }
+
+ drawLine(pointGen, x, y, x2, y2, colRecord, index) {
+
+ var points = pointGen.c[pointGen.m](x, y, x2, y2);
+
+ for (var i = 0; i < points.length; i++) {
+ var p = points[i];
+ this.setPixel(p.x, p.y, colRecord, index);
+ }
+
+ }
+
+ drawBox(x1, y1, x2, y2, colRecord, index) {
+
+ for (var x = x1; x <= x2; x++) {
+ for (var y = y1; y <= y2; y++) {
+ this.setPixel(x, y, colRecord, index);
+ }
+ }
+ }
+
+
+ setPixel(x, y, colRecord, index) {
+
+ if (!this.console.isBitMapMode()) { throw "@bitmap mode"; }
+
+ if (x < 0 || y > 0 || y > 199) {
+ if (x < 0) { throw "@pixel x<0"; }
+ else if (y < 0) { throw "@pixel y<0"; }
+ else if (y > 199) { throw "@pixel y>199"; }
+ }
+
+ if (this.console.isMultiColor()) {
+ if (x > 159) { throw "@pixel x>159"; }
+ this._setPixelMC(x, y, colRecord, index);
+ }
+ else {
+ if (x > 319) { throw "@pixel x>159"; }
+ this._setPixelMono(x, y, colRecord, index);
+ }
+ }
+
+ _setPixelMono(x, y, colRecord, index) {
+
+ var base = this.console.getBitmapAddress();
+ var colX = Math.floor(x >> 3);
+ var rowY = Math.floor(y >> 3); //>>3 == /8
+ var Xremainder = x - (colX << 3);
+ var Yremainder = y - (rowY << 3); //<<3 == *8
+
+ var byteAddr = base +
+ (colX * 8) +
+ (rowY * (40 * 8)) +
+ Yremainder;
+ var oldValue = this.peek(byteAddr);
+ var mask = Math.pow(2, 7 - Xremainder);
+ var newValue;
+ if (index == 1) {
+ newValue = oldValue | mask;
+
+ this.setColorCellModified(
+ colX, rowY, -1, colRecord.c1, -1);
+
+ }
+ else {
+ newValue = oldValue & (255 - mask);
+
+ this.setColorCellModified(
+ colX, rowY, colRecord.c0, -1, -1);
+ }
+
+ this.poke(byteAddr, newValue);
+
+ }
+
+ _setPixelMC(x, y, colRecord, index) {
+
+ var base = this.console.getBitmapAddress();
+ var colX = Math.floor(x >> 2); //>>2 == /4
+ var rowY = Math.floor(y >> 3); //>>3 == /8
+ var Xremainder = x - (colX << 2); //<<2 == *4
+ var Yremainder = y - (rowY << 3); //<<3 == *8
+
+ var byteAddr = base +
+ (colX * 8) +
+ (rowY * (40 * 8)) +
+ Yremainder;
+
+ var oldValue = this.peek(byteAddr);
+ var maskSubPix1 = Math.pow(2, 7 - (Xremainder * 2));
+ var maskSubPix2 = maskSubPix1 >> 1;
+ var newValue;
+ if (index == 1) {
+ newValue = oldValue & (255 - maskSubPix1);
+ newValue = newValue | maskSubPix2;
+
+ this.setColorCellModified(
+ colX, rowY, colRecord.c0, -1, -1);
+
+ }
+ else if (index == 2) {
+ newValue = oldValue | maskSubPix1;
+ newValue = newValue & (255 - maskSubPix2);
+
+ this.setColorCellModified(
+ colX, rowY, -1, colRecord.c1, -1);
+
+ }
+ else if (index == 3) {
+ newValue = oldValue | maskSubPix1;
+ newValue = newValue | maskSubPix2;
+
+ this.setColorCellModified(
+ colX, rowY, -1, -1, colRecord.c2);
+
+ }
+ else { //0
+ newValue = oldValue & (255 - maskSubPix1);
+ newValue = newValue & (255 - maskSubPix2);
+
+ this.setColorCellModified(
+ colX, rowY, -1, -1, -1);
+ }
+
+ this.poke(byteAddr, newValue);
+
+ }
+
+
+ getPixel(x, y, selector) {
+
+ if (!this.console.isBitMapMode()) { throw "@bitmap mode"; }
+
+ if (this.console.isMultiColor()) {
+ this._getPixelMC(x, y, selector);
+ }
+ else {
+ this._getPixelMono(x, y, selector);
+ }
+
+ }
+
+ _getPixelMono(x, y, selector) {
+
+ var base = this.console.getBitmapAddress();
+ var colX = Math.floor(x >> 3);
+ var rowY = Math.floor(y >> 3); //>>3 == /8
+ var Xremainder = x - (colX << 3);
+ var Yremainder = y - (rowY << 3); //<<3 == *8
+
+ var byteAddr = base +
+ (colX * 8) +
+ (rowY * (40 * 8)) +
+ Yremainder;
+ var oldValue = this.peek(byteAddr);
+ var mask = Math.pow(2, 7 - Xremainder);
+ var pixelValue = oldValue & (mask);
+
+ if ((selector === undefined) || selector == 0) {
+ if (pixelValue != 0) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+ }
+ else if (selector == 1) {
+ var charCol = this.console.getChar(colX, rowY);
+ var hiVal = (charCol & 240) >> 4
+ var loVal = charCol & 15;
+
+ if (pixelValue != 0) {
+ return loVal;
+ }
+ else {
+ return hiVal;
+ }
+ }
+
+ }
+
+ _getPixelMC(x, y, selector) {
+ //TODO
+ var base = this.console.getBitmapAddress();
+ var colX = Math.floor(x >> 2); //>>2 == /4
+ var rowY = Math.floor(y >> 3); //>>3 == /8
+ var Xremainder = x - (colX << 2); //<<2 == *4
+ var Yremainder = y - (rowY << 3); //<<3 == *8
+
+ var byteAddr = base +
+ (colX * 8) +
+ (rowY * (40 * 8)) +
+ Yremainder;
+
+ var xr2 = Xremainder * 2;
+ var byteValue = this.peek(byteAddr);
+ var maskSubPix1 = Math.pow(2, 7 - (xr2));
+ var maskSubPix2 = maskSubPix1 >> 1;
+ var shiftResultRight = 6 - xr2;
+ var pixelValue = byteValue & (maskSubPix1 + maskSubPix2);
+ var pixelValue2 = pixelValue >> shiftResultRight;
+
+
+ if ((selector === undefined) || selector == 0) {
+ return pixelValue2;
+ }
+ else if (selector == 1) {
+ if (pixelValue2 == 0) {
+ return this.peek(53281);
+ }
+ else if (pixelValue2 == 1 || pixelValue2 == 2) {
+ var charCol = this.console.getChar(colX, rowY);
+ var hiVal = (charCol & 240) >> 4
+ var loVal = charCol & 15;
+
+ if (pixelValue2 == 1) {
+ return loVal;
+ }
+ else if (pixelValue2 == 1) {
+ return hiVal;
+ }
+ }
+ else {
+ return this.console.getCharCol(colX, rowY);
+ }
+ }
+
+ }
+
+
+ setTextChar(x, y, c, col) {
+ this.poke(1024 + x + (y * 40), c);
+ if (col === undefined) {
+ return;
+ }
+ this.poke(55296 + x + (y * 40), col);
+ }
+
+ getTextChar(x, y) {
+ return this.peek(1024 + x + (y * 40));
+ }
+
+ getTextColor(x, y) {
+ return this.peek(55296 + x + (y * 40));
+ }
+
+ sendChars(s, newline) {
+
+ for (var i = 0; i < s.length; i++) {
+ var c = s.charCodeAt(i);
+
+ if (c < 32 || (c > 128 && c < 160)) {
+ var col = this.code2colMap[c];
+ if (!(col === undefined)) {
+ this.console.setColor(col);
+ }
+ else if (c == 0x12) {
+ //this.console.setColor(8); Set reverse
+
+ this.reverseOn = true;
+ }
+ else if (c == 0x92) {
+ //this.console.setColor(8); Set reverse
+ this.reverseOn = false;
+ }
+ else if (c == 0x13) {
+ this.console.cursorHome();
+ }
+ else if (c == 0x93) {
+ this.console.clearScreen()
+ }
+ else if (c == 29) {
+ var xy = this.console.getCursorPos();
+ if (xy[0] < 39) {
+ this.console.setCursorX(xy[0] + 1);
+ }
+ }
+ else if (c == 157) {
+ var xy = this.console.getCursorPos();
+ if (xy[0] > 0) {
+ this.console.setCursorX(xy[0] - 1);
+ }
+ }
+ else if (c == 17) {
+ var xy = this.console.getCursorPos();
+ if (xy[1] < 24) {
+ this.console.setCursorY(xy[1] + 1);
+ }
+ }
+ else if (c == 145) {
+ var xy = this.console.getCursorPos();
+ if (xy[1] > 0) {
+ this.console.setCursorY(xy[1] - 1);
+ }
+ }
+ }
+ else {
+ if (this.reverseOn) {
+ this.console.writeCharRev(String.fromCharCode(c));
+ }
+ else {
+ this.console.writeChar(String.fromCharCode(c));
+ }
+
+ }
+ }
+
+ if (newline) {
+ this.console.writeString("", true);
+ }
+ }
+
+ getLinePos() {
+ var xy = this.console.getCursorPos();
+ return xy[0];
+ }
+
+ sendCharsSimple(s, newline) {
+
+ for (var i = 0; i < s.length; i++) {
+ var c = s.charCodeAt(i);
+
+ if (this.reverseOn) {
+ this.console.writeCharRev(String.fromCharCode(c));
+ }
+ else {
+ this.console.writeChar(String.fromCharCode(c));
+ }
+ }
+
+ if (newline) {
+ this.console.writeString("", true);
+ }
+ }
+
+ setCursLongXPos(p) {
+ var c = this.console;
+ var x = this.console.getCursorX(p);
+ var start = x;
+
+ for (var i = start; i < p; i++) {
+ c.cursorShiftNextNoCallback();
+ }
+ }
+
+ setCursXPos(p) {
+ this.console.setCursorX(p);
+ }
+
+ resetVic() {
+ this.vpoke(53280, 14);
+ this.vpoke(53281, 6);
+ this.vpoke(53269, 0);
+ this.vpoke(53270, 200);
+ this.vpoke(53272, 21);
+ this.vpoke(53265, 155);
+ this.console.setColor(14);
+ }
+
+ getJiffyTime() {
+ var millis = new Date().getTime() - this.nullTime;
+ var jiffis = Math.floor(millis / (1000 / 60));
+
+ return jiffis % 5184000;
+ }
+
+ getTime() {
+ var millis = new Date().getTime() - this.nullTime;
+ millis = millis % 86400000;
+
+ var hours = Math.floor(millis / 3600000);
+ millis = millis - (hours * 3600000);
+ var minutes = Math.floor(millis / 60000);
+ millis = millis - (minutes * 60000);
+ var seconds = Math.floor(millis / 1000);
+ //millis = millis - (seconds * 1000 );
+ return [hours, minutes, seconds];
+ }
+
+ resetLineMarkers() {
+ this.lineMarkers = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+ }
+
+ reset(hard, muteReady) {
+ this.console.clearScreen();
+ this.vpoke(53280, 14);
+ this.vpoke(53281, 6);
+ this.vpoke(53269, 0);
+ this.vpoke(53270, 200);
+ this.vpoke(53272, 21);
+ this.vpoke(53265, 155);
+ this.console.setColor(14);
+ this.inputFlag = false;
+ this.runFlag = false;
+ this.listFlag = false;
+
+ this.clrPGM();
+
+ this.setTurbo(false);
+
+ this.printLine("");
+ if (hard) {
+ this.printLine(" **** c64 basic emulator v0.80p5 ****");
+ this.printLine("");
+ var ext = "off";
+ if (this.extendedcommands.enabled) ext = "on ";
+
+ var turbo = "off";
+ if (this.turboMode) turbo = "on ";
+
+ var panic = "off";
+ if (this.exitMode == "panic") panic = "on ";
+
+ this.printLine(" ext.: " + ext + " - turbo: " + turbo + " - panic: " + panic);
+ this.printLine("");
+ }
+ if (!muteReady) {
+ this.printLine("ready.");
+ }
+
+ this.resetLineMarkers();
+ this.updateYPos();
+ }
+
+ updateYPos() {
+ this.yPos = this.console.getCursorY();
+ }
+
+ showDebug() {
+ if (!this.showDebugFlag) {
+ this.debugChars = [];
+ this.debugCharsCol = [];
+ this.debugChars2 = [];
+ this.debugCharsCol2 = [];
+
+ var c = this.console;
+ c.clearCursor();
+
+ if (c.getCursorX() == 0) {
+ c.setCursorX(1);
+ }
+ if (c.getCursorY() == 0) {
+ c.setCursorY(1);
+ }
+
+ for (var y = 0; y < 25; y++) {
+ this.debugCharsCol[y] = this.console.getCharCol(0, y);
+ this.debugChars[y] = this.console.getChar(0, y);
+ this.console.setCharCol(0, y, this.lineMarkers[y]);
+ this.console.setChar(0, y, this.lineMarkers[y] + 48);
+ }
+
+ for (var x = 0; x < 40; x++) {
+ this.debugCharsCol2[x] = this.console.getCharCol(x, 0);
+ this.debugChars2[x] = this.console.getChar(x, 0);
+ this.console.setCharCol(x, 0, 1);
+ this.console.setChar(x, 0, 102);
+ }
+
+ //execution flag
+ this.console.setChar(0, 0, 5);
+ this.console.setChar(1, 0, this.executeLineFlag + 48);
+
+ //runflag
+ this.console.setChar(4, 0, 18);
+ this.console.setChar(5, 0, this.runFlag + 48);
+
+ //inputFlag
+ this.console.setChar(8, 0, 9);
+ this.console.setChar(9, 0, this.inputFlag + 48);
+
+ //listFlag
+ this.console.setChar(12, 0, 12);
+ this.console.setChar(13, 0, this.listFlag + 48);
+
+ this.showDebugFlag = true;
+ }
+ else {
+ this.hideDebug();
+
+ }
+ }
+
+
+ hideDebug() {
+
+ if (!this.showDebugFlag) { return; }
+
+ for (var x = 0; x < 40; x++) {
+ this.console.setCharCol(x, 0, this.debugCharsCol2[x]);
+ this.console.setChar(x, 0, this.debugChars2[x]);
+ }
+
+ for (var y = 0; y < 25; y++) {
+ this.console.setCharCol(0, y, this.debugCharsCol[y]);
+ this.console.setChar(0, y, this.debugChars[y]);
+ }
+
+ this.showDebugFlag = false;
+ }
+
+ getCurrentLine() {
+ this.updateYPos();
+
+ if (this.lineMarkers[this.yPos] == 0) {
+ var line0 = this.console.getCurrentLine();
+ return line0;
+ }
+ else if (this.lineMarkers[this.yPos] == 2) {
+ var line0 = this.console.getLine(this.yPos - 1)
+ var line1 = this.console.getLine(this.yPos);
+ console.log("l0>" + line0);
+ console.log("l1>" + line1);
+ return line0 + line1;
+ }
+ else if (this.lineMarkers[this.yPos] == 1) {
+ var line0 = this.console.getLine(this.yPos)
+ var line1 = this.console.getLine(this.yPos + 1);
+ console.log("l0>" + line0);
+ console.log("l1>" + line1);
+ return line0 + line1;
+ }
+ }
+
+ passEnter() {
+ //this.console.setCallbacks( this.consoleCallBacks );
+ this.hideDebug();
+ this.updateYPos();
+ if (this.lineMarkers[this.yPos] == 0 || this.lineMarkers[this.yPos] == 2) {
+ this.printLine("");
+ }
+ else if (this.lineMarkers[this.yPos] == 1) {
+ this.printLine("");
+ this.printLine("");
+ }
+
+
+ this.updateYPos();
+ //this.console.clearCallbacks();
+ }
+ passDeleteChar() {
+ this.hideDebug();
+ this.console.deleteChar(); this.updateYPos();
+ }
+
+ cbLineOverFlow() {
+
+ this.updateYPos();
+
+ if (this.yPos < 24) {
+ if (this.lineMarkers[this.yPos] == 0) {
+ for (var y = 23; y > this.yPos; y--) {
+ this.lineMarkers[y + 1] = this.lineMarkers[y];
+ this.lineCopy(y, y + 1);
+ }
+ this.lineMarkers[this.yPos] = 1;
+ this.lineMarkers[this.yPos + 1] = 2;
+ }
+ }
+ else {
+
+ for (var y = 0; y < 24; y++) {
+ this.lineMarkers[y] = this.lineMarkers[y + 1];
+ }
+ this.lineMarkers[23] = 1;
+ this.lineMarkers[24] = 2;
+ }
+ }
+
+ lineCopy(src, dst) {
+ var c = this.console;
+ var ls = [], lsc = [];
+ for (var x = 0; x < 40; x++) {
+ var ch = c.getChar(x, src);
+ var co = c.getCharCol(x, src);
+
+ c.setChar(x, dst, ch);
+ c.setCharCol(x, dst, co);
+ }
+ }
+
+ cbClearScreen() {
+
+ for (var y = 0; y <= 24; y++) {
+ this.lineMarkers[y] = 0;
+ }
+
+ }
+
+ cbScroll() {
+
+ for (var y = 0; y < 24; y++) {
+ this.lineMarkers[y] = this.lineMarkers[y + 1];
+ }
+
+ this.lineMarkers[24] = 0;
+ this.lineMarkers[0] = 0;
+ }
+
+ passPetsciiChar(pC) {
+
+ this.hideDebug();
+ var xy = this.console.writePetsciiChar(pC);
+
+ }
+
+ passChars(chs, nl) {
+
+ this.hideDebug();
+ var xy = this.sendChars(chs, nl);
+
+ }
+
+ passString(x) {
+
+ this.hideDebug();
+ var xy = this.console.writeString(x);
+
+ }
+
+ setEditModeCallBacks(type) {
+ if (type == "edit") {
+ this.console.setCallbacks(this.consoleCallBacksAll);
+
+ }
+ else if (type == "print") {
+ this.console.setCallbacks(this.consoleCallBacksClScr);
+
+ }
+ else {
+ this.console.clearCallbacks();
+ }
+ }
+
+ clearScreen() {
+ this.console.clearScreen();
+
+ }
+
+ compressPGMText(pgmTxt) {
+
+ var p = new Parser(this.commands, this.extendedcommands);
+ p.init();
+ var kws = p.getKeyWordCodes();
+ var txt2 = pgmTxt;
+
+ for (var i = 0; i < kws.length; i++) {
+ var kw = kws[i];
+ if (!(kw === undefined || kw === null)) {
+ txt2 = txt2.replaceAll(kw.toLowerCase(), String.fromCharCode(i));
+ }
+ }
+
+ return txt2;
+ }
+
+
+ getProgramAsTextNoPETSCII() {
+ var text = "";
+ for (const l of this.program) {
+ if (text != "") {
+ text += "\n";
+ }
+ text += this.prepareLineForExportNoPETSCII(l[2].trim(), true);
+ }
+ return text;
+ }
+
+
+ getProgramAsText() {
+ var text = "";
+ for (const l of this.program) {
+ if (text != "") {
+ text += "\n";
+ }
+ text += this.prepareLineForExport(l[2].trim());
+ }
+ return text;
+ }
+
+ prepareLineForExport(txt0) {
+ var txt;
+ txt = txt0.trim();
+ var dst = "";
+
+ for (var i = 0; i < txt.length; i++) {
+ var c = txt.charCodeAt(i);
+ if (c < 31 || c == 92 || c >= 94) {
+ var symdef = this.symbolTableBM[c];
+ if (!(symdef === undefined)) {
+ dst += "{" + symdef + "}";
+ }
+ else {
+ dst += "{" + c + "}"
+ }
+
+ }
+ else {
+ dst += txt.charAt(i);
+ }
+ }
+ return dst.toLowerCase();
+ }
+
+ replaceAll(src, str1, str2) {
+
+ var rv = src;
+ while (rv.indexOf(str1) > -1) {
+ rv = rv.replace(str1, str2);
+ }
+ return rv;
+ }
+
+
+ rebuildNoPETSCIILineString(raw) {
+
+ var p = new Parser(this.commands, this.extendedcommands);
+ p.init();
+ var noPetsciiLine = this.prepareLineForExportNoPETSCII(raw, false);
+ var rec = p.parseLine(noPetsciiLine);
+ return rec;
+ }
+
+
+ prepareLineForExportNoPETSCII(txt0, toLower) {
+ var txt;
+ txt = txt0.trim();
+ var dst = "";
+ var last = "";
+
+ for (var i = 0; i < txt.length; i++) {
+ var c = txt.charCodeAt(i);
+ var cc = txt.charAt(i);
+ if (c < 31 || c == 92 || c >= 94) {
+
+ var prevCharIsQuote = false, nextCharIsQuote = false;
+ if ((i + 1) < txt.length) {
+ var cc2 = txt.charAt(i + 1);
+ if (cc2 == "\"") {
+ nextCharIsQuote = true;
+ }
+ }
+ if (last == "\"") {
+ prevCharIsQuote = true;
+ }
+
+ //
+ //7 print"{home}{white}":print spc(9);"game over sc:";s;" top:";tp:ifs>tpthentp=s
+ //
+ if (prevCharIsQuote && !nextCharIsQuote) {
+ dst = dst.substr(0, dst.length - 1);
+ dst += "CHR$(" + c + ");\"";
+ }
+ else if (prevCharIsQuote && nextCharIsQuote) {
+ dst = dst.substr(0, dst.length - 1);
+ dst += "CHR$(" + c + ")";
+ i++;
+ }
+ else if (!prevCharIsQuote && nextCharIsQuote) {
+ dst += "\";CHR$(" + c + ")";
+ i++;
+ }
+
+ else {
+ dst += "\";CHR$(" + c + ");\"";
+ }
+ }
+ else {
+ dst += txt.charAt(i);
+ }
+ last = cc;
+ }
+
+ var dst2 = this.replaceAll(dst, ";\"\";", ";");
+
+ if (toLower) { return dst2.toLowerCase(); }
+ return dst2;
+ }
+
+ ResolveStringSymbolToCode(x) {
+
+ if (this.symbolTable[x]) {
+ return this.symbolTable[x];
+ }
+
+ return x;
+ }
+
+
+ prepareLineForImport(txt0) {
+ var txt;
+ txt = txt0.trim().toUpperCase();
+ var dst = "";
+
+ var i = 0; while (i < txt.length) {
+ var c = txt.charCodeAt(i);
+ if (c == 123) {
+ i++;
+ var num = "";
+ while (i < txt.length) {
+ c = txt.charCodeAt(i);
+ if (c == 125) {
+ i++;
+ break;
+ }
+ num += String.fromCharCode(c);
+
+ if (this.debugFlag) {
+ console.log("found ESC seq char " + String.fromCharCode(c));
+ console.log("found ESC seq char code " + c);
+ }
+ i++;
+ }
+
+ if (this.debugFlag) {
+ console.log("found ESC seq " + num);
+ }
+
+ num = this.ResolveStringSymbolToCode(num.toLowerCase());
+
+ if (this.debugFlag) {
+ console.log("found resolved ESC seq " + num);
+ }
+
+ dst += String.fromCharCode(parseInt(num, 10));
+ }
+ else if (c == 8221 || c == 8220) { //looks like a double quote
+ dst += "\"";
+ i++;
+ }
+ else {
+ dst += txt.charAt(i);
+ i++;
+ }
+ }
+
+ /*
+ escape 0-31
+ escape 92
+ escape 94 - 255
+ {} 123 + 125
+ */
+ if (this.debugFlag) {
+ console.log("dst:" + dst);
+ }
+
+ return dst;
+ }
+
+ getProgramLines() {
+
+ return this.program;
+ }
+
+ padZeros2(x) {
+ var s = x + "";
+ for (var i = s.length; i < 2; i++) {
+ s = "0" + s;
+ }
+ return s;
+ }
+
+ evalExpressionPart(p) {
+ var val = 0;
+
+ if (p.type == "num") {
+ if (p.data == ".") {
+ val = 0;
+ }
+ else if (p.data == "~") {
+ val = Math.PI;
+ }
+ else if (("" + p.data).indexOf(".") >= 0) {
+ val = parseFloat(p.data);
+ }
+ else {
+ val = parseInt(p.data);
+ }
+ }
+ else if (p.type == "str") {
+ val = p.data;
+ }
+ else if (p.type == "var") {
+ if (p.data.startsWith("TI")) {
+ val = this.getJiffyTime();
+ if (p.data.endsWith("$")) {
+ val = this.getTime();
+ val = "" +
+ this.padZeros2(val[0]) +
+ this.padZeros2(val[1]) +
+ this.padZeros2(val[2]);
+ }
+ }
+ else {
+ val = this.vars[p.data];
+ }
+ if (val == undefined) {
+ val = 0;
+ }
+ }
+ else if (p.type == "array") {
+ var varIntName = "@array_" + p.data;
+ var arr = this.vars[varIntName];
+
+ if (arr === undefined) {
+ throw "@no such array";
+ }
+
+ if (arr.getIndexCount() != p.indices.length) {
+ throw "@bad subscript";
+ }
+
+ var indices = [];
+ for (var ai = 0; ai < p.indices.length; ai++) {
+ indices[ai] = this.evalExpression(p.indices[ai]);
+ }
+
+ val = arr.get(indices);
+ if (val === undefined) {
+ val = 0;
+ }
+
+ }
+ else if (p.type == "expr") {
+ val = this.evalExpression(p);
+ }
+ else if (p.type == "funCall") {
+
+ var values = [];
+ for (var j = 0; j < p.params.length; j++) {
+ var par = this.evalExpression(p.params[j]);;
+ values.push({ value: par });
+ }
+ try {
+ var commands = this.commands;
+ var ecommands = this.extendedcommands;
+ var cmds = this.commands;
+
+ var nFunName = "_fun_" + p.functionName.toLowerCase().replace("$", "_DLR_");
+
+ var stc = commands[nFunName];
+ if (stc === undefined) {
+
+ stc = ecommands[nFunName];
+
+ if (stc === undefined) {
+
+ stc = ecommands[nFunName];
+
+ this.printError("no such function " + p.functionName);
+ console.log("Cannot find functionName " + nFunName);
+
+ throw "@no such function " + p.functionName;
+
+ }
+ else {
+ cmds = ecommands;
+ }
+ }
+
+ val = cmds[nFunName](values);
+
+ }
+ catch (e) {
+ throw e;
+ }
+ }
+ else if (p.type == "defFnCall") {
+
+ try {
+ var fName = p.functionName;
+ var parValue = this.evalExpression(p.params[0]);
+ var restore = null;
+
+ if (this.functions[fName] === undefined) {
+ throw "@undef'd function";
+ }
+ var functRecord = this.functions[fName];
+
+ if (!(this.vars[functRecord.par] === undefined)) {
+ restore = this.vars[functRecord.par];
+ }
+
+ this.vars[functRecord.par] = parValue;
+ val = this.evalExpression(functRecord.expr);
+
+ if (restore != null) {
+ this.vars[restore.name] = restore;
+ }
+ else {
+ this.vars[functRecord.par] = 0; //TODO, actually should delete it
+ }
+
+ }
+ catch (e) {
+ throw e;
+ }
+ }
+
+ return val;
+ }
+
+ evalExpression(expr) {
+
+ if (expr == null) {
+ return null;
+ }
+
+ if (expr.parts.length == 0) {
+ return null;
+ }
+
+ var val = this.evalExpressionPart(expr.parts[0]);
+
+ for (var i = 1; i < expr.parts.length; i++) {
+ var p = expr.parts[i];
+ if (p.op == "+") {
+ val += this.evalExpressionPart(p);
+ }
+ else if (p.op == "^") {
+ val = Math.pow(val, this.evalExpressionPart(p));
+ }
+ else if (p.op == "-") {
+ val -= this.evalExpressionPart(p);
+ }
+ else if (p.op == "*") {
+ val *= this.evalExpressionPart(p);
+ }
+ else if (p.op == "/") {
+ if (this.evalExpressionPart(p) == 0) {
+ throw "@division by zero";
+ }
+ val /= this.evalExpressionPart(p);
+ }
+ else if (p.op == ";") {
+ val += ("" + this.evalExpressionPart(p));
+ }
+ else if (p.op == "OR") {
+ val |= this.evalExpressionPart(p);
+ }
+ else if (p.op == "AND") {
+ val &= this.evalExpressionPart(p);
+ }
+ else if (p.op == "<") {
+ if (val < (this.evalExpressionPart(p))) {
+ val = -1;
+ } else {
+ val = 0;
+ }
+ }
+ else if (p.op == ">") {
+ if (val > (this.evalExpressionPart(p))) {
+ val = -1;
+ } else {
+ val = 0;
+ }
+ }
+ else if (p.op == "=") {
+ if (val == (this.evalExpressionPart(p))) {
+ val = -1;
+ } else {
+ val = 0;
+ }
+ }
+ else if (p.op == "<>") {
+ if (val != (this.evalExpressionPart(p))) {
+ val = -1;
+ } else {
+ val = 0;
+ }
+ }
+ else if (p.op == "<=") {
+ if (val <= (this.evalExpressionPart(p))) {
+ val = -1;
+ } else {
+ val = 0;
+ }
+ }
+ else if (p.op == ">=") {
+ if (val >= (this.evalExpressionPart(p))) {
+ val = -1;
+ } else {
+ val = 0;
+ }
+ }
+
+ else {
+ throw "@unknown op '" + p.op + "'";
+ }
+ }
+
+ if (expr.negate) {
+ return -val;
+ }
+ if (expr.binaryNegate) {
+ if (val == 0) {
+ return -1;
+ }
+ return 0;
+ }
+ return val;
+ }
+
+
+ panicIfStopped() {
+ if (!this.runFlag && this.exitMode == "panic") {
+
+ var bitmap = this.console.isBitMapMode();
+ this.resetVic();
+
+ if (bitmap) {
+ this.setCursor(0, 22);
+ this.printLine("");
+ this.printLine("");
+ this.printLine("");
+ }
+ }
+ }
+
+ exitInputState() {
+ var c = this.console;
+ var p = this.program;
+
+ this.inputFlag = false;
+
+
+ var l = this.program[this.runPointer];
+ var cmds = l[1];
+ //console.log(cmds);
+
+
+ if (this.runPointer > -1) {
+
+ var l = this.program[this.runPointer];
+ //console.log( l[0] + "after input >>(" + this.runPointer + ":" + this.runPointer2 +")");
+ }
+
+ this.runPointer2++;
+
+ if (this.runPointer > -1) {
+
+ var l = this.program[this.runPointer];
+ //console.log( l[0] + "after input >>>(" + this.runPointer + ":" + this.runPointer2 +")");
+ }
+
+ if (this.runPointer2 >= cmds.length) {
+
+
+ this.runPointer2 = 0;
+ this.runPointer++;
+
+ if (this.runPointer > -1) {
+
+ var l = this.program[this.runPointer];
+ //console.log( l[0] + "after input >>>>(" + this.runPointer + ":" + this.runPointer2 +")");
+ }
+
+
+ if (this.runPointer >= p.length) {
+
+ if (this.runPointer > -1) {
+
+ var l = this.program[this.runPointer];
+ //console.log( l[0] + "after input >>>>>(" + this.runPointer + ":" + this.runPointer2 +")");
+ }
+
+ this.runFlag = false;
+
+ this.panicIfStopped();
+ c.clearCursor();
+ this.printLine("");
+ this.printLine("ready.");
+ }
+
+ }
+
+
+ }
+
+ breakCycle() {
+ this.breakCycleFlag = true;
+ }
+
+ cycle() {
+
+ /*return values*/
+ var END_W_ERROR = 0;
+ var TERMINATE_PROGRAM = -1;
+ var LINE_FINISHED = 10;
+ var MIDLINE_INTERUPT = 20;
+ var TERMINATE_W_JUMP = 30;
+ var PAUSE_F_INPUT = 40;
+
+ var c = this.console;
+
+ var cmdCount = this.cmdCountPerCycle;
+
+
+ try {
+
+ if (!this.runFlag ||
+ this.menuFocus ||
+ this.inputFlag ||
+ this.listFlag
+ ) {
+
+ if (this.listFlag) {
+ if (this.listPointer < this.list.length) {
+ this.listCodeLine(this.list[this.listPointer]);
+ this.listPointer++;
+ }
+ else {
+ this.listFlag = false;
+ this.printLine("ready.");
+ }
+
+ }
+ if (this.cursorCount++ > this.cursorCountMax) {
+ this.cursorCount = 0;
+
+ if (!this.menuFocus && !this.listFlag) {
+ c.blinkCursor();
+ }
+ }
+ }
+ else {
+
+ if (this.debugFlag) console.log("START CYCLE------------------------------");
+
+ var p = this.program;
+
+ while (true) {
+
+ if (this.breakCycleFlag) {
+ this.breakCycleFlag = false;
+ break;
+ }
+ if (this.debugFlag) console.log("START CYCLE LOOP-------------");
+ var l = p[this.runPointer];
+ var bf = this.runPointer2;
+ if (this.debugFlag) console.log(" this.runPointer = " + this.runPointer, " this.runPointer2 = " + this.runPointer2);
+ if (this.debugFlag) console.log(" cmdCount = " + cmdCount);
+
+ /****************************
+ *
+ The actual execution of commands is done by the command below
+ *
+ ****************************/
+ var rv = this.runCommands(l[1], cmdCount);
+
+
+
+ var af = rv[1];
+
+ if (rv[0] == MIDLINE_INTERUPT) {
+ this.runPointer2 = af;
+ }
+
+ var executedCount = rv[2];
+
+ if (this.debugFlag) console.log(" bf = " + bf, " af = " + af);
+ if (this.debugFlag) console.log(" executedCount = " + executedCount);
+ if (this.debugFlag) console.log(" rv = " + rv);
+
+ cmdCount = cmdCount - executedCount;
+
+ if (rv[0] <= 0) {
+ if (this.debugFlag) console.log(" PGM END!!!!");
+ this.runFlag = false;
+ this.printLine("");
+ this.printLine("ready.");
+ this.panicIfStopped();
+ if (rv[0] == END_W_ERROR) {
+ var e = null;
+ if (rv.length >= 4) {
+ e = rv[3];
+ }
+ console.log("ERROR: ", e, " LINE ", this.retreiveRuntimeLine());
+ console.log("PARAMETER DUMP:", this.vars);
+ console.log("FUNCTION DUMP:", this.functions);
+ }
+ if (this.debugFlag) console.log("CYCLE RETURN END");
+ return;
+ }
+ else if (rv[0] == LINE_FINISHED) {
+ this.runPointer++;
+ this.runPointer2 = 0;
+ if (this.debugFlag) console.log(" new this.runPointer = " + this.runPointer, " this.runPointer2 = " + this.runPointer2);
+
+ if (this.runPointer >= p.length) {
+ if (this.debugFlag) console.log("end program");
+ this.runFlag = false;
+ this.panicIfStopped();
+ c.clearCursor();
+ this.printLine("ready.");
+ break;
+ }
+ }
+ else if (rv[0] == TERMINATE_W_JUMP) {
+
+ if (this.debugFlag) console.log(" jump to new this.runPointer = " + this.runPointer, " this.runPointer2 = " + this.runPointer2);
+
+ }
+ else if (rv[0] == PAUSE_F_INPUT) {
+
+ this.runPointer2 = af;
+ //console.log("CYCLE PAUSE 4 INPUT");
+ //console.log("CYCLE PAUSE 4 INPUT" + this.runPointer + "," + this.runPointer2);
+ if (this.debugFlag) console.log("CYCLE PAUSE 4 INPUT" + this.runPointer + "," + this.runPointer2);
+ break;
+
+ }
+
+ if (cmdCount <= 0) {
+ if (this.debugFlag) console.log("Breaking cmdCount=" + cmdCount)
+ break;
+ }
+
+ }
+
+ if (this.debugFlag) console.log(" this.runPointer = " + this.runPointer, " this.runPointer2 = " + this.runPointer2);
+
+ }
+
+ }
+ catch (e) {
+ c.clearCursor();
+
+ if (this.erh.isSerializedError(e)) {
+ var err = this.erh.fromSerializedError(e);
+ this.printError(err.clazz);
+ }
+ else {
+ this.printError("unexpected");
+ }
+
+ this.printLine("ready.");
+ this.runFlag = false;
+ this.panicIfStopped();
+ console.log("ERROR: ", e, " LINE ", this.retreiveRuntimeLine());
+ console.log("PARAMETER DUMP:", this.vars);
+ console.log("FUNCTION DUMP:", this.functions);
+
+ }
+
+
+
+ }
+
+ doReturn() {
+
+ var oldPointers = this.gosubReturn.pop();
+ if (oldPointers === undefined) {
+ throw "@return without gosub";
+ }
+
+ this.runPointer2 = oldPointers[1];
+ this.runPointer = oldPointers[0];
+
+ //this.goto( oldLine );
+ }
+
+ gosub(line, runPointer2) {
+
+ var pgm = this.program;
+ var len = this.program.length;
+ var retLine = null;
+ var retCmd = null;
+
+ this.runPointer2 = runPointer2;
+
+ if ((this.runPointer2 + 1) < this.program[this.runPointer][1].length) {
+ retCmd = this.runPointer2 + 1;
+ retLine = this.runPointer;
+ }
+ else {
+ if ((this.runPointer + 1) < len) {
+ retCmd = 0;
+ retLine = this.runPointer + 1;
+ }
+ else {
+ retCmd = 9999;
+ retLine = this.runPointer;
+ }
+ }
+
+ this.gosubReturn.push([retLine, retCmd]);
+ this.goto(line);
+ }
+
+ goto(line) {
+
+ var pgm = this.program;
+ var len = this.program.length;
+ var found = false;
+
+ for (var i = 0; i < len; i++) {
+ var l = pgm[i];
+
+ if (l[0] == line) {
+ this.runPointer = i;
+ this.runPointer2 = 0;
+ found = true;
+ }
+ }
+
+ if (!found) {
+ throw "@undef'd statement";
+ }
+
+ if (!this.runFlag) {
+ this.startAsGoto = true;
+ this.runPGM();
+ }
+ }
+
+ listStop() {
+ if (this.listFlag) {
+ var c = this.console;
+ this.listFlag = false;
+ c.clearCursor();
+ this.printLine("ready.");
+ }
+ }
+
+ runStop() {
+ if (this.runFlag) {
+ var c = this.console;
+ this.runFlag = false;
+ this.panicIfStopped();
+ c.clearCursor();
+
+ console.log("break in " + this.program[this.runPointer][0]);
+ this.printLine("break in " + this.program[this.runPointer][0]);
+ this.printLine("ready.");
+ }
+ }
+
+ isRunning() {
+ return this.runFlag;
+ }
+
+ isListing() {
+ return this.listFlag;
+ }
+
+ isInput() {
+ return this.inputFlag;
+ }
+
+ readData() {
+
+ if (this.dataPointer >= this.data.length) {
+ return undefined;
+ }
+
+ var result = this.data[this.dataPointer];
+ this.dataPointer++;
+
+ return result;
+ }
+
+ printLineVisibleChars(rawLine) {
+
+ for (var i = 0; i < rawLine.length; i++) {
+
+ var c = rawLine.charAt(i);
+
+ this.sendCharsSimple(c, false);
+
+ }
+ this.printLine("");
+ }
+
+
+
+ listCodeLine(rawLine) {
+
+ var inString = false;
+ for (var i = 0; i < rawLine.length; i++) {
+
+ var c = rawLine.charAt(i);
+
+ if (!inString) {
+ this.sendChars(c, false);
+ }
+ else {
+ this.sendCharsSimple(c, false);
+ }
+
+ if (c == "\"") {
+ inString = !inString;
+ }
+ }
+ this.printLine("");
+
+ }
+
+ rebuildLineString(nr, raw,
+ removePadding,
+ renumbering,
+ addSmartPadding,
+ shortenKeywords) {
+
+ var p = new Parser(this.commands, this.extendedcommands);
+ p.init();
+
+ var tokens = p.getTokens(raw, false, false);
+ tokens = p.mergeBrokenUpTokens(tokens);
+
+ if (!(renumbering === undefined)) {
+
+ var foundGoto = false;
+ for (i = 0; i < tokens.length; i++) {
+ if (tokens[i].type == "name" && (tokens[i].data == "GOTO" || tokens[i].data == "GOSUB")) {
+ foundGoto = true;
+ } else {
+ if (i > 1) {
+ if (tokens[i].type == "num" &&
+ tokens[i - 1].type == "pad" &&
+ tokens[i - 2].type == "name" && tokens[i - 2].data == "THEN") {
+ foundGoto = true;
+ }
+ else if (tokens[i].type == "num" && tokens[i - 1].type == "name" && tokens[i - 1].data == "THEN") {
+ foundGoto = true;
+ }
+ }
+ }
+
+ if (tokens[i].type == "num" && foundGoto) {
+ var newLine = renumbering["old_" + tokens[i].data];
+ if (newLine == undefined) { newLine = 99999; }
+ tokens[i].data = newLine;
+ foundGoto = false;
+ }
+ }
+ }
+ tokens[0].data = nr;
+ var newString;
+
+ newString = nr;
+ if (removePadding) {
+ newString = nr + " ";
+ }
+ for (var i = 1; i < tokens.length; i++) {
+ if (removePadding) {
+ if (tokens[i].type == "pad") {
+ continue;
+ }
+ }
+
+ if (shortenKeywords) {
+ if (tokens[i].type == "name" && tokens[i].data == "PRINT") {
+ tokens[i].data = "?";
+ }
+ }
+ else {
+ if (tokens[i].type == "name" && tokens[i].data == "?") {
+ tokens[i].data = "PRINT";
+ }
+ }
+
+ if (tokens[i].type == "str") {
+ newString += "\"" + tokens[i].data + "\"";
+ }
+ else if (tokens[i].type == "name" && addSmartPadding == true) {
+ newString += tokens[i].data + " ";
+ }
+ else if (tokens[i].type == "num" && addSmartPadding == true) {
+ if (tokens[i].data.length == 1) {
+ newString += " " + tokens[i].data;
+ }
+ else {
+ newString += tokens[i].data;
+ }
+ }
+ else {
+ newString += tokens[i].data;
+ }
+
+ }
+
+ var rec = p.parseLine(newString);
+
+ return rec;
+ }
+
+ lineIsData(line) {
+ console.log(line);
+ if (line[1].length == 1) {
+ if (!(line[1][0].controlKW === undefined)) {
+ if (line[1][0].controlKW.toUpperCase() == "DATA") {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ lineIsRem(line) {
+ console.log(line);
+ if (line[1].length == 1) {
+ if (!(line[1][0].controlKW === undefined)) {
+ if (line[1][0].controlKW.toUpperCase() == "REM") {
+ var remIndex = line[2].indexOf("REM");
+ if (remIndex == -1) { console.log("warning: invalid rem statement on line " + line[0]); return false; }
+
+ var checkline = line[2].substring(remIndex + 3).trim();
+ if (checkline.startsWith("-")) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ renumberProgram(start, gap) {
+
+ var p = this.program;
+
+ var newLineNr = start;
+ var renumbering = {};
+ var lineNumbers = [];
+
+ var method = this.renumMode;
+
+ if (method == "plain") {
+ for (var i = 0; i < p.length; i++) {
+ var line = p[i];
+
+ renumbering["old_" + line[0]] = newLineNr;
+ lineNumbers.push(newLineNr);
+ newLineNr += gap;
+ }
+ }
+ else if (method == "data") {
+ // non data
+ for (var i = 0; i < p.length; i++) {
+ var line = p[i];
+ var data = this.lineIsData(line);
+
+ if (data) {
+ continue;
+ }
+ else {
+ renumbering["old_" + line[0]] = newLineNr;
+ lineNumbers.push(newLineNr);
+ newLineNr += gap;
+ }
+ }
+
+ //data
+ var kNumber = Math.ceil(newLineNr / 1000);
+ var newLineNr2 = 1000 * (kNumber);
+ if (newLineNr2 - newLineNr < 100) {
+ newLineNr2 += 1000;
+ }
+ newLineNr = newLineNr2;
+
+ for (var i = 0; i < p.length; i++) {
+ var line = p[i];
+ var data = this.lineIsData(line);
+
+ if (!data) {
+ continue;
+ }
+ else {
+ renumbering["old_" + line[0]] = newLineNr;
+ lineNumbers.push(newLineNr);
+ newLineNr += gap;
+ }
+ }
+
+ }
+ else if (method == "rem") {
+ // non data
+ for (var i = 0; i < p.length; i++) {
+ var line = p[i];
+ var rem = this.lineIsRem(line);
+
+ if (rem) {
+ var kNumber = Math.ceil(newLineNr / 1000);
+ var newLineNr2 = 1000 * (kNumber);
+ if (newLineNr2 - newLineNr < 100) {
+ newLineNr2 += 1000;
+ }
+ newLineNr = newLineNr2;
+ }
+ renumbering["old_" + line[0]] = newLineNr;
+ lineNumbers.push(newLineNr);
+ newLineNr += gap;
+
+ }
+
+ }
+
+ //newLineNr = start;
+ for (var i = 0; i < p.length; i++) {
+ newLineNr = lineNumbers[i]
+ var line = p[i];
+ var lRec = this.rebuildLineString(newLineNr, line[2], true, renumbering, true);
+
+ line[0] = newLineNr;
+ line[1] = lRec.commands;
+ line[2] = lRec.raw.trim();
+
+ //newLineNr += gap;
+ }
+ }
+
+ PETSCIIreplace(keywordCompress) {
+ var p = this.program;
+
+ for (var i = 0; i < p.length; i++) {
+ var line = p[i];
+
+ var lRec = this.rebuildNoPETSCIILineString(line[2]);
+
+ line[1] = lRec.commands;
+ line[2] = lRec.raw;
+
+ }
+ }
+
+ compressProgram(keywordCompress) {
+ var p = this.program;
+
+ for (var i = 0; i < p.length; i++) {
+ var line = p[i];
+
+ var lRec = this.rebuildLineString(line[0], line[2], true, undefined, false, keywordCompress);
+
+ line[1] = lRec.commands;
+ line[2] = lRec.raw;
+
+ }
+ }
+
+ normalizeProgram() {
+ var p = this.program;
+
+ for (var i = 0; i < p.length; i++) {
+ var line = p[i];
+
+ var lRec = this.rebuildLineString(line[0], line[2], true, undefined, true);
+
+ line[1] = lRec.commands;
+ line[2] = lRec.raw;
+
+ }
+ }
+
+ clrPGM() {
+ this.vars = [];
+ this.functions = [];
+ this.restoreDataPtr();
+ }
+
+ restoreDataPtr() {
+ this.dataPointer = 0;
+ }
+
+ runPGM() {
+
+ this.executeLineFlag = false;
+
+ if (this.startAsGoto) {
+ this.startAsGoto = false;
+
+ var bak1 = this.runPointer;
+ var bak2 = this.runPointer2;
+
+ this.runPGM();
+
+ this.runPointer = bak1;
+ this.runPointer2 = bak2;
+
+
+ return;
+ }
+
+
+ var c = this.console;
+ var p = this.program;
+ this.data = [];
+ this.dataPointer = 0;
+ this.gosubReturn = [];
+ this.vars = [];
+ this.functions = [];
+
+ for (var i = 0; i < p.length; i++) {
+
+ var line = p[i];
+ var commands = line[1];
+
+ for (var j = 0; j < commands.length; j++) {
+
+ var command = commands[j];
+
+ if (command.type == "control" && command.controlKW == "data") {
+ for (var k = 0; k < command.params.length; k++) {
+ this.data.push(command.params[k]);
+ }
+ }
+ }
+ }
+
+ if (this.debugFlag) {
+ console.log("data dump:", this.data);
+ }
+
+
+ if (this.program.length > 0) {
+ this.runFlag = true;
+ this.inputFlag = false;
+ c.clearCursor();
+ this.runPointer = 0;
+ this.runPointer2 = 0;
+ }
+ }
+
+
+ doForInit(from, to, step, varName, cmdPointer, cmdArrayLen, linePointersLen) {
+
+ var ctx = this.forContext;
+
+ if (this.vars[varName] === undefined) {
+ this.vars[varName] = 0;
+ }
+ this.vars[varName] = this.evalExpression(from);
+
+ ctx.default.push(varName);
+ ctx[varName] = {};
+
+ var ctxv = ctx[varName];
+ ctxv.to = this.evalExpression(to);
+
+ if (step == null) {
+ ctxv.step = 1;
+ }
+ else {
+ ctxv.step = this.evalExpression(step);
+ }
+
+ ctxv.jumpTo =
+ {
+ line: this.runPointer,
+ cmdPointer: cmdPointer + 1
+ }
+ if (ctxv.jumpTo.cmdPointer >= cmdArrayLen) {
+
+ if (this.runPointer == -1) {
+ throw "@Cannot find command after for";
+ }
+ else {
+ if ((this.runPointer + 1) >= linePointersLen) {
+ throw "@cannot find command after for, on next line";
+ }
+ ctxv.jumpTo.line++;
+ ctxv.jumpTo.cmdPointer = 0;
+ }
+ }
+
+ }
+
+ doForNext(nextVarName) {
+ var ctx = this.forContext;
+ if (ctx.default.length == 0) {
+ throw "@next without for";
+ }
+ var varName = ctx.default[ctx.default.length - 1];
+ if (nextVarName != null) {
+ varName = nextVarName;
+ }
+
+ var ctxv = ctx[varName];
+
+ this.vars[varName] += ctxv.step;
+ if (ctxv.step > 0) {
+ if (this.vars[varName] <= ctxv.to) {
+
+ return ctxv.jumpTo;
+ }
+ }
+ else if (ctxv.step == 0) {
+ return ctxv.jumpTo;
+ }
+ else {
+ if (this.vars[varName] >= ctxv.to) {
+ return ctxv.jumpTo;
+ }
+ }
+
+ ctx.default.pop();
+ return -1;
+ }
+
+ onLineStr() {
+
+ var line = this.retreiveLine();
+ if (line == -1 || line == "") { return ""; }
+
+ return " in " + line;
+
+ }
+
+ retreiveRuntimeLine() {
+ if (this.runPointer > -1) {
+ var line = this.program[this.runPointer];
+ return line[0];
+ }
+ return -1;
+ }
+
+
+ retreiveLine() {
+ if (this.runFlag) {
+ return this.retreiveRuntimeLine();
+ }
+ else {
+ if (this["parseLineNumber"] === undefined) {
+ return -1;
+ }
+ if (this.parseLineNumber == -1) { return ""; }
+ return this.parseLineNumber;
+ }
+ return -1;
+ }
+
+
+ commandToString(cmd) {
+ if (cmd.type == "control") {
+ return cmd.controlKW.toUpperCase();
+ }
+ else if (cmd.type == "call") {
+ return cmd.statementName;
+ }
+ else if (cmd.type == "assignment") {
+ return "assign ->" + cmd.var;
+ }
+ return "????";
+ }
+
+ runCommands(cmds, limit) {
+ /* return values
+ false -> error or end program
+ true -> executed ok
+
+ should return
+ end_w_error
+ terminate_program
+ line_finished
+ goto_gosub
+ */
+
+ var commands = this.commands;
+ var ecommands = this.extendedcommands;
+ var EXPR = 0, PAR = 1;
+
+ /*return values*/
+ var END_W_ERROR = 0;
+ var TERMINATE_PROGRAM = -1;
+ var LINE_FINISHED = 10;
+ var MIDLINE_INTERUPT = 20;
+ var TERMINATE_W_JUMP = 30;
+ var PAUSE_F_INPUT = 40;
+
+ var end = cmds.length;
+ var i = this.runPointer2;
+ var cnt = 0;
+
+ if (!(limit == undefined)) {
+ //nothing
+ }
+ else {
+ limit = 9999; //reaching to infinite (max on line maybe 40)
+ }
+
+
+
+ while (i < end && cnt < limit) {
+
+
+ if (this.breakCycleFlag) {
+ if (!(limit == undefined)) {
+ this.breakCycleFlag = false;
+ break;
+ }
+ }
+
+ var cmd = cmds[i];
+
+ var l = this.program[this.runPointer];
+
+ //if( this.runPointer > -1 ) {
+ // console.log( l[0] + "(" + this.runPointer + ":" + i +")" + this.commandToString( cmd ) );
+ //}
+
+ if (cmd.type == "control") {
+ var cn = cmd.controlKW;
+ if (cn == "goto") {
+ this.goto(cmd.params[0]);
+ return [TERMINATE_W_JUMP, i + 1, cnt + 1];
+ }
+ else if (cn == "run") {
+ this.runPGM();
+ return [TERMINATE_W_JUMP, i + 1, cnt + 1];
+ }
+ else if (cn == "end") {
+ return [TERMINATE_PROGRAM, i + 1, cnt + 1];
+ }
+ else if (cn == "stop") {
+ this.printInfo("break");
+ return [TERMINATE_PROGRAM, i + 1, cnt + 1];
+ }
+ else if (cn == "gosub") {
+ this.gosub(cmd.params[0], i);
+ return [TERMINATE_W_JUMP, i + 1, cnt + 1];
+ }
+ else if (cn == "on") {
+ var onCommand = cmd.params[0];
+ var onExpr = cmd.params[1];
+ var onLineNrs = cmd.params[2];
+
+ var value = this.evalExpression(onExpr);
+ if ((value - 1) >= 0 && (value - 1) < onLineNrs.length) {
+ if (onCommand == "goto") {
+ this.goto(onLineNrs[(value - 1)]);
+ return [TERMINATE_W_JUMP, i + 1, cnt + 1];
+ }
+ else if (onCommand == "gosub") {
+ this.gosub(onLineNrs[(value - 1)], i);
+ return [TERMINATE_W_JUMP, i + 1, cnt + 1];
+ }
+ }
+
+ //if not jumping, do nothing
+ }
+ else if (cn == "return") {
+ this.doReturn();
+ return [TERMINATE_W_JUMP, i + 1, cnt + 1];
+ }
+ else if (cn == "if") {
+ var IF_ERROR = -1;
+ var IF_TRUE = 1;
+ var IF_FALSE = 0;
+
+ var ifresult = this.evalExpression(cmd.params[0]);
+ if (ifresult != IF_FALSE) {
+ //return [MIDLINE_INTERUPT,i+1];
+ }
+ else {
+ return [LINE_FINISHED, i + 1, cnt + 1];
+ }
+ }
+ else if (cn == "data") {
+ //Nothing
+ }
+ else if (cn == "rem") {
+ return [LINE_FINISHED, i + 1, cnt + 1];
+ }
+ else if (cn == "for:init") {
+ this.doForInit(cmd.params[0], cmd.params[1], cmd.params[2], cmd.variable, i, cmds.length);
+ }
+ else if (cn == "for:next") {
+
+ var jump = this.doForNext(cmd.nextVar);
+
+ if (!(jump === -1)) {
+
+ if (jump.line != -1) {
+ if (this.runPointer == jump.line) {
+ i = jump.cmdPointer;
+ cnt++;
+ continue;
+ }
+ else {
+ this.runPointer = jump.line;
+ this.runPointer2 = jump.cmdPointer;
+ }
+ return [TERMINATE_W_JUMP, i + 1, cnt + 1];
+ }
+ else {
+ i = jump.cmdPointer;
+ cnt++;
+ continue;
+ }
+ }
+ }
+ else if (cn == "dim") {
+ var vars = this.vars;
+
+ for (var ix = 0; ix < cmd.params.length; ix++) {
+
+ var indices = [];
+ for (var ai = 0; ai < cmd.params[ix].length; ai++) {
+ indices[ai] = this.evalExpression(cmd.params[ix][ai]);
+ }
+
+ var arrRec = new BasicArray(cmd.arrayNames[ix], indices, 0);
+
+ var varIntName = "@array_" + cmd.arrayNames[ix];
+
+ if (!(this.vars[varIntName] === undefined)) {
+ this.printError("redim'd array");
+ return [END_W_ERROR, i + 1, cnt + 1];
+ }
+ this.vars[varIntName] = arrRec;
+ }
+
+ }
+ else if (cn == "def") {
+ this.functions[cmd.params[0]] = {
+ par: cmd.params[1],
+ expr: cmd.params[2]
+ };
+ }
+ else {
+ this.printError("illegal ctrl token '" + cn + "'");
+ return [END_W_ERROR, i + 1, cnt + 1];
+ }
+ }
+ else if (cmd.type == "call") {
+ var values = [];
+ var pardefs = [];
+ var mycommands = commands;
+
+ var stc = mycommands["_stat_" + cmd.statementName.toLowerCase()];
+
+ if (stc === undefined) {
+ //cmd.statementName.toLowerCase().startsWith("x") )
+ mycommands = ecommands;
+
+ stc = mycommands["_stat_" + cmd.statementName.toLowerCase()];
+
+ if (stc === undefined) { }
+ else {
+ if (mycommands.enabled == false &&
+ cmd.statementName.toLowerCase() != "xon") {
+ this.printError("extended not enabled");
+ return [END_W_ERROR, i + 1, cnt + 1];
+ }
+ }
+ }
+
+ var intf = mycommands["_if_" + cmd.statementName.toLowerCase()];
+ if (!(intf === undefined)) {
+ pardefs = mycommands["_if_" + cmd.statementName.toLowerCase()]();
+ }
+ else {
+ for (var j = 0; j < cmd.params.length; j++) {
+ pardefs[j] = EXPR;
+ }
+ }
+
+ for (var j = 0; j < cmd.params.length; j++) {
+ if (pardefs[j] == EXPR) {
+
+ var p = this.evalExpression(cmd.params[j]); //NOTE this one gets the trailing ;, from a "PRINT ;" command
+
+ if (p != null) {
+ values.push({ type: "value", value: p });
+ }
+ }
+ else if (pardefs[j] == PAR) {
+ var varName = cmd.params[j].parts[0].data;
+ var varType = "num";
+ if (varName.indexOf("$") > -1) {
+ varType = "str";
+ }
+
+ values.push({ type: "var", value: varName, varType: varType });
+ }
+ else { /*RAW*/
+ //values.push( cmd.params[j].parts );
+ values.push(cmd.params[j]);
+
+ }
+ }
+ try {
+ //var stc = ;
+ if (stc === undefined) {
+ this.printError("syntax");
+ return [END_W_ERROR, i + 1, cnt + 1];
+ }
+ else {
+ mycommands["_stat_" + cmd.statementName.toLowerCase()](values);
+ if (this.inputFlag) {
+ return [PAUSE_F_INPUT, i + 1, cnt + 1];
+ }
+ }
+
+ }
+ catch (e) {
+ console.log(e);
+
+ if (this.erh.isSerializedError(e)) {
+ var err = this.erh.fromSerializedError(e);
+ this.printError(err.clazz);
+ }
+ else if (this.erh.isError(e)) {
+ var err = e;
+ this.printError(err.clazz);
+ }
+ else {
+ this.printError("unexpected " + e);
+ }
+
+ return [END_W_ERROR, i + 1, cnt, e];
+ }
+ }
+ else if (cmd.type == "assignment") {
+ if (cmd.arrayAssignment) {
+ var varIntName = "@array_" + cmd.var;
+ if (this.vars[varIntName] === undefined) {
+ this.printError("bad subscript");
+ return [END_W_ERROR, i + 1, cnt];
+ }
+
+ var arr = this.vars[varIntName];
+ if (cmd.indices.length != arr.getIndexCount()) {
+ this.printError("bad subscript");
+ return [END_W_ERROR, i + 1, cnt];
+ }
+
+ var indices = [];
+ for (var ai = 0; ai < cmd.indices.length; ai++) {
+ indices[ai] = this.evalExpression(cmd.indices[ai]);
+ }
+
+ if (cmd.var.endsWith("%")) {
+ arr.set(indices, Math.floor(this.evalExpression(cmd.expression)));
+ }
+ else if (!cmd.var.endsWith("$")) {
+ var v = this.evalExpression(cmd.expression);
+ if (!(typeof v == "number")) {
+ this.printError("type mismatch");
+ return [END_W_ERROR, i + 1, cnt];
+ }
+ arr.set(indices, this.evalExpression(cmd.expression));
+ }
+ else {
+ arr.set(indices, this.evalExpression(cmd.expression));
+ }
+
+ }
+ else { //single var (not an array)
+ if (this.vars[cmd.var] === undefined) {
+ if (cmd.var.startsWith("TI")) {
+ this.printError("syntax");
+ return [END_W_ERROR, i + 1, cnt + 1];
+ }
+ this.vars[cmd.var] = 0;
+ }
+ if (cmd.var.endsWith("%")) {
+ this.vars[cmd.var] = Math.floor(this.evalExpression(cmd.expression));
+ }
+ else if (!cmd.var.endsWith("$")) {
+ var v = this.evalExpression(cmd.expression);
+ if (!(typeof v == "number")) {
+ this.printError("type mismatch");
+ return [END_W_ERROR, i + 1, cnt];
+ }
+ this.vars[cmd.var] = this.evalExpression(cmd.expression);
+ }
+ else {
+ this.vars[cmd.var] = this.evalExpression(cmd.expression);
+ }
+ }
+ }
+ //cnt++;
+ i++;
+ cnt++;
+ }
+
+ if (i == cmds.length) {
+ return [LINE_FINISHED, i, cnt];
+ }
+
+ return [MIDLINE_INTERUPT, i, cnt];
+
+ }
+
+ setVar(a, b) {
+ this.vars[a] = b;
+ }
+
+ old(linenr) {
+ this.program = this.oldProgram;
+ }
+
+ new(linenr) {
+ this.oldProgram = this.program;
+ this.program = [];
+ }
+
+ removePgmLine(linenr) {
+
+ var pgm2 = [];
+
+ for (var i = 0; i < this.program.length; i++) {
+ var pl = this.program[i];
+ if (pl[0] != linenr) {
+ pgm2.push(pl);
+ }
+ }
+ this.program = pgm2;
+
+ }
+
+ createDisk() {
+ if (!this.confirmCookies()) {
+ return null;
+ }
+
+ this.vDisks.createDisk();
+ }
+
+ setDiskLabel(label) {
+ if (!this.confirmCookies()) {
+ return null;
+ }
+ var dir = this.vDisks.getDir();
+ dir.title = label;
+ this.vDisks.setDir(dir);
+ }
+
+ deleteFile(fn) {
+ if (!this.confirmCookies()) {
+ return null;
+ }
+
+ return this.vDisks.deleteFile(fn);
+ }
+
+ getDisks() {
+ if (!this.confirmCookies()) {
+ return null;
+ }
+
+ return this.vDisks.getDisks();
+ }
+
+ selectDisk(id) {
+ if (!this.confirmCookies()) {
+ return null;
+ }
+
+ this.vDisks.selectDisk(id);
+ }
+
+ getDir() {
+ if (!this.confirmCookies()) {
+ return null;
+ }
+
+ return this.vDisks.getDir();
+ }
+
+ setDir(dir) {
+
+ if (!this.confirmCookies()) {
+ return;
+ }
+
+ this.vDisks.setDir(dir);
+ }
+
+ formatDisk() {
+ if (!this.confirmCookies()) {
+ return null;
+ }
+
+ this.vDisks.formatDisk();
+ }
+
+ loadDir() {
+
+ if (!this.confirmCookies()) {
+ return;
+ }
+
+ var dir = this.getDir();
+ var row;
+
+ this.program = [];
+ this.program.push([null, null, "0 \u0012\"" + dir.title + " \"\u0092 00 2A"]);
+ for (var i = 0; i < dir.files.length; i++) {
+
+ row = this.padSpaces6(dir.files[i].size) + " \"" + dir.files[i].fname + "\"";
+ this.program.push([null, null, row]);
+ }
+
+ row = dir.free + " slots free.".toUpperCase();
+ this.program.push([null, null, row]);
+
+ }
+
+
+
+
+
+ padSpaces6(no) {
+ var s = no + "";
+ for (var i = s.length; i < 6; i++) {
+ s += " ";
+ }
+ return s;
+ }
+
+ padSpaces8(no) {
+ var s = no + "";
+ for (var i = s.length; i < 8; i++) {
+ s += " ";
+ }
+ return s;
+ }
+
+ updateDir(fileName, programLen) {
+
+ if (!this.confirmCookies()) {
+ return;
+ }
+
+ this.vDisks.updateDir(fileName, programLen);
+ }
+
+
+
+ saveSerializedData(fileName0, serializedData, type, len) {
+
+ if (!this.confirmCookies()) {
+ return;
+ }
+
+ var fileName = "default";
+
+
+ if (this.debugFlag) {
+ console.log("saving...");
+ console.log(this.program);
+ }
+
+
+ if (fileName0) {
+ fileName = fileName0;
+ }
+
+ this.vDisks.saveFile(fileName, serializedData, type, len);
+
+
+ return true;
+ }
+
+ save(fileName0) {
+
+ if (!this.confirmCookies()) {
+ return;
+ }
+
+ var fileName = "default";
+
+ if (this.debugFlag) {
+ console.log("saving...");
+ console.log(this.program);
+ }
+
+ if (fileName0) {
+ fileName = fileName0;
+ }
+
+ this.vDisks.saveFile(fileName, JSON.stringify(this.program), "bas", this.program.length);
+
+
+ }
+
+ loadContainer(container) {
+
+ if (container == null) {
+ this.program = [];
+ return false;
+ }
+
+ this.program = null;
+
+ if (container.type == "bas") {
+
+ this.program = JSON.parse(container.data);
+ var p = new Parser(this.commands, this.extendedcommands);
+ p.init();
+
+ if (this.program != null) {
+ for (i = 0; i < this.program.length; i++) {
+ var l = p.parseLine(this.program[i][2]);
+ this.program[i][1] = l.commands;
+ }
+ }
+ }
+ else if (container.type == "snp") {
+
+ var state = JSON.parse(container.data);
+ if (!(state.pgm === undefined)) {
+ this.program = state.pgm;
+ this.setProgramState(state.pgmState);
+ this.console.setState(state.console);
+ }
+ else {
+ throw "error loading snapshot " + fileName;
+ }
+
+ }
+
+ if (this.program != null) {
+ var p = this.program;
+ for (var i = 0; i < p.length; i++) {
+ if (p[i] == null) {
+ delete p[i];
+ }
+ }
+ return [true, container.type == "snp"];
+ }
+ return false;
+ }
+
+ load(fileName) {
+
+ if (!this.confirmCookies()) {
+ return false;
+ }
+
+ if (fileName == "$") {
+ this.loadDir();
+ return [true, false];
+ }
+ else if (fileName == "*") {
+ return this.load(null);
+ }
+
+ var container = this.vDisks.loadFile(fileName);
+
+ return this.loadContainer(container);
+
+ }
+
+ setScale(xy) {
+
+ if (xy === null) {
+ this.console.rescale(this.initScale, this.initScale);
+ return;
+ }
+ this.console.rescale(xy, xy);
+
+ }
+
+
+ getVirtualDisk() {
+
+ if (!this.confirmCookies()) {
+ return null;
+ }
+
+ return this.vDisks.getFullDisk();
+
+ }
+
+ createDiskFromImage(name, image) {
+
+ if (!this.confirmCookies()) {
+ return null;
+ }
+
+ return this.vDisks.createDiskFromImage(name, image);
+
+ }
+
+ insertPgmLine(linenr, commands, raw) {
+
+ this.insertPgmLineLocal(linenr, commands, raw, this.program);
+ }
+
+ insertPgmLineLocal(linenr, commands, raw, myProgram) {
+
+ for (var i = 0; i < myProgram.length; i++) {
+ var pl = myProgram[i];
+ if (pl[0] == linenr) {
+ myProgram[i] = [linenr, commands, raw.trim()];
+ return;
+ }
+ }
+
+ myProgram.push([linenr, commands, raw.trim()]);
+
+ var sortF = function compare(a, b) {
+ return a[0] - b[0];
+ }
+
+ myProgram.sort(sortF);
+
+ }
+
+ enableExtended(flag) {
+ if (flag) {
+ this.extendedcommands._stat_xon(undefined);
+ }
+ else {
+ this.extendedcommands._stat_xoff(undefined);
+ }
+ }
+
+ textLinesToBas(lines) {
+
+ var myProgram = [];
+
+ if (this.debugFlag) {
+ console.log("textLinesToBas");
+ }
+
+ var lineText = "???";
+ var errorsFound = "";
+ try {
+
+ for (var i = 0; i < lines.length; i++) {
+
+ if( myProgram.length == 1 ) {
+ var l0 = myProgram[0];
+ if( l0[0] == 0 ) {
+ if( l0[1].length == 1 ) {
+ var c0 = l0[1][0];
+ if( c0.lineNumber == 0 && c0.statementName.toUpperCase() == "XON" ){
+ this.extendedcommands.enable( true );
+ }
+ }
+ }
+ }
+ try {
+ var line = this.prepareLineForImport(lines[i]);
+ lineText = line;
+ var p = new Parser(this.commands, this.extendedcommands);
+ p.init();
+
+ var l = p.parseLine(line);
+ if (l == null) {
+ continue;
+ }
+ if (l.lineNumber != -1) {
+ if (l.commands.length > 0) {
+ this.insertPgmLineLocal(l.lineNumber, l.commands, l.raw, myProgram);
+
+ }
+ else {
+ throw "Error, no commands on line " + l.lineNumber;
+ }
+ }
+ else {
+ throw "Error, command must start with number to be part of program";
+ }
+
+ if (this.debugFlag) {
+ console.log("program:", myProgram);
+ console.log("Line: ", l);
+ }
+ }
+ catch (e) {
+ //insert as rem statement
+ //parse line number (keep reading numeric chars untill any other char encountered)
+ var lineNr = 0;
+ var lineNrStr = "";
+
+ for (var j = 0; j < lineText.length; j++) {
+ if (lineText[j] >= '0' && lineText[j] <= '9') {
+ lineNrStr += lineText[j];
+ }
+ else {
+ break;
+ }
+ }
+
+ if (lineNrStr.length > 0) {
+ lineNr = parseInt(lineNrStr);
+ if( errorsFound.length > 0 ) {
+ errorsFound += ", ";
+ }
+ errorsFound += lineNr;
+ }
+
+ try {
+ var l = p.parseLine( lineNr + " REM ERR " + lineText.substring(lineNrStr.length) );
+ this.insertPgmLineLocal(l.lineNumber, l.commands, l.raw, myProgram);
+ }
+ catch (e) {
+ if (this.erh.isError(e)) {
+ e.lineText = lineText;
+ }
+ throw (e);
+ }
+ }
+ }
+
+ if( errorsFound.length > 0 ) {
+ this.errorsInParsing = ("Errors in lines: " + errorsFound).toUpperCase();
+ }
+ else {
+ this.errorsInParsing = false;
+ }
+ return myProgram;
+ }
+ catch (e) {
+ if (this.erh.isError(e)) {
+ e.lineText = lineText;
+ }
+ throw (e);
+ }
+ }
+
+ printReady() {
+ this.printLine("ready.");
+ }
+
+
+ startConsoleDataInput(vars) {
+
+ if (this.debugFlag) {
+ console.log("inputvars=", vars);
+ }
+ this.inputFlag = true;
+ this.inputVars = vars;
+ this.inputVarsPointer = 0;
+ this.sendChars("? ", false);
+ }
+
+ handleLineInput(str, isInputCommand) {
+
+
+
+ if (this.debugFlag) {
+ console.log("handleLineInput: start debug / isInputCommand=" + isInputCommand + " -------------");
+ }
+
+ if (isInputCommand) {
+
+ var input = str;
+ var qMark = input.indexOf("?");
+ while (qMark > -1) {
+ input = input.substr(qMark + 2);
+ qMark = input.indexOf("?");
+ }
+
+ if (this.debugFlag) {
+ console.log("handleLineInput: start debug / input, name -------------");
+ console.log("InputVarsPointer:", this.inputVarsPointer);
+ console.log("InputVars:", this.inputVars);
+
+ console.log("Input String:", input);
+ console.log("Input Vars[current]:", this.inputVars[this.inputVarsPointer]);
+ }
+
+
+ var vName = this.inputVars[this.inputVarsPointer];
+ if (vName.indexOf("$") > -1) {
+ this.setVar(this.inputVars[this.inputVarsPointer], input.trim());
+ }
+ else {
+ var num = parseFloat(input.trim());
+
+ if (isNaN(num)) {
+ this.printLine("?redo from start");
+ this.sendChars("? ", false);
+ return;
+ }
+ this.setVar(this.inputVars[this.inputVarsPointer], num);
+ }
+
+ this.inputVarsPointer++;
+ if (this.inputVarsPointer >= this.inputVars.length) {
+
+ this.exitInputState();
+ }
+ else {
+ this.sendChars("?? ", false);
+ }
+
+ if (this.debugFlag) {
+ console.log("handleLineInput: end debug -------------");
+ }
+ return;
+ }
+
+ this.executeLineFlag = true;
+
+ if (this.debugFlag) {
+ console.log(str);
+ }
+ var p = new Parser(this.commands, this.extendedcommands);
+ p.init();
+ try {
+ var l = p.parseLine(str);
+ }
+ catch (e) {
+
+ this.parseLineNumber = -1;
+ if (this.erh.isError(e)) {
+ this.parseLineNumber = e.lineNr;
+ this.printError(e.clazz, true);
+ }
+ else {
+ this.printError("syntax", true);
+ }
+ this.printLine("ready.");
+ }
+ if (l == null) {
+ if (this.debugFlag) {
+ console.log("handleLineInput: end debug -------------");
+ }
+
+ this.executeLineFlag = false;
+ return;
+ }
+
+ if (l.lineNumber != -1) {
+ if (l.commands.length > 0) {
+ this.insertPgmLine(l.lineNumber, l.commands, l.raw);
+ }
+ else {
+ this.removePgmLine(l.lineNumber);
+ }
+ }
+ else {
+ this.runPointer = -1;
+ this.runPointer2 = 0;
+
+ try {
+ this.runCommands(l.commands);
+ }
+ catch (e) {
+
+ this.parseLineNumber = -1;
+
+ if (this.erh.isSerializedError(e)) {
+ var err = this.erh.fromSerializedError(e);
+ this.parseLineNumber = err.lineNr;
+ this.printError(err.clazz);
+ }
+ else if (this.erh.isError(e)) {
+ var err = e;
+ this.printError(err.clazz);
+ this.parseLineNumber = err.lineNr;
+ }
+ else {
+ this.printError("unexpected " + e);
+ }
+
+ this.runFlag = false;
+ }
+
+ if (!this.runFlag && !this.listFlag) {
+ this.printLine("ready.");
+ }
+
+ }
+
+ this.executeLineFlag = false;
+
+ if (this.debugFlag) {
+ console.log("program:", this.program);
+ console.log("Line: ", l);
+
+ console.log("handleLineInput: end debug -------------");
+ }
+ }
+
+}
diff --git a/versions/0.8p5/res/script/basicparser.js b/versions/0.8p5/res/script/basicparser.js
new file mode 100644
index 0000000..d3f3718
--- /dev/null
+++ b/versions/0.8p5/res/script/basicparser.js
@@ -0,0 +1,1584 @@
+class Parser {
+
+ constructor( cmds, ecmds ) {
+ this.commands = cmds;
+ this.extendedcommands = ecmds;
+ this.erh = new ErrorHandler();
+ this.debugFlag = false;
+ }
+
+ init() {
+
+ this.CTRL_KW = ["IF","THEN","GOTO","AND", "NOT", "OR", "GOSUB", "RETURN", "FOR", "TO", "NEXT", "STEP", "DATA", "REM", "GOSUB", "DIM", "END", "LET", "STOP", "DEF", "FN", "ON", "RUN" ];
+ this.SHORTCUT_KW = ["?"];
+
+ this.KEYWORDS = this.commands.getStatements();
+
+ var more = this.extendedcommands.getStatements();
+ for( var i=0; i 0) {
+ arr.push( null );
+ missing--;
+ }
+ }
+
+ throwError( ctx, detail, clazz ) {
+
+ var clazz2 = clazz;
+ if( clazz2 === undefined ) {
+ clazz2 = "syntax";
+ }
+
+ if( ctx ) {
+ console.log(" Exception " + clazz + " at line " + ctx.lineNumber+ " " + detail );
+ }
+
+ if( ctx ) {
+ if( ! ( ctx.lineNumber == undefined ) ) {
+ this.erh.throwError( clazz2, detail, ctx, ctx.lineNumber );
+ }
+ }
+
+ this.erh.throwError( clazz2, detail, undefined, -1 );
+
+ }
+
+ removePadding( tokens ) {
+ var tokens2 = [];
+
+ for( var i=0;
+ i0 ) {
+ var token2 = tokens[i-1];
+ if( ( token.type == "comp" || token.type == "eq" ) &&
+ ( token2.type == "comp" || token2.type == "eq" ) ) {
+ token2.type = "@@removeme";
+ token.data = token2.data + token.data;
+ token.type = "comp";
+ if( token.data == "><" ) {
+ token.data = "<>";
+ }
+ else if( token.data == "=<" ) {
+ token.data = "<=";
+ }
+ else if( token.data == "=>" ) {
+ token.data = ">=";
+ }
+
+ }
+ }
+
+ if( ( token.type == "name" && token.data == "OR" ) ||
+ ( token.type == "name" && token.data == "AND" ) ||
+ ( token.type == "name" && token.data == "NOT" )) {
+ token.type = "bop";
+ }
+
+ }
+
+ for( var i=0;
+ i DER10 (tobesplit) -> DER,10 -> DISCART DER -> Keep 10 as argument
+ */
+
+ tokens2[i-1].data = tokens2[i-0].data.substr( record.p3.length );
+ if( toker.isNumeric( tokens2[i-1].data ) ) {
+ tokens2[i-1].type = "num";
+ }
+ else {
+ tokens2[i-1].type = "name";
+ }
+
+ tokens2[i-0].type = "removeme";
+ }
+
+ }
+ }
+ }
+
+ var j=0;
+ for( var i=0;
+ i 0) {
+ if( tokens[0].type=="bracket" && tokens[0].data==")") {
+ break;
+ }
+ }
+
+ if( even ) {
+ var expr = this.parseBoolExpression( context, endTokens );
+ expr.type = "expr";
+ params.push( expr );
+ }
+ else {
+ token = tokens.shift();
+
+ if( token.type=="sep" ) {
+ //all ok, next par
+ }
+ else {
+ this.throwError( context, "expected comma or ), got "+token.type + " " + token.data);
+ }
+ }
+ even = !even;
+ }
+
+ return params;
+ }
+
+ peekIfNextIsOpenBracket( context ) {
+
+ var tokens = context.tokens;
+
+ if( tokens.length > 0 ) {
+ if( tokens[0].type == "bracket" && tokens[0].data == "(") {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ parseSubExpression( context ) {
+
+ var token = context.tokens.shift();
+
+ if( !(token.type == "bracket" && token.data == "(")) {
+ this.throwError( context, "parsing subexpression, expected bracket, not " + token.type + " - " + token.data);
+ }
+
+ var endTokens = [];
+ endTokens.push( { type: "bracket", data: ")" });
+
+ var expr = this.parseBoolExpression( context, endTokens );
+ context.tokens.shift();
+
+ expr.type = "expr";
+ return expr;
+ }
+
+
+ tokensToString( token ) {
+ var str = "";
+
+ if(token.data == "@@@all") {
+ str = str + "'" + token.type + "'";
+ }
+ else {
+ str = str + "'" + token.type + "/" + token.data + "'";
+ }
+
+ return str;
+ }
+
+ endTokensToString( endTokenArry ) {
+ var str = "";
+
+ for( var et=0; et 0) {
+ if( tokens[0].type == "bop" ) {
+ var op = tokens.shift();
+ continue;
+ }
+ }
+ break;
+ }
+
+ if( eList.length == 1 ) {
+ eList[0].dbg2 = "len=1";
+ return eList[0];
+ }
+
+
+ var retExpr = {
+ negate: false,
+ binaryNegate: false,
+ type: "expr",
+ parts: [],
+ op: null
+ };
+
+ for( i=0; i0 && part.op == op ) {
+ var prevPart = parts1[ i-1 ];
+
+ var subExpr = {
+ negate: false,
+ binaryNegate: false,
+ type: "expr",
+ parts: [],
+ op: prevPart.op
+ };
+
+ subExpr.parts[ 0 ] = prevPart;
+ subExpr.parts[ 0 ].op = null;
+ subExpr.parts[ 1 ] = part;
+
+ parts1[i-1] = null;
+ parts1[ i ] = subExpr;
+
+ }
+ }
+
+
+ for( var i=0; i( varname )");
+ }
+
+ token = tokens.shift();
+ if(! ( token.type == "name" )) {
+ this.throwError( context, "DEF FN expects function name and ( ->varname )");
+ }
+ var varName = token.data;
+
+ token = tokens.shift();
+ if(! ( token.type == "bracket" && token.data == ")" )) {
+ this.throwError( context, "DEF FN expects function name and ( varname -> )");
+ }
+
+ token = tokens.shift();
+ if(! ( token.type == "eq" && token.data == "=" )) {
+ this.throwError( context, "DEF FN expects function name and ( varname ) -> =");
+ }
+
+
+ endTokens = [];
+ var expr_fn = this.parseBoolExpression( context, endTokens );
+
+ if( this.debugFlag ) {
+ console.log("expr = " + expr_fn );
+ }
+
+ command.params=[];
+ command.params[0] = fName;
+ command.params[1] = varName;
+ command.params[2] = expr_fn;
+ commands.push( command );
+
+ }
+ else if( controlToken == "GOTO" || controlToken == "GOSUB") {
+ var num = -1;
+
+ token = tokens.shift();
+
+ if( token === undefined ) {
+ this.throwError( context, "GOTO/GOSUB expects number", "undef'd statement");
+ }
+
+ if( token.type != "num") {
+ this.throwError( context, "GOTO/GOSUB expects number", "undef'd statement");
+ }
+ num = parseInt(token.data);
+ token = tokens.shift();
+ if( token !== undefined ) {
+ if( token.type != "cmdsep") {
+ this.throwError( context, "expected cmdsep, instead of "+token.type+"/"+token.data);
+ }
+ }
+
+ command.params=[];
+ command.params[0] = num;
+ commands.push( command );
+
+ }
+ else if( controlToken == "RUN") {
+ var num = -1;
+
+ token = tokens.shift();
+
+ if( !( token === undefined ) ) {
+ if( token.type != "num") {
+ this.throwError( context, "RUN expects number", "undef'd statement");
+ }
+
+ num = parseInt(token.data);
+ token = tokens.shift();
+ if( token !== undefined ) {
+ if( token.type != "cmdsep") {
+ this.throwError( context, "expected cmdsep, instead of "+token.type+"/"+token.data);
+ }
+ }
+ }
+
+ command.params=[];
+ command.params[0] = num;
+ commands.push( command );
+
+ }
+ else if( controlToken == "ON" ) {
+ var nums = [];
+
+ endTokens = [];
+ endTokens.push( { type: "name", data: "GOTO" });
+ endTokens.push( { type: "name", data: "GOSUB" });
+
+ var onExpr = this.parseBoolExpression( context, endTokens );
+
+ token = tokens.shift();
+ if( token.type != "name") {
+ this.throwError( context, "ON expects GOTO/GOSUB");
+ }
+ if( !( token.data == "GOTO" || token.data == "GOSUB" )) {
+ this.throwError( context, "ON expects GOTO/GOSUB");
+ }
+ var onType = token.data;
+
+ token = tokens.shift();
+
+ if( token.type != "num") {
+ this.throwError( context, "ON GOTO/GOSUB expects number", "undef'd statement");
+ }
+
+ if( token.type != "num") {
+ this.throwError( context, "ON GOTO/GOSUB expects number", "undef'd statement");
+ }
+ nums.push( parseInt(token.data) );
+
+ while ( true ) {
+
+ token = tokens.shift();
+ if( token == undefined ) { break; }
+ if( token.type == "cmdsep") { break; }
+ if( token.type == "cmdsep") { break; }
+ if( !( token.type == "sep" && token.data == "," )) {
+ this.throwError( context, "ON GOTO/GOSUB expects numberlist");
+ }
+
+ token = tokens.shift();
+ if( token.type != "num") {
+ this.throwError( context, "GOTO/GOSUB expects number");
+ }
+ nums.push( parseInt(token.data) );
+ }
+
+ command.params=[];
+ command.params[0] = onType.toLowerCase();
+ command.params[1] = onExpr;
+ command.params[2] = nums;
+ commands.push( command );
+
+ }
+ else if( controlToken == "RETURN") {
+ var num = -1;
+
+ command.params=[];
+ commands.push( command );
+
+ }
+ else if( controlToken == "END") {
+ var num = -1;
+
+ command.params=[];
+ commands.push( command );
+
+ }
+ else if( controlToken == "STOP") {
+ var num = -1;
+
+ command.params=[];
+ commands.push( command );
+
+ }
+ else if( controlToken == "FOR") {
+
+ var variable, expr_from, expr_to, expr_step;
+ var endTokens = [];
+
+ token = tokens.shift();
+ if( token.type != "name" ) {
+ this.throwError( context,
+ "For expects variable, no var found, found " + token.type+"/"+token.data);
+ }
+
+ variable = token.data;
+
+ token = tokens.shift();
+ if( !( token.type == "eq" && token.data == "=" )) {
+ this.throwError( context,
+ "For expects '=', not found, found " + token.type+"/"+token.data);
+ }
+
+ endTokens = [];
+ endTokens.push( { type: "name", data: "TO" });
+
+ expr_from = this.parseBoolExpression( context, endTokens );
+
+ token = tokens.shift();
+ if( !( token.type == "name" && token.data == "TO" ) ) {
+ this.throwError( context, "For expects 'to', not found, found " + token.type+"/"+token.data);
+ }
+
+ endTokens = [];
+ endTokens.push( { type: "cmdsep", data: ":" });
+ endTokens.push( { type: "name", data: "STEP" });
+
+ expr_to = this.parseBoolExpression( context, endTokens );
+ expr_step = { parts: [ { data: "1", op: null, type: "num"} ] };
+
+ token = tokens.shift();
+ if( !( token === undefined ) ) {
+ if( token.type == "name" && token.data == "STEP") {
+
+ endTokens = [];
+ endTokens.push( { type: "cmdsep", data: ":" });
+ expr_step = this.parseBoolExpression( context, endTokens );
+ }
+ else {
+ if(! ( token.type == "cmdsep" && token.data == ":")) {
+ throw "FOR unexpected token " + token.type + "/" + token.data;
+ }
+ }
+ }
+
+ command.controlKW = "for:init";
+ command.params=[];
+ command.params[0] = expr_from;
+ command.params[1] = expr_to;
+ command.params[2] = expr_step;
+ command.variable = variable;
+ commands.push( command );
+ if( this.debugFlag ) {
+ console.log("command=", command);
+ }
+
+ }
+ else if( controlToken == "NEXT") {
+
+ var variable;
+
+ var explicit = false;
+ while( true ) {
+
+ var token = tokens.shift();
+ if( ! token ) {
+ break;
+ }
+ if( token.type == "cmdsep" ) {
+ break;
+ }
+
+ if( token.type != "name" ) {
+ throw "next expected var or nothing";
+ }
+
+ var nextcommand = {
+ controlKW: "for:next",
+ nextVar: token.data,
+ lineNumber: command.lineNumber,
+ type: command.type
+ };
+
+ commands.push( nextcommand );
+ explicit = true;
+
+ var token = tokens.shift();
+ if( ! token ) {
+ break;
+ }
+ if( token.type == "cmdsep" ) {
+ break;
+ }
+ if( !( token.type == "sep" && token.data == "," )) {
+ throw "expected comma, found " + token.type + "/"+token.data;
+ }
+ }
+
+ if( ! explicit ) {
+ command.controlKW = "for:next";
+ command.nextVar = null;
+ commands.push( command );
+ }
+
+ }
+ else if( controlToken == "IF") {
+
+ var expr1, expr2, comp;
+ endTokens = [];
+ endTokens.push( { type: "name", data: "THEN" });
+ endTokens.push( { type: "name", data: "GOTO" });
+ var expr1 = this.parseBoolExpression( context, endTokens );
+ command.params= [ expr1 ];
+
+ token = tokens.shift();
+
+ if( token.type == "name" && token.data == "GOTO") {
+ var insert = {};
+ insert.data = "GOTO";
+ insert.type = "name";
+ tokens.unshift( insert );
+ } else {
+ if( tokens.length > 0 ) {
+ if( tokens[0].type == "num" ) {
+ var insert = {};
+ insert.data = "GOTO";
+ insert.type = "name";
+ tokens.unshift( insert );
+ }
+ }
+ }
+
+ var block = this.parseLineCommands( context );
+
+ if( this.debugFlag ) {
+ console.log( block );
+ }
+
+ commands.push( command );
+
+ for( var bi=0; bi -1) {
+ control = true;
+ }
+
+ if( this.KEYWORDS.indexOf( token.data ) > -1 || token.data == "XON") {
+ keyword = true;
+ }
+ else {
+ if( this.SHORTCUT_KW.indexOf( token.data ) > -1) {
+ keyword = true;
+ }
+ }
+
+ token = tokens.shift();
+ if( token === undefined ) {
+ token = { type: "@@@notoken" };
+ }
+
+ if ( control ) {
+
+ this.parseControlStructure( context, preTokens, commands, command, nameToken, token );
+
+ }
+ else if( token.type == "eq") {
+
+ this.parseAssignment( context, preTokens, commands, command, nameToken, token );
+ }
+ else if( token.type == "bracket" && token.data=="(" && !keyword ) {
+
+ this.parseArrayAssignment( context, preTokens, commands, command, nameToken, token );
+
+ }
+ else {
+ if( !keyword ) {
+ this.throwError( context, "statement without keyword");
+ }
+ this.parseStatementCall( context, preTokens, commands, command, nameToken, token );
+
+ }
+
+ }
+ return commands;
+ }
+
+ logTokens( tokens ) {
+ var tokensStr = "";
+ for( var i=0; i");
+ return [rv,0];
+ }
+
+ isEqChar( ctx ) {
+ if( ctx.c == "=" ) {
+ return [true,0];
+ }
+ return [false,0];
+ }
+
+
+ isNameChar( ctx ) {
+
+ //console.log("SEQ: " + ctx.seq);
+ if( ctx.endFound ) {
+ return [false,0];
+ }
+ var rv = ctx.c.match("[a-zA-Z0-9$%?]") != null;
+
+ if( ctx.c=="$" || ctx.c== "%") {
+ ctx.endFound = true;
+ }
+
+ if( this.keywords.indexOf( ctx.seq ) >-1 ) {
+ //console.log("Found Keyword: " + ctx.seq );
+ ctx.endFound = true;
+ }
+ else if( ! (ctx.seq === undefined )) {
+ var trappedKW = false;
+ var trapped = null;
+ for( var i=0; i 0 ) {
+ trappedKW = true;
+ trapped = kw;
+ //console.log( "trapped-------------" );
+ //console.log( kw );
+ //console.log( ctx.seq );
+ //console.log( ctx );
+ return [rv, kw.length ];
+ }
+ }
+
+ }
+ return [rv,0];
+ }
+
+
+ isNumeric( string ) {
+ for( var i=0; i< string.length; i++) {
+ if(! this.isNumCharRaw( string.substr( i, 1) ) ) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ isNumCharRaw( c ) {
+ return [(c.match("[0-9\.~]") != null),0];
+ }
+
+ isNumChar( ctx ) {
+ return this.isNumCharRaw( ctx.c );
+ }
+
+ isPadChar( ctx ) {
+ if( ctx.c == " " || ctx.c == "\t" || ctx.c == "\n" || ctx.c == "\r") {
+ return [true,0];
+ }
+ return [false,0];
+ }
+
+ isCommandSepChar( ctx ) {
+ if( ctx.c == ":" ) {
+ return [true,0];
+ }
+ return [false,0];
+ }
+
+
+ isSepChar( ctx ) {
+ if( ctx.c == "," ) {
+ return [true,0];
+ }
+ return [false,0];
+ }
+
+ isAnyChar( ctx ) {
+ return [true,0]; /* Will be executed last */
+ }
+
+
+ isBracket( ctx ) {
+ if( ctx.c == "(" || ctx.c == ")" || ctx.c == "[" || ctx.c == "]") {
+ return [true,0];
+ }
+ return [false,0];
+ }
+
+
+ isStrChar( ctx ) {
+
+ if( ctx.endFound ) {
+ return [false,0];
+ }
+
+ if( ctx.index == 0) {
+ if( ctx.c=="\"" ) {
+ ctx.inString = true;
+ return [true,0];
+ }
+ return [false,0];
+ }
+ else if( ctx.inString ) {
+ if ( ctx.index > 0 && ctx.c=="\"") {
+ ctx.endFound = true;
+ }
+ return [true,0];
+ }
+
+ return [false,0];
+
+ }
+
+ normalizeToken( tok0 ) {
+ var tok = tok0;
+
+ tok.type = tok0.type;
+
+ if( tok.type == "str" ) {
+ tok.data = tok0.data.substr(1,tok0.data.length-2);
+ }
+ return tok;
+ }
+
+ readChars( read, type0, compareF, tokenType ) {
+ var tok = { type: type0, data : "" }
+ var ctx = { index:0, prev: null, seq: "" };
+
+ while(!read.EOF()) {
+
+ var c = read.peek();
+
+ ctx.seq += c;
+ ctx.c = c;
+
+ var rv = this[compareF ] ( ctx );
+ if( rv[1] > 0 ) {
+ read.unconsume( rv[1]-1 );
+ ctx.seq = ctx.seq.substr(0,ctx.seq.length-rv[1]) ;
+ tok.data = ctx.seq;
+ break;
+ }
+
+ if( !rv[0] ) {
+ return this.normalizeToken( tok );
+ }
+ tok.data += c;
+ read.consume();
+
+ ctx.index++;
+ ctx.prev = c;
+
+ if( tokenType == "chr") {
+ break;
+ }
+ }
+
+ return this.normalizeToken( tok );
+ }
+
+
+ tokenize() {
+ var read = this.reader;
+
+ var _this = this;
+ var tokens = [];
+
+ var parseRules = [];
+ var TYPEIX = 0;
+ var FUNCIX = 1;
+ var STRINGTYPEIX = 2;
+
+ parseRules.push(["pad", "isPadChar" , "str"] );
+ parseRules.push(["str", "isStrChar" , "str"] );
+ parseRules.push(["num", "isNumChar" , "str"] );
+ parseRules.push(["name", "isNameChar" , "str"] );
+ parseRules.push(["op", "isOpChar" , "chr"] );
+ parseRules.push(["comp", "isCompChar" , "chr"] );
+ parseRules.push(["eq", "isEqChar" , "chr"] );
+ parseRules.push(["bracket", "isBracket" , "chr"] );
+ parseRules.push(["sep", "isSepChar" , "chr"] );
+ parseRules.push(["cmdsep", "isCommandSepChar" , "chr"] );
+ parseRules.push(["trash", "isAnyChar" , "chr"] );
+
+ while( !read.EOF() ) {
+ var c = read.peek();
+ var tokenFound = false;
+
+ for( var i=0; i" + read.line + ":" + read.lineIndex;
+ }
+ }
+ return tokens;
+ }
+}
diff --git a/versions/0.8p5/res/script/c64basicpgm.js b/versions/0.8p5/res/script/c64basicpgm.js
new file mode 100644
index 0000000..73af624
--- /dev/null
+++ b/versions/0.8p5/res/script/c64basicpgm.js
@@ -0,0 +1,200 @@
+//const fs = require('fs');
+//const path = require('path');
+
+class C64BasicProgram {
+ constructor() {
+
+ this.tokens = [];
+ var tokens = this.tokens;
+
+ tokens[0x80] = 'END';
+ tokens[0x81] = 'FOR';
+ tokens[0x82] = 'NEXT';
+ tokens[0x83] = 'DATA';
+ tokens[0x84] = 'INPUT#';
+ tokens[0x85] = 'INPUT';
+ tokens[0x86] = 'DIM';
+ tokens[0x87] = 'READ';
+ tokens[0x88] = 'LET';
+ tokens[0x89] = 'GOTO';
+ tokens[0x8A] = 'RUN';
+ tokens[0x8B] = 'IF';
+ tokens[0x8C] = 'RESTORE';
+ tokens[0x8D] = 'GOSUB';
+ tokens[0x8E] = 'RETURN';
+ tokens[0x8F] = 'REM';
+ tokens[0x90] = 'STOP';
+ tokens[0x91] = 'ON';
+ tokens[0x92] = 'WAIT';
+ tokens[0x93] = 'LOAD';
+ tokens[0x94] = 'SAVE';
+ tokens[0x95] = 'VERIFY';
+ tokens[0x96] = 'DEF';
+ tokens[0x97] = 'POKE';
+ tokens[0x98] = 'PRINT#';
+ tokens[0x99] = 'PRINT';
+ tokens[0x9A] = 'CONT';
+ tokens[0x9B] = 'LIST';
+ tokens[0x9C] = 'CLR';
+ tokens[0x9D] = 'CMD';
+ tokens[0x9E] = 'SYS';
+ tokens[0x9F] = 'OPEN';
+ tokens[0xA0] = 'CLOSE';
+ tokens[0xA1] = 'GET';
+ tokens[0xA2] = 'NEW';
+ tokens[0xA3] = 'TAB(';
+ tokens[0xA4] = 'TO';
+ tokens[0xA5] = 'FN';
+ tokens[0xA6] = 'SPC(';
+ tokens[0xA7] = 'THEN';
+ tokens[0xA8] = 'NOT';
+ tokens[0xA9] = 'STEP';
+ tokens[0xAA] = '+';
+ tokens[0xAB] = '-';
+ tokens[0xAC] = '*';
+ tokens[0xAD] = '/';
+ tokens[0xAE] = '^';
+ tokens[0xAF] = 'AND';
+ tokens[0xB0] = 'OR';
+ tokens[0xB1] = '>';
+ tokens[0xB2] = '=';
+ tokens[0xB3] = '<';
+ tokens[0xB4] = 'SGN';
+ tokens[0xB5] = 'INT';
+ tokens[0xB6] = 'ABS';
+ tokens[0xB7] = 'USR';
+ tokens[0xB8] = 'FRE';
+ tokens[0xB9] = 'POS';
+ tokens[0xBA] = 'SQR';
+ tokens[0xBB] = 'RND';
+ tokens[0xBC] = 'LOG';
+ tokens[0xBD] = 'EXP';
+ tokens[0xBE] = 'COS';
+ tokens[0xBF] = 'SIN';
+ tokens[0xC0] = 'TAN';
+ tokens[0xC1] = 'ATN';
+ tokens[0xC2] = 'PEEK';
+ tokens[0xC3] = 'LEN';
+ tokens[0xC4] = 'STR$';
+ tokens[0xC5] = 'VAL';
+ tokens[0xC6] = 'ASC';
+ tokens[0xC7] = 'CHR$';
+ tokens[0xC8] = 'LEFT$';
+ tokens[0xC9] = 'RIGHT$';
+ tokens[0xCA] = 'MID$';
+ tokens[0xCB] = 'GO';
+
+ }
+
+
+ // Parse BASIC lines
+ parseBasicProgram(data) {
+ let offset = 2; // Start after the load address
+ let lines = [];
+ this.lines = lines;
+
+ if (!(data[0] === 0x01 && data[1] === 0x08)) {
+ throw ('This is not a BASIC program');
+ }
+
+ while (offset < data.length) {
+
+ const nextLineAddr = data[offset] + (data[offset + 1] << 8);
+ const lineNumber = data[offset+2] + (data[offset + 3] << 8);
+
+ if( nextLineAddr == 0) break;
+
+ offset += 4; // Move past the pointer and line number
+
+ let symbols = [];
+ while (data[offset] !== 0x00 && offset < data.length) { // 0x00 marks the end of a line
+ symbols.push(data[offset]);
+ offset++;
+ }
+
+ lines.push({ nextLineAddr, lineNumber, symbols });
+ offset++; // Move past the 0x00 byte
+ }
+ }
+
+ convertLines(lines, escapePetscii = false) {
+ var tokens = this.tokens;
+
+ var printedLines = lines.map(line => {
+ const lineNumberStr = line.lineNumber.toString();
+ const next = line.nextLineAddr.toString();
+ let inString = false; // Flag to track if we are inside a string
+ const symbolsStr = line.symbols.map(symbol => {
+ // Check if we're entering or exiting a string
+ if (symbol === 0x22) { // 0x22 is the ASCII code for "
+ inString = !inString;
+ return '"';
+ }
+
+ // If we're inside a string, or the symbol is unknown, convert to ASCII character
+ if (inString || !tokens[symbol]) {
+ if (inString && (symbol < 32 || symbol > 127)) {
+ if( escapePetscii ) {
+ return `\\x${symbol.toString(16).padStart(2, '0')}`;
+ }
+ return String.fromCharCode(symbol);
+ //return String.fromCharCode(symbol);
+ }
+ return String.fromCharCode(symbol);
+ }
+
+ // If it's a known token and we're not in a string, convert to the token representation
+ return tokens[symbol];
+ }).join('');
+
+ return `${lineNumberStr} ${symbolsStr}`;
+ });
+
+
+ return printedLines;
+ }
+
+ // Print the program
+ getTextProgramLines( escapePetscii = false) {
+
+ var printedLines =
+ this.convertLines(this.lines, escapePetscii );
+
+ return printedLines;
+ }
+
+
+}
+
+
+
+
+// Add more tokens as needed...
+
+// Load and parse the PRG file
+function loadPrgFile(filePath, action) {
+ fs.readFile(filePath, (err, data) => {
+ if (err) {
+ console.error('Error reading the file:', err);
+ return;
+ }
+
+ action(data);
+ // Check if it's a BASIC program
+
+ });
+}
+
+/*
+var pgm = new C64BasicProgram();
+
+// Replace 'your-program.prg' with the path to your actual PRG file
+loadPrgFile(path.join(__dirname, 'bombardement.prg')
+ , (data) => {
+ pgm.parseBasicProgram(data);
+
+ pgm.printProgram(pgm.printedLines);
+ }
+);
+*/
+
diff --git a/versions/0.8p5/res/script/errorhandler.js b/versions/0.8p5/res/script/errorhandler.js
new file mode 100644
index 0000000..9c1fea5
--- /dev/null
+++ b/versions/0.8p5/res/script/errorhandler.js
@@ -0,0 +1,47 @@
+class ErrorHandler {
+
+ newError( clazz, detail, context, lineNr ) {
+ return { context: context, clazz: clazz, detail: detail, lineNr: lineNr };
+ }
+
+ throwError( clazz, detail, context, lineNr ) {
+ throw this.newError( clazz, detail, context, lineNr );
+ }
+
+ fromSerializedError( s, context, lineNr0 ) {
+
+ var lineNr = lineNr0;
+ if( lineNr === undefined ) {
+ lineNr = -1;
+ }
+ if( ! this.isSerializedError( s ) ) {
+ return this.newError( "unknown", null, context, lineNr );
+ }
+ var parts = s.substr(1).split("@");
+ if( parts.length == 1 ) {
+ return this.newError( parts[0], null, context, lineNr );
+ }
+ return this.newError( parts[0], parts[1], context, lineNr );
+
+ }
+
+ isSerializedError( e ) {
+ if( typeof e != "string" ) {
+ return false;
+ }
+ return e.startsWith( "@" );
+ }
+
+ isError( e ) {
+ if( Object.prototype.toString.call( e ) === '[object Object]' ) {
+ var ctx = e[ "context" ];
+ var clss = e[ "clazz" ];
+ var dtl = e[ "detail" ];
+
+ if( !( clss === undefined ) ) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/versions/0.8p5/res/script/extendedcommands.js b/versions/0.8p5/res/script/extendedcommands.js
new file mode 100644
index 0000000..0857ae4
--- /dev/null
+++ b/versions/0.8p5/res/script/extendedcommands.js
@@ -0,0 +1,1562 @@
+class ExtendedCommands {
+
+ constructor( context ) {
+ this.console = context.console;
+ this.context = context;
+ this.cmds = {};
+ this.func = {};
+ this.enabled = false;
+
+ this.statementList = null;
+
+ this.g_colIndex = 1;
+ this.g_col0 = -1;
+ this.g_col1 = -1;
+ this.g_col2 = -1;
+
+ this.erh = new ErrorHandler();
+
+
+ }
+
+ enable( flag ) {
+ this.enabled = flag;
+ }
+
+ _intGetColorRecord() {
+ return {
+ c0: this.g_col0,
+ c1: this.g_col1,
+ c2: this.g_col2
+ }
+ }
+
+ _intGFXLine( _x0, _y0, _x1, _y1 ) {
+
+ var points = new Array();
+
+ if( _x0 == _x1 && _y0 == _y1 ) {
+ points.push( { x: Math.round(_x0), y: Math.round(_y0) } );
+ return points;
+ }
+
+ var x0 = _x0;
+ var y0 = _y0;
+ var x1 = _x1;
+ var y1 = _y1;
+
+ var w = Math.abs(x1 - x0);
+ var h = Math.abs(y1 - y0);
+
+ var tmp;
+ if( w > h ) {
+
+ if( x0 > x1 ) {
+ tmp = x0;
+ x0 = x1;
+ x1 = tmp;
+
+ tmp = y0;
+ y0 = y1;
+ y1 = tmp;
+ }
+
+ var yfact = 1;
+ if( y1 < y0 ) { yfact = -1 ;}
+ for( var x = 0; x<=w ; x++ ) {
+
+ var xx = x + x0;
+
+ var progress = (x / w);
+ var yy = y0 + (yfact * (progress * h));
+
+ points.push( { x:Math.round(xx), y:Math.round(yy) } );
+ }
+
+ }
+ else {
+
+ if( y0 > y1 ) {
+ tmp = x0;
+ x0 = x1;
+ x1 = tmp;
+
+ tmp = y0;
+ y0 = y1;
+ y1 = tmp;
+ }
+
+ var xfact = 1;
+ if( x1 < x0 ) { xfact = -1 ;}
+ for( var y = 0; y<=h ; y++ ) {
+
+ var yy = y + y0;
+
+ var progress = (y / h);
+ var xx = x0 + (xfact * (progress * w));
+
+ points.push( { x:Math.round(xx), y:Math.round(yy) } );
+ }
+ }
+
+ return points;
+ }
+
+ _intMirrorByte( b ) {
+ var c=this.context;
+ var bits = c._getByteBits( b );
+ var bits2 = [];
+
+ for(var i=0; i1) { pathProgress=1; }
+
+ if( _x0 == _x1 && _y0 == _y1 ) {
+ return { x: Math.round(_x0), y: Math.round(_y0) };
+ }
+
+ var x0 = _x0;
+ var y0 = _y0;
+ var x1 = _x1;
+ var y1 = _y1;
+
+ var w = Math.abs(x1 - x0);
+ var h = Math.abs(y1 - y0);
+
+ var tmp;
+ if( w > h ) {
+
+ if( x0 > x1 ) {
+ tmp = x0;
+ x0 = x1;
+ x1 = tmp;
+
+ tmp = y0;
+ y0 = y1;
+ y1 = tmp;
+ }
+
+ var yfact = 1;
+ if( y1 < y0 ) { yfact = -1 ;}
+ var lastpoint = w;
+
+ var thePointIx;
+ if( _x0 < _x1 ) {
+ thePointIx = Math.floor( lastpoint * pathProgress);
+ }
+ else {
+ thePointIx = Math.floor( lastpoint * (1-pathProgress));
+ }
+
+ for( var x = 0; x<=w ; x++ ) {
+ var xx = x + x0;
+
+ var progress = (x / w);
+ var yy = y0 + (yfact * (progress * h));
+
+ if( x == thePointIx ) {
+ return { x:Math.round(xx), y:Math.round(yy) };
+ }
+ }
+
+ }
+ else {
+
+ if( y0 > y1 ) {
+ tmp = x0;
+ x0 = x1;
+ x1 = tmp;
+
+ tmp = y0;
+ y0 = y1;
+ y1 = tmp;
+ }
+
+ var xfact = 1;
+ if( x1 < x0 ) { xfact = -1 ;}
+
+ var lastpoint = h;
+
+ var thePointIx;
+ if( _y0 < _y1 ) {
+ thePointIx = Math.floor( lastpoint * pathProgress);
+ }
+ else {
+ thePointIx = Math.floor( lastpoint * (1-pathProgress));
+ }
+
+ for( var y = 0; y<=h ; y++ ) {
+
+ var yy = y + y0;
+
+ var progress = (y / h);
+ var xx = x0 + (xfact * (progress * w));
+
+ if( y == thePointIx ) {
+ return { x:Math.round(xx), y:Math.round(yy) };
+ }
+ }
+ }
+
+ return{ x: _x0, y: _y0 };
+ }
+
+
+ getCategories() {
+ var stats = this._int_getStatements();
+ var funs = this._int_getFunctions();
+
+ var cat = {};
+ var catLists = {};
+
+ for( var i=0;i" + lbl);
+ this.context.printLine("-----------------");
+ for( var i=0; i 0 ) {
+ this.erh.throwError( "too many parameters" );
+ }
+
+ this.context.clearGFXScreen(
+ this.g_col0,
+ this.g_col1,
+ this.g_col2 );
+ }
+
+ _stat_info_gcls() { return "gfx"; }
+
+ _stat_slow( pars ) {
+ this.context.setTurbo( false );
+ }
+
+ _stat_synctime( pars ) {
+ this.context.synchClock();
+ }
+
+ _stat_renumber( pars ) {
+
+ var start = 100, step = 5;
+
+ if( pars.length == 1 ) {
+ start = pars[0].value;
+ }
+
+ if( pars.length == 2 ) {
+ start = pars[0].value;
+ step = pars[1].value;
+ }
+
+ if( pars.length > 2 ) {
+ this.erh.throwError( "too many parameters" );
+ return;
+ }
+
+ this.context.renumberProgram( start, step );
+
+ }
+
+ _stat_reformat( pars ) {
+
+ var start = 100, step = 100;
+
+ if( pars.length != 0 ) {
+ this.erh.throwError( "unexpected parameter" );
+ return;
+ }
+
+ this.context.normalizeProgram();
+
+ }
+ _stat_info_reformat() { return "disk"; }
+
+ _stat_dir( pars ) {
+ var dir = this.context.getDir();
+
+ this.context.sendChars( "DIR OF " +
+ "\u0012\""+dir.title+" \"\u0092" , true);
+
+ for( var i=0; i 3) {
+ this.erh.throwError( "mode unsupported", "0-3" );
+ return;
+ }
+
+ console.log ("setting gfx mode " + pars[0].value);
+
+ var ctx = this.context;
+ if( pars[0].value == 0 ) {
+ ctx.poke( 53265, ctx.peek(53265) & (255-32));
+ ctx.poke( 53270, ctx.peek(53270) & (255-16));
+ ctx.poke( 53272, ctx.peek(53272) & (255-8));
+ }
+ else if( pars[0].value == 1 ) {
+ ctx.poke( 53265, ctx.peek(53265) & (255-32));
+ ctx.poke( 53270, ctx.peek(53270) | 16 );
+ ctx.poke( 53272, ctx.peek(53272) & (255-8));
+ }
+ else if( pars[0].value == 2 ) {
+ ctx.poke( 53265, ctx.peek(53265) | 32 );
+ ctx.poke( 53270, ctx.peek(53270) & (255-16));
+ ctx.poke( 53272, ctx.peek(53272) | 8);
+ }
+ else if( pars[0].value == 3 ) {
+ ctx.poke( 53265, ctx.peek(53265) | 32 );
+ ctx.poke( 53270, ctx.peek(53270) | 16);
+ ctx.poke( 53272, ctx.peek(53272) | 8);
+ }
+ console.log(pars);
+
+ if( pars.length > 1 ) {
+ this.erh.throwError( "too many parameters" );
+ return;
+ }
+ }
+
+ _stat_info_mode() { return "gfx"; }
+
+ _stat_pen( pars ) {
+
+ if( pars.length < 1 ) {
+ this.erh.throwError( "col missing" );
+ return;
+ }
+ console.log(pars);
+
+ this.console.setColor( pars[0].value );
+
+ if( pars.length > 1 ) {
+ this.erh.throwError( "too many parameters" );
+ return;
+ }
+ }
+ _stat_info_pen() { return "text"; }
+
+
+ _stat_gpen( pars ) {
+ if( pars.length < 1 ) {
+ this.erh.throwError( "pen missing");
+ return;
+ }
+
+ this.g_colIndex = pars[0].value;
+ }
+ _stat_info_gpen() { return "gfx"; }
+
+
+ _stat_gcoldef( pars ) {
+
+ if( pars.length < 1 ) {
+ this.erh.throwError( "color index missing");
+ return;
+ }
+
+ if( pars.length < 2 ) {
+ this.erh.throwError( "color missing");
+ return;
+ }
+
+ var index = pars[0].value;
+ if(index<0 || index>2 ) {
+ this.erh.throwError( "index out of range");
+ }
+
+ if( index==0 ) {
+ this.g_col0 = pars[1].value;
+ }
+ else if( index==1 ) {
+ this.g_col1 = pars[1].value;
+ }
+ else if( index==2 ) {
+ this.g_col2 = pars[1].value;
+ }
+
+ if( pars.length > 2 ) {
+ this.erh.throwError( "too many params");
+ return;
+ }
+ }
+
+ _stat_info_gcoldef() { return "gfx"; }
+
+ _stat_gcolors( pars ) {
+
+ if( pars.length < 1 ) {
+ this.erh.throwError( "color0 missing");
+ return;
+ }
+ this.g_col0 = pars[0].value;
+
+ if( pars.length < 2 ) {
+ return;
+ }
+ this.g_col1 = pars[1].value;
+
+ if( pars.length < 3 ) {
+ return;
+ }
+ this.g_col2 = pars[2].value;
+
+ if( pars.length > 3 ) {
+ this.erh.throwError( "too many colors");
+ return;
+ }
+ }
+
+ _stat_info_gcolors() { return "gfx"; }
+
+ _if_seek() {
+ var EXPR = 0, PAR = 1, RAW=2;
+ return [RAW,RAW,RAW,RAW,RAW,RAW,RAW,RAW];
+ }
+
+ _stat_seek( pars ) {
+ console.log("seek");
+ var start = 0;
+ var end = 999999;
+ var parts = [];
+
+ var mode = "noparam";
+
+ if( pars.length==0 ) {
+ this.erh.throwError( "missing parameters" );
+ }
+
+ this.context.printLine( "" );
+ var context = this.context;
+
+ for (const l of context.program)
+ {
+ for( var i=0; i -1 ) {
+ this.context.listCodeLine( l[2] );
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ _if_debug() {
+ var EXPR = 0, PAR = 1, RAW=2;
+ return [RAW];
+ }
+
+ _stat_debug( pars ) {
+
+ var context = this.context;
+ var ln = context.runPointer;
+
+ var prefix = "DEBUG["+context.program[ln][0]+"]: ";
+ if( pars.length == 0 ) {
+ console.log( prefix+" ---------------" );
+ return;
+ }
+ else if( pars.length == 1 ) {
+ if( pars[0].parts.length == 0 ) {
+ console.log( prefix+" ---------------" );
+ return;
+ }
+ }
+
+ var newLine = true;
+ var value;
+ var buffer = "";
+ for( var i=0; i0) {
+ buffer+= " ";
+ }
+
+ var exparts = pars[i];
+ var exparts2=
+ { parts: [],
+ binaryNegate: exparts.binaryNegate,
+ negate: exparts.negate };
+
+ for( var j=0; j= 1 ) {
+ if( !(pars[0].value >=0
+ && pars[0].value <=14) ) {
+ this.erh.throwError( "range","must be in between 0-14");
+ }
+ }
+
+ if( pars.length >= 2 ) {
+ this.context.vpoke(53280 + pars[0].value, pars[1].value );
+ }
+ else {
+ this.erh.throwError( "color missing");
+ }
+ }
+
+ _stat_info_color() { return "text"; }
+
+ _stat_bgcolor( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "color missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.context.vpoke(53281 , pars[0].value );
+ return;
+ }
+
+ if( pars.length >= 2 ) {
+ this.erh.throwError( "too many params");
+ return;
+ }
+
+ }
+
+ _stat_info_bgcolor() { return "gfx"; }
+
+ _stat_border( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "color missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.context.poke(53280 , pars[0].value );
+ return;
+ }
+
+ if( pars.length >= 2 ) {
+ this.erh.throwError( "too many params");
+ return;
+ }
+
+ }
+
+ _stat_info_border() { return "gfx"; }
+
+ _stat_penpos( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "x missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "y missing");
+ return;
+ }
+
+ if( pars.length > 2 ) {
+ this.erh.throwError( "too many parameters");
+ return;
+ }
+
+ this.context.setCursor( pars[0].value %40, pars[1].value%25);
+
+ }
+
+ _stat_info_penpos() { return "text"; }
+
+ _stat_sprite( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "sprite nr missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "on/off flag");
+ return;
+ }
+
+ if( pars.length > 2 ) {
+ this.erh.throwError( "too many parameters");
+ return;
+ }
+
+ this.context.spriteEnable( pars[0].value %8, pars[1].value %2 );
+
+ }
+
+ _stat_info_sprite() { return "sprite"; }
+
+ _stat_scolmod( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "sprite nr missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "mode flag");
+ return;
+ }
+
+ if( pars.length > 2 ) {
+ this.erh.throwError( "too many parameters");
+ return;
+ }
+
+ this.context.spriteMultiCol( pars[0].value %8, pars[1].value %2 );
+
+ }
+
+ _stat_info_scolmod() { return "sprite"; }
+
+ _stat_sdouble( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "sprite nr missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "x flag");
+ return;
+ }
+
+ if( pars.length == 2 ) {
+ this.erh.throwError( "y flag");
+ return;
+ }
+
+ if( pars.length > 3 ) {
+ this.erh.throwError( "too many parameters");
+ return;
+ }
+
+ this.context.spriteDouble( pars[0].value %8, pars[1].value %2, pars[2].value %2 );
+
+ }
+
+ _stat_info_sdouble() { return "sprite"; }
+
+ _stat_sfcopy( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "srcframe");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "dstframe");
+ return;
+ }
+
+ if( pars.length > 2 ) {
+ this.erh.throwError( "too many parameters");
+ return;
+ }
+
+ this.context.spriteFrameCopy( pars[0].value %256, pars[1].value %256 );
+ }
+
+ _stat_info_sfcopy() { return "sprite"; }
+
+
+ _int_sfxflip( data ) {
+
+ for( var i=0;i 2 ) {
+ this.erh.throwError( "too many parameters");
+ return;
+ }
+
+ var fx = pars[1].value;
+ if( ! ( fx == 0 || fx == 1)) {
+ this.erh.throwError( "unknown fx");
+ return;
+ }
+
+ var data = this.context.spriteFrameGet( pars[0].value %256 );
+
+ if( fx == 0 ) {
+ this._int_sfxflip( data );
+ }
+ else if( fx == 0 ) {
+ this._int_sfyflip( data );
+ }
+ else if( fx == 10 || fx == 11) {
+ var mask = [];
+ mask.push(128+32+8+2);
+ mask.push(64+16+4+1);
+ var flip = fx-10;
+ for( var i=0;i<63;i+=3) {
+ data[i] = data[i] & mask[flip];
+ data[i+1] = data[i+1] & mask[flip];
+ data[i+2] = data[i+2] & mask[flip];
+ flip = 1 - flip;
+ }
+ }
+
+ this.context.spriteFrameSet( pars[0].value %256, data );
+
+ }
+
+ _stat_info_sfx() { return "sprite"; }
+
+ _stat_sframe( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "sprite nr missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "frame");
+ return;
+ }
+
+ if( pars.length > 2 ) {
+ this.erh.throwError( "too many parameters");
+ return;
+ }
+
+ this.context.spriteFrame( pars[0].value %8, pars[1].value );
+ }
+
+ _stat_info_sframe() { return "sprite"; }
+
+ _stat_scol( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "sprite nr missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "color");
+ return;
+ }
+
+ if( pars.length > 2 ) {
+ this.erh.throwError( "too many parameters");
+ return;
+ }
+
+ this.context.spriteColor( pars[0].value %8, pars[1].value %16 );
+
+ }
+
+ _stat_info_scol() { return "sprite"; }
+
+ _stat_sfpoke( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "frame nr missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "address");
+ return;
+ }
+
+ if( pars.length == 2 ) {
+ this.erh.throwError( "value");
+ return;
+ }
+
+ if( pars.length > 3 ) {
+ this.erh.throwError( "too many parameters");
+ return;
+ }
+
+ this.context.spriteFramePoke(
+ pars[0].value % 256, //frame
+ pars[1].value % 64, //offset
+ pars[2].value % 256, //value
+ );
+
+ }
+
+ _stat_info_sfpoke() { return "sprite"; }
+
+ _stat_spos( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "sprite nr missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "x");
+ return;
+ }
+
+ if( pars.length == 2 ) {
+ this.erh.throwError( "y");
+ return;
+ }
+
+ if( pars.length > 3 ) {
+ this.erh.throwError( "too many parameters");
+ return;
+ }
+
+ this.context.spritePos(
+ pars[0].value,
+ pars[1].value % 512,
+ pars[2].value % 256,
+ );
+
+ }
+
+ _stat_info_spos() { return "sprite"; }
+
+ _if_path() {
+ var EXPR = 0, PAR = 1, RAW=2;
+ return [EXPR,EXPR,EXPR,EXPR,EXPR,PAR,PAR];
+ }
+
+ _stat_path( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "x1 missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "y1 missing");
+ return;
+ }
+
+ if( pars.length == 2 ) {
+ this.erh.throwError( "x2 missing");
+ return;
+ }
+
+ if( pars.length == 3 ) {
+ this.erh.throwError( "y2 missing");
+ return;
+ }
+
+ if( pars.length == 4 ) {
+ this.erh.throwError( "progress missing");
+ return;
+ }
+
+ if( pars.length == 5 ) {
+ this.erh.throwError( "xout missing");
+ return;
+ }
+
+ if( pars.length == 6 ) {
+ this.erh.throwError( "yout missing");
+ return;
+ }
+
+ if( pars.length >7 ) {
+ this.erh.throwError( "too many params");
+ return;
+ }
+
+ var p5 = pars[ 5 ];
+ var p6 = pars[ 6 ];
+
+ if( p5.type != "var" ) {
+ this.erh.throwError( "not a variable" );
+ }
+
+ if( p6.type != "var" ) {
+ this.erh.throwError( "not a variable" );
+ }
+
+ var progress = pars[4].value;
+
+ var thePoint = this._intGFXPointOnLine(
+ Math.floor( pars[0].value ),
+ Math.floor( pars[1].value ),
+ Math.floor( pars[2].value ),
+ Math.floor( pars[3].value ),
+ progress
+ );
+
+ this.context.setVar(p5.value, thePoint.x );
+ this.context.setVar(p6.value, thePoint.y );
+
+ }
+
+ _stat_line( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "x1 missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "y1 missing");
+ return;
+ }
+
+ if( pars.length == 2 ) {
+ this.erh.throwError( "x2 missing");
+ return;
+ }
+
+ if( pars.length == 3 ) {
+ this.erh.throwError( "y2 missing");
+ return;
+ }
+
+ if( pars.length >5 ) {
+ this.erh.throwError( "too many params");
+ return;
+ }
+
+ var colIndex = -1;
+ if( pars.length == 5 ) {
+ colIndex =
+ pars[4].value % 4;
+ }
+ else {
+ colIndex = this.g_colIndex;
+ }
+ if( colIndex < 0 ) {
+ this.erh.throwError( "pen is -1" );
+ }
+
+
+ this.context.drawLine(
+ { c:this, m: "_intGFXLine"},
+ Math.floor( pars[0].value ) %320,
+ Math.floor( pars[1].value ) %200,
+ Math.floor( pars[2].value ) %320,
+ Math.floor( pars[3].value ) %200,
+ this._intGetColorRecord(),
+ colIndex );
+
+ }
+
+ _stat_info_line() { return "gfx"; }
+
+ _stat_box( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "x1 missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "y1 missing");
+ return;
+ }
+
+ if( pars.length == 2 ) {
+ this.erh.throwError( "x2 missing");
+ return;
+ }
+
+ if( pars.length == 3 ) {
+ this.erh.throwError( "y2 missing");
+ return;
+ }
+
+ if( pars.length >5 ) {
+ this.erh.throwError( "too many params");
+ return;
+ }
+
+ var colIndex = -1;
+ if( pars.length == 5 ) {
+ colIndex =
+ pars[4].value % 4;
+ }
+ else {
+ colIndex = this.g_colIndex;
+ }
+ if( colIndex < 0 ) {
+ this.erh.throwError( "pen is -1");
+ }
+
+ this.context.drawBox(
+ Math.floor( pars[0].value ) %320,
+ Math.floor( pars[1].value ) %200,
+ Math.floor( pars[2].value ) %320,
+ Math.floor( pars[3].value ) %200,
+ this._intGetColorRecord(),
+ colIndex );
+
+
+ }
+
+ _stat_info_box() { return "gfx"; }
+
+ _stat_hline( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "x1 missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "y1 missing");
+ return;
+ }
+
+ if( pars.length == 2 ) {
+ this.erh.throwError( "x2 missing");
+ return;
+ }
+
+ if( pars.length >4 ) {
+ this.erh.throwError( "too many params");
+ return;
+ }
+
+ var colIndex = -1;
+ if( pars.length == 4 ) {
+ colIndex =
+ pars[3].value % 4;
+ }
+ else {
+ colIndex = this.g_colIndex;
+ }
+ if( colIndex < 0 ) {
+ this.erh.throwError( "pen is -1");
+ }
+
+ this.context.drawBox(
+ Math.floor( pars[0].value ) %320,
+ Math.floor( pars[1].value ) %200,
+ Math.floor( pars[2].value ) %320,
+ Math.floor( pars[1].value ) %200,
+ this._intGetColorRecord(),
+ colIndex );
+
+ }
+
+ _stat_info_hline() { return "gfx"; }
+
+ _stat_plot( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "x missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "y missing");
+ return;
+ }
+
+ if( pars.length > 3 ) {
+ this.erh.throwError( "too many parameters");
+ return;
+ }
+
+ var colIndex = -1;
+ if( pars.length == 3 ) {
+ colIndex =
+ pars[2].value % 4;
+ }
+ else {
+ colIndex = this.g_colIndex;
+ }
+ if( colIndex < 0 ) {
+ this.erh.throwError( "pen is -1");
+ }
+
+ this.context.setPixel(
+ Math.floor( pars[0].value ) %320,
+ Math.floor( pars[1].value ) %200,
+ this._intGetColorRecord(),
+ colIndex );
+
+ }
+ _stat_info_plot() { return "gfx"; }
+
+ _stat_charcol( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "x missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "y missing");
+ return;
+ }
+
+ if( pars.length == 2 ) {
+ this.erh.throwError( "col missing");
+ return;
+ }
+
+ if( pars.length == 3 ) {
+ this.context.setTextCol(
+ pars[0].value %40,
+ pars[1].value %25,
+ pars[2].value %16
+ );
+
+ return;
+ }
+
+ if( pars.length > 3 ) {
+ this.erh.throwError( "too many parameters");
+ return;
+ }
+ }
+
+ _stat_info_charcol() { return "text"; }
+
+
+ _stat_char( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "x missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "y missing");
+ return;
+ }
+
+ if( pars.length == 2 ) {
+ this.erh.throwError( "charcode missing");
+ return;
+ }
+
+ if( pars.length == 3 ) {
+ this.context.setTextChar(
+ pars[0].value %40,
+ pars[1].value %25,
+ pars[2].value %256
+ );
+
+ return;
+ }
+
+ if( pars.length > 3 ) {
+ this.erh.throwError( "too many parameters");
+ return;
+ }
+ }
+ _stat_info_char() { return "text"; }
+
+ /************************ functions ************************/
+
+ _fun_pixcol( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "x missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "y missing");
+ return;
+ }
+
+ if( pars.length == 2 ) {
+ return this.context.getPixel(
+ pars[0].value %320,
+ pars[1].value %200,
+ 0
+ );
+ }
+
+ if( pars.length > 2 ) {
+ this.erh.throwError( "too many parameters");
+ }
+
+ }
+ _fun_info_pixcol() { return "gfx"; }
+
+ _fun_pixel( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "x missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "y missing");
+ return;
+ }
+
+ if( pars.length == 2 ) {
+ return this.context.getPixel(
+ pars[0].value %320,
+ pars[1].value %200,
+ 0
+ );
+ }
+
+ if( pars.length > 2 ) {
+ this.erh.throwError( "too many parameters");
+ }
+
+ }
+ _fun_info_pixel() { return "gfx"; }
+
+
+ _fun_char( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "x missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "y missing");
+ return;
+ }
+
+ if( pars.length > 2 ) {
+ this.erh.throwError( "too many parameters");
+ }
+
+ return this.context.getTextChar(
+ pars[0].value %40,
+ pars[1].value %25
+ );
+ }
+ _fun_info_char() { return "text"; }
+
+ _fun_charcol( pars ) {
+
+ if( pars.length == 0 ) {
+ this.erh.throwError( "x missing");
+ return;
+ }
+
+ if( pars.length == 1 ) {
+ this.erh.throwError( "y missing");
+ return;
+ }
+
+ if( pars.length > 2 ) {
+ this.erh.throwError( "too many parameters");
+ }
+
+ return this.context.getTextColor(
+ pars[0].value %40,
+ pars[1].value %25
+ );
+ }
+
+ _fun_info_charcol() { return "text"; }
+
+}
diff --git a/versions/0.8p5/res/script/g1/core/blockfont.js b/versions/0.8p5/res/script/g1/core/blockfont.js
new file mode 100644
index 0000000..faea36d
--- /dev/null
+++ b/versions/0.8p5/res/script/g1/core/blockfont.js
@@ -0,0 +1,149 @@
+class BlockFont {
+
+ constructor( img, gridw, gridh, transCol ) {
+
+ this.img = img;
+ this.gridw = gridw;
+ this.gridh = gridh;
+
+ this.iconsCanvas = [];
+ this.iconsContext = [];
+
+ var w = this.img.width;
+ var h = this.img.height;
+
+ this.iconCanvas = document.createElement('canvas');
+ this.iconContext = this.iconCanvas.getContext('2d');
+
+ this.iconCanvas.width = w;
+ this.iconCanvas.height = h;
+
+ this.iconContext.drawImage( this.img, 0, 0, w, h);
+
+ this.xiconcount = w / this.gridw;
+ this.xiconrowcount = h / this.gridh;
+
+ for (var yicon = 0; yicon < this.xiconrowcount; yicon++) {
+ for (var xicon = 0; xicon < this.xiconcount; xicon++) {
+
+ var sx = (xicon * this.gridw);
+ var sy = (yicon * this.gridh);
+ var imgdata = this.iconContext.getImageData(sx, sy, this.gridw, this.gridh);
+ var sd = imgdata.data;
+
+ var dcanvas = document.createElement('canvas');
+ dcanvas.width = this.gridw;
+ dcanvas.height = this.gridh;
+
+ var dcontext = dcanvas.getContext('2d');
+ var dimgdata = dcontext.createImageData( this.gridw, this.gridh );
+ var dd = dimgdata.data;
+
+ var xoffset = 0;
+ var yoffset = 0;
+ var rowoffset = this.gridw * 4;
+ var offset;
+
+ for (var y = 0; y < this.gridh; y++) {
+ xoffset = 0;
+ for (var x = 0; x < this.gridw; x++) {
+ offset = yoffset + xoffset;
+
+ dd[ offset + 0] = sd[ offset + 0];
+ dd[ offset + 1] = sd[ offset + 1];
+ dd[ offset + 2] = sd[ offset + 2];
+ dd[ offset + 3] = sd[ offset + 3];
+
+ if( dd[ offset + 0] == transCol.r && dd[ offset + 1] == transCol.g && dd[ offset + 2] == transCol.b )
+ {
+ dd[ offset + 0] = 0;
+ dd[ offset + 1] = 0;
+ dd[ offset + 2] = 0;
+ dd[ offset + 3] = 0; /* Make transparent */
+ }
+
+ xoffset += 4;
+ }
+
+ yoffset += rowoffset;
+ }
+
+ dcontext.putImageData( dimgdata, 0, 0);
+ this.iconsCanvas.push( dcanvas );
+ this.iconsContext.push( dcontext );
+ }
+ }
+
+ this.iconCanvas = null;
+ this.iconContext = null;
+ this.img = null;
+
+ }
+
+ mapChar( c0 ) {
+
+ var c = c0.toLowerCase();
+
+ var map = [];
+ var index;
+
+ map['a'] = 0; map['b'] = 1;
+ map['c'] = 2; map['d'] = 3;
+ map['e'] = 4; map['f'] = 5;
+ map['g'] = 6; map['h'] = 7;
+ map['i'] = 8; map['j'] = 9;
+ map['k'] = 10; map['l'] = 11;
+ map['m'] = 12; map['n'] = 13;
+ map['o'] = 14; map['p'] = 15;
+ map['q'] = 16; map['r'] = 17;
+ map['s'] = 18; map['t'] = 19;
+ map['u'] = 20; map['v'] = 21;
+ map['w'] = 22; map['x'] = 23;
+ map['y'] = 24; map['z'] = 25;
+
+ map['0'] = 26; map['1'] = 27;
+ map['2'] = 28; map['3'] = 29;
+ map['4'] = 30; map['5'] = 31;
+ map['6'] = 32; map['7'] = 33;
+ map['8'] = 34; map['9'] = 35;
+ map['@'] = 36; map['&'] = 37;
+ map['*'] = 38; map['+'] = 39;
+ map['|'] = 40; map['_'] = 41;
+ map['.'] = 42; map[','] = 43;
+ map[':'] = 44; map['()'] = 45;
+ map[')'] = 46; map['-'] = 47;
+ map['#'] = 48; map['?'] = 49;
+ map['%'] = 50; map['!'] = 51;
+
+ index = map [ c ];
+ if( index == undefined ) {
+ if( c == ' ' ) {
+ return -1;
+ }
+ index = 49;
+ }
+
+ return index;
+ }
+
+ drawChar( ctx, x, y, c ) {
+ var index = this.mapChar( c );
+ if( index > -1 ) {
+ ctx.drawImage( this.iconsCanvas[ index ], x, y, );
+ }
+ }
+
+ centerX( str, screenWidth ) {
+ var txtW = str.length * this.gridw;
+ return Math.floor( (screenWidth/2) - ( txtW/2)) ;
+ }
+
+ drawString( ctx, x0, y, str ) {
+ var x = x0;
+ for (var i = 0; i < str.length; i++) {
+ this.drawChar( ctx, x, y, str.charAt(i) );
+ x+= this.gridw;
+ }
+ }
+
+}
diff --git a/versions/0.8p5/res/script/g1/core/blockimage.js b/versions/0.8p5/res/script/g1/core/blockimage.js
new file mode 100644
index 0000000..2c5540e
--- /dev/null
+++ b/versions/0.8p5/res/script/g1/core/blockimage.js
@@ -0,0 +1,288 @@
+var BlockImage_counter = 0;
+
+class BlockImage {
+
+ constructor( a, b ) {
+
+ if( typeof( a ) == "object") {
+ if( a.width != undefined ) {
+ this.initFromImage( a );
+ }
+ }
+ else {
+ this.initNewCanvas( a, b );
+ }
+
+ }
+
+ initNewCanvas( w, h ) {
+
+ this.canvas = document.createElement('canvas');
+
+ this.canvas.id = "ImageCanvasContext_" + BlockImage_counter++;
+ this.canvas.width = w;
+ this.canvas.height = h;
+
+ this.w = w;
+ this.h = h;
+
+ this.context = this.canvas.getContext('2d',{ alpha: false, desynchronized: true });
+ }
+
+ initFromImage( img ) {
+
+ this.canvas = document.createElement('canvas');
+
+ this.canvas.id = "ImageCanvasContext_" + BlockImage_counter++;
+ this.canvas.width = img.width;
+ this.canvas.height = img.height;
+
+ this.w = img.width;
+ this.h = img.height;
+
+ this.source = img;
+
+ var context = this.canvas.getContext('2d',{ alpha: false, desynchronized: true });
+ context.drawImage(img, 0, 0);
+ this.context = context;
+
+ }
+
+
+ reInit() {
+ if( this.source != undefined ) {
+ this.initFromImage( this.source );
+ }
+ }
+
+
+ copy() {
+
+ var tmpImgCtxCanv = new BlockImage();
+
+ tmpImgCtxCanv.initNewCanvas( this.w, this.h );
+ tmpImgCtxCanv.context.drawImage( this.canvas, 0, 0);
+
+ return tmpImgCtxCanv;
+
+ }
+
+ getCopyAllData() {
+ return this.context.getImageData(0, 0, this.w, this.h);
+ }
+
+ getContext() {
+ return this.context;
+ }
+
+ getCanvas() {
+ return this.canvas;
+ }
+
+ setAllData( data ) {
+ this.context.putImageData(data, 0, 0);
+ }
+
+ flipX() {
+
+ var imgCtxCanv = this;
+
+ var tmpImgCtxCanv = imgCtxCanv.copy( );
+ var w=tmpImgCtxCanv.w;
+ var h=tmpImgCtxCanv.h;
+ var srcIData = tmpImgCtxCanv.getCopyAllData();
+ var dstIData = imgCtxCanv.getCopyAllData();
+ var srcData = srcIData.data;
+ var dstData = dstIData.data;
+
+ var yoffset = 0;
+
+ for( var y=0; y 0 ) {
+ if( this.char_count( stateId, '.' ) > 1 ) {
+ throw "State name/id " + stateId+ " can only point out one subclass. (can only contain one dot)";
+ }
+
+ var parts = stateId.split('.');
+
+ this.stateClass = this.bookClass[ parts[0] ];
+
+ this.method = parts[ 1 ] ;
+
+ if( this.debugFlag ) {
+ console.log( this.stateClass );
+ }
+ }
+
+ var myClass = this.stateClass;
+
+
+ if( this.state.__typedef.LOD == true ||
+ this.state.__typedef.INI == true ||
+ this.state.__typedef.CLE == true) {
+
+
+ if (typeof this.stateClass[ this.method ] !== "function") {
+ throw "Class " + this.stateClass.constructor.name +
+ " does not contain elementary state function " + this.method + "(...)'" +
+ ", but state " + stateId+ " contains LOAD, INIT or CLEANUP as state type.";
+ }
+ }
+
+ if( this.state.__typedef.LOD == true ) {
+
+ var method = this.method + "";
+ var data = { currentState: this.stateId , resources: null };
+ this.stateClass[ this.method ]( 'GETURLS', data );
+
+ if( data.urls == null ) {
+ var newState = this.state[ 'next' ];
+ if( this.debugFlag ) {
+ console.log( "seturls ended, no resources, nextstate => " + newState );
+ }
+ this.gotoState( newState );
+ return;
+ }
+
+ this.loadResources( data.urls );
+ //return;
+ }
+
+ if( this.state.__typedef.INI == true ) {
+ this.stateClass[ this.method ]( 'INIT' );
+
+ if( this.state.__typedef.REN == false && this.state.__typedef.PRO == false )
+ {
+ var newState = this.state[ 'next' ];
+ if( this.debugFlag ) {
+ console.log( "init ended, nothing more to do, nextstate => " + newState );
+ }
+ this.gotoState( newState );
+ return;
+ }
+
+ }
+ if( this.state.__typedef.REN == true && this.state.__typedef.LOD == true ) {
+ this.methodRender = this.method + definitions.stateMethodSuffix.LSRENDER;
+
+ if (typeof this.stateClass[ this.methodRender ] !== "function") {
+ throw "Class " + this.stateClass.constructor.name +
+ " does not contain render state function " + this.methodRender + "(...)'" +
+ ", but state " + stateId+ " contains LSRENDER as state type.";
+ }
+ }
+ if( this.state.__typedef.REN == true && this.state.__typedef.LOD == false ) {
+ this.methodRender = this.method + definitions.stateMethodSuffix.RENDER;
+
+ if (typeof this.stateClass[ this.methodRender ] !== "function") {
+ throw "Class " + this.stateClass.constructor.name +
+ " does not contain render state function " + this.methodRender + "(...)'" +
+ ", but state " + stateId+ " contains RENDER as state type.";
+ }
+
+ }
+ if( this.state.__typedef.PRO == true && this.state.__typedef.LOD == true ) {
+ this.methodProcess = this.method + definitions.stateMethodSuffix.LSPROCESS;
+
+ if (typeof this.stateClass[ this.methodProcess ] !== "function") {
+ throw "Class " + this.stateClass.constructor.name +
+ " does not contain process state function " + this.methodProcess + "(...)'" +
+ ", but state " + stateId+ " contains LSPROCESS as state type.";
+ }
+ }
+ if( this.state.__typedef.PRO == true && this.state.__typedef.LOD == false ) {
+ this.methodProcess = this.method + definitions.stateMethodSuffix.PROCESS;
+
+ if (typeof this.stateClass[ this.methodProcess ] !== "function") {
+ throw "Class " + this.stateClass.constructor.name +
+ " does not contain process state function " + this.methodProcess + "(...)'" +
+ ", but state " + stateId+ " contains PROCESS as state type.";
+ }
+
+ }
+ if( this.state.__typedef.INP == true ) {
+ this.methodEvents = this.method + definitions.stateMethodSuffix.HANDLEINPUT;
+
+ if (typeof this.stateClass[ this.methodEvents ] !== "function") {
+ throw "Class " + this.stateClass.constructor.name +
+ " does not contain process state function " + this.methodEvents + "(...)'" +
+ ", but state " + stateId+ " contains HANDLEINPUT as state type.";
+ }
+
+ }
+ if( this.state.__typedef.BRA == true ) {
+
+ var stateChange = this.state._branchFunction( this.bookClass );
+
+ if( stateChange == false ) {
+ throw "State ("+this.stateId+") MUST return a next event";
+ }
+
+ if( this.state[ stateChange ] == undefined ) {
+ throw "unknown exitEvent '"+ stateChange +"' in state ("+this.stateId+")";
+ }
+
+
+ if( this.state[ stateChange ] == undefined ) {
+ throw "unknown exitEvent '"+ stateChange +"' in state ("+this.stateId+")";
+ }
+ this.gotoState( this.state[ stateChange ] );
+ }
+ }
+
+ loadResources( resources ) {
+
+ var myClass = this.stateClass;
+
+ var myArray, myDestArray, myState;
+ var imgState, audioState, dataState;
+ imgState = { count:0 };
+ audioState = { count:0 };
+ dataState = { count:0 };
+
+ imgState.load = false;
+ audioState.load = false;
+ dataState.load = false;
+
+ if( resources == undefined ) {
+ this.gotoState( this.state.next );
+ return;
+ }
+
+ myArray = resources.imgSrcArray;
+ myState = imgState;
+ if( myArray != undefined ) {
+ myState.keys = Object.keys( myArray );
+ myState.urls = myArray;
+ myState.count = myState.keys.length;
+ if( myState.count > 0 ) {
+ myState.load = true;
+ }
+ }
+
+ myArray = resources.audioSrcArray;
+ myState = audioState;
+ if( myArray != undefined ) {
+ myState.keys = Object.keys( myArray );
+ myState.urls = myArray;
+ myState.count = myState.keys.length;
+ if( myState.count > 0 ) {
+ myState.load = true;
+ }
+ }
+
+ myArray = resources.dataSrcArray;
+ myState = dataState;
+ if( myArray != undefined ) {
+ myState.keys = Object.keys( myArray );
+ myState.urls = myArray;
+ myState.count = myState.keys.length;
+ if( myState.count > 0 ) {
+ myState.load = true;
+ }
+ }
+
+ this.loadedCount = 0;
+ this.loadingCount = imgState.count + audioState.count + dataState.count;
+
+ if( this.loadingCount == 0 ) {
+ this.gotoState( this.state.next );
+ return;
+ }
+
+ var loadedResources = {};
+ loadedResources.imgArray = [];
+ loadedResources.audioArray = [];
+ loadedResources.dataArray = [];
+
+ myArray = resources.imgSrcArray;
+ myDestArray = loadedResources.imgArray;
+ myState = imgState;
+ for( var i=0; i response.json())
+ .then((data) => {
+ var evt = { currentTarget: { id: 'jsondata.'+url } };
+
+ if( __this.debugFlag ) {
+ console.log(data)
+ }
+ res.data = data;
+
+ __this.onLoadedResource( evt, myClass, loadedResources );
+ })
+ }
+ else {
+ fetch( url )
+ .then(response => response.text())
+ .then((data) => {
+ var evt = { currentTarget: { id: 'txtdata.'+url } };
+ if( __this.debugFlag ) {
+ console.log(data)
+ }
+ res.data = data;
+
+ __this.onLoadedResource( evt, myClass, loadedResources );
+ })
+ }
+ }
+
+ onLoadedResource( evt, myClass, loadedResources ) {
+
+ if( this.debugFlag ) {
+ console.log("resource is loaded " + evt.currentTarget.id );
+ }
+
+ this.loadedCount ++;
+
+ if( this.debugFlag ) {
+ console.log("resources loaded " + this.loadedCount );
+ console.log("resources to be loaded " + this.loadingCount );
+ }
+
+ if( this.loadedCount == this.loadingCount ) {
+ if( this.debugFlag ) {
+ console.log("all loaded, signalling");
+ }
+
+ var data = { currentState: this.stateId , resources: loadedResources };
+ this.stateClass[ this.method ]( 'LOADED', data );
+
+ if( this.debugFlag ) {
+ console.log("goto next state " + this.state.next);
+ }
+ this.gotoState(this.state.next );
+ }
+ }
+
+
+ gotoNextState() {
+
+ this.gotoState( this.state.next );
+ return null;
+ }
+
+ handleEvent( evt ) {
+
+ var myClass = this.stateClass;
+ try {
+ if( this.methodEvents != undefined ) {
+ myClass[ this.methodEvents ]( evt );
+ }
+ }
+ catch ( except ) {
+ var err = {};
+ err.message="Exception[" +
+ myClass.constructor.name + "." + this.methodEvents + "(...) at chapter '" + this.getCurrentPlayBookId()+ "']:" + except.message;
+ err.exception = except;
+ err.myClass = myClass;
+
+ console.log( except );
+ throw err;
+ }
+
+ }
+
+ renderFrame( ctx, exceptionHandler ) {
+
+ var myClass = this.stateClass;
+
+ if( myClass == undefined ) {
+ throw "game1.state[" + this.getCurrentPlayBookId() + "]."+this.methodRender+":Cannot execute, 'myClassUndefined' for chapter '" + this.getCurrentPlayBookId() +"'";
+ }
+
+ try {
+ if( this.methodRender != undefined ) {
+ myClass[this.methodRender]( ctx );
+ }
+ }
+ catch ( except ) {
+ var err = {};
+ err.message="Exception[" +
+ myClass.constructor.name + "." + this.methodRender + "(...) at chapter '" + this.getCurrentPlayBookId()+ "']:" + except.message;
+ err.exception = except;
+ err.myClass = myClass;
+
+ exceptionHandler.doException( err );
+ }
+
+ if( this.exception == false ) {
+
+ gameRenderFrameFunctionRec = {
+ _this: this,
+ ctx: ctx,
+ exceptionHandler: exceptionHandler
+ };
+
+
+ requestAnimationFrame( gameRenderFrameFunction );
+ }
+
+ }
+
+ processIteration () {
+
+ var myClass = this.stateClass;
+
+ if( myClass == undefined ) {
+ throw "game1.state[" + this.getCurrentPlayBookId() + "].processIteration:Cannot execute, 'myClassUndefined' for chapter '" + this.getCurrentPlayBookId() +"'";
+ }
+
+ var stateChange = false;
+
+ if( this.methodProcess != null ) {
+ stateChange = myClass[this.methodProcess]();
+ }
+
+
+ if( stateChange != false ) {
+ if( this.state._type == "WATCH" && stateChange != 'next' ) {
+ throw "Only next or false allowed in run phase of WATCH state ("+this.stateId+")";
+ }
+
+ if( this.state[ stateChange ] == undefined ) {
+ throw "unknown exitEvent '"+ stateChange +"' in state ("+this.stateId+")";
+ }
+ this.gotoState( this.state[ stateChange ] );
+ }
+ }
+}
+
+class DefaultStateDefinitions {
+
+ constructor ( classObject ) {
+
+ this.startPlaybook = "basic";
+
+ /* -----------------------------------------------------
+ Playbooks
+ ----------------------------------------------------- */
+
+ this.playbooks = {
+ basic: { object: classObject, enter: 'load', definition: this },
+ };
+
+ /* -----------------------------------------------------
+ Global state setup
+ ----------------------------------------------------- */
+
+ this.stateTypes = {
+ LOADSILENT: ['LOAD'],
+ PLAY: ['INIT','CLEANUP','RENDER','PROCESS','HANDLEINPUT'],
+ WATCH: ['INIT','CLEANUP','RENDER','PROCESS'],
+ INIT: ['INIT'],
+ BRANCH: ['BRANCH']
+ };
+
+ this.stateMethodSuffix = {
+ LSRENDER: undefined,
+ LSPROCESS: undefined,
+ RENDER: 'Render',
+ PROCESS: 'Run',
+ HANDLEINPUT: 'Handle'
+ };
+
+
+ /* basic playbook */
+ var playbook = this.playbooks.basic;
+ playbook.states = {
+
+ /* Only load, play and repeat since this is a demo, not a game */
+
+ 'load': { _type: "LOADSILENT", next: 'play'},
+ 'play': { _type: "PLAY", next: 'play' },
+
+ } ;
+ }
+}
+
+
+class Boot {
+ constructor ( _renderCanvasId, _SCRW, _SCRH, stateDefinitions ) {
+
+ /* Prevent reload, without confirmation */
+ window.onbeforeunload = function() {
+ return "";
+ }
+
+ document.addEventListener('contextmenu', event => event.preventDefault());
+
+ this.renderCanvasId = _renderCanvasId;
+ this.renderCanvas = document.getElementById( _renderCanvasId );
+
+ this.renderCanvas.style.touchAction = "none";
+
+ this.renderCanvas.id = "ApplicationCanvas";
+ this.SCRW = _SCRW;
+ this.SCRH = _SCRH;
+
+ this.properties = {};
+ this.properties.w = _SCRW;
+ this.properties.h = _SCRH;
+
+ this.sizeCanvas( this.SCRW, this.SCRH );
+ this.renderContext = this.renderCanvas.getContext('2d',
+ {
+ alpha: false,
+ desynchronized: true
+ });
+
+ this.renderContext.fillStyle = 'rgba(100,100,150,1)';
+ this.renderContext.fillRect(
+ 0,
+ 0,
+ _SCRW,
+ _SCRH
+ );
+
+ if( Array.isArray( stateDefinitions ) ) {
+ var errorString = "new Boot( ..., ..., ..., stateDefinitions ), stateDefinitions must be either and object or an array of [ runClassObject, 'basic' ]";
+ if( stateDefinitions.length != 2 ) {
+ throw errorString;
+ }
+ else {
+ if( stateDefinitions[ 1 ] != 'basic' ) {
+ throw errorString;
+ }
+ }
+
+ var stateDef = new DefaultStateDefinitions( stateDefinitions[ 0 ] );
+ this.state = new GameState ( stateDef, this.properties );
+ }
+ else {
+ this.state = new GameState ( stateDefinitions, this.properties );
+ }
+
+ var __this = this;
+
+ try {
+ this.state.renderFrame( this.renderContext, this );
+ }
+ catch( except ) {
+ console.log( "RENDER ERROR");
+ }
+
+ this.loopTimer = setInterval(
+ function() {
+
+ __this.state.processIteration();
+
+ }
+ , 20
+ );
+
+
+ this.renderCanvas.addEventListener("keyup", this.state, true);
+ this.renderCanvas.addEventListener("keydown", this.state, true);
+
+ }
+
+
+ doException( obj ) {
+ this.state.exception = true;
+ this.logException( obj );
+ }
+
+ logException( obj ) {
+
+ var cause = obj;
+
+ if( obj.message != undefined ) {
+ cause = obj.message;
+ }
+ var parts = cause.split(":");
+
+ var consoletext = 'Zen! Exception ('+parts[0]+') => ' + parts[1];
+ var text1 = 'Exception: ' + parts[1];
+ var text2 = 'From ('+parts[0]+')';
+
+ console.error( consoletext );
+ console.error( obj.exception );
+ if( obj.exception.stack != undefined ) {
+ console.log( obj.exception.stack );
+ console.log( obj.myClass);
+ }
+
+ var flip = 0;
+ var __this = this;
+ var bwidth = 8;
+ var yoffset = 16;
+
+ var errorTimer = setInterval(
+ function() {
+ var line;
+ flip ++;
+
+ if( flip <= 4 ) {
+ __this.renderContext.fillStyle = 'rgba(255,100,0,1)';
+ }
+ else {
+ __this.renderContext.fillStyle = 'rgba(0 ,0,0,1)';
+ }
+ if( flip == 8 ) { flip =0; }
+
+ __this.renderContext.fillRect(
+ 0,
+ 0,
+ __this.SCRW,
+ 105
+ );
+
+ __this.renderContext.fillStyle = 'rgba(0,0,0,1)';
+ __this.renderContext.fillRect(
+ bwidth,
+ bwidth,
+ __this.SCRW - (bwidth*2),
+ 105-(bwidth*2)
+ );
+
+ __this.renderContext.font = '15px arial';
+ __this.renderContext.textBaseline = 'top';
+ __this.renderContext.fillStyle = "rgba(255,100,000,1)";
+
+ line = 0;
+ __this.renderContext.fillText( "Game1 Zen Exception",
+ bwidth + 5,bwidth + 5 + (yoffset * line)
+ );
+
+ line++;
+ __this.renderContext.fillText( text1,
+ bwidth + 5,bwidth + 5 + (yoffset * line)
+ );
+
+ line++;
+ __this.renderContext.fillText( text2,
+ bwidth + 5,bwidth + 5 + (yoffset * line)
+ );
+
+ line++;
+ __this.renderContext.fillText( "Check console for more information.",
+ bwidth + 5,bwidth + 5 + (yoffset * line)
+ );
+
+
+ __this.renderContext.fillStyle = "rgba(100,255,100,1)";
+ line++;
+ __this.renderContext.fillText( "Fix the bug, and return to the light :)",
+ bwidth + 5,bwidth + 5 + (yoffset * line)
+ );
+
+
+ },
+ 300
+ );
+ }
+
+ sizeCanvas( w, h )
+ {
+
+ this.renderCanvas.width = w;
+ this.renderCanvas.height = h;
+
+ }
+}
diff --git a/versions/0.8p5/res/script/g1/core/spriteimagemagic.js b/versions/0.8p5/res/script/g1/core/spriteimagemagic.js
new file mode 100644
index 0000000..83240b0
--- /dev/null
+++ b/versions/0.8p5/res/script/g1/core/spriteimagemagic.js
@@ -0,0 +1,158 @@
+
+class SpriteImageMagic {
+
+ mkShadow1( srcCtx,
+ dstCtx,
+ transCol ) {
+
+ var w = srcCtx.canvas.width;
+ var h = srcCtx.canvas.height;
+
+ var imgdata = srcCtx.getImageData(0, 0, w, h);
+ var dd = imgdata.data;
+
+ var rowoffset = w * 4;
+
+ var xoffset = 0;
+ var yoffset = 0;
+ var offset;
+
+ for (var y = 0; y < h; y++) {
+ yoffset = y * rowoffset;
+ xoffset = 0;
+ for (var x = 0; x < w; x++) {
+ offset = yoffset + xoffset;
+
+ if( dd[ offset + 0] == transCol.r && dd[ offset + 1] == transCol.g && dd[ offset + 2] == transCol.b )
+ {
+ dd[ offset + 0] = 0;
+ dd[ offset + 1] = 0;
+ dd[ offset + 2] = 0;
+ dd[ offset + 3] = 0; /* Make transparent */
+ }
+ else {
+ if( (x+y) % 2 == 0 ) {
+ dd[ offset + 0] = 0;
+ dd[ offset + 1] = 0;
+ dd[ offset + 2] = 0;
+ dd[ offset + 3] = 255;
+ }
+ else {
+ dd[ offset + 0] = 0;
+ dd[ offset + 1] = 0;
+ dd[ offset + 2] = 0;
+ dd[ offset + 3] = 0;
+ }
+ }
+ xoffset += 4;
+ }
+ yoffset += rowoffset;
+ }
+
+ dstCtx.putImageData( imgdata, 0, 0);
+ }
+
+
+ scale( srcCtx,
+ dstCtx,
+ factor ) {
+
+ var w = srcCtx.canvas.width;
+ var h = srcCtx.canvas.height;
+
+ var w2 = Math.floor(w * factor);
+ var h2 = Math.floor(h * factor);
+
+ dstCtx.canvas.width = w2;
+ dstCtx.canvas.height = h2;
+
+ var imgdata = srcCtx.getImageData(0, 0, w, h);
+ var dd = imgdata.data;
+
+ var imgdata2 = dstCtx.getImageData(0, 0, w2, h2);
+ var dd2 = imgdata2.data;
+
+ var rowoffset = w * 4;
+ var rowoffset2 = w2 * 4;
+
+ var xoffset = 0;
+ var yoffset = 0;
+ var xoffset2 = 0;
+ var yoffset2 = 0;
+ var offset;
+ var offset2;
+
+ for (var y2 = 0; y2 < h2; y2++) {
+ yoffset2 = y2 * rowoffset2;
+ xoffset2 = 0;
+ for (var x2 = 0; x2 < w2; x2++) {
+ offset2 = yoffset2 + xoffset2;
+
+ var x = Math.floor( x2 / factor);
+ var y = Math.floor( y2 / factor);
+
+ yoffset = y * rowoffset;
+ xoffset = x * 4;
+
+ offset = yoffset + xoffset;
+
+ dd2[ offset2 + 0] = dd[ offset + 0];
+ dd2[ offset2 + 1] = dd[ offset + 1];
+ dd2[ offset2 + 2] = dd[ offset + 2];
+ dd2[ offset2 + 3] = dd[ offset + 3];
+
+ xoffset2 += 4;
+ }
+ yoffset2 += rowoffset2;
+ }
+
+ dstCtx.putImageData( imgdata2, 0, 0);
+ }
+
+
+ colorize( srcCtx,
+ dstCtx,
+ rec ) {
+
+ var f = 1-rec.effect;
+ var nR = rec.r;
+ var nG = rec.g;
+ var nB = rec.b;
+
+ var w = srcCtx.canvas.width;
+ var h = srcCtx.canvas.height;
+
+ var imgdata = srcCtx.getImageData(0, 0, w, h);
+ var dd = imgdata.data;
+
+ var rowoffset = w * 4;
+
+ var xoffset = 0;
+ var yoffset = 0;
+ var offset;
+
+ for (var y = 0; y < h; y++) {
+ yoffset = y * rowoffset;
+ xoffset = 0;
+ for (var x = 0; x < w; x++) {
+ offset = yoffset + xoffset;
+
+ dd[ offset + 0] = dd[ offset + 0] * f +
+ (nR * (1-f));
+
+ dd[ offset + 1] = dd[ offset + 1] * f +
+ (nG * (1-f));
+
+ dd[ offset + 2] = dd[ offset + 2] * f +
+ (nB * (1-f));
+
+ xoffset += 4;
+ }
+ yoffset += rowoffset;
+
+ }
+
+ dstCtx.putImageData( imgdata, 0, 0);
+ }
+
+}
diff --git a/versions/0.8p5/res/script/g1/core/spritemover.js b/versions/0.8p5/res/script/g1/core/spritemover.js
new file mode 100644
index 0000000..24c0b27
--- /dev/null
+++ b/versions/0.8p5/res/script/g1/core/spritemover.js
@@ -0,0 +1,1636 @@
+var CollisionBoxFactory_Debug_a260592cbef84c018c6f3f4eff1037a0 = false;
+
+
+class CollisionBoxFactory {
+ constructor( canvas, xfidelity, yfidelity ) {
+ this.canvas = canvas;
+ this.context = this.canvas.getContext('2d');//,{ alpha: false, desynchronized: true }
+
+ var boxes = [];
+
+ /* debug colors */
+ var cols = [];
+ cols[ 0 ] = "#ff0000";
+ cols[ 1 ] = "#00ff00";
+ cols[ 2 ] = "#0000ff";
+ cols[ 3 ] = "#ff00ff";
+ cols[ 4 ] = "#00ffff";
+ cols[ 5 ] = "#ffff00";
+
+ /* Set up initial collision boxes, with resolution xfidelity * yfidelity */
+ this.groupid = 0;
+ var MAXXI = 0;
+ var MAXYI = 0;
+ var XI = 0;
+ for( var x0=0; x0 canvas.width-1) {
+ x1 = canvas.width-1;
+ }
+
+ var YI = 0;
+ for( var y0=0; y0 canvas.height-1) {
+ y1 = canvas.height-1;
+ }
+
+ boxes.push( { x0:x0, x1: x1, y0: y0, y1: y1, xi:XI, yi: YI } );
+
+ YI++;
+ if( YI > MAXYI ) {
+ MAXYI = YI;
+ }
+ }
+
+ XI++;
+ if( XI > MAXXI ) {
+ MAXXI = XI;
+ }
+ }
+
+ /*
+ only keep boxes that have pixel content AND
+ make the boxes adressable in x_index, y_index coordinates (fullBoxes array)
+ */
+ var fullBoxes = [];
+ var flip = 0;
+
+ for( var i=0; i x1 ) { x1 = b.x1; }
+ if( b.y0 < y0 ) { y0 = b.y0; }
+ if( b.y1 > y1 ) { y1 = b.y1; }
+ }
+ }
+
+ newBoxes.push( { x0:x0, x1: x1, y0: y0, y1: y1, group: groupId } );
+ }
+
+ boxes = newBoxes;
+ newBoxes = null;
+
+ /* merge boxes that are vertically aligned, if they have the same size, and are neighbours */
+ for( var i=0; i (6-1) ) { flip=0;}
+ b.group = i;
+ }
+
+
+ /* end */
+ this.boxes = boxes;
+
+ }
+
+
+ getNeighborUnGroupedBoxes( indexes, fullBoxes ) {
+
+ /* check neigbours on the rights and bottom only */
+ /* good-enough, for the overal allgoritm */
+ var list=[];
+
+ for( var yi=indexes.top; yi<=indexes.bottom+1; yi++ ) {
+ var index = (indexes.right+1) + "_" + yi;
+ var b= fullBoxes[ index ];
+
+ if( b == undefined ) {
+ return [];
+ }
+ if( b.group != null ) {
+ return [];
+ }
+
+ list.push(b);
+
+ }
+
+ for( var xi=indexes.left; xi<=indexes.right; xi++ ) {
+ var index = xi + "_" + (indexes.bottom+1);
+ var b= fullBoxes[ index ];
+
+ if( b == undefined ) {
+ return [];
+ }
+ if( b.group != null ) {
+ return [];
+ }
+
+ list.push(b);
+
+ }
+
+ return list;
+ }
+
+ markGroupsForMerge( indexes, fullBoxes ) {
+ var list = this.getNeighborUnGroupedBoxes( indexes , fullBoxes );
+
+ if( list.length > 0 ) {
+ for( var i=0; i= c ) {
+ throw "Sprite.moreToFront(), sprite cannot move to front when allready in front";
+ }
+
+ p.removeSprite( this );
+ var p2 = mgr.getLayer( dest );
+ p2.addSprite( this );
+
+ }
+
+ moreToBack() {
+ var p = this.parent;
+ var mgr = p.layerManager;
+
+ if( mgr === undefined ) {
+ throw "Sprite.moreToBack() needs to be in a SpriteMover that needs to have a SpriteLayers parent";
+ }
+
+ var c = mgr.getLayerCount();
+
+ var dest = p.layerId -1;
+ if( dest < 0 ) {
+ throw "Sprite.moreToBack(), sprite cannot move to back when allready in back";
+ }
+
+ p.removeSprite( this );
+ var p2 = mgr.getLayer( dest );
+ p2.addSprite( this );
+ }
+
+ toLayer( dest ) {
+ var p = this.parent;
+ var mgr = p.layerManager;
+
+ if( mgr === undefined ) {
+ throw "Sprite.moreToFront() needs to be in a SpriteMover that needs to have a SpriteLayers parent";
+ }
+
+ var c = mgr.getLayerCount();
+
+ p.removeSprite( this );
+ var p2 = mgr.getLayer( dest );
+ p2.addSprite( this );
+ }
+
+ getWH() {
+ return [this.spriteImage.w, this.spriteImage.h];
+ }
+
+ cycleFrame() {
+ if( !this.pauseAnimFlag ) {
+ this.frameIndex++;
+ this.frameIndexF += this.frameFlipSpeed;
+ this.frameIndex = Math.floor( this.frameIndexF );
+ if( this.frameIndex >this.frameRange.max ) {
+ this.frameIndex = this.frameRange.min;
+ this.frameIndexF = this.frameIndex;
+ }
+ }
+ }
+
+ setColliding( flag ) {
+ this.colliding = flag;
+ }
+
+ setType( t ) {
+ this.type = t;
+ }
+
+ setData( d ) {
+ this.data = d;
+ }
+
+ getData() {
+ return( this.data );
+ }
+
+ setCycleFrameRate( r ) {
+ this.frameFlipSpeed = r;
+ }
+
+ setFrame( f ) {
+ this.pauseAnimFlag = true;
+ this.frameIndex = f;
+ }
+
+
+ setFrameRange( a, b) {
+
+
+ this.frameRange.min = a;
+ this.frameRange.max = b;
+ this.frameIndex = a;
+ this.frameIndexF = this.frameIndex;
+
+ }
+
+ pauseAnim() {
+ this.pauseAnimFlag = true;
+ }
+
+ playAnim() {
+ this.pauseAnimFlag = false;
+ }
+
+
+ setLinkXoYo( xoff, yoff ) {
+ this.linkOffsetX = xoff;
+ this.linkOffsetY = yoff;
+ }
+
+
+ getLinkXoYo() {
+ return [this.linkOffsetX, this.linkOffsetY];
+ }
+
+ factorLinkXoYo( f ) {
+ this.linkOffsetX *= f;
+ this.linkOffsetY *= f;
+ }
+
+ setLinkXoYoFactor( f ) {
+
+ this.effects.active = true;
+ this.effects.doLinkXoYoChange = true;
+ this.effects.linkXoYoChange = f;
+
+ }
+
+ linkPos( parent, xoff, yoff ) {
+ this.linked = true;
+ this.linkParent = parent;
+ this.linkOffsetX = xoff;
+ this.linkOffsetY = yoff;
+ }
+
+ linkAnim( parent ) {
+ this.linkedAnim = true;
+ this.linkAnimParent = parent;
+ }
+
+
+ setCompositeOperation( op ) {
+
+ //this.effects.active = true;
+ this.effects.compositeOperation = op;
+ this.effects.doCompositeOperation = true;
+
+ }
+
+ setTimer( time ) {
+
+ this.onTimer = true;
+ this.timer = time;
+
+ }
+
+ setFadeFactor( alphaFactor ) {
+
+ this.effects.active = true;
+ this.effects.alpha = 1;
+ this.effects.doAlpha = true;
+ this.effects.alphaFactor = alphaFactor;
+
+ }
+
+
+ adjustFadeFactor( alphaFactor ) {
+
+ this.effects.alphaFactor = scaleFactor;
+
+ }
+
+ setScaleFactor( scaleFactor ) {
+
+ this.effects.active = true;
+ this.effects.scale = 1;
+ this.effects.doScale = true;
+ this.effects.scaleFactor = scaleFactor;
+
+ }
+
+ adjustScaleFactor( scaleFactor ) {
+
+ this.effects.scaleFactor = scaleFactor;
+
+ }
+
+ setRotateIncrease( rotateIncrease ) {
+
+ this.effects.active = true;
+ this.effects.rotate = 0;
+ this.effects.doRotate = true;
+ this.effects.rotateIncrease = rotateIncrease;
+
+ }
+
+
+ adjustRotateIncrease( rotateIncrease ) {
+ this.effects.rotateIncrease = rotateIncrease;
+ }
+
+ resetEffects() {
+
+ this.effects.active = false;
+ this.effects.alpha = 1;
+ this.effects.doAlpha = false;
+ this.effects.alphaFactor = 1;
+ this.effects.scale = 1;
+ this.effects.doScale = false;
+ this.effects.scaleFactor = 1;
+ this.effects.rotate = 0;
+ this.effects.doRotate = false;
+ this.effects.rotateIncrease = 0;
+ this.effects.doLinkXoYoChange = false;
+ this.effects.linkXoYoChange = 1;
+
+ }
+
+ setBoundary( x0, y0, x1, y1 ) {
+ this.boundary.x0 = x0;
+ this.boundary.x1 = x1;
+ this.boundary.y0 = y0;
+ this.boundary.y1 = y1;
+ }
+
+
+ setBoundaryActionBound() {
+ this.boundaryAction = {
+ bound: true,
+ bounce: false,
+ dissapear: false,
+ wrap: false,
+ event: false
+ }
+ }
+
+ setBoundaryActionBounce() {
+ this.boundaryAction = {
+ bound: false,
+ bounce: true,
+ dissapear: false,
+ wrap: false,
+ event: false
+ }
+ }
+
+ setBoundaryActionDisappear() {
+ this.boundaryAction = {
+ bound: false,
+ bounce: false,
+ dissapear: true,
+ wrap: false,
+ event: false
+ }
+ }
+
+ setBoundaryActionWrap() {
+ this.boundaryAction = {
+ bound: false,
+ bounce: false,
+ dissapear: false,
+ wrap: true,
+ event: false
+ }
+ }
+
+ setBoundaryActionEvent( handler ) {
+ this.boundaryAction = {
+ bound: false,
+ bounce: false,
+ dissapear: false,
+ wrap: false,
+ event: true,
+ eventHandler: handler
+ }
+ }
+
+ wrapInBoundary() {
+ var s = this;
+ var bound = s.boundary;
+
+ if( s.x < bound.x0 ) { s.x = bound.x1; }
+ if( s.x > bound.x1 ) { s.x = bound.x0; }
+ if( s.y < bound.y0 ) { s.y = bound.y1; }
+ if( s.y > bound.y1 ) { s.y = bound.y0; }
+ }
+
+
+ bounceInBoundary() {
+
+ var s = this;
+ var bound = s.boundary;
+
+ var crossedX = false, crossedY = false;
+ if( s.x < bound.x0 ) { crossedX = true; }
+ if( s.x > bound.x1 ) { crossedX = true; }
+ if( s.y < bound.y0 ) { crossedY = true; }
+ if( s.y > bound.y1 ) { crossedY = true; }
+
+ this.placeInBoundary();
+
+ if( crossedX ) { this.dx = - this.dx; }
+ if( crossedY ) { this.dy = - this.dy; }
+ }
+
+ placeInBoundary() {
+
+ var s = this;
+ var bound = s.boundary;
+
+ if( s.x < bound.x0 ) { s.x = bound.x0; }
+ if( s.x > bound.x1 ) { s.x = bound.x1; }
+ if( s.y < bound.y0 ) { s.y = bound.y0; }
+ if( s.y > bound.y1 ) { s.y = bound.y1; }
+
+ }
+
+ inBoundary( ) {
+ var s = this;
+ var bound = s.boundary;
+
+ if( s.x < bound.x0 ) { return false }
+ else if( s.x > bound.x1 ) { return false }
+ else if( s.y < bound.y0 ) { return false }
+ else if( s.y > bound.y1 ) { return false }
+
+ return true;
+
+ }
+
+ getBoundaryAction( ) {
+
+ return this.boundaryAction;
+
+ }
+
+
+ setXY( x, y ) {
+ this.x = x;
+ this.y = y;
+ }
+
+ getXY( ) {
+ return [ this.x, this.y ];
+ }
+
+ addXY( x, y ) {
+ this.x += x;
+ this.y += y;
+ }
+
+
+ adjustDXDY( dx, dy, factor ) {
+ var olddx = this.dx;
+ var olddy = this.dy;
+ var inFactor = 1-factor;
+
+ this.dx = (dx * factor) + (olddx * inFactor);
+ this.dy = (dy * factor) + (olddy * inFactor) ;
+ }
+
+
+ setDXDY( dx, dy ) {
+ this.dx = dx;
+ this.dy = dy;
+ }
+
+ getDXDY( ) {
+ return [ this.dx, this.dy ];
+ }
+
+ decreaseSpeed( factor ) {
+ this.dx = this.dx * factor;
+ this.dy = this.dy * factor;
+ }
+
+ collide( this2 ) {
+
+ var this1 = this;
+
+ if( this1.effects.active || this2.effects.active ) {
+ return false;
+ }
+
+ if( this1.colliding == false || this2.colliding == false ) {
+ return false;
+ }
+
+
+ var a1 = this1.spriteImage.getColissionArea( this1.x, this1.y );
+ var a2 = this2.spriteImage.getColissionArea( this2.x, this2.y );
+
+ this1.debugBoxcollideSprite = this2;
+ this2.debugBoxcollideSprite = this1;
+
+ if (!this.colideAreas( a1, a2 ) ) {
+ return false;
+ }
+
+ var ba1 = this1.spriteImage.getColissionBoxArray( this1.frameIndex );
+ var ba2 = this2.spriteImage.getColissionBoxArray( this2.frameIndex );
+
+ //try {
+ var collided =
+ this.checkCollisionBoxes(
+ { x: this1.x + this1.spriteImage.xoff, y:this1.y + this1.spriteImage.yoff, boxArray: ba1 },
+ { x: this2.x + this2.spriteImage.xoff, y:this2.y + this2.spriteImage.yoff, boxArray: ba2 }
+ );
+ //}
+ //catch ( e ) {
+// var ba2 = this2.spriteImage.getColissionBoxArray( this1.frameIndex );
+// var ba1 = this1.spriteImage.getColissionBoxArray( this1.frameIndex );
+// }
+
+ return collided;
+
+ }
+
+ checkCollisionBoxes( cobj1, cobj2 ) {
+ var i1, i2;
+ for( i1=0; i1 5 ) { this.dbgCol = 0;}
+ b2.col = this.cols[ this.dbgCol ];
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ colideAreas( a1, a2 ) {
+
+ if( this.overlappingCoords( a1.x0, a1.x1, a2.x0, a2.x1 ) ) {
+ if( this.overlappingCoords( a1.y0, a1.y1, a2.y0, a2.y1 ) ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ overlappingCoords( obj1_XMIN, obj1_XMAX, obj2_XMIN, obj2_XMAX ) {
+
+ return obj1_XMAX >= obj2_XMIN && obj2_XMAX >= obj1_XMIN;
+
+ }
+
+}
+
+class SpriteLayers {
+
+ constructor( x ) {
+ this.movers = [];
+ if( x === undefined ) {
+ return;
+ }
+ else {
+ for( var i=0; i -1 ) {
+ this.sprites.splice(index, 1);
+ }
+ else {
+ console.error("sprite with issue:");
+ console.error( s );
+ console.error( "spritearraylen = " + this.sprites.length );
+ throw "(SpriteMover) could not find index for sprite, during sliceSprite";
+ }
+ }
+
+
+ removeSprite( s ) {
+
+ var check = null;
+ var found = -1;
+
+ for( var i=0; i -1) {
+ this.sprites[ i ] = { active: false }
+ }
+ else {
+ console.error("sprite could not be removed: " + s.uid);
+ console.error( s );
+ console.error( "spritearraylen = " + this.sprites.length );
+ throw "(SpriteMover) could not find index for sprite, during removeSprite";
+ }
+ }
+
+
+ detectColissions() {
+ var colissions = [];
+
+ for( var i=0; i 1 ) {
+ s.deactivate();
+ }
+ }
+ if( s.effects.doLinkXoYoChange ) {
+
+ var f=s.effects.linkXoYoChange;
+ s.linkOffsetX *= f;
+ s.linkOffsetY *= f;
+
+ if( s.linkOffsetX < 0.01 && s.linkOffsetY < 0.01 ) {
+ s.deactivate();
+ }
+ }
+ if( s.effects.doScale ) {
+ s.effects.scale = s.effects.scale * s.effects.scaleFactor;
+ if( s.effects.scale < 0.01 || s.effects.scale > 10 ) {
+ s.deactivate();
+ }
+ }
+ if( s.effects.doRotate ) {
+ s.effects.rotate = s.effects.rotate + s.effects.rotateIncrease;
+ }
+ }
+
+ }
+ }
+ }
+
+
+ render( ctx ) {
+ for( var i=0; i.9 ) {
+ this.memory[ i ] = Math.floor(Math.random() * 255);
+ }
+ }
+
+ this.rescale( 2.5, 2.5 );
+
+ }
+
+ setCallbacks( cb ) {
+ this.lineOverflowCallback = cb.lineOverFlow;
+ this.scrollCallback = cb.scroll;
+ this.clearScreenCallback = cb.clearScreen;
+ }
+
+ clearCallbacks( ) {
+ this.lineOverflowCallback = null;
+ this.scrollCallback = null;
+ this.clearScreenCallback = null;
+ }
+
+
+ cursorShiftNext() {
+ this.cursorx++;
+ if(this.cursorx > 39) {
+ this.cursorx = 39;
+
+ if( this.cursory != 24) {
+ if( this.lineOverflowCallback ) {
+ var clazz = this.lineOverflowCallback.clazz;
+ var method = this.lineOverflowCallback.method;
+ clazz[method]();
+ }
+
+ this.cursory++;
+ this.cursorx=0;
+ }
+ else {
+ this.scrollUpNoCallback();
+
+ if( this.lineOverflowCallback ) {
+ var clazz = this.lineOverflowCallback.clazz;
+ var method = this.lineOverflowCallback.method;
+ clazz[method]();
+ }
+ this.cursorx=0;
+ }
+ }
+ }
+
+
+ cursorShiftNextNoCallback() {
+ this.cursorx++;
+ if(this.cursorx > 39) {
+ this.cursorx = 39;
+
+ if( this.cursory != 24) {
+
+ this.cursory++;
+ this.cursorx=0;
+ }
+ else {
+ this.scrollUpNoCallback();
+ this.cursorx=0;
+ }
+ }
+ }
+
+ rescale(xs,ys) {
+ this.xScale = xs;
+ this.yScale = ys;
+
+ this.border = {
+ w: this.border0.w * xs,
+ h: this.border0.h * ys
+ }
+
+/*
+ this.WIDTH = 320*xs;
+ this.HEIGHT = 200*ys;
+
+ this.FULLWIDTH = this.WIDTH + (this.border.w * 2);
+ this.FULLHEIGHT = this.HEIGHT + (this.border.h * 2);
+*/
+
+ this.WIDTH = 320*xs;
+ this.HEIGHT = 200*ys;
+
+ if( this.skipSideBorder ) {
+ this.FULLWIDTH = this.WIDTH; // + (this.border.w * 2);
+ this.FULLHEIGHT = this.HEIGHT + (this.border.h * 2);
+ }
+ else {
+ this.FULLWIDTH = this.WIDTH + (this.border.w * 2);
+ this.FULLHEIGHT = this.HEIGHT + (this.border.h * 2);
+ }
+ this.rcanvas.width=this.FULLWIDTH ;
+ this.rcanvas.height=this.FULLHEIGHT;
+
+ this.rcontext.imageSmoothingEnabled= false;
+ this.context.imageSmoothingEnabled= false;
+ this.bufcontext.imageSmoothingEnabled= false;
+
+ this.bcolLast = -1 ; //force border redraw
+ }
+
+
+ getColorRGB( i ) {
+ return this.colors[ i ];
+ }
+
+ getColorHTML( i ) {
+ return this._htmlColor( this.colors[ i ] );
+ }
+
+ getBorderColor() {
+ return this.bcol;
+ }
+
+ getBorderChangedState() {
+ if( this.bcolLast != this.bcol ) {
+ return true;
+ }
+ return false;
+ }
+
+ getBitmapAddress() {
+ return this.videoBMRam;
+ }
+
+ getMemory() {
+ return this.memory;
+ }
+
+ setVicRegisters( regs ) {
+
+ for( var i=0; i<47; i++) {
+ this.vic[ i ] = regs[ i ];
+ this.vicUsed.push( i );
+ }
+ }
+
+ getCopyVicRegisters() {
+ var copy = [];
+ for( var i=0; i<47; i++) {
+ copy.push( this.vic[i] );
+ }
+ return copy;
+ }
+
+ getCopyScreen() {
+ var rows = [];
+
+ for( var y=0; y<25; y++) {
+ var row0 = this.txScBuf[ y ];
+ var row = [];
+
+ for( var x=0; x<40; x++) {
+ row[ x ] = row0[ x ];
+ }
+
+ rows[ y ] = row;
+ }
+
+ return rows;
+ }
+
+ setScreen( rows ) {
+
+ for( var y=0; y<25; y++) {
+ var row = rows[ y ];
+ var newRow = [];
+
+ for( var x=0; x<40; x++) {
+ newRow[ x ] = row[ x ];
+ newRow[ x ][2] = true;
+ }
+ this.txScBuf[ y ] = newRow;
+ }
+ }
+
+ getCursorPos() {
+ return [ this.cursorx, this.cursory ];
+ }
+
+ getState() {
+ var cursor = {
+ col: this.col,
+ cx: this.cursorx,
+ cy: this.cursory
+ };
+ var state = {
+ vicRegisters: this.getCopyVicRegisters(),
+ screen: this.getCopyScreen(),
+ cursor: cursor
+ }
+
+ return state;
+ }
+
+ setState( state ) {
+ this.setVicRegisters( state.vicRegisters );
+ this.setScreen( state.screen );
+ this.bcolLast = -1;
+ this.bcol = state.vicRegisters[32];
+
+ this.col = state.cursor.col;
+ this.cursorx = state.cursor.cx;
+ this.cursory = state.cursor.cy;
+ }
+
+ setCharRomVisible( x ) {
+ this.visibleRomCharMem = x;
+ }
+
+ getCharRomVisible() {
+ return this.visibleRomCharMem;
+ }
+
+ _initSpriteArrays() {
+
+ this.sprites = [];
+ for( var i=0; i<8; i++ ) {
+
+ this.sprites[ i ] = new Object();
+ var sp = this.sprites[ i ];
+ sp.x = 0;
+ sp.y = 0;
+ sp.enabled = false;
+ sp.fat = false;
+ sp.long = false;
+ sp.addr = 0;
+ sp.col = 1;
+ sp.multiCol = false;
+
+ }
+
+ }
+
+ _setCharMapping() {
+ var map = [];
+ for( var i=0 ; i<32; i++ ) {
+ map[String.fromCharCode(i)] = 128+i;
+ }
+
+ for( var i=128 ; i<160; i++ ) {
+ map[String.fromCharCode(i)] = 64+i;
+ }
+
+ map['\x7e'] = 94; //PI
+ map['\x5e'] = 30; //EXP
+
+ map['@'] = 0;
+ map['A'] = 1;
+ map['B'] = 2;
+ map['C'] = 3;
+ map['D'] = 4;
+ map['E'] = 5;
+ map['F'] = 6;
+ map['G'] = 7;
+ map['H'] = 8;
+ map['I'] = 9;
+ map['J'] = 10;
+ map['K'] = 11;
+ map['L'] = 12;
+ map['M'] = 13;
+ map['N'] = 14;
+ map['O'] = 15;
+ map['P'] = 16;
+ map['Q'] = 17;
+ map['R'] = 18;
+ map['S'] = 19;
+ map['T'] = 20;
+ map['U'] = 21;
+ map['V'] = 22;
+ map['W'] = 23;
+ map['X'] = 24;
+ map['Y'] = 25;
+ map['Z'] = 26;
+
+ map['['] = 27;
+ map[']'] = 29;
+ map['!'] = 33;
+ map['"'] = 34;
+ map['#'] = 35;
+ map['$'] = 36;
+ map['%'] = 37;
+ map['&'] = 38;
+ map['\''] = 39;
+ map['\\'] = 77;
+ map['{'] = 0x73;
+ map['}'] = 0x6b;
+ map['('] = 40;
+ map[')'] = 41;
+
+ map['*'] = 42;
+ map['+'] = 43;
+ map[','] = 44;
+ map['-'] = 45;
+ map['.'] = 46;
+ map['/'] = 47;
+
+ map['0'] = 48;
+ map['1'] = 49;
+ map['2'] = 50;
+ map['3'] = 51;
+ map['4'] = 52;
+ map['5'] = 53;
+ map['6'] = 54;
+ map['7'] = 55;
+ map['8'] = 56;
+ map['9'] = 57;
+
+ map[' '] = 32;
+
+ map[':'] = 58;
+ map[';'] = 59;
+ map['<'] = 60;
+ map['='] = 61;
+ map['>'] = 62;
+ map['?'] = 63;
+
+ this.map = map;
+
+ var backmap = []
+ var mapInfo = Object.entries(map);
+ for( var i=0; i 0;
+
+ }
+
+ return results;
+ }
+
+ _intVICMem2VICVRegs() {
+ if( this.vicUsed.length == 0) {
+ return;
+ }
+
+ var vu = this.vicUsed;
+ if( vu.indexOf( 16 ) > -1 ) {
+ for( var sp=0; sp<8; sp++) {
+ var addr = sp*2;
+ if( vu.indexOf( addr ) == -1) {
+ vu.push(addr);
+ }
+ }
+ }
+
+ var vul = vu.length;
+ for( var i=0; i 0; //bit 5 (starting w bit 0)
+
+ if( this.debugFlag ) {
+ console.log("this.useHires -> " + this.useHires);
+ }
+
+
+ }
+ else if( nr == 53272) { /*$D018*/
+ //http://www.devili.iki.fi/Computers/Commodore/C64/Programmers_Reference/Chapter_3/page_104.html
+
+ var bits = this._getByteBits( v );
+ var b1,b2,b3, value;
+ b1 = bits[1];
+ b2 = bits[2];
+ b3 = bits[3];
+
+ value = 0;
+
+ if( b1 ) { value += 2; }
+ if( b2 ) { value += 4; }
+ if( b3 ) { value += 8; }
+
+ if( value == 8 ) {
+ this.useRomCharMem = false;
+ this.videoRam = 8192;
+ }
+ else if( value == 12 ) {
+ this.useRomCharMem = false;
+ this.videoRam = 12288;
+ } else {
+ this.useRomCharMem = true;
+ }
+
+ if( b3 ) {
+ this.videoBMRam = 8192;
+ } else {
+ this.videoBMRam = 0;
+ }
+ if( this.debugFlag ) {
+ console.log("BitMapRam set to: " + this.videoBMRam);
+ }
+ }
+ else if(nr == 53276) {
+ var bits = this._getByteBits( v );
+ var spr = this.sprites;
+ for( var j=0; j<8; j++) {
+ spr[ j ].multiCol = bits[j];
+
+ }
+ this.screenRefresh = true;
+ }
+ else if(nr == 53277) {
+ var bits = this._getByteBits( v );
+ var spr = this.sprites;
+ for( var j=0; j<8; j++) {
+ spr[ j ].fat = bits[j];
+
+ }
+ this.screenRefresh = true;
+ }
+ else if(nr == 53271) {
+ var bits = this._getByteBits( v );
+ var spr = this.sprites;
+ for( var j=0; j<8; j++) {
+ spr[ j ].long = bits[j];
+
+ }
+ this.screenRefresh = true;
+ }
+ else if( nr>53247 && nr < 53264 ) { //sprite pos
+ var sprno = Math.floor((nr -53248) / 2);
+ var xcoord = !(nr % 2);
+
+ if( xcoord ) {
+
+ var val_9thbit = this.vic[ 16 ];
+ var bits_9thbit = this._getByteBits( val_9thbit );
+
+ this.spriteXPos( sprno, v + (bits_9thbit[ sprno ] * 256) );
+ }
+ else {
+ this.spriteYPos( sprno, v );
+ }
+ this.screenRefresh = true;
+ }
+ else if( nr>53286 && nr < 53295 ) {
+ var sprno = nr - 53287;
+
+ this.spriteCol( sprno, v % 16);
+
+ }
+ this.screenRefresh = true;
+ }
+
+ this.vicUsed = [];
+ }
+
+
+ pokeFlush() {
+ this._intVICMem2VICVRegs();
+ }
+
+ poke( a, b ) {
+ this.memory[a] = b % 256;
+
+ if( this.useHires ) {
+
+ if( a >= this.videoBMRam && a< this.videoBMRam + 8000 ) {
+
+ var buf = this.txScBuf;
+ var addr = Math.floor (( a-this.videoBMRam ) / 8 );
+ var y = Math.floor( (addr / 40) );
+ var x = addr % 40;
+ buf[y][x][2] = true;
+ }
+ }
+ else { //videoRam should point to ScBuffer, does it ever?
+ if( a >= this.videoRam && a< (this.videoRam + (256*8)) ) {
+ this.screenRefresh = true;
+ }
+ //else if( a >= 2040 && a< 2048 ) {
+ // this.screenRefresh = true;
+ //}
+ }
+ }
+
+ peek( a ) {
+ return this.memory[a];
+ }
+
+ charRomPeek( a ) {
+ return this.fontImageRom[a];
+ }
+
+ vpoke( a, b ) {
+ this.vic[a] = b % 256;
+ this.vicUsed.push( a );
+ }
+
+ vpeek( a ) {
+ return this.vic[a];
+ }
+
+ reset( ) {
+ this.rcontext.imageSmoothingEnabled= false;
+ }
+
+ preparefontImageRom() {
+
+ var img1 = this.characterSetImage;
+ var img2 = document.createElement("canvas");
+
+ var ctx2 = img2.getContext("2d");
+
+ img2.width = img1.width;
+ img2.height = img1.height;
+ ctx2.drawImage(img1, 0, 0);
+
+ var imgdata = ctx2.getImageData(0, 0, img1.width, img1.height );
+ var sd = imgdata.data;
+
+ var pixelsCount = img1.width * img1.height ;
+ var pixelsCountD8 = (img1.width * img1.height) / 8 ;
+ var len = pixelsCount * 4;
+ var data = new Uint8Array( 256 * 8 );
+ var srcBytesWidth = img1.width*4;
+
+ for (var i = 0; i < pixelsCountD8; i ++ ) {
+ data[i] = 0;
+ }
+
+ var masks = [
+ 0b00000001,0b00000010,0b00000100,0b00001000,
+ 0b00010000,0b00100000,0b01000000,0b10000000
+ ];
+
+ var di = 0;
+ for (var charIx = 0; charIx < 128; charIx ++) {
+ di = charIx * 8;
+
+ var srcAddressRow = Math.floor(charIx / 16);
+ var srcAddressCol = charIx % 16;
+ var srcAddressBase = ((srcAddressCol * 8 * 4) + ( srcAddressRow * srcBytesWidth * 8));
+
+ if( charIx == 16) {
+ var tmp = 1001;
+ }
+
+ for (var pixRow = 0; pixRow < 8; pixRow ++) {
+
+ for (var pixColumn = 0; pixColumn < 8; pixColumn ++) {
+ var srcAddress = srcAddressBase
+ + ( (7-pixColumn) * 4 )
+ + ( pixRow * srcBytesWidth );
+
+
+ if (sd[ srcAddress ]) {
+ data[ di ] = data[ di ] | masks[ pixColumn ];
+ data[ di + pixelsCountD8 ] = data[ di + pixelsCountD8 ] | masks[ pixColumn ];
+ }
+ }
+ data[ di + pixelsCountD8 ] = 255 - data[ di + pixelsCountD8 ];
+ di++;
+ }
+ }
+
+ return data;
+ }
+
+
+ _postLoadFontImage() {
+
+ if( this.debugFlag ) {
+ console.log("_postLoadFontImage reached");
+ }
+
+ //this.fontImageData = this._prepareFontImageData(this.srcImage);
+ this.fontImageRom = this.preparefontImageRom(this.srcImage);
+
+ //-------------------------
+ this.bcolLast = -1;
+
+ this.clearScreen();
+ this.writeString( "ready.", true );
+ this._updateBorder();
+ this._renderBackGround();
+ this._renderBuffer();
+
+ this._updateDisplay();
+
+ this.ready = true;
+ if( this.onload != undefined ) {
+ this.onload( this, this.onloaddata );
+ }
+ }
+
+
+ setColor( c ) {
+ this.col = c;
+ }
+
+ getColor() {
+ return this.col;
+ }
+
+ setBGColor( c ) {
+ this.bgcol = c;
+ }
+
+
+ setSpriteMColor1( c ) {
+ this.spritemcol1 = c;
+ }
+
+ setSpriteMColor2( c ) {
+ this.spritemcol2 = c;
+ }
+
+ setMColor1( c ) {
+ this.mcol1 = c;
+ }
+
+ setMColor2( c ) {
+ this.mcol2 = c;
+ }
+
+ setBorderColor( c ) {
+ this.bcol = c;
+ }
+
+ spriteEnable( n, enabled ) {
+ this.sprites[ n ].enabled = enabled;
+ }
+
+ spriteXPos( n, x ) {
+ this.sprites[ n ].x = x;
+ }
+
+ spriteYPos( n, y ) {
+ this.sprites[ n ].y = y;
+ }
+
+ spritePos( n, x, y ) {
+ this.sprites[ n ].x = x;
+ this.sprites[ n ].y = y;
+ }
+
+ spriteCol( n, c ) {
+ this.sprites[ n ].col = c;
+
+ }
+
+ getRenderSize() {
+ return [ this.rcanvas.width, this.rcanvas.height ];
+ }
+
+ clearScreen() {
+ this.txScBuf = [];
+ this.cursorx = 0;
+ this.cursory = 0;
+
+ for( var y=0; y<25; y++) {
+ var row = [];
+ for( var x=0; x<40; x++) {
+ row[ x ] = [32,14,true];
+ }
+ this.txScBuf[ y ] = row;
+ }
+
+ if( this.clearScreenCallback ) {
+
+ var clazz = this.clearScreenCallback.clazz;
+ var method = this.clearScreenCallback.method;
+ clazz[method]();
+ }
+ }
+
+ isBitMapMode() {
+ return this.useHires;
+ }
+
+ isMultiColor() {
+ return this.multiColor;
+ }
+
+ getMemory() {
+ return this.memory;
+ }
+
+
+ scrollUpNoCallback() {
+
+ var buf = this.txScBuf;
+ this.cursory=24;
+
+ for( var y=0; y<24; y++) {
+ buf[y] = buf[y + 1];
+ }
+ var newrow = [];
+ for( var x=0; x<40; x++) {
+ newrow[ x ] = [32,14,true];
+ }
+ buf[ 24 ] = newrow;
+
+ for( var y=0; y<25; y++) {
+ for( var x=0; x<40; x++) {
+ buf[y][x][2] = true;
+ }
+ }
+ }
+
+
+ scrollUp() {
+
+ this.scrollUpNoCallback();
+
+ if( this.scrollCallback ) {
+
+ var clazz = this.scrollCallback.clazz;
+ var method = this.scrollCallback.method;
+ clazz[method]();
+ }
+
+ }
+
+ nextLine( c ) {
+ this.cursory++;
+ this.cursorx=0;
+ if( this.cursory > 24 ) {
+ this.cursory = 24;
+ this.scrollUp();
+ }
+ }
+
+
+ getChar( x, y ) {
+
+ var buf = this.txScBuf;
+ var chr = buf[y][x];
+
+ return chr[0];
+
+ }
+
+ getCharCol( x, y ) {
+
+ var buf = this.txScBuf;
+ var chr = buf[y][x];
+
+ return chr[1];
+
+ }
+
+
+ setCellModified( x, y ) {
+
+ var buf = this.txScBuf;
+ var chr = buf[y][x];
+
+ chr[2] = true;
+
+ }
+
+ setChar( x, y, index ) {
+
+ var buf = this.txScBuf;
+ var chr = buf[y][x];
+
+ chr[2] = true;
+ chr[0] = index;
+
+ }
+
+ setCharCol( x, y, index ) {
+
+ var buf = this.txScBuf;
+ var chr = buf[y][x];
+
+ chr[2] = true;
+ chr[1] = index;
+
+ }
+
+ saveCursor( x ) {
+ if( x < 0 ) {
+ return (x+128)%256;
+ }
+ return x%256;
+ }
+
+ blinkCursor() {
+ var buf = this.txScBuf;
+ if( !this.cursorOn ) {
+ this.cursorOn = true;
+ this.cursorChar = buf[this.cursory][this.cursorx][0];
+ this.cursorCharCol = buf[this.cursory][this.cursorx][1];
+ var index = 32+128;
+ buf[this.cursory][this.cursorx][2] = true;
+ buf[this.cursory][this.cursorx][1] = this.col;
+ buf[this.cursory][this.cursorx][0] = this.saveCursor(buf[this.cursory][this.cursorx][0] + 128);
+ }
+ else {
+ this.cursorOn = false;
+ var index = 32;
+ buf[this.cursory][this.cursorx][2] = true;
+ buf[this.cursory][this.cursorx][1] = this.cursorCharCol;
+ buf[this.cursory][this.cursorx][0] = this.cursorChar;
+ }
+
+ }
+
+ clearCursor() {
+ var buf = this.txScBuf;
+ if( this.cursorOn ) {
+ this.cursorOn = false;
+ var index = 32;
+ buf[this.cursory][this.cursorx][2] = true;
+ buf[this.cursory][this.cursorx][1] = this.cursorCharCol;
+ buf[this.cursory][this.cursorx][0] = this.cursorChar;
+ }
+ }
+
+
+ setCursorY( y ) {
+ this.cursory = y;
+ }
+
+ getCursorY() {
+ return this.cursory;
+ }
+
+ setCursorX( x ) {
+ this.cursorx = x;
+ }
+
+ getCursorX() {
+ return this.cursorx;
+ }
+
+ cursorUp() {
+ this.cursory--;
+ if( this.cursory<0 ) { this.cursory = 0;}
+ }
+
+ cursorDown() {
+ this.cursory++;
+ if( this.cursory>24 ) { this.cursory = 24;}
+ }
+
+ cursorLeft() {
+ this.cursorx--;
+ if( this.cursorx<0 ) { this.cursorx = 0;}
+ }
+
+ cursorRight() {
+ this.cursorx++;
+ if( this.cursorx>39 ) { this.cursorx = 39;}
+ }
+
+ cursorHome() {
+ this.cursorx=0;
+ this.cursory=0;
+ }
+
+
+
+ writePetsciiChar( c ) {
+ var index = c.charCodeAt(0);
+ if( index < 0 || index >255) { index = 0;}
+
+ var buf = this.txScBuf;
+ if( index > -1 ) {
+ buf[this.cursory][this.cursorx][2] = true;
+ buf[this.cursory][this.cursorx][1] = this.col;
+ buf[this.cursory][this.cursorx][0] = index;
+ }
+
+ this.cursorShiftNext();
+
+ }
+
+ writeCharRev( c ) {
+ var index = (this._mapASCII2Screen( c ) + 128) % 256;
+
+ var buf = this.txScBuf;
+ if( index > -1 ) {
+ buf[this.cursory][this.cursorx][2] = true;
+ buf[this.cursory][this.cursorx][1] = this.col;
+ buf[this.cursory][this.cursorx][0] = index;
+ }
+
+ this.cursorShiftNext();
+
+ }
+
+ writeChar( c ) {
+
+ var index = this._mapASCII2Screen( c );
+
+ var buf = this.txScBuf;
+ if( index > -1 ) {
+ buf[this.cursory][this.cursorx][2] = true;
+ buf[this.cursory][this.cursorx][1] = this.col;
+ buf[this.cursory][this.cursorx][0] = index;
+ }
+ this.cursorShiftNext();
+
+ }
+
+
+ deleteChar() {
+ var index = 32;
+ var buf = this.txScBuf;
+
+ this.cursorx--;
+ if(this.cursorx <0 ) {
+ this.cursorx = 39;
+
+ this.cursory--;
+ if(this.cursory <0 ) {
+ this.cursory = 0;
+ this.cursorx = 0;
+ }
+
+ }
+
+ buf[this.cursory][this.cursorx][2] = true;
+ buf[this.cursory][this.cursorx][0] = index;
+
+ }
+
+
+ getLine( y ) {
+ var line;
+ var buf = this.txScBuf;
+
+ line = "";
+
+ for( var x=0; x<40; x++) {
+ var c=this.backmap[ buf[y][x][0] ];
+ if( !c ) { c=" "};
+ line = line + c;
+ }
+ return line;
+ }
+
+ getCurrentLine() {
+
+ return this.getLine( this.cursory );
+
+ }
+
+ writeString( str, newLine ) {
+ for (var i = 0; i < str.length; i++) {
+ this.writeChar( str.charAt(i) );
+ }
+ if(newLine) {
+ this.nextLine();
+ }
+ }
+
+ _mapASCII2Screen( c ) {
+//https://sta.c64.org/cbm64pettoscr.html
+ var c0 = c.charCodeAt(0);
+ if( c0 < 32) { return c0+128; }
+ else if( c0 >= 32 && c0<64) { return c0; }
+ else if( c0 >= 64 && c0<96) { return c0-64; }
+ else if( c0 >= 96 && c0<128) { return c0-32; }
+ else if( c0 >= 128 && c0<160) { return c0+64; }
+ else if( c0 >= 160 && c0<192) { return c0-64; }
+ else if( c0 >= 192 && c0<224) { return c0-128; }
+ else if( c0 >= 224 && c0<255) { return c0-128; }
+ else if( c0 == 255 ) { return 94; }
+
+/*
+ var c = c0; //.toLowerCase();
+
+ var map = this.map;
+ var index;
+
+ index = map [ c ];
+ if( index == undefined ) {
+ if( c == ' ' ) {
+ return -1;
+ }
+ index = 63;
+ }
+
+ return index;
+ */
+ }
+
+ setSpriteAddress( no, addr ) {
+ this.sprites[no].addr = addr;
+
+ this.screenRefresh = true;
+ }
+
+
+ renderSprite( no, x, y) {
+
+
+ var sprite = this.sprites[ no ];
+ if( sprite.multiCol ) {
+ if(sprite.fat) {
+ this._renderDirectSprMultiFat( no, x, y, sprite.long);
+ }
+ else {
+ this._renderDirectSprMulti( no, x, y, sprite.long);
+ }
+
+ }
+ else {
+ if(sprite.fat) {
+ this._renderDirectSprMonoFat( no, x, y, sprite.long);
+ }
+ else {
+ this._renderDirectSprMono( no, x, y, sprite.long);
+ }
+ }
+
+
+ //mono,w
+ //mono,W
+ //multi,w
+ //multi,W
+
+ }
+
+
+ _renderDirectSprMulti( no, x, y, long) {
+ //https://retro64.altervista.org/blog/programming-sprites-the-commodore-64-simple-tutorial-using-basic-v2/
+
+ var fid = this.memory;
+ var iDta = this.iDta;
+ var pixWidthM4 = this.iwidth * 4;
+ var sprite = this.sprites[ no ];
+ var dataPtr = sprite.addr;
+
+ var fgCol = this.colors[ sprite.col ];
+ var mcCol1 = this.colors[ this.spritemcol1 ];
+ var mcCol2 = this.colors[ this.spritemcol2 ];
+
+ var xd0 = x << 2 /* multiply 4, 4 bytes per pixel */;
+ var yd= pixWidthM4 * y;
+ var yd2= pixWidthM4 * (y+1);
+
+
+ for( var yC = 0; yC<21; yC++) {
+
+ var xd = xd0;
+ for( var xByteCount=0; xByteCount < 3; xByteCount++) {
+
+ var byte = fid[ dataPtr ];
+ var mask = 0b10000000;
+ var mask2 = 0b01000000;
+
+ if(long) {
+
+ for( var xC = 0; xC<4; xC++) {
+
+ var col = null;
+ var val = 0;
+
+ if ( (byte & mask ) > 0 ) {
+ val=1;
+ }
+ if ( (byte & mask2 ) > 0 ) {
+ val+=2;
+ }
+
+ switch (val){
+ case 1:
+ col = mcCol1;
+ break;
+ case 2:
+ col = mcCol2;
+ break;
+ case 3:
+ col = fgCol;
+ break;
+ default:
+
+ }
+
+ var dBase = xd + yd;
+ var dBase2 = xd + yd2;
+
+ if ( col!=null ) {
+
+ iDta[ dBase + 0 ] = col.r;
+ iDta[ dBase + 1 ] = col.g;
+ iDta[ dBase + 2 ] = col.b;
+ iDta[ dBase + 3 ] = 255;
+
+ iDta[ dBase + 4 ] = col.r;
+ iDta[ dBase + 5 ] = col.g;
+ iDta[ dBase + 6 ] = col.b;
+ iDta[ dBase + 7 ] = 255;
+
+ iDta[ dBase2 + 0 ] = col.r;
+ iDta[ dBase2 + 1 ] = col.g;
+ iDta[ dBase2 + 2 ] = col.b;
+ iDta[ dBase2 + 3 ] = 255;
+
+ iDta[ dBase2 + 4 ] = col.r;
+ iDta[ dBase2 + 5 ] = col.g;
+ iDta[ dBase2 + 6 ] = col.b;
+ iDta[ dBase2 + 7 ] = 255;
+
+ }
+
+
+ mask = mask >> 2;
+ mask2 = mask2 >> 2;
+ xd+=8;
+ }
+ }
+ else {
+ for( var xC = 0; xC<4; xC++) {
+
+ var col = null;
+ var val = 0;
+
+ if ( (byte & mask ) > 0 ) {
+ val=1;
+ }
+ if ( (byte & mask2 ) > 0 ) {
+ val+=2;
+ }
+
+ switch (val){
+ case 1:
+ col = mcCol1;
+ break;
+ case 2:
+ col = mcCol2;
+ break;
+ case 3:
+ col = fgCol;
+ break;
+ default:
+
+ }
+
+ var dBase = xd + yd;
+
+ if ( col!=null ) {
+
+ iDta[ dBase + 0 ] = col.r;
+ iDta[ dBase + 1 ] = col.g;
+ iDta[ dBase + 2 ] = col.b;
+ iDta[ dBase + 3 ] = 255;
+
+ iDta[ dBase + 4 ] = col.r;
+ iDta[ dBase + 5 ] = col.g;
+ iDta[ dBase + 6 ] = col.b;
+ iDta[ dBase + 7 ] = 255;
+
+ }
+
+
+ mask = mask >> 2;
+ mask2 = mask2 >> 2;
+ xd+=8;
+ }
+ }
+
+ dataPtr++;
+ }
+
+
+ yd += pixWidthM4;
+ if( long ) {
+ yd += pixWidthM4;
+ yd2 += pixWidthM4;
+ yd2 += pixWidthM4;
+ }
+ }
+
+ }
+
+ _renderDirectSprMultiFat( no, x, y, long) {
+ //https://retro64.altervista.org/blog/programming-sprites-the-commodore-64-simple-tutorial-using-basic-v2/
+
+ var fid = this.memory;
+ var iDta = this.iDta;
+ var pixWidthM4 = this.iwidth * 4;
+ var sprite = this.sprites[ no ];
+ var dataPtr = sprite.addr;
+
+ var fgCol = this.colors[ sprite.col ];
+ var mcCol1 = this.colors[ this.spritemcol1 ];
+ var mcCol2 = this.colors[ this.spritemcol2 ];
+
+ var xd0 = x << 2 /* multiply 4, 4 bytes per pixel */;
+ var yd= pixWidthM4 * y;
+ var yd2= pixWidthM4 * (y+1);
+
+
+ for( var yC = 0; yC<21; yC++) {
+
+ var xd = xd0;
+ for( var xByteCount=0; xByteCount < 3; xByteCount++) {
+
+ var byte = fid[ dataPtr ];
+ var mask = 0b10000000;
+ var mask2 = 0b01000000;
+
+ if( long ) {
+ for( var xC = 0; xC<4; xC++) {
+
+ var col = null;
+ var val = 0;
+
+ if ( (byte & mask ) > 0 ) {
+ val=1;
+ }
+ if ( (byte & mask2 ) > 0 ) {
+ val+=2;
+ }
+
+ switch (val){
+ case 1:
+ col = mcCol1;
+ break;
+ case 2:
+ col = mcCol2;
+ break;
+ case 3:
+ col = fgCol;
+ break;
+ default:
+
+ }
+
+ var dBase = xd + yd;
+ var dBase2 = xd + yd2;
+
+ if ( col!=null ) {
+
+ iDta[ dBase + 0 ] = col.r;
+ iDta[ dBase + 1 ] = col.g;
+ iDta[ dBase + 2 ] = col.b;
+ iDta[ dBase + 3 ] = 255;
+
+ iDta[ dBase + 4 ] = col.r;
+ iDta[ dBase + 5 ] = col.g;
+ iDta[ dBase + 6 ] = col.b;
+ iDta[ dBase + 7 ] = 255;
+
+ iDta[ dBase + 8 ] = col.r;
+ iDta[ dBase + 9 ] = col.g;
+ iDta[ dBase + 10 ] = col.b;
+ iDta[ dBase + 11] = 255;
+
+ iDta[ dBase + 12] = col.r;
+ iDta[ dBase + 13] = col.g;
+ iDta[ dBase + 14] = col.b;
+ iDta[ dBase + 15] = 255;
+
+ iDta[ dBase2 + 0 ] = col.r;
+ iDta[ dBase2 + 1 ] = col.g;
+ iDta[ dBase2 + 2 ] = col.b;
+ iDta[ dBase2 + 3 ] = 255;
+
+ iDta[ dBase2 + 4 ] = col.r;
+ iDta[ dBase2 + 5 ] = col.g;
+ iDta[ dBase2 + 6 ] = col.b;
+ iDta[ dBase2 + 7 ] = 255;
+
+ iDta[ dBase2 + 8 ] = col.r;
+ iDta[ dBase2 + 9 ] = col.g;
+ iDta[ dBase2 + 10 ] = col.b;
+ iDta[ dBase2 + 11] = 255;
+
+ iDta[ dBase2 + 12] = col.r;
+ iDta[ dBase2 + 13] = col.g;
+ iDta[ dBase2 + 14] = col.b;
+ iDta[ dBase2 + 15] = 255;
+
+ }
+
+
+ mask = mask >> 2;
+ mask2 = mask2 >> 2;
+ xd+=16;
+ }
+ }
+ else {
+ for( var xC = 0; xC<4; xC++) {
+
+ var col = null;
+ var val = 0;
+
+ if ( (byte & mask ) > 0 ) {
+ val=1;
+ }
+ if ( (byte & mask2 ) > 0 ) {
+ val+=2;
+ }
+
+ switch (val){
+ case 1:
+ col = mcCol1;
+ break;
+ case 2:
+ col = mcCol2;
+ break;
+ case 3:
+ col = fgCol;
+ break;
+ default:
+
+ }
+
+ var dBase = xd + yd;
+
+ if ( col!=null ) {
+
+ iDta[ dBase + 0 ] = col.r;
+ iDta[ dBase + 1 ] = col.g;
+ iDta[ dBase + 2 ] = col.b;
+ iDta[ dBase + 3 ] = 255;
+
+ iDta[ dBase + 4 ] = col.r;
+ iDta[ dBase + 5 ] = col.g;
+ iDta[ dBase + 6 ] = col.b;
+ iDta[ dBase + 7 ] = 255;
+
+ iDta[ dBase + 8 ] = col.r;
+ iDta[ dBase + 9 ] = col.g;
+ iDta[ dBase + 10 ] = col.b;
+ iDta[ dBase + 11] = 255;
+
+ iDta[ dBase + 12] = col.r;
+ iDta[ dBase + 13] = col.g;
+ iDta[ dBase + 14] = col.b;
+ iDta[ dBase + 15] = 255;
+
+ }
+
+
+ mask = mask >> 2;
+ mask2 = mask2 >> 2;
+ xd+=16;
+ }
+ }
+
+ dataPtr++;
+ }
+
+
+ yd += pixWidthM4;
+ if( long ) {
+ yd += pixWidthM4;
+ yd2 += pixWidthM4;
+ yd2 += pixWidthM4;
+ }
+ }
+
+ }
+
+ _renderDirectSprMono( no, x, y, long ) {
+ //https://retro64.altervista.org/blog/programming-sprites-the-commodore-64-simple-tutorial-using-basic-v2/
+
+ var fid = this.memory;
+ var iDta = this.iDta;
+ var pixWidthM4 = this.iwidth * 4;
+ var sprite = this.sprites[ no ];
+ var dataPtr = sprite.addr;
+
+ var fgCol = this.colors[ sprite.col ];
+
+ var xd0 = x << 2 /* multiply 4, 4 bytes per pixel */;
+ var yd= pixWidthM4 * y;
+ var yd2= pixWidthM4 * (y+1);
+
+
+ for( var yC = 0; yC<21; yC++) {
+
+ var xd = xd0;
+ for( var xByteCount=0; xByteCount < 3; xByteCount++) {
+
+ var byte = fid[ dataPtr ];
+ var mask = 0b10000000;
+
+ if(long) {
+ for( var xC = 0; xC<8; xC++) {
+
+ var dBase = xd + yd;
+ var dBase2 = xd + yd2;
+
+ if ( (byte & mask ) > 0 ) {
+
+ iDta[ dBase + 0 ] = fgCol.r;
+ iDta[ dBase + 1 ] = fgCol.g;
+ iDta[ dBase + 2 ] = fgCol.b;
+ iDta[ dBase + 3 ] = 255;
+
+ iDta[ dBase2 + 0 ] = fgCol.r;
+ iDta[ dBase2 + 1 ] = fgCol.g;
+ iDta[ dBase2 + 2 ] = fgCol.b;
+ iDta[ dBase2 + 3 ] = 255;
+ }
+
+
+ mask = mask >> 1;
+ xd+=4;
+ }
+ }
+ else {
+ for( var xC = 0; xC<8; xC++) {
+
+ var dBase = xd + yd;
+
+ if ( (byte & mask ) > 0 ) {
+
+
+ iDta[ dBase + 0 ] = fgCol.r;
+ iDta[ dBase + 1 ] = fgCol.g;
+ iDta[ dBase + 2 ] = fgCol.b;
+ iDta[ dBase + 3 ] = 255;
+
+ }
+ mask = mask >> 1;
+ xd+=4;
+ }
+ }
+ dataPtr++;
+ }
+
+ yd += pixWidthM4;
+ if( long ) { yd += pixWidthM4; yd2 += pixWidthM4; yd2 += pixWidthM4;}
+ }
+
+ }
+
+
+ _renderDirectSprMonoFat( no, x, y, long ) {
+ //https://retro64.altervista.org/blog/programming-sprites-the-commodore-64-simple-tutorial-using-basic-v2/
+
+ var fid = this.memory;
+ var iDta = this.iDta;
+ var pixWidthM4 = this.iwidth * 4;
+ var sprite = this.sprites[ no ];
+ var dataPtr = sprite.addr;
+
+ var fgCol = this.colors[ sprite.col ];
+
+ var xd0 = x << 2 /* multiply 4, 4 bytes per pixel */;
+ var yd= pixWidthM4 * y;
+ var yd2= pixWidthM4 * (y + 1);
+
+
+ for( var yC = 0; yC<21; yC++) {
+
+ var xd = xd0;
+ for( var xByteCount=0; xByteCount < 3; xByteCount++) {
+
+ var byte = fid[ dataPtr ];
+ var mask = 0b10000000;
+
+ if( long ) {
+ for( var xC = 0; xC<8; xC++) {
+
+ var dBase = xd + yd;
+ var dBase2 = xd + yd2;
+
+ if ( (byte & mask ) > 0 ) {
+
+ iDta[ dBase + 0 ] = fgCol.r;
+ iDta[ dBase + 1 ] = fgCol.g;
+ iDta[ dBase + 2 ] = fgCol.b;
+ iDta[ dBase + 3 ] = 255;
+
+ iDta[ dBase + 4 ] = fgCol.r;
+ iDta[ dBase + 5 ] = fgCol.g;
+ iDta[ dBase + 6 ] = fgCol.b;
+ iDta[ dBase + 7 ] = 255;
+
+ iDta[ dBase2 + 0 ] = fgCol.r;
+ iDta[ dBase2 + 1 ] = fgCol.g;
+ iDta[ dBase2 + 2 ] = fgCol.b;
+ iDta[ dBase2 + 3 ] = 255;
+
+ iDta[ dBase2 + 4 ] = fgCol.r;
+ iDta[ dBase2 + 5 ] = fgCol.g;
+ iDta[ dBase2 + 6 ] = fgCol.b;
+ iDta[ dBase2 + 7 ] = 255;
+
+ }
+
+
+ mask = mask >> 1;
+ xd+=8;
+ }
+ }
+ else {
+ for( var xC = 0; xC<8; xC++) {
+
+ var dBase = xd + yd;
+
+ if ( (byte & mask ) > 0 ) {
+
+ iDta[ dBase + 0 ] = fgCol.r;
+ iDta[ dBase + 1 ] = fgCol.g;
+ iDta[ dBase + 2 ] = fgCol.b;
+ iDta[ dBase + 3 ] = 255;
+
+ iDta[ dBase + 4 ] = fgCol.r;
+ iDta[ dBase + 5 ] = fgCol.g;
+ iDta[ dBase + 6 ] = fgCol.b;
+ iDta[ dBase + 7 ] = 255;
+
+
+ }
+
+
+ mask = mask >> 1;
+ xd+=8;
+ }
+ }
+
+
+ dataPtr++;
+ }
+
+ yd += pixWidthM4;
+ if( long ) {
+ yd += pixWidthM4;
+ yd2 += pixWidthM4;
+ yd2 += pixWidthM4;
+ }
+ }
+
+ }
+
+ _renderDirectChrMultiHres( x, y, ch0, colRam, chRamLoCol, chRamHiCol) {
+
+ var fid;
+ var dataPtr;
+
+ fid = this.memory;
+ dataPtr = this.videoBMRam;
+
+ var iDta = this.iDta;
+ var pixWidthM4 = this.iwidth * 4;
+
+ //( x, y, charIndex, colRam, chRamLoCol, chRamHiCol )
+ var bgCol = this.colors[ this.bgcol ];
+ var fgCol = this.colors[ colRam ];
+ var mcCol1 = this.colors[ chRamLoCol ];
+ var mcCol2 = this.colors[ chRamHiCol ];
+
+
+ var ch=ch0;
+
+ var row = ch >> 4 /* div 16*/ ;
+ var column = ch % 16;
+
+ var xd0 = x << 2 /* multiply 4 */;
+ var yd= pixWidthM4 * y;
+
+ var chM8 = dataPtr + (ch*8);
+
+ for( var yC = 0; yC<8; yC++) {
+ var xd = xd0;
+
+ var byte = fid[ chM8 + yC ];
+ var mask = 0b10000000;
+ var mask2 = 0b01000000;
+
+ for( var xC = 0; xC<4; xC+=1) { /*4 thick pixels */
+
+ var col = bgCol;
+ var val = 0;
+
+ if ( (byte & mask ) > 0 ) {
+ val=1;
+ }
+ if ( (byte & mask2 ) > 0 ) {
+ val+=2;
+ }
+
+ switch (val){
+ case 1:
+ col = mcCol1;
+ break;
+ case 2:
+ col = mcCol2;
+ break;
+ case 3:
+ col = fgCol;
+ break;
+ default:
+
+ }
+
+ var dBase = xd + yd;
+
+ iDta[ dBase + 0 ] = col.r;
+ iDta[ dBase + 1 ] = col.g;
+ iDta[ dBase + 2 ] = col.b;
+ iDta[ dBase + 3 ] = 255;
+
+ iDta[ dBase + 4 ] = col.r;
+ iDta[ dBase + 5 ] = col.g;
+ iDta[ dBase + 6 ] = col.b;
+ iDta[ dBase + 7 ] = 255;
+
+ xd+=8;
+ mask = mask >> 2;
+ mask2 = mask2 >> 2;
+ }
+ yd += pixWidthM4;
+ }
+
+ }
+
+ _renderDirectChrMono( x, y, ch0, col0, bgcol) {
+
+ var fid;
+ var dataPtr;
+
+ if( this.useHires ) {
+ fid = this.memory;
+ dataPtr = this.videoBMRam;
+ }
+ else {
+ if( this.useRomCharMem ) {
+ fid = this.fontImageRom;
+ dataPtr = 0;
+ }
+ else {
+ fid = this.memory;
+ dataPtr = this.videoRam;
+ }
+ }
+
+ var iDta = this.iDta;
+ var pixWidthM4 = this.iwidth * 4;
+
+ var fgCol = this.colors[ col0 ];
+ var bgCol = this.colors[ bgcol ];
+
+ var ch=ch0;
+
+ //calculate row + column nrs
+ var row = ch >> 4 /* div 16*/;
+ var column = ch % 16;
+
+
+ var xd0 = x << 2 /* multiply 4, 4 bytes per pixel */;
+ var yd= pixWidthM4 * y;
+
+ //BASE of source data -> chM8 = font data start offset + char offset
+ var chM8 = dataPtr + ch*8;
+
+ for( var yC = 0; yC<8; yC++) {
+ var xd = xd0;
+
+ var byte = fid[ chM8 + yC ];
+ var mask = 0b10000000;
+
+ for( var xC = 0; xC<8; xC++) {
+
+ var col = bgCol;
+
+ if ( (byte & mask ) > 0 ) {
+ col = fgCol;
+ }
+
+ var dBase = xd + yd;
+
+ iDta[ dBase + 0 ] = col.r;
+ iDta[ dBase + 1 ] = col.g;
+ iDta[ dBase + 2 ] = col.b;
+ iDta[ dBase + 3 ] = 255;
+
+ xd+=4;
+ mask = mask >> 1;
+ }
+ yd += pixWidthM4;
+ }
+
+ }
+
+ _renderDirectChrMulti( x, y, ch0, col0) {
+
+ var fid = this.fontImageRom;
+ var iDta = this.iDta;
+ var pixWidthM4 = this.iwidth * 4;
+
+ var fgCol = this.colors[ col0 ];
+ var bgCol = this.colors[ this.bgcol ];
+ var mcCol1 = this.colors[ this.mcol1 ];
+ var mcCol2 = this.colors[ this.mcol2 ];
+
+ var ch=ch0;
+
+ var row = ch >> 4 /* div 16*/ ;
+ var column = ch % 16;
+
+ var xd0 = x << 2 /* multiply 4 */;
+ var yd= pixWidthM4 * y;
+
+ var chM8 = ch*8;
+
+ for( var yC = 0; yC<8; yC++) {
+ var xd = xd0;
+
+ var byte = fid[ chM8 + yC ];
+ var mask = 0b10000000;
+ var mask2 = 0b01000000;
+
+ for( var xC = 0; xC<4; xC+=1) { /*4 thick pixels */
+
+ var col = bgCol;
+ var val = 0;
+
+ if ( (byte & mask ) > 0 ) {
+ val=1;
+ }
+ if ( (byte & mask2 ) > 0 ) {
+ val+=2;
+ }
+
+ switch (val){
+ case 1:
+ col = mcCol1;
+ break;
+ case 2:
+ col = mcCol2;
+ break;
+ case 3:
+ col = fgCol;
+ break;
+ default:
+
+ }
+
+ var dBase = xd + yd;
+
+ iDta[ dBase + 0 ] = col.r;
+ iDta[ dBase + 1 ] = col.g;
+ iDta[ dBase + 2 ] = col.b;
+ iDta[ dBase + 3 ] = 255;
+
+ iDta[ dBase + 4 ] = col.r;
+ iDta[ dBase + 5 ] = col.g;
+ iDta[ dBase + 6 ] = col.b;
+ iDta[ dBase + 7 ] = 255;
+
+ xd+=8;
+ mask = mask >> 2;
+ mask2 = mask2 >> 2;
+ }
+ yd += pixWidthM4;
+ }
+
+ }
+
+ setSideBorders( flag ) {
+ this.skipSideBorder = !flag;
+
+ this.rescale(this.xScale, this.yScale);
+ }
+
+
+ renderChar(x, y, c, col0, bgcol) {
+ var col = col0 % 16;
+
+ this._renderDirectChrMono( x, y, c, col, this.bgcol );
+ }
+
+ renderCharHires(x, y, c, col0, dummy) {
+ var col = col0 % 16;
+ var bgcol = (col0 & 240) >> 4;
+
+ this._renderDirectChrMono( x, y, c, col, bgcol );
+ }
+
+ renderCharHiresMC(x, y, charIndex, charMem, colMem) {
+
+ var chRamLoCol = charMem % 16;
+ var chRamHiCol = (charMem & 240) >> 4;
+ var colRam = colMem % 16;
+ this._renderDirectChrMultiHres( x, y, charIndex, colRam, chRamLoCol, chRamHiCol );
+ }
+
+ renderCharMC(x, y, c, col0) {
+ var col = col0 % 16;
+ if( col > 7 ) {
+ this._renderDirectChrMulti( x, y, c, col0 % 8);
+ }
+ else {
+
+ this._renderDirectChrMono( x, y, c, col0, bgcol );
+ }
+ }
+
+ _htmlColor( c ) {
+ return 'rgba('+c.r+','+c.g+','+c.b+',1)';
+ }
+
+
+ renderDisplay( ) {
+
+ this._intVICMem2VICVRegs();
+
+ if( this.bcolLast != this.bcol ) {
+
+ this._updateBorder();
+ this.bcolLast = this.bcol;
+ }
+
+ this._renderBuffer();
+ this._updateDisplay();
+ }
+
+ _updateBorder( ) {
+ var dw = this.FULLWIDTH;
+ var dh = this.FULLHEIGHT;
+ var dCtx = this.rcontext;
+ dCtx.fillStyle = this._htmlColor( this.colors[ this.bcol ] );
+ dCtx.fillRect(
+ 0,0,
+ dw,
+ dh
+ );
+ }
+
+ _updateDisplay( ) {
+
+ var sCvs = this.bufcanvas;
+ var dCtx = this.rcontext;
+
+ var w = 320;
+ var h = 200;
+ var dw = this.WIDTH;
+ var dh = this.HEIGHT;
+ var b = this.border;
+ var b0=this.border0;
+
+ //void ctx.drawImage(image, dx, dy);
+ //void ctx.drawImage(image, dx, dy, dWidth, dHeight);
+ //void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
+ //dCtx.drawImage( sCvs, b.w, b.h, dw, dh);
+
+ //old dCtx.drawImage( sCvs, 24, 21, w, h, b.w, b.h, dw, dh );
+
+
+ if( this.skipSideBorder ) {
+ dCtx.drawImage( sCvs, 24, 21, w, h, 0, b.h, dw, dh );
+ }
+ else {
+ dCtx.drawImage( sCvs, 24, 21, w, h, b.w, b.h, dw, dh );
+ }
+ }
+
+ _renderBackGround() {
+ var ctx = this.context;
+ var cvs = this.canvas;
+
+ ctx.fillStyle = this._htmlColor( this.colors[ this.bgcol ] );
+ ctx.fillRect(
+ 0,0,
+ cvs.width,
+ cvs.height
+ );
+ }
+
+ _renderBuffer() {
+ var buf = this.txScBuf;
+ var ctx = this.context;
+ var bufctx = this.bufcontext;
+
+ //ctx.fillStyle = this._htmlColor( this.colors[ this.bgcol ] );
+
+ var xo=24, yo=21;
+
+ if( this.useHires ) {
+
+ this.renderChr = this.renderCharHires;
+ if( this.multiColor ) {
+ this.renderChr = this.renderCharHiresMC;
+ }
+
+ if( this.bgcolLast != this.bgcol
+ || this.mcol1Last != this.mcol1
+ || this.mcol2Last != this.mcol2
+ || this.multiColorLast != this.multiColor
+ || this.useHiresLast != this.useHires
+
+ ) { //update whole screen
+ for( var y=0; y<25; y++) {
+ for( var x=0; x<40; x++) {
+
+ var chr = (y*40+x);
+ buf[y][x][2] = false;
+ this.renderChr(xo+x*8, yo+y*8, chr, buf[y][x][0], buf[y][x][1] );
+
+ }
+ }
+ this.bgcolLast = this.bgcol;
+ this.mcol1Last = this.mcol1;
+ this.mcol2Last = this.mcol2;
+ this.multiColorLast = this.multiColor;
+ this.useHiresLast = this.useHires;
+
+ }
+ else { //update only certain chars on screen
+
+ for( var y=0; y<25; y++) {
+ for( var x=0; x<40; x++) {
+
+ var chr = (y*40+x);
+
+ if( buf[y][x][2] ) {
+ buf[y][x][2] = false;
+ this.renderChr(xo+x*8, yo+y*8, chr, buf[y][x][0], buf[y][x][1] );
+ }
+ }
+ }
+ }
+ }
+ else {
+
+ this.renderChr = this.renderChar;
+ if( this.multiColor ) {
+ this.renderChr = this.renderCharMC;
+ }
+
+
+
+ if( this.bgcolLast != this.bgcol
+ || this.mcol1Last != this.mcol1
+ || this.mcol2Last != this.mcol2
+ || this.multiColorLast != this.multiColor
+ || this.useHiresLast != this.useHires
+ || this.screenRefresh
+ ) {
+
+ for( var y=0; y<25; y++) {
+ for( var x=0; x<40; x++) {
+
+ buf[y][x][2] = false;
+ this.renderChr(xo+x*8, yo+y*8, buf[y][x][0], buf[y][x][1] );
+
+ }
+ }
+ this.bgcolLast = this.bgcol;
+ this.mcol1Last = this.mcol1;
+ this.mcol2Last = this.mcol2;
+ this.multiColorLast = this.multiColor;
+ this.useHiresLast = this.useHires;
+ this.screenRefresh = false;
+ }
+ else {
+ for( var y=0; y<25; y++) {
+ for( var x=0; x<40; x++) {
+ if( buf[y][x][2] ) {
+ buf[y][x][2] = false;
+ this.renderChr(xo+x*8, yo+y*8, buf[y][x][0], buf[y][x][1] );
+ }
+ }
+ }
+ }
+ }
+
+ for( var i = this.sprites.length -1; i>=0; i-- ) {
+ var sp = this.sprites[ i ];
+ if( sp.enabled ) {
+
+ this.renderSprite( i, sp.x, sp.y );
+ }
+ }
+
+ ctx.putImageData(this.iImgDta, 0, 0);
+
+ bufctx.drawImage( this.canvas, 0, 0);
+
+ }
+
+
+ _prepColor( img, col ) {
+
+ var canvas = document.createElement('canvas');
+ var context = canvas.getContext('2d');
+
+ var w = img.width;
+ var h = img.height;
+
+ canvas.width = w;
+ canvas.height = h * 2;
+
+ context.drawImage( img, 0, 0 );
+ context.drawImage( img, 0, h );
+ var imgdata = context.getImageData(0, 0, w, h*2);
+ var dd = imgdata.data;
+
+ for (var y = 0; y < h; y++) {
+ for (var x = 0; x < w; x++) {
+ var offset = (x + ( y * w )) * 4;
+
+ if( dd[ offset ] != 0 && dd[ offset + 1 ] != 0 && dd[ offset + 2 ] != 0 ) {
+ dd[ offset ] = col.r;
+ dd[ offset + 1] = col.g;
+ dd[ offset + 2] = col.b;
+ }
+ }
+ }
+
+ for ( ; y < (h*2); y++) {
+ for (var x = 0; x < w; x++) {
+ var offset = (x + ( y * w )) * 4;
+
+
+ if( dd[ offset ] != 0 && dd[ offset + 1 ] != 0 && dd[ offset + 2 ] != 0 ) {
+
+ dd[ offset ] = 0;
+ dd[ offset + 1] = 0;
+ dd[ offset + 2] = 0;
+ }
+ else {
+ dd[ offset ] = col.r;
+ dd[ offset + 1] = col.g;
+ dd[ offset + 2] = col.b;
+ }
+ }
+ }
+
+ context.putImageData( imgdata, 0, 0);
+ return canvas;
+ }
+
+}
diff --git a/versions/0.8p5/res/script/kb.js b/versions/0.8p5/res/script/kb.js
new file mode 100644
index 0000000..a149d0a
--- /dev/null
+++ b/versions/0.8p5/res/script/kb.js
@@ -0,0 +1,452 @@
+
+function VirtualKB_event( x ) {
+
+ console.log("VirtualKB_event",x);
+
+}
+
+class VirtualKB {
+
+ constructor( kbTable, eventHandlerClass ) {
+
+ var U = undefined;
+ var ORIG = "%%%";
+
+
+ this.eventHandlerClass = eventHandlerClass;
+ this.kbArray = [];
+ this.htmlTable = kbTable;
+ this.shift = false;
+ this.shiftLock = false;
+ this.commodore = false;
+ this.control = false;
+
+
+ var T = this;
+ var kbArray = this.kbArray;
+
+ var kbRow = [];
+ kbRow.push( T.padDummyKey() );
+ kbRow.push( T.singleKey( "STOP", true, "stop" ) );
+ kbRow.push( T.singleKey( "MENU", true, "menu" ) );
+ kbRow.push( T.padDummyKey() );
+ kbRow.push( T.singleKey2( "F1", U, "", U, "", U, "F2", U ) );
+ kbRow.push( T.singleKey2( "F3", U, "", U, "", U, "F4", U ) );
+ kbRow.push( T.singleKey2( "F5", U, "", U, "", U, "F6", U ) );
+ kbRow.push( T.singleKey2( "F7", U, "", U, "", U, "F8", U ) );
+
+ kbRow.push( T.padDummyKey() );
+ kbRow.push( T.singleKey( "↑", false, "cursup" ) );
+ kbRow.push( T.padDummyKey() );
+ kbRow.push( T.longKey( "RESTORE", 2.0, "restore" ) );
+
+ kbArray.push( kbRow );
+
+
+ var kbRow = [];
+ kbRow.push( T.padDummyKey() );
+ kbRow.push( T.singleKey( "←", false, "leftarrow" ) );
+ kbRow.push( T.singleKey( "+" ) );
+ kbRow.push( T.singleKey( "-" ) );
+ kbRow.push( T.singleKey( "*" ) );
+ kbRow.push( T.singleKey2( "/", U, U, U, U, U, "?", U ) );
+ kbRow.push( T.singleKey( "£", false, "pound" ) );
+ kbRow.push( T.padDummyKey() );
+ kbRow.push( T.singleKey( "←", false, "cursleft" ) );
+ kbRow.push( T.singleKey( "↓", false, "cursdown" ) );
+ kbRow.push( T.singleKey( "→", false, "cursright" ) );
+ kbRow.push( T.padDummyKey() );
+ kbRow.push( T.singleKey2( "HOME", "home", U, U, U, U, "CLR", "clear", true ) );
+ kbArray.push( kbRow );
+
+
+ var kbRow = [];
+ kbRow.push( T.padDummyKey() );
+
+ kbRow.push( T.singleKey2( "1", U, "?", ORIG, "?", ORIG, "!", U ) );
+ kbRow.push( T.singleKey2( "2", U, "?", ORIG, "?", ORIG, "\"", U ) );
+ kbRow.push( T.singleKey2( "3", U, "?", ORIG, "?", ORIG, "#", U ) );
+ kbRow.push( T.singleKey2( "4", U, "?", ORIG, "?", ORIG, "$", U ) );
+ kbRow.push( T.singleKey2( "5", U, "?", ORIG, "?", ORIG, "%", U ) );
+ kbRow.push( T.singleKey2( "6", U, "?", ORIG, "?", ORIG, "&", U ) );
+ kbRow.push( T.singleKey2( "7", U, "?", ORIG, "?", ORIG, "'", U ) );
+ kbRow.push( T.singleKey2( "8", U, "?", ORIG, "?", ORIG, "(", U ) );
+ kbRow.push( T.singleKey2( "9", U, "?", ORIG, "?", ORIG, ")", U ) );
+ kbRow.push( T.singleKey2( "0", U, "?", ORIG, "?", ORIG, "", U ) );
+
+ kbRow.push( T.doubleKey2( "DEL", "delete", U, U, U, U, U, U ) );
+ kbRow.push( T.padDummyKey() );
+ kbArray.push( kbRow );
+
+ var kbRow = [];
+ kbRow.push( T.padDummyKey() );
+
+ kbRow.push( T.singleKey( "↑", false, "uparrow" ) );
+ kbRow.push( T.singleKey( "q" ) );
+ kbRow.push( T.singleKey( "w" ) );
+ kbRow.push( T.singleKey( "e" ) );
+ kbRow.push( T.singleKey( "r" ) );
+ kbRow.push( T.singleKey( "t" ) );
+ kbRow.push( T.singleKey( "y" ) );
+ kbRow.push( T.singleKey( "u" ) );
+ kbRow.push( T.singleKey( "i" ) );
+ kbRow.push( T.singleKey( "o" ) );
+ kbRow.push( T.singleKey( "p" ) );
+ kbRow.push( T.singleKey( "@" ) );
+
+ kbRow.push( T.padDummyKey() );
+ kbArray.push( kbRow );
+
+ var kbRow = [];
+ kbRow.push( T.padDummyKey() );
+
+ kbRow.push( T.singleKey( "=" ) );
+ kbRow.push( T.singleKey( "a" ) );
+ kbRow.push( T.singleKey( "s" ) );
+ kbRow.push( T.singleKey( "d" ) );
+ kbRow.push( T.singleKey( "f" ) );
+ kbRow.push( T.singleKey( "g" ) );
+ kbRow.push( T.singleKey( "h" ) );
+ kbRow.push( T.singleKey( "j" ) );
+ kbRow.push( T.singleKey( "k" ) );
+ kbRow.push( T.singleKey( "l" ) );
+ kbRow.push( T.singleKey2( ":", U, "1", U, "1", U, "[", U ) );
+ kbRow.push( T.singleKey2( ";", U, "1", U, "1", U, "]", U ) );
+
+
+ kbRow.push( T.padDummyKey() );
+ kbArray.push( kbRow );
+
+ var kbRow = [];
+ kbRow.push( T.padDummyKey() );
+ kbRow.push( T.singleKey( "LOCK", true, "lock" ) );
+
+ kbRow.push( T.singleKey( "z" ) );
+ kbRow.push( T.singleKey( "x" ) );
+ kbRow.push( T.singleKey( "c" ) );
+ kbRow.push( T.singleKey( "v" ) );
+ kbRow.push( T.singleKey( "b" ) );
+ kbRow.push( T.singleKey( "n" ) );
+ kbRow.push( T.singleKey( "m" ) );
+ kbRow.push( T.singleKey2( ".", U, "1", U, "1", U, "<", U ) );
+ kbRow.push( T.singleKey2( ",", U, "1", U, "1", U, ">", U ) );
+
+ kbRow.push( T.longKey( "RETURN", 2.0, "return" ) );
+ kbRow.push( T.padDummyKey() );
+ kbArray.push( kbRow );
+
+ var kbRow = [];
+ kbRow.push( T.padDummyKey() );
+ kbRow.push( T.longKey( "SHFT",1.5, "shift" ) );
+
+ var cbmLogo = "";
+ kbRow.push( T.singleKey( cbmLogo, 1, "commodore" ) );
+
+ kbRow.push( T.longKey( "SPACE", 8, " " ) );
+ kbRow.push( T.longKey( "CTRL", 1.5, "control" ) );
+
+ kbRow.push( T.padDummyKey() );
+
+
+
+ kbArray.push( kbRow );
+
+
+
+ const body = document.body,
+ tbl = kbTable;
+ tbl.classList.add("kbbg");
+
+ for (let i = 0; i < kbArray.length; i++) {
+ var r = kbArray[ i ];
+ const tr = tbl.insertRow();
+ for (let j = 0; j < r.length; j++) {
+
+ var k = r[ j ];
+ const td = tr.insertCell();
+ k.td = td;
+
+ if( k.pad ) {
+ var clazz = "kbkeys" + (k.width+"").replace(".","p");
+ //console.log( clazz );
+ td.colSpan = 1 * 2;
+ }
+ else {
+ if( k.visualSHIFT ) {
+ var shiftDiv = document.createElement("div");
+ shiftDiv.classList.add( "kbkeysShift" );
+
+ var plainDiv = document.createElement("div");
+ td.appendChild( shiftDiv );
+ td.appendChild( plainDiv );
+
+
+ shiftDiv.innerHTML = k.visualSHIFT;
+ plainDiv.innerHTML = k.visual;
+
+ shiftDiv.id = i + "_" + j + "_SDIV";
+ plainDiv.id = i + "_" + j + "_PDIV";
+
+ td.addEventListener('touchend', this, false);
+ }
+ else {
+ td.innerHTML = k.visual;
+ if( td.childNodes.length > 0) {
+ if( td.childNodes[0].localName == "img" ) {
+ td.childNodes[0].id = i + "_" + j + "_IMG";
+ }
+ }
+ td.addEventListener('touchend', this, false);
+ }
+
+ var clazz;
+
+ if( k.smallText === undefined ) {
+ clazz = "kbkeys" + (k.width+"").replace(".","p");
+ }
+ else {
+ clazz = "kbkeys1p5";
+ }
+
+ td.classList.add( clazz );
+ td.classList.add( "kbkeysbase" );
+ td.colSpan = k.width * 2;
+ td.id = i + "_" + j;
+
+
+ }
+
+ //td.style.border = '1px solid black';
+ }
+
+ }
+
+ }
+
+ handleEvent( x ) {
+ //console.log("handleEvent", x, x.type )
+
+ if( x.type == "touchend" ) {
+ var target = x.target.id.split("_");
+ var key = this.kbArray[ target[0]][target[1]];
+ var shift = this.shift;
+ var shiftLock = this.shiftLock;
+ var control = this.control;
+ var commodore = this.commodore;
+ var eventValue;
+
+ if( key.eventValue == "control") {
+ this.control = ! this.control;
+ this.controlKey = key;
+
+ if( this.control ) {
+ key.td.style="background-color: #0000aa"
+ }
+ else {
+ key.td.style="background-color: #000000"
+ }
+ return;
+ }
+ else if( key.eventValue == "commodore") {
+ this.commodore = ! this.commodore;
+ this.commodoreKey = key;
+
+ if( this.commodore ) {
+ key.td.style="background-color: #0000aa"
+ }
+ else {
+ key.td.style="background-color: #000000"
+ }
+ return;
+ }
+ else if( key.eventValue == "shift") {
+ this.shift = ! this.shift;
+ this.shiftKey = key;
+
+ if( this.shiftLock ) { this.shift = false; }
+ if( this.shift ) {
+ key.td.style="background-color: #0000aa"
+ }
+ else {
+ key.td.style="background-color: #000000"
+ }
+ return;
+ }
+ else if( key.eventValue == "lock") {
+ this.shiftLock = ! this.shiftLock;
+ //this.shiftLockKey = key;
+ if( this.shiftLock ) {
+ key.td.style="background-color: #0000aa"
+ }
+ else {
+ key.td.style="background-color: #000000"
+ }
+ return;
+ }
+ else {
+ eventValue = key.eventValue;
+
+ if( this.shift || this.shiftLock ) {
+
+ eventValue = key.eventValueSHIFT;
+ if( this.shift ) {
+ this.shift = false;
+ this.shiftKey.td.style="background-color: #000000";
+ }
+
+ }
+ else if( this.commodore ) {
+
+ eventValue = key.eventValueCBM;
+ if( eventValue == "%%%" ) {
+ eventValue = key.eventValue;
+ }
+ this.commodore = false;
+ this.commodoreKey.td.style="background-color: #000000";
+
+ }
+ else if( this.control ) {
+
+ eventValue = key.eventValueCTRL;
+ if( eventValue == "%%%" ) {
+ eventValue = key.eventValue;
+ }
+ this.control = false;
+ this.controlKey.td.style="background-color: #000000";
+
+ }
+
+ key.td.style="background-color: #0000aa";
+ setTimeout(function(){
+ // The code you want to run goes here.
+ key.td.style="background-color: #000000";
+ }, 150);
+ }
+
+ var newkey = {
+ shift: shift,
+ control: control,
+ commodore: commodore,
+ visual: key.visual,
+ width: key.width,
+ eventValue: eventValue,
+ smallText: key.smallText,
+ pad: key.pad
+ }
+
+ this.eventHandlerClass["handleVKPressEvent"]( newkey );
+
+ }
+ }
+
+ singleKey( visual, smallText, eventValue ) {
+
+ if( eventValue === undefined ) {
+ return {
+ visual: visual,
+ width: 1,
+ eventValue: visual,
+ smallText: smallText
+ }
+ }
+ return {
+ visual: visual,
+ width: 1,
+ eventValue: eventValue,
+ smallText: smallText
+ }
+ }
+
+
+ doubleKey2(
+ visualPlain, _eventValuePlain,
+ visualCTRL, _eventValueCTRL,
+ visualCBM, _eventValueCBM,
+ visualSHIFT, _eventValueSHIFT ) {
+
+ var eventValuePlain = _eventValuePlain,
+ eventValueCTRL = _eventValueCTRL,
+ eventValueCBM = _eventValueCBM,
+ eventValueSHIFT = _eventValueCBM;
+
+ if( eventValuePlain === undefined ) { eventValuePlain = visualPlain; }
+ if( eventValueCTRL === undefined ) { eventValueCTRL = visualCBM; }
+ if( eventValueSHIFT === undefined ) { eventValueSHIFT = visualSHIFT; }
+ if( eventValueCBM === undefined ) { eventValueCBM = visualCBM; }
+
+ return {
+ visual: visualPlain,
+ visualCTRL: visualCTRL,
+ visualCBM: visualCBM,
+ visualSHIFT: visualSHIFT,
+
+ eventValue: eventValuePlain,
+ eventValueCTRL: eventValueCTRL,
+ eventValueCBM: eventValueCBM,
+ eventValueSHIFT: eventValueSHIFT,
+
+ width: 2,
+
+ smallText: false
+ }
+ }
+
+
+ singleKey2(
+ visualPlain, _eventValuePlain,
+ visualCTRL, _eventValueCTRL,
+ visualCBM, _eventValueCBM,
+ visualSHIFT, _eventValueSHIFT,
+ smallText ) {
+
+ var eventValuePlain = _eventValuePlain,
+ eventValueCTRL = _eventValueCTRL,
+ eventValueCBM = _eventValueCBM,
+ eventValueSHIFT = _eventValueSHIFT;
+
+ if( eventValuePlain === undefined ) { eventValuePlain = visualPlain; }
+ if( eventValueCTRL === undefined ) { eventValueCTRL = visualCBM; }
+ if( eventValueSHIFT === undefined ) { eventValueSHIFT = visualSHIFT; }
+ if( eventValueCBM === undefined ) { eventValueCBM = visualCBM; }
+
+ return {
+ visual: visualPlain,
+ visualCTRL: visualCTRL,
+ visualCBM: visualCBM,
+ visualSHIFT: visualSHIFT,
+
+ eventValue: eventValuePlain,
+ eventValueCTRL: eventValueCTRL,
+ eventValueCBM: eventValueCBM,
+ eventValueSHIFT: eventValueSHIFT,
+
+ width: 1,
+
+ smallText: smallText
+ }
+ }
+
+
+ padDummyHalfKey() {
+ return {
+ pad: true,
+ width: .5
+ }
+ }
+
+ padDummyKey() {
+ return {
+ pad: true,
+ width: 1
+ }
+ }
+
+ longKey( visual, width, eventValue ) {
+ return {
+ visual: visual,
+ width: width,
+ eventValue: eventValue
+ }
+ }
+
+}
diff --git a/versions/0.8p5/res/script/menu.js b/versions/0.8p5/res/script/menu.js
new file mode 100644
index 0000000..391d8eb
--- /dev/null
+++ b/versions/0.8p5/res/script/menu.js
@@ -0,0 +1,2057 @@
+class Uploader {
+
+ constructor(element) {
+ this.debugFlag = false;
+ this.element = element;
+ this.callbackC = null;
+ this.callbackM = null;
+ this.isBinary = false;
+ }
+
+ setCallback(callbackC, callbackM, binary) {
+ this.callbackC = callbackC;
+ this.callbackM = callbackM;
+ this.debugFlag = false;
+ this.isBinary = binary;
+ }
+
+ start( filetypes, isBinary = false) {
+ this.element.accept = filetypes;
+ this.isBinary = isBinary;
+ this.element.click();
+
+ }
+
+ handleEvent(evt) {
+ if (this.debugFlag) {
+ console.log("handleEvent " + evt.type);
+ }
+
+ switch (evt.type) {
+ case "change":
+ if (this.debugFlag) {
+ console.log("--------------handle upload event");
+ console.log(evt);
+ }
+ if( !this.isBinary ) {
+ this.handleUpload(evt);
+ }
+ else {
+ this.handleBinaryUpload(evt);
+ }
+
+
+ break;
+ }
+ }
+
+ handleBinaryUpload(e) {
+
+ if (this.debugFlag) {
+ console.log("handleBinaryUpload " + e);
+ }
+
+ var reader = new FileReader();
+
+ var thisFileName = e.target.files[0].name;
+ var _this = this;
+
+ reader.onload = function (event) {
+
+ if (this.debugFlag) {
+ console.log("reader onload " + thisFileName);
+ }
+
+ var blob = event.target.result;
+
+ if (this.debugFlag) {
+ console.log(blob);
+ }
+
+ _this.callbackC[_this.callbackM](blob, thisFileName, null);
+
+ }
+
+ if (this.debugFlag) {
+ console.log("read " + e.target.files[0]);
+ console.log(e.target.files[0]);
+ }
+
+ reader.readAsArrayBuffer(e.target.files[0]);
+
+ }
+
+
+ handleUpload(e) {
+
+ if (this.debugFlag) {
+ console.log("handleUpload " + e);
+ }
+
+ var reader = new FileReader();
+
+ var thisFileName = e.target.files[0].name;
+ var _this = this;
+
+ reader.onload = function (event) {
+
+ if (this.debugFlag) {
+ console.log("reader onload " + thisFileName);
+ }
+
+ var text = event.target.result;
+ if (this.debugFlag) {
+ console.log(text);
+ }
+
+ _this.callbackC[_this.callbackM](text, thisFileName);
+
+ }
+
+ if (this.debugFlag) {
+ console.log("read " + e.target.files[0]);
+ console.log(e.target.files[0]);
+ }
+
+ reader.readAsText(e.target.files[0]);
+
+ }
+}
+
+
+class Menu {
+
+ constructor(screen, context) {
+
+ this.debugFlag = false;
+ this.console = screen;
+ this.context = context;
+ this.erh = new ErrorHandler();
+
+ var uploadElement = document.getElementById("imageLoader");
+
+ this.uploader = new Uploader( uploadElement );
+
+ this.runImportedPGMFlag = false;
+ this.uploader.setCallback(this, "notset");
+
+ uploadElement.addEventListener('change', this.uploader, true);
+
+ this.menuvmState = "main";
+ this.listSelector = false;
+ this.optSelect = 0;
+
+ this.options = {};
+ this.menus = {};
+ this.menuOffset = {};
+
+ this.stateMemory = new Uint8Array(256 * 256);
+
+ var opts = [];
+ //opts.push({opt: "status", display: "Status" });
+ //opts.push({opt: "loadsave", display: "Load/Save" });
+
+ opts.push({ opt: "basicMenu", display: "Basic" });
+ opts.push({ opt: "diskMenu", display: "Virtual Disk" });
+ opts.push({ opt: "exportMenu", display: "Import" });
+ opts.push({ opt: "clipboardMenu", display: "Clipboard" });
+ opts.push({ opt: "docsSettingsMenu", display: "Settings and docs" });
+ opts.push({ opt: "toolsMenu", display: "Tools" });
+ opts.push({ opt: "reset", display: "Reset" });
+
+ this.options["main"] = opts;
+ this.menus["main"] = "main";
+ this.menuOffset["main"] = 10;
+
+ opts = [];
+ opts.push({ opt: "copyPGMtoClip", display: "Copy program" });
+ opts.push({ opt: "pastePGMFromClip", display: "Paste Program" });
+ opts.push({ opt: "pastePGMFromClipAppend", display: "Paste and Merge" });
+ this.options["clipboard"] = opts;
+ this.menus["clipboard"] = "clipboard";
+ this.menuOffset["clipboard"] = 10;
+
+ opts = [];
+ opts.push({ opt: "generatePGMUrl", display: "Generate Program URL" });
+ opts.push({ opt: "copyPGMURLtoClip", display: "Generate Inline Program URL" });
+ this.options["tools"] = opts;
+ this.menus["tools"] = "tools";
+ this.menuOffset["tools"] = 3;
+
+ opts = [];
+ opts.push({ opt: "list", display: "List" });
+ opts.push({ opt: "renumber", display: "Renumber Basic Program" });
+ opts.push({ opt: "compress", display: "Remove Spaces" });
+ opts.push({ opt: "compress2", display: "Compress" });
+ opts.push({ opt: "PETSCIIreplace", display: "Strip PETSCII Chars" });
+ opts.push({ opt: "normalize", display: "Normalize Spaces" });
+ this.options["basic"] = opts;
+ this.menus["basic"] = "basic";
+ this.menuOffset["basic"] = 4;
+
+ opts = [];
+ opts.push({ opt: "importBas", display: "Import Basic Program" });
+ opts.push({ opt: "importBasRun", display: "Import/Run Basic Program" });
+ opts.push({ opt: "exportBas", display: "Export Basic Program" });
+ opts.push({ opt: "exportBasNoPETSCII", display: "Export Basic Program:nopet" });
+ opts.push({ opt: "importPRGBas", display: "Import Basic PRG File" });
+ opts.push({ opt: "importSnapshot", display: "Import Snapshot" });
+ opts.push({ opt: "exportSnapshot", display: "Export Snapshot" });
+ opts.push({ opt: "importVDisk", display: "Import Virtual Disk" });
+ opts.push({ opt: "exportVDisk", display: "Export Virtual Disk" });
+
+ this.options["export"] = opts;
+ this.menus["export"] = "export";
+ this.menuOffset["export"] = 5;
+
+
+ opts = [];
+ opts.push({ opt: "changeExitMode", display: "exit mode" });
+ opts.push({ opt: "changeImmersiveMode", display: "immersive mode" });
+ opts.push({ opt: "changeClock", display: "clock mode" });
+ opts.push({ opt: "changeTurbo", display: "turbo mode" });
+ opts.push({ opt: "changeRenum", display: "renumber mode" });
+ opts.push({ opt: "changeExtended", display: "Extended commands" });
+ opts.push({ opt: "changeDisplay", display: "Display" });
+ opts.push({ opt: "changeTheme", display: "Change Menu Theme" });
+ opts.push({ opt: "documentation", display: "documentation" });
+ this.options["docssettings"] = opts;
+ this.menus["docssettings"] = "docs & settings";
+ this.menuOffset["docssettings"] = 9;
+
+ opts = [];
+ opts.push({ opt: "listDirectory", display: "Load File" });
+ opts.push({ opt: "formatDisk", display: "Format Disk", confirm: true });
+ opts.push({ opt: "listDisks", display: "Swap Disks" });
+ opts.push({ opt: "createDisk", display: "Create new Disk", confirm: true });
+ opts.push({ opt: "saveSnapshot", display: "Save Snapshot" });
+
+ this.options["disk"] = opts;
+ this.menus["disk"] = "disk";
+ this.menuOffset["disk"] = 12;
+
+ this.themes = [];
+
+
+ this.themes.push(
+ {
+ bg: 2,
+ border: 2,
+ fg: 0,
+ hl: 7,
+ logorows: [8, 8, 7, 4],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
+
+ this.themes.push(
+ {
+ bg: 6,
+ border: 6,
+ fg: 14,
+ hl: 1,
+ logorows: [3, 3, 3, 3],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
+
+ this.themes.push(
+ {
+ bg: 6,
+ border: 6,
+ fg: 14,
+ hl: 1,
+ logorows: [8, 8, 8, 8],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
+
+ this.themes.push(
+ {
+ bg: 6,
+ border: 6,
+ fg: 14,
+ hl: 1,
+ logorows: [14, 14, 14, 14],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
+
+ this.themes.push(
+ {
+ bg: 0,
+ border: 0,
+ fg: 8,
+ hl: 7,
+ logorows: [8, 8, 8, 8],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
+
+ this.themes.push(
+ {
+ bg: 0,
+ border: 0,
+ fg: 14,
+ hl: 1,
+ logorows: [6, 6, 6, 6],
+ splotches: [[36, 2, 14], [36, 3, 14]]
+ }
+ );
+
+ this.themes.push(
+ {
+ bg: 0,
+ border: 0,
+ fg: 5,
+ hl: 13,
+ logorows: [5, 5, 5, 5],
+ splotches: [[36, 2, 13], [36, 3, 13]]
+ }
+ );
+
+ this.themes.push(
+ {
+ bg: 11,
+ border: 11,
+ fg: 12,
+ hl: 1,
+ logorows: [0, 0, 0, 0],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
+
+ this.themes.push(
+ {
+ bg: 11,
+ border: 12,
+ fg: 12,
+ hl: 1,
+ logorows: [0, 0, 0, 0],
+ splotches: [[36, 2, 1], [36, 3, 1]]
+ }
+ );
+
+ this.themes.push(
+ {
+ bg: 14,
+ border: 6,
+ fg: 6,
+ hl: 0,
+ logorows: [0, 6, 3, 1],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
+
+ this.themes.push(
+ {
+ bg: 0,
+ border: 5,
+ fg: 13,
+ hl: 1,
+ logorows: [1, 1, 7, 13],
+ splotches: [[36, 2, 8], [36, 3, 8]]
+ }
+ );
+
+ this.themes.push(
+ {
+ bg: 6,
+ border: 14,
+ fg: 14,
+ hl: 1,
+ logorows: [5, 5, 3, 5],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
+ this.themes.push(
+ {
+ bg: 6,
+ border: 14,
+ fg: 14,
+ hl: 1,
+ logorows: [4, 4, 8, 4],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
+ this.themes.push(
+ {
+ bg: 6,
+ border: 14,
+ fg: 14,
+ hl: 1,
+ logorows: [7, 7, 1, 7],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
+ this.themes.push(
+ {
+ bg: 6,
+ border: 14,
+ fg: 14,
+ hl: 1,
+ logorows: [1, 1, 1, 1],
+ splotches: [[36, 2, 7], [36, 3, 7]]
+ }
+ );
+
+ this.theme = 0;
+
+ var menuSettings = localStorage.getItem("BJ64_Menu");
+ if (menuSettings != null) {
+ menuSettings = JSON.parse(menuSettings);
+ this.theme = menuSettings.theme;
+ }
+
+ //this.initLogo();
+ }
+
+ initLogo() {
+
+ var context = this.context;
+
+ var logo = getMenuLogo();
+ this.logo = logo;
+
+ context.poke(53265, 27);
+ context.poke(53272, 12);
+ context.poke(1, 0);
+ for (var i = 0; i < (64 * 8); i++) {
+ context.poke(12288 + i, context.peek(53248 + i));
+ }
+ context.poke(1, 255);
+
+ for (var i = 0; i < this.logo.length; i++) {
+ context.poke(12288 + (64 * 8) + i, this.logo[i]);
+ }
+
+ }
+
+ rendervmState() {
+
+ var t = this;
+ var context = this.context;
+ var theme = this.themes[this.theme];
+
+ context.poke(53280, theme.border);
+ context.poke(53281, theme.bg);
+ context.poke(53269, 0);
+ context.poke(53270, 200);
+
+ t.rendervmStateText();
+
+ }
+
+
+ rendervmStateText() {
+
+ var t = this;
+ var context = this.context;
+ var theme = this.themes[this.theme];
+
+ var txtColor = theme.fg;
+ var hlColor = theme.hl;
+ var cols1 = theme.logorows;
+
+ t.console.clearScreen();
+ t.console.setColor(txtColor);
+
+ var title = t.menus[t.menuvmState];
+ var options = this.options[t.menuvmState];
+
+ var x;
+ var drawMenu = !this.selectList;
+ var maxPrintCount = 11;
+ var skiplineInList = true;
+
+ if (!this.hideLogo || drawMenu) {
+
+ /********* draw logo ***/
+ var c = 64, xof = 4, yof = 1;
+ var x, y, addr, caddr;
+ for (y = 0; y < 4; y++) {
+ for (x = 0; x < 34; x++) {
+ addr = 1024 + xof + x + ((y + yof) * 40);
+ caddr = 55296 + xof + x + ((y + yof) * 40);
+ this.context.poke(addr, c);
+ var col = cols1[y];
+ this.context.poke(caddr, col);
+ c++;
+ }
+ }
+
+ for (var i = 0; i < theme.splotches.length; i++) {
+ var sp = theme.splotches[i];
+ x = sp[0]; y = sp[1]; caddr = 55296 + x + ((y) * 40); this.context.poke(caddr, sp[2]);
+ }
+ /********* end draw logo ***/
+ t.nl(); t.nl(); t.nl(); t.nl(); t.nl(); t.nl();
+ }
+ else {
+ maxPrintCount = 23;
+ skiplineInList = false;
+ }
+
+
+ if (!this.selectList) {
+ /**** Draw menu option ****/
+ if (title != "main") {
+ var menuStr = "*** " + title + " ***";
+ x = 20 - (Math.floor(menuStr.length / 2));
+ t.padLine(x, menuStr);
+ }
+
+ t.nl();
+
+ x = this.menuOffset[t.menuvmState];
+
+ this.curs = [];
+ if (options.length <= 8) {
+ maxPrintCount = 8;
+ skiplineInList = true;
+ }
+ else {
+ maxPrintCount = 16;
+ skiplineInList = false;
+ }
+
+ for (var i = 0; i < maxPrintCount && i < options.length; i++) {
+
+ if (i == this.optSelect) {
+ t.console.setColor(hlColor);
+ }
+ else {
+ t.console.setColor(txtColor);
+ }
+ t.pad(x, " " + (i + 1) + " - " + options[i].display);
+
+ this.curs.push(t.console.getCursorPos());
+
+ t.nl();
+ if (skiplineInList) {
+ t.nl();
+ }
+ }
+
+ }
+ else {
+ /**** Draw list of data ****/
+
+
+ if (this.showNumbers) {
+ maxPrintCount = maxPrintCount - 4;
+ }
+
+ if (!this.hideLogo) {
+
+ var menuStr = "*** " + this.listTitle + " ***";
+ x = 20 - (Math.floor(menuStr.length / 2));
+ var offX = x;
+ if (this.listOffset != -1) {
+ offX = this.listOffset;
+ }
+ t.padLine(x, menuStr);
+
+ t.nl();
+
+ }
+
+ this.listPage = Math.floor((this.optSelect) / 5);
+ if (this.listPage < 0) {
+ this.listPage = 0;
+ }
+ var offset = this.listPage * 4;
+ var printCount = 0;
+ this.curs = [];
+ var more = false;
+
+ if (offset > 0) {
+ t.pad(offX, "...");
+ t.nl();
+ }
+ else {
+ t.pad(offX, "");
+ t.nl();
+ }
+
+ var first = true;
+ for (var i = 0; i < this.listItems.length; i++) {
+
+ if (i < offset) {
+ continue;
+ }
+ else {
+ if (first) {
+ this.page_first = i;
+ first = false;
+ }
+ }
+ this.page_last = i;
+
+ if (printCount >= maxPrintCount) {
+ more = true;
+ break;
+ }
+
+ if (i == this.optSelect) {
+ t.console.setColor(hlColor);
+ }
+ else {
+ t.console.setColor(txtColor);
+ }
+ if (this.showNumbers) {
+ t.padSave(this.listOffset, " " + (i + 1) + " - " + this.listItems[i].name);
+ }
+ else {
+ t.printCodeLine(this.listItems[i].name);
+ }
+
+ if (skiplineInList) {
+ t.nl();
+ }
+
+ this.curs.push(t.console.getCursorPos());
+
+ printCount++;
+ }
+ if (more) {
+ t.pad(offX, "...");
+ }
+ }
+ }
+
+
+ color(x) {
+ this.console.setColor(x);
+ }
+
+ nl() {
+ this.context.printLine("");
+ }
+
+ pad(pad, txt) {
+
+ var padStr = "";
+ for (var i = 0; i < pad; i++) {
+ padStr += " ";
+ }
+
+ this.context.print(padStr + txt);
+ }
+
+ padSave(pad, txt) {
+
+ var padStr = "";
+ for (var i = 0; i < pad; i++) {
+ padStr += " ";
+ }
+
+ this.context.printLineVisibleChars(padStr + txt.toUpperCase());
+ }
+
+
+ printCodeLine(x) {
+ this.context.listCodeLine(x);
+ }
+
+ padLine(pad, txt) {
+
+ var padStr = "";
+ for (var i = 0; i < pad; i++) {
+ padStr += " ";
+ }
+ this.context.printLine(padStr + txt);
+ }
+
+ start() {
+
+ this.console.clearCursor();
+
+ this.vmState =
+ {
+ console: this.console.getState(),
+ pgm: this.context.getProgram(),
+ pgmState: this.context.getProgramState(),
+ }
+
+ var mem = this.console.getMemory();
+ for (var i = 0; i < (256 * 256); i++) {
+ this.stateMemory[i] = mem[i];
+ }
+
+ if (this.debugFlag) {
+ console.log(this.vmState);
+ }
+ this.initLogo();
+ this.rendervmState();
+
+ }
+
+ startList(l) {
+
+ this.selectList = true;
+ this.oldOptSelect = this.optSelect;
+ this.optSelect = 0;
+ this.listPage = 0;
+ this.listTitle = l.title;
+ this.listItems = l.items;
+ this.listResult = -1;
+ this.listCallback = l.callback;
+ this.listOffset = -1;
+ this.listAtExit = "close";
+ if (!(l.offset === undefined)) {
+ this.listOffset = l.offset;
+ }
+ if (!(l.atExit === undefined)) {
+ this.listAtExit = l.atExit;
+ }
+ this.showNumbers = true;
+ if (!(l.showNum === undefined)) {
+ this.showNumbers = l.showNum;
+ }
+ this.hideLogo = false;
+ if (l.hideLogo) {
+ this.hideLogo = true;
+ }
+
+ this.rendervmStateText();
+ }
+
+
+ message(m) {
+ this.context.printLine("*** " + m);
+ }
+
+ errorMessage(m, extra0) {
+ this.context.printLine("??" + m + " error");
+
+ var extra = "";
+ if (!(extra0 === undefined)) {
+ extra = ">" + extra0;
+ this.context.printLine( extra );
+ }
+
+ }
+
+ stop() {
+ if (this.debugFlag) {
+ console.log("End menu");
+ }
+
+ this.console.setState(this.vmState.console);
+
+ var mem = this.console.getMemory();
+ for (var i = 0; i < (256 * 256); i++) {
+ mem[i] = this.stateMemory[i];
+ }
+ this.console.clearCursor();
+ //this.context.setBorderChangedFlag();
+ }
+
+ endMenu() {
+ this.context.endMenu();
+ this.stop();
+ }
+
+ handleImportError(e) {
+ if (this.erh.isError(e)) {
+ this.context.printLine("");
+ this.context.printError(e.clazz, false, e.lineNr);
+ this.context.printLine(">" + e.detail);
+ if( e.lineText ) {
+ this.context.sendCharsSimple( ">" + e.lineText, true);
+ }
+ this.context.printLine("ready.");
+ }
+
+ }
+
+
+ endMenuWithMessage(m, detailError) {
+ this.context.endMenu();
+ this.stop();
+ this.context.printLine("");
+ if (!(detailError === undefined)) {
+ this.message(m);
+ this.context.printLine("");
+ this.context.printLine("?" + detailError.typeError);
+ this.context.printLine("!" + detailError.detailError);
+ }
+ else {
+ this.message(m);
+ }
+
+ }
+
+ endMenuWithError(m, extra) {
+ this.context.endMenu();
+ this.stop();
+ this.context.printLine("");
+ this.errorMessage(m, extra);
+ this.context.printLine( "ready" );
+ }
+
+
+
+ handleKey(evt) {
+
+ if (evt.key == "Enter") {
+
+ if (this.selectList == true) {
+
+ var listIndex = this.optSelect;
+
+ if (this.debugFlag) {
+ console.log("List selected " + listIndex);
+ console.log("List selected item " + this.listItems[listIndex].id);
+ }
+
+ if (this.listAtExit != "stay") {
+
+ this.selectList = false;
+ this.optSelect = this.oldOptSelect;
+
+ }
+
+ this.rendervmStateText();
+
+ this[this.listCallback](this.listItems[listIndex].id,
+ {
+ ixFrom: this.page_first,
+ ixTo: this.page_last
+ });
+
+ }
+ else {
+ var options = this.options[this.menuvmState];
+
+ if (this.debugFlag) {
+ console.log(this.optSelect);
+ }
+
+ var opt = options[this.optSelect];
+
+ if (!opt.confirm) {
+ this["do_" + opt.opt]();
+ }
+ else {
+ this.chooseYesOrNo(opt.display, "do_" + opt.opt);
+ }
+ }
+ }
+ if (evt.key == "Escape") {
+
+ if (this.selectList == true) {
+ this.selectList = false;
+ this.optSelect = this.oldOptSelect;
+ this.rendervmStateText();
+ }
+ else if (this.menuvmState == "main") {
+ this.endMenu();
+ }
+ else {
+ this.do_mainMenu();
+ }
+
+ }
+ else if (evt.key == "Pause" && evt.ctrlKey) {
+ }
+ else if (evt.key == "ArrowUp") {
+ //var options = this.options[ this.menuvmState ];
+ if ((this.optSelect) > 0) {
+ this.optSelect--;
+ this.rendervmStateText();
+ evt.preventDefault();
+ }
+ }
+ else if (evt.key == "ArrowDown") {
+
+ if (this.selectList == true) {
+ if ((this.optSelect + 1) < this.listItems.length) {
+ this.optSelect++;
+ this.rendervmStateText();
+ }
+ }
+ else {
+ var options = this.options[this.menuvmState];
+ if ((this.optSelect + 1) < options.length) {
+ this.optSelect++;
+ this.rendervmStateText();
+ }
+ }
+ evt.preventDefault();
+ }
+ else if (evt.key == "F1" || evt.key == "1") {
+ this.executeOption(0);
+ evt.preventDefault();
+ }
+ else if (evt.key == "F2" || evt.key == "2") {
+ this.executeOption(1);
+ evt.preventDefault();
+ }
+ else if (evt.key == "F3" || evt.key == "3") {
+ this.executeOption(2);
+ evt.preventDefault();
+ }
+ else if (evt.key == "F4" || evt.key == "4") {
+ this.executeOption(3);
+ evt.preventDefault();
+ }
+ else if (evt.key == "F5" || evt.key == "5") {
+ this.executeOption(4);
+ evt.preventDefault();
+ }
+ else if (evt.key == "F6" || evt.key == "6") {
+ this.executeOption(5);
+ evt.preventDefault();
+ }
+ else if (evt.key == "F7" || evt.key == "7") {
+ this.executeOption(6);
+ evt.preventDefault();
+ }
+ else if (evt.key == "F8" || evt.key == "8") {
+ this.executeOption(7);
+ evt.preventDefault();
+ }
+ }
+
+ executeOption(no) {
+ var options = this.options[this.menuvmState];
+
+ if ((no + 1) <= options.length) {
+
+ this.optSelect = no;
+
+ if (this.debugFlag) {
+ console.log(this.optSelect);
+ }
+
+ var opt = options[this.optSelect];
+
+ if (this.debugFlag) {
+ console.log(opt);
+ }
+ this["do_" + opt.opt]();
+
+ }
+
+ }
+
+
+ do_docsSettingsMenu() {
+ this.menuvmState = "docssettings";
+ this.optSelect = 0
+ this.rendervmState();
+ }
+
+ do_exportMenu() {
+ this.menuvmState = "export";
+ this.optSelect = 0
+ this.rendervmState();
+ }
+
+ do_diskMenu() {
+ this.menuvmState = "disk";
+ this.optSelect = 0
+ this.rendervmState();
+ }
+
+ do_toolsMenu() {
+ this.menuvmState = "tools";
+ this.optSelect = 0
+ this.rendervmState();
+ }
+
+ do_clipboardMenu() {
+ this.menuvmState = "clipboard";
+ this.optSelect = 0
+ this.rendervmState();
+ }
+
+ do_mainMenu() {
+ this.menuvmState = "main";
+ this.optSelect = 0
+ this.rendervmState();
+ }
+
+ do_basicMenu() {
+ this.menuvmState = "basic";
+ this.optSelect = 0
+ this.rendervmState();
+ }
+
+
+ do_copyPGMURLtoClip() {
+
+ var text = this.context.getProgramAsText();
+
+ var url = window.location +
+ "?pgm=" +
+ encodeURIComponent(btoa(text));
+
+ if (this.debugFlag) {
+ console.log(url);
+ console.log(btoa(text));
+
+ console.log(atob(btoa(text)));
+ }
+
+ navigator.clipboard.writeText(url);
+
+ this.endMenuWithMessage("url to clip");
+ }
+
+ do_generatePGMUrl() {
+
+ registerClipboardCallback(this, "do_generatePGMUrlCallBack");
+ enableConvertLinkWidget();
+ this.runImportedPGMFlag = false;
+ }
+
+ do_generatePGMUrlCallBack(text) {
+
+ var encodedLink = encodeURIComponent(text);
+ setLinkCallbackText(document.URL + "?linkpgm=" + encodedLink);
+ }
+
+
+ do_copyPGMtoClip() {
+ navigator.clipboard.writeText(this.context.getProgramAsText());
+
+ this.endMenuWithMessage("copied to clip");
+ }
+
+ do_pastePGMFromClipAppend() {
+
+ registerClipboardCallback(this, "do_pastePGMFromClipAppendCallback");
+ enableClipBoardWidget();
+ this.runImportedPGMFlag = false;
+ }
+
+ do_pastePGMFromClip() {
+
+ registerClipboardCallback(this, "do_pastePGMFromClipCallback");
+ enableClipBoardWidget();
+ this.runImportedPGMFlag = false;
+ }
+
+
+ do_pastePGMFromClipAppendCallback(text) {
+
+ if (this.debugFlag) {
+ console.log("callback3");
+ }
+
+ var lines = text.split(/\r?\n/);
+
+ try {
+ var bas = this.context.textLinesToBas(lines);
+ this.context.appendProgram(bas);
+
+ this.endMenuWithMessage("paste ok");
+ this.context.printLine("list");
+
+ var pgm = this.context.getProgramLines();
+ for (const l of pgm) {
+ this.context.listCodeLine(l[2]);
+
+ if (this.debugFlag) {
+ console.log(l[2]);
+ }
+ }
+
+ }
+ catch (e) {
+
+ this.endMenuWithMessage("parse error on import", detailError);
+ var detailError = this.handleImportError(e);
+ console.log(e);
+ return;
+ }
+ }
+
+ do_pastePGMFromClipCallback(text) {
+
+ if (this.debugFlag) {
+ console.log("callback2");
+ }
+
+ var lines = text.split(/\r?\n/);
+
+ try {
+ var bas = this.context.textLinesToBas(lines);
+ this.context.setProgram(bas);
+
+ this.endMenuWithMessage("paste ok");
+ this.context.printLine("list");
+
+ var pgm = this.context.getProgramLines();
+ for (const l of pgm) {
+ this.context.listCodeLine(l[2]);
+ if (this.debugFlag) {
+ console.log(l[2]);
+ }
+ }
+ }
+ catch (e) {
+
+ var detailError = this.handleImportError(e);
+ this.endMenuWithMessage("parse error on import", detailError);
+
+ console.log(e);
+ return;
+ }
+ }
+
+ do_listDisks() {
+
+ if (!this.context.confirmCookies()) {
+ return;
+ }
+
+ var list = { title: "Select Disk", items: [] };
+
+ var disks = this.context.getDisks();
+ for (var i = 0; i < disks.length; i++) {
+ list.items.push({ name: disks[i], id: disks[i] });
+ }
+
+
+ list.callback = "select_Disk";
+
+ this.startList(list);
+
+ }
+
+ select_Disk(id) {
+
+ this.context.selectDisk(id);
+ }
+
+ select_ExitMode(id) {
+ localStorage.setItem("BJ64_ExitMode", JSON.stringify({ exitmode: id }));
+
+ if (id == "stay") {
+ this.context.setExitMode("stay");
+ }
+ else {
+ this.context.setExitMode("panic");
+ }
+
+ }
+
+ select_ImmersiveMode(id) {
+ localStorage.setItem("BJ64_ImmersiveMode", JSON.stringify({ immersive: id }));
+
+ if (id == "immersive") {
+ this.context.setImmersiveFlag(true);
+ this.context.setBorderChangedFlag();
+ }
+ else {
+ this.context.setImmersiveFlag(false);
+ default_Document_Page_Color();
+ }
+
+ }
+
+ select_Clock(id) {
+ if (this.debugFlag) {
+ console.log(id);
+ }
+
+ localStorage.setItem("BJ64_Clock", JSON.stringify({ synchronized: id }));
+
+ if (id == "clocksync") {
+ this.context.synchClock();
+ }
+ }
+
+
+ select_Extended(id) {
+ if (this.debugFlag) {
+ console.log(id);
+ }
+
+ localStorage.setItem("BJ64_Extended", JSON.stringify({ extended: id }));
+
+ if (id == "on") {
+ this.context.enableExtended(true);
+ }
+ }
+
+ do_createDisk() {
+ if (!this.context.confirmCookies()) {
+ return;
+ }
+
+ this.context.createDisk();
+ this.infoBox("a new disk has been created");
+ }
+
+ do_formatDisk() {
+ if (!this.context.confirmCookies()) {
+ return;
+ }
+
+ if (this.debugFlag) {
+ console.log("do_FormatDisk");
+ }
+ this.context.formatDisk();
+
+ if (this.debugFlag) {
+ console.log("Formating Disk...");
+ }
+
+ this.infoBox("Disk has been formatted");
+ }
+
+ chooseYesOrNoCallBack(id) {
+
+ if (id == "yes") {
+ this[this.chooseYesCallBack]();
+ }
+
+ }
+
+ chooseYesOrNo(action, callback) {
+
+ var list = {
+ title: action + " - Are you sure?", items: [
+ { name: "Yes", id: "yes" },
+ { name: "No", id: "no" }
+ ]
+ };
+
+ this.chooseYesCallBack = callback;
+ list.callback = "chooseYesOrNoCallBack";
+
+ if (this.debugFlag) {
+ console.log("list options");
+ }
+
+ this.startList(list);
+
+ }
+
+ emptyCallBack(id) {
+ }
+
+ infoBox(info) {
+
+ var list = {
+ title: info, items: [
+ { name: "Ok", id: "ok" }
+ ]
+ };
+
+ list.callback = "emptyCallBack";
+
+ this.startList(list);
+
+ }
+
+ do_changeDisplay() {
+
+ if (!this.context.confirmCookies()) {
+ return;
+ }
+
+ var list = {
+ title: "Select Zoom", items: [
+ { name: "1.0x", id: "1.0" },
+ { name: "1.5x", id: "1.5" },
+ { name: "2.0x", id: "2.0" },
+ { name: "2.5x", id: "2.5" },
+ { name: "3.0x", id: "3.0" },
+ { name: "3.5x", id: "3.5" },
+ { name: "4.0x", id: "4.0" },
+ { name: "4.5x", id: "4.5" },
+ { name: "5.0x", id: "5.0" },
+ { name: "5.5x", id: "5.5" },
+ { name: "Side Borders", id: "sideborders" }
+ ]
+ };
+
+ list.callback = "select_Display";
+ list.atExit = "stay";
+
+ if (this.debugFlag) {
+ console.log("list options");
+ }
+
+ this.startList(list);
+
+ }
+
+ select_Display(id) {
+ if (this.debugFlag) {
+ console.log(id);
+ }
+
+ if (id == "sideborders") {
+ this.context.toggleSideBorders();
+ var flag = this.context.getSideBordersFlag();
+ localStorage.setItem("BJ64_SideBorder", JSON.stringify({ sideborder: flag }));
+ }
+ else {
+ localStorage.setItem("BJ64_Zoom", JSON.stringify({ zoom: id }));
+
+ this.context.setScale(id);
+ }
+
+ }
+
+ do_changeExtended() {
+
+ if (!this.context.confirmCookies()) {
+ return;
+ }
+
+ var list = {
+ title: "Extended Commands", items: [
+ { name: "on at startup", id: "on" },
+ { name: "'XON' command to enable", id: "xon" }
+ ]
+ };
+
+ list.callback = "select_Extended";
+
+ if (this.debugFlag) {
+ console.log("list options");
+ }
+
+ this.startList(list);
+
+ }
+
+ select_RenumberMode(id) {
+ if (this.debugFlag) {
+ console.log(id);
+ }
+
+ localStorage.setItem("BJ64_Renum", JSON.stringify({ renumMode: id }));
+
+ this.context.setRenumMode(id);
+ }
+
+ select_Turbo(id) {
+ if (this.debugFlag) {
+ console.log(id);
+ }
+
+ localStorage.setItem("BJ64_Turbo", JSON.stringify({ turbo: id }));
+
+ if (id == "on") {
+ this.context.setTurbo(true);
+ }
+ }
+
+ select_List(id, page) {
+ if (this.debugFlag) {
+ console.log(id, page);
+ }
+ this.endMenuWithMessage("LISTING PAGE");
+
+ var pgm = this.context.getProgramLines();
+ var start = id - 3;
+
+ if (start < 0) { start = 0; }
+
+ var col1 = this.console.getColor();
+ var col2 = 1;
+ if (col1 == 1) { col2 = 7; }
+ var max = 20;
+ for (var i = start; max > 0 && i < pgm.length; i++) {
+ var l = pgm[i];
+ if (id == i) {
+ this.console.setColor(col2);
+ this.context.listCodeLine(l[2]);
+ this.console.setColor(col1);
+ }
+ else {
+ this.context.listCodeLine(l[2]);
+ }
+
+ if (l[2].length > 38) {
+ max -= 2;
+ }
+ else {
+ max -= 1;
+ }
+ }
+
+ }
+
+
+ do_list() {
+
+ var list = {
+ title: "Basic Listing", showNum: false, offset: 0, items: []
+ // { name: "compatible", id: "compat"},
+ // { name: "synchronized with host", id: "clocksync"}
+ };
+
+ list.callback = "select_List";
+
+ var pgm = this.context.getProgramLines();
+
+ //var basicList = [];
+
+ for (var i = 0; i < pgm.length; i++) {
+ var l = pgm[i];
+ var display = l[2].trim();
+ if (display.length > 35) {
+ display = l[2].substr(0, 34) + "..";
+ }
+ list.items.push({ name: display, id: i });
+ // basicList.push({name: display, id: i});
+
+ if (this.debugFlag) {
+ console.log(l[2]);
+ }
+ }
+
+ list.hideLogo = true;
+ this.startList(list);
+
+ }
+
+
+ do_changeExitMode() {
+
+ if (!this.context.confirmCookies()) {
+ return;
+ }
+
+ var list = {
+ title: "when program exists:", items: [
+ { name: "stay in current graphics mode", id: "stay" },
+ { name: "return to text mode", id: "panic" }
+ ]
+ };
+
+ list.callback = "select_ExitMode";
+
+ this.startList(list);
+
+ }
+
+ do_changeImmersiveMode() {
+
+ if (!this.context.confirmCookies()) {
+ return;
+ }
+
+ var list = {
+ title: "immersive mode:", items: [
+ { name: "on", id: "immersive" },
+ { name: "off", id: "off" }
+ ]
+ };
+
+ list.callback = "select_ImmersiveMode";
+
+ this.startList(list);
+
+ }
+
+ do_changeClock() {
+
+ if (!this.context.confirmCookies()) {
+ return;
+ }
+
+ var list = {
+ title: "Clock Mode", items: [
+ { name: "compatible", id: "compat" },
+ { name: "synchronized with host", id: "clocksync" }
+ ]
+ };
+
+ list.callback = "select_Clock";
+
+ this.startList(list);
+
+ }
+
+ do_changeRenum() {
+
+ if (!this.context.confirmCookies()) {
+ return;
+ }
+
+ var list = {
+ title: "Renumber Mode", items: [
+ { name: "plain", id: "plain" },
+ { name: "data", id: "data" },
+ { name: "rem", id: "rem" }
+ ]
+ };
+
+ list.callback = "select_RenumberMode";
+
+ if (this.debugFlag) {
+ console.log("list options");
+ }
+
+ this.startList(list);
+
+ }
+
+
+ do_changeTurbo() {
+
+ if (!this.context.confirmCookies()) {
+ return;
+ }
+
+ var list = {
+ title: "Turbo Mode", items: [
+ { name: "on at startup", id: "on" },
+ { name: "'turbo' command to enable", id: "manual" }
+ ]
+ };
+
+ list.callback = "select_Extended";
+
+ if (this.debugFlag) {
+ console.log("list options");
+ }
+
+ this.startList(list);
+
+ }
+
+ select_File(id) {
+
+ this.endMenu();
+
+ if (this.debugFlag) {
+ console.log(id);
+ }
+
+ this.context.load(id);
+
+ this.context.printLine("list");
+
+ var pgm = this.context.getProgramLines();
+ for (const l of pgm) {
+ this.context.listCodeLine(l[2]);
+ if (this.debugFlag) {
+ console.log(l[2]);
+ }
+ }
+ }
+
+
+ do_listDirectory() {
+
+ if (!this.context.confirmCookies()) {
+ return;
+ }
+
+ var list = { title: "Directory", showNum: true, items: [], offset: 0 };
+ var dir = this.context.getDir();
+ var row;
+
+ for (var i = 0; i < dir.files.length; i++) {
+ list.items.push({ name: dir.files[i].fname.trim(), id: dir.files[i].fname });
+
+ }
+
+ list.callback = "select_File";
+
+ if (this.debugFlag) {
+ console.log("list dir");
+ }
+
+ list.hideLogo = true;
+ this.startList(list);
+ }
+
+ do_renumber() {
+ this.renumber(100, 10);
+ }
+
+ do_normalize() {
+ this.context.normalizeProgram();
+
+ this.endMenuWithMessage("normalize ok");
+ this.context.printLine("list");
+
+ var pgm = this.context.getProgramLines();
+ for (const l of pgm) {
+ this.context.listCodeLine(l[2]);
+ if (this.debugFlag) {
+ console.log(l[2]);
+ }
+ }
+ }
+
+ do_compress() {
+ this.context.compressProgram(false);
+
+ this.endMenuWithMessage("compress ok");
+ this.context.printLine("list");
+
+ var pgm = this.context.getProgramLines();
+ for (const l of pgm) {
+ this.context.listCodeLine(l[2]);
+ if (this.debugFlag) {
+ console.log(l[2]);
+ }
+ }
+ }
+
+ do_compress2() {
+ this.context.compressProgram(true);
+
+ this.endMenuWithMessage("compress ok");
+ this.context.printLine("list");
+
+ var pgm = this.context.getProgramLines();
+ for (const l of pgm) {
+ this.context.listCodeLine(l[2]);
+ if (this.debugFlag) {
+ console.log(l[2]);
+ }
+ }
+ }
+
+ do_PETSCIIreplace() {
+
+ this.context.PETSCIIreplace(true);
+
+ this.endMenuWithMessage("PETSCIIreplace");
+ this.context.printLine("list");
+
+ var pgm = this.context.getProgramLines();
+ for (const l of pgm) {
+ this.context.listCodeLine(l[2]);
+ if (this.debugFlag) {
+ console.log(l[2]);
+ }
+ }
+ }
+
+ renumber(x, y) {
+ this.context.renumberProgram(x, y);
+
+ this.endMenuWithMessage("renumber ok");
+ this.context.printLine("list");
+
+ var pgm = this.context.getProgramLines();
+ for (const l of pgm) {
+ this.context.listCodeLine(l[2]);
+ if (this.debugFlag) {
+ console.log(l[2]);
+ }
+ }
+ }
+
+ do_exportVDisk() {
+ var data = this.context.getVirtualDisk();
+
+ var blob = new Blob([data], {
+ type: 'text/plain'
+ });
+
+ var objectUrl = URL.createObjectURL(blob);
+
+ var link = document.getElementById("imageSaver");
+ link.download = "basic64js.vd64";
+ link.href = objectUrl;
+ link.click();
+
+ this.endMenuWithMessage("downloading vdisk");
+
+ }
+
+ do_importVDisk() {
+ var uploadElement = document.getElementById("imageLoader");
+
+ this.runImportedPGMFlag = true;
+ this.uploader.setCallback(this, "do_importVDiskCallBack");
+ this.uploader.start(".vd64");
+
+ if (this.debugFlag) {
+ console.log("clicked");
+ }
+
+ }
+
+ do_importVDiskCallBack(text, fName) {
+ if (this.debugFlag) {
+ console.log("import vdisk " + text);
+ console.log("import vdisk " + fName);
+ }
+
+ var diskName = fName;
+
+ if (diskName == null || diskName == "") {
+ diskName = "noname";
+ }
+
+ if (diskName.endsWith(".vd64")) {
+ diskName = diskName.substring(0, diskName.length - 5);
+ }
+ this.context.createDiskFromImage(diskName, JSON.parse(text));
+ }
+
+ do_exportBasNoPETSCII() {
+ var data = this.context.getProgramAsTextNoPETSCII();
+
+ var blob = new Blob([data], {
+ type: 'text/plain'
+ });
+
+ //console.log(data);
+
+ var objectUrl = URL.createObjectURL(blob);
+
+ var link = document.getElementById("imageSaver");
+ link.download = "myprogram.bas";
+ link.href = objectUrl;
+ link.click();
+
+ this.endMenuWithMessage("downloading bas");
+
+ }
+
+ do_exportBas() {
+ var data = this.context.getProgramAsText();
+
+ var blob = new Blob([data], {
+ type: 'text/plain'
+ });
+
+ var objectUrl = URL.createObjectURL(blob);
+
+ var link = document.getElementById("imageSaver");
+ link.download = "myprogram.bas";
+ link.href = objectUrl;
+ link.click();
+
+ this.endMenuWithMessage("downloading bas");
+
+ }
+
+ do_importBasRun() {
+
+ var uploadElement = document.getElementById("imageLoader");
+
+ this.runImportedPGMFlag = true;
+ this.uploader.setCallback(this, "do_importBasCallBack");
+ this.uploader.start(".bas");
+
+
+ if (this.debugFlag) {
+ console.log("clicked");
+ }
+
+ }
+
+ do_importBas() {
+
+ var uploadElement = document.getElementById("imageLoader");
+ this.runImportedPGMFlag = false;
+
+ this.uploader.setCallback(this, "do_importBasCallBack");
+ this.uploader.start(".bas");
+
+ if (this.debugFlag) {
+ console.log("clicked");
+ }
+
+ }
+
+ do_importPRGBas() {
+
+ var uploadElement = document.getElementById("imageLoader");
+ this.runImportedPGMFlag = false;
+
+ this.uploader.setCallback(this, "do_importPRGBasCallBack");
+ this.uploader.start(".prg", true );
+
+ if (this.debugFlag) {
+ console.log("clicked");
+ }
+
+ }
+
+ patchLine(line) {
+ var patchedLine = "";
+ //produce code here, that parses the line
+ //it is important to identify areas inside and outside of strings
+ //strings start and end with " and are not allowed to contain a "
+ //at the end of a string, either, nother, a colon, a commor or a semi colon is expected
+ //if there is something else, insert a semicolon
+
+ var inString = false;
+ for( var i=0; i 0) {
+ pgmText += "\n";
+ }
+ var patchedLine = this.patchLine( lines[i] );
+ pgmText += patchedLine;
+
+ }
+
+ var lines2 = pgmText.split(/\r?\n/);
+ try {
+ var bas = this.context.textLinesToBas(lines2);
+ }
+ catch (e) {
+
+
+ this.endMenuWithMessage("parse error on import" );
+ this.handleImportError(e);
+
+ console.log(e);
+ return;
+ }
+
+ try {
+ this.context.setProgram(bas);
+ if( this.context.errorsInParsing ) {
+ this.endMenuWithError("import", this.context.errorsInParsing );
+ return;
+ }
+ }
+ catch (e) {
+ this.endMenuWithMessage("setpgm error on import");
+ console.log(e);
+ console.log(text);
+ return;
+ }
+
+ if (this.runImportedPGMFlag) {
+ this.runImportedPGMFlag = false;
+ this.endMenu();
+ this.context.printLine("run");
+ this.context.runPGM();
+
+ }
+ else {
+ this.endMenuWithMessage("import ok");
+ this.context.printLine("list");
+
+ var pgm = this.context.getProgramLines();
+ for (const l of pgm) {
+ this.context.listCodeLine(l[2]);
+ if (this.debugFlag) {
+ console.log(l[2]);
+ }
+ }
+ }
+
+ }
+
+
+ do_importBasCallBack(text, fName) {
+
+ var lines = text.split(/\r?\n/);
+ try {
+ var bas = this.context.textLinesToBas(lines);
+ }
+ catch (e) {
+
+ this.endMenuWithMessage("parse error on import", detailError);
+ var detailError = this.handleImportError(e);
+ console.log(e);
+ return;
+ }
+
+ try {
+ this.context.setProgram(bas);
+ }
+ catch (e) {
+ this.endMenuWithMessage("setpgm error on import");
+ console.log(e);
+ console.log(text);
+ return;
+ }
+
+ if (this.runImportedPGMFlag) {
+ this.runImportedPGMFlag = false;
+ this.endMenu();
+ this.context.printLine("run");
+ this.context.runPGM();
+
+ }
+ else {
+ this.endMenuWithMessage("import ok");
+ this.context.printLine("list");
+
+ var pgm = this.context.getProgramLines();
+ for (const l of pgm) {
+ this.context.listCodeLine(l[2]);
+ if (this.debugFlag) {
+ console.log(l[2]);
+ }
+ }
+ }
+
+ }
+
+ do_exportSnapshot() {
+ var data = JSON.stringify(this.vmState);
+
+ var blob = new Blob([data], {
+ type: 'text/plain'
+ });
+
+ var objectUrl = URL.createObjectURL(blob);
+
+ var link = document.getElementById("imageSaver");
+ link.download = "basic64js.snap64";
+ link.href = objectUrl;
+ link.click();
+
+ }
+
+ do_importSnapshot() {
+
+ var uploadElement = document.getElementById("imageLoader");
+ this.runImportedPGMFlag = false;
+
+ this.uploader.setCallback(this, "do_importSnapshotCallBack");
+ this.uploader.start(".snap64");
+
+ if (this.debugFlag) {
+ console.log("clicked");
+ }
+
+ }
+
+ do_importSnapshotCallBack(text, fName) {
+
+ if (this.debugFlag) {
+ console.log("Import Snapshot");
+ }
+
+ this.endMenuWithMessage("snapshot restore");
+
+ this.context.loadContainer(
+ {
+ type: "snp",
+ data: text
+ });
+ }
+
+ do_saveSnapshot() {
+
+ var data = JSON.stringify(this.vmState);
+
+ this.context.saveSerializedData("SNAPSHOT", data, "snp", 65536);
+
+ this.endMenuWithMessage("snapshot saved");
+ }
+
+ do_reset() {
+ this.endMenu();
+ this.context.reset(true);
+ }
+
+ do_changeTheme() {
+ this.theme++;
+ if (this.theme > (this.themes.length - 1)) {
+ this.theme = 0;
+ }
+
+ if (this.context.confirmCookies()) {
+ localStorage.setItem("BJ64_Menu", JSON.stringify({ theme: this.theme }));
+ }
+
+ this.rendervmState();
+ }
+
+
+ do_documentation() {
+ window.open("https://github.com/JoystickAndCursorKeys/basic64-js/wiki", '_blank');
+
+ this.endMenuWithMessage("opened docs");
+ }
+
+ /*
+
+ Keyboard
+
+ Special Chars
+
+ PC - Commodore
+ ----------------
+ F9 - Power Menu Toggle
+ F1 - F1
+ F2 - F2
+ F3 - F3
+ F4 - F4
+ F5 - Shift F1
+ F6 - Shift F2
+ F7 - Shift F3
+ F8 - Shift F4
+ CTRL/PAUSE - Run/Stop + Restore
+ ESCAPE - Stop (RUN/STOP)
+ ALT 1-8 - Colors
+ ALT 9 - Reverse on
+ ALT 0 - Reverse off
+
+
+
+
+
+
+
+
+
+ */
+
+}
diff --git a/versions/0.8p5/res/script/menu_images.js b/versions/0.8p5/res/script/menu_images.js
new file mode 100644
index 0000000..0775db8
--- /dev/null
+++ b/versions/0.8p5/res/script/menu_images.js
@@ -0,0 +1,146 @@
+
+ function getMenuLogo( ) {
+
+ /* 34x4 */
+ var logo =
+ [
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+ 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0x75, 0x35,
+ 0x00, 0xe0, 0xf8, 0xfc, 0xfc, 0xfe, 0xfe, 0xff,
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x03,
+ 0x0f, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xfe, 0xf8, 0xf8, 0xf8,
+ 0xff, 0xff, 0xff, 0xff, 0x1f, 0x07, 0x03, 0x03,
+ 0xac, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
+ 0x00, 0x00, 0xc0, 0xe0, 0xf0, 0xf0, 0xf8, 0xf8,
+ 0x1f, 0x1f, 0x1f, 0x0f, 0x0f, 0x0f, 0x0f, 0x07,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x83, 0x83, 0x83,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xc0, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0,
+ 0x2b, 0x2b, 0x2b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b,
+ 0xfe, 0xfe, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xf8,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xf0, 0xf0, 0xf0,
+ 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0x00, 0x00, 0x00,
+ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x00, 0x00, 0x00,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0x3a, 0x1a, 0x1a,
+ 0x80, 0xf0, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+ 0xc3, 0xe7, 0xff, 0xdb, 0xdb, 0xdb, 0xc3, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0x35, 0x35, 0x35, 0x75, 0xf5, 0xf5, 0xf5, 0xf5,
+ 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfc, 0xf8,
+ 0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
+ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+ 0x07, 0x07, 0x07, 0x03, 0x03, 0x03, 0x03, 0x01,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x87, 0xc7, 0xc7, 0xc7, 0xcf, 0xcf, 0xcf, 0xdf,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7,
+ 0xf0, 0xf0, 0xf8, 0xf8, 0xf9, 0xfd, 0xfd, 0xfd,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xf8, 0xf8, 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, 0xe0,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xfe, 0xfe, 0xfe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0xbe, 0xbe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0x1a, 0x1a, 0x1a, 0x3a, 0x7a, 0xfa, 0xfa, 0xfa,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfc, 0xf8,
+ 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xe0, 0xe0, 0xfc, 0xe0, 0xe0, 0xff, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00,
+ 0x00, 0x08, 0x00, 0x49, 0x22, 0x1c, 0x5d, 0x1c,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+ 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf5, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
+ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf7, 0xf3, 0xf3, 0xe3, 0xe1, 0xe1, 0xc1, 0xc0,
+ 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+ 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80,
+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xfe, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x0f, 0x0f, 0x07, 0x07, 0x03, 0x01,
+ 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+ 0xc0, 0xc0, 0xc0, 0xe0, 0xe0, 0xf0, 0xf8, 0xf8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe3, 0xf3, 0xfb, 0xff, 0xef, 0xe7, 0xe3, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+ 0x22, 0x49, 0x00, 0x08, 0x20, 0x60, 0x88, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
+ 0xfe, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0xff, 0x00, 0x7f, 0x00, 0x07,
+ 0xf8, 0xf8, 0x00, 0xfe, 0x00, 0xff, 0x00, 0xff,
+ 0x03, 0x07, 0x00, 0x1f, 0x00, 0xff, 0x00, 0xff,
+ 0xaf, 0xaf, 0x00, 0xaf, 0x00, 0xaf, 0x00, 0xa8,
+ 0xf8, 0xf8, 0x00, 0xf0, 0x00, 0xc0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7f, 0x7f, 0x00, 0x7f, 0x00, 0x3f, 0x00, 0x3f,
+ 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
+ 0xc0, 0xc0, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0x7f, 0x00, 0x7f, 0x00, 0x3f,
+ 0xeb, 0xeb, 0x00, 0xeb, 0x00, 0xeb, 0x00, 0xea,
+ 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x07, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07,
+ 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
+ 0xf0, 0xf0, 0x00, 0xf0, 0x00, 0xfe, 0x00, 0xfe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0xbf,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xe0,
+ 0x7f, 0x7f, 0x00, 0x7f, 0x00, 0x7f, 0x00, 0x7f,
+ 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfa, 0xfa, 0x00, 0xfa, 0x00, 0x7a, 0x00, 0x3a,
+ 0xfc, 0xfc, 0x00, 0xfe, 0x00, 0xff, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+ 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0xc0, 0x30, 0x08, 0x07, 0x00,
+ 0x02, 0x02, 0x04, 0x04, 0x08, 0x70, 0x80, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ ];
+
+ return logo;
+ }
diff --git a/versions/0.8p5/res/script/polyfix.js b/versions/0.8p5/res/script/polyfix.js
new file mode 100644
index 0000000..908a9c8
--- /dev/null
+++ b/versions/0.8p5/res/script/polyfix.js
@@ -0,0 +1,3 @@
+function polyfix() {
+
+}
diff --git a/versions/0.8p5/res/script/statedefinitions.js b/versions/0.8p5/res/script/statedefinitions.js
new file mode 100644
index 0000000..03ed82d
--- /dev/null
+++ b/versions/0.8p5/res/script/statedefinitions.js
@@ -0,0 +1,54 @@
+class StateDefinitions {
+
+ constructor ( pgm ) {
+
+ this.startPlaybook = "pgm";
+
+ /* -----------------------------------------------------
+ Playbooks
+ ----------------------------------------------------- */
+
+ this.playbooks = {
+ pgm: { object: pgm, enter: 'load', definition: this },
+ };
+
+ /* -----------------------------------------------------
+ Global state setup
+ ----------------------------------------------------- */
+
+ this.stateTypes = {
+ LOAD: ['LOAD', 'RENDER' ],
+ PLAY: ['INIT','CLEANUP','RENDER','PROCESS','HANDLEINPUT'],
+ WATCH: ['INIT','CLEANUP','RENDER','PROCESS'],
+ INIT: ['INIT'],
+ BRANCH: ['BRANCH']
+ };
+
+ this.stateMethodSuffix = {
+ LSRENDER: 'LSRender',
+ LSPROCESS: undefined,
+ RENDER: 'Render',
+ PROCESS: 'Run',
+ HANDLEINPUT: 'Handle'
+ };
+
+ /* -----------------------------------------------------
+ Demo playbook
+ ----------------------------------------------------- */
+
+ /* no branch functions */
+
+ /* demo playbook */
+ var demoPlaybook = this.playbooks.pgm;
+ demoPlaybook.states = {
+
+ /* Only load, play and repeat since this is a demo, not a game */
+
+ 'loadexample': { _type: "LOAD", next: 'load'},
+ 'load': { _type: "LOAD", next: 'play'},
+ 'play': { _type: "PLAY", loadExample: 'loadexample' },
+
+
+ } ;
+ }
+}
diff --git a/versions/0.8p5/res/script/vdisk.js b/versions/0.8p5/res/script/vdisk.js
new file mode 100644
index 0000000..c7d1b29
--- /dev/null
+++ b/versions/0.8p5/res/script/vdisk.js
@@ -0,0 +1,367 @@
+class VDisk {
+
+ constructor() {
+ this.initialized = false;
+ }
+
+ initialize() {
+ this.disks = [];
+ this.currentDisk = null;
+ var defaultDisk = "0001"
+
+ var json = localStorage.getItem( "BJ64_disks_list" );
+ if( json == null ) {
+
+ var diskId = "0001";
+ var diskName = "Default";
+ this.disks = [ diskId ];
+ this.currentDisk = diskId;
+ this.lastDisk = 1;
+
+ localStorage.setItem( "BJ64_disks_list", JSON.stringify( this.disks ) );
+ localStorage.setItem( "BJ64_0001_dir", JSON.stringify( {files:[], title: diskName, readOnly: false } ) );
+ localStorage.setItem( "BJ64_disk_current", diskId );
+ }
+ else {
+ this.disks = JSON.parse( json );
+ this.currentDisk = localStorage.getItem( "BJ64_disk_current" );
+
+ var last = -1;
+ for( var i=0; i last ) {
+ last = parseInt( this.disks[ i ] );
+ }
+ }
+ this.lastDisk = last;
+ }
+
+
+ this.initialized=true;
+
+ }
+
+ selectDisk( diskId ) {
+ this.currentDisk = diskId;
+ localStorage.setItem( "BJ64_disk_current", diskId );
+ }
+
+ ready() {
+ return this.initialized;
+ }
+
+
+ getDisks() {
+
+ if( !this.initialized ) {
+ return [];
+ }
+
+ var storageName = "BJ64_disks_list";
+ var json = localStorage.getItem( storageName );
+ var disks = JSON.parse( json );
+
+ return disks;
+
+ }
+
+ getEmptyDirStructure(name) {
+ return {files:[], title: "null" };
+ }
+
+ getDir() {
+
+ if( !this.initialized ) {
+ return getEmptyDirStructure(null);
+ }
+
+ var storageName = "BJ64_" + this.currentDisk + "_dir";
+ var json = localStorage.getItem( storageName );
+ var dir = JSON.parse( json );
+
+ //var title = "0 \u0012\""+dir.title+" \"\u0092 00 2A";
+ var title = dir.title;
+
+ if(!json) {
+ return {files:[], title: title };
+ }
+ dir.title = title;
+ dir.free = 32-dir.files.length;
+
+ var foundNullIx = -1;
+
+ while( true ) {
+ for( var i=0; i -1) {
+ dir.files.splice( foundNullIx, 1 );
+ foundNullIx = -1;
+ }
+ else {
+ break;
+ }
+ }
+ return dir;
+
+ }
+
+ getSelectedDir( x ) {
+
+ if( !this.initialized ) {
+ return {files:[], title: "null" };
+ }
+
+ var storageName = "BJ64_" + x + "_dir";
+ var json = localStorage.getItem( storageName );
+ var dir = JSON.parse( json );
+
+ //var title = "0 \u0012\""+dir.title+" \"\u0092 00 2A";
+ var title = dir.title;
+
+ if(!json) {
+ return {files:[], title: title };
+ }
+ dir.title = title;
+ dir.free = 32-dir.files.length;
+ return dir;
+
+ }
+
+ setDir( dir ) {
+
+ if( !this.initialized ) {
+ return;
+ }
+
+ var storageName = "BJ64_" + this.currentDisk + "_dir";
+
+ localStorage.setItem(storageName, JSON.stringify( dir ) );
+
+ }
+
+ existsFile( fileName ) {
+
+ if( !this.initialized ) {
+ return false;
+ }
+
+ var dir = this.getDir();
+
+ var found = -1;
+ for( var i=0; i -1 ) {
+ return true;
+ }
+ return false;
+ }
+
+
+ removeFromDir( fileName ) {
+
+ if( !this.initialized ) {
+ return;
+ }
+
+ var dir = this.getDir();
+
+ var found = -1;
+ for( var i=0; i -1 ) {
+ dir.files.splice( i, 1 );
+ }
+ this.setDir(dir);
+ }
+
+ updateDir( fileName, programLen ) {
+
+ if( !this.initialized ) {
+ return;
+ }
+
+ var dir = this.getDir();
+
+ var found = -1;
+ for( var i=0; i -1 ) {
+ dir.files[i].size = programLen;
+ }
+ else {
+ dir.files.push( {fname: fileName, size: programLen } );
+ }
+ this.setDir(dir);
+ }
+
+ saveFile( fileName0, data, type, length ) {
+
+ if( !this.initialized ) {
+ return;
+ }
+
+ var fileName = fileName0;
+ if( fileName0.length > 32) {
+ fileName = fileName0.substr(0,32);
+ }
+
+ var storageName = "BJ64_" + this.currentDisk + "_" + fileName;
+
+ //save pgm
+ var container = JSON.stringify( { type: type, data: data} );
+ localStorage.setItem(storageName, container );
+
+ this.updateDir( fileName, length );
+ }
+
+ loadFile( fileName ) {
+
+ if( !this.initialized ) {
+ return null;
+ }
+
+ var storageName = "BJ64_" + this.currentDisk + "_" + fileName;
+
+ var json = localStorage.getItem( storageName );
+
+ return JSON.parse( json );
+ }
+
+ deleteFile( fileName ) {
+ if( ! this.existsFile( fileName ) ) {
+ return "no such file";
+ }
+
+ try {
+ this.removeFromDir( fileName );
+ this._removeFile( fileName );
+ }
+ catch ( e ) {
+ return "unexpected";
+ }
+ return "ok";
+ }
+
+ _removeFile( fileName ) {
+
+ var storageName = "BJ64_" +
+ this.currentDisk + "_" +
+ fileName;
+
+ localStorage.removeItem( storageName );
+
+ }
+
+ formatDisk() {
+
+ var dir = this.getDir();
+
+ for( var i=0; i96 && code <123)) {
+ code -=32;
+ }
+ bcontext.pushKeyBuffer( code );
+ }
+ else if( evt.key == "Home") {
+ if( evt.k_shift ) {
+ bcontext.pushKeyBuffer( String.fromCharCode(147) );
+ }
+ else {
+ bcontext.pushKeyBuffer( String.fromCharCode(19) );
+ }
+ }
+ else if( evt.key == "Pause" && evt.ctrlKey) {
+ this.reset();
+ }
+ else if( evt.key == "Escape") {
+ this.basiccontext.runStop();
+ }
+
+
+ //this.resetKeyModifiers();
+ return;
+ }
+
+
+ handleScrListKeys( evt, bcontext, isInputCommand ) {
+
+ if( evt.type == 'keydown' ) {
+
+ if( evt.key == "Escape") {
+ this.basiccontext.listStop();
+ }
+ }
+
+ }
+
+
+ handleScrEditKeys( evt, bcontext, isInputCommand ) {
+
+ if( evt.type == 'keydown' ) {
+
+ var c = this.console;
+ var ctx = bcontext;
+ var stringMode;
+ stringMode = this.stringMode;
+
+ if( evt.key == "Enter") {
+
+ c.clearCursor();
+ var line=ctx.getCurrentLine();
+
+ this.stringMode = false;
+ stringMode = false;
+
+ ctx.passEnter();
+
+ bcontext.handleLineInput( line, isInputCommand );
+
+ }
+ else if( evt.key == "Pause" && evt.ctrlKey) {
+ this.basiccontext.reset( false );
+ }
+ else if( evt.key == "Backspace" && !evt.ctrlKey) {
+ c.clearCursor();
+ ctx.passDeleteChar();
+ }
+ else if( evt.key == "Backspace" && evt.ctrlKey) {
+ ctx.reset( false );
+ }
+ else if( evt.key == "p" && evt.ctrlKey ) {
+
+ ctx.passChars( '\x7e', false ); //https://sta.c64.org/cbm64pet.html
+
+ evt.preventDefault();
+ }
+ else if( evt.key == "d" && evt.ctrlKey ) {
+
+ ctx.showDebug(); //https://sta.c64.org/cbm64pet.html
+
+ evt.preventDefault();
+ }
+ else if( evt.key == "x" && evt.ctrlKey ) {
+
+ ctx.passChars( '\x5e', false ); //https://sta.c64.org/cbm64pet.html
+
+ evt.preventDefault();
+ }
+ else if( evt.key == "^" ) {
+ ctx.passChars( '\x5e', false ); //https://sta.c64.org/cbm64pet.html
+
+ evt.preventDefault();
+ }
+ else if( evt.key == "ArrowLeft") {
+
+ c.clearCursor();
+ c.cursorLeft();
+ ctx.updateYPos();
+ evt.preventDefault();
+ }
+ else if( evt.key == "ArrowRight") {
+ c.clearCursor();
+ c.cursorRight();
+ ctx.updateYPos();
+ evt.preventDefault();
+ }
+ else if( evt.key == "ArrowUp" && !evt.ctrlKey) {
+ c.clearCursor();
+ c.cursorUp();
+ ctx.updateYPos();
+ evt.preventDefault();
+ }
+ else if( evt.key == "ArrowDown") {
+ var pos = c.getCursorPos();
+
+ if( pos[ 1 ] < 24 ) {
+ c.clearCursor();
+ c.cursorDown();
+ ctx.updateYPos();
+ }
+ else {
+ c.clearCursor();
+ ctx.passEnter();
+ c.cursorDown();
+ ctx.updateYPos();
+ }
+
+ evt.preventDefault();
+ }
+ else if( evt.key == "ArrowUp" && evt.ctrlKey) {
+ ctx.passChars( '\x5e', false ); //https://sta.c64.org/cbm64pet.html
+ evt.preventDefault();
+ }
+ else if( evt.key == "F1") {
+ ctx.passString('LIST');
+ }
+ else if( evt.key == "F2") {
+ ctx.passString('RUN');
+ }
+ else if( evt.key == "F5") {
+ ctx.passString('LOAD "$":LIST');
+ evt.preventDefault();
+ }
+ else if( evt.key == "F6") {
+ ctx.passString('LOAD "*"');
+ evt.preventDefault();
+ }
+ else if( evt.key == "I" ) { //why do we need this?
+ c.clearCursor();
+ ctx.passChars( evt.key, false );
+ }
+ else if( evt.key == "\"") {
+ c.clearCursor();
+ ctx.passChars( evt.key, false );
+ evt.preventDefault();
+ this.stringMode = !this.stringMode;
+ }
+ else {
+
+ /*
+ var k2c = this.keyToCode;
+ k2c["ALT_CODE49"] = '\xd0'; //1
+ */
+
+ var checkKey = "";
+ if( evt.k_shift ) {
+ checkKey += "SHFT_";
+ }
+ if( evt.k_control ) {
+ checkKey += "CTRL_";
+ }
+ if( evt.k_alt ) {
+ checkKey += "ALT_";
+ }
+ if( evt.k_altGraph ) {
+ checkKey += "ALTGR_";
+ }
+
+ checkKey += ":" + evt.key;
+ //console.log("check_key: " + checkKey );
+
+ if( this.stringMode ) {
+ var mapEntry = this.keyToCode[checkKey];
+ if( ! (mapEntry===undefined)) {
+ console.log("check_key: " + checkKey + "\/" );
+
+ ctx.passPetsciiChar( mapEntry );
+ evt.preventDefault();
+ return;
+ }
+ }
+ else {
+ var mapEntry = this.keyToCTRLCode[checkKey];
+ if( ! (mapEntry===undefined)) {
+
+ console.log("check_key: " + checkKey + " - out string " + mapEntry.charCodeAt(0));
+ c.clearCursor();
+ ctx.passChars( mapEntry, false );
+ evt.preventDefault();
+ return;
+ }
+ }
+
+ if( evt.key.length == 1) {
+ c.clearCursor();
+ ctx.passChars( evt.key.toUpperCase(), false );
+ evt.preventDefault();
+ }
+
+ }
+ }
+ }
+
+ playRun() {
+
+ var basiccontext = this.basiccontext;
+
+ basiccontext.cycle();
+
+ if( this.basiccontext.getPlayExampleFlag() ) {
+ return "loadExample";
+ }
+ return false;
+ }
+
+
+ playRender(context) {
+
+ if( this.renderError ) { return; }
+ var c = this.console;
+ var cx = this.basiccontext;
+ try {
+
+ if( ( c.getBorderChangedState() || cx.getBorderChangedFlag() ) &&
+ cx.getImmersiveFlag()) {
+ var col = c.getBorderColor();
+ col = c.getColorHTML( col );
+
+ var div0 = document.getElementById("outerdiv");
+ div0.style.backgroundColor = col;
+
+ console.log("Border update: " + col);
+ }
+ this.console.renderDisplay();
+ }
+ catch ( e ) {
+ this.renderError = true;
+ console.log( e );
+ throw e;
+ }
+ }
+
+
+}