Page 1 of 2

Fire effect

Posted: Sat Nov 19, 2011 12:48 pm
by Kananga
After two months of "serious" programming for the FE3 RAM Disk, I needed a break and had a go at implementing the fire effect from C-64 version on the VIC-20.
It uses custom characters to display dithered colours, so it was not too difficult to adopt it for the VIC-20. And it runs on the unexpanded Vic.

Then I put some bloat in by adding a (slow) scroller and playback of a digitized sound sample. (needs 24K RAM)

Have fun with my first "intro"!

Source code

Posted: Sat Nov 19, 2011 7:41 pm
by Wilson
Yay! I liked this a lot.
edit: Oops, should've read the readme :mrgreen:
The expanded version is great! It has a very cozy vibe. Perfect for the season. Thanks, Kananga. :)

Posted: Sun Nov 20, 2011 6:33 am
by Boray
Hmmm.... Where is the .prg?

Posted: Sun Nov 20, 2011 10:17 am
by Kananga
Boray wrote:Hmmm.... Where is the .prg?
here :)

Posted: Sun Nov 20, 2011 4:52 pm
by Boray
Cool

Posted: Mon Nov 21, 2011 6:15 am
by joshuadenmark
Hi Kananga

Thanks for sharing this awesome fire demo, liked it alot :D

Posted: Mon Nov 21, 2011 6:55 am
by orion70
Me too, will try it on the real VIC tonight... :)

Posted: Mon Nov 21, 2011 1:33 pm
by Kananga
Thank you all, but I did not do much.
Just took this fire demo for C-64, Jeff's font and put it together.

BTW, if anybody got an idea how to make computing the fire faster, I'd really appreciate to read it :)

It takes way more time than a screen refresh and therefore I did not bother to sync it with vertical retrace in the unexpanded version. The principle is quite easy:

seed the bottom line with new (pseudo-random) characters
for each screen position do (starting from top)
add the character value and the three characters below it
subtract 3 and divide by 4
write the value to the current position

custom characters are filled with patterns for increasing heat,
i.e. 0 is black/empty, 1 has a few red dots, ... more yellow added ... up to character 63 (so the sum of 4 characters is less than 256)

Simple but nice to watch.

Posted: Mon Nov 21, 2011 2:01 pm
by orion70
Kananga wrote:Simple but nice to watch.
...like all good programs for the VIC :) . Great effect also on the real machine.

Posted: Mon Nov 21, 2011 2:15 pm
by Mike
Kananga wrote:BTW, if anybody got an idea how to make computing the fire faster, I'd really appreciate to read it :)
This table based routine takes 34 cycles (+ some extra ones, when a page is crossed) for each character:

Code: Select all

.loop
 CLC                    ;  2
 LDA base,Y             ;  4
 ADC base+offset-1,Y    ;  4
 ADC base+offset  ,Y    ;  4
 ADC base+offset+1,Y    ;  4
 TAX                    ;  2
 LDA table,X            ;  4
 STA base,Y             ;  5
 INY                    ;  2
 BNE loop               ;  3
-----------------------------------
                          34 cycles
Greetings,

Michael

Posted: Tue Nov 22, 2011 1:22 am
by Kananga
Mike wrote: This table based routine takes 34 cycles (+ some extra ones, when a page is crossed) for each character:

Code: Select all

.loop
 CLC                    ;  2
 LDA base,Y             ;  4
 ADC base+offset-1,Y    ;  4
 ADC base+offset  ,Y    ;  4
 ADC base+offset+1,Y    ;  4
 TAX                    ;  2
 LDA table,X            ;  4
 STA base,Y             ;  5
 INY                    ;  2
 BNE loop               ;  3
-----------------------------------
                          34 cycles
Thanks! :)

In order to get rid of the cycles for indirect ZP-based addressing, you need this routine four times (Screen memory spreads over 4 pages), giving ~34000 cycles. Screen refresh happens approx. every 22000 cycles (PAL). For the version with the scroll text, I have left out one page of video RAM, which still results in ~26000 cycles.

It is perhaps not doable in under 22K cycles without reducing the screen size.

Posted: Tue Nov 22, 2011 3:33 pm
by Mike
Kananga wrote:It is perhaps not doable in under 22K cycles without reducing the screen size.
You could also try to do the effect with double-height characters.

Posted: Tue Nov 22, 2011 4:58 pm
by Kweepa
You can move the CLC out of the loop since the ADCs are guaranteed not to overflow.
You can use LSR/LSR instead of TAX/LDA tab,X which is 2 cycles less, if you can put up with some noise (!) in the fire from not clearing the carry. Might actually be preferable.
You could also put all four updates inside the same loop with different base values, to save 15*256 cycles on loop checking. There might be an obvious artifact at each page boundary though, I'm not sure.
I make that 256*(3*25 + 30) = 26880 full screen.
Leaving out one page makes it 256*(2*25 + 30) = 20480.

[EDIT: ah, I misunderstood the algorithm. Still, some of these ideas are valid... just not the LSR/LSR...

256*(2*27 + 32) = 22016. So close! Unrolling again...
128*(5*27 + 32) = 21376. Phew! Unrolling again...
64*(11*27 + 32) = 21056.
A full unroll would be 20736, so this is a good balance.]

[EDIT 2: I tested this, and didn't see any obvious artifacts. Whee!]

Posted: Wed Nov 23, 2011 1:54 am
by Kananga
Kweepa wrote: 256*(2*27 + 32) = 22016. So close! Unrolling again...
128*(5*27 + 32) = 21376. Phew! Unrolling again...
64*(11*27 + 32) = 21056.
A full unroll would be 20736, so this is a good balance.]

[EDIT 2: I tested this, and didn't see any obvious artifacts. Whee!]
Great! :D

Posted: Wed Nov 23, 2011 3:49 am
by Jeff-20
I'm just amazed by this. I don't remember my font being so large... and multicolor... and smoothly scrolling pixel by pixel. Great demo!