Sunday, September 15, 2019

Linux Setup Cheat Sheet

Linux is everywhere! Linux is free open source operating system based on Unix OS. Linux powers 90% of the world's fastest servers thus is the backbone of the Internet. Linux dominates mobile platforms and the cloud. Let's check it out!

Windows
Install Ubuntu Linux on Windows using VirtualBox. Download VirtualBox and install. Follow all the prompts. Next, follow all instructions here to create the virtual machine to host Ubuntu. I have tweaked some inputs:
 Step  Key  Value
 VM Name and OS Type  Version  Ubuntu (64-bit)
 Memory  Base Memory Size  8 GB
 Virtual Hard Disk  Start up Disk  Create new hard disk
 Create New Virtual Disk  File type  VDI (VirtualBox Disk Image)
 Virtual disk storage details  Storage details  Fixed size
 Virtual disk file location and size  Size  100 GB

Complete virtual hard drive: click Create. Download Ubuntu 19.04. In VirtualBox, click Settings | Storage | Controller IDE | Empty | Optical Drive: IDE Secondary Master. Click icon | Choose Virtual Optical Disk File...

Navigate to downloaded Ubuntu ISO file | OK. In VirtualBox, double click Ubuntu [Powered Off] to Start the virtual machine. Next, follow all instructions here for the Ubuntu installation. I have tweaked some inputs:
 Step  Key  Value
 Welcome  Option  Install Ubuntu
 Keyboard layout*  English  English (US)
 Updates and other software  What apps would you like to install  Normal installation
 Installation type  Computer has no detected OS  Erase disk and install Ubuntu
 Where are you?  City  Leave default selection
* IMPORTANT do not change keyboard layout here as can corrupt buttons! You can always change it later.

The final install step "Who are you?"
 Key  Value
 Your name  Steven Boland
 Your computer's name  stevepro-VirtualBox
 Pick a username  stevepro
 Choose a password  password
 Confirm your password  password

Troubleshooting
VT-x is not available (VERR_VMX_NO_VMX) After Windows 10 Update
You may receive this error on Windows 10 especially after a Windows Update. If so then try the following;
  • Launch the Terminal command prompt Run as Administrator
  • Start | Programs | right click Command Prompt | Run as administrator
  • Type the following command: dism.exe /Online /Disable-Feature:Microsoft-Hyper-V
Restart computer when prompted. Note: Windows may perform additional updates one or two more times.


Hyper-V Manager
If you are still experiencing issues running Ubuntu Linux on Windows using VirtualBox because of the Microsoft hypervisor then try host Ubuntu using the Hyper-V Manager. Start | run | Hyper-V Manager.

Next, follow all instructions here to create a Linux virtual machine on Windows 10 using Hyper-V. Verify Hyper-V is supported with systeminfo.exe command and that Hyper-V is enabled via Windows features.

In Hyper-V Manager choose Action menu | Virtual Switch Manager | New virtual network switch | External. Create Virtual Switch e.g. "MyVirtualSwitch". Choose network adapter as External Network | Apply | OK.

Create virtual machine: Action menu | New | Virtual Machine | Ubuntu. Use default location. Use default Generation 1. Choose "MyVirtualSwitch" | Finish. Follow steps as above to complete Ubuntu installation.


Windows Subsystem for Linux
Windows Subsystem for Linux [WSL] is an optional feature in Windows that provides a kernel compatibility layer based on Ubuntu. This layer allows Linux programs to run on a Windows 10 version of the Bash shell.

Determine if your Windows 10 64-bit version supports WSL: Settings | System | About. Version >= 1607. Follow YouTube instructions: Enable Developer Mode via Settings | Update & Security then For developers.

Enable Windows Subsystem for Linux: Control Panel | Programs and Features | Turn Windows features on. Finally, launch Microsoft store. Search for Ubuntu. Install and Launch. Set username and password to begin. From cmd prompt type bash to shell out. Windows files are mapped from /mnt directory thus C:\ => /mnt/c


Mac OS/X
Install Ubuntu Linux on Mac OS/X using VirtualBox. Download VirtualBox and install. Follow all the prompts. Next, follow all instructions here to create the virtual machine to host Ubuntu. Repeat install like Windows!


Setup
This section assumes Ubuntu Linux is installed irrespective of the platform. Now, let's do some basic setup: Login and verify an Internet connection: Settings (top right hand side) | System Settings | Network | Wired.

