Wednesday, May 1, 2019

Platform Explorer Code Complete

In the old days of Game Creation with XNA, there was a popular Microosft XNA project called "Platformer". This starter kit contained code + content to demo basic game mechanics of a simple platform video game.

Therefore, the "Platformer" starter kit seemed a good candidate project to port to the Sega Master System. Enter Platform Explorer!

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

Note: previous titles published for the Master System include 3D City, Candy Kid Demo + Simpsons Trivia.
Download source code here.

Sega Retro Gaming post documents how to play video games like Platform Explorer using a Fusion emulator.
devkitSMS Programming Setup post documents development environment required to build C / Z80 source.

Instructions
Simple: move joystick Left or Right to run and Button1 to jump. Avoid all enemies + guards and watch out for the pits! After feedback from the community, you can now choose game speed as Slow [motion] or Fast.

After the third iteration, the first 10x levels are Tutorial and the currently remaining 40x levels are available "New Game". There is capacity for 80-100 levels. Please let me know if you'd like to design some levels J

Tools
Here are a list of Tools and frameworks that were used in the development of this project:
 KEY  VALUE
 Programming  devkitSMS
 Compiler  sdcc 3.6
 Assembler  WLA-DX
 IDE  Visual Studio 2015
 Languages  C / Z80
 Graphics  BMP2Tile 0.43 / GIMP 2 / paint.net
 Music  Mod2PSG2 / vgm2psg
 Emulators  Emulicious / Fusion / Meka

ROM Hacking
You can hack this ROM! Download + dump PlatformExplorer into Hex Editor, e.g. HxD, and modify bytes:
 ADDRESS  VARIABLE  DESCRIPTION
 0x004F  DelaySpeed  Used during dev disables screen delays.
 0x0050  Invincible  Non-zero value enables auto invincible.
 0x0051  Difficulty  Set value to 1=Hard otherwise use Easy.
 0x0052  Game Speed  Set value to 1=Slow otherwise use Fast.
 0x0053  World No.  Set start world no to zero-based value.
 0x0054  Round No.  Set start round no to zero-based value.
 0x0055  Music Off  Set 0=music to play otherwise disabled.
 0x0056  Sound Off  Set 0=sound to play otherwise disabled.
 0x0057  Enemy move  Set value non-zero to disable movement.

Bonuses
  • Player will receive free man for every 20x gems collected during game.
  • Player will also receive bonus 5x gems on collecting all gems in level.

Cheats
  • Press Button2 five times on Start screen and you will be invincible each game this is actioned.
  • Press Button2 three times while holding down on Difficulty screen to navigate to select screen.
  • Press and hold Button2 during game play to reset player to original starting spot in each level.
  • Press and hold Button2 while holding down to secretly quit out game back to the Start screen.

Credits
Extra special thanks goes to sverx for the devkitSMS. Plus StevePro Studios would like to thank eruiz00 and haroldoop for sharing source code from SMS Homebrew projects. Many ideas here were used in this project!

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!

Platform Explorer presented the challenge of reverse engineering the original Platformer starter kit code written for a more modern CPU with floating point functionality and run on an 8-bit system with no FPU!

Thankfully, "Writing a platformer for the TIC-80 fantasy console" blog post was available and helped to build more optimized code by pre-calculating physics velocity + acceleration and caching in integer lookup tables.

Promotion
A simple video was made to promote this game. But a special mention must go out ARCADE MAN for all his work producing some amazing videos for the Coding and Hack entries in the SMS Power! 2019 Competition.

Summary
To summarize, the 2019 Coding Competition featured fewer entries than last year as opposed to the Hacks. The quality of the hacks in 2019 was really high and actually scored higher than coding competition entries!

The hacks are mainly based around the KiddEd editor. Explanations about how to use editor are found here: Create an IPS patch in editor. Download "Alex Kidd in Miracle World" ROM and use Lunar IPS to patch ROM.

This video tutorial demos how to patch ROMs with IPS patches. Maybe something to try for a future project!

Sunday, April 28, 2019

devkitSMS Programming Sample III

In 2017, we checked out devkitsms to setup productive development environment to build 8-bit retro video games for the Sega Master System. In 2018, we streamlined this build process to develop Simpsons Trivia.

However, as projects became larger they seemed longer to build. Plus it didn't seem possible to debug step through C source code. Look for opportunities to improve the process further as we build Platform Explorer! Let's check it out!

Game
Platform Explorer is an open source port of the XNA Platform starter kit for the Sega Master System. This video game was also an entry in the SMS Power! 2019 Coding Competition. Download source code here.

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].

Checklist
Here is a checklist of tasks to complete in order to try and improve the existing development environment:
  • Graphics changes and BMP2Tile update
  • Visual Studio 2015 upgrade and setup
  • Code file separation and build times
  • Various code architectural updates
  • Debug step through code support
  • Performance tweaks then polish

Graphics
Previous work on SMS graphics progressed from MS Paint to Gimp to use Indexed mode with max 16 colors to conform to the 4bpp (bits per pixel) constraints. However, this was only with 256x192 full screen images.

Now, we would like to save multiple individual image files, for example, for sprite animations and share the color palette such that it can be used across all relevant tiles. Therefore, here is how to import the palette:

Launch Gimp | Open an image you would like the palette shared. Image | Mode | Indexed to generate the 16 color palette (4bpp). Windows | Dockable dialogs | Palettes. Right click list and enter the following info:
Now there will new custom 4bpp 16-color palette at %USERPROFILE%\.gimp-2.8\palettes. Finally, extend previous process after Image | Mode | Indexed choose Colors | Map | Set Colormap... Palette: Platformer.

