Jump to content
bfollett

Bitmap mode.

Recommended Posts

Yeah, TI BASIC is the wrong application for this. But it's not actually comparing apples to apples, either. ABASIC and the Atari BASIC both have their graphics primitives written in assembly language, and both have a dot-addressable mode to plot to. My program is calculating the graphics in BASIC via string manipulation and redefining characters. But I did it because it's one of those things that a younger me would have called impossible, and I like showing myself up. ;) (That said, TI BASIC /is/ really slow and doesn't even compete.)

 

I'm not letting it run to completion either way, though, you'll have to settle for the 80% pic I posted already. (It's too distracting, I keep checking in on it.)

 

Who's going to dive in with some other versions to show what the TI can really do?

 

Here's my take on it in Extended Basic. It's running as I am typing this and here's a sneak peak at 10 minutes under Overdrive mode. It still has a long way to go. I am going for the same scale you did (0.5), but even then I think I will run out of characters before it completes. I have only 110 characters to work with in XB, which is really not a lot. How did you manage to squeeze it all on screen?

 

 

100 CALL CLEAR:: CALL SCREEN(2):: FOR I=1 TO 14:: CALL COLOR(I,16,2):: NEXT I

110 DIM HEX$(16)
120 FOR I=0 TO 15:: READ HEX$(I):: NEXT I
130 CURCHAR=32
140 XP=144
150 XR=4.71238905
160 XF=XR/XP
170 FOR ZI=-64 TO 64 STEP 4
180 ZT=ZI*2.25
190 ZS=ZT*ZT
200 XL=INT(SQR(20736-ZS)+0.5)
210 FOR XI=0-XL TO XL STEP 4
220 XT=SQR(XI*XI+ZS)*XF
230 YY=(SIN(XT)+SIN(XT*3)*0.4)*56
240 X=INT((XI+ZI)*0.3+128+0.5)
250 Y=INT((96-YY+ZI)*0.3+0.5)
260 GOSUB 320
270 IF ENDFLAG=1 THEN 300
280 NEXT XI
290 NEXT ZI
300 GOTO 300
310 DATA 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F
320 RFLAG=0:: EFLAG=0:: ENDFLAG=0:: BFLAG=0:: H$="":: NH$=""
330 IF X<9 THEN COL=1:: XOFFSET=X ELSE COL=INT(X/8)+1:: XOFFSET=(X-((COL-1)*8))+1
340 IF Y<9 THEN ROW=1:: YOFFSET=Y ELSE ROW=INT(Y/8)+1:: YOFFSET=(Y-((ROW-1)*8))+1
350 IF XOFFSET>4 THEN XPOS=XOFFSET-4:: RFLAG=1 ELSE XPOS=XOFFSET
360 BINVAL=2^(4-XPOS):: HEXVAL$=STR$(BINVAL)
370 FOR J=1 TO 8
380 IF YOFFSET=J THEN IF RFLAG=0 THEN H$=H$&HEXVAL$&"0" ELSE H$=H$&"0"&HEXVAL$ ELSE H$=H$&"00"
390 NEXT J
400 CALL GCHAR(ROW,COL,C):: IF C>32 THEN CALL CHARPAT(C,EH$):: EFLAG=1
410 IF EFLAG=0 THEN CURCHAR=CURCHAR+1:: IF CURCHAR>143 THEN ENDFLAG=1:: RETURN ELSE CALL CHAR(CURCHAR,H$):: CALL HCHAR(ROW,COL,CURCHAR):: GOTO 520
420 FOR I=1 TO 16
430 CURVAL$=SEG$(EH$,I,1):: IF ASC(CURVAL$)<58 THEN CVAL=VAL(CURVAL$) ELSE CVAL=ASC(CURVAL$)-55
440 NEWVAL$=SEG$(H$,I,1):: IF ASC(NEWVAL$)<58 THEN NVAL=VAL(NEWVAL$) ELSE NVAL=ASC(NEWVAL$)-55
450 FVAL=CVAL OR NVAL:: HEXVAL$=HEX$(FVAL):: NH$=NH$&HEXVAL$
460 NEXT I
470 EH$=NH$
480 BINVAL=NOT BINVAL
490 IF YOFFSET=8 THEN 520 ELSE P=YOFFSET*2+1
500 GOSUB 570
510 CALL CHAR(C,NH$):: CALL HCHAR(ROW,COL,C)
520 CALL GCHAR(ROW+1,COL,C):: IF C=32 THEN RETURN
530 ROW=ROW+1:: P=1
540 CALL CHARPAT(C,EH$)
550 GOSUB 570
560 CALL CHAR(C,NH$):: CALL HCHAR(ROW,COL,C):: GOTO 520
570 IF P=1 THEN NH$="" ELSE NH$=SEG$(EH$,1,P-1)
580 IF RFLAG=1 THEN 610
590 NEWVAL$=SEG$(EH$,P,1):: IF ASC(NEWVAL$)<58 THEN NVAL=VAL(NEWVAL$) ELSE NVAL=ASC(NEWVAL$)-55
600 FVAL=NVAL AND BINVAL:: HEXVAL$=HEX$(FVAL):: P=P+1:: NH$=NH$&HEXVAL$&SEG$(EH$,P,1):: GOTO 640
610 P=P+1:: NEWVAL$=SEG$(EH$,P,1)
620 IF ASC(NEWVAL$)<58 THEN NVAL=VAL(NEWVAL$) ELSE NVAL=ASC(NEWVAL$)-55
630 FVAL=NVAL AND BINVAL:: HEXVAL$=HEX$(FVAL):: NH$=NH$&SEG$(EH$,P-1,1)&HEXVAL$
640 P=P+1:: IF P<17 THEN 580
650 RETURN

 

 

 

Hat

1 hour and 20 minutes into it...

 

  • Like 2

Share this post


Link to post
Share on other sites

 

Here's my take on it in Extended Basic. It's running as I am typing this and here's a sneak peak at 10 minutes under Overdrive mode. It still has a long way to go. I am going for the same scale you did (0.5), but even then I think I will run out of characters before it completes. I have only 110 characters to work with in XB, which is really not a lot. How did you manage to squeeze it all on screen?

 

I don't... I run out of characters about 80% of the way in. A smaller scale is needed to fit it, but it takes too long to work out what that is. ;)

 

That said, I updated my post with a finished run (big piece missing out of the hat at 50%, and a tiny little 10% hat that finished ;) ).

Share this post


Link to post
Share on other sites

Ah... I'm going to let it run to completion overnight and see how far I get.

As you stated earlier though, this is no way near a fair comparison between the TI and the Atari given the lack of bitmap primitives in TI Basic/XB.

I think I spent far too much time on this today, but it did pike my interest :grin:

  • Like 2

Share this post


Link to post
Share on other sites

Someone try with an 80-col card on the TI? The Geneve can, of course, make good use of the line primitives in the v9938.

Share this post


Link to post
Share on other sites

Again, just for a bit of fun. The Hat or Archimedes Spiral. The TI-99/4A being simulated with speed limit knock off. The resulting Flash file is less than 14 KB. The main code is very much the same as listed in post #84.

 

[media=544,416]http://sometimes.planet-99.net/pic/hat.swf[/media]

 

Edit: I might add that what you see is the algorithm running and setting of pixels. Should run with older Flash player versions, but you may need a more modern computer to have it run fast and smooth.

 

:)

