Saturday, September 15, 2018

Simpsons Trivia Android Port

Placeholder for Simpsons Trivia Android Port coming soon...!

Friday, August 31, 2018

Simpsons Trivia Windows Port

In the previous post, we introduced Simpsons Trivia: a simple quiz game for the Sega Master System. Here we outlined tasks to port game to XNA 4.0. Now we will port to MonoGame for Windows as a new baseline.

The motivation here assumes a point where it is difficult / impossible to install XNA 4.0 plus required Visual Studio 2010 pre-requisite onto Windows PC. Especially if / when Windows 7 is deprecated for Windows 10. Let's check it out!

Setup
Follow all instructions from this post to setup MonoGame, Visual Studio and, if necessary, Xamarin Studio.

Outline
Similar to previous post, write all game code in an external library to be consumed by multiple thin clients. Configure SVN Externals as previous post but library and test projects now driven from Windows solution!

WIN Game Server
Launch Visual Studio 2015. Create blank solution. Add the following 4x new C#/.NET projects to solution:
 Project  Type  Description
 SimpsonsTrivia.WIN  MonoGame 3.6 Windows  Entry point + game built content
 SimpsonsTrivia.WIN.Library  MonoGame 3.6 Windows  Generic game library for all clients
 SimpsonsTrivia.WIN.SystemTests  Windows Class Library  Uses for game library system tests
 SimpsonsTrivia.WIN.UnitTests  Windows Class Library  Uses for game library unit tests

Note: as there is not a corresponding XNA Library project template for MonoGame, create 2x MonoGame Windows projects but set the second project output type for SimpsonsTrivia.WIN.Library to Class Library:

Checklist
Here is a quick checklist of tasks to complete first including Delete the default C#/.NET file, Update project properties profile to use "Reach" and Rename the default namepsace to WindowsGame. Add the packages:

packages
  • log4net.2.0.8
  • Ninject.3.3.4
  • NUnit.3.2.1
  • RhinoMocks.3.6.1
SimpsonsTrivia.WIN
  • Add Data folder for all text file data
  • Add SimpsonsTrivia.WIN.Library ref
  • Update EXE binary output path
  • Replace all initial game icons
SimpsonsTrivia.WIN.Library
  • Add Common folder for all game code logic
  • Add Master folder for all game engine code
  • Add log4net reference
  • Add Ninject reference
SimpsonsTrivia.WIN.SystemTests
  • Remove DataSetExtensions reference
  • Add SimpsonsTrivia.WIN.Library ref
  • Add nunit framework reference
  • Add nunit GUI test runner
SimpsonsTrivia.WIN.UnitTests
  • Remove DataSetExtensions reference
  • Add SimpsonsTrivia.WIN.Library ref
  • Add nunit framework reference
  • Add Rhino Mocks reference
  • Add nunit GUI test runner

IMPORTANT
Create directory symbolic link using mklink to WIN Content folder to run system tests [and on build server]

Start | run | cmd
mklink /D C:\SimpsonsTrivia.WIN.Content 
C:\SVN\SimpsonsTrivia\SimpsonsTrivia.WIN\SimpsonsTrivia.WIN\bin\x86\Debug\

// BaseSsytemTests.cs
protected const String CONTENT_ROOT = @"C:\SimpsonsTrivia.WIN.Content\";

Warnings
Manually edit system and unit test projects in Notepad and add following XML to mitigate MSIL warning:
<PropertyGroup>
  <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
</PropertyGroup>

Re-install NuGet packages as necessary to mitigate against warning using a different target framework:
Tools | NuGet Package Manager | Package Manager Console. Type update-package -reinstall

Finally, action the following if conflicts found between different versions of the same dependent assemblies:
Open SimpsonsTrivia.WIN.csproj in Notepad++ Add XML following <OutputType>WinExe</OutputType>
  <OutputType>WinExe</OutputType>
  <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>

NUnit
Don't forget to setup the *.nunit files to open with NUnit (x86) version by default. Right click SystemTests or UnitTests nunit file | Open With... | Add as "C:\Program Files (x86)\NUnit 2.5.7\bin\net-2.0\nunit-x86.exe"
 Key  Value
 Program:  "C:\Program Files (x86)\NUnit 2.5.7\bin\net-2.0\nunit-x86.exe"
 Arguments:  
 Friendly name:  NUnit (x86)


Audio
The original music used for Simpsons Trivia was in VGM format for title and game over and PSG format for the sound effects. Therefore, these must be converted to MP3 + WAV format respectively for Windows PC.

