Log inRegister an accountBrowse CSDbHelp & documentationFacts & StatisticsThe forumsAvailable RSS-feeds on CSDbSupport CSDb Commodore 64 Scene Database
You are not logged in - nap
CSDb User Forums


Forums > C64 Coding > Clearing bitmap screen quickly
2012-05-20 22:47
Taskmaster
Account closed

Registered: May 2012
Posts: 12
Clearing bitmap screen quickly

I've begun tinkering with drawing software sprites to the bitmap screen and I'm already running into serious problem. Good ol' 64. Nice and challenging, just how I remember it.

At any rate, my thought was to take my PC mentality into the rendering here and clear the screen each frame and redraw all the graphics from scratch. This is proving a challenge because ... well, clearing the bitmap memory takes the entire screen refresh and THEN some. Makes for kind of a boring game.

Anyhoo, I tried several methods of loop unrolling and self modifying code but it's just too much. Always too slow.

So I started to think about maybe drawing back over the graphics I drew the last frame and turn those bits off before drawing the new frame. Essentially drawing the frame once so the player can see it, and then inverted to erase it when the time comes.

Is this the generally accepted method on the C=64? I'm running out of options here...
2012-05-21 01:51
Codey

Registered: Oct 2005
Posts: 79
i would zero out any unique bytes that were previously written to only. this could possibly be pre-calculated if you know what you're plotting. keep everything unrolled of course. if u can't do it in a single frame, double buffering would work...
2012-05-21 05:11
Angel of Death

Registered: Apr 2008
Posts: 211
Do you really need to redraw EVERY frame?
No idea what game you are making but 12 to 16 frames/second is generally accepted for a 'vector' game. Then double-buffering is the way to go. (even DOT.NET in Windows uses DB)
For redrawing parts of the screen or just updating seperate objects you could use a sort of partial clear. (with blocks of fixed size?)
If you want to scroll a hires screen then mostly a witches-brew of VSP and hardware-scroll is used, all or not combined with DB. (there should be some games on here showing an example)
2012-05-21 07:24
MagerValp

Registered: Dec 2001
Posts: 1078
You might want to check in the with Plus/4 coders at Plus/4 World since they have a lot of experience working with software sprites. And I assume you have a valid reason for not using char mode and a sprite multiplexer, which is how you typically move a lot of graphics around? If you share what you're trying to achieve it'd be easier to give good suggestions.

I've never implemented software sprites myself, but from what I've gleaned from others the two big cycle savers are keeping pre-rotated sprites in memory so you don't have to shift when blitting, and only erasing what you need to erase.
2012-05-21 07:29
Skate

Registered: Jul 2003
Posts: 494
@Taskmaster: Yes, deleting only the drawn parts instead of the entire screen is a commonly used method on C64. But to achieve that, you have to slow down your drawing routine a little bit. So, if you draw only a few software sprites, you have a gain. But if you plan to draw a lot of them, covering a big part of the screen, a simple drawing routine with an unrolled clear screen code might be faster. So, the answer is "it depends".

If you believe cleaning the drawn parts would be faster, here is the fastest method i know.

clearScreen
sta $ffff
sta $ffff
sta $ffff
sta $ffff
sta $ffff
...


You need a lot of STAs prepared in your initialization routine. You set a pointer to clearScreen+1 address and when you set a byte on the bitmap screen, you write this byte's address as parameters of the STA opcode.

Next thing to do is to increase your pointer by 3. Something like;

lda #<clearScreen+1
sta pointerClearScreen ; a zeropage pointer
lda #>clearScreen+1
sta pointerClearScreen
...
...
ldy #$00
lda #<address
sta (pointerClearScreen),y
iny
lda #>address
sta (pointerClearScreen),y
lda pointerClearScreen
clc
adc #3
sta pointerClearScreen
bcc +
inc pointerClearScreen+1
+


you need to blend this code with your drawing routine and optimize as much as you can.

After you set the last drawing byte you need to put an RTS opcode using pointerClearScreen to the correct position. After that, to clear screen, all you need to do is;

jsr clearScreen


Notes:

1) After you call clearScreen routine, don't forget to replace the last RTS with STA again.
2) Required STAs for each frame would be different. Be sure to have enough STAs reserved for your drawing/cleaning routine. You may want to measure a maximum first and add a 10% to that for safety.
3) If you need double buffering (i think you would...), you will probably need 2x space for cleaning code since clear screen routine is created with the drawing routine. But you may find a way to use the same memory space somehow. It might be possible with a well designed frame switching system, i'm not really sure.
2012-05-21 07:57
Wisdom

Registered: Dec 2001
Posts: 90
You might employ a "dirty rectangles" algorithm, with optionally taking delta of two consecutive frames to determine the final dirty area. Then you can generate an unrolled eraser routine with the addresses of the dirty area on the fly. Just the first thought that came to my mind.
2012-05-21 08:25
enthusi

