(http://underwaredesign.com/PlayBasicSig.png)
PlayBASIC V1.64P (Work In Progress) Gallery (September 1, 2013 - November 2016)
This thread will document the changes being made for the PlayBASIC 1.64 revision P.
V1.64P4 (Revision #4) released 24th, Mar, 2016 (http://www.underwaredesign.com/forums/index.php?topic=1774.msg29079#msg29079) (Newest!)
V1.64P3 (Revision #3) released 20th, Nov, 2015 (http://www.underwaredesign.com/forums/index.php?topic=1774.msg28977#msg28977)
V1.64P2 (Revision #2) released 29th, Dec, 2014 (http://www.underwaredesign.com/forums/index.php?topic=1774.msg28609#msg28609)
V1.64P (Revision #1) released 22nd,Sep,2014 (http://www.underwaredesign.com/forums/index.php?topic=1774.msg28470#msg28470)
Upgrade History
For older upgrade work in progress see,
See PlayBASIC V1.64O (http://www.underwaredesign.com/forums/index.php?topic=3988.0)
See PlayBASIC V1.64N2 & V1.64N3 (http://www.underwaredesign.com/forums/index.php?topic=3833.0)
See PlayBASIC V1.64N (http://www.underwaredesign.com/forums/index.php?topic=3651.0)
See PlayBASIC V1.64M (http://www.underwaredesign.com/forums/index.php?topic=3440.0)
See PlayBASIC V1.64L Learning Edition History (http://www.underwaredesign.com/forums/index.php?topic=3405.0) (Building learning Edition Thread)
See PlayBASIC V1.64L (http://www.underwaredesign.com/forums/index.php?topic=3364.0)
Upgrade Work In Progress Blog Followes
PlayBASIC V1.64P Beta1/2 - Compiler Tweaks While working on the PlayBASIC to DLL noticed a few situations where the compiler was dropped extra opcodes, or the instructions being produced could be better arranged. One such situation was noticed when the writing to static array fields in Type Pointers where the compiler would drop generally 3 opcodes to resolve the address and perform the write. The pointer instruction set support a fixed offset in write, but this was being overlooked for some unknown reason. So at least one of those 3 opcodes can be removed by just piping the offset in the write. Which reduces it to two instructions, so potentially a 1/3 faster. If the field is a literal, we can precompute the offset at compile time, which trims this operation back to a single opcode. Not only will it be faster pointer operations, but the stream lining will help with some the data pooling that occurs around pointers.
Bench-marked todays build and it's about 35% faster than V1.64O in that situation.
[pbcode]
Type CoolType
x,y,z
a#,b#,c#
ThisString$
IntArray(5)
FltArray#(5)
StrArray$(5)
cool
EndType
DIm You as CoolType
DIm Me as CoolType pointer
you = new cooltype
me =new cooltype
; Me=Address
max=10000
Do
cls
frames++
;------------------------------------------------------------------------
;--[Integer Fields ]-----------------------------------------------------
;------------------------------------------------------------------------
t=timer()
for lp =0 to max
me.x=111
me.y=222
me.z=333
me.z++
next
tt1#+=timer()-t
print " Integer Field:"+str$(tt1#/frames)
;------------------------------------------------------------------------
;--[Float Fields ]-----------------------------------------------------
;------------------------------------------------------------------------
t=timer()
for lp =0 to max
me.a#=111.111
me.b#=222.222
me.c#=333.333
next
tt2#+=timer()-t
print " Float Field:"+str$(tt2#/frames)
;------------------------------------------------------------------------
;--[String Fields ]-----------------------------------------------------
;------------------------------------------------------------------------
t=timer()
for lp =0 to max
me.ThisSTring="String1"
me.ThisSTring="String2"
me.ThisSTring="String3"
me.ThisSTring="String4"
next
tt3#+=timer()-t
print " String Field:"+str$(tt3#/frames)
;------------------------------------------------------------------------
;--[Int Array Fields ]-----------------------------------------------------
;------------------------------------------------------------------------
t=timer()
for lp =0 to max
me.intarray(a) = 1000
me.intarray(a) = 1001
me.intarray(a) = 1002
me.intarray(a) = 1003
next
tt4#+=timer()-t
print "Integer Array Fields:"+str$(tt4#/frames)
;------------------------------------------------------------------------
;--[Flt Array Fields ]-----------------------------------------------------
;------------------------------------------------------------------------
t=timer()
for lp =0 to max
me.fltarray(a) = 1000.111
me.fltarray(a) = 1001.111
me.fltarray(a) = 1002.111
me.fltarray(a) = 1003.111
next
tt5#+=timer()-t
print " Float Array Fields:"+str$(tt5#/frames)
;------------------------------------------------------------------------
;--[String Fields ]-----------------------------------------------------
;------------------------------------------------------------------------
t=timer()
for lp =0 to max
me.Strarray(a) = "cool1"
me.Strarray(a) = "cool2"
me.Strarray(a) = "cool3"
me.Strarray(a) = "cool4"
next
tt6#+=timer()-t
print " String Array Fields:"+str$(tt6#/frames)
print fps()
Sync
loop
[/pbcode]
PlayBASIC V1.64P Beta3- Math Short Cuts + Pointers
The parser didn't support ++,--, +=, -= operators on pointers, does now. The VM was also missing support for subtractions from stringref pointers.
[pbcode]
Type Vector
x#,y#,z#
endtype
Dim VectorPointer as Vector pointer
Dim GenericPointer as pointer
Dim BytePointer as byte pointer
Dim WordPointer as word pointer
Dim IntegerPointer as integer pointer
Dim FloatPointer as float pointer
Dim StringPointer as stringref pointer
me=1000
VectorPointer =me
GenericPointer =me
BytePointer =me
WordPointer =me
IntegerPointer =me
FloatPointer =me
StringPointer =me
VectorPointer ++
GenericPointer ++
BytePointer ++
WordPointer ++
IntegerPointer ++
FloatPointer ++
StringPointer ++
VectorPointer --
GenericPointer --
BytePointer --
WordPointer --
IntegerPointer --
FloatPointer --
StringPointer --
VectorPointer +=10
GenericPointer +=10
BytePointer +=10
WordPointer +=10
IntegerPointer +=10
FloatPointer +=10
StringPointer +=10
VectorPointer -=20
GenericPointer -=20
BytePointer -=20
WordPointer -=20
IntegerPointer -=20
FloatPointer -=20
StringPointer -=20
#break
sync
waitkey
[/pbcode]
PlayBASIC V1.64P Beta5- Link List Support In Debugger
One by product of changing how VM controls type declarations, is I've been sifting through some really really old code tucked away all over the place. Since how the type structures has changed, then it stands to reason the debugger needs to be aware of these changes also. While updating the routines I noticed some TODO remarks about getting the view typed array routines to support linked lists from years ago. In older versions of PB, if you clicked on linked list it would run through the container and not actually the list order. So today's change includes a mode for literate through the list.
For example,
[pbcode]
Type ThisThing
Index
x
EndTYpe
Dim Things as ThisThing list
For lp=1 to 10
Things = new ThisThing
Things.index=lp
Things.x = rnd(1000)
next
For each Things()
print Things.index
print Things.x
next
print "Done"
Sync
waitkey
[/pbcode]
If you run this in debug mode F7, go to the Variables TAB, click Main then clicks THINGS(), it'll dump this into text box panel
----------------------------------------------------------
THINGS.thisthing
Type =thisthing
Size =112
Bank =177
----------------------------------------------------------
--------------------------------------------------------
THINGS( 10 ).thisthing
--------------------------------------------------------
INDEX =10
X =609
--------------------------------------------------------
THINGS( 9 ).thisthing
--------------------------------------------------------
INDEX =9
X =296
--------------------------------------------------------
THINGS( 8 ).thisthing
--------------------------------------------------------
INDEX =8
X =280
--------------------------------------------------------
THINGS( 7 ).thisthing
--------------------------------------------------------
INDEX =7
X =753
--------------------------------------------------------
THINGS( 6 ).thisthing
--------------------------------------------------------
INDEX =6
X =938
--------------------------------------------------------
THINGS( 5 ).thisthing
--------------------------------------------------------
INDEX =5
X =165
--------------------------------------------------------
THINGS( 4 ).thisthing
--------------------------------------------------------
INDEX =4
X =163
--------------------------------------------------------
THINGS( 3 ).thisthing
--------------------------------------------------------
INDEX =3
X =501
--------------------------------------------------------
THINGS( 2 ).thisthing
--------------------------------------------------------
INDEX =2
X =882
--------------------------------------------------------
THINGS( 1 ).thisthing
--------------------------------------------------------
INDEX =1
X =788
PlayBASIC V1.64P Beta5/6 - Reading UDT pointer fields
The current beta seems to be back to normal, so figured it'd be a good time to try and clean up the code generation when reading from a static array in UDT pointer. About a week or so I noticed when writing to the these structures the compiler with spit out more instructions than it needed and assuming reading would be the much the same and it is, but that section of the expression solver is a bit of a mess. There's some really neat ideas hidden away in it, but trying to the follow logic in some places can be a little more clumsy than i'd like.
When a UDT pointer with array field offset is detected in an expression, the parser modifies the current tokens state and falls through these a generic resolvers. Which I'm sure was a good idea back in the day, which was probably 5, 6 or more years ago now, but I'm having trouble cleaning up the output without breaking some other situation i'd not even considered. So the best option seems to be detect the specific situation and call a more specific solver.. Have already removed one bogus additions when the field is being offset and hope to get it to be able to pre-solve literal offsets also. So in some cases it'll only take one read instruction to grab the correct data from the data structure rather than a fixed cost of 3 (or more opcodes).
Tested the initial changes and it wins back the same 30% when reading from the structure as the write changes made. So In the brute force bench mark we get about a 30 millisecond performance improvement. Not only does this mean the native code translation will be faster, but UDT pointers can actually be quicker than regular typed variables and probably typed arrays also..
[pbcode]
Type CoolType
x,y,z
a#,b#,c#
ThisString$
IntArray(5)
FltArray#(5)
StrArray$(5)
cool
EndType
DIm Me as CoolType pointer
me =new cooltype
max=10000
Do
cls
frames++
;------------------------------------------------------------------------
;--[Integer Fields ]-----------------------------------------------------
;------------------------------------------------------------------------
t=timer()
for lp =0 to max
me.x=111
me.y=222
me.z=333
next
tt1#+=timer()-t
print " Integer Field:"+str$(tt1#/frames)
;------------------------------------------------------------------------
;--[Float Fields ]-----------------------------------------------------
;------------------------------------------------------------------------
t=timer()
for lp =0 to max
me.a#=111.111
me.b#=222.222
me.c#=333.333
next
tt2#+=timer()-t
print " Float Field:"+str$(tt2#/frames)
;------------------------------------------------------------------------
;--[String Fields ]-----------------------------------------------------
;------------------------------------------------------------------------
t=timer()
for lp =0 to max
me.ThisSTring="String1"
me.ThisSTring="String2"
me.ThisSTring="String3"
me.ThisSTring="String4"
next
tt3#+=timer()-t
print " String Field:"+str$(tt3#/frames)
;------------------------------------------------------------------------
;--[Int Array Fields ]-----------------------------------------------------
;------------------------------------------------------------------------
t=timer()
for lp =0 to max
me.intarray(a) = 1000
me.intarray(a) = 1001
me.intarray(a) = 1002
me.intarray(a) = 1003
next
tt4#+=timer()-t
print "Integer Array Fields:"+str$(tt4#/frames)
;------------------------------------------------------------------------
;--[Flt Array Fields ]-----------------------------------------------------
;------------------------------------------------------------------------
t=timer()
for lp =0 to max
me.fltarray(a) = 1000.111
me.fltarray(a) = 1001.111
me.fltarray(a) = 1002.111
me.fltarray(a) = 1003.111
next
tt5#+=timer()-t
print " Float Array Fields:"+str$(tt5#/frames)
;------------------------------------------------------------------------
;--[String Fields ]-----------------------------------------------------
;------------------------------------------------------------------------
t=timer()
for lp =0 to max
me.Strarray(a) = "cool1"
me.Strarray(a) = "cool2"
me.Strarray(a) = "cool3"
me.Strarray(a) = "cool4"
next
tt6#+=timer()-t
print " String Array Fields:"+str$(tt6#/frames)
print ""
;------------------------------------------------------------------------
;--[Int Array Fields ]-----------------------------------------------------
;------------------------------------------------------------------------
t=timer()
for lp =0 to max
me.intarray(a) += 1
me.intarray(a) += 1
me.intarray(a) += 1
me.intarray(a) += 1
next
tt7#+=timer()-t
print "Add To Integer Array Fields:"+str$(tt7#/frames)
;------------------------------------------------------------------------
;--[Flt Array Fields ]-----------------------------------------------------
;------------------------------------------------------------------------
t=timer()
for lp =0 to max
me.fltarray(a) += 1
me.fltarray(a) += 1
me.fltarray(a) += 1
me.fltarray(a) += 1
next
tt8#+=timer()-t
print "Add To Float Array Fields:"+str$(tt8#/frames)
print ""
;------------------------------------------------------------------------
;--[Read Array Fields ]-----------------------------------------------------
;------------------------------------------------------------------------
a=5
me.intarray(a)=44444
t=timer()
for lp =0 to max
temp=me.intarray(a)
temp=me.intarray(a)
temp=me.intarray(a)
temp=me.intarray(a)
next
tt9#+=timer()-t
print "Read Integer Array Fields:"+str$(tt9#/frames)
print temp
;------------------------------------------------------------------------
;--[Flt Array Fields ]-----------------------------------------------------
;------------------------------------------------------------------------
me.fltarray(a)=123.456
t=timer()
for lp =0 to max
temp#=me.fltarray(a)
temp#=me.fltarray(a)
temp#=me.fltarray(a)
temp#=me.fltarray(a)
next
tt10#+=timer()-t
print "Read Float Array Fields:"+str$(tt10#/frames)
print temp#
print fps()
Sync
loop
[/pbcode]
PlayBASIC V1.64P Beta6 - UDT pointers Continued
Still working on the compiler, have updated some optimization code to support dealing with typed pointers, which are things types have enjoyed for a while now. The expression resolver has a number of pretty simple, but rather effective short cutting mechanics built in. These are little traps that can strip unnecessary moves between VM registers and user variables namely. They generally work by back tracking the last few opcodes, if the data types match then some these expressions can be short cut. One of the many benefits of using 3 register opcodes in the VM. Often it's just match of noticing those situations where a short can be made and wiring it in.
Short cuts can turn some code like X = Player.X into a single VM opcode. That's of course assuming the field Player.X and the variable X it's returning the result in are the same data type. If they're different, like say one is an integer and the other is a float, then the exported result from Player has to be recast prior to being written it to the output variable. Making it at least a 2 instruction operation. Without the write tracing, the compiler would always spit out the latter, so the short cutting just lets it detect situations where the casting isn't necessary and the result can be plugging back into a previous operation directly.
Another area that's I've been looking into, is trying to detect and resolve literal array field accesses not only with typed pointers, but regular typed variable/arrays also. The theory is, that when you access a static array field within type at a fixed offset, then the compiler should be able to reduce this from it's current 4+ opcodes down to the as low as two opcodes in some explicit cases but probably 3 opcodes in the general use. Which might sound like mumbo jumbo, but we're talking about a 20% or more speed up in a fundamental.
Changes like these aren't likely to make any big difference to a game with 5, 10, 20 characters on screen, but they would make a sizable impact if there's 100's of characters or programs that insist upon trying brute force solutions. Obviously a better idea would be to never rely upon brute forcing any solution to begin with, but some people just never learn.
Only problem I've been having so far is that there's some odd cascading errors that seem to appear when optimizing the static array fields in the select programs. No idea why.. What a fun afternoon I'm now in for.
PlayBASIC V1.64P Beta10 Download
Surprise Surprise, BETA 10 of V1.64P upgrade is online and ready for testing. This beta has a lot of internal changes range from improved code generation and the internal command set interfaces which will be used for building external DLL's with PlayBASIC To Dll. So we're keen to find out what if anything has been broken during the update process NOT after.
PlayBASIC V1.64P Beta16 Download
Here's BETA 16 of V1.64P upgrade. This version includes all the internal command set interfaces for use with external DLL's created with PlayBASIC To Dll.
The process has introduced a lot of small, but necessary changes to the command sets which may have altered the behavior.. So get testing.
Download
Old beta removed
PlayBASIC V1.64P Beta 17 - Operators and Precedence
It shouldn't come as any great surprise that changes in this revision are to help with the PlayBASIC To DLL (http://www.underwaredesign.com/?l=PlayBASIC-To-DLL-Development-Blog) translator and it's ability to produce cleaner and better code generally. Building the translator means taking a fine tooth comb to the generated byte code and making sure the compiler outputs the leanest set of instructions possible to perform each operation. While looking over the bit wise/logical operators recently noticed they'd not been set to force an integer result. So if you had an expression fragment that contained a float, it'd return a float in the legacy VM. Fortunately this is simple to rectify as the parser has a switch to force an integer return. This is a bit of a none issue in most programs since the operators are generally only ever see integers on either side of them, but it can and does actually occur in some code.
Having operators return a float isn't an earth shattering problem, it just makes a simple operation messy and slower than need be when such things occur. The existing translator already supports operations upon integers, but it didn't handle mixtures between integers and floats. Forcing the compiler to produce an integer only result, helps the VM keep everything integer and translator produce cleaner machine code from the byte code without making multiple path ways.
While looking at the operators again in the compiler and translator, noticed that NOT seems have a precedence issue. For some reason it's evaluated before the math/compare operators in an expression. It should be the same as the other operators and occur after them.
So code like print not a=b is being evaluated Not A then result_of_Not_A=b , where it should do A=b then do Not Result_Of_Compare_A_With_B.
Moreover Not is implemented as a mask and Xor of the bit zero value on the right hand side. After a rethink, it'd be better implemented as a equality test with zero then xor. So code like Not 45, would actually be evaluated as Not (44<>0), Not 1 = 0. Where it'd currently return 1 since bit zero is OFF, it'll flip that off bit to on.
The bad thing about the NOT operator is that your introducing complexity into your expression for no real benefit, as result = (Not A = B) and Result = (A <>B) are functionality the same, expect the former is two operations and the latter is single operation. No big deal in a loop of 1 to 100, but a very big deal when iteration count blows out in both VM and Machine Code.
Edit #1:
Found the problem, the operator trap in the parser was missing the operation level screen. Once added, the order solves as expected.
[pbcode]
print not a=b
print not a<>b
print not a#=b#
print not a#<>b#
; thee lines would fail in older versions of PB, since it'd evaluate Not A$ first
print not a$=b$
print not a$<>b$
[/pbcode]
Edit #2: Optimizer
The expression solver now contains logic to optimize & rewrite code fragments like the following. The optimizer also supports literal Not statements as well so that be evaluated in constant expressions.
[pbcode]
Print Not 1
Print Not 0
Print Not 1.0
Print Not 0.0
Print Not A=B
Print Not A<>B
Print Not A#=B#
Print Not A#<>B#
Print Not A$=B$
Print Not A$<>B$
[/pbcode]
Becomes,
[pbcode]
Print 0
Print 1
Print 0
Print 1
Print A<>B
Print A=B
Print A#<>B#
Print A#=B#
Print A$<>B$
Print A$=B$
[/pbcode]
So since we're saving an opcode every time, the object code is smaller and of course faster in both the VM and machine code. No brainier really.
PlayBASIC V1.64P Beta 18 - Shift Operators
Just dropping in some more C styled operators with the << and >> which are equivalent of the existing LSR32 and LSL32 functions (which is what they are in assembly btw). Just makes dragging code between dialects that little bit simpler. There's no functionality difference between them.
[pbcode]
print 1 << 2
print 256 >> 2
a=16
b=4
b#=b
print "variables & literals:"
print a << 4
print a >> 4
print 4 << a
print 4 >> a
print "integer only"
print a << b
print a >> b
print b << a
print b >> a
print "mixtures (floats recast as ints)"
print a << b#
print a >> b#
print b# << a
print b# >> a
Sync
waitkey
[/pbcode]
PlayBASIC V1.64P Beta 18 - Updated Operator Codes For IDE
The compiler and IDE talk to each other when you first start PlayBASIC up. The discussion is pretty one sided, but the IDE basically asks PB for it's current internal command, constant and operator list.
The board syntax highlighter currently doesn't support them all as you can currently see in this snippet. (This statement will be obsolette when i next update the board, so they'll appear as per the IDE..)
[pbcode]
; Testing operators in standard PlayBASIC IDE
a++
a--
a+=b
a-=b
a*=b
a/=b
print a< B
print a> B
print a<>B
print a><B
print a>=B
print a<=B
print a=>B
print a=<B
print 1 << 2
print 256 >> 2
a=16
b=4
b#=b
print "variables & literals:"
print a << 4
print a >> 4
print 4 << a
print 4 >> a
print "integer only"
print a << b
print a >> b
print b << a
print b >> a
print "mixtures (floats recast as ints)"
print a << b#
print a >> b#
print b# << a
print b# >> a
print hex$(255 and 15 << 8)
Sync
waitkey
[/pbcode]
Attached is a what it looks like in the classic IDE
Edit #1 - Not Equal Operator
It appears PB parser would only ID one version of the Not Equal operator, that being <> , where as the inverse also represents an inequality, but the parser didn't pick it up. With a quick tinker and it supports >< also.
Edit #2 - C styled not Not Equal Operator
Dropped in the != this in for those who can't live without their c fix.. Same as <>and ><
PlayBASIC V1.64P Beta18 Download
Here's BETA 18 of V1.64P upgrade, this version contains a number of small fixes from the trig functions that are used in the external command interfaces (PlayBASIC to DLL) through to some optimizations and correction regarding the NOT operator as well as even a few new operators such as the shift left/Right operators << and >>
Download
Old beta removed
I've got a little suggestion for a new graphics command (actually a group of them), which if I remember rightly can be found in qbasic. It is for arcs and sectors of circles and possibly ellipses too, further to full and filled circles and ellipses. You have the same arguments as before - Xpos, Ypos, Radius (X and Y for ellipses), FillMode, optionally Colour - but you also have a start angle and an end angle, for which a starting point would have to be defined, e.g. the vertical. With these commands, you could draw the mouth of a smiley face using the following:
sector xpos, ypos, rad, 0, 90, 270
And pacman using the following:
sectorC xpos, ypos, rad, 1, yellowrgb, 135, 45
What do you think?
@bmorris,
Thanks for the suggestion and it does seem doable, but requests really shouldn't be in these threads. They just get lost and quickly forgotten. V1.64P is almost entirely focused on changes required for PlayBASIC to DLL (http://www.underwaredesign.com/?l=PlayBASIC-To-DLL-Development-Blog)
So it's better to put such things in the [plink]Request Boards (http://www.underwaredesign.com/forums/index.php?board=29.0)[/plink] (See [plink]FAQ (http://www.underwaredesign.com/forums/index.php?topic=2839.0)[/plink])
Oh dear, the existence of that subforum had slipped me by! If the idea does get forgotten, I'll repost it there ahead of 1.65 or later.
PlayBASIC V1.64P Beta 19/20
The V1.64P revision has only had a few changes late last year, none of them were really user related (just the odd tweak for how PB and PlayBASIC 2 DLL communicate) , although tonight i've been looking over the GetArray and SetArray commands. These are a way a user can access arrays through a stub array. So if you create a stub (and array with no data of it's own) via MakeArray, you can copy the 'pointer/buffer' from any other array into the stub via getting that arrays index via GetArray and then setting it via SetArray. The array indexes are linear, so you can actually write code that runs through a block of similar arrays without having to pass them. The process is basically the same as how and array is passed into a function or psub anyway..
[pbcode]
Dim Table(100)
Dim Table2(1000)
; make a stub array called Me()
MakeArray Me()
; Me() now contains a copy of buffer that Table() officially owns
SetArray Me(), GetArray(Table())
; see me is now 100 elements in size
Print GetArrayElements(Me())
; put some data in table are indexes 0,1,2
Table(0) = 111
Table(1) = 222
Table(2) = 333
; show what me()'s looking at
print Me(0)
print Me(1)
print Me(2)
Sync
waitkey
[/pbcode]
While working on PlayBASIC to DLL noticed the GetARRAY function can be pre computed at compile time, currently there's actually a library function that preforms the rather trivial calculation at runtime. SetArray is little more difficult as it's scope aware, which is fine for the VM environment, but a little difficult in translated version, without piping all the compile time data into the DLL, which i'm not too keen on. Originally the SetArray would let you set and get between any array regardless of scope. I forget why it was changed, but have a feeling that could well get reverted at some point in the near future :)
PlayBASIC V1.64P Beta 21 - Data updates
While building the data support into PlayBASIC to DLL, found a we issues with the VM data commands. The main one was the Restore would allow a negative data pointer position. Which would pull data from off the table, it's not clamped. Another change is the FindDATA function had some dead weight in it and was missing the ability to search from the current DataPointer position. This has been added as a switch in the position field, if you set the field to a -1 the command will use the existing data pointer to search from. The position field is optional now and defaults to -1
[pbcode]
Data 10, 20,30,40,50,10,10,50
; find the first instant of the Integer value 50
; and set the data pointer to the cell after that value
Restore FindData(50)+1
; show us what where it is within the set
Print GetDataPointer()
; find the next instance of 50
Restore FindData(50)
; show us where it is
Print GetDataPointer()
sync
waitkey
[/pbcode]
Test Code.
[pbcode]
Data "StartBaby"
Label1:
Data 10
Label2:
data 20,30,40,50
Label3:
Data 111.111,222.222,333.333 ,444.444, 555.555
Label4:
data "hello world1","hello world2","hello world3","hello world4","hello world5"
DLL_DATATEST()
sync
waitkey
Function DLL_DATATEST()
print GetDataPointer()
Label4=100
restore Label4
print "Reading data types on heap"
Count=GetDataQuantity()
print "Count:"+str$(count)
for lp=-10 to count
restore lp
DataType=getDataType()
s$= Str$(lp)+" ="+str$(getDataPointer())+" type="+str$(DataType)
Select DataType
case 0
s$+=" Data="+str$( ReadData())
case 1
s$+=" Data="+str$( ReadData#())
case 2
s$+=" Data="+ReadData$()
endselect
print s$
next
print "restore tests"
restore "hello world2"
print GetDataPointer()
restore "StartBaby"
print GetDataPointer()
print "find Data tests"
print FindData("hello world3",0)
print FindData(50,0)
print FindData(222.222,0)
; find the first instance of 50 from the current data pointer position
print FindData(50)
EndFunction
[/pbcode]
PlayBASIC V1.64P Beta #21 - Download
Beta #21 fixes a few newly uncovered issues but mainly it brings everything into line with the latest builds of PlayBASIC to DLL. The only new feature that comes to mind is the ability to search the data heap from the current heap pointer from the FindDATA function.
FindData originally would only search from the user defined position in the data heap, but if you pass the position as -1 now, it'll use the current data heap position (which you can read via GetDataPointer() ) as it's starting point. The position and direction flags are optional, so the statement FindData(50) would search for the next integer value on the heap of 50. The direction defaults to forward. The data pointer would then be pointing at this item. If no such item can be found it'll return -1
PlayBASIC V1.64P Beta 23 - Opting Dead Weight from Byte Code
When you look through enough code, you'll see various ways people make use of the core command set. Sometimes noticing code fragments that are effectively null. In particular within decisions & loops where the decision expression is literal. When such things occor, the compiler can remove/replace such statements when it notices them.
For example take the following Repeat/Until examples. Both have literal expressions, so both can be solved at compile time. In the first loop we're really just emulation a Do/LOOP, so the parser now substitutes the Until False with a JMP statement. In the second example, which would always fall through at runtime, the compiler now generates nothing.
Example #1
[pbcode]
setfps 60
Repeat
cls
print "running"
sync
Until false
[/pbcode]
Since the Until will always branch back to the repeat, the decision isn't needed at all, so the code fragment actually compiles like it was this.
[pbcode]
setfps 60
do
cls
print "running"
sync
loop
[/pbcode]
Example #2
[pbcode]
setfps 60
repeat
cls
print "running again"
sync
until true
[/pbcode]
Since the Until is TRUE at compile time, the decision and branch aren't need at all, so the code fragment actually compiles like it was this.
[pbcode]
setfps 60
cls
print "running again"
sync
[/pbcode]
PlayBASIC V1.64P Beta 23 - Instruction Remapping
Instruction sets are laid out in blocks inside the Virtual Machine(s), which is fine, until you run into the odd instruction that's been wrongly blocked. For some reason, some of the more senior instructions are mapped into various 'core' instruction sets. There's a few layers of core instructions, but they're generally the most primitive operations. Things like math operations, comparisons, flow control etc.
This is not a huge drama for the VM, providing it can locate the instructions it needs, which it can. But when we want to export/translate the byte code, this can be quite a pain handling custom exceptions. The PlayBASIC to DLL translator is built around the idea of mapping instruction sets into common tables. Where the high level command sets all breaks down in a separate tables. The low level operations don't, they must be manually resolved. So the annoyance this creates is it's more work and ultimately more dependent than it need be. PB2DLL can translate any known set of commands via one routine, regardless of the input/output fields. But lower level stuff, has to be manually written. Making the former easier in the long run, but tedious in the short term ;(
In terms of functionality difference to PB1.64P VM, this makes virtually no difference at the moment. The hope is to share some of the newer code between the two sides. This should make execution under the VM faster (of those operations) and will strip sway some of the baby fat that's been introduced in the short term.
PlayBASIC V1.64P Beta 24 - Instruction Remapping Continued - MidPoint, MinVal,MaxVal
Still wading through the core operation functions trying to weed out any unnecessary byte code from ever being produced. You might be aware that the PlayBASIC compiler supports pre-evaluation of literal(constant) expressions. This means that when PB notices an operator in your code being performed upon literals. The operation is solved right there and then without producing any byte code at all. So if you have line of code Print 67*56 , the Multiply is solved during compilation and the output code is actually Print 3752 - Which is really handy for the programmer and more efficient for the runtime.
The compile time evaluations don't just stop at simple math operators though, as a number of the internally bound functions are also able to be solved at compile time. You can't solve everything, but the more of this stuff you trap then the less work a program has to be at runtime. Which in term means, the less code being translated when it's exported to DLL for example.
The MidPoint function is one of those little operations that short cut some pretty basic logic, same goes for the Min/Max functions. Which are also supported.
[pbcode]
print MinVal(100,200)
print MaxVal(100,200)
print MinVal#(100,200)
print MaxVal#(100,200)
; test pre-solver for the mid point function
print midpoint(100,200)
print midpoint(100.0,200)
print midpoint(100 ,200.0)
print midpoint(100.0 ,200.0)
[/pbcode]
PlayBASIC V1.64P Beta 26 / 27 - Testing Calling VM instructions from DLL interface
When we build a DLL with PlayBASIC to DLL,that code hooks backs into the PlayBASIC runtime to execute any commands you call. The commands live in tables basically and the translator uses the table data to build calls for you. The legacy VM uses a part table and part unrolled decisions to look up and call instructions. What I've been thinking is the DLL tables could be used to help short cut that even more, at least for most of the main command sets. This should reduce the calling overhead on the instruction in question. Meaning less VM overhead and more time spent executing command set functions
To test this, I've been working with the Bank Command set, writing a generic function caller for the DLL interface. So the VM traps the command block and then just passes it to the generic caller. My gut feeling was this might well add extra overhead to simpler higher level operations, which would even out in the end. Any initial fears seems to be have been somewhat put to rest, with the experimental build (beta 27) being able to out preform beta 26.
On my 8 year old athlon system the code bellow runs each test in approximately 2 milliseconds per test using Beta26. Beta27 reduce that to around 1.6/1.7 milliseconds per test. Adding around 15 FPS to the test.
[pbcode]
Max =10000
Do
cls
frames++
Bank=NewBank(Max+64)
t=timer()
for lp =0 to Max-1
ThisByte=PeekBankByte(Bank,lp)
next
tt1#+=Timer()-t
print tt1#/frames
t=timer()
for lp =0 to Max-1
ThisByte=PeekBankWord(Bank,lp)
next
tt2#+=Timer()-t
print tt2#/frames
t=timer()
for lp =0 to Max-1
ThisByte=PeekBankInt(Bank,lp)
next
tt3#+=Timer()-t
print tt3#/frames
t=timer()
for lp =0 to Max-1
POkeBankByte Bank,lp,ThisByte
next
tt4#+=Timer()-t
print tt4#/frames
t=timer()
for lp =0 to Max-1
POkeBankWord Bank,lp,ThisByte
next
tt5#+=Timer()-t
print tt5#/frames
t=timer()
for lp =0 to Max-1
PokeBankInt Bank,lp,ThisByte
next
tt6#+=Timer()-t
print tt6#/frames
; pokebankstring Bank,10,"Hello World",0
; s$=PeekBankString(BAnk,10,0)
deletebank Bank
print s$
print fps()
Sync
loop
[/pbcode]
PlayBASIC V1.64P BETA #27 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (8th,Mar,2014)
PlayBASIC V1.64P Beta #27 continues with it's PlayBASIC to DLL alignment so many changes related around cleaning up byte code / fixes mainly. But that's not the only thing this build includes, Beta 27 is first built to share the DLL interface with the internal VM. This means the VM and now call some commands directly without having to solve them. So far only the BANKS, SOUND and MUSIC sets have been converted to this form, but the idea is to convert as many of possible.
The advantage of sharing the DLL interface with the VM, is we not only get faster function calling from the VM but it helps reduce the size of the VM. Just converting 3 mid sized command sets pulls 16->20K from the runtime. I suspect we'll be able to trim a lot more when some of the bigger sets are done. At this point I just want to be sure it's all working as expected.
Download
Download PlayBASIC V1.64P Beta 27 (8th,Mar,2014) (old file removed)
PlayBASIC V1.64P Beta 28 - Expanding Support For Calling VM instructions via the DLL interface
The previous version (#27) includes the first few tastes of refreshed VM calling convention, so today's objective was to extend the support across more of the core command sets, as I write this, FONTS, RGB, 2D graphics General & SHAPES are using the new method. Everything has progressed fairly easily as most of the hard work was done when building the internal DLL interfaces some months ago. All I really have to do to hook these up, is strip out the old legacy opcode trapper for each command and replace it with the new one. The only problem I ran into so far, was some speed issues with DOT/FASTDot, which initially perform worse due to the change. The overhead they experience is from the 'wrapped' nature of the command set, it should be possible to get trim some of that fat away, but for now i've reverted that change. All the other commands in that library (2d drawing) are handled the new way and do perform better for it.
So how fast is it ? - Well, in the RGB benchmark bellow, beta 28 is around twice as fast as previous editions. Not too bad for a change that's really a by-product of PB2DLL :)
[pbcode]
Max =10000
Do
cls
frames++
print "Rgb()"
t=timer()
for lp =0 to Max
a=rgb(lp,lp,lp)
next
tt1#+=Timer()-t
print tt1#/frames
print "ARgb()"
t=timer()
for lp =0 to Max
a=argb(lp,lp,lp,lp)
next
tt2#+=Timer()-t
print tt2#/frames
print "RgbA() RgbR() RgbG() RgbB()"
t=timer()
for lp =0 to Max
a=rgba(lp)
a=rgbr(lp)
a=rgbg(lp)
a=rgbb(lp)
next
tt3#+=Timer()-t
print tt3#/frames
print "RgbFADE"
t=timer()
for lp =0 to Max
a=rgbfade(lp,50)
next
tt4#+=Timer()-t
print tt4#/frames
print "RgbAlphaMult"
t=timer()
for lp =0 to Max
a=rgbalphamult(lp,lp)
next
tt5#+=Timer()-t
print tt5#/frames
print "RgbAlphaAdd"
t=timer()
for lp =0 to Max
a=rgbalphaadd(lp,lp)
next
tt6#+=Timer()-t
print tt6#/frames
print fps()
Sync
loop
[/pbcode]
PlayBASIC V1.64P BETA #28 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (10th,Mar,2014)
PlayBASIC V1.64P Beta #28 goes further with VM calling convention changes, moving the FONT, RGB, SCREEN, 2D Graphics (general) and Shape command set to the new form. Generally everything has gained in terms of performance. Some functions will benefit more than others, which is to be expected. For example, calling a colour function like RGB() turns out to be about 50% faster, where as calling a function like GetScreenWidth() might only be about 10->15% faster.
You should expect a steady flow of betas as the transformation takes place. It's best to test them incrementally, rather than waiting and trying to run the final on your code, as there are bound to be differences that have gone unnoticed in the DLL function interfaces. Testing small steps lets us solves what works and what doesn't during the process.
Download
Download PlayBASIC V1.64P Beta 28 (10th,Mar,2014) (Obsolete version removed)
PlayBASIC V1.64P Beta 29/30 - Expanding Support For Calling VM instructions via the DLL interface
Today was something of a small victory, translating 5 command set banks to the new format. Starting with the Math Intersections library, moving to the Camera commands/functions, onto the scene commands and finally through the World commands. The progress was fairly painless, it's just making sure everything lines up in the tables. When they do, things seem to work out of the box, if not, they don't.. Have found the odd command/function that does behave differently mostly due to the wrappers having incorrect parameter types. Nothing really big through, just little things. There's bounf to be more of them though !
One of the best things about converting the VM to use the internal DLL function interfaces for command sets, is it means they'll be functionality identical. So calling CLS from the VM or from your DLL, means they're both running the exact same code. In previous editions of the P upgrade that was dependent upon the function, so they weren't always the same. Moreover this has a flow on effect also, meaning less PB2DLL testing is required, since if it works in normal PB, they it's 99.9% likely it's going to work from an exported DLL too.
So timing today's build 29/30 against 26 for the following and we win back 15->16 milliseconds across the test.
[pbcode]
Max =10000
Gosub MakeWorld
Cam=NewCamera()
Do
cls
frames++
print "GetCameraX & Y()"
t=timer()
for lp =0 to Max
x=getcamerax(Cam)
y=getcameray(Cam)
next
tt1#+=Timer()-t
print tt1#/frames
print x
print y
print "POsitionCamera()"
t=timer()
for lp =0 to Max
positioncamera cam,100,200
next
tt2#+=Timer()-t
print tt2#/frames
print "MoveCamera()"
t=timer()
for lp =0 to Max
Movecamera cam,1,1
next
tt3#+=Timer()-t
print tt3#/frames
print "Get Camera Width & Height"
t=timer()
for lp =0 to Max
w=getcamerawidth(Cam)
h=getcameraheight(Cam)
next
tt4#+=Timer()-t
print tt4#/frames
print "World Info"
t=timer()
for lp =0 to Max
result=GetWorldStatus(MyWorld)
result=GetWorldElements(MyWorld)
next
tt5#+=Timer()-t
print tt5#/frames
print "GetWordlClosestPOint()"
t=timer()
for lp =0 to Max
result=GetWorldClosestPoint(MyWorld,mx#,my#,x1#,y1#,x2#,y2#)
next
tt6#+=Timer()-t
print tt6#/frames
print "Ray Intersect World()"
t=timer()
for lp =0 to Max/2
result=RayintersectWorld(MyWorld,100,100,200,200)
next
tt7#+=Timer()-t
print tt7#/frames
print lp
print fps()
Sync
loop
MakeWorld:
; ==============
; Part #1 - create a world to collide with
; ==============
; Get the Screen size and use it as the world size
WorldWidth=GetScreenWidth()
WorldHeight=GetScreenHeight()
; create a Camera
MyCamera=NewCamera()
; Create world
MyWorld=NewWorld()
CaptureToWorld MyWorld
; draw a series of boarder line for this world
Line 0,0,worldwidth,0
Line worldwidth,0,worldwidth,worldheight
Line worldwidth,worldheight,0,worldheight
Line 0,worldheight,0,0
randomize 1000
; draw a series of polygon shaped obejct into the world
For lp=1 To 10
xpos#=50+Rnd(worldwidth-100)
zpos#=50+Rnd(worldheight-100)
size=RndRange(30,100)
angle=Rnd(359)
Make_Convex(RndRange(3,20),xpos#,zpos#,Size,angle)
Next lp
; Partition The world up into 32 by 32 cells
PartitionWorld MyWorld,32
; Tell PB to return to Immediate drawing mode
DrawGFXImmediate
return
; This function creates a convex polygon shape
Function Make_Convex(edges,xpos#,ypos#,Size,angle)
sa#=360.0/edges
c=RndRGB()
For lp=0 To edges-1
a#=angle+(lp*sa#)
x1#=xpos#+CosRadius(a#,size)
y1#=ypos#+SinRadius(a#,size)
If lp<(edges-1)
a#=angle+((lp+1)*sa#)
Else
a#=angle
EndIf
x2#=xpos#+CosRadius(a#,size)
y2#=ypos#+SinRadius(a#,size)
Line x2#,y2#,x1#,y1#
Next lp
EndFunction i
[/pbcode]
PlayBASIC V1.64P BETA #30 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (13th,Mar,2014)
Beta #30 continues with the VM calling convention changes. This version has most of the command sets converted, including the main ones like IMAGES, SPRITES, MAPS and so on. Read the history for a detailed list of VM changes.
Be warned though, I've noticed a few gremlins in some examples and are expecting users to help find the differences !
Download
Download PlayBASIC V1.64P Beta 30 (13th,Mar,2014) - (Obsolete Version Removed)
PlayBASIC V1.64P BETA #31 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (16th,Mar,2014)
Beta #31 continues with the VM calling convention changes extending support the input commands Mouse, KeyBoard, Joystick, File SYSTEM, File STREAM, File Name and ReadDir commands.
It also includes a number fixes from the conversion, there's still a few oddities here and there and probably a lot more than than that, so get testing !
Download
Download PlayBASIC V1.64P Beta 31 (16th,Mar,2014) (Obsolete Version Removed)
PlayBASIC V1.64P Beta 32 - Testing Testing Testing
Progress has been super slow this last week due to amount of testing required, been able to trap a lot of issues with the DLL interface command sets, meaning those commands will function the same way internally and externally now, but there's still problems with some programs, like in 'For Foxes Sake' after the user picks up the paint brush the peeks/pokes to the map seem to go a little haywire. Having not written it, i'm struggling to follow the logic to try and isolate where the issue originates form. But that's about only the big demo I've run that misbehaves today, that i'm aware of :)
Taking the axe to the VM has meant about a 200K reduction in the final runtime sizes. So the current test runtimes for PV1.64P are now smaller than the V1.64O release runtimes. So it'll be smaller and faster.. can't complain about that !
PlayBASIC V1.64P Beta 32 - Testing Continued
Today is really the last day i can afford to spend on testing, have found a few commands that weren't functioning, like SpritesInShape because the caller didn't understand array fields. Actually cleaned the up the command somewhat also, just making sure it won't crash if passed an array that doesn't exist, or is the wrong type. The VM is ambiguous when passing arrays and complex structures, so it's possible to pass commands structures of the wrong type, which need to weeded out at runtime. Generally the type is uses as the reaction.
PlayBASIC V1.64P BETA #36 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (8th,Apr,2014)
PlayBASIC V1.64P Beta #36 completes the VM calling convention changes, as well as includes some bug fixes to the byte code libs. Ran into a strange problem with the byte code libs where the exported byte code could be hundreds of megabytes in size, turn out to be the resizing routines being a tad over jealous when expanding the buffers.
This version also includes a subtle change to the compiler when returning errors. Previously when the compiler found an error, the compile dialog would stop and wait for some input from the user, but this is now gone in favor of just using the IDE for this. The stop could be problematic in PB2DLL when an error occurs in the input source code.
Download
Removed - Newer betas on next page
PlayBASIC V1.64P Beta 38 - Loopy Loops
After much head scratching it was decided that the VM's instruction set needed a few alterations with it's looping instructions. These changes are two fold, the parser now does a better job at producing cleaner input parameter data and the instructions produced are now more stream lined. Producing better code, is better for everything down the line from running the code through the VM and thus any translations. The translation stuff is really why these changes need to be made now, since the original parser would use generic instructions where some data was pre-computed. From the translators perspective, this made it very difficult to accurately detect those loops in a single pass.
Today's changes introduce some new high level instructions to the VM. These changes make it trivial to accurately pin point the set up code in a FOR/NEXT looping blocks. I've already added a decoder to PB2DLL which locates the new opcodes and builds a export string in the dissassembly. The detection and output are working fine, but it's here that I noticed there's a few extra moves creating into the output code than need be. Which mostly happens when a loop is using literals. In previous editions the parser would drop an extra move prior to the loop entry point. The same can happen in the destination value expressions also. These things are easily tweaked out, just hadn't noticed them before.
glad to see you're not watching the new tv box too much.Roll on PBDLL. :-)
Quoteglad to see you're not watching the new tv box too much.Roll on PBDLL. :-)
Well it is (well was) holiday time here.. so yeah i've been watching and playing a bit more than normal..
PlayBASIC V1.64P Beta 38 - For / Next Loop updates If you didn't already know, it's been Easter holidays here which has just come to a close, so only started firing up the compilers today. Last time I was working on the tuning the compiler and VM to use the new looping setup codes for FOR/NEXT loops. These changes have were translated across to PB2DLL when I was happy with the new structures. The changes are much easier for PB2LL parser to accurately detect what's going on in the program in regards to loops. But not only that, the new format allows us to make more optimizations to the assembly.
Tonight I've been back working on the parser in the PlayBASIC compiler, as when converting the code to assembly, there's often these extra move operations that would end up in the byte code first and thus translated assembly. Surprisingly it generally happened what a for loop's (start / end) were both literal. For some reason it'd drop them into temps and then pull them into the loop structures internal registers. Which appears to be some left over instruction set behaviors that are no longer necessary. Older versions of the VM worked differently than today, in particular when dealing with literals. Now they can be treated just like variables, so don't they need to be treated special ways.
Something you might not be aware of is that when a for/loop is started, there's a comparison between the Start and End of loop. If Start is bigger than the end, the execution jumps to the beyond the matching next.
For example,
[pbcode]
For lp =0 to 100
print lp
next
[/pbcode]
So there's an indivisible screening wrapped around loop entry, which might look at like this in PB style code.
[pbcode]
if 0<=100
For lp =0 to 100
print lp
next
endif
[/pbcode]
One of the new benefits of the FOR/NEXT replacement opcodes, is the export parser can detect constant behaviors and produce code accordingly. So the comparison behind the Start /End loop counters can actually be made at compile time when they're both literal. Removing those lead in comparisons from the output code. The same goes for the storing them in internal VM registers, saving more set up code.
Being able to trap literals helps with STEP loops also. When a variable is used in for/next/step loop, the looping structure has constantly query what sign the STEP, then clip the loop counter based upon it. If the sign of step is known at compile time, then the loop can be created with this knowledge ahead of time. Removing more redundancy from the final translated assembly (in PB2DLL)
PB is pretty flexible with FOR/NEXTS allowing integer and floating point counters with variable step directions in both. People rarely use floating point loops, but since the VM supports it, the exported assembly through PB2DLL should also. Dropped in the standard by one loop structure earlier today and have just started adding the variable STEP stuff with floats. It's painful purely because of the horrible fpu instruction set in x86 chips...
PlayBASIC V1.64P BETA #39 (Retail Compiler Only Beta) (30th,Apr,2014)
Beta #39 introduces a bunch of subtle but equally important changes, starting with the newly replaced FOR/NEXT/STEP parser and VM instruction set, there's also a few changes to the VM close down behavior. The close down changes are due to a strange issue i've been having with PB2DLL where the PB2DLL EXE would crash on exit when the program wasn't registered (worked fine once you entered your serial).
So i've been chasing the close down issue most of the day, it appears that some typed arrays can somehow contained data that wasn't a typed array container. How that's the possible is a mystery at the moment, but i've included some more screening in the clean up code to make sure it's releasing the array an not some of random bank of that data that something else was/is using. Getting this right is more important now than ever, thus is because of the way type deletion works in the runtime, so we have to make sure it's releasing data that makes sense, as if it doesn't it'll die.
The real question is how is the bad array data was/is getting into the arrays in the first place, which i'm not 100% on at this point. So i've added some debug messages to the debugger console (F7 to run, then click on the console tab) to help the community track where else these quirks put up.. Does it happen at runtime ? or only closing down the VM..
So get testing !!!!!!
Download
Old beta removed
PlayBASIC V1.64P BETA #41 (Retail Compiler Only Beta) (11th,June,2014)
Beta #41 includes some string function replacements including GetFileName$(), GetFolderName$(), GetDeviceName$() and GetFileExt$(). The existing where legacy functions and internally needed to be converted from VM2 ->VM1 format then back to VM2 strings. Which obviously very slow and a potentially buggy process.
The show just how slow that process can be we have the standards performance over time test. The code first demo's that the functions work, then brute force calls them 10000 odd times. Running this code on BETA 39 and gives runtime performance of about 1FPS.. Where as running on Beta 41 and it runs and 60fps (Althon 3000 FX64 system)
Those performance benefits are not just from the VM though, DLL built with PB2DLL call the internal PB command sets. So any performance gain from the function will be gained from compiling the code to DLL also..
[pbcode]
s$="C:\Stuff\MoreStuff\yeah.exe"
; s$="C:notehead.txt"
print GetDeviceName$(S$)
print GetFolderName$(s$)
print GetFileName$(s$)
print GetFileExt$(s$)
print FileExist(S$)
print FolderExist(GetFolderNAme$(S$))
print asc("\")
sync
waitkey
Max=10000
Do
cls
frames++
t=timer()
for lp =0 to max
result$= GetDeviceName$(S$)
next
tt1#+=timer()-t
print result$
t=timer()
for lp =0 to max
result$= GetFolderName$(S$)
next
tt2#+=timer()-t
print result$
t=timer()
for lp =0 to max
result$= GetfileName$(S$)
next
tt3#+=timer()-t
print result$
t=timer()
for lp =0 to max
result$= GetFileext$(S$)
next
tt4#+=timer()-t
print result$
print tt1#/frames
print tt2#/frames
print tt3#/frames
print tt4#/frames
print Fps()
sync
loop
[/pbcode]
Download
removed.
PlayBASIC V1.64P BETA #41b (Retail Compiler Only Beta) (12th,June,2014)
Beta #41b restores GetFileName$() to the same behavior as old editions. In Beta 40 it'd not return anything if there wasn't a \ or colon in the path.
Download
Obsolete, newer release bellow
PlayBASIC V1.64P BETA #42 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (24th,Jun,2014)
Beta #42 this build both corrects a few nasty little issues and of course adds some limited support for OPENGL
NOTE: OpenGL rendering requires the G2D library..
Download:
Obsolete Beta Removed
PlayBASIC V1.64P - Building Release
Well... after something of a delay I've started building the all the release versions for the V1.64P update. There's not enough time tonight for a release, so suspect that'll come later today possibly Sunday night (my time). Was planning on importing a few more VM changes, but they can wait until the next round of updates. This version will sync up with current PB2DLL releases, so there's no need to update that at this time.
PlayBASIC V1.64P2 BETA #01 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (7h,Oct,2014)
Beta #01 addresses a few bugs in the sprite commands as well as addressing pass #1 parsing issue that wouldn't allow comments after Function/Psub prototypes. While single comments are supported now, comment blocks aren't at this time.
Eg..
[pbcode]
Function DoStuff(A,B,C) ; My Comment
EndFunction
[/pbcode]
Download:
Old beta Removed.
PlayBASIC V1.64P2 BETA #02 - Pointer Corrections
Somewhere during V1.64P (or perhaps later) a number of odd parsing issues have appeared with pointers. Pointers are internally one of the foundational elements of the runtime, the issue has been with the higher level exposure of these. In terms of the parser they've always been (and still are) something of after thought which apparently makes them even more susceptible to parsing changes. Fixed a couple of odd problems that seemed to occur during math operations between them as well as de-referencing (peeking) them..
So code like this is working again..
[pbcode]
; declare this as a generic (type less) pointer
Dim GenericPointer As Pointer
; Allocate a new bank and get the address of the bank for our pointer
GenericPointer= GetBankPtr(NewBank(1000))
; Write some integer data into this memory (assumes type from the right hand data type)
*GenericPointer = $11223344
; Recast our generic pointer as byte pointer and return this byte from memory as a hex string
print hex$(*byteptr(GenericPointer))
; do the same as above, but from the next byte and so on
print hex$(*byteptr(GenericPointer+1))
print hex$(*byteptr(GenericPointer+2))
print hex$(*byteptr(GenericPointer+3))
Sync
WaitKey
[/pbcode]
PlayBASIC V1.64P2 BETA #02 - Pointer Corrections Continued
Last week was full of fun, if not wasn't out on the mower or wrestling with our tax return then i was hunting parsing issues concerning pointers. Fixed a number oddities earlier in the week, only to discover those fixes broke other seemingly unrelated code later in the week. Initially it seem unrelated, but upon close inspection there was generation common function that could leave the expression in the state that following generators would make incorrect assumptions upon.
One such case occurred, when the parser was resolving user defined type array fields, which would call this function and occasionally get back some strange data. Making them do everything from function correctly to completely fail. I've actually noticed something like this oddity before in the byte code diss-assemblies, but was unsure if that an issue in the compiler, runtime or dissassembly. The program ran so one would assume the latter, but apparently not. Which is fairly rare really.
The following is the current test code that's running in the latest Beta #2 which i'll uploader later
[pbcode]
Test01_GenericPointerCasting()
TEst02_TypedPointers()
TEst03_TypedArrays()
end
; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------
Function Test01_GenericPointerCasting()
cls
print "Test #01 - Generic Pointer Read Writing"
; Allocate a new bank and get it's address in memory
Dim GenericPointer As Pointer
GenericPointer= GetBankPtr(NewBank(1000))
; Write sopme data into this memory
*GenericPointer = $11223344
print Int(GenericPointer)
print hex$(*byteptr(GenericPointer))
print hex$(*byteptr(GenericPointer+1))
print hex$(*byteptr(GenericPointer+2))
print hex$(*byteptr(GenericPointer+3))
GenericPointer=GenericPointer+4
*GenericPointer = $11112222
print Int(GenericPointer)
print hex$(*wordptr(GenericPointer))
print hex$(*wordptr(GenericPointer+2))
GenericPointer=GenericPointer+4
*GenericPointer = $AABBCCDD
print Int(GenericPointer)
print hex$(*intptr(GenericPointer))
GenericPointer+=4
*GenericPointer = $AABBCCDD
print Int(GenericPointer)
print hex$(*intptr(GenericPointer))
print "Press Any Key"
flushkeys
Sync
WaitKey
EndFunction
; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------
Type PersonInfo
Name$
Age
Address$
EndType
Type TestType
Status
Counter
x#,y#,z#
IntArray(10)
FltArray#(10)
StrArray$(10)
Person as PersonInfo
EndTYpe
Function TEst02_TypedPointers()
cls
print "Test #02 - Typed Pointer Testing"
Dim Me as TestType Pointer
Me = new TestType
print "Me Address:"+Str$(Int(Me))
Me.Status = true
Me.Counter = 1
Me.Counter = 1.0
Me.Counter ++
Me.X =ME.X +100
Me.X =100+ME.X
Me.X += 100
Me.Y += me.x*10
Me.Z += me.y*22
Me.Z += me.y/22
Me.Z += 22/me.z*me.z
Me.Z += 22*me.z
; array fields
For lp =0 to 5
me.IntArray(lp)++
me.IntArray(lp)+=1+me.IntArray(lp)
me.FltArray(lp)++
me.FltArray(lp)+=1.23+me.FltArray(lp)
me.StrArray(lp)= "Hello World"
me.StrArray(lp)++
me.StrArray(lp)+= "More Text"+me.StrArray(lp)
me.Person.Name ="Name of person"
me.Person.Age =101
next
print ".Status:"+Str$(Me.Status)
print ".Counter:"+Str$(Me.Counter)
print " .X#:"+Str$(Me.x#)
print " .Y#:"+Str$(Me.y#)
print " .Z#:"+Str$(Me.z#)
For lp =0 to 5
print lp
print " >"+str$(int(me.IntArray))
print " >"+str$(me.IntArray(lp))
print " >"+str$(me.FltArray(lp))
print " >"+(me.StrArray(lp))
next
print " .Person:"+Str$(int(Me.Person))
print " .Person.Name:"+(Me.Person.Name)
print " .Person .Age:"+Str$(Me.Person.Age)
TestPointer(Me.Person)
print "Press Any Key"
flushkeys
Sync
WaitKey
EndFunction
Function TestPointer(This as PersonInfo Pointer)
print " .Person:"+Str$(int(This))
print " .Person.Name:"+(This.Name)
print " .Person .Age:"+Str$(This.Age)
EndFunction
; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------
Function TEst03_TypedArrays()
cls
print "Test #03 - Typed Array Tests"
Dim Me(10) as TestType
Me(1) = new TestType
print "Me(1) Address:"+Str$(Int(Me(1).TestType))
Me(1).Status = true
Me(1).Counter = 1
Me(1).Counter = 1.0
Me(1).Counter ++
Me(1).X =ME(1).X +100
Me(1).X =100+ME(1).X
Me(1).X += 100
Me(1).Y += me(1).x*10
Me(1).Z += me(1).y*22
Me(1).Z += me(1).y/22
Me(1).Z += 22/me(1).z*me(1).z
Me(1).Z += 22*me(1).z
; array fields
For lp =0 to 5
me(1).IntArray(lp)++
me(1).IntArray(lp)+=1+me(1).IntArray(lp)
me(1).FltArray(lp)++
me(1).FltArray(lp)+=1.23+me(1).FltArray(lp)
me(1).StrArray(lp)= "Hello World"
me(1).StrArray(lp)++
me(1).StrArray(lp)+= "More Text"+me(1).StrArray(lp)
next
me(1).Person.Name ="Name of person"
me(1).Person.Age =101
print ".Status:"+Str$(Me(1).Status)
print ".Counter:"+Str$(Me(1).Counter)
print " .X#:"+Str$(Me(1).x#)
print " .Y#:"+Str$(Me(1).y#)
print " .Z#:"+Str$(Me(1).z#)
For lp =0 to 5
print lp
print " >"+str$(int(me(1).IntArray))
print " >"+str$(me(1).IntArray(lp))
print " >"+str$(me(1).FltArray(lp))
print " >"+(me(1).StrArray(lp))
next
print " .Person:"+Str$(int(Me(1).Person))
print " .Person.Name:"+(Me(1).Person.Name)
print " .Person .Age:"+Str$(Me(1).Person.Age)
TestPointer(Me(1).Person)
print "Press Any Key"
flushkeys
Sync
WaitKey
EndFunction
[/pbcode]
Download:
Download PlayBASIC V1.64P2 Beta #2 (3rd,Nov,2014) - ( Obsolete Beta Removed )
PlayBASIC V1.64P2 BETA #04 - Debugger - Controlling Auto Allocation Behavior
Even though automatic type allocation is one of those things that's been hidden away deep inside PlayBASIC now for the best part of a decade, i'd be surprised if many people actually knew it occurs. Basically any time you declare a typed variable , or typed array, the runtime includes some hand holding code with will prevent you code from failing when you attempt to access a type that's not been allocated.
Here's an example,
[pbcode]
Type pos
x#,y#,z#
EndType
dim a as pos
a.x = 45
print a.x
sync
waitkey
[/pbcode]
Notice after the declaration we're writing to a type before we've written a NEW object in it ? That's automatic type allocation right there. The VM traps this situation and automatically NEWS the type structure so we've something to write into. Something similar occurs when reading a none existent type, where is the opcode returns a NULL.
What today's addition does is allows the user to toggle the runtime type allocation when running in debug mode. When you turn it off, it'll error on such lines. Which might not seem all that useful, until you start writing DLL libraries with PlayBASIC2DLL, since the auto allocation isn't supported in the DLL's at this time.
PlayBASIC V1.64P2 BETA #04b (Released) (26th Nov,2014)
Beta #04 makes a few subtle changes. This is the first version to include a manifest resource which will help PB when running on newer operating systems and with some of new libraries such as PB Dialogs2, which is another replacement for the PB dialogs library. The Dialogs 2 library is same in principal to the first, but smaller and more up to date.
Some other changes found in this build are some more compiler optimizations, which can resolve array pointers with literal array indexes, plus even a new debugger mode that allows you to toggle if the runtime allows 'auto type allocations' or not. This mode is enabled by default (so your programs run as normal!), there's no compiler switch at this time, only a debugger switch. Whenauto allocation is turned off the runtime will halt execution if your program tries to access a type variable / type array that hasn't been manually allocated with the NEW operator.
[pbcode]
#break
Type Stuff
x,y,z
EndType
Dim me as stuff
me.x = 100
me.y = 100
me.z = 100
Sync
waitkey
[/pbcode]
Code like this will only run when automatic type allocation is enabled, if you run this in debug mode and turn it off, you'll get a runtime error. This is because the DIM statement allocates the variable/array container and not actually the TYPE instance. So the structure is created, but no types have been allocated and stored in it. Which is what allows you to store different types in the same variable/list/array (inheritance)
[pbcode]
#break
Type Stuff
x,y,z
EndType
; builds the container this variable uses at runtime
Dim me as stuff
; allocate a type handle and store it in ME() container.
Me = new STUFF
; proceed as normal
me.x = 100
me.y = 100
me.z = 100
Sync
waitkey
[/pbcode]
Download
Obsolete beta removed
PlayBASIC V1.64P2 BETA #06 - Better Literal Casting When Writing to UDT Pointer fields.
While working on the PB2DLL machine code translator ran into a could of issues, the first was that the compiler didn't tag and export pointers flags correctly. Without those, it made it impossible to detect if pointer was user defined or a VM temp register. This is necessary when you wish to resolve UDT pointers and their fields when they appear in sequences. The other issue was that there was some bogus casting when using operators on UDT fields and literals. The casting would throw and extra instruction that wasn't necessary.
The following example benchmarks 30% quicker in tonight's build than any previous edition, which will of course have a flow of effect into PB2DLL code generation. What was happening, is if you assigned an Integer to a float field say, the process would insert a cast. Which is fine, when it's an integer variable, but if it's an integer literal, then the compiler should recast it compile time, avoiding the casting at runtime..
[pbcode]
type Stuff
x#,y#,z#
a,b,c
Endtype
dim me as stuff pointer
me = new stuff
max=10000
Do
Cls
Frames#++
t=timer()
For lp=0 to max
me.x#=100
me.y#=100
me.z#=100
me.x#+=5
me.y#+=5
me.z#+=5
next
TT1+=(timer()-t)
print tt1/frames#
t=timer()
For lp=0 to max
me.a=100.0
me.b=100.0
me.c=100.0
me.a+=1.0
me.b+=1.0
me.c+=1.0
next
tt2+=(timer()-t)
print tt2/frames#
Sync
loop
[/pbcode]
PlayBASIC V1.64P2 BETA #07 - Constant Colour Alpha Blend Speed Ups
An hour of ago hit upon an idea for a possible speed up when doing variable alpha blending with a constant colour (inkmode 16), so when I had a look at the graphic engine noticed there wasn't any MMX support for this operation, so decided to add some and try the idea out. The concept is simple you can pre-blend the input colour and do the post blend on with packed multiply. Which gives us an inner loop of about 8->9 assembly instructions per 32bit pixel, but only 1 multiply per pixel. After a bit of messing around, with the routine not working or blending in reserve to the old routine, it's up and running. Performance wise the replacement routine is about twice as fast as the previous routine.
The demo bellow is potentially blending 14647680 32bit pixels. On my legacy test system it only renders at about 10->11fps, the new version runs at 19fps. Might be able to claw back a few extra cycles when I look at the routine(s) later. Would be nice to break 20 on this old box.
[pbcode]
Screen=NewImage(getScreenWidth(),GetSCreenHeight(),2)
; build a table of colours
Dim Colours(1024)
for lp=0 to 1024
Colours(lp)=rndrgb()
next
; --------------------------------------------------------------------
Do
; --------------------------------------------------------------------
rendertoimage screen
cls $334466
Size=100
xpos=0
ypos=0
pixelcount=0
; set ink mode to variable alpha blend with target
inkmode 1+16
for Alpha =0 to 255
;
inkalpha alpha/255.0 ;512.0
; draw box using the current inkmode
boxc xpos,xpos,xpos+size,ypos+size,true,Colours(Alpha)
; tally the number of pixels
PixelCount+=(Size*size)
; move boxes position, so we're not drawing completely over each previous render
xpos++
ypos++
; increase the size of the box
Size++
next
inkmode 1
rendertoscreen
drawimage screen,0,0,false
text 0,0,"Pixels Blended:"+Str$(pixelcount)
text 0,20,"MmX:"+Str$(GetGFXMMX())
text 0,40,"Fps:"+Str$(fps())
if spacekey()
GFXMMX 1-GetGFXMMX()
flushkeys
endif
Sync
; --------------------------------------------------------------------
loop
; --------------------------------------------------------------------
[/pbcode]
EDIT #1: The initial alpha blender was only handling a single pixel per loop, converting it to parallel gives us another couple of FPS back on this system, so it's now in the 21/22 range for the same number of pixels (another 5->6 milliseconds faster).
PlayBASIC V1.64P2 BETA #08 - Constant Colour Alpha Blend Speed Ups #2
Updated the strip render routines to use the newer Scaler and MMX logic for variable alpha blending. The changes has resulted in doubling basically of the alpha performance of those effects. Most convex render routines use the strip list back end, so circles/boxes/triangles/quads all use the same filler, but filled Shapes use the legacy draw strip interface since the order of spans isn't necessarily linear. That interface has been tuned a few times, but when you're calling it potentially a hundred thousand times (and above) like in the following demo, then there's going to be a loss in purely function calling/passing overhead. Which is more than you might think, even in assembly.
The code bellow is much like the previous example, but this time we're waving the diagonal row and swapping boxes for filled shapes.. Each shape has a variable alpha blend level. Running in today's build of PB1.64P2 it's twice as fast V1.64P and about 60% faster than V1.64O..
[pbcode]
#include "blitimage"
LoadFont "Veranda",1,24,8
ClsColour=$334455
Screen=NewImage(getScreenWidth(),GetSCreenHeight(),2)
rendertoimage Screen
cls $334466
; build a table of colours
Dim Colours(1024)
for lp=0 to 1024
Colours(lp)=rndrgb()
next
Size=128
Shape =MakeBoxShape(0,0,size,size)
shiftshape shape,size/-2,size/-2
; --------------------------------------------------------------------
Do
; --------------------------------------------------------------------
rendertoimage screen
xpos=-50
ypos=-50
pixelcount=0
; set ink mode to variable alpha blend with target
inkmode 1+64
inkmode 1+16
lockbuffer
rotateshape shape,angle#,1.25
WaveAngle#=wrapangle(WaveAngle#,1)
for Alpha =0 to 750
;
inkalpha (alpha and 255)/255.0 ;512.0
ink Colours(Alpha)
; compute the size of the wave at this point along the line
dist#=cos(WaveAngle#+Alpha)*sin(Angle#)*100
; add this position to the origin position
nx=xpos+cos(360-45)*Dist#
ny=ypos+sin(360-45)*(Dist#)
drawshape Shape,nx,ny,2
; move origin position, so we're not drawing completely over each previous render
xpos++
ypos++
; increase the size of the box
;Size++
next
unlockbuffer
; tally the number of pixels
PixelCount=(Size*size)*lp
inkmode 1+16
inkalpha 0.5+cos(angle#)*0.5
angle#=wrapangle(angle#,2)
; inkalpha 0.25
; draw box using the current inkmode
; boxc 0,0,800,600,true,$605030
;
circlec mousex(),mousey(),size,true,$ff00000
ink $557788
rotateshape shape,angle#,4
drawshape Shape,400,300,2
ink -1
inkmode 1
rendertoscreen
BlitImageClear(Screen,0,0,ClsColour)
text 0,0,"Blending:"+Str$(pixelcount/1000.0)+" K pixels - MMX:"+Str$(GetGFXMMX())+" FPS:"+Str$(fps())
if spacekey()
GFXMMX 1-GetGFXMMX()
flushkeys
endif
Sync
; --------------------------------------------------------------------
loop
; --------------------------------------------------------------------
Function MakeBoxShape(x1,y1,x2,y2)
ThisShape=NewShape(4,4)
SetShapeVertex ThisShape,0,x1,y1
SetShapeVertex ThisShape,1,x2,y1
SetShapeVertex ThisShape,2,x2,y2
SetShapeVertex ThisShape,3,x1,y2
SetShapeEdge ThisShape,0,0,1
SetShapeEdge ThisShape,1,1,2
SetShapeEdge ThisShape,2,2,3
SetShapeEdge ThisShape,3,3,0
refreshshape Thisshape
EndFunction ThisSHape
[/pbcode]
Sounds really good!
PlayBASIC V1.64P2 BETA #08b - Compiler Runtime Null Pointer Errors
After finalizing the ink colour alpha blending stuff, added some runtime trapping to the compiler-runtime when code tries to peek/poke a null pointer. Which just mean that if you try and de-reference a pointer that's null or query or write to a field in UDT pointer, you're more likely to get a runtime error than a crash.
[pbcode]
dim pb as byte pointer
dim pw as word pointer
dim pf as float pointer
dim pi as integer pointer
print *pb
; print *pw
; print *pf
; print *pi
[/pbcode]
Since none of the pointers are set to poke at some allocated memory, they'd be null when you tried and de-ref them. This would normally cash, it still will if the pointer is pointing at memory you've freed or never owned. Can't do much about that.
[pbcode]
Type Stuff
a,b#,c$
Table(10)
EndTYpe
Dim me as stuff pointer
print Me.a;
print Me.b;
print Me.c
print Me.Table(a)
[/pbcode]
Neither the release or debug runtimes will include this functionality, it's just for the compiler-runtime.
PlayBASIC V1.64P2 BETA #08 (Retail Compiler Only Beta) (8th Dec,2014)
Beta #08 has a number of minor command set tweaks with TypeOF(), SpriteInregion() through as well as the pointer instruction sets, which now include stuff like runtime null pointer error trapping, so if you try and re-ref a pointer that's currently null that runtime will step in and give you a runtime error. These are pointers though, and that doesn't prevent you from addressing memory you don't currently own, or that you've since released. If your code does, it'll crash.
Some other changes come in the form of some rendering improvements, in particular when alpha blending a single coloured vector shape with the backdrop. The rendering engine didn't seem to include an MMX version of that fill method, so there's was 2 multiples per pixel. The MMX version pre-computed the blend level of the colour and can therefore double the variable alpha blend speed.
The demo bellow draws a snakey styled object out of alpha blended rotating box shapes, which runs about twice as quick here now. If you wanted to draw a convex polygon, i'd recommend using the QUAD function, which would be more efficient than a shape, since shapes are span render based, convex shapes like Quads/Boxes can be rasterized linearly.
[pbcode]
#include "blitimage"
LoadFont "Veranda",1,24,8
ClsColour =$334455
Screen =NewImage(getScreenWidth(),GetSCreenHeight(),2)
rendertoimage Screen
cls $334466
; build a table of colours
Dim Colours(1024)
for lp=0 to 1024
Colours(lp)=rndrgb()
next
Size=128
Shape =MakeBoxShape(0,0,size,size)
shiftshape shape,size/-2,size/-2
; --------------------------------------------------------------------
Do
; --------------------------------------------------------------------
rendertoimage screen
xpos=-50
ypos=-50
pixelcount=0
; set ink mode to variable alpha blend with target
Scaler#=1
rotateshape shape,angle#,scaler#
WaveAngle#=wrapangle(WaveAngle#,1)
startinterval(0)
lockbuffer
inkmode 1+16 ;4096
for Alpha =0 to 750
;
inkalpha (alpha and 255)/512.0
ink Colours(Alpha)
; compute the size of the wave at this point along the line
dist#=cos(WaveAngle#+Alpha)*sin(Angle#)*100
; add this position to the origin position
nx=xpos+cos(360-45)*Dist#
ny=ypos+sin(360-45)*(Dist#)
drawshape Shape,nx,ny,2
; try these
; box nx,ny,nx+size,ny+Size,1
; ellipse nx,ny,size/2,Size/2,1
; move origin position, so we're not drawing completely over each previous render
xpos+=1
ypos+=1
; increase the size of the box
;Size++
next
unlockbuffer
ThisTime=EndInterval(0)
; tally the number of pixels
PixelCount=((Size*size)*Alpha)*Scaler#
inkalpha 0.5+cos(angle#)*0.5
angle#=wrapangle(angle#,2)
inkmode 1+16
; draw box using the current inkmode
circlec mousex(),mousey(),size,true,$ff00000
ink $8faad7
rotateshape shape,angle#,6
drawshape Shape,400,300,2
ink -1
inkmode 1
rendertoscreen
BlitImageClear(Screen,0,0,ClsColour)
text 0,0,"Blending:"+Str$(pixelcount/1000.0)+" K pixels - MMX:"+Str$(GetGFXMMX())+" FPS:"+Str$(fps())
text 0,20,ThisTime
if spacekey()
GFXMMX 1-GetGFXMMX()
flushkeys
endif
Sync
; --------------------------------------------------------------------
loop
; --------------------------------------------------------------------
Function MakeBoxShape(x1,y1,x2,y2)
ThisShape=NewShape(4,4)
SetShapeVertex ThisShape,0,x1,y1
SetShapeVertex ThisShape,1,x2,y1
SetShapeVertex ThisShape,2,x2,y2
SetShapeVertex ThisShape,3,x1,y2
SetShapeEdge ThisShape,0,0,1
SetShapeEdge ThisShape,1,1,2
SetShapeEdge ThisShape,2,2,3
SetShapeEdge ThisShape,3,3,0
refreshshape Thisshape
EndFunction ThisSHape
[/pbcode]
Download
PlayBASIC V1.64P2 BETA #08 (8th Dec,2014)
PlayBASIC V1.64P2 BETA #09 - AFX Blitter updates
Updated the AFX images/surfaces blitter routines, so they combined the screening logic with MMX support, which is bit of pain as VC++ tends to produce object code that won't run... Anyway, the screening means pixels at are completely translucent (Alpha channel of 0 for each pixel) are ignored and those that are completely opaque (A=255) pass through without needing to read the destination or blend the two pixels together. This will work better for most images, as generally the alpha level of pixels in most images is 0 or 255, of course for images where they're all translucent won't benefit from this change.
The demo & image bellow is one of those brute force situations where it's drawing a few hundred big AFX images on screen. With some of the test scenes it's about 20% faster, but it depends on the amount of pixels that need to be blended.
PlayBASIC V1.64P2 BETA #09b - Rotated AFX Images + Sprites updates
Updated the rendering engine for handling rendering AFX surfaces to 32bit surfaces, the newer code supports alpha screening and opaque pixel short cutting in MMX assembly. The changes only bring a few more fps in the brute force tests over previous V1.64p2 revisions, but that's still a significant 5->6 millisecond saving. Rotating images is generally about twice as slow as a straight none rotated blit. Probably slower are certain angles also, as the data won't cache very well. Way back in the the old 16/32bit days we'd handle such things by using pre flipped images, you can of course do this also. My general advise would be to minimize what you're actually drawing and pre-compute any rotations if possible. Using a CRF in place of images tends to be even faster. So be creative with how you solve such problems.
Interestingly when you draw images via DrawRotatedImage or rotated sprite, DrawSprite with drawmode 2 enabled the rendering backend is the same as you might expect, but there's something of a strange anomaly where rotated sprites have a little more overhead around than they should. Looking at the rendering code, there doesn't really seem to be any huge differences, although it does appear there's no shape clipping which does strike me as odd. I've a feeling object level clipping is done elsewhere in the pipeline, so will have to have a closer look at that later. There might well be some easy gains in to be had in those libraries, but I'm not too keen to start a complete overhaul at the moment.
With the most recent tweaks I'd say upgrade V1.64P2 is coming to an end, it was only intended to tweak those missing functions and or changed behaviors from the previous massive V1.64P update. I say massive, as internally every command has changed, but functionality it's not significantly different to V1.64O say from the users perspective. The true power of it lies in the combination with PlayBASIC2DLL (http://www.underwaredesign.com/forums/index.php?topic=4199.0) companion tool, which can be easily seen in G2D libraries for example. PB2DLL aren't the only benefactors with V1.64P pushing the performance barrier forward constantly.
Will no doubt post the final beta today sometime..
PlayBASIC V1.64P2 BETA #09b (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (14th Dec,2014)
Beta #09b includes the MMX versions of the AFX blend blending code and couple of minor command set tweaks. I'm expecting this to be the release version, so it'd be most helpful if you'd run you code through this prior to release!
Download
Download PlayBASIC V1.64P2 Beta09b (14th,Dec,2014)
(http://www.underwaredesign.com/PlayBasicSig.png)
PlayBASIC V1.64P2 _Retail Upgrade_ Now Available (29th, Dec, 2014)
This release updates any version from PlayBASIC
V1.63w2 to PlayBASIC V1.64P (retail) to the current retail version of PlayBASIC V1.64P. If your current version is
older than PB1.63W (pre June/July 1997), then you may need to install patch
PB1.63w2 prior to this one ! (if you haven't already)
The
PlayBASIC V1.64P2 package includes updates of PlayBASIC Compiler, Release / Debug Runtimes, SLIBS, DOCS (HELP FILES) & IDE V1.17b.
The V1.64P2 release is a relatively minor update to address functionality broken during the massive V1.64P update. Beyond those bug fixes, there are of course more improvements to the compiler & runtime command sets and debugger.
The compiler / runtime time changes are generally improvements to the quality of the byte code the compiler produces within certain circumstances. One that comes to mind, was the ability to completely optimizing out literal fields when querying array structures from typed pointers. So code like the snippet bellow runs better in V1.64P2 than previous versions. Which in turn helps PlayBASIC2DLL produce even faster machine code versions of such routines. So that's a big win !
[pbcode]
Type SomeStructure
IntegerArray(16)
EndTYpe
dim Me as SomeStructure pointer
Me = new SomeStructure
// such field offsets are solved at compile time
Me.Array(0) = 1
Me.Array(2) = 1
Me.Array(3) = 1
Me.Array(4) = 1
Print Me.Array(0)
Print Me.Array(1)
Print Me.Array(2)
Print Me.Array(3)
[/pbcode]
Such compile time optimizations are useful when we want to iterate through structures of data, so rather than bumping the ME pointer between integer fields, we could unroll the inner loop to process groups of integers and access fields at fixed offsets then bump the ME pointer. Which is a more efficient approach generally.
Changes to commands sets that users will find the most useful, can be found in variable Alpha Blending situations, generally filling surface routines are now
twice as fast when performing variable alpha blending in this version, there's also changes to the AFX alpha blending logic which screens the alpha channel value for pixels that are fully translucent or opaque, in either case those are handled with a special case. The performance benefit really comes down to how many pixels in the image need to be alpha blended. But the standard tests had a
10->20% improvement without change..
In terms of Debugging, there's two new subtle changes in the compiler runtime. The first, is the new ability of the runtime to intervene when some pointer opcode attempts peek/poke from a null pointer. Which should generally return a runtime error if that occurs like in the example bellow.
[pbcode]
; declare a ME as type Integer POinter
DIM Me as Integer Pointer
; the runtime will stop before this line is execute as ME is
; will be pointing at ZERO.. Which is memory your program doesn't
; own and would kill your program
print *ME
sync
waitkey
[/pbcode]
The other runtime/debugger change is a mode in the debugger to Enable/Disable automatic type creation when executing a program. The PB runtimes default behavior is to automatically allocate a type if you're writing to a structure that's currently empty. Generally this is handy behavior as it saves you some lines of code, but can be an issue when exporting your programs to DLL since PlayBASIC2DLL doesn't support this behavior. So if you writing library code that you're going to build a DLL of, you'll find this invaluable !
Don't have a retail version of PlayBASIC ? and want to find out more information about PlayBASIC programming > please visit the www.PlayBasic.com (http://www.playbasic.com) and download the free learning edition.
Downloads
[plink] Download PB1.64P2 Retail Upgrade (http://www.underwaredesign.com/forums/index.php?topic=1182.msg28608#msg28608)[/plink] (29th,Dec,2014)
PlayBASIC V1.64P3 BETA #01
Found a couple of interesting little chestnuts in V1.64P2 over the last day. The first was problem with the For/Next Loop pre-screening, which appears to be broken since V1.64P beta 37. When a loop is started, the runtime checks the range to see if there's an overflow up front, if there is the loop is skipped. The logic was correct, but the opcode was writing to an integer variable that was being cast as integer->float->integer. Which means some bit precision is lost. Not to worry, this issue only appears when the loop counter is larger than 2^24, like the example bellow
[pbcode]
For address=$70203040 to $70203040
a++
next
print a
print address
sync
waitkey
[/pbcode]
Obviously it's pretty unlikely you've run into this issue in your everyday code, unless you've been using the packer.pba slib which is also used in other includes like the Map.pba slib.. Which is how this was discovered.. The issue has already been FIXED!
The other fix was an issue that could occur when writing float literals to integer fields in typed pointers. The compiler used to pass this code through to the code generator, which would create a bogus cast operation in the byte-code before the move operation, where all it had to do, is cast the float to integer than dump that out. Of course in this case, it wasn't returning the correct index and you could get anything written into the field.. But that's fixed now also..
PlayBASIC V1.64P3 BETA #03 - Cleaning House
Ok... so before we were rudely interrupted, a Beta #2 build was in the works and looking back it appears to include a built version of the packer library. The packer library just performs some run length encoding, it's purpose was to compress small chunks of raw data in banks. Since maps level array are basically chunks of the raw data the library was used in the maps library to keep the file sizes down. The problem is if the data set is large, then both compress/decompress routines are is fairly slow. Most of the time is a none an issue, but could be if you converted a picture to a map say and the level dimensions ended up almost the size of the original image. So that's been internalized, the thing is, that was few months ago and I can't find the 'test projects that I was using to validate the compressed input/output is the same as the original library, as if it's not some legacy level would probably fail.
Anyway.. pressing on, today has been about cleaning the legacy VM sources up which is far from thrilling but a necessary evil as time goes on. The main instruction set clean up will come post V1.64, which is unlikely going to be smooth sailing. That will a lot of time, so ironing out any V1.64P issues it's important pre V1.65 as we'll be breaking a lot of new (and old) ground.
PlayBASIC V1.64P3 BETA #04 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (28th Apr,2015)
V1.64P3 is all about little fix ups so in Beta #04 you'll find mostly little hidden away errors have been address, the main one would have to be the casting errors that appears in the next FOR/NEXT opcodes with Integers. Effectively the counting was being cast as float at some point which limits the precision to 2^24 (whole number). It's not the sort of thing you're likely to run into in everyday looping code, unless you step through memory addresses in a for/next , which is how it was discovered.
So something like this,
[pbcode]
Size=1024
ThisBank=NewBank(Size)
StartAddress=GetBankPtr(ThisBank)
For Ptr=StartAddress to StartAddress+Size-1
pokebyte ptr,rnd(255)
next
sync
waitkey
[/pbcode]
This would break in older versions of V1.64P if the bank was allocated in memory where it's address range exceeded 24bit (2^24), but it's back the same as it used to be now.
PlayBASIC V1.64P3 BETA #05 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (25th May,2015)
V1.64P3 Beta #05 contains another minor fix up created from an earlier version of V1.64P or there abouts. The main change here is the SpriteInRegion function, which had some dodgy comparisons in the function making it fail with some/most areas for none rotated sprites. This function is also used when detecting if a sprite is inside a camera viewport and possible a few others.
[pbcode]
IMage=Newimage(64,64,2)
RendertoImage Image
cls 255
rendertoscreen
s=newsprite(100,100,Image)
; spritedrawmode s,2
setfps 30
do
cls $203040
speed#=5
if leftkey()
movesprite s,-speed#,0
endif
if rightkey()
movesprite s,speed#,0
endif
if upkey()
movespriteY s,-speed#
endif
if downkey()
movespriteY s,speed#
endif
box 100,100,600,400,false
if spriteinregion(s,100,100,600,400)
print "inside region"
endif
drawallsprites
sync
loop
[/pbcode]
PlayBASIC V1.64P3 BETA #06 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (18th June,2015)
V1.64P3 Beta #06 some parser changes to allow optional parameters in the linkDLL bindings, unfortunately it's still only limited to Integer/Float and String fields.. I can easily expand it to support arrays/pointers in this build as the pre-processing. The other changes can be found in the FillMemory function. Which now has a some high level bit mode to enable AND/OR/XOR modes rather than just write mode. There's also new Packer and MAP slibs with now support the internal packing library code. Making saving levels and loading big levels much faster..
Here's an example of the fill memory changes.
[pbcode]
; This example encodes a message using XOR fill mode
Message$="My Secret Message"
; The Size of our test bank in bytes
Size=Len(Message$)+1
; create bank #1
CreateBank 1,Size
; store the original message into this bank
pokebankstring 1,0,Message$,0
; show the bank
ShowBank(1)
; XOR to encode the bank data with our key of $4B
FillMemory GetBankPtr(1),Size,$4B,1+32
; show the bank to screen
ShowBank(1)
; read the bytes in the bank back as string..
EncodedMessage$=PeekbankString(1,0,size)
; USE XOR with a key of $4B again to restore the bank
; data to it's original state
FillMemory GetBankPtr(1),Size,$4B,1+32
; read the bytes in the bank back as string..
DecodedMessage$=PeekbankString(1,0,size)
; show the bank to screen
ShowBank(1)
ink -1
print "Original Message"
ink $ff00
print Message$
print ""
ink -1
print "Encoded Message"
ink $ff0000
print EncodedMessage$
print ""
ink -1
print "Decoded Message"
ink $ff00
print DecodedMessage$
print ""
ink -1
print ""
; --------------------------------------------
; refresh the screen and wait for a key press
; --------------------------------------------
Sync
waitkey
Function ShowBank(Index)
Print "Bank Contents"
Size=GetBankSize(Index)-1
; Show the bytes from this bank
For lp=0 to Size
c$=right$(Hex$(peekbankbyte(index,lp)),2)
if lp<>size
r$=r$+c$+","
else
r$=r$+c$
endif
next
print r$
print ""
EndFunction
[/pbcode]
Read V1.64P Update Work In Progress gallery (http://www.underwaredesign.com/?l=PlayBASIC-V164P-WIP-GALLERY)
Download
Newer version bellow.
PlayBASIC V1.64P3 BETA #08 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (2nd Sep,2015)
V1.64P3 Beta #08 includes a number of operational optimizations in regards to clipping of certain drawing functions. Functions like LINE,BOX (and a number of others) for example would refresh the clipping viewport every time you called the function. Which was just overkill, or at least it should be. If you find a problem you think might be attributed to these changes then of course jump on the forums and post a bug report. The up side is of course some more speed..
PlayBASIC V1.64P3 BETA #09 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (8th Sep,2015)
V1.64P3 Beta #09 this one includes more migrated libraries, this time around it's the time and date libraries. Yeah i know exciting, but it has to be done.. :(
PlayBASIC V1.64P3 BETA #13 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (24th Sep,2015)
V1.64P3 Beta #13 this moves mor legacy VM out with updates to the strings/dates and call DLL libraries.
Download
Newer downloads on next page!
PlayBASIC V1.64P3 BETA #15 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (12th Oct,2015)
V1.64P3 Beta #15 this one includes updated Documentation and more translated commands with things like the FastCall parser being moved into the new instruction set format inside the runtime. This gives you more computational bang if you need long floating point calculations. The trade off point seems to be calculations that include 3 or more operations.
Here's some example FastCalc code, it's not like a normal expression, in these you have to order the instructions manually. This way there's no compiler getting in the way of the order of operations, you control it..
[pbcode]
; Init some variables to perform some calculations with
a#=10
b#=20
c#=30
d#=40
; ===============
; Example #1
; ===============
print "-----------------------------------------------------------"
; A normal expression
Result#= A# +b#+C#
; The same expression rearranged for FastCalc
FastCalc FastCalcResult#=A# +b#+C#
Print Result#
Print FastCalcResult#
; sync
;waitkey
; ===============
; Example #2
; ===============
print "-----------------------------------------------------------"
; A normal expression
Result#= A# +b#*10
; The same expression rearranged for FastCalc
Temp#=10
FastCalc FastCalcResult#=b#*temp#+a#
Print Result#
Print FastCalcResult#
; ===============
; Example #3
; ===============
print "-----------------------------------------------------------"
; A normal expression
Result#= Cos(a#) * c#
; The same expression rearranged for FastCalc
FastCalc FastCalcResult#=C# * Cos(a#)
; Note Operations like COS/SIN etc can't be the
; first operation in the FastCalc list
Print Result#
Print FastCalcResult#
; ===============
; Example #4
; ===============
print "-----------------------------------------------------------"
; A normal expression
Result#= (B#*C#) +(b#+D#)
; The same expression rearranged for FastCalc
FastCalc FastCalcResult#= b# *C#=temp#, B#+D#+Temp#
Print Result#
Print FastCalcResult#
print "-----------------------------------------------------------"
Radius#=100
Angle#=327
BaseX#=1000
; A normal expression
Result#= Cos(Angle#) * Radius# + BaseX#
; The same expression rearranged for FastCalc
FastCalc FastCalcResult#=Radius# * Cos(Angle#) + BaseX#
Print Result#
Print FastCalcResult#
print "-----------------------------------------------------------"
; A normal expression
Result#= Tan(Angle#) * Radius#
; The same expression rearranged for FastCalc
FastCalc FastCalcResult#=Radius# * Tan(Angle#)
Print Result#
Print FastCalcResult#
print "-----------------------------------------------------------"
; A normal expression
Result#= Rnd(Angle#) * Radius#
; The same expression rearranged for FastCalc
FastCalc FastCalcResult#=Radius# * Rnd(Angle#)
Print Result#
Print FastCalcResult#
print "--------------------------- TIMING -------------------------"
max=100000
t=timer()
for lp =0 to max
Result#= Rnd(Angle#) * Radius#
Result#= Rnd(Angle#) * Radius#
Result#= Rnd(Angle#) * Radius#
Result#= Rnd(Angle#) * Radius#
Result#= Rnd(Angle#) * Radius#
next
print timer()-t
t=timer()
for lp =0 to max
FastCalc FastCalcResult#=Radius# * Rnd(Angle#)
FastCalc FastCalcResult#=Radius# * Rnd(Angle#)
FastCalc FastCalcResult#=Radius# * Rnd(Angle#)
FastCalc FastCalcResult#=Radius# * Rnd(Angle#)
FastCalc FastCalcResult#=Radius# * Rnd(Angle#)
next
print timer()-t
t=timer()
for lp =0 to max
FastCalcResult#=Radius#+Radius#+Radius#+Radius#+Radius#
FastCalcResult#=Radius#+Radius#+Radius#+Radius#+Radius#
FastCalcResult#=Radius#+Radius#+Radius#+Radius#+Radius#
FastCalcResult#=Radius#+Radius#+Radius#+Radius#+Radius#
FastCalcResult#=Radius#+Radius#+Radius#+Radius#+Radius#
next
print timer()-t
t=timer()
for lp =0 to max
FastCalc FastCalcResult#=Radius#+Radius#+Radius#+Radius#+Radius#
FastCalc FastCalcResult#=Radius#+Radius#+Radius#+Radius#+Radius#
FastCalc FastCalcResult#=Radius#+Radius#+Radius#+Radius#+Radius#
FastCalc FastCalcResult#=Radius#+Radius#+Radius#+Radius#+Radius#
FastCalc FastCalcResult#=Radius#+Radius#+Radius#+Radius#+Radius#
next
print timer()-t
; refresh the screen wait for a key press
Sync
WaitKey
[/pbcode]
Download
Newer builds bellow
PlayBASIC V1.64P3 BETA #16 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (16th Oct,2015)
V1.64P3 Beta #16 this one includes another static opcode library conversion with the translation of the Pointer opcode set. It also includes the updated Documentation from the previous build. SO there's no need to download Beta 15 and Beta 16
Download
Obsolete built removed, newer builds bellow
PlayBASIC V1.64P3 BETA #17 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (19th Oct,2015)
V1.64P3 Beta #17 takes the static instruction set conversion one step futher with the tranlations the bit functions, which includes stuff like the shift/roll (LSR32, LSL32, ROR32, ROL32) the move operations, swapbyteorder, swapword etc as well as the bit operations (SetBit,SwapBit etc etc). We gain extra performance and drop from size from the runtimes.
This zip also includes the Documentation and the EXE runtimes, so you can actuall build EXE's with this version, although it'll give you a warning if you do so.. Which in this case you can ignore since the compiler and runtimes do match (ie they're built with the same instruction sets...) where as normally that'd give undefined results, since there's no guarantee the two sides use the same instruction sets, nor would an old runtime include new fixes.
Download
Obsolete built removed, newer builds bellow
PlayBASIC V1.64P3 BETA #18 - Opcode translations Dynamic To Static Continues
While hopefully while you guys have been testing revision/beta 17, I've been pushing ahead with more translations harnessing every drop of speed from the legacy runtimes. One example would the calling externally bound functions like those attached via LinkDLL blocks.
On closer inspection at those linkdll opcode execution blocks there's some fat that can be trimmed from the calling process. So that's been the focus of basically the last 24 hours of coding. Resulting an almost doubling of performance of the benchmark (about 40% actually), but there's some odd stuff happening with the replacement code at this time. There would seem to be some logical differences between them, so I unfortunately can't roll that out today.
anyway, back to it..
PlayBASIC V1.64P3 BETA #18 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (28th Oct,2015)
V1.64P3 Beta #18 continues with the migration to a static instruction set, with some conversions centering around the calling of linked DLL functions, such as functions defined within LinkDLL/EndLinkDll blocks. The changes result in a performance boost of about 25% improvement when calling a test function million times. This was further improved with the addition a some post processing done in the compiler to stream line the output values of such calls, which pushes the test to about 40->45% faster. There's a few other things that can be done in the future, but break compatibility at this time.
This package includes ithe Documentation and the EXE runtimes. So if you haven't updated to Beta17, you can skip that and just run this one. Since this is a BETA build which as includes in the runtimes, you'll get a warning when trying building an EXE from your project. The warning can be ignored since the compiler and runtimes do match (ie they're built with the same instruction sets...) where as normally that'd give undefined results, since there's no guarantee the two sides use the same instruction sets, nor would they include new fixes.
Download
Obsolete beta removed
(http://www.underwaredesign.com/PlayBasicSig.png)
PlayBASIC V1.64P3 _Retail Upgrade_ Now Available (20th, Nov, 2015)
This release updates any version from PlayBASIC
V1.63w2 to PlayBASIC V1.64P2 (retail) to the current retail version of PlayBASIC V1.64P3. If your current version is
older than PB1.63W (pre June/July 1997), then you may need to install patch
PB1.63w2 prior to this one ! (if you haven't already)
The
PlayBASIC V1.64P3 package includes updates of PlayBASIC Compiler, Release / Debug Runtimes, SLIBS, DOCS & IDE V1.17b.
The V1.64P3 release includes fixes for known functionality breakages during the massive V1.64P/V1.64P3 update. But like all updates that's not the only thing it includes, with a lot of work being done under the hood with the compiler / runtimes in the way of more dynamic to static byte code navigation. Which includes translations of thing like the DLL command block as well as pointer instruction sets and a number of others. For more information about those read the blog thread.
Don't have a retail version of PlayBASIC ? and want to find out more information about PlayBASIC programming > please visit the www.PlayBasic.com (http://www.playbasic.com) and download the free learning edition.
Downloads
[plink] Download PB1.64P3 Retail Upgrade (http://www.underwaredesign.com/forums/index.php?topic=1182.msg28975#msg28975)[/plink] (20th,Nov,2015)
PlayBASIC V1.64P4 BETA #1 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (7th Dec,2015)
V1.64P4 Beta #1 tweaks the pre-processing a little and adds from nanny code for scene depth control, which should stop most overflows, but can't stop all of them.
Download
Old beta remove, newer builds bellow
Shifty Operators
While working on some sorting algos this morning, noticed a problem the LSR (and >>) operations in newer VM's which are found in the last couple of builds. It occurs from the static opcodes replacements made in those revisions which have since been fixed. The issue was simply some the operation was doing an arithmetic shift rather than a bit wise shift, which is how it's defined originally.
So for the time being and depending upon your version, this will either return the correct answer of $0000ffff or the wrong answer of $ffffffff
[pbcode]
a=$ffff0000
print hex$( a>> 16)
sync
waitkey
[/pbcode]
In the code i was having trouble with was doing a AND then a SHIFT, something like this
Result = ThisValue And MASK >> Shift
all i needed to do is flip that.. SHIFT then MASK off any nwanted bits
PlayBASIC V1.64P4 BETA #5 - String Sorting - 250000 strings per second
Been working on various sorting algorithms which are used in the internals of the PlayBASIC runtimes, originally the replacement routines only handled integer/float data, but I've since managed to build a version that will work on string arrays also.
The command set uses string sorting a number of commands, but these are generally hidden deep away and often uses combination pre-passes with the sorting to speed them up. The one exception of course, is found in the SortArray command, which uses a classic Quick Sort implementation. Which is ok on small sets but chokes on the bigger sets of strings. While I suspect some of the choking is by product of my legacy implementation :), it's just doesn't cut it for big sets of data...
The replacement code is what I calla freq sort, it's a none comparative sort, which just means its skim through on various key, where it rearranges on those keys and then repeats the process until all keys have been passed. Once you get to end of the final sweep the array should be in order. The only issue really is that the ordering in case incentive, so AAAA and aaaa would have equal precedence in the output.
So performance,
Ok.... In the previous builds, the SortArray command can only handle about 800 variables length strings (1 to 32 characters) per second on my test machine per 1000->1100 millisecond gap.
Compare that to todays version that can handle 250,000 variable length strings (1 to 32 characters) in the 1000->1100 millisecond range...
That's approximately 312 times faster.. Which doesn't happen every day !
PlayBASIC V1.64P4 BETA #6 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (2nd Feb,2016)
V1.64P4 Beta #6 contains a few bugs and tweaks as well as include the new sorting routines used in the SortArray() command, making the command much much much much faster than before... For example it'll handle 250000 strings in about 1.1 seconds, which in not too bad for the old althon test machine.
Read V1.64P Update Work In Progress gallery (http://www.underwaredesign.com/?l=PlayBASIC-V164P-WIP-GALLERY)
[pbcode]
r =123456
Size =25000
Dim Table(Size+1)
Dim TableCopy(size+1)
For lp=0 to Size
Table(lp)=rnd(r)
TableCopy(lp)=Table(lp)
next
; init arrays of floats
Dim f#(Size)
Dim f2#(Size)
For lp=0 to Size
f#(lp)=rndrange#(-r,r)
next
; init the string array with random strings
Dim s$(Size)
Dim s2$(Size)
Init_String_Arrays(Size)
maxtests=1
Do
cls
frames++
Test_Integer_Sorting_Speed(Size,Frames)
Test_Float_Sorting_Speed(Size,Frames)
Test_String_Sorting_Speed(Size,Frames)
Sync
loop
psub Test_Integer_Sorting_Speed(Size,Frames)
print "---------------------------------------"
print "Number of Integers:"+str$(Size)
print "---------------------------------------"
t=timer()
copyArray TableCopy(),Table()
tt1#+=timer()-t
print " Copy Array Time:"+str$((tt1#/frames))
t=timer()
sortArray Table(),0,Size
tt2#+=timer()-t
print " Freq Sort Time:"+str$((tt2#/frames))
print ""
ENdPsub
psub Test_Float_Sorting_Speed(Size,Frames)
print "---------------------------------------"
print " Number of Floats:"+str$(Size)
print "---------------------------------------"
t=timer()
copyArray f#(),f2#()
tt1#+=timer()-t
print " Copy Array Time:"+str$((tt1#/frames))
t=timer()
sortArray f2#(),0,Size
tt2#+=timer()-t
print " Freq Sort Time:"+str$((tt2#/frames))
print ""
ENdPsub
Psub Test_String_Sorting_Speed(Size,Frames)
print "---------------------------------------"
print " Number of Strings:"+str$(Size)
print "---------------------------------------"
// Copy the array to a temp string
; VM_SortArrayMethod(1)
t=timer()
copyarray s$(),s2$()
tt1#+=timer()-t
print " Copy Array Time:"+str$((tt1#/frames))
t=timer()
sortArray s2$(),0,Size
tt2#+=timer()-t
print " String Sort Time:"+str$((tt2#/frames))
print ""
EndPsub
Psub Init_String_Arrays(Size)
Dim s$(Size)
Dim s2$(Size)
// fill the string array with random strings
// ranging in size from 1 to 32 characters
for lp=0 to Size
s$=""
for l=0 to 1+(lp and 31) ;rndrange(10,100)
if rnd(100)>50
ThisChr=asc("a")+rnd(asc("z")-asc("a"))
else
ThisChr=asc("A")+rnd(asc("Z")-asc("A"))
endif
s$+=chr$(THisCHR)
next
s$(lp)=s$
next
EndPsub
[/pbcode]
Download
Obsolete beta removed
PlayBASIC V1.64P4 BETA #7 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (24th Feb,2016)
V1.64P4 Beta #7 includes the first edition of the PlayBASIC image format (PBI). The user command set now supports it though the normal LoadImage style commands when loading from disc, there's no support for loading from memory as yet. This package also includes a new SLIB called SavePBI which is simple saver library.
Download
old file removed, newer build bellow
PlayBASIC V1.64P4: The final days
Getting back to time work (after that unfortunate real life distractions of the past couple of weeks) on what I hope will be final V1.64 revision ever! The latest focus has been tweaking PBI conversion code, adding a PBI analysis interface and the inclusion of loading from memory support to the command set. All of which went relatively painlessly.
The next little chore on the agenda is another tweak round over the doc's, you know include the newest stuff, tweak old examples etc etc. Not going to bother with the project pack as nobody even looks at them. Will probably post the latest build in the new few days and if the sky doesn't fall, that'll be it.
PlayBASIC V1.64P4 BETA #8 (Retail Compiler Only Beta) - (Avail for Registered Users ONLY) (14th Mar,2016)
V1.64P4 Beta #8 is the final clean up, including some library tweaks & help tweaks.
Download
[plink]Download PlayBASIC V1.64P4 Beta8 (http://www.underwaredesign.com/forums/index.php?topic=1150.msg29072#msg29072)[/plink] (14th,Mar,2016)
Thank you for your hard work! :)
(http://www.underwaredesign.com/PlayBasicSig.png)
PlayBASIC V1.64P4 _Retail Upgrade_ Now Available (24th, Mar, 2016)
The
PlayBASIC V1.64P4 package includes updates of PlayBASIC Compiler, Release / Debug Runtimes, SLIBS, DOCS & IDE V1.17b.
The V1.64P4 revision introduces the PBI (PlayBASIC Image format (http://www.underwaredesign.com/forums/index.php?topic=4329.0)) as well as including a round of documentation and bug tweaks. For more information about those read the blog thread.
Don't have a retail version of PlayBASIC ? and want to find out more information about PlayBASIC programming > please visit the www.PlayBasic.com (http://www.playbasic.com) and download the free learning edition.
Downloads
[plink]Download PlayBASIC V1.64P4 Retail Upgrade (http://www.underwaredesign.com/forums/index.php?topic=1182.msg29077#msg29077)[/plink] (24th,Mar,2016)
The LoadNewDLL appears to be broken in PB1.64P4, so use this until V1.65 releases
[pbcode]
Function LoadNewDll2(DllName$)
Index=GetFreeDll()
LoadDll DllName$,Index
EndFunction Index
[/pbcode]