Music
Download Audio Overload application and extract. Launch aowin64.exe. Dag VGM file into application. Save clip as WAV file and click Play button. Play song to end. Once finished will save. Convert WAV to MP3 online.

Note: Audacity can also be used to convert WAV files to MP3. Open WAV file. Choose File | Export Audio and Save as MP3. However, it may be required to download Lame to complete export! Download Lame from here.

Sound
First write sample program to play PSG files in Sega Master System program. These will recorded manually:
#include "..\lib\SMSlib.h"
#include "..\lib\PSGlib.h"
#include "gfx.h"
#include "psg.h"

#define SFX_RIGHT_PSG sfx_right_psg
#define SFX_WRONG_PSG sfx_wrong_psg
#define SFX_CHEAT_PSG sfx_cheat_psg

void main (void)
{
 PSGSFXPlay( SFX_RIGHT_PSG, SFX_CHANNEL2 );
 SMS_displayOn();
 for (;;)
 {
  SMS_waitForVBlank();
  PSGSFXFrame();
 }
}
SMS_EMBED_SEGA_ROM_HEADER( 9999, 0 );
SMS_EMBED_SDSC_HEADER( 1, 2, 2018, 3, 27, "StevePro Studios", "Simpsons Trivia", "Simpsons Trivia game for the SMS Power! 2018 Competition" );

Setup computer as follows:
Unplug speaker cable from audio jack. Plug black cable from microphone into headphone jack. Launch Voice Recorder. Start recorder. Play Sega Master System program. Stop recorder. Save as, or convert to, WAV file.


Content
MonoGame Windows project templates add a "Content" folder as the default location for all Content. Right click the "Content" folder | Add New Folder. Simpsons Trivia uses the 4x following subfolders (listed below):

Data
Contains flat TXT + XML data files to be consumed by the game. Do not need to be built as XNB files!
Right click each data file | Properties | Build action: None | Copy to output directory: Copy if newer

Fonts
Font XNB files may need to be rebuilt for Windows using the MonoGame Pipeline; instructions below:
Right click each font file | Properties | Build action: Content | Copy to output directory: Copy if newer

Sound
Sound effect XNB files may need to be rebuilt for Windows using the MonoGame Pipeline; see below:
Right click sound effect | Properties | Build action: Content | Copy to output directory: Copy if newer

Song XNB files may also be rebuilt along with corresponding WMA files to be included in the project:
Right click music files | Properties | Build action: Content | Copy to output directory: Copy if newer

Textures
Here texture XNB files may need to be rebuilt for Windows using the MonoGame Pipeline; see below:
Right click sound effect | Properties | Build action: Content | Copy to output directory: Copy if newer


MonoGame Pipeline
The MonoGame Pipeline Tool is used to manage MonoGame content and generate corresponding XNB files. Follow this documentation on how to use the MonoGame Pipeline Tool. Create Simpsons Trivia WIN project:

Start | run | MonoGame Pipeline. File | New. File name: WindowsProject.mgcb | Save content pipeline file. Select top level "WindowsProject" node. In the Properties window choose Platform; in this case Windows. Import all content from original game such as Fonts, Sound [music + sound FX] and Textures [images]. Right click on top level node and choose Rebuild. The converted XNB files will be generated in bin folder.

MAC Game Server
In the previous post, it was assumed to use Cross Platform Desktop project template for MAC. However, this seems more Linux-based. Instead, on the Mac, launch Xamarin Studio. Create Xamarin Mac Classic project: Unfortunately, as this is an experimental build, it was not currently possible to integrate music and sound FX. Open Info.plist and choose minimum deployment target available. At this time the minimum version is 10.7.

Finally, set up SVN Externals manually similar to this post:
cd ~/SVN/SimpsonsTrivia/SimpsonsTrivia.IOS/SimpsonsTrivia.IOS/Content
svn propset svn:externals 'Data http://build/svn/SimpsonsTrivia/SimpsonsTrivia.WIN/SimpsonsTrivia.WIN/Content/Data' .

cd ~/SVN/SimpsonsTrivia/SimpsonsTrivia.IOS/SimpsonsTrivia.IOS
svn propset svn:externals 'Common http://build/svn/SimpsonsTrivia/SimpsonsTrivia.WIN/SimpsonsTrivia.WIN.Library/Common' .
svn propset svn:externals 'Master http://build/svn/SimpsonsTrivia/SimpsonsTrivia.WIN/SimpsonsTrivia.WIN.Library/Master' .

