In this post I will describe how to draw sprites using the Sega Genesis VDP emulator.
The process for rendering sprites is very similar to rendering tiles:
- Loading colors into CRAM
- Upload parts of 8×8 sprites to VRAM
- Filling the Sprite Table in VRAM
For example, let’s take a skeleton sprite with a sword 32×32 pixels
Skeleton Guy [Animated] by Disthorn
Let’s use ImaGenesis to convert it to CRAM colors and VRAM patterns for assembler. After that we get two files in asm format, then we rewrite the colors to the word size, and the tiles must be put in the correct order for rendering.
Interesting information: you can switch the VDP auto-increment through register 0xF to word size, this will remove the address increment from the CRAM color fill code.
The shogi manula has the correct tile order for large sprites, but we’re smarter, so we’ll take the indexes from the blog ChibiAkumas , let’s start counting from index 0:
0 4 8 12
1 5 9 13
2 6 10 14
3 7 11 15
Why is everyone upside down? And what do you want, because the prefix is Japanese! It could have been from right to left!
Let’s manually change the order in the sprite asm file:
Sprite: dc.l $11111111 ; Tile #0 dc.l $11111111 dc.l $11111111 dc.l $11111111 dc.l $11111111 dc.l $11111111 dc.l $11111111 dc.l $11111111 dc.l $11111111 ; Tile #4 dc.l $11111111 dc.l $11111111 dc.l $11111111 dc.l $11111111 dc.l $11111111 dc.l $11111111 dc.l $11111111 dc.l $11111111 ; Tile #8 dc.l $11111111 dc.l $11111111 dc.l $11111111 dc.l $11111111 dc.l $11111122 dc.l $11111122 dc.l $11111166 dc.l $11111166 ; Tile #12 dc.l $11111166 dc.l $11111166 и т.д.
Load the sprite like regular tiles / patterns:
SpriteVRAM: lea Sprite,a0 move.l #$40200000,vdp_control_port; write to VRAM command move.w #128,d0 ; (16*8 rows of sprite) counter SpriteVRAMLoop: move.l (a0)+,vdp_data_port; dbra d0,SpriteVRAMLoop
To draw the sprite, it remains to fill the Sprite Table
The sprite table is filled in VRAM, the address of its location is put in the VDP register 0x05, the address is again tricky, you can see it in the manual, an example for the F000 address:
dc.b $78 ; 0x05: Sprite table at VRAM 0xF000 (bits 0-6 = bits 9-15)
Ok, now let’s write our sprite to the table. To do this, you need to fill in the data “structure” consisting of four words. You can find a binary description of the structure in the manual. Personally, I made it easier, the sprite sheet can be edited manually in the Exodus emulator.
The structure parameters are obvious from the name, for example XPos, YPos – coordinates, Tiles – starting tile number for drawing, HSize, VSize – sprite sizes by adding 8×8 parts, HFlip, VFlip – hardware horizontal and vertical sprite rotations.
It is very important to remember that sprites can be off-screen, this is the correct behavior. unloading off-screen sprites from memory is quite a resource-intensive task.
After filling in the data in the emulator, they need to be copied from VRAM at 0xF000, Exodus also supports this feature.
By analogy with drawing tiles, first we turn to the VDP control port to start recording at 0xF000, then write the structure to the data port.
Let me remind you that the description of VRAM addressing can be read in the manual, or in the blog Nameless Algorithm .
In short, VDP addressing works like this:
[..DC BA98 7654 3210 …. …. …. ..FE]
Where hex is the position of the bit in the desired address. The first two bits are the type of the requested command, for example 01 – write to VRAM. Then for the address 0XF000 it turns out:
0111 0000 0000 0000 0000 0000 0000 0011 (70000003)
As a result, we get the code:
SpriteTable: move.l #$70000003,vdp_control_port move.w #$0100,vdp_data_port move.w #$0F00,vdp_data_port move.w #$0001,vdp_data_port move.w #$0100,vdp_data_port
After that, the skeleton sprite will be displayed at coordinates 256, 256. Cool yes?