Genesis Development: Sprite Tuts

Edge-`

New Member
Heya Guys,

I was wondering if anyone can point me to tutorials (newbie level even :D) in regards to the basics of displaying images, sprites, backgrounds on the genesis. I started learning a bit of programming on the genny awhile back but I got a bit busy. I'd like to try my hand at possibly making some games now that I can test them on the Genesis and that I have a bit more education in programming in C/C++ and a basic knowledge of ASM.

I'm new to game programming, but not new to programming with C++, fairly new to ASM. I'm really interesed in the basics of displaying graphics, sprites, moving them, etc. Any help to jumpstart my genny programming would be appreciated :D.
 

Mask of Destiny

New Member
I have a 68K assembly tutorial over at my site ( http://www.pages.drexel.edu/~mrp29/index.html ) over in the Sega CD section. I do plan on writing some basic Sega CD programming tutorials (which will focus mainly on the Genesis hardware) soon, but I haven't started yet.

There are some Genesis tutorials over at http://www.emulationzone.org/projects/metalix/ Those might be of some help.

The Sozobon C compiler for Genesis has some demos with it that are set up sort of like a tutorial.

For documentation on the hardware I'd head over to Charles MacDonald's site ( http://cgfm2.emuviews.com/ ).
 

Edge-`

New Member
Thanks Mask of Destiny,

I often see your posts at the Tavern at Eidolons (which I'm glad is back :D).

I'll check out the tutorials. Kaneda's site seems to be quite helpful as well. With the recent tools that have come out, is it possible to develop mostly in C? I mean there are several tools to convert the graphics, sound, etc. to the format require to link with the C compiler.

Anyway, making some personal progress from the demos and example sources. Thanks for the links :)
 

Mask of Destiny

New Member
It is entirely possible to develop completely in C, though I'm not sure how low-level you have to get with the C environment on the Genesis. I don't know how well developed it is.

You might want to check out Kevin Bank's site( http://home.hiwaay.net/~kbanks/ ). He has several programs for the Genesis written in C which he has provided source for.
 

ExCyber

Staff member
It is entirely possible to develop completely in C
Is there a free 68K compiler out there that supports interrupts? IIRC, GCC doesn't because it would be this tremendous pain in the ass to change its internal architecture to support it. I suppose asm wrapper functions would do the same thing better anyhow...
 

Mask of Destiny

New Member
There is very limited support for interrupts in both the GCC and sozobon packages. Ib eliev it's set up to increment/set a variable so that you know when you've reached VBlank or HBlank, but it doesn't support assigning a function as an interrupt handler.
 

Edge-`

New Member
I was wondering if someone could provide me an example of loading two sprites into vram and then displaying the two sprites. I understand writing the sprites to memory, but I'm not exactly sure how to display two or more sprites at once. Forgive my newbie level on this. So far its been quite fasinating to say the least, I've written several text display-related functions, but many aspects such as storing the sprites then knowing what memory address that sprite is stored at is causing me a bit of greif.

We have an excellent community of Saturn dev. here, maybe we can promote the same for Genesis Dev. Tools are getting easier and easier now. Maybe add a new section under Saturn Development for Genesis Development if enough are intersted :D.
 

ExCyber

Staff member
A lot of it is configurable, and the sprite system in Genesis is a little more like some arcade hardware than like e.g. TMS9918. You actually put together a linked list of sprites in memory that the VDP follows to draw sprites. I don't have time to put down all the details, but basically you have to set up the VRAM locations for the sprite patterns and sprite list, then write the sprite list. Each sprite has a "linking" value that specifies the next sprite to render, and then there has to be an "end of list" entry. Details can be found in Charles MacDonald's VDP doc.
 

Mask of Destiny

New Member
Excyber pretty much summed it up.

If you're programming in assembly and want to make your life a bit easier, I have a sprite library that does most of the work for you. It still needs a lot of work before it's truly complete, but it does handle managing the sprite list quite well and does have some preliminary support for large sprites and sprite animation (though at the moment you can only do this with one "big" sprite at a time)

If you want to use it, I'll post it up.
 

Edge-`

New Member
I think I'm picking up the just of it. Just need to keep track of the size of the sprites when they are being copied to vram so that you may grab the correct parts when you need to display. Thanks for the description ExCyber.

I'm currently just doing C at the moment Mask of Destiny, but I'm sure I can extern the functions in if you are willing to share the code :>.

Edit in regards to my problems displaying sprites: I found out what I was doing wrong that was causing me so much grief. When I was using bmp2tile to create sprites I was outputting the assembly of the sprites in tile mode instead of sprite mode. After I did this correctly all of my code worked perfectly and displayed at the right x and y (where as before it would not display at all or just display at 0,0).