svn status
cd ~/SVN/SimpsonsTrivia/SimpsonsTrivia.IOS/SimpsonsTrivia.IOS
svn commit -m "Add SVN Externals"
svn update

WP7 Game Server
Previously, WinPhone7 [WP7] was used as a destination client intermediary between Windows PC and mobile device deployment + testing on Windows 7. However, WP7 projects may fail to build in Visual Studio 2010 as FilterItemsBySupportedCultures task failed unexpectedly.

If this error occurs then close Visual Studio 2010. Update the binding redirect in the devenv.exe.config file:
Edit devenv.exe.config found as here C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\
<runtime>
  <UseSmallInternalThreadStacks enabled="true"/>
  <dependentAssembly xmlns="urn:schemas-microsoft-com:asm.v1"><Tag ...
    <dependentAssembly>
      <assemblyIdentity name="Microsoft.Build.Framework" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
      <bindingRedirect oldVersion="12.0.0.0-14.0.0.0" newVersion="4.0.0.0"/>
    </dependentAssembly>
However, this may not be required with the upgrade of Windows 10 as WP7 may now not be compatible!

WP8 Game Server
The successor to WP7 is WP8. Therefore, it makes sense to look for an experimental client to replace WP7. While it's possible to get corresponding build, there may be Hyper V Manager issues on some Windows PCs.

Summary
To summarize, the transition from XNA 4.0 + Visual Studio 2010 + Windows 7 to MonoGame 3.6 + Visual Studio 2015 + Windows 10 was very smooth. Plus, was an opportunity for additional experimental builds.

This included, an exploration of WP7 to WP8 for mobile device deployment + testing from the Windows PC. Finally, in order to complete mobile device deployment, the next posts will include ports to Android + iOS!

Wednesday, July 4, 2018

Simpsons Trivia XNA Port

In 2015, Candy Kid was written in XNA as a simple maze chase video game and ported to Android and iOS mobile platforms using MonoGame. The game code was written in an external library and scaled out using SVN Externals.

Earlier in 2018, Simpsons Trivia was built for the Sega Master System. Now, we would like to employ similar techniques to re-write the game in XNA / MonoGame and scale out across multiple game clients accordingly. Let's check it out!

Outline
Create solution in Visual Studio and build the entire game using XNA. Write all game code in an external library to be consumed by multiple thin clients for all destination platforms. Add any experimental clients.
 Alias  Name  Development  Framework  Description  Source Code
 XNA  Windows Game  Visual Studio 2010  XNA 4.0  Game server  Download
 WP7  Windows Phone 7  Visual Studio 2010  XNA 4.0  Game client  Download
 WIN  Windows Project  Visual Studio 2015  MonoGame 3.6  Game client  Download
 AND  Android Project  Visual Studio 2017  MonoGame 3.4  Game client  Download
 IOS  iOS Project  Visual Studio 2017  MonoGame 3.5  Game client  Download
 WP8  Windows Phone 8  Visual Studio 2015  MonoGame 3.6  Game client  Experimental
 MAC  Cross Platform Desktop  Visual Studio 2017  MonoGame 3.6  Game client  Experimental
 UWP  Windows Universal Project  Visual Studio 2017  MonoGame 3.6  Game client  Experimental

IMPORTANT
Now that Microsoft integrates iOS templates into Visual Studio all clients can be developed on Windows PC. Mac computer is still required for iOS and Mac deployments, however.

Implementation
Create top level SimpsonsTrivia node in Subversion SVN. Add 1x sub-node for the XNA solution and multiple sub-nodes, one sub-node for each destination client such as WinPhone7 [WP7], Windows PC, Android + iOS.
 Alias  Path  URL
 XNA  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.XNA  http://build/svn/SimpsonsTrivia/SimpsonsTrivia.XNA 
 WP7  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.WP7  http://build/svn/SimpsonsTrivia/SimpsonsTrivia.WP7
 WIN  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.WIN  http://build/svn/SimpsonsTrivia/SimpsonsTrivia.WIN
 AND  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.AND  http://build/svn/SimpsonsTrivia/SimpsonsTrivia.AND
 IOS  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.IOS  http://build/svn/SimpsonsTrivia/SimpsonsTrivia.IOS
As Simpsons Trivia is small stand-alone game there will not be standard SVN branches / tags / trunk setup.

