Wednesday, July 4, 2018

Simpsons Trivia XNA Port

Placeholder for new post on Simpsons Trivia XNA port...!

Friday, May 25, 2018

Simpsons Trivia Code Complete

I am a big fan of The Simpsons; particularly the early seasons of the show. The Simpsons appeared in comic books, film, music and video games. However, The Simpsons had not appeared on the Sega Master System!
Enter Simpsons Trivia Quiz.

Inspired from previous posts on Sega Console Programming and devkitSMS Programming Setup, Simpsons Trivia is my third 8-bit video game written in C / Z80 assembler to target the Sega Master System (SMS). Let's check it out!

Note: my two previous titles published for the Sega Master System were 3D City and Candy Kid Demo.
Download source code here.

Sega Retro Gaming post documents how to play video games like Simpsons Trivia using a Fusion emulator.
devkitSMS Programming Setup post documents development environment required to build C / Z80 source.
Instructions
Simple: move joystick Up and Down to select a multi-choice answer: A, B, C, D.
Press Button1 to select an answer or progress forward through any prompts.
Note: Press Button2 to always go back. Joystick Left and Right are not used.

ROM Hacking
You can hack this ROM! Download + dump SimpsonsTrivia.sms into Hex Editor, e.g. HxD, and modify bytes:
 ADDRESS  VARIABLE  DESCRIPTION
 0x004F  Debug  Used in development => debugging.
 0x0050  Cheat  Non-zero value will show answers.
 0x0051  Random  Ask random questions during quiz.
 0x0052  Music  0=music play otherwise off.
 0x0053  Sound  0=sound on otherwise off.
 0x0054  Extra  Set visibility on all extra info.
#ifndef _HACK_MANAGER_H_
#define _HACK_MANAGER_H_

#define PEEK(addr)   (*(unsigned char *)(addr))
#define POKE(addr, data) (*(unsigned char *)(addr) = (data))

#define HACKER_START  0x0050

extern unsigned char hacker_debug, hacker_cheat, hacker_random;
extern unsigned char hacker_music, hacker_sound, hacker_extra;

void engine_hack_manager_init()
{
  hacker_debug = PEEK( HACKER_START - 1 );  // 0x004F
  hacker_cheat = PEEK( HACKER_START + 0 );  // 0x0050
  hacker_random= PEEK( HACKER_START + 1 );  // 0x0051
  hacker_music = PEEK( HACKER_START + 2 );  // 0x0052
  hacker_sound = PEEK( HACKER_START + 3 );  // 0x0053
  hacker_extra = PEEK( HACKER_START + 4 );  // 0x0054
}
#endif//_HACK_MANAGER_H_
Cheat
Some of the questions may be tough so you can cheat if necessary! Either hack the ROM as above to show the answers or alternatively press Button2 five times on the Title screen when prompted to "Press Start".

Credits
StevePro Studios would like to thank the following, esp. at SMS Power, for making this project possible:
 sverx  devkitSMS  Sega Master System development kit + libraries
 Maxim  BMP2Tile  Converts BMP images into 8x8 SMS tile data
 vhelin  WLA-DX  Z80 multi platform cross Assembler package
 Martin  SMS Examine  Z80 disassembler recompilable by WLA-DX
 Calindro  Emulicious  SMS emulator (excellent debugging features)
 Bock  Meka  SMS emulator (excellent debugging features)
 Steve Snake  Fusion  SMS emulator used for general play testing
Note: music used from Bart vs. the Space Mutants + Flicky and sound FX from Baluba Balok + Super Uwol! Reference to original Simpsons Trivia questions can be found here.

Homebrew
The Homebrew community at SMS Power celebrates Sega 8-bit preservation and fanaticism each year with its annual competitions. Therefore, this is always an opportunity to participate by entering these games!

However, during the past 3 years, I haven't seen as much interest in SMS Homebrew games than in 2018:
 Atari Age  SMS Power! Coding competition 2018
 Indie Retro News  SMS Power! Competition 2018
 Vlog retrogaming  6 nouveaux jeux Master System grâce au SMS Power 2018 !!
 Marianne Vote *aka Révo*  Présentation SMS Power Competition #21 2018 SEGA Master System
 ROMhacking.Ru  ????? SMS Power! Competition 2018
Here are some cool Simpsons Trivia links from PD ROMS, DC EMU UK, idpixel.ru + Tsar Evgeniy [YouTube]

Popularity
Arguably, recent interest for Sega Master System games has grown in popularity could be due to the high quality work of Indie game developer eruiz00 with titles Astro Force, Silver Valley and Galactic Revenge.

Not only do these awesome games keep the console alive but the fact that the community shares source code and assets; this certainly does help other developers improve their skills + contribute more games!

Summary
To summarize, the 2018 coding competition featured the fewest entries [6] compared to 2017 [8] and 2016 [16]. However, for each entry in 2018, there seemed to be more accompanying box art and/or instructions.

In fact, some Homebrew productions come complete with box art, case, cover and physical ROM cartridge e.g. Duke Nukem. Again, community members helping transform this fun past time into a serious hobby!

Retrospective
In 2013, an initial ambitious goal was to build a retro game in pure Z80 assembler to target the Sega Master System. During the past 5 years, it seemed more feasible to code in C using either the z88dk or devkitSMS.

However, the 2018 competition entry Astroswab by hang-on was written in pure Z80 assembler. By sharing the source code, this project has given some solid ideas on how it could be possible to achieve this goal J

Saturday, March 17, 2018

devkitSMS Programming Sample II

In 2014, we checked out z88dk Programming Setup + Sample to build 3D City for the Sega Master System. While this worked on Fusion + Meka emulators unfortunately 3D City encountered graphics glitches on real hardware.