BMP2Tile
Upgrade to Version 0.43 for -fullpalette option to Output 16 colors rather than as many present in image.
bmp2tile.exe raw\back_tiles.bmp -savetiles "back_tiles (tiles).psgcompr" -noremovedupes -planar -tileoffset 0 -exit
bmp2tile.exe raw\back_tiles.bmp -savetilemap "back_tiles (tilemap).bin" -exit
bmp2tile.exe raw\back_tiles.bmp -savepalette "back_tiles (palette).bin" -fullpalette -exit

Visual Studio
In 2017, we were 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. Now it is time to upgrade from VS2008 to 2015.

The motivation here assumes a point where it is difficult / impossible to use Visual Studio 2008 on Windows PC. Plus Visual Studio 2015 has a cool feature to easily Toggle Header / Code files for increased productivity. Replicate all instructions here: Setup External Tools to integrate the build process directly from within Visual Studio and connect "Run Batch File" command to Ctrl+1 hot key and automatically build and execute code!

Formatting
Formatting is important because formatted code makes it easier to read, understand, maintain and debug. Visual Studio 2015. Tools menu | Options... | Text Editor | C/C++ | Formatting | Spacing. Update settings:

Setup
Create folder C:\PlatformExplorerSMS. Create the following sub-folders: asm, crt0, dev, gfx, lib, psg, tmp. Note: tmp sub-folder contains dummy PSGlib.h and SMSlib.h header files used for debugging - more soon. IMPORTANT: more information on which files reside in sub-folders and why can be found at here and here.

Separation
As projects became larger they seemed longer to build. Traditionally, this has been because all the code has been spread across multiple header files and with only 1x main.c which forces a complete rebuild each time.

Therefore, in an attempt to improve build compile times, we'd like to separate interface from implementation code: keep header files lean with goal that static code in translation units need not be constantly recompiled!

Note: here object files would have to be version controlled and build script may change during development.

Timing
In order to test hypothesis that separating code improves compilation speed then record build script times:
:: Calculate the start timestamp
set _time=%time: =0%
set /a _hours=100%_time:~0,2%%%100,_min=100%_time:~3,2%%%100,_sec=100%_time:~6,2%%%100,_cs=%_time:~9,2%
set /a _started=_hours*60*60*100+_min*60*100+_sec*100+_cs

sdcc -c -mz80 --opt-code-speed --peep-file ..\peep-rules.txt --std-c99 _sms_manager.c
sdcc -c -mz80 --opt-code-speed --peep-file ..\peep-rules.txt --std-c99 _snd_manager.c
sdcc -c -mz80 --opt-code-speed --peep-file ..\peep-rules.txt --std-c99 global_manager.c
sdcc -c -mz80 --opt-code-speed --peep-file ..\peep-rules.txt --std-c99 debug_manager.c
sdcc -c -mz80 --opt-code-speed --peep-file ..\peep-rules.txt --std-c99 hack_manager.c
:: continue compiling remaining implementation [*.c] files

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

:: Calculate the difference in cSeconds
set _time=%time: =0%
set /a _hours=100%_time:~0,2%%%100,_min=100%_time:~3,2%%%100,_sec=100%_time:~6,2%%%100,_cs=%_time:~9,2%
set /a _duration=_hours*60*60*100+_min*60*100+_sec*100+_cs-_started

:: Populate variables for rendering (100+ needed for padding)
set /a _hours=_duration/60/60/100,_min=100+_duration/60/100%%60,_sec=100+(_duration/100%%60%%60),_cs=100+_duration%%100

echo.
echo Time taken: %_sec:~-2%.%_cs:~-2% secs
echo

Coding
The following coding changes + enhancements have been made throughout Platform Explorer development:

devkitSMS
The original SMSlib.h and PSGlib.h header files do not seem to have include guard clauses which means they can't be included more than once so let's create wrappers for them. In fact, this is beneficial for debugging.
// _sms_manager.h
#ifndef _SMS_MANAGER_H_
#define _SMS_MANAGER_H_

void devkit_SMS_init();
void devkit_SMS_displayOn();
void devkit_SMS_displayOff();
void devkit_SMS_mapROMBank( unsigned char n );
// ...

// input
unsigned int devkit_SMS_getKeysStatus();
unsigned int devkit_PORT_A_KEY_UP();
unsigned int devkit_PORT_A_KEY_DOWN();
// ...
unsigned int devkit_PORT_A_KEY_1();
unsigned int devkit_PORT_A_KEY_2();

// #defines
unsigned char devkit_SPRITEMODE_NORMAL();
unsigned int devkit_VDPFEATURE_HIDEFIRSTCOL();

#endif//_SMS_MANAGER_H_
Note: repeat this process for PSGlib.h. Also, don't forget to upgrade PSGlib to include PSGResume() API.

Screen
As projects get larger there will be more screens. Therefore, refactor and channel through screen manager:
// screen_manager.c
#include "screen_manager.h"
#include "global_manager.h"
#include "enum_manager.h"

// Screens
#include "splash_screen.h"
#include "intro_screen.h"
// ...
#include "over_screen.h"

static void( *load_method[ MAX_SCREEENS ] )( );
static void( *update_method[ MAX_SCREEENS ] )( unsigned char *screen_type );

static unsigned char curr_screen_type;
static unsigned char next_screen_type;

void engine_screen_manager_init( unsigned char open_screen_type )
{
  next_screen_type = open_screen_type;
  curr_screen_type = screen_type_none;

  // Set load methods.
  load_method[ screen_type_splash ] = screen_splash_screen_load;
  load_method[ screen_type_intro ] = screen_intro_screen_load;
  // ...
}