XNA Game Server
Launch Visual Studio 2010. Create blank solution. Add the following 4x new C#/.NET projects to solution:
 Project  Type  Description
 SimpsonsTrivia.XNA  XNA 4.0 Game  Entry point + game built content
 SimpsonsTrivia.XNA.Library  XNA 4.0 Game Library  Generic game library for all clients
 SimpsonsTrivia.XNA.SystemTests  Windows Class Library  Uses for game library system tests
 SimpsonsTrivia.XNA.UnitTests  Windows Class Library  Uses for game library unit tests

Checklist
Here is a quick checklist of tasks to complete first including Delete the default C#/.NET file, Update project properties profile to use "Reach" and Rename the default namepsace to WindowsGame. Add the packages:

packages
  • log4net.2.0.5
  • Ninject.3.2.2.0
  • NUnit.3.2.1
  • RhinoMocks.3.6.1
SimpsonsTrivia.XNA
  • Add Data folder for all text file data
  • Add SimpsonsTrivia.XNA.Library ref
  • Remove all unused XNA references
  • Replace all initial game icons
SimpsonsTrivia.XNA.Library
  • Add Common folder for all game code logic
  • Add Master folder for all game engine code
  • Remove all unused XNA references
  • Add XNA Input Touch reference
  • Add log4net reference
  • Add Ninject reference
SimpsonsTrivia.XNA.SystemTests
  • Remove DataSetExtensions reference
  • Add SimpsonsTrivia.XNA.Library ref
  • Add nunit framework reference
  • Add nunit GUI test runner
SimpsonsTrivia.XNA.UnitTests
  • Remove DataSetExtensions reference
  • Add SimpsonsTrivia.XNA.Library ref
  • Add nunit framework reference
  • Add Rhino Mocks reference
  • Add nunit GUI test runner

IMPORTANT
Create directory symbolic link using mklink to XNA Content folder to run system tests [and on build server]

Start | run | cmd
mklink /D C:\SimpsonsTrivia.XNA.Content 
C:\SVN\SimpsonsTrivia\SimpsonsTrivia.XNA\SimpsonsTrivia.XNA\SimpsonsTrivia.XNA\bin\x86\Debug\

// BaseSsytemTests.cs
protected const String CONTENT_ROOT = @"C:\SimpsonsTrivia.XNA.Content\";

Manually edit system and unit test projects in Notepad and add following XML to mitigate MSIL warning:
<PropertyGroup>
  <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
</PropertyGroup>

ALL Game Clients
Refer to initial table and launch Visual Studio to create multiple thin client projects. SVN externals used to link XNA library to all destination platforms [below] such as WinPhone7 [WP7], Windows PC, Android + iOS.


SVN Externals
Employ SVN Externals to avoid copy + paste programming for Common and Master code and content Data.
At the start of a project, there won't be any SVN Externals setup by default. Verify from Command prompt:
 Alias   Folder 
 WP7  cd C:\SVN\SimpsonsTrivia\SimpsonsTrivia.WP7\SimpsonsTrivia.WP7
 WIN  cd C:\SVN\SimpsonsTrivia\SimpsonsTrivia.WIN\SimpsonsTrivia.WIN
 AND  cd C:\SVN\SimpsonsTrivia\SimpsonsTrivia.AND\SimpsonsTrivia.AND
 IOS  cd C:\SVN\SimpsonsTrivia\SimpsonsTrivia.IOS\SimpsonsTrivia.IOS
Start | run | cmd. Type svn propget -R svn:externals
empty


SimpsonsTrivia.XNA
Scale game built content including all text file Data as shared across multiple thin clients via SVN Externals:

DATA
 Path  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.XNA\SimpsonsTrivia.XNA\SimpsonsTrivia.XNAContent\Data
 URL  H://svn/SimpsonsTrivia/SimpsonsTrivia.XNA/SimpsonsTrivia.XNA/SimpsonsTrivia.XNAContent/Data
* H:// = http://build/

Launch Windows Explorer | Navigate to following [parent] folder:
 Alias   
 WP7  Folder :  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.WP7\SimpsonsTrivia.WP7
 Action :  Right click "SimpsonsTrivia.WP7Content" folder
 WIN  Folder :  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.WIN\SimpsonsTrivia.WIN
 Action :  Right click "Content" folder
 AND  Folder :  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.AND\SimpsonsTrivia.AND\Assets
 Action :  Right click "Content" folder
 IOS  Folder :  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.IOS\SimpsonsTrivia.IOS
 Action :  Right click "Content" folder