In 2017 we checked out devkitSMS Programming Setup + Sample to build CandyKid Demo for the SMS also. As this demo worked on Emulicious emulator with VDP constraints enabled CandyKid Demo now ran on real hardware.

Building upon knowledge + experience shared by the SMS Power community, plus gaining access to source code, we have now streamlined the SMS development process to build Simpsons Trivia using the devkitSMS.
Let’s check it out!

Software
Follow all instructions from the previous post: this documents how to setup the pre-requisite software.
Note: ensure you have downloaded and installed the devkitSMS and Small Device C Compiler [SDCC].

Folders
The devkitSMS requires certain utilities to work such as ihx2sms, assets2banks and/or folder2c. Plus, it is common to use utilities like BMP2Tile for graphics, VGM2PSG for sound, assemblers like WLA-DX etc. etc.

Therefore, it makes sense to centralize these utilities in a parent folder C:\SEGA\Utilities. Also, all emulators such as Fusion, Meka + Emulicious can be re-located to C:\SEGA and added to PATH Environment variable. System | Advanced system settings | Environment Variables | PATH. Add all corresponding C:\SEGA folders

Graphics
Previous work on SMS graphics simply used basic tools like MS Paint to save sprite and tile data in 16 Color Bitmap format to conform to the 4bpp (bits per pixel) constraints. However, graphics here were very simple!

In order to achieve a more authentic 8-bit look and feel, and still comply with 4bpp, let's use another tool: Download Gimp. Load typical 256x192 BMP image as before but save as Indexed mode with max 16 colors. Image menu | Mode | Indexed... Convert Image to Indexed Colors | Generate optimum palette | Maximum number of colors: 16 Click Convert button. Finally, File menu | Export As... simpsons.bmp | Export

BMP2Tile
Previous work using BMP2Tile was a very manual process: Launch BMP2Tile | drag n' drop the 4bpp image into BMP2Tile and manually configure options and save out the Tiles, Tilemap and Palette files one by one.

After inspecting the source code for Astro Force, we see that eruiz00 automates this process using batch scripts. Let's replicate this process to produce Tiles, Tilemap and Palette files for simpsons.bmp [above].

Image.bat
bmp2tile.exe raw\simpsons.bmp -savetiles "simpsons (tiles).psgcompr" -removedupes -nomirror -planar -tileoffset 96
bmp2tile.exe raw\simpsons.bmp -savetilemap "simpsons (tilemap).stmcompr" -exit
bmp2tile.exe raw\simpsons.bmp -savepalette "simpsons (palette).bin" -exit
Tiles Tilemap Palette IMPORTANT: for multiple images loaded and rendered at the same time ensure the palette file is the same!
Note: folder2c ..\gfx gfx is used as before to convert files to code. Here 96 is the tile offset used in code:

ContentManager.c
#define SIMPSONS_TILES 96
void engine_content_manager_title()
{
  SMS_loadPSGaidencompressedTiles( simpsons__tiles__psgcompr, SIMPSONS_TILES );
  SMS_loadSTMcompressedTileMap( 0, 0, simpsons__tilemap__stmcompr );
  SMS_loadBGPalette( simpsons__palette__bin );
}
Finally, see here for a complete list of all Command line mode arguments that can be used with BMP2Tile.

ROM Banking
Simpsons Trivia is 128KB in size thus uses ROM banking to allow for more that 48KB in the game ROM. Again Astro, Force gives a real world example on how bank switching can be achieved for more content.

For example, let's load the Splash screen from bank 2 as this is rendered once during the entire game:

Image.bat
bmp2tile.exe raw\splash.bmp -savetiles "splash (tiles).psgcompr" -removedupes -nomirror -planar -tileoffset 112 
bmp2tile.exe raw\splash.bmp -savetilemap "splash (tilemap).stmcompr" -exit
bmp2tile.exe raw\splash.bmp -savepalette "splash (palette).bin" -exit
Build.bat
REM echo Build banks.c and banks.h from banks folder
cd banks
folder2c bank2 bank6 2

REM echo Build banks
sdcc -c --no-std-crt0 -mz80 --Werror --opt-code-speed --constseg BANK2 bank2.c

REM echo Build main
sdcc -c -mz80 --opt-code-speed --peep-file peep-rules.txt --std-c99 main.c

REM echo Linking
sdcc -o output.ihx --Werror --opt-code-speed -mz80 --no-std-crt0 --data-loc 0xC000 ^
-Wl-b_BANK2=0x8000 ^
..\crt0\crt0_sms.rel ^main.rel ^
..\lib\SMSlib.lib ^
..\lib\PSGlib.rel ^
banks\bank2.rel

ContentManager.c
#define GRAPHICS_TILES 112
void engine_content_manager_splash()
{
  SMS_mapROMBank( 2 );
  SMS_loadPSGaidencompressedTiles( splash__tiles__psgcompr, GRAPHICS_TILES );
  SMS_loadSTMcompressedTileMap( 0, 0, splash__tilemap__stmcompr );
  SMS_loadBGPalette( splash__palette__bin );
}

Function Pointers
Game development is renown for using the State design pattern. Therefore, previous SMS titles like 3D City or CandyKid demo have a main loop that switches load and update methods depending on the current state.

For example, CandyKid demo has 4x states: Splash, Title, Ready, and Play thus the main loop is as follows:

Main.c
for ( ;; )
{
  if ( enum_curr_screen_type != enum_next_screen_type )
  {
    enum_curr_screen_type = enum_next_screen_type;
    custom_screen_manager_load( enum_curr_screen_type );
  }
  // ...
  custom_screen_manager_update( &enum_next_screen_type, curr_joypad1, prev_joypad1 );
}
void custom_screen_manager_load( unsigned char screen_type )
{
  switch( screen_type )
  {
  case SCREEN_TYPE_SPLASH:
    screen_splash_screen_load(); break;
  case SCREEN_TYPE_TITLE:
    screen_title_screen_load(); break;
  case SCREEN_TYPE_READY:
    screen_ready_screen_load(); break;
  case SCREEN_TYPE_PLAY:
    screen_play_screen_load(); break;
  }
}
void custom_screen_manager_update( unsigned char *screen_type, const int curr_joypad1, const int prev_joypad1 )
{
  switch ( *screen_type )
  {
  case SCREEN_TYPE_SPLASH:
    screen_splash_screen_update( screen_type, curr_joypad1, prev_joypad1 ); break;
  case SCREEN_TYPE_TITLE:
    screen_title_screen_update( screen_type, curr_joypad1, prev_joypad1 ); break;
  case SCREEN_TYPE_READY:
    screen_ready_screen_update( screen_type, curr_joypad1, prev_joypad1 ); break;
  case SCREEN_TYPE_PLAY:
    screen_play_screen_update( screen_type, curr_joypad1, prev_joypad1 ); break;
  }
}

Consequently, this solution does not scale! Instead, opt for an array of function pointers: for each state add to an array of load and update function pointers; the main loop invokes the correct function based on state.

Main.c
void ( *load_method[ MAX_STATES ] )();
void ( *update_method[ MAX_STATES ] )( unsigned char *screen_type, const int curr_joypad1, const int prev_joypad1 );

for ( ;; )
{
  if ( enum_curr_screen_type != enum_next_screen_type )
  {
    enum_curr_screen_type = enum_next_screen_type;
    load_method[ enum_curr_screen_type ]();
  }
  // ...
  update_method[ enum_curr_screen_type ]( &enum_next_screen_type, curr_joypad1, prev_joypad1 );
}

void custom_initialize()
{
// Set load methods
load_method[ SCREEN_TYPE_SPLASH ] = screen_splash_screen_load;
load_method[ SCREEN_TYPE_TITLE ] = screen_title_screen_load;
load_method[ SCREEN_TYPE_READY ] = screen_ready_screen_load;
load_method[ SCREEN_TYPE_PLAY ] = screen_play_screen_load;
// ...
load_method[ SCREEN_TYPE_OVER ] = screen_over_screen_load;

// Set update methods
update_method[ SCREEN_TYPE_SPLASH ] = screen_splash_screen_update;
update_method[ SCREEN_TYPE_TITLE ] = screen_title_screen_update;
update_method[ SCREEN_TYPE_READY ] = screen_ready_screen_update;
update_method[ SCREEN_TYPE_PLAY ] = screen_play_screen_update;
// ...
update_method[ SCREEN_TYPE_OVER ] = screen_over_screen_update;
}

Emulation
In the past, Fusion emulator was used during development especially to test code changes quickly. However, more developers prefer Emulicious as this has an option to Emulate VDP constraints for real SMS hardware.

Also, Emulicious has numerous built-in tools to view memory, tiles, tilemaps, palettes, sprites etc. plus it has an awesome debugger! Therefore, let's integrate Emulicious into our build batch script development process:

First, launch Emulicious. Tools menu open all windows. Ensure the "Reopen Tools" option is checked. Launch the debugger. Run menu | ensure "Suspend On Open" is checked. Close Emulicious. Update the build script:

Build.bat
REM output.sms
java -jar C:\SEGA\Emulicious\emulicious.jar output.sms
Finally, Ctrl+1 in Visual Studio 2008 will now launch in Emulicious with debug step through Z80 assembler!

Summary
To summarize, the SMS Power community has been awesome and by members sharing especially their code, for example like Astro Force then this really does help develop ideas for new projects like Simpsons Trivia.

Recently, eruiz00 has shared the source code for Galactic Revenge. This game uses an up-to-date version of z88dk with devkitSMS [instead of sdcc] as the libraries are optimized in ASM + produce smaller object code.

Therefore, 3D City and future games could be written using z88dk with devkitSMS without graphics glitches!

Monday, January 1, 2018

Retrospective IX

Last year, I conducted a simple retrospective for 2016. Therefore, here is a retrospective for 2017.

2017 Achievements
  • Setup studio for Windows PC, Mac OS/X and Linux cross platform development
  • Employ large scale C++ program architecture using levelization and insulation
  • Graduate Effective C++ to Modern Effective C++ theory + practical examples
  • Align OpenGL graphics learning [desktop] with OpenGL ES [mobile platforms]
  • Source control branches out SVN, Git + Mercurial with HgFlow on Source Tree
  • Extend retro game development on Sega Master System using the devkitSMS
  • Complete Sega Master System demo on real hardware using Master Everdrive
  • Support Spartan Console proposed next gen Sega console to showcase game!
Note: running Sega Master System demo on real hardware without glitches is an achievement!

2018 Objectives
  • Continue C++11 language improvements to C++14 and C++17 standard additions
  • Virtual Reality with Unity3D + Unreal game engine integration: GoogleVR SteamVR
  • Augmented Reality Unity3D + Unreal game engine integration: ARToolKit + Vuforia
  • Investigate new tech: Crypto currency [Bitcoin | Blockchain] and Machine Learning