void engine_screen_manager_update()
{
  if( curr_screen_type != next_screen_type )
  {
    curr_screen_type = next_screen_type;
    load_method[ curr_screen_type ]();
  }

  update_method[ curr_screen_type ]( &next_screen_type );
}

Input
Remove previous + current input state that was injected into methods and channel through input manager:
// input_manager.c
#include "input_manager.h"
#include "_sms_manager.h"

// Must be static to persist values!
static unsigned int curr_joypad1 = 0;
static unsigned int prev_joypad1 = 0;

// Private helper methods.
static unsigned char engine_input_manager_hold( unsigned int data );
static unsigned char engine_input_manager_move( unsigned int data );

// Public method.
void engine_input_manager_update()
{
  prev_joypad1 = curr_joypad1;
  curr_joypad1 = devkit_SMS_getKeysStatus();
}

// main.c
for (;;)
{
  if( devkit_SMS_queryPauseRequested() )
  {
    // ...
  }

  devkit_SMS_initSprites();
  engine_input_manager_update();
  engine_screen_manager_update();

  devkit_SMS_finalizeSprites();
  devkit_SMS_waitForVBlank();
  devkit_SMS_copySpritestoSAT();

  devkit_PSGFrame();
  devkit_PSGSFXFrame();
}

Banks
In 2017, Astro Force by eruiz00 gave a great example on how to reference bank information generated from bmp2tile and folder2c in code to lookup data stored in arrays, for example, to load banked sprite animation:
// anim_object.h
extern const unsigned char *player_anim_data[];
extern const unsigned char player_anim_bank[];

//anim_object.c
#include "anim_object.h"
#include "..\banks\bank2.h"

const unsigned char *player_anim_data[] =
{
  player_idle__tiles__psgcompr,
  player_run_left_01__tiles__psgcompr,
  player_run_left_02__tiles__psgcompr,
  // ...
  player_run_rght_04__tiles__psgcompr,
  player_run_rght_05__tiles__psgcompr,
};
const unsigned char player_anim_bank[] =
{
  player_idle__tiles__psgcompr_bank,
  player_run_left_01__tiles__psgcompr_bank,
  player_run_left_02__tiles__psgcompr_bank,
  // ...
  player_run_rght_04__tiles__psgcompr_bank,
  player_run_rght_05__tiles__psgcompr_bank,
};

// anim_manager.c
static void player_load( unsigned char index, unsigned int tile )
{
  const unsigned char *data = ( const unsigned char * ) player_anim_data[ index ];
  const unsigned char bank = ( const unsigned char ) player_anim_bank[ index ];

  devkit_SMS_mapROMBank( bank );
  devkit_SMS_loadPSGaidencompressedTiles( data, tile );
}

Levels
In 2018, Duckslayer Adventures by haroldoop gave a great example of how levels could be stored externally in text files then converted into byte arrays using folder2c. The byte arrays are then interpreted for drawing:
 KEY  VALUE
 .  Blank
 #  Block
 @  Platform
 $  Optional
 1  Player
 X  Exit
 G  Gem
 P  Power
  // Level0101
  ................
  .P..............
  .@@...........@@
  ..........A.....
  ..G...$@@@@....G
  .@@...........@@
  ................
  .G............G.
  .@@...........@@
  .@@.1.......X.@@
  .####$$$$$$#####
  ..###$$$$$$####.

Structs
Finally, as seen in many code samples from haroldoop, structs are used extensively to store data especially data accessed globally throughout the code base. Platform Explorer uses this idea coupled with "manager":
// hack_object.h
typedef struct tag_struct_hack_object
{
  unsigned char hack_delayspeed;
  unsigned char hack_invincible;
  unsigned char hack_difficulty;
  unsigned char hack_game_speed;

} struct_hack_object;

 
// hack_manager.h
#include "hack_object.h"

void engine_hack_manager_init();
extern struct_hack_object global_hack_object;


// hack_manager.c
#include "hack_manager.h"
#include "global_manager.h"
#include "enum_manager.h"

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

#define HACKER_START       0x0050

// Global variable.
struct_hack_object global_hack_object;

void engine_hack_manager_init()
{
  struct_hack_object *ho = &global_hack_object;
  ho->hack_delayspeed = 0;
  ho->hack_invincible = 0;
  ho->hack_difficulty = 0;
  ho->hack_game_speed = 0;

#ifndef _CONSOLE
  ho->hack_delayspeed = PEEK( HACKER_START - 1 );
  ho->hack_invincible = PEEK( HACKER_START + 0 );
  ho->hack_difficulty = PEEK( HACKER_START + 1 );
  ho->hack_game_speed = PEEK( HACKER_START + 2 );
#endif
}

Debugging
Visual Studio is useful IDE for navigating a large code base. However, as the game code currently targets SDCC compiler it does not seem possible to debug step through the devkitSMS specific API source calls.

Nonetheless, leverage the _CONSOLE conditional compilation statement and implement the following code. Here, it is possible to debug step through all ANSI-C code at least trusting devkitSMS code works correctly.
// _sms_manager.c
#include "_sms_manager.h"
#include "info_manager.h"
#include <stdbool.h>

#ifdef _CONSOLE
#include "..\..\tmp\SMSlib.h"
#else
#include "..\..\lib\SMSlib.h"
#endif