Edited by sometimes99er

Share this post


Link to post
Share on other sites

 

Everyone did such a great job getting the TI to run the Mad magazine demo using various TI programming languages. I thought I'd post a challenge for another Atari demo conversion. This one actually took about 3 hours to run with Atari Basic and produced an on screen hat. The Atari's hires mode(Graphics 8+16) is 320 pixels so some variables might need a little tweaking to keep the results under 256 pixels for the TI.

140 GRAPHICS 8+16:SETCOLOR 2,0,0

150 XP=144:XR=4.71238905:XF=XR/XP

160 FOR ZI=-64 TO 64

170 ZT=ZI*2.25:ZS=ZT*ZT

180 XL=INT(SQR(20736-ZS)+0.5)

190 FOR XI=0-XL TO XL

200 XT=SQR(XI*XI+ZS)*XF

210 YY=(SIN(XT)+SIN(XT*3)*0.4)*56

220 X1=XI+ZI+160:Y1=90-YY+ZI

230 TRAP 250:COLOR 1:PLOT X1,Y1

240 COLOR 0:PLOT X1,Y1+1:DRAWTO X1,191

250 NEXT XI:NEXT ZI

260 GOTO 260

More info here: http://j-b.livejournal.com/419883.html

Bob

 

 

 

How would we do this in fixed point? How many "virtual" decimal places would we need?

Share this post


Link to post
Share on other sites

 

How would we do this in fixed point? How many "virtual" decimal places would we need?

 

Floating Point math maintains 13 – 14 significant decimal digits on the 4A. The larger problem would likely be to figure out how far left the DP floats to get a handle on scaling intermediate results. There is also managing the sine and square-root functions. Some sort of CORDIC or table lookup algorithm would work for sine.

 

I actually plan to use FP math for sine and square root calculations, converting to integer math everywhere else. I just haven't had a lot of time to work on it since the challenge arose.

 

...lee

Share this post


Link to post
Share on other sites

How would we do this in fixed point? How many "virtual" decimal places would we need?