Registered: May 2004
Posts: 677
It also often helps to just set the FG colors to BG of areas you want 'erased'.
Often when you plot new data into 8x8-blocks you set the bg-col new anyway.
2012-05-21 09:28
Taskmaster
Account closed

Registered: May 2012
Posts: 12
I'm playing around with a little space ship shooter game idea. Player controls a ship that fires at a screen full of randomly spawning enemies and there are some power ups and things they can collect along the way.

Nothing all that complicated but there is a lot of stuff moving around so I didn't want to mess with sprites for this.

At any rate, you guys are BEASTS. Thanks for the ideas! Some of these methods would never have occurred to me.

I'll give this stuff a shot and report back, thanks!
2012-05-21 12:20
Skate

Registered: Jul 2003
Posts: 494
@Taskmaster: I've never coded a shoot'em up game before but afaik, fastest method is using hardware sprites for player & enemies (multiplexers & sorting algorithms are heavily involved) and software sprites for bullets and other small stuff. I know multiplexers are not really easy to handle and using multiplexers may affect your game design (not trying to have more than 8 sprites in a line etc.) but if you try to do everything using software sprites, you shouldn't expect a reasonable FPS i guess.

I remember Doynax was working on some shooter 4-5 years ago. I don't know the project's current status but he may share his experience if he sees this thread.

Edit: I just found this.

http://www.gtw64.co.uk/Pages/b/Review_Ballsofscrolling.php

It seems like Doynax' game is unfinished but it was in a good shape when he decided to abandon the project. He has released the source codes. It may help you to find a faster way for your project.
2012-05-21 12:41
Taskmaster
Account closed

Registered: May 2012
Posts: 12
OK, so this will be a silly question I'm sure but I can't make heads or tails out of the documentation on this.

I know that:

lda #$18
sta $d018

Sets my bitmap screen to be at $2000 ... how do I set it to be at $4000? This SHOULD be simple, and maybe it's just too early in the morning, but I'll be damned if I can figure it out.
2012-05-21 13:02
Mixer

Registered: Apr 2008
Posts: 452
Learn about c-64 memory banks, and address $dd00

Check following for instance. http://unusedino.de/ec64/technical/project64/mapping_c64.html
2012-05-21 13:14
Taskmaster
Account closed

Registered: May 2012
Posts: 12
I appreciate the link, but my hard copy of that book is one of the ones I was looking at. I guess I'll go over it again.
2012-05-21 13:16
Oswald

Registered: Apr 2002
Posts: 5094
http://codebase64.org/doku.php?id=base:vicii_memory_organizing&..
2012-05-21 13:43
Taskmaster
Account closed

Registered: May 2012
Posts: 12
So I need to switch the Vic bank then. :) OK, will try that next time I'm at my home computer. Thanks all!

EDIT : Hey thanks for that link Oswald, that make it click in my head finally!
2012-05-22 00:17
Taskmaster
Account closed

Registered: May 2012
Posts: 12
OK, so I switched the Vic bank and got it rendering on another bitmap screen. Now I just need to toggle the bank each frame to eliminate the flicker.

Shame this eats so much memory. And it really sucks to have to duplicate the screen memory as that's basically just color data that will never change. Blah... Price of the machine I guess.

Anyway, thanks all! On to the next stage of this thing...
2012-05-22 06:46
MagerValp

Registered: Dec 2001
Posts: 1078
Well, this is why we have char mode - 8x improvement in speed and memory usage.
2012-05-22 09:16
Taskmaster
Account closed

Registered: May 2012
Posts: 12
Can someone break that down for me? I'm not getting that.

Bitmap memory is laid out exactly the same as character memory (8 vertical bytes, etc) and to cover the screen with characters would be pretty memory consuming so ... I don't understand where the savings come from. It should be the same speed to copy to/from it so ... ?

Is the C=64 just inherently faster at character graphics or something? I was never aware of this and I feel that I've been cheated. :)
2012-05-22 09:30
JackAsser

Registered: Jun 2002
Posts: 2014
Quote: Can someone break that down for me? I'm not getting that.

Bitmap memory is laid out exactly the same as character memory (8 vertical bytes, etc) and to cover the screen with characters would be pretty memory consuming so ... I don't understand where the savings come from. It should be the same speed to copy to/from it so ... ?

Is the C=64 just inherently faster at character graphics or something? I was never aware of this and I feel that I've been cheated. :)


Well imagine the following (a possible use for char mode and software bobs):