void devkit_SMS_init()
{
  SMS_init();
}
void devkit_SMS_displayOn()
{
  SMS_displayOn();
}
void devkit_SMS_displayOff()
{
  SMS_displayOff();
}
void devkit_SMS_mapROMBank( unsigned char n )
{
  SMS_mapROMBank( n );
}
// ...

// Sega header.
#ifdef _CONSOLE
#else
  SMS_EMBED_SEGA_ROM_HEADER( productCode, revision );
  SMS_EMBED_SDSC_HEADER( verMaj, verMin, dateYear, dateMonth, dateDay, author, name, descr );
#endif
Remember: tmp sub-folder contains dummy PSGlib.h and SMSlib.h header files that facilitate debugging.

Performance
In order to process collision detections in Platformers, it is commonplace to take the absolute value of the distance of two points + use for comparison. Unfortunately, there was noticeable delay with this function:
int abs( int v )
{
  return v * ( ( v < 0 ) * ( -1 ) + ( v > 0 ) );
}
After examining code this function invoked multiple times per frame it was clear that abs() could be replaced with simple if statement. Being able to debug step through C code helped ensure this still worked as before!

Polish
Also, as projects become larger, more content is required. Therefore, to ensure polish throughout the game it was critical that the VRAM was cleared properly between large graphic content loads to avoid any glitches.
// intro_screen.c
void screen_intro_screen_load()
{
  // Unload VRAM each begin to remove any unwanted graphics glitches...!
  devkit_SMS_displayOff();
  engine_asm_manager_clear_VRAM();
  engine_text_manager_clear_all();

  engine_content_manager_load_back_tiles();
  engine_content_manager_load_sprites();
  engine_content_manager_load_title();
  // ...
  devkit_SMS_displayOn();
}
Deployment
Finally, a big shout out to Calindro who helped deploy updated versions of Platform Explorer during the competition + for outlining is always better to stick with Power of 2 ROM sizes for compatibility reasons.

Summary
To summarize, once again the SMS Power! community has been awesome and by members sharing their code this has helped immensely with Platform Explorer doing so well in the 2019 Coding Competition J

Tuesday, January 1, 2019

Retrospective X

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

2018 Achievements
  • Complete ten year blog on agile software application to game development
  • Streamline Sega Master System retro game development using devkitSMS
  • Enter Simpsons Trivia into Sega Master System annual coding competition
  • Port Simpsons Trivia to XNA then to PC, Andriod and iOS using MonoGame
  • Experiment additional platforms using MonoGame e.g. Mac, WP8 and UWP
  • Build 3D City adding MonoGame targets PC, Mac, WP8, Android, iOS, UWP
  • Test VR Unity plugins SteamVR, Oculus and AR Xamarin frameworks ARKit
  • Begin AI and Machine Learning format with TensorFlow on WinPC and Mac
Note: completing ten year blog post on various game development topics is an achievement!

2019 Objectives
  • Investigate sharing code options online: Git Submodules or Mercurial Subrepos
  • Explore Sega dev environment + debugging from Master System to MegaDrive
  • Expand MonoGame cross platform ideas trailing 3D models and custom effects
  • Continue AI and Machine Learning studies cross platform and cross languages

Blog
This blog was created in 2009 after the completion of my first independent game built using XNA: Henway. The goal was to discuss issues found during independent game development and provide potential solutions.

Ten years later and this blog has expanded ideas to modern agile software application in game development and the ability to scale game projects quickly cross multiple platforms while always being mindful of quality.

During this time, XNA has given way to other frameworks and engines but MonoGame has proved to be most successful in terms of applying these ideas to new titles such as Candy Kid, Simpsons Trivia plus 3D City.


History
Conversely, must time has also been spent especially during the past five years programming older systems. Writing low level code to run on real 8-bit hardware like the Sega Master System with limited memory and storage requires performance-critical algorithms to be written to achieve maximum frame rate at all times.


Future
The future in Software Engineering looks exciting as LinkedIn opportunities include Blockchain Developer, Machine Learning Engineer and Machine Learning Specialist as part of the top five emerging jobs in 2018.

Therefore, frameworks like TensorFlow for example, used in machine learning applications available cross multiple platforms in both high + low level languages seem very aligned to approaches used in this blog J

Thursday, November 15, 2018

Simpsons Trivia iOS Port

In the previous post, we introduced Simpsons Trivia: a simple quiz game for the Sega Master System. Here we outlined tasks to port original game to Android using MonoGame. Now we would like to port game to iOS.
Let's check it out!

Pre-Requisites
This post extends Candy Kid iOS port which assumes MonoGame and Apple certificates + profiles installed. Although Visual Studio now integrates iOS templates for development Mac is still required for deployment.

Setup
Download and install Visual Studio 2017. Install "Mobile development with .NET" for Xamarin development.
Launch Visual Studio 2017. Tools | Options | Xamarin. Configure Apple Accounts. Click "Pair to Mac". Click "Add Mac" in popup and enter Mac name or IP address. Enter login details to connect. Verify iOS Settings.
IMPORTANT
Ensure Username entered matches Current User on Mac e.g. "Steven Boland" and matching login password. If unable to connect using Mac name then ensure Xamarin SDK version compatible on Visual Studio for Mac.

Development
IOS Game Client
Visual Studio 2017: Create new project. New Project | Visual C# | MonoGame | MonoGame iOS Project.
 Key  Value
 Name  SimpsonsTrivia.IOS
 Location  C:\SVN\SimpsonsTrivia
 Solution name  SimpsonsTrivia.IOS
Download code sample here.

Checklist
Here is a checklist of tasks to complete in order to port game from Windows to iOS using MonoGame:
  • Configure project administration
  • Generate AppIconSet assets
  • Update Info plist config file
  • Update project references
  • Update nuget packages
  • Configure SVN Externals
  • Import Assets content
  • Update client files