All I changed was X1=XI+ZI+160 to X1=XI*0.75+ZI+128 and otherwise I'm getting ...

 

XP:Number = 144;		// (see below)
XR:Number = 4.71238905;		// (see below)
XF:Number = XR/XP;		// a constant but float (see values above) = 0.03272492395833333 (a value of 0.032 seems to work fine)
ZI:int				// integer, goes from -64 to 64
ZT:Number;			// goes from -144 in steps of 2.25 up to 144
ZS:Number;			// is the square of ZT, goes from 20736 down to 0 and up again with 4 decimal places (decimals cycles through .0000, .0625, .0250 and .5625)
XL:int;				// works fine as integer, has a range from 0 to 144
XI:int;				// works fine as integer, has a range from -11 to 144 
XT:Number;			// range from 0 to 4.7279588003184525
YY:int;				// works fine as integer, has a range from -55 to 55
X1:int;				// works fine as integer, has a range from 2 to 253
Y1:int;				// works fine as integer, has a range from 2 to 198

Share this post


Link to post
Share on other sites

Here's a tough challenge for any computer: calculate and display a Lyapunov chaos space image :) I did this in assembly on the TI as part of my Chaos Musings program (disk and manual attached below), and I believe it took 2-3 days to complete under V9t9 unthrottled on a Pentium II desktop. On a real TI, I estimated it will take about 36 days although I never ran it to completion on real hardware. There are 200 floating point calculations for each pixel, so for the TI we are looking at a total 9,830,400 calculations for a single image!

 

Lyapunov

I wonder how the Geneve or the Atari will perform here :D

 

Chaos.zip

  • Like 1

Share this post


Link to post
Share on other sites

Here's a tough challenge for any computer: calculate and display a Lyapunov chaos space image :) I did this in assembly on the TI as part of my Chaos Musings program (disk and manual attached below), and I believe it took 2-3 days to complete under V9t9 unthrottled on a Pentium II desktop. On a real TI, I estimated it will take about 36 days although I never ran it to completion on real hardware. There are 200 floating point calculations for each pixel, so for the TI we are looking at a total 9,830,400 calculations for a single image!

 

 

 

I wonder how the Geneve or the Atari will perform here :D

 

Cool! The question i'm inclined to ask is: is floating point actually required? Could it be done with fixed point? We have a very limited screen resolution so I wonder if floats are even required? It's the floating point that is the killer in terms of performance, obviously.

Share this post


Link to post
Share on other sites

In my FRACTALS program I used a simple fixed point arithmetic with 16 bits integer and 48 bits fraction part, but for calculating x(n+1) = x(n)²+c you just need multiplication and addition. If anyone would like to add trigonometic routines for that, go ahead!

Share this post


Link to post
Share on other sites

Cool! The question i'm inclined to ask is: is floating point actually required? Could it be done with fixed point? We have a very limited screen resolution so I wonder if floats are even required? It's the floating point that is the killer in terms of performance, obviously.

 

Frankly this is likely above my pay grade as an amateur programmer :)

Here's an excerpt from the manual explaining the calculations involved, and I have a feeling it could be done without floating point math. I would love to see the speed increase with that!

 

Lyapunov1

Share this post


Link to post
Share on other sites

Cool! The question i'm inclined to ask is: is floating point actually required?

 

oooo ... yes, there's a logarithm involved.

Share this post


Link to post
Share on other sites

@Walid: The program is running here, showing a first line with rapidly changing characters. Is that OK? Until now nothing else has changed. I guess there is a progress meter 0% to 100%, but nothing in between.

 

Edit: Just watched the processing in the debugger - OK, things are progressing, but slowly ...

 

One pixel takes about 31 seconds on the (emulated) Geneve, so I would expect a total of 17.6 days.

Edited by mizapf

Share this post


Link to post
Share on other sites

I decided to try it in Extended Basic with The Missing Link:

 

140 CALL LINK("CLEAR")
150 XP=144 :: XR=4.71238905 :: XF=XR/XP
160 FOR ZI=-64 TO 64
170 ZT=ZI*2.25 :: ZS=ZT*ZT
180 XL=INT(SQR(20736-ZS)+0.5)
190 FOR XI=0-XL TO XL
200 XT=SQR(XI*XI+ZS)*XF
210 YY=(SIN(XT)+SIN(XT*3)*0.4)*56
220 X1=XI+ZI+160 :: Y1=90-YY+ZI
230 ON ERROR 270
235 CALL LINK("PD") :: CALL LINK("PIXEL",Y1*.75,X1*.75)
240 CALL LINK("PE") :: CALL LINK("LINE",Y1*.75+1,X1*.75,144,X1*.75)
250 NEXT XI :: NEXT ZI
260 GOTO 260
270 RETURN 250

