PDA

View Full Version : Sega Megadrive - sprite flipping on the fly, major confusion!



Headcrab
05-23-2012, 04:57 PM
Hi all.

I'm at my wits end with this one! I'm trying to flip a sprite at runtime, by changing the 5th byte in my sprite descriptor struct (live in VRAM).

My sprite:

RunningManSprite:

dc.w 0x0080 ; Y coord (+ 128)
dc.b RunningManDimentions ; Width (bits 0-1) and height (bits 2-3) in tiles
dc.b 0x00 ; Index of next sprite (linked list)
dc.b 0x40 ; H/V flipping (bits 3/4), palette index (bits 5-6), priority (bit 7)
dc.b RunningManTileID ; Index of first tile
dc.w 0x0080 ; X coord (+ 128)



Upload to VRAM (sprite desc. table at 0xE400):

vdp_write_sprite_table equ 0x60000003

LoadSpriteTables:
; a0 - Sprite data address
; d0 - Number of sprites

move.l #vdp_write_sprite_table, vdp_control

subq.b #0x1, d0 ; Minus 1 for counter
@AttrCopy:
move.l (a0)+, vdp_data
move.l (a0)+, vdp_data
dbra d0, @AttrCopy

rts




lea RunningManSprite, a0 ; Sprite table data
move.w #0x1, d0 ; 1 sprite
jsr LoadSpriteTables



So... to flip the sprite horizontally, I need to set bit 3 in byte 5. Surely I can just set the VRAM address to 0x60040003 and push 0x48?

move.l #0x60040003, vdp_control
move.b #0x48, vdp_data




But the sprite disappears completely. I've been scratching my head and poking around various things for hours now. Can anyone spot anything blindingly obvious?

Thanks

Nemesis
05-23-2012, 10:51 PM
You can't do 8-bit writes to the VDP control/data ports. Well, you can, but it doesn't do what you think it should do. The M68000 has a 16-bit data bus. If you do a word write, it performs a single 16-bit bus operation. If you perform a long write, it performs two 16-bit bus operations, one for each 16-bit half of the 32-bit value. If you perform an 8-bit write, it performs a 16-bit bus operation with the 8-bit value mirrored in both the upper and lower 8-bits of the 16-bit data value, and sets the UDS/LDS lines to indicate whether the 8-bit write it targetted at either the upper or the lower half of the 23-bit target address (LSB is dropped). The thing is, the VDP doesn't use the UDS/LDS lines in its address decoding. When you perform an 8-bit write to the VDP, say, with 0x48 like you did above, what the VDP actually sees is a 16-bit write of 0x4848. If you perform a word-wide write instead, targetted at an even VRAM address, you'll get the result you want. This will of course mean that you'll need to write the contents of byte 6 along with byte 5.

Headcrab
05-24-2012, 05:29 PM
Yes! Perfect, thank you so much. I'm sure I read that somewhere when I was starting out, it's just hit me. Anyway it's working fine now.