-
Notifications
You must be signed in to change notification settings - Fork 34
Advanced
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 direction making the sprite twice its set dimensions, so these sprites will take 16x16 pixels or 16x32 pixels respectively. SMSlib supports all these 4 total possibile 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 (the default mode), the 8x16 pixels mode, and then the two previous modes, this time 'zoomed'. BTW be aware that zooming isn't supported by the Genesis/MegaDrive when in SMS mode, and sadly there's also a bug in first revision SMS 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.
SMSlib also supports reserving sprites for later use and updating of the sprites which have been already declared, using:
signed char SMS_reserveSprite (void);
to 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)
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
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 anyway use SMS_copySpritestoSAT to flush your RAM copy of the SAT into the VRAM to update what will appear in the next screen frame.
Game cartridges, alongside game's ROM, can contain a (small) amount of RAM, whose contents will be held in place by a battery, making it non-volatile. This is called SRAM. You can activate that 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 SMS_SRAM[] array just like any normal unsigned char array, or using its address for your own SRAM variables. I wrote a simple example about accessing/using SRAM in this slightly better fashion, it's here.
When done, you should unlink SRAM using the macro:
SMS_disableSRAM();
so to restore normal ROM mapping operations, which won't work when SRAM is enabled.
To query if the PAUSE key on the console has been pressed since last check, you can use the provided function:
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:
SMS_resetPauseRequest (void);
to acknowledge that it has been serviced.
The VDP can automatically trigger your function when the screen vertical raster reaches a specific scanline, and then again each time that the same number of scanlines are processed. You can link your function's address using:
SMS_setLineInterruptHandler (void (*theHandlerFunction)(void));
and set on which scanline the triggers happen using:
SMS_setLineCounter (unsigned char count);
Nothing will anyway happen until you activate the VDP trigger using the macro:
SMS_enableLineInterrupt();
and you can suspend the trigger using the macro:
SMS_disableLineInterrupt();
which you may want to call inside your own handler, to avoid the repeated function calls.