Let's say your object spans 1x1 characters or when unaligned to the character grid 2x2 characters. And say you can move these in half resolution steps. Then you need 2*2*4*4 = 64 different chars to describe all possible combinations. This gives you 256/64=4 different possible background blocks to play with. Splitting the screen every character row into an odd / even charset would double that to 8 different background blocks.

So, in char mode you can very quickly move around an 8x8 pixel object in half resolution motion over a background consisting of 8 various chars if you like. This method would allow you to have "tons" of objects flying around (but they can't intersect each other).

But the normal use on a c64 for a game would of course to use charmode as background and a sprite multiplexer for objects that need pixel precision motion. Use chars for objects that do not need pixel precision objects, like a fast shooting bullet or so.
2012-05-22 10:36
MagerValp

Registered: Dec 2001
Posts: 1078
Quoting Taskmaster
Is the C=64 just inherently faster at character graphics or something?

Basically:
    STA $0400 ; updates 64 pixels
    STA $2000 ; updates 8 pixels
Let's say you want to move 16x16 pixels bobs around on a black background with 2 pixel horizontal resultion and single pixel vertical resolution. For each bob, allocate 9 characters arranged like so:
    036
    147
    258
For each bob, keep four copies of the source graphics in memory, shifted 0, 2, 4, and 6 pixels. Now, to draw the bob into the character buffer, do something along the lines of:
; Call with position in X/Y
; X: 0-158
; y: 0-199
draw_bob_0:
	lda screen_line_lo,y	; get screen coordinates
	sta @screen_line
	lda screen_line_hi,y
	sta @screen_line + 1
	txa
	lsr
	lsr
	sta @screen_offset
	
	txa			; select source image
	and #3
	tax
	lda bob_src_lo,x
	sta @bob_src
	lda bob_src_hi,x
	sta @bob_src + 1
	
	tya
	and #7
	sta @save_y_and_7
	jsr erase_bob_0		; erase unused lines in buffer

@save_y_and_7 = * + 1		; get offsets for source and dest
	lda #$5e
	ora #$40
	tay
	ldx #$3f
@copy:				; copy shifted image
@bob_src = * + 1
	lda $5e1f,x
	sta bob_0_buf,x
	dey
	dex
	bpl @copy

You can now plot these 9 chars into the screen using the address in @screen_line + @screen_offset. To erase it again all you have to do is zero out those 9 chars on the screen.

There is a lot of room for optimization here and you can do a lot of unrolling - it's just a question of how much memory you can spare. If you don't need smooth movement it gets a lot easier of course, e.g. for bullets it's common to just plot 8x8 chars on the grid.
2012-05-22 11:44
Taskmaster
Account closed

Registered: May 2012
Posts: 12
Ahh OK. This code assumes no overlap though, right? If a blob touches another blob, it will just overwrite what's there as opposed to OR'ing anything together. Choices and compromises...
2012-05-22 16:07
MagerValp

Registered: Dec 2001
Posts: 1078
You also have to manage backgrounds and masking manually if you don't want a blank background.

Meanwhile a 32-sprite multiplexer manages all of this without breaking a sweat at 50 fps.
2012-05-22 19:06
Taskmaster
Account closed

Registered: May 2012
Posts: 12
The most direct path is not always the most interesting one .... you know? :)
RefreshSubscribe to this thread:

You need to be logged in to post in the forum.

Search the forum:
Search   for   in  
All times are CET.
Search CSDb
Advanced
Users Online
DJ Gruby/TRiAD
kbs/Pht/Lxt
The Syndrom/TIA/Pret..
leonofsgr/Singular C..
Freeze/Blazon
Guests online: 92
Top Demos
1 Next Level  (9.7)
2 13:37  (9.7)
3 Mojo  (9.7)
4 Coma Light 13  (9.6)
5 Edge of Disgrace  (9.6)
6 What Is The Matrix 2  (9.6)
7 The Demo Coder  (9.6)
8 Uncensored  (9.6)
9 Comaland 100%  (9.6)
10 Wonderland XIV  (9.6)
Top onefile Demos
1 No Listen  (9.6)
2 Layers  (9.6)
3 Cubic Dream  (9.6)
4 Party Elk 2  (9.6)
5 Copper Booze  (9.6)
6 Dawnfall V1.1  (9.5)
7 Rainbow Connection  (9.5)
8 Onscreen 5k  (9.5)
9 Morph  (9.5)
10 Libertongo  (9.5)
Top Groups
1 Performers  (9.3)
2 Booze Design  (9.3)
3 Oxyron  (9.3)
4 Triad  (9.3)
5 Censor Design  (9.3)
Top Graphicians
1 Mirage  (9.8)
2 Archmage  (9.7)
3 Pal  (9.6)
4 Carrion  (9.6)
5 Sulevi  (9.6)

Home - Disclaimer
Copyright © No Name 2001-2024
Page generated in: 0.062 sec.