I do have a question that could be easily answered. When displaying a sprite, how is the size determined. In several examples I see a 2x2 sprite's size is 0x500, 5x4 sprite is 0xF00 which didn't make sense exactly to me. I assume its calculated by like length * width * 32 and then shifted by some amount to set the.
 

Edge-`

New Member
Alright,

Well I was able to get this down finally. It seems MUCH simpler now and the documents make much more sense. Here is a screenshot of a simple demo program I did based off of the other demos for using SGCC.



Shows a background from Aqua Teen Hunger Force (the pilot episodes) and a small sprite of shake that can be controlled via the genny controller. (I'm a HUGE ATHF fan btw). For as simple as the main characters are drawn, damn there are a lot of colors in the backgrounds of ATHF, the background is a bit granulated from the conversion :D.

For those who are curious here is the C code. All the externs are from .asm files created by bmp2tile (a background image and the shake sprite). If you are really curious and want the .bin, let me know.

I hope to get better at this, my main concern was learning to display the graphics and then sound (which will have to come a bit later). My motivation and goal is to make a Advance Wars clone (the GBA version) for the Sega Genesis with similar graphics and gameplay.

Thanks for the advice and help!

Code:
/*

 * Includes

 */

#include "genesis.h"

/*

 * Function prototypes

 */

void init_gfx();

/*

 * External Calls/Data

 */

extern uint back2_pal[];

extern ulong back2[];

extern uint back2_VSize;

extern uint back2_HSize;

extern uint shake_pal[];

extern ulong shake[];

extern uint shake_VSize;

extern uint shake_HSize;

/*

 * Main program

 */

void main()

{

	uint posx, posy, joy;

	register uint x,y,k;

  /* Initialize Genesis GFX registers */

  init_gfx();

	/* Initialize Genesis joypads */

	init_joypad();

	

	/* Set Palette Colors */

	set_colors(0,back2_pal);

	set_colors(1,shake_pal);

	/* Load Tiles and Sprite into VRAM */

  dma_vram_copy(back2, 32, 32 * back2_HSize * back2_VSize);

	dma_vram_copy(shake, 32 + 32 * back2_HSize * back2_VSize, 32 * shake_HSize * shake_VSize);

	wait_sync();

	/* Display Background */

	k=1;

	for(y=0;y<back2_VSize*2;y++,y++)

	{

 for(x=0;x<back2_HSize;x++)

 {

 	show_tiles(k, k, 0,x,y, BPLAN, 0,0,0);

 	k++;

 }

	}

	/* Set Start sprite position */

	posx=160;

	posy=165;

	/* Define and show the sprite in Plane A, with Palette 1 */

	def_sprite(1,posx,posy,0xF00,0xA000 + (32 + 32 * back2_HSize * back2_VSize)/32 );

	show_sprite(1,1);

	wait_sync();

	/* Program Loop, read joypad and move sprite */

  while(1)

  {

    joy= read_joypad1();

    if (joy)

    {

 	switch(joy & 0xff)

      {

  case JOY_RIGHT:

  	posx++;               

          break;

        case JOY_LEFT:

          posx--;

          break;

        case JOY_UP:

          posy--;

          break;

        case JOY_DOWN:

          posy++;

          break;

  case JOY_ULEFT:

  	posy--;

  	posx--;

          break;

  case JOY_URIGHT:

  	posy--;

  	posx++;

          break;

  case JOY_DLEFT:

  	posy++;

  	posx--;

          break;

  case JOY_DRIGHT:

  	posy++;

  	posx++;

          break;

 	}

      def_sprite(1,posx,posy,0xF00,0xA000 + (32 + 32 * back2_HSize * back2_VSize)/32 );

 	show_sprite(1,1);

 	wait_sync();

        

    }

  } 

}

/*

 * Initilize the GFX.

 */

void init_gfx()

{

  register uint *pw;

  pw = (uint *) GFXCNTL;

  *pw = 0x8016;  /* reg. 0 - Enable HBL */

  *pw = 0x8174;  /* reg. 1 - Enable display, VBL, DMA + VCell size */

  *pw = 0x8230;  /* reg. 2 - Plane A =$30*$400=$C000 */

  *pw = 0x832C;  /* reg. 3 - Window =$2C*$400=$B000 */

  *pw = 0x8407;  /* reg. 4 - Plane B =$7*$2000=$E000 */

  *pw = 0x855F;  /* reg. 5 - sprite table begins at $BC00=$5E*$200 */

  *pw = 0x8600;  /* reg. 6 - not used */

  *pw = 0x8700;  /* reg. 7 - Background Color number*/

  *pw = 0x8800;  /* reg. 8 - not used */

  *pw = 0x8900;  /* reg. 9 - not used */

  *pw = 0x8a01;  /* reg 10 - HInterrupt timing */

  *pw = 0x8b00;  /* reg 11 - $0000abcd a=extr.int b=vscr cd=hscr */

  *pw = 0x8c00;  /* reg 12 - hcell mode + shadow/highight + interlaced mode (40 cell, no shadow, no interlace)*/

  *pw = 0x8d2E;  /* reg 13 - HScoll Table = $B800 */

  *pw = 0x8e00;  /* reg 14 - not used */

  *pw = 0x8f02;  /* reg 15 - auto increment data */

  *pw = 0x9011;  /* reg 16 - scrl screen v&h size (64x64) */

  *pw = 0x9100;  /* reg 17 - window hpos */

  *pw = 0x92ff;  /* reg 18 - window vpos */

}
 

Edge-`