Configure project administration
Sign in to your Apple developer account | Certificates, Identifiers & Profiles. Ensure certificates are valid. Identifiers | App IDs click "+" to create new bundle identifier. Create corresponding Provisioning Profiles.

On the Mac, launch Visual Studio for Mac. Visual Studio Community | Preferences... | Publishing | Apple Developer Accounts. Click "+" to sign in. View Details... and choose "Download All Profiles" in the popup.


Generate AppIconSet assets
Navigate to makeappicon. Upload generic icon image that represents game. Best results use 1536 x 1536 image. After processing, download generated ZIP file and extract. Expand ios folder | AppIcon.appiconset.

On the Mac, launch Visual Studio for Mac. Open SimpsonsTrivia.IOS.sln. Double click Info.plist file. Next to iPhone icons | Sources click "Migrate to Asset Catalog" This auto-generates AppIcon plus Assets.xcassets.

Double click Assets.xcassets to launch AppIcon. Click each icon + open each corresponding icon accordingly:
 Location  Version  Size  Ratio  Dimension  Filename
 iPhone Notification  iOS 7-12  20pt  2x  40 x 40  Icon-App-20x20@2x
 iPhone Notification  iOS 7-12  20pt  3x  60 x 60  Icon-App-20x20@3x
 iPhone Spotlight  iOS 5-12  29pt  2x  58 x 58  Icon-App-29x29@2x
 iPhone Spotlight  iOS 5-12  29pt 3x  87 x 87  Icon-App-29x29@3x
 iPhone Spotlight iOS 7-12 40pt 2x 80 x 80 Icon-App-40x40@2x
 iPhone Spotlight iOS 7-12 40pt 3x 120 x 120 Icon-App-40x40@3x
 iPhone App iOS 7-12 60pt 2x 120 x 120 Icon-App-60x60@2x
 iPhone App iOS 7-12 60pt 3x 180 x 180 Icon-App-60x60@3x
 iPad Notification iOS 7-12 20pt 1x 20 x 20 Icon-App-20x20@1x
 iPad Notification iOS 7-12 40pt 2x 40 x 40 Icon-App-40x40@1x
 iPad Settings iOS 5-12 29pt 1x 29 x 29 Icon-App-29x29@1x
 iPad Settings iOS 5-12 29pt 2x 58 x 58 Icon-App-29x29@2x
 iPad Spotlight iOS 7-12 40pt 1x 40 x 40 Icon-App-40x40@1x
 iPad Spotlight iOS 7-12 40pt 2x 80 x 80 Icon-App-40x40@2x
 iPad App iOS 7-12 76pt 1x 76 x 76 Icon-App-76x76@1x
 iPad App iOS 7-12 76pt 2x 152 x 152 Icon-App-76x76@2x
 iPad Pro App iOS 9-12 83.5pt 2x 167 x 167 Icon-App-83.5x83.5@2x
 App Store iOS 1024pt 1x 1024 x 1024 ItunesArtwork@2x
Finally, import the 3x iTunesArtwork.png files to the project as these will also be used in the Info.plist file.

Update Info plist config file
On the Mac, with SimpsonsTrivia.IOS still open. Double click Info.plist. Manually enter the relevant project information. Scroll down to iTunes Artwork and click placeholders for the iTunes artwork. Import both files:
 CFBundleName  Simpsons Trivia
 CFBundleDisplayName  Simpsons Trivia
 CFBundleIdentifier  com.steveproxna.simpsons
 CFBundleVersion 1.0.0
 CFBundleShortVersionString  1.0
 MinimumOSVersion  7.0
 UISupportedInterfaceOrientations  UIInterfaceOrientationLandscapeLeft
 UIStatusBarHidden  true
 UIRequiresFullScreen  true
 UIDeviceFamily  1, 2
 XSAppIconAssets  Assets.xcassets/AppIcon.appiconset
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>CFBundleName</key>
  <string>Simpsons Trivia</string>
  <key>CFBundleDisplayName</key>
  <string>Simpsons Trivia</string>
  <key>CFBundleIdentifier</key>
  <string>com.steveproxna.simpsons</string>
  <key>CFBundleVersion</key>
  <string>1.0.0</string>
  <key>CFBundleShortVersionString</key>
  <string>1.0</string>
  <key>MinimumOSVersion</key>
  <string>7.0</string>
  <key>UISupportedInterfaceOrientations</key>
  <array>
    <string>UIInterfaceOrientationLandscapeLeft</string>
  </array>
  <key>UIStatusBarHidden</key>
  <true/>
  <key>UIRequiresFullScreen</key>
  <true/>
  <key>UIDeviceFamily</key>
  <array>
    <integer>1</integer>
    <integer>2</integer>
  </array>
  <key>XSAppIconAssets</key>
  <string>Assets.xcassets/AppIcon.appiconset</string>
</dict>
</plist>
NOTE: if the AppIcon magically disappears then it is always possible to edit Info.plist file by hand.

Update project references
Add reference to System.Xml.Linq as required by the game engine for any Serialization of custom XML files.

Update nuget packages
It may be necessary to downgrade to MonoGame.Framework to 3.5.1.1679 in order to load Content from the Content parent folder and play sound effects. Right click References node | Manage NuGet Packages. Search for MonoGame.Framework. Also, install Portable Ninject package as Ninject is required as the IoC Container.

