MaxCoderz

for your 1 bit pleasure!

All times are UTC




Post new topic Reply to topic  [ 120 posts ]  Go to page Previous  1 ... 3, 4, 5, 6, 7, 8  Next
Author Message
PostPosted: Wed 12 Nov, 2008 1:56 am 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
Here's an interesting speed comparison between BBC BASIC and the native TI-OS programming language. The test is the Sierpinski Triangle program in the guidebook (17-7):-
Code:
:FnOff :ClrDraw
:PlotsOff
:AxesOff
:0→Xmin:1→Xmax
:0→Ymin:1→Ymax
:rand→X:rand→Y
:For(K,1,3000)
:rand→N
:If N≤1/3
:Then
:.5X→X
:.5Y→Y
:End
:If 1/3<N and N≤2/3
:Then
:.5(.5+X)→X
:.5(1+Y)→Y
:End
:If 2/3<N
:Then
:.5(1+X)→X
:.5Y→Y
:End
:Pt-On(X,Y)
:End

Translated into BBC BASIC, it looks like this:-
Code:
   10 REM Sierpinski Triangle by Texas Instruments.
   20 REM Taken from the TI-83 Plus Guidebook.
   30 CLG
   40 X=RND(1):Y=RND(1)
   50 FOR K=1 TO 3000
   60   N=RND(1)
   70   IF N<=1/3 THEN X=.5*X : Y=.5*Y
   80   IF 1/3<N AND N<=2/3 THEN X=.5*(.5+X) : Y=.5*(1+Y)
   90   IF 2/3<N THEN X=.5*(1+X) : Y=.5*Y
  100   PLOT 69,X*96,64-Y*64
  110 NEXT K

On a regular TI-83+ (6MHz) the TI-OS program takes 7 minutes and 8 seconds to complete. The BBC BASIC program takes 2 minutes and 21 seconds. That's quite a speed difference!

Image

Here it is running on an emulated 83+SE at 15MHz. :-)


Top
 Profile  
Reply with quote  
PostPosted: Wed 12 Nov, 2008 5:39 am 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 4094
Location: I cant seem to get out of this cryogenic chamber!
Yay, its own forum!

I always liked the Sierpinski Triangle, and wow! Thats a huge speed improvement!

_________________
"My world is Black & White. But if I blink fast enough, I see it in Grayscale."
Image
Image


Top
 Profile  
Reply with quote  
PostPosted: Wed 12 Nov, 2008 8:12 pm 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
A slightly optimised version takes it down to 1 minute and 56 seconds. :)

Image

BBC BASIC passes control to the host interface when it encounters GCOL so I've managed to exploit that to add an extra statement - GCOLPAT. You can pass it a pointer to an 8-by-8 pixel pattern in memory and it will use that in place of the foreground/background dither patterns in subsequent plotting operations that fill regions of the screen (you can reset it to normal by invoking GCOL again or passing 0/FALSE to GCOLPAT. The code for the above example is here. This could allow for some interesting special effects!

Edit: I've just reshuffled the app around a bit and added *EXEC. This reads console input from a text file; this could be useful with external text editors. You could type up your BBC BASIC program in any on-calc text editor, then *EXEC then SAVE it in the BBC BASIC environment to convert it (tokenise it) to a BASIC program.

Image

In the image a file is opened for writing with OPENOUT, three lines of program text are PRINT#ed to it, then it is *EXECecuted to convert its text to a BASIC program. You could also use this for runtime code generation or similar by storing the text to a temp file first.


Top
 Profile  
Reply with quote  
PostPosted: Mon 17 Nov, 2008 12:14 pm 
Offline
Calc King
User avatar

Joined: Sun 23 Jan, 2005 12:37 am
Posts: 1727
Location: Netherlands
Ben... this is insane! :mrgreen:
A clock, fill patterns, all these features... and the SPEED... I envy your brain ;)

_________________
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS


Top
 Profile  
Reply with quote  
PostPosted: Mon 17 Nov, 2008 9:00 pm 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 4094
Location: I cant seem to get out of this cryogenic chamber!
Ive been trying to devise ways to covertly thieve brain power from Ben. So far all my efforts have proven unsuccessful :S.

I am confident that this project will have the added side effect of succeeding BASIC libs in that the speed gain should be a fair bit better. Plus the familiar/friendly BBC BASIC syntax and bens sweet editor are all pluses in my eyes :).