Virtual Reality
Building upon 2016, as every Virtual Reality evangelist will tell you was "the year of VR", research and development began with Unity3D game engine integration using plugins such as Google VR [C#/.NET].

However, as VR design and best practices demand delivery of minimum 75fps, .NET languages like C# may be less suited for VR since they require a virtual machine to run. Also, services such as automatic garbage collection can have a negative effect on performance as well.

Conversely, C++ is arguably more suited performance-wise since code written is compiled directly into machine code and doesn't suffer from the overhead imposed by virtual machine and garbage collection.

Therefore, Unreal Engine may be better choice for VR game engine integration because C++ is default language. Otherwise, if writing from scratch, C++ with OpenGL should perform well on any platform.

Augmented Reality
Alternatively, Augmented Reality has grown in popularity this year, especially with releases like Pokémon GO. Apple has incorporated AR into their iOS 11 mobile operating system with expectations that AR will "change the way we use technology forever".

Consequently, AR is currently being used more on mobile devices which will limit the language choice to:
 Type  Specific  Generic
 Android  Java  C++
 iOS  Objective-C  C++
 Mono  C#/.NET  C++
Subsequently, AR is also performance critical thus languages like C++ with OpenGL may also be better suited for this type of native development or alternatively Unreal Engine for game engine integration.

Modern C++
In the above examples, C++ is the common denominator regularly listed. Fortunately, the C++ language has improved upon previous iterations with C++11 and additions to the standard i.e. C++14 and C++17.

At it's base: C++11 offers greater performance benefits with move semantics, which is a way to optimize copying, and improved productivity e.g. the new auto keyword which helps make code shorter + clearer.

There are also other features added to the C++11 standard, such as enum classes, lambda expressions, automatic type deduction, etc. all of which are coincidentally available as the baseline for Unreal Engine.

Summary
Outside commercial development, much work was done during the year with the Sega Master System!

Writing low level C code to run on real hardware with limited memory + storage requires performance-critical algorithms to be written at all times to achieve consistent maximum frame rate. Perfecting this skill becomes beneficial especially when transitioning future development to VR / AR environments J

Wednesday, November 15, 2017

devkitSMS Programming Sample

In the previous post, we checked out devkitSMS Programming Setup. The devkitSMS provides tools and code to support homebrew development for the Sega Master System, SG-1000, and Sega Game Gear.

Using devkitSMS, it is possible to write game code using the C language rather than pure Z80 assembly. Therefore, we would now like to extend this knowledge and write more detailed programming sample.
Let's check it out!

Software
Follow all instructions from the previous post: this documents how to setup the pre-requisite software.
Note: ensure you have downloaded and installed the devkitSMS and Small Device C Compiler [SDCC].

Also download vgm2psg.exe required to convert VGM files to the Programmable Sound Generator [PSG].
# Clone PSGlib
cd C:\GitHub\sverx
git clone https://github.com/sverx/PSGlib.git

Demo
The devkitSMS programming sample is based on the Candy Kid Demo coding competition entry for 2017. All graphics, sprites, music, sound fx, coding logic etc. here is based on the devkitSMS tutorial by @sverx.

Create folder C:\CandyKidDemoSMS. Create the following sub-folders: asm, crt0, dev, gfx, lib, psg, utl
 Folder  File  Location
 asm  Opcodes.dat
 smsexamine.exe
 C:\smsexamine1_2a
 C:\smsexamine1_2a
 crt0  crt0_sms.rel  C:\Github\sverx\devkitSMS\crt0
 lib  SMSlib.h
 SMSlib.lib
 PSGlib.h
 PSGlib.rel
 C:\GitHub\sverx\devkitSMS\SMSlib\src
 C:\GitHub\sverx\devkitSMS\SMSlib
 C:\GitHub\sverx\devkitSMS\PSGlib\src
 C:\GitHub\sverx\devkitSMS\PSGlib
 utl  folder2c.exe
 ihx2sms.exe
 vgm2psg.exe
 C:\GitHub\sverx\devkitSMS\folder2c
 C:\GitHub\sverx\devkitSMS\ihx2sms
 C:\GitHub\sverx\PSGlib\tools
Note: assumes Opcodes.dat and smsexamine.exe downloaded from SMS Examine and extracted to C:\

Development
Launch Visual Studio 2008. File | New | Project... | Visual C++ | Win32 | Win32 Project
 Name:  Game
 Location:  C:\CandyKidDemoSMS\dev
 Create directory for solution  UNCHECKED
OK

 Application type:  Console application
 Additional options:  Empty project CHECKED
Finish

Graphics
Follow all instructions from the previous post to download and install BMP2Tile utility to convert graphics into Sega Master System format. Download gfxcomp_stm.dll STM compressed format to output directory.

Splash
Here is an example of background tiles that exhaust the full 256 x 192 resolution e.g. the Splash screen:

Choose "Tiles" tab. Ensure that "Remove duplicates" and "Planar tile output" are both checked.
Click Save button | File name splash (tiles).psgcompr | File type PS Gaiden (*.psgcompr)

Choose "Tilemap" tab. Leave "Use sprite palette" and "In front of sprites" options both unchecked.
Click Save button | File name splash (tilemap).stmcompr | File type Sverx's TileMap (*.stmcompr)

Choose "Palette" tab. Leave the "Output hex (SMS)" option checked for Sega Master System.
Click Save button | File name splash (palette).bin | File type Binary files (*.bin)
Here is basic code sample to render the splash screen in main.c with corresponding updated build.bat

main.c
#include "..\lib\SMSlib.h"
#include "gfx.h"

#define SPLASH_TILES 144

void engine_content_manager_splash()
{
  SMS_loadPSGaidencompressedTiles(splash__tiles__psgcompr, SPLASH_TILES);
  SMS_loadSTMcompressedTileMap(0, 0, splash__tilemap__stmcompr);
  SMS_loadBGPalette(splash__palette__bin);
}
void main (void)
{
  engine_content_manager_splash();
  SMS_displayOn();
  for (;;)
  {
    SMS_waitForVBlank();
  }
}

SMS_EMBED_SEGA_ROM_HEADER(9999, 0);
SMS_EMBED_SDSC_HEADER(1, 0, 2017, 3, 17, "StevePro Studios", "Candy Kid Demo", "DESC");

build.bat
@echo off
..\utl\folder2c ..\gfx gfx

sdcc -c -mz80 gfx.c
sdcc -c -mz80 main.c
sdcc -o output.ihx -mz80 --data-loc 0xC000 --no-std-crt0 ..\crt0\crt0_sms.rel main.rel ..\lib\SMSlib.lib gfx.rel

..\utl\ihx2sms output.ihx output.sms
output.sms


Background
Repeat the process for background tiles e.g. Font however save tilemap as uncompressed binary format [bin] to access data randomly. Save tiles in PS Gaiden compressed format + use same palette as above.
 Tiles  font (tiles).psgcompr  PS Gaiden (*.psgcompr)
 Tilemap  font (tilemap).bin  Raw (uncompressed) binary (*.bin)
 Palette  font (palette).bin  Raw (uncompressed) binary (*.bin)

main.c
#include "..\lib\SMSlib.h"
#include "gfx.h"

#define FONT_TILES  16
#define TEXT_ROOT  33  // 33 is "!" in ASCII.

void engine_content_manager_load()
{
  SMS_loadPSGaidencompressedTiles(font__tiles__psgcompr, FONT_TILES);
  SMS_loadBGPalette(font__palette__bin);
}
void engine_font_manager_draw_text(unsigned char* text, unsigned char x, unsigned char y)
{
  const unsigned int *pnt = font__tilemap__bin;
  unsigned char idx=0;
  while ('\0' != text[idx])
  {
    signed char tile = text[idx] - TEXT_ROOT;
    SMS_setNextTileatXY(x++, y);
    SMS_setTile(*pnt + tile);
    idx++;
  }
}
void main (void)
{
  char *text = "HELLO";
  engine_content_manager_load();
  engine_font_manager_draw_text(text, 0, 0);

  SMS_displayOn();
  for (;;)
  {
    SMS_waitForVBlank();
  }
}

SMS_EMBED_SEGA_ROM_HEADER(9999, 0);
SMS_EMBED_SDSC_HEADER(1, 0, 2017, 3, 17, "StevePro Studios", "Candy Kid Demo", "DESC");

Sprites
Repeat the process for sprite tiles however no need to save the tilemap file. Also, introduce sprite code:
 Tiles  sprites (tiles).psgcompr  PS Gaiden (*.psgcompr)
 Palette  sprites (palette).bin  Raw (uncompressed) binary (*.bin)

main.c
#include <stdbool.h>
#include "..\lib\SMSlib.h"
#include "gfx.h"

#define SPRITE_TILES  80
#define KID_BASE_TILE  SPRITE_TILES + 0

void engine_content_manager_load()
{
  SMS_loadPSGaidencompressedTiles(sprites__tiles__psgcompr, SPRITE_TILES);
  SMS_loadSpritePalette(sprites__palette__bin);
}
void engine_sprite_manager_draw(unsigned char x, unsigned char y, unsigned char tile)
{
  SMS_addSprite(x+0, y+0, tile+0);
  SMS_addSprite(x+8, y+0, tile+1);
  SMS_addSprite(x+0, y+8, tile+8);
  SMS_addSprite(x+8, y+8, tile+9);
}
void main (void)
{
  unsigned char kidX = 32;
  unsigned char kidY = 32;
  unsigned char kidColor = 0;
  unsigned char kidFrame = 0;
  unsigned char kidTile = KID_BASE_TILE + ((kidColor * 2) + kidFrame) * 2;

  SMS_setSpriteMode(SPRITEMODE_NORMAL);
  SMS_useFirstHalfTilesforSprites(true);
  engine_content_manager_load();

  SMS_displayOn();
  for (;;)
  {
    SMS_initSprites();
    engine_sprite_manager_draw(kidX, kidY, kidTile);
    SMS_finalizeSprites();
    SMS_waitForVBlank();
    SMS_copySpritestoSAT();
  }
}

SMS_EMBED_SEGA_ROM_HEADER(9999, 0);
SMS_EMBED_SDSC_HEADER(1, 0, 2017, 3, 17, "StevePro Studios", "Candy Kid Demo", "DESC");

Music
Download Mod2PSG2 music tracker to record music [FX] and convert output VGM files to PSG file format. File | Export module | VGM... | C:\CandyKidDemoSMS\psg\raw\music.vgm | Save
Now convert to PSG file format using vgm2psg.exe utility downloaded previously:

Start | run | cmd | cd C:\CandyKidDemoSMS
utl\vgm2psg.exe psg\raw\music.vgm psg\music.psg
Here is basic code sample to play the background music in main.c with corresponding updated build.bat
main.c
#include "..\lib\SMSlib.h"
#include "..\lib\PSGlib.h"
#include "gfx.h"
#include "psg.h"

#define MUSIC_PSG   music_psg

void main (void)
{
  PSGPlayNoRepeat(MUSIC_PSG);
  SMS_displayOn();
  for (;;)
  {
    SMS_waitForVBlank();
    PSGFrame();
  }
}

SMS_EMBED_SEGA_ROM_HEADER(9999, 0);
SMS_EMBED_SDSC_HEADER(1, 0, 2017, 3, 17, "StevePro Studios", "Candy Kid Demo", "DESC");

build.bat
@echo off
..\utl\folder2c ..\gfx gfx
..\utl\folder2c ..\psg psg

sdcc -c -mz80 gfx.c
sdcc -c -mz80 psg.c
sdcc -c -mz80 main.c
sdcc -o output.ihx -mz80 --data-loc 0xC000 --no-std-crt0 ..\crt0\crt0_sms.rel main.rel ..\lib\SMSlib.lib ..\lib\PSGlib.rel gfx.rel psg.rel

..\utl\ihx2sms output.ihx output.sms
output.sms

Sound
Repeat the process for sound effects however export VGM file to channel 2 and play on SFX_CHANNEL2:

Start | run | cmd | cd C:\CandyKidDemoSMS
utl\vgm2psg.exe psg\raw\sound.vgm psg\sound.psg 2 main.c
#include "..\lib\SMSlib.h"
#include "..\lib\PSGlib.h"
#include "gfx.h"
#include "psg.h"

#define SOUND_PSG   sound_psg

void main (void)
{
  PSGSFXPlay(SOUND_PSG, SFX_CHANNEL2);
  SMS_displayOn();
  for (;;)
  {
    SMS_waitForVBlank();
    PSGSFXFrame();
  }
}

SMS_EMBED_SEGA_ROM_HEADER(9999, 0);
SMS_EMBED_SDSC_HEADER(1, 0, 2017, 3, 17, "StevePro Studios", "Candy Kid Demo", "DESC");

Noise
Repeat the process for noise effects however export VGM file to channel 3 and play on SFX_CHANNEL3:

Start | run | cmd | cd C:\CandyKidDemoSMS
utl\vgm2psg.exe psg\raw\noise.vgm psg\noise.psg 3 main.c
#include "..\lib\SMSlib.h"
#include "..\lib\PSGlib.h"
#include "gfx.h"
#include "psg.h"

#define NOISE_PSG   noise_psg

void main (void)
{
  PSGSFXPlay(NOISE_PSG, SFX_CHANNEL3);
  SMS_displayOn();
  for (;;)
  {
    SMS_waitForVBlank();
    PSGSFXFrame();
  }
}

SMS_EMBED_SEGA_ROM_HEADER(9999, 0);
SMS_EMBED_SDSC_HEADER(1, 0, 2017, 3, 17, "StevePro Studios", "Candy Kid Demo", "DESC");

Input
Input detection is straightforward although it seems joypad variables must be static so to persist values:

main.c
#include "..\lib\SMSlib.h"
void update(const unsigned int curr_joypad1, const unsigned int prev_joypad1)
{
  if (curr_joypad1 & PORT_A_KEY_1 && !(prev_joypad1 & PORT_A_KEY_1))
  {
    SMS_setSpritePaletteColor(0, RGB(2,2,2));
  }
}
void main (void)
{
  // Must be static to persist values!
  static unsigned int curr_joypad1 = 0;
  static unsigned int prev_joypad1 = 0;

  SMS_setSpritePaletteColor(0, RGB(3,3,3));
  SMS_displayOn();
  for (;;)
  {
    curr_joypad1 = SMS_getKeysStatus();
    update(curr_joypad1, prev_joypad1);
    SMS_waitForVBlank();
    prev_joypad1 = curr_joypad1;
  }
}

SMS_EMBED_SEGA_ROM_HEADER(9999, 0);
SMS_EMBED_SDSC_HEADER(1, 0, 2017, 3, 17, "StevePro Studios", "Candy Kid Demo", "DESC");

Pause
Many homebrew games do not query pause button although I believe this is good programming practice!

main.c
#include <stdbool.h>
#include "..\lib\SMSlib.h"
#include "..\lib\PSGlib.h"

bool global_pause;
void main (void)
{
  global_pause = false;
  SMS_setSpritePaletteColor(0, RGB(3,3,3));
  SMS_displayOn();
  for (;;)
  {
    if (SMS_queryPauseRequested())
    {
      SMS_resetPauseRequest();
      global_pause = !global_pause;
      if (global_pause)
      {
        SMS_setSpritePaletteColor(0, RGB(1,1,1));
        PSGSilenceChannels();
      }
      else
      {
        SMS_setSpritePaletteColor(0, RGB(3,3,3));
        PSGRestoreVolumes();
      }
    }
    if (global_pause)
    {
      continue;
    }

    SMS_waitForVBlank();
  }
}

SMS_EMBED_SEGA_ROM_HEADER(9999, 0);
SMS_EMBED_SDSC_HEADER(1, 0, 2017, 3, 17, "StevePro Studios", "Candy Kid Demo", "DESC");

Assembler
Ultimately the goal would be to write game code in Z80 assembly! However, one useful way to slowly transition from C language to Z80 assembly would be to wrap inline assembly blocks via C functions.

Let's integrate the Z80 assembly code inline to clear VRAM from Maxim Hello World example directly:

main.c
#include "..\lib\SMSlib.h"
__sfr __at 0xBF VDPControlPort;
__sfr __at 0xBE VDPDataPort;

void engine_asm_manager_clear_VRAM()
{
  __asm
    ld a,#0x00
    out (_VDPControlPort),a
    ld a,#0x40
    out (_VDPControlPort),a
    ld bc, #0x4000
ClearVRAMLoop:
    ld a,#0x00
    out (_VDPDataPort),a
    dec bc
    ld a,b
    or c
    jp nz,ClearVRAMLoop
  __endasm;
}

void main (void)
{
  engine_asm_manager_clear_VRAM();
  SMS_displayOn();
  for (;;)
  {
    SMS_waitForVBlank();
  }
}

SMS_EMBED_SEGA_ROM_HEADER(9999, 0);
SMS_EMBED_SDSC_HEADER(1, 0, 2017, 3, 17, "StevePro Studios", "Candy Kid Demo", "DESC");

Summary
Armed with all this knowledge, we are now in an excellent position to build complete video games for the Sega Master System that will be able to run on real hardware but now without any VDP graphics glitches!

Friday, September 15, 2017

devkitSMS Programming Setup

In 2013, we checked out Sega Console Programming, specifically for the Sega Master System (SMS).
The SMS was the last ever 8-bit video game console manufactured by Sega built using the Z80 chip.

However, the process to write Z80 assembly language from scratch for the SMS can be very daunting. Instead, in 2014 we checked out z88dk Programming Setup to write code in C language using z88dk.

All code here worked on emulators but real Sega Master System hardware experienced graphics glitches! Fortunately, there is another way: write game code in C language using devkitSMS and SDCC compiler.
Let’s check it out!

devkitSMS
The devkitSMS is a collection of tools and code built specifically for the Sega Master System but also supports homebrew development using C language for SG-1000, SC-3000 and the Sega Game Gear.

Software
Follow all instructions from the previous post: this documents how to setup the pre-requisite software.

Here is a summary of all required software to be installed:
 Name Version
 Z80 Editor ConTEXT
 Assembler WLA DX
 Emulators Fusion, Meka, Emulicious
 Disassembler SMS Examine
 
 Name Version
 C IDE Editor Visual Studio 2008
 Cross compiler Small Device C Compiler
 Make files Cygwin
 Hex Editor HxD

SDCC
Download and install sdcc-3.6.0-x64-setup.exe to C:\Program Files\SDCC. Choose all features to install. UPDATE: if you build games like Astro Force then I believe you need to upgrade to version sdcc-3.6.9.

There should be no extra configuration except add C:\Program Files\SDCC\bin to the Environment PATH.

Start | Run | cmd. Type sdcc --version. The following should display to confirm SDCC version 3.6.0:

devkitSMS
Navigate to the devkitSMS repository on github. @sverx has full instructions here and advises to copy the following 3x executables into the SDCC bin folder [above]: ihx2sms.exe, assets2banks.exe, folder2c.exe.
# Clone devkitSMS
cd C:\GitHub\sverx
git clone https://github.com/sverx/devkitSMS.git

# Copy 3x files
cd devkitSMS
copy ihx2sms\ihx2sms.exe C:\Program Files\SDCC\bin
copy assets2banks\assets2banks.exe C:\Program Files\SDCC\bin
copy folder2c\folder2c.exe C:\Program Files\SDCC\bin
Note: my preference is to usually copy these 3x files up-top-date as each Master System project is built.


Example
As an example, let's write a simple program that sets the border colors of the screen using devkitSMS. Create new directory: C:\HelloWorld. Copy these files: crt0_sms.rel, SMSlib.h, SMSlib.lib, ihx2sms.exe

main.c
#include "SMSlib.h"
void main (void)
{
  SMS_setSpritePaletteColor(0, RGB(3,3,3));
  SMS_displayOn();
  for (;;)
  {
    SMS_waitForVBlank();
  }
}

SMS_EMBED_SEGA_ROM_HEADER(9999, 0);
SMS_EMBED_SDSC_HEADER(1, 0, 2017, 9, 15, "StevePro Studios", "Hello World", "Simple Sega Master System demo to run on real hardware!");

Build
Manually compile, link and execute the Hello program. Launch command prompt: Start | Run | cmd.

Change directory cd C:\HelloWorld. Next, execute the following 3x commands (in bold):
 ACTION  COMMAND  OUTPUT
 Compile   sdcc -c -mz80 main.c  main.rel
 Link  sdcc -o output.ihx -mz80 --data-loc 0xC000 --no-std-crt0 crt0_sms.rel
 main.rel SMSlib.lib
 output.ihx
 Exceute  ihx2sms output.ihx output.sms  output.sms 

Finally, type output.sms. The Hello program should launch in the Fusion emulator.
Congratulations! You have just written your first SMS program using devkitSMS.

Automate
Let's automate the build process: create C:\HelloWorld\build.bat script file that contains the commands:
@echo off
sdcc -c -mz80 main.c
sdcc -o output.ihx -mz80 --data-loc 0xC000 --no-std-crt0 crt0_sms.rel main.rel SMSlib.lib
ihx2sms output.ihx output.sms
output.sms

Visual Studio
Inspired by this suggestion to use Visual Studio as an IDE to better navigate files in larger projects and help automate the development build system. Download + install Visual Studio 2008 and setup solution.

Launch Visual Studio 2008. File | New | Project... | Visual C++ | Win32 | Win32 Project
 Name:  HelloWorld
 Location:  C:\
 Create directory for solution  UNCHECKED

 Application type:  Console application
 Additional options:  Empty project CHECKED

Navigate to C:\HelloWorld. Copy the following files as before such that they are on the same folder level like HelloWorld.sln: crt0_sms.rel, SMSlib.h, SMSlib.lib, ihx2sms.exe. Add existing: main.c and build.bat.

External Tools
Integrate the build process directly from within Visual Studio 2008 using the External Tools functionality.
Choose Tools menu | External Tools... | Add
 Title:  Run Batch File
 Command:  CMD.EXE
 Arguments:  /c "$(SolutionDir)"build.bat
 Initial directory:  $(SolutionDir)
 Use Output Window  CHECKED
 Close on exit  CHECKED
Click Apply button. Click Move Up button until "Run Batch File" is at the top of the list.

Keyboard Shortcut
Next connect "Run Batch File" command to Ctrl+1 hot key to automatically build, link and execute code!

Choose Tools menu | Options... | Environment | Keyboard. Show command containing: "Tools". Scroll list down to "Tools.ExternalCommand1". In the "Press shortcut keys:" textbox hit Ctrl+1. Click Apply button.

Disassemble
Finally, disassemble the compiled binary file output.sms generated from the Visual Studio batch script.
In directory C:\HelloWorld, copy the 2x files Opcodes.dat and smsexamine.exe from SMS Examine zip.

Launch command prompt, change directory to cd C:\HelloWorld. Type: smsexamine.exe output.sms.
This action will generate output.sms.asm and any data files. Launch ConTEXT. Open output.sms.asm: Follow instructions to setup emulator hotkeys for: F10 (Fusion) F11 (Meka) + HOTKEY F12 (Emulicious).

Press F12 to run program in Emulicious. Ensure VDP constraints are ENABLED to emulate real hardware.

Note: in Emulicious we are able to debug through the HelloWorld source assembly code:

Compare machine code in the debugger with the raw binary output file from output.sms.

Update the build.bat script to include the disassemble step. Clean up and delete any unnecessary files:
@echo off
sdcc -c -mz80 main.c
sdcc -o output.ihx -mz80 --data-loc 0xC000 --no-std-crt0 crt0_sms.rel main.rel SMSlib.lib
ihx2sms output.ihx output.sms
smsexamine.exe output.sms
del *.ihx > nul
del *.lk > nul
del *.lst > nul
del *.map > nul
del *.noi > nul
del *.sym > nul
output.sms

Summary
Now the devkitSMS has been downloaded, installed and setup, it is possible to write full homebrew demos and / or video games to target real Sega Master System hardware! This will be the topic of the next post.

Tuesday, July 4, 2017

Sega Master Everdrive

In 2013, we checked out Sega Retro Gaming to mark the 30 year anniversary [July 1983] launch of the Sega SG-1000 and SC-3000. We also checked out the Sega Master System as these were the last ever 8-bit video game consoles manufactured by Sega built using the Z80 chip.

Here, we installed an emulator on a modern-day computer and downloaded ROMs in order to play some classic Sega retro games. Now we would like to play these game on real hardware via Master Everdrive.
Let’s check it out!

Description
The Master Everdrive is a multi-cart for the Sega Master System which loads ROMs in the console itself: Store ROM files on SD card. Plug SD card into Everdrive and load Everdrive into Master System cart slot.

Features
The Master Everdrive Printed Circuit Board (PCB) is built by @krikzz and contains the following features:
  • FRAM for game saves (no battery required)
  • Max supported ROM size is 8Mbit (1Mbyte)
  • SMS and SG-1000 games are supported
  • Save RAM data can be stored or loaded from the SD card
  • Cartridge used on Game Gear via Master Gear Converter
  • Codemasters and Sega mappers are supported
  • SD/SDHC cards supported up to 32GB
  • FAT16 and FAT32 support
Therefore, the Everdrive allows entire library of SG-1000 + Master System games on a single cartridge! Note: valid binary files should have extension *.sg [SG-1000] *.sc [SC-3000] *.sms [Master System]

Requirements
Purchase the following equipment in order to play classic 8-bit Sega retro video games on real hardware:
  1. Sega Master System
  2. Master Everdrive
  3. SD card [storage]
  4. USB SD card reader
  5. CRT TV [optional]

1. Sega Master System
 Amazon  Sega Master System 1
 The Rage  Shop Sega [incl. SMS]
 eBay  SEGA Master System Original

2. Master Everdrive
 Stone Age Gamer  Master Everdrive (Deluxe Edition)
 Retro Towers  Master Everdrive (Cartridge Form) With Shell
 eBay  Everdrive Sega Master System + Carcasa

3. SD card
If / when you buy a Master Everdrive from Stone Age Gamer there is an option to include 2GB SD card.

4. SD card reader
Some computers do not have an SD drive therefore is may be necessary to buy a USB SD card reader.

5. CRT Television
Optional extra however a CRT Television would be necessary to play Light Phaser games like Rambo III.

Instructions
Here are some You Tube videos on the Master Everdrive beginning with this cool Cart Review "tutorial":
 You Tube  Fantastic Flashcarts
 You Tube  SMS Flashcart Demo
 You Tube  Master Everdrive Opening

Homebrew
Finally, we would like to play many of the SG-1000 + Master System Homebrew games available on real hardware via the Master Everdrive! Checkout SMS Power web site especially Homebrew + Competitions.

Choices to build your own 8-bit Sega Homebrew games generally result in 2x options: writing game code in pure Z80 assembly or writing game code in C and using cross compiler to generate the binary output. References: Sega Console Programming or z88dk Programming Setup or z88dk Programming Sample

Either way, it is imperative there are enough clock cycles, i.e. at least 26 clock cycles, between two Video RAM (VRAM) writes when in the active phase. Otherwise VRAM corruption will occur as graphics glitches!

Emulation
Emulate graphics on real hardware to check for potential glitches in the Visual Display Processor (VDP). Download Emulicious emulator. Setup Options | Emulation | Master System | Emulate VDP constraints.

Example
Download and extract "Hello World". Launch ConTEXT editor, choose File menu, Open, "Hello World.asm" Follow Sega Console Programming to setup ConTEXT F9, F10, and F11, keys. Now setup the F12 key:

F12 - Emulicious Execute: Emulicious.bat
Parameters: "%poutput.sms"
Start in: C:\PathTo\Emulicious-with-Java

Press F9 to compile and link "Hello World.asm". This generates the "output.sms" binary file.
Press F12 to run Hello World in Emulicious emulator [Emulate VDP constraints real hardware]

Summary
To summarize, the Master Everdrive is a great way to play classic Sega retro games on real hardware.
It also makes it possible to play many of the Homebrew games available on the Sega Master System.

In 2014, we checked out z88dk as a way to write our own Homebrew game code in C language as an alternative to pure Z80 assembly. This is how 3D City and other SMS homebrew games were built.

Unfortunately, it seems that the z88dk does not allow for enough clock cycles between multiple VRAM writes, which results in graphics glitches! The devkitSMS, however, does not seem to have this issue J

This will be the topic in the next post.