In this post, I thought I would start to delve a bit deeper into the actual problems I have encountered tinkering with the DTV system, as well as introducing some assembly language concepts and problem solving, so that others can perhaps gain from the scenarios introduced.
Ok, so the strange bug that was either causing a distorted character image to be rendered, or the background restored image to be trashed has been fixed.
While a vid would have been better, heres an image of the character having moved left of its original position and nothing has gone wrong: (Ive also cheated and used DTV v3 emulation, which fixes the HW blit bugs, but I will work around those if I can)
DMAsc038.png
So now I can focus on the actual movement of the character, which seems a bit flickery and very likely too slow, once other parts have been eventually added into the mix. The final outcome (it is hoped) being to see if I can create a game engine based on either high level function libraries, or (if I go the whole hog) a low level BASIC language compiler for others to make use of. Im not sure if anything like this has ever been created on the C64DTV, but it will be fun to see how far we can go.
Most (if not all) of the engine specifics will be based on the workings of my DC1 game engine, which is currently PC based. A version is also planned for the 68k machines. (ST to start with, as Amiga already has Scorpion/Redpill/BlitzBasic/AMOS/etc), whereas the Atari has far less choice.
Anyway, I digress...
Where was I? Oh yes, flickery character movement.
I already know what is causing this;
In an attempt to make the code as 'user friendly' as possible, my blitter based draw routines have MACRO based support.
So to draw an image with the blitter (from assembly) its as simple as preloading the variables in the brackets with the required data and calling:
DrawImageBB(Image,x,y,ImageFrame)
Where:
Image is the image base address
x is the x screen position to start from
y ...as above but y
ImageFrame is the actual frame index in the image to display.
All image size and frame sizes are already known and set (but alternatively could be put into variable data and set from the DrawImageBB command itself if required) and the correct source and destination buffers are already set up accordingly.
This is all pretty smooth so far. The problem being, that to hammer this out so it would work, I used a 16 bit multiply routine to transform the (easy to maintain) Cartesian co-ordinates that are fed to the MACRO for x and y, to the rasterised data needed for the blitter source/destination registers.
For those who dont know, unlike the MC68000+ CPUs, the 6502/6510 and the slightly different variant in the DTV do not have a multiplication or division instruction. So creating not just an 8, but 16 bit multiply routine (although pretty quick for what it is), is very costly, processor cycle-wise. Hence the flickering and not particularly super fast speed that we need so we can add extra elements and not bog the system down excessively.
So what can we do?
Well, my favourite rule of thumb, if we have a relatively slow processor, but ample RAM, offload the processing to RAM if possible. What does this mean?
Use pre calculated data tables.
Now, instead of using a slow multiplication routine to calculate image position, I just need to supply the MACRO with the blocks y position (in this case, the character image) and an indexed addressing mode can be used to extract the position for a far quicker MACRO process:
Code: Select all
lda Char_y
asl y // dont forget to double y index as the data field is words NOT bytes!
tay // put acc. into y reg for below indexing
lda (Left_screen_lookup data),y // y is image x axis start of line position ****
sta Store
lda (Left_screen_lookup data),y+1 // y is image x axis start of line position ****
sta Store+1
lda Char_x+1 // now get the x axis position of char...
adc Store+1 //...and add it to the first x axis pixel on the screen position...
//...to get the starting point for the blit destination registers
lda Char_x // now get the x axis position of char...
adc Store //...and add it to the first x axis pixel on the screen position...
//...to get the starting point for the blit destination registers
// **** ****
// **** Where 'Left_screen_lookup_data' holds the leftmost x pixel raster ****
// **** data position for every single y axis position of the display. ****
// **** ****
Left_screen_lookup data: .word //+320 for every +y axis value
$0000,$0140,$0280,$03c0,$0500,$0640,$0780,$08c0,$0a00,$0b40,$0c80,$0dc0,$0f00,$1040,$1180,$12c0,$1400,$1540,$1680,$17c0,$1900,$1a40 //etc
Whilst I havent yet tested the above code, replacing the multiplication of the MACRO with the above should greatly improve the speed of the process.
For the next post, I will install the faster routines and do a 'before - after' video comparison of the speed difference.
In the meantime, I will be looking also at ways to streamline the blit process. Currently, I am blitting individual blocks. Each call to DrawImageBB() is blitting the single block immediately. What I need to do, is change the MACRO so that each DrawImage() call transfers blit data to a list of blit jobs. Then when all the blit jobs have been written to the list (or the frame runs out of time!) the blitter becomes operational and - at the optimum position of the raster beam - begins drawing all the block images all together from data on the list.
But thats some food for thought that needs a bit more of a chew.