Configure SVN Externals
Follow instructions to setup SVN Externals and use shared Data content plus Common + Master source code.
DATA
 IOS  Folder :  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.IOS\SimpsonsTrivia.IOS
 Action :  Right click "Content" folder
 URL  http://build/svn/SimpsonsTrivia/SimpsonsTrivia.XNA/SimpsonsTrivia.XNA/SimpsonsTrivia.XNAContent/Data

CODE
 IOS  Folder :  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.IOS
 Action :  Right click "SimpsonsTrivia.IOS" folder
 URL  http://build/svn/SimpsonsTrivia/SimpsonsTrivia.XNA/SimpsonsTrivia.XNA.Library/Common
 URL  http://build/svn/SimpsonsTrivia/SimpsonsTrivia.XNA/SimpsonsTrivia.XNA.Library/Master

Import Assets content
Manually import game content and set file properties. Refer to Candy Kid iOS port for more information:
 Folder  Type  XNB  Build Action  Copy to Output Directory
 Data  All  No  Content  Copy if newer
 Fonts  All  Yes  Content  Copy if newer
 Sound  Wav  Yes  Content  Copy if newer
 Sound  Mp3  No  Content  Do not copy
 Textures  All  No  BundleResource  Do not copy

Update client files
Finally, delete default Game1.cs code file. Delete Default.png and GameThumbnail.png images as these not required. Import iTunesArtwork@1x iTunesArtwork@2x iTunesArtwork@3x PNG [above] if not already done.

Refer to Candy Kid iOS port as reference to exit game code sample on iOS and to MediaPlayer workaround. Also, to prevent annoying landscape flipping during game play set display orientation to landscape left only:
//AnGame.cs
graphics = new GraphicsDeviceManager(this) {SupportedOrientations = DisplayOrientation.LandscapeLeft};

Deployment
Despite the fact that you are able to complete all game development on Windows PC using Visual Studio 2017, it may actually be easier to complete the iOS deployment on the Mac using Visual Studio for Mac.

Launch the Terminal, checkout the source code and open SimpsonsTrivia.IOS.sln in Visual Studio for Mac. Right click project | Options | Build | iOS Build. Ensure that all 3x supported architectures are selected:
Connect iOS device. In Visual Studio ensure device selected. Right click project | Archive for Publishing.
Click Sign and Distribute... Here, there are 3x iOS Distribution channels: Ad Hoc, App Store and Enterprise. Choose Ad Hoc to save to disk and test locally while App Store will upload IPA to the store available for sale.

The App Store deployment will prompt you to select signing identity and provisioning profile created earlier. Note: Enterprise is not valid here!


Ad Hoc
If you'd like to deploy test the IPA build to iOS device before uploading to App Store then follow these steps:
Choose Ad hoc [Save to disk]. Choose provisioning profile | Publish | Save IPA file | Reveal in Finder. Launch Xcode | Window | Devices and Simulators. Select connected iOS device. Click "+". Navigate + open IPA file.


App Store
Choose App Store [Save to disk and open Application Loader]. Previously, Application Loader simply required Apple developer account credentials to be entered. Now, Apple requires app specific password to be created:

Sign in Apple ID web site. In Security section under "APP-SPECIFIC PASSWORDS" click "Generate Password". In the popup window enter, for example "SimpsonsTrivia". Apple will generate an app specific password. Use information to sign in to Application Loader. Click "Deliver Your App" | Choose. Navigate to + upload IPA file.


Publication
Complete the App Store deployment to sign IPA binary ready for upload. In iTunes Connect click the "+" to create New App. Enter all relevant details. Create promotional images and upload to App Previews section:
 Device  Policy  Image  Video
 iPhone 6.5" Display  Optional  2688 x 1242  1920 x 886
 iPhone 5.5" Display  Mandatory  2208 x 1242  1920 x 1080
 iPad Pro (3rd Gen) 12.9" Display  Optional  2732 x 2048  1600 x 1200
 iPad Pro (2nd Gen) 12.9" Display  Mandatory  2732 x 2048  1200 x 900
NOTE: resizeimage.net is a great online tool to help resize the same generic image for different resolutions.

VIDEO
Produce a YouTube video to showcase the game. Use My Movie Maker to resize video to dimensions [above]:
Launch My Movie Maker. Open MP4 file. Choose "Save movie" drop down | Create custom setting. Enter the dimensions. For height > 1080px try Online Convert: e.g. Screen size to 1600 x 1200 and fame rate: 30fps.

REVIEW
Once published, if app is "Waiting in Review" for weeks then you have the option to expedite this process. Contact Apple and choose I would like to "request an expedited app review". Enter all information + Send.

Summary
That concludes the Simpsons Trivia port to iOS. These blog posts set the foundation for the next video game!

Saturday, September 15, 2018

Simpsons Trivia Android 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 Windows using MonoGame. Now we would like to port game to Android.
Let's check it out!

Pre-Requisites
This post extends the Candy Kid Android port which assumes MonoGame, JDK + Android SDK are installed.

Setup
Download and install Visual Studio 2017. Install "Mobile development with .NET" for Xamarin development.

Launch Visual Studio 2017. Configure JDK and Android SDK. Tools | Options | Xamarin | Android Settings:
 Type  Location
 Java Development Kit Location  C:\Program Files\Java\jdk1.8.0_172
 Android SDK Location  C:\Program Files (x86)\Android\android-sdk
 Android NDK Location  C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r11c

Development
AND Game Client
Visual Studio 2017: Create new project. New Project | Visual C# | MonoGame | MonoGame Android Project.
 Key  Value
 Name  SimpsonsTrivia.AND
 Location  C:\SVN\SimpsonsTrivia
 Solution name  SimpsonsTrivia.AND
