Login
Back to forumSee the full topicGo to last reply

Posted By

Rybags
on 2010-11-09
08:41:17
 Re: Assembly and interrupts: my first attempt. Help needed!

Buffering then moving sprite data isn't really the done thing on our slow old computers.

You can fare better by doing one or more of the following:

1. Trigger your "VBlank" IRQ via a Raster Int request for a scanline near the bottom of the display window portion of the screen. That means you'll get maximum non-display time to do screen changes.
If it's the case that you do stuff like read joysticks, move object x/y positions around etc you might find that task takes a good number of scanlines. As such, you could move your IRQ upwards such that these preliminary tasks take place during the display area.
"Raster bars" as a debug aid can help here... e.g. have the border black, then change it temporarily to other colours during each stage of your per-frame processing.

2. "Double-buffering" - if you're moving lots of stuff around it can be more beneficial sometimes to just have 2 screens. Do all the erases and updates on the "non-active" screen copy while the "active" screen is being displayed, then switch to the non-active screen once a VBlank has occurred and that screen is ready.

3. Pre-Shifted sprites. Bigger memory cost, but much quicker to put to screen than having an object that you have to run through shift/rotate instructions.

4. The Brute-Force approach. Can cost a lot of memory, but the fastest way to do software sprites. Rather than reading from definitions by instructions like LDA (Sprite_ptr),Y - use immediate mode instructions to read the sprite data.
Not necessarily valid for all your moving objects, but for little things like bullets and pickup objects could save you sufficient time to do plenty of other processing.

Additional to that, there's a method we call the "Stripe Method" where you just have a huge block of instructions.

Imagine the code block:
lda screen,x
and mask,y
ora sprite,y
sta screen,x
iny

Repeat that code block such that every single possible vertical screen offset is catered for. So you'd have screen+1 through +7, then 320 to 327, 640 to 647 etc.

So, you end up with this big block of code - it must reside in RAM because you need to self-modify it. The entry point to the block of code is dependant on what the Sprite's Y position is. So, you calculate the offset needed, then self-modify a JSR instruction that calls the routine. You preload the Y register with the offset to your sprite "stripe" segment.
Also before calling, you need to insert an RTS instruction, so calculate the offset for that one too. Save that calculated address so you can restore the "iny" instruction later.
The limitation is that the block of code can only cater for 4x256 pixels worth of sprite data, any more and you need more code blocks pointing to different sprite/mask areas. Also the sprite data has to be pre-shifted, so effectively we lose out quite a bit there too.
Set the X register to the "stripe number", ie for a 12 pixel wide sprite, you'd call the routine in succession with X=0 then 1 then 2. If the sprite isn't right-justified to a 4-pixel boundary, then you'd call it again with X=3.



Back to top


Copyright © Plus/4 World Team, 2001-2024