_________________
"My world is Black & White. But if I blink fast enough, I see it in Grayscale."
Image
Image


Top
 Profile  
Reply with quote  
PostPosted: Tue 18 Nov, 2008 12:02 am 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
Cheers for the kind comments chaps. :)

I've been working on triangle filling over the weekend. I initially tried to do something clever using the line clipping code qarnos wrote, but couldn't get good results from the "clever" method so have gone for sluggish "stupid" method instead.


The requirements of the triangle filler are as follows:

  • All three vertices are specified using signed 16-bit coordinates.
  • The triangle is clipped to the user-definable graphics window - 8-bit coordinates indicating a top-left and bottom-right corner.
  • Each scanline must be filled once (and once only - no overdraw) by calling HLineFill by qarnos with a=y, b=x1, c=x2 and b≤c.

I use Bresenham's line drawing algorithm to trace the three sides of the triangle, storing the minimum X and maximum X for each scanline (think of a line where its |dX|>|dY| - more than one pixel would be plotted per scanline, else the line would have gaps). Then the triangle is filled in two halves, from A.Y to B.Y-1 then B.Y to C.Y. For each scanline the minimum and maximum X component is found from the two sides and used as the bounds of the filled scanline.

This is rather slow for a number of reasons - Bresenham's line drawing algorithm is implemented in full 16-bits (using both "regular" registers and the shadow registers), and the whole triangle is scanned from top to bottom. I may add a special-case 8-bit version of the tracer (when both ends of a edge fit into 8-bit coordinates) but for the moment I'm going for robustness over speed, and only having one code-path makes life easier!


Top
 Profile  
Reply with quote  
PostPosted: Tue 18 Nov, 2008 4:53 am 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 4094
Location: I cant seem to get out of this cryogenic chamber!
Looking great ben, by the way that code listing script you have is really nice :).

_________________
"My world is Black & White. But if I blink fast enough, I see it in Grayscale."
Image
Image


Top
 Profile  
Reply with quote  
PostPosted: Tue 18 Nov, 2008 3:45 pm 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
Thanks. :) The slightly garish colours are courtesy of the Windows version of BBC BASIC.

Image

I've added rough-and-ready parallelogram filling as an extension of triangle filling. Given point1, point2 and point3 the fourth point is calculated by point3-point2+point1.

As it's drawn as two triangles there is a line of pixels that doesn't appear to be drawn between points 1 and 3 in EOR/inverse modes thanks to overdraw (draw the same pixel twice in EOR/inverse mode and you're back to where you're started). That needs to be fixed.


Top
 Profile  
Reply with quote  
PostPosted: Fri 21 Nov, 2008 12:18 am 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
I've started hacking together support for some of the BBC Micro OS call routines. Naturally there are some differences in implementations (as this is a Z80 there isn't an X or Y register) but the addresses and functionality are similar.

As an example, in BBC BASIC you can output a byte to the VDU driver (and so output text, define viewports, draw shapes and so on) by using the VDU command, like this:

Code:
VDU 16

(VDU 16 = clear graphics screen - ie, what CLG normally does). This is good, but such functionality would be nice to have in assembly too so your snippets of inline Z80 code can also output text, graphics and so on. For this purpose, there's a routine at address &FFEE called OSWRCH that outputs the byte in the accumulator, so the above could be replicated with the following:

Code:
A%=16 : CALL &FFEE

BBC BASIC lets you intercept CALLs to the &FF80..&FFFF range (where the BBC Micro routines reside) and redirect them to somewhere more appropriate. However, this functionality does not work in the assembler - and a CALL &FFEE will crash the calculator as &FFEE on the protected RAM page 0. Therefore, all OS calls are offset from &FF80..&FFFF to &4080..&40FF, and so

Code:
[ LD A,16 : CALL &40EE ]

would be the equivalent inline assembly version.

There are a large number of useful routines (setting clocks, getting cursor positions, reading lines of text, handling files, finding out memory ranges). Some are available in BASIC, and some can be used to perform tricks in assembly that aren't possible in BASIC directly.

An example of this is the following assembly program. It can be used to work out the graphics origin. It works by moving the graphics cursor to (0,0) then reading back the current cursor position via the OSWORD OS command. OSWORD is a generic routine that takes a routine number in A and a pointer to a parameter block in HL. In this case A is &09, which means "read the last two graphics cursor positions", and it outputs the cursor positions as an 8-byte block .

