Skip to content
sverx edited this page Aug 12, 2016 · 6 revisions

Sprite size / sprite zoom

The SEGA Master System (and the SEGA Game Gear) VDP supports both 8x8 pixels and 8x16 pixels sprites, even if it's done through a global setting, thus making it possible to have only sprites of either size at a given time. Also, the VDP supports sprite zooming, again globally: when zoom is active, each pixel in the sprite will be doubled both in horizontal and vertical directions making the sprite twice its original sizes, so these sprites will take 16x16 pixels or 16x32 pixels respectively. SMSlib supports all these 4 total possible modes, and you can select the desired one using:

void SMS_setSpriteMode (unsigned char mode);

where mode can be one of the following:

SPRITEMODE_NORMAL
SPRITEMODE_TALL
SPRITEMODE_ZOOMED
SPRITEMODE_TALL_ZOOMED

which are respectively the 8x8 pixels sprites (default mode), the 8x16 pixels mode, and the two previous modes, 'zoomed'. BTW be aware that zooming isn't supported by the Genesis/MegaDrive when in SMS mode, and sadly there's also a bug the Master System's first revision which affects the zooming of (some of) the sprites. In Charles MacDonald's own words:

There is a bug in how the original SMS VDP processes zoomed sprites compared to the SMS 2 and GG VDP; it will only allow the first four sprites of the eight shown on a scanline to be zoomed horizontally and vertically, and the remaining four will be zoomed vertically. The SMS 2 and GG allow all eight sprites to be zoomed in both directions.

Updating Sprites

SMSlib also supports reserving sprites for later use and the update of (an already declared) sprite's attributes. By using:

signed char SMS_reserveSprite (void);

you can reserve a sprite for later use: the returned value is the sprite 'handle', or if it's negative it means there are no more available sprites. Then you can use:

void SMS_updateSpritePosition (signed char sprite, unsigned char x, unsigned char y);

to 'move' a sprite to a different position

void SMS_updateSpriteImage (signed char sprite, unsigned char image);

to change the image used by the sprite, and

void SMS_hideSprite (signed char sprite);

to hide the sprite so that it doesn't appear on screen. These functions should be used with the standard function. In particular I mean you should use SMS_copySpritestoSAT to flush your RAM copy of the SAT into the VRAM to update what will appear in the next screen frame.

SRAM

Game cartridges can contain a (small) amount of RAM whose contents will be held in place by a battery making it non-volatile. This is commonly called SRAM. You can activate that memory by using the macro:

SMS_enableSRAM();

if the SRAM is 16 KB (or smaller) or using the macro:

SMS_enableSRAMBank(n);

if the SRAM is 32 KB (in this case n should be 0 to access first half and 1 to access second half) Then, to read from and write to SRAM, you can simply access the unsigned char SMS_SRAM[] array, or use its address for your own SRAM-based variables. A simple example about accessing/using SRAM in this slightly better fashion it's here.

When done, you must unlink SRAM using the macro:

SMS_disableSRAM();

so to restore normal ROM mapping operations, which won't work when SRAM is enabled.

Pause key

To query if the PAUSE key on the console has been pressed since last check, you can use the provided function:

_Bool SMS_queryPauseRequested (void);

which will return a boolean. If it's the case, you can trigger your own routine to handle the event, as the PAUSE key doesn't trigger any specific action by itself (it doesn't stop the program or mute the audio or whatever). Then, you should reset the request using:

void SMS_resetPauseRequest (void);

to acknowledge that it has been serviced.

Line IRQ

The VDP can automatically trigger one of your own functions when the screen vertical raster reaches a specific scanline, and then again each time that the same number of scanlines are processed. To do so, you should link your own function's address using:

void SMS_setLineInterruptHandler (void (*theHandlerFunction)(void));

and set on which scanline the trigger should happen using:

void SMS_setLineCounter (unsigned char count);

Nothing will anyway happen until you actually activate the VDP trigger using the macro:

SMS_enableLineInterrupt();

and you can of course deactivate the VDP trigger using the macro:

SMS_disableLineInterrupt();

which you may also want to call inside your own handler function, to avoid the repeated calls.

Clone this wiki locally