post-37510-0-26688900-1424893934_thumb.png

  • Like 4

Share this post


Link to post
Share on other sites

I decided to try it in Extended Basic with The Missing Link:

 

I remember TML from a long way back, I think I even had a copy. Anyway I wanted to try this on R.I., but was only able to locate the manual for it on WHTECH. :)

So, I'll just have to ask, how long did it take to complete?

Share this post


Link to post
Share on other sites

 

I remember TML from a long way back, I think I even had a copy. Anyway I wanted to try this on R.I., but was only able to locate the manual for it on WHTECH. :)

So, I'll just have to ask, how long did it take to complete?

I didn't time it, but it was about an hour on unthrottled MESS.

 

Here's The Missing Link: http://www.retroclouds.de/atariage/The_Missing_Link_2_0.zip

  • Like 1

Share this post


Link to post
Share on other sites

@Walid: The program is running here, showing a first line with rapidly changing characters. Is that OK? Until now nothing else has changed. I guess there is a progress meter 0% to 100%, but nothing in between.

 

Edit: Just watched the processing in the debugger - OK, things are progressing, but slowly ...

 

One pixel takes about 31 seconds on the (emulated) Geneve, so I would expect a total of 17.6 days.

 

Yes, it takes a while to see any progress on the bar :) The rapidly changing characters at the top of the screen are a side effect of the floating point functions on the TI. I could have eliminated them by saving and restoring that portion of the screen between each calculation, but it would have slowed things further...

17.6 is 50% faster than the stock TI. Impressive!

Share this post


Link to post
Share on other sites

I decided to try it in Extended Basic with The Missing Link:

 

140 CALL LINK("CLEAR")

150 XP=144 :: XR=4.71238905 :: XF=XR/XP

160 FOR ZI=-64 TO 64

170 ZT=ZI*2.25 :: ZS=ZT*ZT

180 XL=INT(SQR(20736-ZS)+0.5)

190 FOR XI=0-XL TO XL

200 XT=SQR(XI*XI+ZS)*XF

210 YY=(SIN(XT)+SIN(XT*3)*0.4)*56

220 X1=XI+ZI+160 :: Y1=90-YY+ZI

230 ON ERROR 270

235 CALL LINK("PD") :: CALL LINK("PIXEL",Y1*.75,X1*.75)

240 CALL LINK("PE") :: CALL LINK("LINE",Y1*.75+1,X1*.75,144,X1*.75)

250 NEXT XI :: NEXT ZI

260 GOTO 260

270 RETURN 250

 

How long did it take to draw it?

Share this post


Link to post
Share on other sites

It takes around 4 hours to run as you have shown it. One easy way to get a slight speedup is to select the 2 color mode when TML starts up. Hold down a key when it starts to get the menu and select the appropriate options.

I made line 220 read:

220 X1=(XI+ZI+160)*.75::Y1=90-YY+ZI (this way you only multiply once. this gives a full height hat; you can multiply y1 by .75 if you want to keep the correct proportions. I don't think you need line 230.

220 X1=XI+ZI+160 :: Y1=90-YY+ZI
230 ON ERROR 270
235 CALL LINK("PD") :: CALL LINK("PIXEL",Y1*.75,X1*.75)
240 CALL LINK("PE") :: CALL LINK("LINE",Y1*.75+1,X1*.75,144,X1*.75)

A big improvement can be obtained if you work from the front to the back. Make line 160:

160 FOR ZI=64 TO -64 STEP -1

Make an array to hold the maximum heights of the pixels in each column and initialize it so all the elements are 193. Then, before printing the pixel in line 235 check the row (X1) of the pixel you are about to print. If the row is less (i.e. higher on the screen) than the highest row then print the pixel and store that X1 as the new high in the array. If it is greater (i.e. lower on the screen) then skip to line 250 without printing the pixel. This way you don't need the PD in line 235 and can eliminate line 240. Drawing that line takes a lot of time. With this change it runs in about 2:20 which edges out the Atari BASIC. Would be interesting to see how the Atari fares with this change.

There is no big mystery in getting TML. Go to page 1 of Development resources on this site.

Edited by senior_falcon
  • Like 3

Share this post


Link to post
Share on other sites
Make an array to hold the maximum heights of the pixels in each column and initialize it so all the elements are 193. Then, before printing the pixel in line 235 check the row (X1) of the pixel you are about to print. If the row is less (i.e. higher on the screen) than the highest row then print the pixel and store that X1 as the new high in the array.

 

In TI BASIC, are array elements fetched by indexed look-up or by sequential walk up the array's contents? IOW, how much of a penalty is using an array?

 

 

I'll have to that later, after this completes! :)

 

So far at the three hour point...

 

Stop watching it or it will never boil!

  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...