Code:
   10 REM OS call routine constants
   20 OSWRCH=&40EE
   30 OSWORD=&40F1
   40 :
   50 DIM GetOrigin 90
   60 FOR pass%=0 TO 1
   70   P%=GetOrigin
   80   [
   90   OPT pass%*2
  100   ;
  110   ; Check there are 2 arguments
  120   LD A,(IX+0) : CP 2 : RET NZ
  130   ;
  140   ; Check they are both integers
  150   LD A,(IX+1) : CP 4 : RET NZ
  160   LD A,(IX+4) : CP 4 : RET NZ
  170   ;
  180   ; MOVE to the origin by invoking VDU 25,5,0;0;
  190   LD A,25 : CALL OSWRCH
  200   LD A,5 : CALL OSWRCH
  210   ; Output 4 zeroes to move to (0,0).
  220   LD B,4
  230   .lp XOR A : CALL OSWRCH : DJNZ lp
  240   ;
  250   ; Invoke OSWORD &0D to read last two cursor positions
  260   LD HL,PrevX
  270   LD A,&0D : CALL OSWORD
  280   ;
  290   ; Now we know the origin we need to output it.
  300   LD L,(IX+2) : LD H,(IX+3)
  310   LD DE,(CurrX) : CALL OutputCoord
  320   LD L,(IX+5) : LD H,(IX+6)
  330   LD DE,(CurrY) : CALL OutputCoord
  340   RET
  350   ;
  360   ; 8 bytes of storage for cursor positions
  370   .PrevX : DEFW 0 : .PrevY : DEFW 0
  380   .CurrX : DEFW 0 : .CurrY : DEFW 0
  390   ;
  400   ; Outputs 16-bit value DE to 32-bit variable at HL
  410   .OutputCoord
  420   LD (HL),E : INC HL
  430   LD (HL),D : INC HL
  440   SLA D
  450   SBC A,A
  460   LD (HL),A : INC HL
  470   LD (HL),A : RET
  480   ]
  490 NEXT pass%

You could invoke it like this (note that VDU 29 sets the graphics origin):

Code:
VDU 29,48;-32;
CALL GetOrigin,x%,y%
PRINT "Origin = (";x%;",";y%;")"

I appreciate this probably means nothing to people not familiar with BBC BASIC..!


Top
 Profile  
Reply with quote  
PostPosted: Sat 22 Nov, 2008 3:05 pm 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
Wstfgl. After all that time, odd bugs have started creeping in, usually resulting in a crash if certain operations are carried out in sequence (for example, mixing * commands with file manipulation). When switching between BBC BASIC and the TI-OS registers are backed up like this:

Code:
FunctionA:
    call SaveBasicRegisters
    ; ... stuff ...
    call RestoreBasicRegisters
    ret

FunctionB:
    call SaveBasicRegisters
    ; ... stuff ...
    call RestoreBasicRegisters
    ret
If FunctionA (which may be the OSCLI handler for * commands) calls FunctionB (which may be related to file I/O) it would end up saving the TI-OS mode registers to the BASIC register save slot. After inserting a counter to ensure that you don't accidentally save or restore too many times the nature of the crashes changed somewhat.

Another potential source of errors is an imbalanced stack.

I've removed every function that used SaveBasicRegisters or RestoreBasicRegisters and the calculator no longer crashes, but this has removed a lot of functionality (namely anything that works with files). Hrm. :( This is quite a significant set-back.

Edit: It seems to be related to the file I/O routines. BBC BASIC lets you open a file for read and/or write access, returns a handle, then gives you full random access to it. This makes the TI-83+ code rather complex, eg writing to the end of a file opened for writing should make it grow. There's some rather messy code in there to deal with "dirty handles" to cope with RAM being shuffled around by the TI-OS file editing routines and the like. It may need a full rewrite... :(

Edit 2: Seems like it could be related to enlarging files. The following program locks up the calculator:

Code:
   10 h=OPENOUT"TESTFILE"
   20 FOR i=1 TO 100
   30   PRINT "Test #";i
   40   PRINT#h,"The quick brown fox jumps over the lazy dog."
   50 NEXT i
   60 CLOSE#h