Tortoise SVN | Properties | New... | Externals
In popup window click New button:
 Local path:  Data
 URL:  http://build/svn/SimpsonsTrivia/SimpsonsTrivia.XNA/SimpsonsTrivia.XNA/SimpsonsTrivia.XNAContent/Data
OK | OK | OK

Start | run | cmd. Type svn propget -R svn:externals
. - http://build/svn/SimpsonsTrivia/SimpsonsTrivia.XNA/SimpsonsTrivia.XNA/SimpsonsTrivia.XNAContent/Data

Windows Explorer | Navigate to [parent] folder as before. Tortoise SVN | Check for modifications | Commit
Finally, right click C:\SVN\SimpsonsTrivia | SVN Update. Data folder available to include in ALL clients.


SimpsonsTrivia.XNA.Library
Scale all Common game code and logic + Master engine code across multiple thin clients via SVN Externals:

COMMON
 Path  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.XNA\SimpsonsTrivia.XNA.Library\Common  Common game
 URL  H://svn/SimpsonsTrivia/SimpsonsTrivia.XNA/SimpsonsTrivia.XNA.Library/Common  code and logic.
* H:// = http://build/

Launch Windows Explorer | Navigate to following [parent] folder:
 Alias   
 WP7  Folder :  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.WP7\SimpsonsTrivia.WP7
 Action :  Right click "SimpsonsTrivia.WP7" folder
 WIN  Folder :  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.WIN
 Action :  Right click "SimpsonsTrivia.WIN" folder
 AND  Folder :  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.AND
 Action :  Right click "SimpsonsTrivia.AND" folder
 IOS  Folder :  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.IOS
 Action :  Right click "SimpsonsTrivia.IOS" folder

Tortoise SVN | Properties | New... | Externals
In popup window click New button:
 Local path:  Common
 URL:  http://build/svn/SimpsonsTrivia/SimpsonsTrivia.XNA/SimpsonsTrivia.XNA.Library/Common
OK | OK | OK

Start | run | cmd. Type svn propget -R svn:externals
. - http://build/svn/SimpsonsTrivia/SimpsonsTrivia.XNA/SimpsonsTrivia.XNA.Library/Common Common

Windows Explorer | Navigate to [parent] folder as before. Tortoise SVN | Check for modifications | Commit
Finally, right click C:\SVN\SimpsonsTrivia | SVN Update. Common folder available to include in ALL clients.


MASTER
 Path  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.XNA\SimpsonsTrivia.XNA.Library\Master  Master game
 URL  H://svn/SimpsonsTrivia/SimpsonsTrivia.XNA/SimpsonsTrivia.XNA.Library/Master  engine code.
* H:// = http://build/

Launch Windows Explorer | Navigate to following [parent] folder:
 Alias   
 WP7  Folder :  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.WP7\SimpsonsTrivia.WP7
 Action :  Right click "SimpsonsTrivia.WP7" folder
 WIN  Folder :  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.WIN
 Action :  Right click "SimpsonsTrivia.WIN" folder
 AND  Folder :  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.AND
 Action :  Right click "SimpsonsTrivia.AND" folder
 IOS  Folder :  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.IOS
 Action :  Right click "SimpsonsTrivia.IOS" folder

Tortoise SVN | Properties | New... | Externals
In popup window click New button:
 Local path:  Master
 URL:  http://build/svn/SimpsonsTrivia/SimpsonsTrivia.XNA/SimpsonsTrivia.XNA.Library/Master
OK | OK | OK

Start | run | cmd. Type svn propget -R svn:externals
. - http://build/svn/SimpsonsTrivia/SimpsonsTrivia.XNA/SimpsonsTrivia.XNA.Library/Master Master

Windows Explorer | Navigate to [parent] folder as before. Tortoise SVN | Check for modifications | Commit
Finally, right click C:\SVN\SimpsonsTrivia | SVN Update. Master folder available to include in ALL clients.


Summary
To summarize, there will most likely become a point where it is difficult / impossible to install XNA 4.0 plus required Visual Studio 2010 pre-requisite onto Windows PC. Especially if / when Windows 7 is deprecated.

Therefore, it seems sensible to upgrade to Windows 10 : transfer these skills to integrate MonoGame 3.6 on Visual Studio 2015 as new baseline. After this, Android and iOS ports can resume using Visual Studio 2017.

Consequently, the next posts will document just that; starting with Windows port then to Android and iOS J

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!