Videopac / Odyssey2 forum

Programming the Videopac / Odyssey2 => Unreleased HomeBrew and test code => Topic started by: LD on March 22, 2015, 04:40:44 PM



Title: "Horizontal flip" by software
Post by: LD on March 22, 2015, 04:40:44 PM
On Atari 2600 we have a register (REFPx) that turns the sprite horizontally, so if you have a sprite facing to right, set this register and the sprite is displayed facing to the left.
There's no such feature on Odyssey 2, you need to draw the same sprite twice, one for each facing.
Each sprite facing waste 8 bytes of ROM, so I had the idea to make a code to switch the facing by software.

There are 3 ways to make this (that I know) :

1 - Set individual pixels each time using byte shift and carry. The problem this code is very slow and need 64 loops to change all the 8 bytes of a single sprite. Probably this take more of the available time you have on VBlank.

2 - Flip each nibble at time. This is the code I'm using, still slow, and require a table of 16 bytes. The code itself including the table takes about 50 bytes of ROM space. It require 8 loops to flip the sprite.

3 - Flip each byte at time - The faster one, done in 8 loops,  but require a table of 256 bytes, you can store 32 sprites in this amount of ROM.

So my code flips each nibble at time, and like I said, uses about 50 bytes of ROM. You can store 6 sprites on that amount of ROM, so this code only is useful if you need flip more than 6 individual sprites, less than that you should flip them manually and not using the code, else you're wasting ROM and VBlank Time.

How it works : put the sprite on VDC RAM normally, after that, call a subroutine and it will flip the sprite that is pointed at R0, here's the code :
(no RAM needed and uses registers R0 to R4)

Code:
   mov R0,#080h       ;Sprite to be mirrored (80 or 88 or 90 or 98)
   call Mirroring     ;go to mirror code

;----------------------------------------------
Mirroring ;Subroutine
;----------------------------------------------
mov R4,#8
GetNibble
movx a,@R0
mov R1,a
;---
anl a,#00Fh
mov R2,#TableMirror & 0ffh
add a,R2
movp a,@a
swap a
mov R3,a
;---
mov a,R1 ;xxxx0000
swap a ;0000xxxx
anl a,#00Fh
mov R2,#TableMirror & 0ffh
add a,R2
movp a,@a
orl a,R3
movx @R0,a
inc R0
djnz R4,GetNibble
ret
TableMirror
db 0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15

The code needs to be run during Vblank (VDC Off) but you can store the result on extra RAM and later update to the sprite RAM, for calculate it off VBlank time.

EDIT : Code was optimized


Title: Re: "Horizontal flip" by software
Post by: gertk on March 22, 2015, 05:08:21 PM
There are several ways to flip a byte but each of these routines will consume more memory than the 8 bytes you try to spare...  :)


Title: Re: "Horizontal flip" by software
Post by: LD on March 22, 2015, 09:35:21 PM
If you know a faster way please, share :)

I'm not trying to make something smaller than 8 bytes, but something small and fast as possible. :)

This code based on nibble is half way between others two.


Title: Re: "Horizontal flip" by software
Post by: Rene_G7400 on March 23, 2015, 09:24:07 AM
Although this is a very interesting experiment, I think that CPU time (especially in Vblank) will usually be a bigger problem than ROM space (especially on NTSC consoles).


Title: Re: "Horizontal flip" by software
Post by: gertk on March 23, 2015, 12:10:35 PM
If you know a faster way please, share :)

I'm not trying to make something smaller than 8 bytes, but something small and fast as possible. :)

This code based on nibble is half way between others two.


The fastest and smallest way is to pre-calculate every sprite which needs reversing and store that data in rom, then use (unrolled) loops to copy them to the VDC. If you place them smartly into different pages you can use a single pointer/index register.


Title: Re: "Horizontal flip" by software
Post by: LD on March 23, 2015, 11:07:05 PM
Although this is a very interesting experiment, I think that CPU time (especially in Vblank) will usually be a bigger problem than ROM space (especially on NTSC consoles).

Usually games for Odyssey 2 / Videopac are minimalist in usage of sprites and animations.
But in games that you need a lot of animation frames, perhaps this code can help to save some ROM.
I don't know exactly how many cycles this code will take, but assuming it's something like 30 cycles, it will takes 1.5 scanline to flip the sprite.
Not that bad, actually.


Title: Re: "Horizontal flip" by software
Post by: Mux on April 25, 2019, 10:04:37 PM
Couple of years late but optimization is always a trade-off between CPU and memory. A bit of an in-between would be to have a 16-byte look-up table and use SWAP to get the upper / lower nibbles. Won't be as fast but faster than using rotates only..

-Mux


Title: Re: "Horizontal flip" by software
Post by: LD on May 02, 2019, 11:27:22 PM
That's what I'm doing ;)

Actually, now reading my old code, I found some optimizations....
I don't need R1 and R2 at all... this saves 2 cycles and 3 bytes... not much but works!
The new code uses now registers R0 to R2 :)
It takes about 26 cycles and waste 39 bytes.

Here is  :

Code:
   mov R0,#080h       ;Sprite to be mirrored (80 or 88 or 90 or 98)
   call Mirroring     ;go to mirror code

;----------------------------------------------
Mirroring ;Subroutine
;----------------------------------------------
mov R1,#8
GetNibble
movx a,@R0
anl a,#00Fh
add a,#TableMirror & 0ffh
movp a,@a
swap a
mov R2,a
;---
movx a,@R0 ;xxxx0000
swap a ;0000xxxx
anl a,#00Fh
add a,#TableMirror & 0ffh
movp a,@a
orl a,R2
movx @R0,a
inc R0
djnz R1,GetNibble
ret
TableMirror
db 0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15

And the ROM for you try on emulators.
Hold button to flip the sprite! What a demo!


Title: Re: "Horizontal flip" by software
Post by: Janzl on May 03, 2019, 07:45:19 AM
And the ROM for you try on emulators.
Hold button to flip the sprite! What a demo!

You should start up a scene  :D


Title: Re: "Horizontal flip" by software
Post by: LD on May 04, 2019, 12:37:50 AM
I have some ideas for a demo, actually...
The problem I'm not that good for code it.  :'(