Download code sample here.

Checklist
Here is a checklist of tasks to complete in order to port game from Windows to Android using MonoGame:
  • Configure project properties
  • Build Android Manifest file
  • Update project references
  • Update nuget packages
  • Configure SVN Externals
  • Import Assets content
  • Import Resources
  • Update client files

Configure project properties
As of August 1, 2018 Google Play requires new apps to target at least Android 8.0 (API level 26) to meet the minimum target API level requirement. Right click SimpsonsTrivia.AND project | Properties. Application tab. Ensure "Compile using Android version: (Target Framework)" is set to, at a minimum, Android 8.0 (Oreo).
If Android 8.0 (Oreo) not installed then launch Android Studio. Tools | SDK Manager. Download API level 26. Note the Android SDK location and copy "platforms" folder to C:\Program Files (x86)\Android\android-sdk.

Build Android Manifest file
Right click SimpsonsTrivia.AND project | Properties. Android Manifest tab. Click "No AndroidManifest.xml"
 Key  Value  Element  Attribute
 Application name  Simpsons Trivia  application  android:label
 Package name  com.steveproxna.simpsons  manifest  package
 Application icon  @drawable/Icon  application  android:icon
 Version number  1  manifest  android:versionCode
 Version name  1.0.0  manifest  android:versionName
 Minimum Android version  Android 8.0 (API Level 26 - Oreo)  uses-sdk  android:minSdkVersion
 Target Android version  Android 8.0 (API Level 26 - Oreo)  uses-sdk  android:targetSdkVersion
IMPORTANT
If there is an integer in the bundle identifier then Google will prepend an "x" e.g. 3dcity becomes "x3dcity"

Update project references
Changes to Android version (Target Framework) on the Application tab [above] will update Mono.Android.dll reference. Note, it may be necessary to change OpenTK-1.0 reference to OpenTK for compatibility reasons.

Update nuget packages
It may also be necessary to downgrade MonoGame.Framework to 3.4.0.459 in order to load Content from the Assets parent folder and play sound effects. Right click References node and Manage NuGet Packages. Change MonoGame version. Install Portable Ninject package too as Ninject is required as an IoC Container.

Configure SVN Externals
Follow instructions to setup SVN Externals and use shared Data content plus Common + Master source code:
DATA
 AND  Folder :  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.AND\SimpsonsTrivia.AND\Assets
 Action :  Right click "Content" folder
 URL  http://build/svn/SimpsonsTrivia/SimpsonsTrivia.XNA/SimpsonsTrivia.XNA/SimpsonsTrivia.XNAContent/Data

CODE
 AND  Folder :  C:\SVN\SimpsonsTrivia\SimpsonsTrivia.AND
 Action :  Right click "SimpsonsTrivia.AND" folder
 URL  http://build/svn/SimpsonsTrivia/SimpsonsTrivia.XNA/SimpsonsTrivia.XNA.Library/Common
 URL  http://build/svn/SimpsonsTrivia/SimpsonsTrivia.XNA/SimpsonsTrivia.XNA.Library/Master

Import Assets content
Manually import game content and set file properties. Refer to Candy Kid Android port for more information:
 Folder  Type  XNB  Build Action  Copy to Output Directory
 Data  All  No  AndroidAsset  Do not copy
 Fonts  All  Yes  AndroidAsset  Do not copy
 Sound  All  No  AndroidAsset  Do not copy
 Textures  All  No  AndroidAsset  Do not copy

Import Resources
Replace default Icon and Splash images located in Resources / Drawable folder with custom images:
 Icon.png 72x72
 Splash.png 800x480

Navigate to makeappicon. Upload generic icon image that represents game. Best results use 1536 x 1536 image. After processing, create the following sub folders beneath the Resources parent folder and import:
 Folder  Dimension    Folder  Dimension
 mipmap-hdpi  72 x 72    mipmap-xhdpi  96 x 96
 mipmap-ldpi  36 x 36    mipmap-xxhdpi  144 x 144
 mipmap-mdpi  48 x 48    mipmap-xxxhdpi  192 x 192

Delete default Strings.xml file as not needed here. Update the default Styles.xml file for fullscreen splash:
<?xml version="1.0" encoding="utf-8"?>
<resources>
 <style name="Theme.Splash" parent="@android:style/Theme.NoTitleBar.Fullscreen">
  <item name="android:windowBackground">@drawable/splash</item>
  <item name="android:windowFullscreen">true</item>
  <item name="android:windowNoTitle">true</item>
  <item name="android:windowIsFloating">false</item>
 </style>
</resources>

Update client files
Finally, delete default Game1.cs code file. Rename Activity1.cs to SplashActivity.cs + add the following code:
[Android.App.Activity(Label = "Simpsons Trivia"
  , MainLauncher = true, NoHistory = true, Icon = "@drawable/icon"
  , Theme = "@style/Theme.Splash", AlwaysRetainTaskState = true
  , ScreenOrientation = Android.Content.PM.ScreenOrientation.SensorLandscape)]
public class SplashActivity : Android.App.Activity
{
  protected override void OnCreate(Android.OS.Bundle bundle)
  {
    base.OnCreate(bundle);
    StartActivity(typeof(GameActivity));
  }
}

Next, add GameActivity.cs. Add the following code to take advantage of the new fullscreen Immersive mode:
using Android.Content.PM;
using Android.Views;
[Android.App.Activity(Label = "Simpsons Trivia"
  , NoHistory = true, Icon = "@drawable/icon"
  , Theme = "@style/Theme.Splash", AlwaysRetainTaskState = true
  , LaunchMode = Android.Content.PM.LaunchMode.SingleInstance
  , ScreenOrientation = ScreenOrientation.SensorLandscape
  , ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.ScreenSize)]