This usually crashes after about 5 iterations. Changing "TESTFILE" to "PIC1.PIC" (the fixed-size Pic1 variable) hits iteration 17 before the safe BASIC Disk full error is triggered. Working on it... :(

Edit 3: I think I found it. After a lot of rewriting to no avail, I've removed a bcall from the ISR and it all started working again! :D (Even with a dummy bcall, ie to a routine that just rets, causes the weird crashes).

In the meantime I rewrote the entire Windows-based tokeniser (thing that converts text to BBC BASIC programs and wraps them in a .8xp) and that has ironed out all its bugs.


Top
 Profile  
Reply with quote  
PostPosted: Mon 24 Nov, 2008 10:41 pm 
Offline
Extreme Poster
User avatar

Joined: Thu 17 May, 2007 4:49 pm
Posts: 395
Location: $4080
I feel your pain... If you just added some code and it crashes, then fixing the problem is trivial.
But if something appears to be working fine, you move your focus to other things and suddenly you get weird errors? Those are the most annoying bugs to find. It gets harder as the complexity if the project increases.

I sure wish you good luck :P


Top
 Profile  
Reply with quote  
PostPosted: Tue 25 Nov, 2008 12:41 am 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
Thanks for the support. :D It seems to have been fixed now, at any rate.

Image

A couple of glitches in the triangle filler are causing me grief now. They seem to be related to calculating which scanlines to fill between. :(

On the features front, I've added a break/reset key. Holding On for five seconds forces BBC BASIC to restart.

Image

The On key triggers an Escape error normally. If there is an error in your error handler this can cause real problems; in the above example the error handler in line 10 doesn't bail out and runs into line 20 (which contains an error) causing an infinite loop. Pressing On to terminate execution doesn't work, as that itself triggers an error!

Once BBC BASIC has been restarted your program is lost, but as long as you don't enter any new program lines you can retrieve it with the OLD keyword.


Top
 Profile  
Reply with quote  
PostPosted: Tue 25 Nov, 2008 5:47 am 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 4094
Location: I cant seem to get out of this cryogenic chamber!
Ahh goodo, safety first! I was worried as i read '...your program is lost' but i see the life saving OLD is there to save the day :).

_________________
"My world is Black & White. But if I blink fast enough, I see it in Grayscale."
Image
Image


Top
 Profile  
Reply with quote  
PostPosted: Tue 25 Nov, 2008 11:35 am 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
When I say "lost" that's the copy of the program that had been loaded into BBC BASIC's memory, not the program variable (if it had been saved previously). That means that if you have a program variable in RAM and LOAD it into BASIC there are two copies; normally you'd run BBC BASIC on a computer with some sort of external filing system (eg disc, tape or network). As the host interface transparently handles reading files from the archive you can store all your programs there, at least.

OLD works if you exit the flash app and restart BBC BASIC, as long as you haven't overwritten the RAM that BBC BASIC previously used to store the program.

Safety doesn't really go hand-in-hand with power, so you'll still be able to crash the calculator by using the indirection operators to overwrite important memory, CALL a routine you shouldn't or write a buggy assembly routine - but it's good to try and keep the high-level functionality as safe as possible.


Top
 Profile  
Reply with quote  
PostPosted: Sat 29 Nov, 2008 2:57 am 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
A post on RevSoft made me check and see if it was possible to use BBC BASIC's inline assembler to assemble "regular" assembly programs on-calc.


The BBC BASIC program creates an assembly program. A few nifty features of BBC BASIC allow this to be possible - usually programs are assembled directly at the specified origin P% but one of the OPT bits can be used to assemble it elsewhere (at O%). Once it has been assembled *SAVE is used to save the assembled file (in memory) to a program variable. A little clunkier than a dedicated on-calc assembler, but this may show how flexible BBC BASIC is. :)

I've rewritten all of the OS-level commands (they were implemented slowly, buggily and inefficiently).

Image

One that's been missing is *CAT (aliased to *DIR and *.) to list calculator variables. By default it outputs the name of every available variable, but you can pass it a pattern with wildcards which can be used to filter the names (eg *CAT F* to list all variables starting with the letter F or *.???.VAR to list every AppVar with a three-lettered name).

I've also optimised the block copy and save operations (operations that save or load an large block of memory to/from a file) with special cases to handle variables in RAM (LDIR) and a simplified loader for variables in ROM. The result is instantaneous loads for variables in RAM, and loads from ROM are not much slower.

The Escape condition is now maskable, and you can prevent pressing On from triggering an error with the *ESC OFF command.

I think I fixed the triangle filling bug from the earlier post, too.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 120 posts ]  Go to page Previous  1 ... 3, 4, 5, 6, 7, 8  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB ® Forum Software © phpBB Group | DVGFX2 by: Matt