Resolution
Typically, the initial display will not max out monitor resolution so let's fix that: Show Applications (bottom right) | Settings | Display. Choose resolution that makes sense for monitor size. Use Landscape orientation. In VirtualBox, View menu. Choose Scaled Mode. Drag screen borders to maximize remaining monitor space.

Guest Additions
In order to copy + paste between the host and virtual machine enable Guest Editions. In VirtualBox Devices menu | Insert Guest Additions CD image. Follow all prompts and choose "Y" accordingly. Restart Ubuntu VM.

After installation, choose Ubuntu virtual machine | Settings | General | Advanced. Ensure that both "Shared Clipboard" and "Drag n' Drop" are set to Bidirectional. If this doesn't work then launch Terminal commands:
sudo apt-get update
sudo apt-get install virtualbox-guest-x11

Keyboard
Settings | Region & Language. Choose Language English (US) and Format for keyboard layout that you like. Also, you may switch the Command and Control key if you are on a Mac for consistency. Launch Terminal:
cd /usr/share/X11/xkb/symbols
sudo cp pc pc_bak
sudo gedit pc
key  {    [ Super_L       ]   };
key  {    [ Control_L     ]   };
key  {    [ Super_R       ]   };
key  {    [ Control_R     ]   };
sudo rm -rf /var/lib/xkb/*

Shortcuts
Following Keyboard, update Terminal keyboard shortcuts for copy and paste consistency. Launch Terminal menu | Preferences | Shortcuts | Edit. Choose Copy and press Ctrl+C and choose Paste and press Ctrl+V. Also, handy Files Manager shortcuts: Ctrl+D to create [bookmark] link to folder and Ctrl+L to show path.

Applications
Remove any unwanted applications from Favorites. Add any new applications to Favorites accordingly. E.g.: Show Applications | Search "Terminal". Double Terminal to launch. Right click Terminal | Add to Favorites.

Folder Share
In order to share files between the host and virtual machine enable folder share: Show Applications | Files | Other Locations. Connect to Server "smb://host-pc" | Connect. Enter Windows Username and Password and WORKGROUP for Domain. Otherwise, choose Domain as the Local Area Network [LAN] domain accordingly.

Screen Lock
Finally, you may like to disable screen lock for long periods of time. Settings | Privacy | Screen Lock | Off.

IMPORTANT
If, for any reason, changes made don't replicate then it may be necessary to simply restart virtual machine.


Summary
Now that Ubuntu Linux is installed on computer whichever configuration chosen it is time to install software! This will be the topic in the next post.

Saturday, August 31, 2019

3D City Code Complete II

3D City is a simple "Shoot 'em up" video game originally programmed by StevePro Studios in New Zealand January 1988. The game was written using BASIC programming language built against the Sega SC-3000.

In 2016, 3D City was re-written in C / Z80 assembler to target the Sega Master System. In 2018, 3D City was re-written in XNA to celebrate its 30yr anniversary and was ported to Windows [UWP], Android and iOS.

Click here for more information on the classic 8-bit retro version for 3D City on the Sega Master System.
Let's check it out!

IMPORTANT
Simpsons Trivia techniques were used to port 3D City XNA to Windows, Android and iOS using MonoGame.

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  Download
 UWP  Windows Universal Project  Visual Studio 2017  MonoGame 3.6  Game client  Download

Publishing
Choose a unique game title, short description and bullet points to be applied consistently across stores.
 Title  Retro 3D City
 Short description  Retro style 80s rails based shooter arcade video game
 Keywords  80s, retro, arcade, video, game
Do you love to blast away innocent fighter ships in an infinite pixelated universe?
If so then this 80s retro style rails based shooter arcade video game is for you!

Use your skill to defeat the relentless attack of the rebel star fighters throughout 18x levels of hyperactive destruction! Two main modes: Easy vs. Hard plus unlimited continues to navigate the continual, high-paced frantic and exhaustive action.


Cheats
  • Press "1988" text bottom right on Splash screen to play secret speed metal music
  • Press the large "3D City" yellow title on the intro screen five times for invincibility
  • Press the small white "-- 3D City --" text in the top middle to go back, quit or exit

Summary
3D City has come along way in 30yrs: from humble beginnings written in BASIC for the Sega SC-3000, to C / Z80 for the Sega Master System and finally re-written again for modern day desktop and mobile platforms.

If you love to blast away innocent fighter ships then grab yourself a free copy on Windows, Android or iOS!

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, much 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.