New Member
Hah, cool RadSil, Shake and Carl are by far my favs.

Here is another screenshot of some quick enhancements I made while testing what I could do:



You might notice a frame from Advance Wars (for the GBA) that I had used to test some layering and the Advance Wars font which I converted for use on the Genesis.

The text show in the box is the X and Y position (111222 would be x of 111, y of 222) of the shake sprite. It changes as you move shake around the screen.

Per JNB's request, you can try it out here. It just a demo, nothing more or less, just me getting comfy with the graphics of the genny. It should work on the actual hardware if you are bored with a flash cart.

Thanks!
 

Alexvrb

Member
I like ATHF, but I'm a HUGE Sealab 2021 fan!

Anyone here see the episode "In the Closet"?

"I warned him!" LOL :D

Edit: Hey, the sprite wraps around.
 

Edge-`

New Member
Sealab is FUNNY. I also like it, closet eps. is very funny.

Yeah, I didn't set any limits on movement for the sprite... no scrolling either, but it was not a bad start for someone going from scratch in a week :D Still need to figure out how to calculate the size for the cell, how a 2x2 cell ends up being 0x500, etc. Also, I understand that the sprite display has a high and low area (high on top, low below), is that set purely by priority or is there a register I need to define when initting the gfx and then write to that (if different then the Sprite List location).
 

ExCyber

Staff member
Still need to figure out how to calculate the size for the cell, how a 2x2 cell ends up being 0x500, etc.
If my math is straight, it's:

n = ((height - 1) << 2) | (width - 1)

where n is the first digit in your size value (shouldn't the rest be the link field?)

so substituting in your 2x2:

n = ((2 - 1) << 2) | (2 - 1)

n = (4 | 1)

n = 5

Make any sense? :)

edit: also there are only 16 possible sizes, so you could just make #defines for them (NB: I'm tired right now - see disclaimer in sig :devil):

0 = 1x1

1 = 1x2

2 = 1x3

3 = 1x4

4 = 2x1

5 = 2x2

6 = 2x3

7 = 2x4

8 = 3x1

9 = 3x2

A = 3x3

B = 3x4

C = 4x1

D = 4x2

E = 4x3

F = 4x4
 

Edge-`

New Member
Thats what I was after :D.

Thanks ExCyber! And I believe you are right about the set sizes, I seem to remember a listing in the Sega Genesis Programming Reference (commonly named sega2.doc if you are after it) Kaneda also mailed me an answer shortly after you posted, here is his reply for those who are curious:

i think you talk about my def_sprite func ?

/***************** DEF_SPRITE *******************

* Definition of the sprite

* number = number of the sprite

* posx, posy =position of the sprite

* size = in hexa

* ex: 0xb00 = 3*4 (b=1011)

* from =

* bit 15= priority

* bit 14-13 = palette

* bit 12 = vertical flipping

* bit 11 = horizontal flipping

* bit 10-0 = tile number

*

* Made by Kaneda

************************************************/

for the size it's this formula :

size = width-1 (width must be between 1&4)

size <<= 2

size |= height-2

size <<=8

et voila, send it to like this to the def_sprite
 

Edge-`

New Member
I'm getting quite comfy with sprites now (even thought the 32x32 sprite size limit makes displaying big spriates a bit of a chore :D). I'll probably create a new thread for this for future progress, but I started on the title screen for the Advance Wars clone. Here is a pic of it compared to the actual game. (not done yet, have to add the "Advance Wars" sprite ontop of the wrench and enable the fading of the Press Start. On the left, what I've made for the genesis, on the right, the original game on the GBA.



Thanks again for the formula ExCyber, I took your suggestion and set them up as defines and it has worked out great. I think I may write some simple tutorials for those who want to learn to program for the Genesis using a C enviroment as there isn't a lot of simple step by step tutorials aside from some really good examples.
 
Top