public class GameActivity : Microsoft.Xna.Framework.AndroidGameActivity
{
  protected override void OnCreate(Android.OS.Bundle bundle)
  {
    base.OnCreate(bundle);
    var g = new WindowsGame.Common.AnGame();
    Android.Views.View view = (Android.Views.View)g.Services.GetService(typeof(Android.Views.View));
    if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Kitkat)
    {
      view.SystemUiVisibility = (Android.Views.StatusBarVisibility)(
        SystemUiFlags.LayoutStable | SystemUiFlags.LayoutHideNavigation |
        SystemUiFlags.LayoutFullscreen | SystemUiFlags.HideNavigation |
        SystemUiFlags.Fullscreen | SystemUiFlags.ImmersiveSticky);
    }
    SetContentView(view);
    g.Run();
  }
}

Also, to prevent annoying landscape flipping during game play set display orientation to landscape left only:
//AnGame.cs
graphics = new GraphicsDeviceManager(this) {SupportedOrientations = DisplayOrientation.LandscapeLeft};

Update AndroidManifest.xml. Add "android.max_aspect" at 2:1 value to ensure immersive mode accordingly:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
 package="com.steveproxna.simpsons" 
 android:versionCode="1" 
 android:versionName="1.0.0" 
 android:installLocation="auto">
 <uses-sdk android:minSdkVersion="26" android:targetSdkVersion="26" />
 <application android:label="Simpsons Trivia" android:icon="@drawable/Icon">
  <meta-data android:name="android.max_aspect" android:value="2.1" />
 </application>
</manifest>

IMPORTANT
If 2x app icons appear on device then ensure there is one instance of MainLauncher=true only in an Activity!

Deployment
Despite the fact that you are able to complete all game development on Windows PC using Visual Studio 2017, it may actually be easier to complete Android deployment on the Mac using Visual Studio for Mac.

Launch the Terminal, checkout the source code and open SimpsonsTrivia.AND.sln in Visual Studio for Mac. Right click project | Options | Build | Android Build | Advanced. Ensure 3x Supported ABIs are checked:
Connect Android device. Launch Terminal and enter adb devices to ensure Android device is detected in the list of devices attached. In Visual Studio ensure device selected. Right click project | Archive for Publishing.
Click Sign and Distribute... There are 2x Android Distribution channels: Ad Hoc and Google Play. Choose Ad Hoc to save to disk and test locally while Google Play will upload to the Google Play store available for sale.

During Google Play deployment you may be prompted to create a new project in the "API access" tab linked to your Google Play Developer account in which you must create an OAuth client and enter the ID + Secret:
Sign in to your Google Developer account. Navigate to play.google.com/apps/publish | Settings | API access. Create OAuth client. View in Google Developers Console. Download JSON and extract the Client ID + Secret.

Publication
Complete the Google Play deployment to sign APK binary ready for upload. In Google Play Developer console Create Application. Enter all relevant details. Create promotional images and upload to Store listing section:
 Type  Dimensions  Description
 Hi-res icon  512 x 512  32-bit PNG (with alpha)
 Feature Graphic  1024 x 500  JPG or 24-bit PNG (no alpha)
 Promo Graphic  180 x 120  JPG or 24-bit PNG (no alpha)
 TV Banner  1280 x 720  JPG or 24-bit PNG (no alpha)
 Daydream 360 degree stereoscopic image  4096 x 4096  JPG or 24-bit PNG (no alpha)
NOTE: resizeimage.net is a great online tool to help resize the same generic image for different resolutions.

VIDEO
Produce a YouTube video to showcase the game: Launch Camtasia Studio. Disconnect webcam if connected. Choose Record screen. In popup | click Audio button. You should see the following message about No audio: No audio input sources were found, pls verify that your audio devices are installed and plugged in correctly.

Plug black cable from microphone into headphone jack. Shouldn't need to unplug speaker cable from audio jack. Click Audio drop down | Click Microphone Real Tech [visible] to enable. Now record screen as before.

COPPA
Ensure the game is COPPA compliant by completing the "Primarily Child-Detected" section under the Store Presence | Pricing & Distribution section otherwise the game could be unpublished from Google Play store.
Finally, upload signed APK binary from deployment completion to Google Play and rollout Production release!

Summary
That concludes the Simpsons Trivia port to Android. The next post will focus on Simpsons Trivia port to iOS.

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. [In fact, currently you may be prompted to install GFWL for Windows 10 compatibility.] 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
Download code sample here.

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.MAC/SimpsonsTrivia.MAC/Content
svn propset svn:externals 'Data http://build/svn/SimpsonsTrivia/SimpsonsTrivia.WIN/SimpsonsTrivia.WIN/Content/Data' .

cd ~/SVN/SimpsonsTrivia/SimpsonsTrivia.MAC/SimpsonsTrivia.MAC
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.MAC/SimpsonsTrivia.MAC
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: Follow instructions here but refer to 8.1 parent folder in C:\Program Files (x86)\Microsoft XDE\8.1\xde.exe. Start | run | Hyper V Manager lists WP8 emulators available to connect ignoring the Virtual Switch Manager.

Right click C:\ Program Files (x86)\Microsoft SDKs\Windows Phone\v8.1\Emulation\Images and disable file compression. Right click %USERPROFILE%\AppData\Local\Microsoft\XDE and disable file compression also.


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!