Tuesday, 29th July 2008
I've got a fairly hackish "graphical text" mode set up (enabled with VDU 5, disabled with VDU 4) that causes all text that is sent to the console to be drawn using the current graphics mode (at the graphics cursor position, using the graphics colour and logical plotting mode and graphics viewport). This allows text to be drawn at any position on-screen, but is (understandably) a bit slower and doesn't let you do some of the things you may be used to (such as scrolling text, copy-key editing and the like).
I've also done some work on a tool to convert files from the PC to use in BBC BASIC. It takes the form of a Notepad-like text editor:
BBC BASIC programs are stored in a tokenised format (usually .bbc files on a PC) and need to be wrapped into a .8xp for transferring to the calculator. The editor above can open .8xp, .bbc and .txt directly, and will save to .8xp.
The detokeniser can be passed a number of settings, which can be used to (for example) generate HTML output, like this. The indentation is generated by the detokeniser (leading/trailing whitespace is stripped by the tokeniser). The tool can also be used to directly convert binaries into .8xp files if need be.
I've been doing a little work on a flood-filling algorithm. (PLOT 128-135, 136-143). The above images show its progress; on the left is the first version (which can only fill in black). There is a hole in the bottom-left of the shape, so the leaking is intentional. It also stops one pixel away from the screen boundary -- this too is intentional (it clips against the viewport). The second version, in the middle, plugs the leak and applies a pattern (which will be a dither pattern in BBC BASIC) to the filled area. On the right is the third version, which will fill over black or white pixels with a pattern.
The main filling algorithm needs a 764 byte buffer for the node queue and three 16-bit pointer variables to manage the queue. I've rounded the queue size up to 768 bytes, so it fits neatly on one of the RAM areas designed to store a bitmap of the display.
The problem is filling with a pattern. The way I currently do this is to back up the current screen image to a second 768-byte buffer, fill in black as normal, then compare the two buffers to work out which bits have been filled and use those as a mask to overlay the dither pattern. This is quite a lot of RAM, just to flood-fill an image!
For those who are interested, I'm using the "practical" implementation of a flood fill algorithm from Wikipedia.
Monday, 21st July 2008
Back to work on the TI-83 Plus port of BBC BASIC! To complement the graphics viewport I've added support for text viewports — this lets you define the area the text console uses. The following VDU commands are now supported:
- VDU 24,<left>;<top>;<right>;<bottom>;
Define a graphics viewport.
- VDU 28,<left>,<top>,<right>,<bottom>
Define a text viewport.
- VDU 26
Reset both viewports to their default settings (full screen).
- VDU 29,<x>;<y>;
Defines the graphics origin.
The above screenshots defines the graphics viewport to fill the left hand side of the screen and shunts the text viewport over to the right half, using the following code:
VDU 24,0;0;47;63; VDU 28,12,0,23,9 VDU 29,24;32;I've also added simple sprite drawing to BBC BASIC's PLOT command. PLOT usually takes a shape type and two coordinates, but for sprites (shapes 208..215) I've added an extra parameter - the address of the sprite data to use.
10 DIM ball 7 20 ball?0=&3C 30 ball?1=&5E 40 ball?2=&8F 50 ball?3=&DF 60 ball?4=&FF 70 ball?5=&FF 80 ball?6=&7E 90 ball?7=&3C 100 *REFRESH OFF 110 REPEAT 120 CLG 130 T=TIME/100 140 FOR P=0 TO 5 150 A=P/3*PI+T 160 X=16*SIN(A)+44 170 Y=16*COS(A)+28 180 PLOT 213,X,Y,ball 190 NEXT 200 *REFRESH 210 UNTIL INKEY(0)<>-1 220 *REFRESH ON
The above code allocates 8 bytes of memory (DIM ball 7) then copies the sprite data to it by use of the ? indirection operator. This is a little laborious, so in reality you'd probably store your sprites in a binary file external to the main program, and might load them like this:
10 ball%=FN_loadSprite("SPRITES",0) 20 face%=FN_loadSprite("SPRITES",1) 30 *REFRESH OFF 40 REPEAT 50 CLG 60 T=TIME/100 70 FOR P=0 TO 5 80 A=P/3*PI+T 90 X=16*SIN(A)+44 100 Y=16*COS(A)+28 110 PLOT 213,X,Y,ball% 120 NEXT 130 PLOT 213,44,28,face% 140 *REFRESH 150 UNTIL INKEY(0)<>-1 160 *REFRESH ON 170 END 180 DEF FN_loadSprite(f$,i%) 190 fh%=OPENIN(f$) 200 PTR#fh%=i%*8 210 DIM spr 7 220 FOR j%=0 TO 7 230 spr?j%=BGET#fh% 240 NEXT j% 250 CLOSE#fh% 260 =spr 270 ENDPROC
(Note FN_loadSprite() at the end of the program). The result is the following:
Next up: drawing text at the graphics cursor position (as sprites).
Thursday, 3rd July 2008
This journal is starting to look a little drab, so here's a splash of colour.
Not really all that colourful, on second thoughts. I fancied a short break from BBC BASIC, and seeing that the current XNA CTP supports VS 2008 I thought I'd try a bit more work on hardware-accelerated 3D. I've never worked with shadows, bump mapping or visibility portals, and have a copy of DOOM 3, so thought that would provide a nice set of resources to experiment with.
The screenshots are generated by simply brute-force rendering of all surfaces of all models in a level (.proc) file. The odd colours and lighting are courtesy of the default lighting provided by the BasicEffect class. The level files are simple to parse (they're just text files breaking each surface down into vertex and index arrays, ready to be fed to the video hardware), so though I've not found much documentation on them it's been pretty easy to guess what's what so far.
The above textures are loaded by taking the material name and appending .tga, which seems to return a random mixture of specular, diffuse or normal maps. There is a materials directory that appears to contain definitions for which image file to use for each different type of texture map, so that looks like the next thing to investigate.