Just a sidenote:
Here's what it takes to make a basic style interpreter:
Pre-Constants
Spoiler
; PROJECT : TinySBRunTime
; EDITED : 2016-05-20
; ---------------------------------------------------------------------
#Include "SaveBitmap"
//Define the constant colors oldschool style :)
Dim constant_colors$(18)
//Define the constant rgb values oldschool style :)
Dim rgb_colors(18)
constant_colors$(1)="#AQUA"
constant_colors$(2)="#BLACK"
constant_colors$(3)="#BLUE"
constant_colors$(4)="#CYAN"
constant_colors$(5)="#FUCHSIA"
constant_colors$(6)="#GRAY"
constant_colors$(7)="#GREEN"
constant_colors$(8)="#LIME"
constant_colors$(9)="#MAGENTA"
constant_colors$(10)="#MAROON"
constant_colors$(11)="#NAVY"
constant_colors$(12)="#OLIVE"
constant_colors$(13)="#PURPLE"
constant_colors$(14)="#RED"
constant_colors$(15)="#SILVER"
constant_colors$(16)="#TEAL"
constant_colors$(17)="#WHITE"
constant_colors$(18)="#YELLOW"
rgb_colors(1)=rgb(0, 248, 248)
rgb_colors(2)=rgb(0, 0, 0)
rgb_colors(3)=rgb(0, 0, 255)
rgb_colors(4)=rgb(0, 0, 248)
rgb_colors(5)=rgb(248, 0, 248)
rgb_colors(6)=rgb(128, 128, 128)
rgb_colors(7)=rgb(0, 128, 0)
rgb_colors(8)=rgb(0, 248, 0)
rgb_colors(9)=rgb(248, 0, 248)
rgb_colors(10)=rgb(128, 0, 0)
rgb_colors(11)=rgb(0, 0, 128)
rgb_colors(12)=rgb(128, 128, 0)
rgb_colors(13)=rgb(128, 0, 128)
rgb_colors(14)=rgb(248, 0, 0)
rgb_colors(15)=rgb(192, 192, 192)
rgb_colors(16)=rgb(0, 128, 128)
rgb_colors(17)=rgb(248, 248, 248)
rgb_colors(18)=rgb(248, 248, 0)
//Define the text color indexes as rgb values
dim constant_Tcolors$(15)
constant_Tcolors$(1) = "#TBLACK" //1
constant_Tcolors$(2) = "#TMAROON" //2
constant_Tcolors$(3) = "#TRED" //3
constant_Tcolors$(4) = "#TGREEN" //4
constant_Tcolors$(5) = "#TLIME" //5
constant_Tcolors$(6) = "#TOLIVE" //6
constant_Tcolors$(7) = "#TYELLOW" //7
constant_Tcolors$(8) = "#TNAVY" //8
constant_Tcolors$(9) = "#TBLUE" //9
constant_Tcolors$(10) = "#TPURPLE" //10
constant_Tcolors$(11) = "#TMAGENTA" //11
constant_Tcolors$(12) = "#TTEAL" //12
constant_Tcolors$(13) = "#TCYAN" //13
constant_Tcolors$(14) = "#TGRAY" //14
constant_Tcolors$(15) = "#TWHITE" //15
//Set the rgb values in the mirror rgb array
//We may as well just copy the values by their color names from the rgb_colors array
dim constant_Tcolors(15)
constant_Tcolors(1) = rgb_colors(2) //#BLACK
constant_Tcolors(2) = rgb_colors(10) //#MAROON
constant_Tcolors(3) = rgb_colors(14) //#RED
constant_Tcolors(4) = rgb_colors(7) //#GREEN
constant_Tcolors(5) = rgb_colors(8) //#LIME
constant_Tcolors(6) = rgb_colors(12) //#OLIVE
constant_Tcolors(7) = rgb_colors(18) //#YELLOW
constant_Tcolors(8) = rgb_colors(11) //#NAVY
constant_Tcolors(9) = rgb_colors(3) //#BLUE
constant_Tcolors(10) = rgb_colors(13) //#PURPLE
constant_Tcolors(11) = rgb_colors(9) //#MAGENTA
constant_Tcolors(12) = rgb_colors(16) //#TEAL
constant_Tcolors(13) = rgb_colors(4) //#CYAN
constant_Tcolors(14) = rgb_colors(6) //#GRAY
constant_Tcolors(15) = rgb_colors(17) //#WHITE
//Define tile_image constants make them all random color squares
Dim tiles(1024)
for t=0 to 1024
tiles(t)=newfximage(16, 16)
rendertoimage tiles(t)
cls rndrgb()
ink rgb(0,0,0)
circle 8, 8, 8, 1
next t
ink rgb(255, 255, 255)
global global_textbackground=5
global global_textforeground=6
global global_textcursorX=0 //These work I think on 8 by 8
global global_textcursorY=0
//Create the color tiles
dim TXTBG(15)
for t=1 to 15
TXTBG(t) = newimage(16, 16)
rendertoimage TXTBG(t)
cls constant_Tcolors(t)
next t
rendertoscreen
dim graphics_page(2)
for t=1 to 2
graphics_page(t)=newfximage(getscreenwidth(), getscreenheight() )
imagemaskcolour graphics_page(t),rgb(0,0,0) //Black
next t
//Just a BIG note when dealing with text.
//IF YOU EVER want to draw text to an image, for one reason or another using FX images is unreliable
//ORRRR Playbasic is just fucked in the head.
global text_page = newimage(getscreenwidth(), getscreenheight() )
imagemaskcolour text_page, rgb(0, 0, 0) ; black
rendertoimage text_page
Print "HELLO THERE" // This line breaks if the type of image text_page is an FXIMAGE
//Not only that..
rendertoscreen
drawimage text_page, 0, 0, 0
//drawimage text_page, 0, 0, 0
cls
//When using CLS or ACLS sometimes we want to only clear the txt not the graphics.
//To do this we need to draw the text onto our text_page damnit
//easy change the print command to draw on this page
//Integrate a framerender function
//draw everything in it
global currentGPAGEDSP=1 //Which Gpage to render
global currentGPAGEDRT=1 //Which Gpage to draw to
dim commands$(100); //probably more than this but this goes in pre constants
commands$(1)="BGPUT" //PUT tiles on a bg Layer
commands$(2)="BGOFS" //BGOFFSET
commands$(3)="BGSHOW" //Show a bg layer
commands$(4)="BGHIDE" //Hide a bg layer
commands$(5)="COLOR" //text colors
commands$(6)="GCOLOR" //drawing ink color
commands$(7)="LOCATE" //set the text cursor
commands$(8)="Print" //needs parsing sometimes can accept any $ parameter, may only need parsing if + str$() is present
commands$(9)="INC" //Increment
commands$(10)="DEC" //Decrement
commands$(11)="BGCLR" //accepts parameter or no parameters
commands$(12)="DIM " //requires a parameter with parameters
commands$(13)="CLS" //requires no parameters
commands$(14)="GCLS" // Clears the screen graphics only. may need a seperate graphics screen painted under everything.
//Am I really doing this? Ehhhhyeeeep I think so o.o
//a list of constant math operands we may need them in case we do math parsing down the road
//Just good to have.
dim operands$(7)
operands$(1)="+"
operands$(2)="-"
operands$(3)="/"
operands$(4)="*"
operands$(5)="="
operands$(6)=">"
operands$(7)="<"
//Program stack stuff
dim program_stack$(1)
dim return_stack(1)
global return_stack_size=1
global return_stack_index=0 //This is the current stack index
global last_call=0 //This is the last index in the stack that was called
global label_list_size=1
global pc = 0 //This is the program counter it'll be in charge of stepping our program
global program_stack_size=1 //the program stack size
dim labels$(1)
dim label_pointers(1)
//The PC pointer is the most important in program flow control
//Inside of TinySB as it takes care of running one command at a time smoothly.
//To see how it progresses see step.
//A function to read the program in should resize the Program_stack$() to the same amount
//as there are readable string line numbers.
System Types
Spoiler
; PROJECT : TinySBRunTime
; EDITED : 2016-05-20
; ---------------------------------------------------------------------
//====Guide
//===_STR means String
//===_INT means Integer
//===_REL means Real
//==Strings1D, 2D, 3D are arrays of arrays of the string arrays user creates
//==INTS1D, 2D, 3D are arrays of arrays of the integer arrays user creates
//String Array Types
type one_dimensionalSTR
entries$(8129); //Static size, about the same as SB
internal_name$ //a list of these in another array will be provided, along with their indexes in the main array
total_length //used to get the index
endtype
type two_dimensionalSTR
entries$(5000*5000);
internal_name$ //a list of these in another array will be provided, along with their indexes in the main array
X_width //used to get the index
Y_depth //used to check array boundaries
endtype
type three_dimensionalSTR
entries$(500*500*500);
internal_name$ //a list of these in another array will be provided, along with their indexes in the main array
X_width //used to get the index
Y_depth //used to check array boundaries
Z_depth
endtype
//Integer Array Types
type one_dimensional_INT
entries(8129) ; //Static size about the same as SB
internal_name$ //a list of these in another array will be provided, along with their indexes in the main array
total_length //used to get the index
endtype
type two_dimensional_INT
entries(5000*5000)
internal_name$ //a list of these in another array will be provided, along with their indexes in the main array
X_width //used to get the index
Y_depth //used to check array boundaries
endtype
type three_dimensional_INT
entries(500*500*500)
internal_name$ //a list of these in another array will be provided, along with their indexes in the main array
X_width //used to get the index
Y_depth //used to check array boundaries
Z_depth
endtype
//Addition of user declared single variables
//Addition of user decclared single strings
//Let's do this
type _variable
name$
value
value_$ //For temporary storage of last conversion to string Ie str$()
endtype
type _string
name$
value_$
value //for temporary storage of last conversion to value ie val(mystring$)
endtype
// ===End of declarations
//==End
global variable_str_size=1 //The size of the user string stack
global variable_int_size=1 //The size of the user variable stack
dim variable_strings(variable_str_size) as _string
dim variable_ints(variable_int_size) as _variable
//the type for a BGlayer.
type BGLAYER
BGImage
width
height
BGVARS(8)
BGROTANGLE
OFFSETX
OFFSETY
VISIBLE
endtype
dim Strings1D(1) as one_dimensionalSTR
dim Strings2D(1) as two_dimensionalSTR
dim Strings3D(1) as three_dimensionalSTR
Dim INTS1D(1) as one_dimensional_INT
dim INTS2D(1) as two_dimensional_INT
dim INTS3D(1) as three_dimensional_INT
dim BGLAYERS(4) as BGLAYER
for t=1 to 4
BGLAYERS(t).BGImage=newfximage(127*16, 127*16)
imagemaskcolour BGLAYERS(t).BGImage, rgb(0, 0,0 )
BGLAYERS(t).width = 127
BGLAYERS(t).height = 127
BGLAYERS(t).BGROTANGLE =0
BGLAYERS(t).OFFSETX = 0
BGLAYERS(t).OFFSETY = 0
//Used for BGSHOW and BGHIDE
BGLAYERS(t).VISIBLE = FALSE
next t
Support Functions (This will get even bigger !)
Spoiler
; PROJECT : TinySBRunTime
; EDITED : 2016-05-20
; ---------------------------------------------------------------------
//psub POW(num,power)
//n=1
//for i=1 to power
//n=n*num
//next i
//endpsub n
//This is called after whatever is meant to be parsed is parsed
//That is to say any math etc will be parsed before print is called not during
psub print_string(mystring$)
//parse(mystring$) I will comment this out for now so that print_string can be called directly
print_S(mystring$) //Ths calls print_S because it actually prints the colors properly
endpsub
//This should print the string after parsing
psub print_S(mystring$)
rendertoimage text_page//let's just make sure we're rendering to the screen ok?
//first we have to print the text background color
templength = len(mystring$)
//We're going to paint the tiles for the text background first
if len(mystring$) >0 //This patches the bug where random square is drawn when no text is present during blank print call.
for t=0 to templength
DrawTXTBG(global_textbackground, global_textcursorX+(t/2), global_textcursorY)
next t
endif
ink constant_Tcolors(global_textforeground) //Set the ink color to the right value
curs_x = (global_textcursorX-1)*16
curs_y = (global_textcursorY-1)*16
setcursor curs_x, curs_y
print mystring$ //Finally we print the string setting the color first
rendertoscreen
endpsub
//Color parsing. I'll seperate these and use a seperate function when parsing to figure out which case to use
//Then pass the correctly formatted data to whichever case matches.
psub gcolor_rgb(color)
#print "nothing"
endpsub
psub gcolor_#(color$)
for t=1 to 18
if color$=constant_colors$(t)
ink rgb_colors(t)
exitfor
endif
next t
endpsub
//this function deals with if both the parameters use #T
psub color_#(colorTXT$, colorBG$)
//we'll get both the colors at once , even if they're closer this is a faster search than trying to search twice
//in the case that one color may be found right away
//we're only losing 1/2 the processing time with this search than independently searching each one out
for t=1 to 15
if colorTXT$ = constant_Tcolors$(t)
color1= Constant_tcolors(t)
set_global_textforeground(t) //This is the global text foreground value we're sending this to to the main system
endif
if colorBG$ = constant_Tcolors$(t)
color2= Constant_tcolors(t)
colorindex=t //added this so that it can be used to quickly get the color tile the rgb value won't be needed
//Good to have it as a constant anyways for setting text colors
set_global_textbackground(t) //This is the global color value, we're sending this to the main system
endif
next t
endpsub color1, color2, colorindex
//this function deals with if just the first parameter is given using #T
psub color_1#(colorTXT$)
for t=1 to 15
if colorTXT$ = constant_Tcolors$(t)
color1= Constant_tcolors(t)
set_global_textforeground(t) //this is the global foreground text color. We're sending this to the system!
endif
next t
endpsub color1
//This function deals with if just the second parameter was given using #T
psub color_2#(ColorBG$)
for t=1 to 15
if ColorBG$ = constant_Tcolors$(t)
color2 = Constant_tcolors(t)
colorindex=t
set_global_textbackground(t) //This is the global background text color. SEND IT TO THE SYSTEM :D
endif
next t
endpsub color2, colorindex
psub gcolor_hex(color$)
endpsub
psub bgscreen(layer, width, height)
endpsub
//Case to clear just one BG layer
psub bgclr(layer)
select layer
case 0:
rendertoimage BGLAYERS(1).BGImage
case 1:
rendertoimage BGLAYERS(2).BGImage
case 2:
rendertoimage BGLAYERS(3).BGImage
case 3:
rendertoimage BGLAYERS(4).BGImage
default:
rendertoimage BGLAYERS(1).BGImage
endselect
cls
rendertoscreen
endpsub
//Case to clear all BG layers
psub bgclrall()
for t=1 to 4
rendertoimage BGLAYERS(t).BGImage
cls
next t
rendertoscreen
endpsub
psub locate(x, y)
setcursor (x-1)*16, (y-1)*16
//Since this modifies the text cursor the entire system should know about it
global_textcursorX=x
global_textcursorY=y
endpsub
psub BGOFS(layer, NewOFFSETX, NewOFFSETY)
select layer
case 0:
BGLAYERS(1).OFFSETX = NewOFFSETX
BGLAYERS(1).OFFSETY = NewOFFSETY
case 1:
BGLAYERS(2).OFFSETX = NewOFFSETX
BGLAYERS(2).OFFSETY = NewOFFSETY
case 2:
BGLAYERS(3).OFFSETX = NewOFFSETX
BGLAYERS(3).OFFSETY = NewOFFSETY
case 3:
BGLAYERS(4).OFFSETX = NewOFFSETX
BGLAYERS(4).OFFSETY = NewOFFSETY
default:
BGLAYERS(1).OFFSETX = NewOFFSETX
BGLAYERS(1).OFFSETY = NewOFFSETY
endselect
endpsub
psub BGPUT(Layer,X,Y,Screen_data)
select layer
case 0:
rendertoimage BGLAYERS(1).BGImage
case 1:
rendertoimage BGLAYERS(2).BGImage
case 2:
rendertoimage BGLAYERS(3).BGImage
case 3:
rendertoimage BGLAYERS(4).BGImage
default:
rendertoimage BGLAYERS(1).BGImage
endselect
drawimage tiles(Screen_data), (x-1)*16, (y-1)*16, 1
rendertoscreen
endpsub
psub DRAWBGS()
for t=1 to 4
X_OFFS = BGLAYERS(t).OFFSETX
Y_OFFS = BGLAYERS(t).OFFSETY
//Get the visible flag of the BG layer
VISIBLE = BGLAYERS(t).VISIBLE
//Only draw the bg layer if visible is true
if VISIBLE=true then Drawimage BGLAYERS(t).BGImage, X_OFFS, Y_OFFS, 1
next t
endpsub
psub BGhide(layer)
BGLAYERS(layer).Visible = false
endpsub
psub Bgshow(layer)
BGLAYERS(layer).Visible = true
endpsub
psub vsync(value)
sync
wait value
endpsub
psub vsync_novalue()
sync
endpsub
//These functions deal with arrays that are virtualized.
psub get_index1D(index)
index1D = index
endpsub index1D
psub get_index2D(x, y, X_width)
index2D = (y*X_width)+x
endpsub index2D
psub get_index3D(x, y, z, X_width, Y_depth)
index3D = (z * X_width * Y_depth) + (y * X_width) + x
endpsub index3D
//This resizes an array of string type in 3 dimensions.
psub resize_array3DSTR(array_index, X_width, Y_depth, Z_depth, old_X_width, old_Y_depth, old_Z_depth)
dim temparray$(old_X_width, old_Y_depth, old_Z_depth) //we're making a copy
dim temparray_$(old_x_width, old_Y_depth, old_Z_depth)
temparray$() = copyarray3DSTR(array_index, temparray_$(), old_X_width, old_Y_depth, old_Z_depth)
_type = 3 //type 3 is string
allocate_size3D(X_width, Y_depth, Z_depth, array_index, _type)
//Next we need to copy the old contents to the new 3D array.
copyOld3DNew3DSTR(array_index, temparray$(), X_width, Y_depth, Z_depth, old_X_width, old_Y_depth, old_Z_depth)
//and that should be it
endpsub
//This resizes an array of string type in 2 dimensions.
psub resize_array2DSTR(array_index, X_width, Y_depth, old_X_width, old_Y_depth)
dim temparray$(old_X_width, old_Y_depth) //we're making a copy
dim temparray_$(old_x_width, old_Y_depth)
temparray$() = copyarray2DSTR(array_index, temparray_$(), old_X_width, old_Y_depth)
_type = 3 //type 3 is string
allocate_size2D(X_width, Y_depth, array_index, _type)
//Next we need to copy the old contents to the new 3D array.
copyOld2DNew2DSTR(array_index, temparray$(), X_width, Y_depth, old_X_width, old_Y_depth)
//and that should be it
endpsub
psub resize_array1DSTR(array_index, new_length)
STRINGS1D(array_index).total_length = new_length
endpsub
//This resizes an array of int type in 3 dimensions.
psub resize_array3DINT(array_index, X_width, Y_depth, Z_depth, old_X_width, old_Y_depth, old_Z_depth)
dim temparray(old_X_width, old_Y_depth, old_Z_depth) //we're making a copy
dim temparray_(old_x_width, old_Y_depth, old_Z_depth)
temparray() = copyarray3DINT(array_index, temparray_(), old_X_width, old_Y_depth, old_Z_depth)
//Next the program needs to resize the array properties. I'll use a function for that too. it's easier.
_type = 1 //type 1 is int
allocate_size3D(X_width, Y_depth, Z_depth, array_index, _type)
//Next we need to copy the old contents to the new 3D array.
copyOld3DNew3DINT(array_index, temparray(), X_width, Y_depth, Z_depth, old_X_width, old_Y_depth, old_Z_depth)
//and that should be it
endpsub
//This resizes an array of int type in 2 dimensions.
psub resize_array2DINT(array_index, X_width, Y_depth, old_X_width, old_Y_depth)
dim temparray(old_X_width, old_Y_depth) //we're making a copy
dim temparray_(old_x_width, old_Y_depth)
temparray() = copyarray2DINT(array_index, temparray_(), old_X_width, old_Y_depth)
//Next the program needs to resize the array properties. I'll use a function for that too. it's easier.
_type = 1 //type 1 is int
allocate_size2D(X_width, Y_depth, array_index, _type)
//Next we need to copy the old contents to the new 3D array.
copyOld2DNew2DINT(array_index, temparray(), X_width, Y_depth, old_X_width, old_Y_depth)
//and that should be it
endpsub
psub resize_array1DINT(array_index, new_length)
INTS1D(array_index).total_length = new_length
endpsub
//The below function requires both arrays have the same X, Y, Z sizing.
psub copyarray3DSTR(array_index, temparray$(), sizeX, sizeY, sizeZ )
for x=0 to SizeX
for y=0 to SizeY
for z=0 to SizeZ
sourceindex = get_index3D(x, y, z, SizeX, SizeY)
temparray$(x, y, z) = Strings3D(array_index).entries$(sourceindex)
next z
next y
next x
endpsub temparray$()
//Copy the 2D string array safely to a temp array
psub copyarray2DSTR(array_index, temparray$(), sizeX, sizeY)
for x=0 to SizeX
for y=0 to SizeY
sourceindex = get_index2D(x, y, SizeX)
temparray$(x, y) = Strings3D(array_index).entries$(sourceindex)
next y
next x
endpsub temparray$()
//Copy the 3D int array safely to a temp array
psub copyarray3DINT(array_index, temparray(), sizeX, sizeY, sizeZ )
for x=0 to SizeX
for y=0 to SizeY
for z=0 to SizeZ
sourceindex = get_index3D(x, y, z, SizeX, SizeY)
temparray(x, y, z) = INTS3D(array_index).entries(sourceindex)
next z
next y
next x
endpsub temparray()
//Copy the 2D int array safely to a temp array
psub copyarray2DINT(array_index, temparray(), sizeX, sizeY)
for x=0 to SizeX
for y=0 to SizeY
sourceindex = get_index2D(x, y, SizeX)
temparray(x, y) = INTS2D(array_index).entries(sourceindex)
next y
next x
endpsub temparray()
//This doesn't resize an array it only changes the internal size definition
psub allocate_size3D(X, Y, Z, index, _type)
select _type
case 1:
INTS3D(index).X_width = X
INTS3D(index).Y_depth = Y
INTS3D(index).Z_depth = Z
case 2:
case 3:
Strings3D(index).X_width = X
Strings3D(index).Y_depth = Y
Strings3D(index).Z_depth = Z
endselect
endpsub
//This doesn't resize an array it only changes the internal size definition
psub allocate_size2D(X, Y, index, _type)
select _type
case 1:
INTS2D(index).X_width = X
INTS2D(index).Y_depth = Y
case 2:
case 3:
Strings2D(index).X_width = X
Strings2D(index).Y_depth = Y
endselect
endpsub
//Function deals with 3D string arrays
psub copyOld3DNew3DSTR(array_index, temparray$(), X_width, Y_depth, Z_depth, old_X_width, old_Y_depth, old_Z_depth)
for x=0 to old_X_width
for y=0 to old_Y_depth
for z=0 to old_Z_depth
//Here the indexes will be different for a differently dimensioned 3D String array as a 1D array so we need
//to do a translation based on the new Width and Height of the array
Old_Index = get_index3D(x, y, z, old_X_width, old_Y_depth)
New_Index = get_index3D(x, y, z, X_width, Y_depth)
//Ok we have our indexes, let's hope this isn't too costly.
old_string$ = temparray$(x, y, z)
Strings3D(array_index).entries$(New_Index) = old_string$
//and that's it, we've copied back the data.
//This function should be used with CopyArray3DSTR only.
next z
next y
next x
endpsub
//Function deals with 2d String arrays
psub copyOLD2DNew2DSTR(array_index, temparray$(), X_width, Y_depth, old_X_width, old_y_depth)
for x=0 to old_X_width
for y=0 to old_y_width
//Here the indexes will be different for a differently dimensioned 2D String array as a 1D array so we need
//to do a translation based on the new Width and Height of the array
Old_Index = get_index2D(x, y, Old_X_width)
New_Index = get_index2D(x, y, X_width)
//We have our indexes, coding this i feel craazy
old_string$ = temparray$(x, y)
Strings2D(array_index).entries$(New_Index) = old_string$
//tada done
//Skip hop and away we go
next y
next x
endpsub
//Function deals with 3D Integer arrays
psub CopyOld3DNew3DINT(array_index, temparray(), X_width, Y_depth, Z_depth, old_X_width, old_y_depth, old_z_depth)
for x=0 to old_X_width
for y=0 to old_y_depth
for z=0 to old_z_depth
//Here the indexes will be different for a differently dimensioned 3d INT array as 1D array so
//We have to do a translation based on the new Width and Height of the array yep yep
Old_Index = get_index3D(x, y, z, old_X_width, old_y_depth)
New_Index = get_index3D(x, y , z, X_width, y_depth)
//Got indexes? Great! Next we just copy and it doesn't seem costly
old_value = temparray(x, y, z)
INTS3D(array_index).entries(New_Index) = old_value
//and done
//~Tada 3D array copying and safety.
next z
next y
next x
endpsub
//Function deals with 2D Integer arrays
psub CopyOld2DNew2DINT(array_index, temparray(), X_width, Y_depth, old_X_width, old_y_depth)
for x=0 to old_X_width
for y=0 to old_y_depth
//Here the indexes will be different for a differently dimensioned 3d INT array as 1D array so
//We have to do a translation based on the new Width and Height of the array yep yep
Old_Index = get_index2D(x, y, old_X_width)
New_Index = get_index2D(x, y , X_width)
//Got indexes? Great! Next we just copy and it doesn't seem costly
old_value = temparray(x, y)
INTS2D(array_index).entries(New_Index) = old_value
//and done
//~Tada 2D array copying and safety.
next y
next x
endpsub
psub get3DSTRByname(total_entries, arrayname$)
for t=1 to total_entries
if Strings3D(t).internal_name$=arrayname$
arrayindex=t
exitfor
endif
next t
endpsub arrayindex
psub get2DSTRByname(total_entries, arrayname$)
for t=1 to total_entries
if Strings2D(t).internal_name$=arrayname$
arrayindex=t
exitfor
endif
next t
endpsub arrayindex
psub get1DSTRByname(total_entries, arrayname$)
for t=1 to total_entries
if Strings1D(t).internal_name$=arrayname$
arrayindex=t
exitfor
endif
next t
endpsub arrayindex
psub get3DINTByname(total_entries, arrayname$)
for t=1 to total_entries
if INTS3D(t).internal_name$=arrayname$
arrayindex=t
exitfor
endif
next t
endpsub arrayindex
psub get2DINTByname(total_entries, arrayname$)
for t=1 to total_entries
if INTS2D(t).internal_name$=arrayname$
arrayindex=t
exitfor
endif
next t
endpsub arrayindex
psub get1DINTByname(total_entries, arrayname$)
for t=1 to total_entries
if INTS1D(t).internal_name$=arrayname$
arrayindex=t
exitfor
endif
next t
endpsub arrayindex
//Variable handler functions for strings and variable
//This returns the variable value of a user declared single variable by it's index
psub return_int_VBYIndex(V_index)
// If the stack isn't big enough return the correct error and exit this call.
if variable_int_size<V_index
error(1, V_index)
return
endif
//now that we've actually made sure it's within the range of the array size
//We do this and return value
value = variable_ints(V_index).value //Get the actual value
endpsub value
//Make a simpler function that just returns the variable value by name.
//This is used for parsing to because it will actually get a value of 0
//if the variable doesn't exist or hasn't been declared
//Somewhat dangerous because it doesn't even exist on the stack still!!
//In most cases finding the variable name for the first time
//Should be enough to put it on the stack.
psub get_int_VB(name$)
V_value = 0 //set V_value to 0
//If un initialized it will initialize to zero to reduce errors
//First search for it by name
index = return_int_VByName(name$)
//Second get the value
if index >0 then V_value = return_int_VBYIndex(index)
endpsub V_value
//Make it so the variable stack can be resized
//This resizes the variable stack and makes dynamic allocation of variable management possible
//DO NOT use this, use inc_Vstack() instead for all dynamic resizing of the variable stack
psub resize_int_V(new_size)
redim variable_ints(new_size) as _variable
endpsub
psub inc_Vstack()
variable_int_size +=1 //this should be valid
resize_int_V(variable_int_size) //Resize the stack dynamically.
endpsub
//Get the index of a variable on the user declared variable stack by it's string name internally
psub return_int_VByName(searchname$)
V_index = 0 //Act as a false flag
for t=1 to variable_int_size
if variable_ints(t).value_$ = searchname$
V_index = t //resolve the linear search
exitfor //end the for loop
endif
next t
endpsub V_index
psub set_int_V(V_index, V_value)
variable_ints(V_index).value = V_value //set the value all there is to it
endpsub
psub set_int_N(V_index, V_name$)
variable_ints(V_index).value_$=V_name$
endpsub
//Used to test if the variable exists by name on the stack
//The reason we're creating this is so we know whether or not to create a new variable on the stack
psub variable_exists(V_name$)
V_EXISTS = FALSE
//Search to see if the variable exists
//If it doesn't return false
if V_index <= getarrayelements(variable_ints(), 1)
V_index = return_int_VByName(V_name$)
else
V_index=0
endif
if V_index >0 then V_EXISTS = true // Now we know the variable exists on the stack
endpsub V_EXISTS
//The below function adds a variable to the stack conditionally.
psub set_int_VB(V_name$, V_value)
//Cleanly checks if the variable exists, if it does just set it.
Case_A = variable_exists(V_name$)
if Case_A=true
//Patches >> just fixed this the parameters were in reverse order
set_int_V( return_int_VByname(V_name$),V_value)
return //Exit the psub because no further processing is needed saves time
//This case is evaluated first to save time because in most cases the variable already exists.
else
//Call inc_Vstack()
inc_Vstack() //Just increase the variable stack by 1 to make room for the newly declared variable
set_int_V(get_Vstack_size() ,V_value ) //Safer because it gets the size of the stack indirectly rather than directly
//Set the variable name to
set_int_N(get_Vstack_size(), V_name$) //This should hopefully allow getting later
endif
endpsub
psub get_Vstack_size()
A = variable_int_size //Hopefully this wraps the global value and returns it
endpsub A
//This is a psub that will actually get the value of a variable
psub DrawTXTBG(colorindex, X, Y)
PosX=(X-1)*16
PosY=(Y-1)*16
drawimage TXTBG(colorindex), PosX, PosY, 0
endpsub
//This sets the global text background color
psub set_global_textbackground(value)
global_textbackground=value
endpsub
//This sets the global text foreground color
psub set_global_textforeground(value)
global_textforeground=value
endpsub
psub cls_()
rendertoimage text_page
cls
rendertoscreen
endpsub
psub gcls()
rendertoimage graphics_page(currentGPAGEDSP)
cls
endpsub
Sub-Layer Functions
Spoiler
; PROJECT : TinySBRunTime
; EDITED : 2016-05-20
; ---------------------------------------------------------------------
//NYI not yet implemented
Psub parse(mystring$)
endpsub
psub get_color#(color$)
endpsub
//This does a few things, it draws the text page on the screen and the bg layers including ones shown/hidden
psub frame_render()
rendertoscreen
DRAWBGS()
render_TEXTPAGE()
endpsub
//Draw the textpage onto the screen
psub render_TEXTPAGE()
drawimage text_page, 0, 0, 1
endpsub
//This should be in charge of stepping the program stack foreward
psub step_()
inc pc //Increment the program counter
endpsub
//Used for utility to resize the stack of the program
psub resize_stack(value)
redim program_stack$(value)
endpsub
psub resize_labels(value)
redim labels$(value) //the labels themselves matter
redim label_pointers(value) //take care of the pointers to these are important
endpsub
psub getlabelbyvalue(value)
endpsub labels$(value)
psub add_returnstack(pc_pointer)
//first increase the return stack size by 1
inc return_stack_size
//We also have to resize the return stack array now
resize_Rstack(return_stack_size)
return_stack(return_stack_size)=pc //the address or line number to return to after the jump
pc = pc_pointer //the address or line number we are jumping to by directly modifying the pc pointer.
//the logic is simple instead of parsing where we are if we see return we pop a value off the stack
//and go back to the last pc address
endpsub
//This should literally take care of gosub
psub gosub_(label_name$)
index = findlabelbystring(label_name$)
if index>0
add_returnstack(index)
endif
endpsub
psub goto_(label_name$)
index = findlabelbystring(label_name$)
address = label_pointers(index)
if index>0
jump_pc(address) //changed value to address this would have been broken
endif
endpsub
psub remove_returnstack()
//first decrement the return stack size by 1
dec return_stack_size
//we have to also resize it
resize_Rstack(return_stack_size)
//next store the pc address from the jump below us
pc = return_stack(return_stack_size)
//the logic is simple, we're going back to the last place we had saved (line number)
//to continue execution.
//As you'd expect in this way we can have 5 or even 10 different lines to eventually return to
endpsub
psub findlabelbystring(str_$)
for t=0 to getarrayelements( labels$() )
if str_$ = labels$(t)
index=t
exitfor
endif
next t
endpsub index
psub resize_Rstack(value)
redim return_stack(value)
endpsub
//this takes care of jumping to the line number or index of the program to run
//Probably used by goto and other commands like it
psub jump_pc(value)
pc = value
endpsub
//utility for testing
//puts an item in the program stack,
//increments stack counter
psub put(command$)
program_stack$(program_stack_size) = command$
inc program_stack_size //increments the program stack size
resize_stack(program_stack_size)
endpsub
Psub find_labels()
dim label_strings$(1) //it should auto resize
current_label = 1 //set the temporary current label counter so we actually have a label counter
//pre parsing labels so we know what their line numbers are
for t=1 to program_stack_size //Go through the whoollle stack
entry_string$ = program_stack$(t)
//Lots of nested ifs here. basically just check the label string
if left$(entry_string$, 1)="@"
//Ok we found one, let's see if we can get the full string of the label we need to store it
Tokens=SplitToArray(entry_string$," ",label_strings$(),1)
if len(label_strings$(1))>0 and left$(label_strings$(1), 1)="@"
//Just double check that the @ symbol is there.
//and this adds the label to our list
add_label(label_strings$(1), t, current_label)
inc current_label //don't forget to increment this or we'll over write
//a previously saved or stored label
//and now gosub/goto should work if called
endif
endif
next t
endpsub
//This function handles dynamically adding new labels to the label list pre-parsing
//This is never used during runtime and it better not ever be ;)
psub add_label(label$, pc_index, current_label)
//A little safety to make sure it doesn't break things and
//that this array stays within it's indexes
if current_label > label_list_size
resize_labels(current_label)
endif
//end of safety
labels$(current_label) = label$ //the actual label's name
label_pointers(current_label) = pc_index //the pc address it's on
endpsub
Psub parse_command(index)
dim command_strings$(20)
dim command_strings_$(20)
Tokens=SplitToArray(program_stack$(index),", ",command_strings$(),1)
//Parse the color command
for g=1 to Tokens
if command_strings$(g) ="COLOR"
//Tokens=SplitToArray(command_strings$(g+1),",",command_strings_$(),1)
color_1$ = command_strings$(g+1)
color_2$ = command_strings$(g+2)
color_#(color_1$, color_2$)
exitfor
endif
//Kind of parse the print command
if command_strings$(g) = "Print"
output_string$ = ""
for a = 2 to Tokens
if a>2 then output_string$ = output_string$ +" "+ command_strings$(a)
if a=2 or a=Tokens then output_string$ = output_string$ + command_strings$(a)
//locate(10, g)
next a //Hopefully this makes print able to print more ??
print_string(output_string$)
endif
if command_strings$(g) = "goto"
//We'll get the goto label first
goto_label$ = command_strings$(g+1)
//Next we're going to see if it has an @
if left$(goto_label$, 1)="@"
//we're dealing with a correct label
goto_(goto_label$) //and this should change the pc address!
exitfor //now exit the for loop
endif
endif
if command_strings$(g) = "locate"
//we'll try to get the X and Y out of this
X$ = command_strings$(g+1)
Y$ = command_strings$(g+2)
//if right$(X$, 1)="," then X$=left$(X$, len(X$)-1)
x = val(X$)
y = val(Y$)
//locate(5, 15)
//print_string(X$)
//locate(5, 16)
//print_string(Y$)
locate(x, y)// actually try to use the command
//locate(20, 7)
exitfor
endif
next g
endpsub
psub error(value, param1)
select errornum
case 1:
error_$ = "The global variable stack size is less than the intended index of user variable "
error_$=error_$+str$(variable_int_size) +" < " +str$(param1)
default:
error_$ = "Generic Error!" //PlaceHolder in case a real error can not be resolved.
endselect
endpsub error_$
Without all of the previous none of this would work or atleast a large portion of it would throw errors or do nothing
Spoiler
; PROJECT : TinySBRunTime
; AUTHOR : Microsoft
; CREATED : 2016-05-16
; EDITED : 2016-05-20
; ---------------------------------------------------------------------
SETFPS 60
//A Tiny SB TestLoop
for tx=0 to 127
for ty=0 to 127
BGPUT(2, tx, ty, tiles(tx+ty) )
if mod(tx, 8)=<12 and mod(ty, 2)=0 then BGPUT(3, tx, ty, tiles(tx+ty*2) )
next ty
next tx
Bg3ofX=0
Bg3ofY=0
Bg2ofX=0
Bg2ofY=0
BGSHOW(3)
BGSHOW(4)
main:
inc Bg3OfY
inc Bg2OfX
BGOFS(2, bg2Ofx, 1)
BGOFS(3, 1, Bg3ofY)
locate(5, 5)
color_#("#TRED", "#TGREEN");
print_string("Hi this is a test");
color_#("#TYELLOW", "#TTEAL");
locate(5, 6)
print_string("Another color test!! WOOO!!")
locate(5, 7)
color_#("#TGREEN", "#TMAROON")
print_string("And just to be cool")
locate(5, 8)
color_#("#TNAVY", "#TGRAY")
print_string("Cool right")
print "Global Text Background is " +str$(global_textbackground) + "And Global Text Foreground is " +str$(global_textforeground);
//frame_render()
put("@loop")
//This might happen after label parsing..
//put a color command in the stack
put("COLOR #TRED, #TGREEN");
//put a locate in the stack
put("locate 20, 7")
//put a print in the stack
put("Print hello")
put("COLOR #TTEAL #TYELLOW")
put("locate 20, 8")
put("Print this is A+ PLUSSER YEAHHH HOOO")
put("locate 20, 9")
put("Print");
//here we're going to try parsing the first loop
put("goto @loop")
//Call the Psub to create the label indexes
find_labels()
cls rgb(0,0,0)
set_int_VB("hi" , 25)
set_int_VB("hithere", 10)
ink rgb(255, 255, 255)
print get_int_VB("hi");
print get_int_VB("hithere");
set_int_VB("hithere", 15);
print "New value is " + str$( get_int_VB("hithere") )
set_int_VB("A", 1999);
set_int_VB("A", get_int_VB("A") +1 );
print get_int_VB("A");
sync
waitkey
waitnokey
do
if pc>program_stack_size
locate(9,25)
print_string( "END OF PROGRAM at " +str$(pc) )
frame_render() //render the frame including bg/sprite etc
sync
waitkey
waitnokey
end
Endif
frame_render() //render the frame including bg/sprite etc
parse_command(pc)
step_() //step the program stack
sync
cls rgb(0,0,0)
loop
This is the crazyness I've been working towards for a while.