Friday, June 24, 2016

Copa America Centenario: Or the embarassment of the US Men's National Team

I am fan of football aka "soccer", I am also an American. This is my little rant on the subject following the United States National team defeat at the hands of Argentina on June 21st, 2016 during the 2016 Copa America tournament held in the U.S.

$ start stream of consciousness

So the U.S. is now out of the tournament after last night's game. It felt worse than a loss because they played far below their potential. I don't really blame the coach for this one, although some US soccer commentators do.

Prior to the tournament, the goal Jurgen Klinsmann had was to reach the Semi-finals, which they did. Along the way, they had to get out of a pretty decent group (by CONCACAF standards), and they won an elimination game in the tournament. So in some sense, they did achieve that, but to put it in perspective, the narrative, has always been that "soccer is growing in this country", the team used to be amateurs and college players, now we also have professionals with our own domestic soccer league that is growing in skill-level and popularity. That has been the case since 1994 supposedly (or 1972 if you believe the Men in Blazers).
The semi-final in Copa America, really isn't that deep when compared to FIFA World Cups, where you have: Group stage, Round of 16, then Quarterfinals, Semi-finals and the Final championship.
  • So we made the World Cup quarterfinals in 2002
  • We went just as deep in the 1995 Copa America, making the semi-finals that year, losing to then world champion's, Brazil, 1-0 (we also managed to beat Argentina that year 3-0, I literally have no conscious memory of any of this).
This year we got as far as we did with the following record:
  • Loss to Colombia 2-0.
  • Wins against Costa Rica, Paraguay and Ecuador
  • Then being blown out, in front of home crowd by Argentina 4-0.
Prior to this tournament, compared to last World Cup even, I wouldn't say the teams we beat were upsets by the US, although Ecuador and Costa Rica were higher in FIFA rankings, we absolutely should have won those games. Compare that to Mexico, our main CONCACAF rival, that had Chile in the Quarterfinals and look what happened to them.
So anyway, that is my perspective, I guess the disappointment is higher since it seemed like there had been some incremental progress leading up to this game. But historically I think we are just getting lucky here or there and still staying a fairly mediocre national team. It doesn't seem like as a nation we have taken the game as seriously as other countries, we have not gotten better in 20 years after the sport supposedly "broke through" and we got our domestic league off the ground. It can be even argued, that our best players are squandering opportunities to play in more competitive European leagues, than for lucrative MLS contracts in the ol' US of A.

About the game itself. 

Argentina played well overall. Messi had an amazing goal. They just had more talent, it is obvious. But the US played absolutely terrible soccer. Some people say Klinsmann lineup was too conservative with all the players suspended (Wood, Bedoya, Jones). But I can't really blame him, for putting some more veteran and defensive players in, it's not like you would expect us to try to outgun Argentina with our offense. That said, the players themselves did them no service, so it looked worse than the decision was.

First goal at the start of the game, total defensive mistake, questionable goalkeeping. Totally changed the pace of the game, as Argentina could sit back and US had to force to try to get the ball at all.
On the Offense:
  • I like Clint Dempsey, and he was having a good tournament, until last night. I am not sure how much is to blame for him. Mostly no one was able to complete a pass through midfield, so that's not really his fault. He is not a super fast striker, so he doesn't threaten so much, reminds me of World Cup vs Belgium.
  • Gyasi Zardes , is supposed to be a young, fast talent. Yet, throughout the entire tournament, whenever he got the ball at his feet, it seemed to magically bounce off and land in front of an opponent. The guy has no ball handling/dribbling skills. His goal was tapping in to a wide open net. He missed tons of other chances, and I did not seem him even shoot the ball impressively once in all the games I saw. His passing was poor too.
  • Kyle Beckerman, the supposedly strong, defensive midfielder, he seemed lost against Argentina defensively. But worse, whenever he had the ball, he would either a) Pass backwards b) opt for a long ball pass with no accuracy and little or no success all night. I hated watching him last world cup too (he stinks), he always passes backwards.
  • Michael Bradley, sweet, sweet, Michael Bradley, dear God. He is supposed to be really smart, tactical "European-experienced" player, the hope for this team. But he doesn't do that, he was terrible last night, and had plenty of missed passes. There were jokes about him completing more passes to the Argentinian team. This is not about being pressured, or Argentina being SOO much better, he just flat out made dumb decisions and poorly executed passes. Also guilty of the pass backwards phenomena. One of Bradley's bad passes led directly to the ball going to Messi who passed it to wide open Higuain for the 4th goal. In retrospect, it might be more apparent how much Bradley was benefited by having Jermaine Jones by his side for most of the early games, since despite his own flaws, has at least some composure with the ball under pressure.
Towards the end of the game, the US was desperate so they started to push more people forward, and pressuring the Argentinians in their own half of the field. The danger with this was that if the pressure failed, and the Argentinians could make a pass up to one of their forwards (Messi, Higuain, etc..), then we would be in trouble. The irony was, that I watched many times in that game, where we pressed rather well, and eventually the the Argentine defense would try a long ball forward, rather than playing keepaway, and a bunch of those times the US got the ball back at midfield! That is how it is supposed to work. The problem is that the US team once having the ball. Passed to no one, or kicked the ball to the goalie, or passed backwards to their defense, who getting a little pressure, passed back to their own goalie, who just kicked the ball upfield, giving it right back to Argentina. If you are going to kick the ball away anyways...why not at least try kicking it from closer to where your forwards are? (This isn't only a US thing, many teams, including pro club teams in Europe, do the pass backwards thing, it almost never works from what I've seen, on the theory that having possession is more important than having chances to score).

The US got 0 shots on goal. their top 6 forward players all play for MLS, coincidence?

The most entertainment I got that evening was watching the post-game livestream on Vice Sports by the Men in Blazers, as they downed glasses of scotch and complained bitterly. Best line of the night is captured in this tweet quoting Rog:

Monday, June 15, 2015

Viewing Atlas V Launch at Cape Canaveral

Rocket launch up close
Courtesy of www.nasa.gov. Launch of MMS on the Atlas V
A little late is better than never...
This past March, I had the opportunity while visiting Florida to go to Cape Canaveral and watch a launch of a NASA satellite for The Magnetospheric Multiscale Mission (MMS). This is actually a set of four satellites, launched together, which will fly in formation and take measurements of the Earth's magnetosphere. Yeah, I never heard of it either until I found out about the launch. The MMS was launched on a United Launch Alliance Atlas-V 400-series rocket.


Logistics

I had a trip planned to the central Florida area this March, and since I have been several times before to the area, but never during a real launch I was excited to find out that there was indeed a scheduled launch during my trip. I initially just used the Kennedy Space Center (the tourist site company) website, which lists upcoming scheduled launches, and found the post for an Atlas V launch
When: March 12, 10:44 pm

Where: SLC-41, Cape Canaveral Air Force Station
Kennedy Space Center
Rocket Launch: Atlas V | Magnetospheric Multiscale (MMS)

At some point I've subscribed to a Kennedy Space Center "Launch Alert" mailing list, although this particular launch wasn't one that I got an email for. This was probably due to the scheduled time, at 10:44 pm, the official Kennedy Space Center visitor center is closed. I called the day before to the KSC's main number and left a voice message asking if they still had any sort of ticket available to view the launches at night, they did not respond.

After reading a number of other sites with viewing advice for launches, we decided to wing it by going to Cape Canaveral and looking for one of the public viewing areas outside the actual NASA / U.S. Air Force base in the town of Port Canaveral or some of the other nearby state parks. According to launchphotography.com
For off-hours/night launches, when no tickets are being sold by the Visitor Complex and Playalinda Beach is closed,
the best option for Atlas 5 launches is Port Canaveral on Route 401, at 11.7 miles from the pad. In that case it is the furthest viewing of any rocket.
Armed with this minimal information we headed off to view the launch!


Night of the Launch

After double-checking the weather reports, the launch appeared to be on schedule. We drove the hour or so to Cape Canaveral in the early evening, the sun was still up and went to get dinner. I think we ate here, which was unremarkable, except for the fact that nearly everyone in there were "space launch groupies" all going to the same launch afterwards. At the table next to us was a couple who apparently had connections to access the base. They were kind enough to suggest we take a look at spaceflightnow.com as the best place to get real-time info on the upcomming launches. After eating our dinner, we drove over to try to get a spot along Rt. 401 which faces the launch pad for Atlas Vs to the North, across an open body of water called the Banana River.
Map of Rt. 401 where we watched the launch
As you may see in from this map image, there is a curve of Rt 401 which goes behind the Port Canaveral cruise terminal. There really isn't an official beach or parking area, people just parked on the north side of the road on some grass next to the water. By the time we got there it was around 8:45 PM and the enter stretch of the road from the entrance to the Air Force base to the East of this map, all the way to the road cornering to the south was taken. Our car was one of the last cars to fit in to a spot before there is a guard rail that prevents any roadside parking on that side, just around that bend. There are "No Parking" signs across the street and there is an active police presence who we saw forced some people who parked on that side to leave. Moral of this story is try to get there early, 2 hrs or more.

After we parked we had two hours to wait. A lot of people were setting up large cameras with zoom lenses on tripods. Since the only people there are the people who drove and were able to park in that area, it wasn't particularly crowded at all, but you had neighbors to your right and left at all times. We sat on the grass in a spot with a good direct view at the rocket on the pad, preparing for launch. From our smart phones, we caught the NASA TV live stream which was mostly just a video of the rocket from close up. Occasionally there would be a feed of some talk of the mission controllers asking for a status check on some system. Things like this were often heard during the hours before the countdown: "The Centaur liquid oxygen pad storage area has been prepped. The next step is conditioning the transfer lines, which is now beginning to prepare the plumbing for flowing the cryogenic oxidizer."

The worst part of this experience was the wait. Right offshore in the shallow water, parallel to the road were some high power lines, which made an incredible loud electrical buzzing the entire time. There were also police patrol cars going up and down the rows of cars along the street, with their lights flashing. The two combined in the most awful synergy to probably qualify as a form of torture in most of the developed world. We spent the next hour listening to updates on my phone, while taking looks at the rocket and the Vehicle Assembly Building which was also nicely lit, and perfectly visible using my binoculars.

Pictures of the Rocket

Here were some pictures we managed to take. It was dark, and my camera isn't meant for this. My camera is a Sony Cybershot with 20x optical zoom. These were all taken during the fueling stage.
Landscape of the Cape Canaveral base. The Atlas V launch is at center. The VAB is on the left and well lit.

The clearest shot with full zoom

Another zoomed shot of the Atlas V on the launch pad



The Launch

After 2 hours of waiting (and nearly a half day of driving and waiting overall) we finally began hearing the dramatic count down. As I was informed halfway through their count down by a "neighbor" the stream from my smart phone was on about a 20 second delay. So around "T-20" we started seeing the bright orange flames and smoke around the base of the rocket as it silently began to lift off. It was nearly overhead before we heard the loud rumble of the rocket pass by us. I spent most of the launch trying to see something with my binoculars, at first the flame was too bright and I didn't see much. I barely saw it as the first stage separated I think. My mom did the honors and held my digital camera as we filmed a movie.


Aftermath

I can't say I was a big enthusiast for Magnetospheric science, but I have been keeping an eye on the MMS mission since launch. The four satellites in the rocket that were launched together all separated and are flying in a formation in orbit around Earth. They are continuing to take measurements and function as of today. I look forward to seeing what science they are able to do from this mission.

Sunday, December 14, 2014

Adventures in 32X Homebrew - Part 3: 2D Graphics

Previous: Part 2: 32X Hello World

Drawing Stuff

Now that I had the ability to compile a program, run it and get it to display something, the next step to making my masterpiece game would be to get the thing to display some graphics.

Here is one of the first "working" attempts I made at creating a 2D sprite and animating a few frames of action with 32X.

While this sort of worked, there were problems with my implementation that were visibly apparent. As there is no standard library for graphics when working with 32X you pretty much need to implement your own.

Principles

To keep in mind the objective, in order to draw something to the screen on any system you will need to the following tasks.
  1. Convert source images to a format and size that can be processed by tools for 32X, including the right resolution and color depth that our hardware supports.
  2. Provide a mechanism to represent the image data in our ROM which we can reference from our code.
  3. In the game code be able to load the graphic image data to RAM.
  4. At the appropriate times in the game logic draw the image from memory to specified coordinates in the frame buffer.
  5. When finished rendering everything in the frame, flip the frame buffers.
Recall the 32X Video specs:
Video Memory: 256Kb (two 128 Kb framebuffers)
Screen Resolution: 320x224 or 320x240 (PAL)
Color depth: Up to 15 bits, 32768 unique colors, two-bytes per pixel, can use paletted color (Packed Pixel, 8BPP) mode, using up to 256 on-screen colors with one byte per pixel to save memory.

If you use the Packed Pixel mode, you will save on memory (RAM) to store your image files or your the read only memory in your ROM. I started with this approach thinking I might run out of memory on the 32X with all the 2d sprite graphics I wanted to display for my game. In my case I wanted to try to make a "16-bit plus" kind of game, so a ton of colors wasn't really necessary.

Most of this information I have taken from the excellent reference in Devster's Guide to the 32X.

Drawing Blocks

I thought the best way to start giving examples how to draw things on the screen for 32X was to not involve the whole image formatting/importing processing that would need to be done to load an image into your ROM during build time, and to reference the image data, load into memory and draw it out in your game code. Instead will begin with drawing colored blocks of pixels to the screen procedurally, instead of going loading an image. In this example we'll look at setting an RGB color in the color palette memory and drawing rectangles to the 32X framebuffer to create the images on the display.
Starting with the hello world tutorial code from the previous post, I am going to invoke some new methods that we didn't use before.

Global Variables and Constants

Just to note for further sections, the following global variables were added in the main.c

#define BLOCK_COLOR_1 32
#define BLOCK_COLOR_2 34


int r1 = 6;
int g1 = 0;
int b1 = 0;


These were used to set the color for the blocks when they are drawn.

Setting up the Color Palette

In this demo, like HelloWorld, we continue to use the 256 color, packed pixel mode, as a reminder this mode is set in the main.c before the main game loop using function Hw32xInit(MARS_VDP_MODE_256, 0);. The palette is a memory buffer called the CRAM, it holds up to 256 colors, each color being a 16 bit word of memory that can be any of the supported 32768 colors. The color in memory is stored in RGB format with the following bits:
15             0
PBBBBBGGGGGRRRRR

Bits 0-4: Red Value
Bits 5-9: Green Value
Bits 10-14: Blue Value
Bit 15: Represents a flag for "priority" of whether to draw 32X in front of Genesis VDP or behind.

For each of the Red, Green, Blue values you have 5 bits, which allows you to specify a numeric value for each color from 0-31, where 0 is basically black and 31 would be the "full" color (this is how you get 32768 colors, 32 red x 32 green x 32 blue = 32768 total possible color combinations).

To set a value in the CRAM, you need to write this data to that memory location, offset by the index of the color, you then refer to that index when drawing pixels of that color to the main framebuffer used to display. The CRAM can be referenced directly using MARS_CRAM define from 32x.h. It is the memory location: 0x20004200. However, there are utility functions which you may use in hw_32x.h,
extern void Hw32xSetFGColor(int s, int r, int g, int b);
extern void Hw32xSetBGColor(int s, int r, int g, int b);


To set a color "white" in the CRAM, at index 1 for example you may do the following:
//set block color in CRAM
Hw32xSetFGColor(1,31,31,31);

To set additional colors at other indices:
Hw32xSetFGColor(BLOCK_COLOR_1,r1,g1,b1);
Hw32xSetFGColor(BLOCK_COLOR_2,31-r1,31-g1,31-b1);

In this case, I use the global int variables I defined above, and the defines as constants to keep track of which index is being used for which color in the CRAM. In my demo I will vary the values of these ints from 0-31 to get various different combinations of colors which I will use when drawing the blocks.

While you can certainly set up all the values you want to use in your color palette up front, before your main game loop, you can also change them dynamically on the fly, for a "palette" swap effect without having to have a different image in memory.

Setting up Line Table in 32X Framebuffer

Now that we have the colors we want to draw in the CRAM. We need to write to the framebuffer what colors we want to draw at what pixels. There are two DRAM framebuffers in the 32x hardware, and so the general flow of your program is to write to one of the framebuffers, set a flag to "flip" the framebuffers, this causes the 32X hardware to write one of the framebuffers to the display while allowing you to know write to the other framebuffer again, and so on.

The drawing works by writing to memory locations in the framebuffer, in 256 color mode, for each pixel you have to write one byte for the index of the color in the CRAM. For the Direct Color mode (15 BPP) you need to write two bytes to draw a pixel. The location where that pixel is drawn depends on what location in the framebuffer memory location you write to. Determining which memory address is what on-screen pixel is sometimes complicated. First thing to understand is something called the Line Table which informs the 32X VDP where in the framebuffer each line of pixels should start, and for each line the VDP will display the next 320 pixels starting from the line address. The Line table itself is just the first 256 words of the framebuffer, so the first line of the display is generally after that 256th line table address. Here is a diagram of the relationship between line table and framebuffer lines, if you think about X, Y coordinates each line refers to an X on the screen, while the 320 bytes after the line address are the Y coordinates for pixels.
The line table doesn't say what addresses you need to point to, so the above example uses no offset, each line is right after the previous one in contiguous memory. In my own development, I came across a number of issues where objects being written to either the start or end of the line might go past line ending and then wrap around the the start of the next line. In some cases this made it difficult to fix without a lot of expensive checking. What I ended up doing was putting an offset of 4 words before and after every line, and updating the Line table accordingly.

This padding enabled my drawing code to be more efficient and allow some pixels to be written into the padding without corrupting the next line. All of my drawing functions in my sample currently depend on this four word offset. To set up the Line Table, in my main.c at the end of every loop I call
        //draw the 32X framebuffer line table with offset of 4
        drawLineTable(4);


This function is defined in 32x_images.c.

Drawing Rectangle to the Framebuffer

With all that work so far, now comes the "easy" part, drawing the darn thing. Objective here is to write out pixel data to the line address in memory, and to place the pixels at the write point in the line so it shows up in the correct place on the screen. In my code, I do all the heavy lifting for this inside the 32x_images.c's
void drawFillRect(const int16 x, const int16 y, const int xWidth,  const int yWidth, vu8* color)
void drawRect(const int16 x, const int16 y, const int xWidth,  const int yWidth, vu8* color)

These functions will draw a rectangle to the x, y pixel coordinates in the display, with a certain height and width in pixels, using a pointer to a color array. Wait, why is the color parameter a pointer to an array? Well this is basically a performance optimization that was suggested by the SpritesMind forum folks. Basically the fastest possible memory operation are when you write 8 bytes in one shot, so when filling or drawing a rectangle we are going to copy 8 bytes of a single color value from the palette to the framebuffer. To set up the color array I did this before the game loop.
vu8 blockColor[8] = {BLOCK_COLOR_1,BLOCK_COLOR_1,BLOCK_COLOR_1,BLOCK_COLOR_1, BLOCK_COLOR_1,BLOCK_COLOR_1,BLOCK_COLOR_1,BLOCK_COLOR_1};

This array references just the index number for the color in the CRAM we want to use. I then use this in some calls to draw the colored rectangles inside of the game loop.
drawRect(10,70,296,144,(vu8*)&whiteColor);
drawFillRect(20,80,40,40,(vu8*)&blockColor);
drawFillRect(60,80,40,40,(vu8*)&blockColor2);


Flipping the Framebuffers

To get the rectangles to display you need to flip the framebuffer after everything has been drawn to it. To trigger the flip you need to set a special register at the end of the main game loop.

//flip the FB, without waiting on flip
currentFB ^= 1;
MARS_VDP_FBCTL = currentFB;


This can actually take some cycles, so you want to ensure that your code doesn't start trying to drawn anything to the framebuffer again until the flip has completed. Use the following check to wait for the flip to complete near the start of the main game loop, before you draw anything.
   
// wait on flip to finish
while ((MARS_VDP_FBCTL & MARS_VDP_FS) != currentFB) {}


Final Game

Putting it all together, and adding some dynamic color changes by updating the palette with new RGB values each game loop iteration, I created a simple flashing effect. Take a look at it on youtube.


Source code for this project is on GitHub 32XHombrew : drawingblocks

Feel free to send any feedback on this or other tutorials. There is so much information it is hard to put it all down on paper in a cohesive way. Hopefully these are useful to the next person who wants to try out 32X programming.

Saturday, July 19, 2014

Adventures in 32X Homebrew - Part 2

Previous part: Part 1: Introduction to the 32X system

Building a ROM

So as I said in my last post, there is no IDE or standard dev kit to use when building a 32X Game. Fortunately some of the heroes of the homebrew community have pieced together the parts to get a simple game functioning.

Where to begin.

Building a Toolchain for 32X

Let's assume you have a basic familiarity with the C language and compilers and you want to write your game in C as opposed to SH2 assembly language. In order to build a 32X ROM you will need to compile your code for the architecture of the 32X which happens to be the 32-bit Hitachi SH2 processor (as well as a secondary tool chain for the 16-bit M68k of the Genesis). Your standard C compiler or IDE is probably using a toolchain which is designed to target your 32-bit or 64-bit architecture of the PC, based on x86. This will of course produce a binary set of instructions that would not be readable by our friend the 32X. So before going further you must find (or build) a 32X compatible toolchain.

Courtesy SpritesMind.net forum poster Chilly Willy
Building a Genesis/32X toolchain

 0 - System Prerequisites (based on testing on various Ubuntu Linux distros as of 1/18/2015):

  • Package gcc-4.6 (I have run into issues using default gcc on Mac OSX, as well as higher versions of gcc on linux e.g. 4.8.2). I have had success with gcc-4.6.4
  • Package texinfo (e.g. sudo apt-get install texinfo)
  • Package p7zip-full for extracting .7z using Archive Manager (e.g. sudo apt-get install p7zip-full)

1 - Go here and download the following:

gcc-4.6.2.tar.bz2

Decompress it to wherever you keep your projects; you should end up with a folder called gcc-4.6.2.

2.1 - Go here and download mpfr-2.4.2.tar.bz2.
2.2 - Go here and download mpc-0.9.tar.gz.
2.3 - Go here and download gmp-5.0.4.tar.bz2.

Decompress them all in the same folder. You should have three folders called mpfr-2.4.2, mpc-0.9, and gmp-5.0.4. Rename them to get rid of the version numbers, leaving you with mpfr, mpc, and gmp. Copy them into the gcc-4.6.2 folder.

3 - Go here and download binutils-2.22.tar.bz2.

Decompress it in the same folder as the gcc folder so that you have two folders - gcc-4.6.2 and binutils-2.22.

4 - Go here and download newlib-1.20.0.tar.gz.

Decompress it in the same folder as gcc and binutils, leaving you with the folders - gcc-4.6.2, binutils-2.22, and newlib-1.20.0.

5 - Get this archive and decompress it to the same place as the previous directories. You should have two more directories, bin and ldscripts, in addition to the file, makefile-sega.

6 - If you wish to leave the makefile with the default path of /opt/toolchains/sega, make sure you have permission to write to /opt or the toolchain will fail to install to the path. Since there's nothing critical in /opt, it's easiest just to do "sudo chmod 777 -R /opt" which allows anyone to do anything they want in /opt.

7 - Run "make -f makefile-sega" - depending on the speed of your computer, in an hour or two you should have two toolchains in /opt/toolchains/sega: m68k-elf and sh-elf. Copy the ldscripts and bin directories to /opt/toolchains/sega.

You now have the latest gcc, binutils, and newlib for both the 68000 and the SH2. Both have compilers for C, C++, Objective-C, and Objective-C++. The bin directory has a few common tools one might use for compiling Z80 code for the MD. Copy whatever other tools you use into it, like sixpack or bin2c.

Note: The size of the built toolchain can be reduced by stripping the debug symbols from the executables in the bin directories, and by deleting the libraries meant for CPUs other than the 68000 and SH2. For example, you don't need the libraries for the 68020 or 68040 or SH3 or SH4, etc. 


If you do not want to build the toolchain yourself with the above steps, you may be able to find posters who have posted their copy of the resulting binaries which you could then take and use (for Windows OS for example). Furthermore most of the steps above are for a Linux environment, to build for Windows you'll first need software to emulate a Linux environment such as MinGW. I did not have too much luck with Cygwin personally, but it should also work in theory.

Let us assume you have your toolchain built and in place. On my system I decided to put it here C:\bin\_gcc\gen
My gen\ directory contained:
  • bin
  • ldscripts
  • m68k-elf (toolchain for Sega Genesis M68k CPU)
  • sh-elf (toolchain for 32X's SH2 CPUs)

Hello World ROM

32x Hello World

You can download the source code and the ROM binary that this produces from my GitHub repo
https://github.com/ammianus/32xHomebrew/tree/master/32xhelloworld

Using the toolchain, I have created a simple HelloWorld 32X application. Besides displaying the text "Hello World" it also will print some text which corresponds to controls pressed (A, B, C, Up, Down, Left, Right, Start)

If you download the 32xhelloworld.zip I linked to, extract it to some folder. Note that I am on a Windows 7 Home Premium environment. To compile it you will need to run the Make command from the toolchain we've installed. First edit the 'Makefile' in a text editor of your choice ( I use the extremely productive Notepad++ ). Make sure to change the path of variable:
GENDEV=C:/bin/_gcc/gen
To whatever the path of your toolchain from above steps.

To run use a command a prompt (Run As Administrator on Windows 7). Change directory (cd) to the directory of the extracted 32xhelloworld directory. Then run the 'make' command.
C:\Users\ammianus\Documents\roms\homebrew\32xhelloworld>make
C:/bin/_gcc/gen/m68k-elf/bin/m68k-elf-as -m68000 --register-prefix-optional -o m
68k_crt0.o m68k_crt0.s
C:/bin/_gcc/gen/m68k-elf/bin/m68k-elf-ld -T C:/bin/_gcc/gen/ldscripts/md.ld --of
ormat binary -o m68k_crt0.bin m68k_crt0.o
C:/bin/_gcc/gen/m68k-elf/bin/m68k-elf-as -m68000 --register-prefix-optional -o m
68k_crt1.o m68k_crt1.s
C:/bin/_gcc/gen/m68k-elf/bin/m68k-elf-ld -T C:/bin/_gcc/gen/ldscripts/md.ld --of
ormat binary -o m68k_crt1.bin m68k_crt1.o
C:/bin/_gcc/gen/sh-elf/bin/sh-elf-as --small -o sh2_crt0.o sh2_crt0.s
C:/bin/_gcc/gen/sh-elf/bin/sh-elf-gcc -m2 -mb -O3 -Wall -Wformat -c -fomit-frame
-pointer main.c -o main.o
C:/bin/_gcc/gen/sh-elf/bin/sh-elf-gcc -m2 -mb -O3 -Wall -Wformat -c -fomit-frame
-pointer slave.c -o slave.o
C:/bin/_gcc/gen/sh-elf/bin/sh-elf-gcc -m2 -mb -O1 -Wall -c -fomit-frame-pointer
hw_32x.c -o hw_32x.o
C:/bin/_gcc/gen/sh-elf/bin/sh-elf-gcc -m2 -mb -O3 -Wall -Wformat -c -fomit-frame
-pointer font.c -o font.o
C:/bin/_gcc/gen/sh-elf/bin/sh-elf-as --small -o lzss_decode.o lzss_decode.s
C:/bin/_gcc/gen/sh-elf/bin/sh-elf-gcc -m2 -mb -O3 -Wall -Wformat -c -fomit-frame
-pointer 32x_images.c -o 32x_images.o
C:/bin/_gcc/gen/sh-elf/bin/sh-elf-gcc -m2 -mb -O3 -Wall -Wformat -c -fomit-frame
-pointer graphics.c -o graphics.o
C:/bin/_gcc/gen/sh-elf/bin/sh-elf-gcc -m2 -mb -O3 -Wall -Wformat -c -fomit-frame
-pointer shared_objects.c -o shared_objects.o
C:/bin/_gcc/gen/sh-elf/bin/sh-elf-gcc -T mars-helloworld.ld -Wl,-Map=output.map
-nostdlib --warn-section-align --sort-common sh2_crt0.o main.o slave.o hw_32x.o
font.o lzss_decode.o 32x_images.o graphics.o shared_objects.o  -LC:/bin/_gcc/gen
/sh-elf/sh-elf/lib -LC:/bin/_gcc/gen/sh-elf/lib/gcc/sh-elf/4.5.2 -lc -lgcc -lgcc
-Os-4-200 -lnosys -lm -o helloworld.elf
C:/bin/_gcc/gen/sh-elf/bin/sh-elf-objcopy -O binary helloworld.elf temp.bin
dd if=temp.bin of=helloworld.32x bs=64K conv=sync
0+1 records in
1+0 records out
65536 bytes (66 kB) copied, 0.00307811 s, 21.3 MB/s

This results in a bunch of new binary files generated in the same directory. One should be called helloworld.32x, this is the ROM file which you may load with your favorite Genesis/32X emulator (Fusion 3.64, Gens, etc...)

You can try it out and see what happens if you press your controller keys for up, up, down, down, left, right, left, right, b, a, b, a, start (for example).

A 32X Hello World: How It's Made


I apologize in advance for those who would expect at this point a tutorial where I tell you how to write every line of code from scratch in an easy to follow, incremental process. If my time and resources were infinite I would do that. But creating a working game in 32X is no easy process. I have been mostly copying code from other tutorials (especially from the hero, Chilly Willy of the SpritesMind forums) and modifying for what I wanted to do.

I have tried to strip out most of my code that isn't required for this tutorial, but it is still a complex animal after all.

Let's look at what the various files are in the 32helloworld.zip and what they do:
  • 32x.h - General 32x / MD constants and function signatures for assembly file sh2_crt0.s
  • 32x_images.h/.c -  functions for drawing image (sprites) to different memory locations of 32x, e.g. the framebuffer
  • font.c - Open Source default font characters for printing text to screen
  • game_constants.h - my own set of game specific constants, some not used for helloworld
  • graphics.h/.c - my own set of graphics functions for drawing circle, calculating sin values
  • hw_32x.h/.c - Chilly Willy's set of 32X functions for various operations and for controlling the MegaDrive (MD)
  • lzss_decode.h/.s - LZSS compression decoder for 32X which was used for decoding images compressed with lzss by the "sixpack" tool tile conversion and compression utility
  • m68k_crt0.s - Chilly Willy's first part of the ROM header for MegaDrive and initial exception vectors. MegaDrive 68k assembly!
  • m68k_crt1.s - Chilly Willy's  third part of rom header, standard 32X header code. MegaDrive 68k assembly!
  • main.c - the main code for the Master CPU, all logic for Hello World and handling input
  • Makefile - the make file for this project
  • mars-helloworld.ld - linker script for this project which puts the generated binaries into the right places in the ROM which sega/32x will be able to process.
  • sh2_crt0.s - Chilly Willy's Rom header and SH2 init/exception code - must be first in object list
  • shared_objects.h/.c - My own shared global variables
  • slave.c - the main code for the Slave CPU, mostly just idle looping in Hello World.
  • types.h - typedefs for various commonly used types e.g. typdef unsigned char uint8 //unsigned 8-bit integer
If we look a little closely at the main.c we can see where the Hello World is being printed.

main.c source (thanks to Chilly Willy for some of the code):
/*
* Copyright 2014 ammianus
*/
#include <stdlib.h>
#include <math.h>
#include "types.h"
#include "32x.h"
#include "hw_32x.h"
#include "32x_images.h"
#include "game_constants.h"
#include "graphics.h"
#include "shared_objects.h"



#define DEBUG 1
#define MAP_WIDTH 320


#define IMAGE_START_ADDRESS 0
#define IMAGE_END_ADDRESS 1
#define NINJA_STANDING_INDEX 0

//global variable
char keyPressedText[100];

//const int world_width = WORLD_WIDTH;
//int paused = UNPAUSED;
//stores the previous buttons pressed for handle_input
unsigned short prev_buttons = 0;


/*
* Converts an integer to the relevant ascii char where 0 = ascii 65 ('A')
*/
char ascii(int letterIndex){
    int asciiOffset = 65;
    char newChar;
    newChar = (char)(asciiOffset + letterIndex);
    return newChar;
}

/*
* Call 32x hardware initialization routine
*/
void mars_init(void)
{
  //using 256 color mode using palette
  Hw32xInit(MARS_VDP_MODE_256, 0);
}

/*
* Check the current SEGA Controllers for inputs, update player, direction
* , speed, and action accordingly.
*/
void handle_input()
{
    unsigned short new_buttons, curr_buttons;
    //unsigned short buttons = 0;

    //The type is either 0xF if no controller is present, 1 if a six button pad is present, or 0 if a three button pad is present. The buttons are SET to 1 if the corresponding button is pressed, and consist of:
    //(0 0 0 1 M X Y Z S A C B R L D U) or (0 0 0 0 0 0 0 0 S A C B R L D U)

    // MARS_SYS_COMM10 holds the current button values: - - - - M X Y Z S A C B R L D U
    curr_buttons = MARS_SYS_COMM8;
    if ((curr_buttons & SEGA_CTRL_TYPE) == SEGA_CTRL_NONE)
        curr_buttons = MARS_SYS_COMM10; // if no pad 1, try using pad 2
   
    // set if button changed
    new_buttons = (curr_buttons & 0x0FFF) ^ prev_buttons;
    prev_buttons = curr_buttons & 0x0FFF;
   
    while (MARS_SYS_COMM6 == SLAVE_LOCK) ; // wait until slave isn't blocking
    MARS_SYS_COMM6 = MASTER_LOCK; //tell slave to wait
   
    //pause when start is first pressed only
    if (curr_buttons & SEGA_CTRL_START )
    {
        sprintf(keyPressedText,"Key Pressed: Start");
    }
    else if (curr_buttons & SEGA_CTRL_UP )
    {
        sprintf(keyPressedText,"Key Pressed: Up");
    }
    else if (curr_buttons & SEGA_CTRL_DOWN )
    {
        sprintf(keyPressedText,"Key Pressed: Down");   
    }
    else if (curr_buttons & SEGA_CTRL_LEFT )
    {
        sprintf(keyPressedText,"Key Pressed: Left");
    }
    else if (curr_buttons & SEGA_CTRL_RIGHT )
    {
        sprintf(keyPressedText,"Key Pressed: Right");
    }
    else if (curr_buttons & SEGA_CTRL_A)
    {
        sprintf(keyPressedText,"Key Pressed: A");
    }
   
    else if (curr_buttons & SEGA_CTRL_B)
    {
        sprintf(keyPressedText,"Key Pressed: B");
    }
   
    else if (curr_buttons & SEGA_CTRL_C)
    {
        sprintf(keyPressedText,"Key Pressed: C");
    }
   
    MARS_SYS_COMM6 = MASTER_STATUS_OK; //tell slave to resume
}


/*
* Starts application
*/
int main(void)
{
    //
    // Declarations
    //
    int more = 1;
    int frameDelay = 5;
   
   
    MARS_SYS_COMM6 = 0; //init COMM6 for slave
   

   
    //
    // Init Graphics
    //
    mars_init();

   
    //init screen
    Hw32xScreenClear();
    HwMdClearScreen();
    Hw32xSetBGColor(0,0,0,0);
    sprintf(keyPressedText,"Key Pressed: ...");
   
    currentFB = MARS_VDP_FBCTL & MARS_VDP_FS;
   
   
    MARS_SYS_COMM6 = MASTER_STATUS_OK; // tells slave to start
   
    //game loop
    while ( more ) {
        handle_input();
        HwMdClearScreen();

       
        // wait on flip to finish
        while ((MARS_VDP_FBCTL & MARS_VDP_FS) != currentFB) {}
       
        //print paused to screen
        HwMdPuts("Hello World", 0x2000, 16, 14);
        HwMdPuts(keyPressedText, 0x2000, 10, 16);
        //
        // draw to FB
        //
        //redraw background 10*BG_TILE_SIZE
        while (MARS_SYS_COMM6 == SLAVE_LOCK) ; // wait until slave isn't blocking
        MARS_SYS_COMM6 = 4; //tell slave to wait
       
       
       
        MARS_SYS_COMM6 = 1; //tell slave to resume
       

       
        //draw the 32X framebuffer line table with offset of 4
        drawLineTable(4);
       

       
        //flip the FB, without waiting on flip
        currentFB ^= 1;
        MARS_VDP_FBCTL = currentFB;
       
        //do game loo
        //artificially introduce delay
        Hw32xDelay(frameDelay);
    }
   
    HwMdClearScreen ();
    return 0;
} // end of main function



In the main function int main(void), there is a while loop which is where the main action takes place. First when the program initializes it will set various attributes of the 32X and the synchronization between the master CPU running the main.c and slave CPU. The place where any real logic is happening in this game loop are where handle_input(); function is called for each loop iteration. The handle_input() function reads the current control inputs and determines if a button has been pressed, then sets a char[] with some text to say which has been pressed. The place where this gets printed to the output is with the lines:

        HwMdPuts("Hello World", 0x2000, 16, 14);
        HwMdPuts(keyPressedText, 0x2000, 10, 16);


The HwMdPuts() function is a function from hw_32x.h. As the name suggests, this actually is sending a command to the MegaDrive (Md aka Genesis) to print some text to the sprite layer of the Genesis. This is displayed on top of the 32X display output, which was only a black background.

This is certainly not the only way to achieve the same result, if you wished you would be able to create functions to print directly the the 32X display, but it is slightly more involved and get's into the 32X graphics systems. This just shows how you can get a ROM to be build and run in an emulator, as well as offload some processing work to the M68k cpu in the Genesis.

More on how to display graphics in my next installment!

Further reading:

Further references to other simple projects to get you started, courtesy of SpritesMind forums:
32X ROM Template [ASM]
Toolchain with links to several demos program projects

Monday, June 2, 2014

Adventures in 32X Homebrew - Part 1

I have not been posting a lot recently, one of the reasons has been a project that I started in early 2012, which as it never quite reached completion I did not want to let the cat out of the bag with premature posts, more importantly I was a novice in the areas that contributed to this project so to write a bunch of posts without knowing a thing about what I was writing would have been fruitless exercise. This mysterious project consumed my nights and weekends, on and off for at least a year and although I think what I originally intended to do is feasible, I do believe I have learned enough that sharing this knowledge may be useful to someone else, at least as a cautionary tale of things not to do.

As you may conclude from the title of this piece, the subject of my project was the Sega 32X game console, and specifically developing "homebrew" games for it. For the sake of brevity I will refer to all consoles and games by their U.S. titles, for example the Sega Genesis was titled Sega Megadrive in other markets.

Background

Sega 32X

Sega 32X ( was released in 1994 as an add-on unit for the Sega Genesis/Megadrive video game console. The 32X was considered as a way to "upgrade" the 16-bit Genesis to be a 32-bit console without having to buy an entire new console that were starting to enter the market, such as the 3DO, Atari Jaguar and even NeoGeo, this would have been nice for the millions of owners of Genesis unit's with large libraries of existing games that would still be playable on the 32X expansion. In addition, at the time, Sega was already being edged out in the 16-bit console wars by the Super Nintendo (SNES) where games like Donkey Kong Counter, Starfox, Killer Instinct and Final Fantasy 3/VI were beginning to eclipse the Genesis titles visually and even in other areas like game sound and the sheer amount of content. Whether the concept was sound or not, the result was 32-bit capable system that was less powerful than the other 32-bit consoles on the market or the next generation that was coming, the so-called "fifth generation" consoles, of Sega Saturn, Sony Playstation or Nintendo 64.  The result of the release of this console was that while initially popular with American genesis owners, the lack of third party development support and poor quality titles crippled the platform, sales fell when people realized that this wasn't going to get the games that were coming out for the real 32-bit systems. Sega ended up completely pulling the plug on the 32X in 1996 with no new games being released. The saga of the development and release of the 32X in this context is a fascinating story by itself, and excellent accounting of that can be found in Project Mars: Anatomy of a Failure.

I will out myself by admitting to owning the 32X (and still do), and in my blind brand loyalty to Sega I had at the time, tried as hard as I could to like the 32X and the games that were released for it. Looking back with almost 20 years of hindsight, I was rather naive over the state of the market at the time. for one thing, I did not have any subscriptions to gaming magazines at the time, so I really did not have any critical analysis of the 32X, it's expected game library or system specifications and capabilities. I did not recall that the Sega Saturn and Sony Playstation came out so soon after the 32X did. I also remember believing some things initially, don't know where I heard it, such as that the Sega 32X + Sega CD add-ons would create a combined system "equivalent" to the Saturn, even that the games would physically be compatible, or that there was some kind of hardware acceleration for 3D games. I was in school at the time, and couldn't have afforded a Saturn in any case, with my meager part-time home chore income, the idea we could have a 32-bit system instead of a 16-bit one, was very appealing. The initial lineup of games that were released were promising as well, Doom being of the biggest titles, probably one of the biggest PC games at the time, Star Wars Arcade looked incredible, and it was Star Wars! Virtua Racing was another cool 3D polygonal car racing game, that was pretty impressive for the time. Both of these Sega titles I had actually played a few times in Arcades around '94. Again I was not a very educated consumer, I did not go to arcades all that often, while in the 8-bit era, it seemed pretty obvious that arcade games were far superior, as 32-bit era approached, it wasn't clear that the arcades still had far better graphics than what we were going to be getting at home. Even for 16-bit, at the time I was not really sophisticated enough to realize that the Mortal Kombat I played at home was a different experience to the one in the arcades. In any case, the games looked "good enough" and surely, more and better games would be coming out?

Its a trap: Repetitive arcade game play from one of
the best 32X games
Now, I loved Sega at the time, but overall, my impression of the 32X was a major let down, even if I didn't want to admit it. In my opinion, the games were generally just boring, it's hard to pin-point why, I think mainly the game play was lacking, and the 3d effects and fairly limited worlds were underwhelming after a while. For example Virtua Racing Deluxe, had really nice, crisp polygonal graphics in true 3d world with multiple camera angles, decent sound and music, but it in the end, it lacked the rush and thunder of the arcade version, especially after going around the same tracks 2-3 times, there isn't much else going on. I've never been a fan of racing games, but there was only so much you could drive around, and you could never get outside the track and explore. Motocross Championship, was basically like EA's Road Rash series, except the graphics were barely better, the locations were always the same dusty dirt track and the sound effects were particularly terrible. The best 32X game was Star Wars arcade, which again, as an arcade port, was repetitive, fly through hyperspace to an area and chase TIE fighters in circles. Now it was beautiful 3d space environment with asteroid fields and star destroyers, but it did lose it's edge after the 15th tie fighter blew up in a small yellow virtua-explosion off in the distance after 20 other similar laser shots failed to do any damage. I don't think I ever actually made it to the Death Star trench run level. I was also disappointed that you couldn't damage the star destroyers, it was my dream to  blow up their deflector shield domes, ala Return of the Jedi (Intensify forward firepower!....Too Late!!!). I don't think I actually had any other 32X games. I probably played Sonic & Knuckles alone twice as much as all those games combined while I owned that system.

Making Dreams a Reality

So money spent, dreams shattered, I always wished that they made better games for the 32X. Many years later, I had heard that one of the reasons that the games weren't that impressive was due to the developers not utilizing the hardware to it's fullest. Now being a developer myself, I wondered, what if I made the next great 32X game? The context is that I have been interested in gaming and computer programming all my life, I have made some game-ish programs for university courses and I briefly dabbled in libSDL programming on Unix. I have a few game ideas I have been kicking around in notebooks and in my head for years, and it was always a dream to someday put them down into reality. Why the 32X, well it just so happens that the genre's of games I want to make are generally side-scrolling, 2D affairs. For me and probably a generation of gamers, there is nostalgia for games that look and act like the ones we grew up immersing ourselves in on our old sega's and nintendo's. My grand vision was to take some of game story ideas, using genre's that were mostly done in the 16-bit era, and make even better versions of those for the 32X! Not only would these retro games be good in their own-right, they would be unique for being released for one of the most maligned and obscure platforms ever, nobody would be able to compete with me! I own a Sega Genesis and 32X although it had been sitting in a box in my parent's basement for 10 years or so, I planned to eventually resurect it and play my homebrew masterpieces on it one day. So I set out to "teach myself" how to program for 32X and make the best darn game anyone had ever played on that system.

Hardware and Development Environment

The 32X is an interesting piece of hardware, the overall system combined with the Genesis (+ Sega CD) is a complex multi-processor machine with heterogeneous CPU architectures, video processing capabilities, memory spaces, but sharing the main inputs/outputs (Cartridge ROM, controllers, video and audio out). Unfortunately to learn the 32X you have to know at least a little about the way the Genesis works and some of the ways it differs. This is a crucial point to keep in mind for later, because often you'll be amazed by things that Genesis games could do with apparent ease which seem to require vast computing power in the 32X.

There is relatively scant documentation on the internet, and most of it, that does exist is useful as background reading, rather than being actionable step-by-step guides to do anything. There is a small community of homebrew developers who are mostly self-taught, extremely technical and interested in all the bits and bytes of hardware in both the Genesis and 32X. Without their help and guidance I would never have been able to get a Hello World to run on the 32X.

Specifications

CPUs: Dual Hitachi SuperH RISC processers (SH-2, SH7064)
Clock Speed: 23 Mhz
Main Memory: 256Kb SDRAM

Video:
Video Memory: 256Kb (two 128 Kb framebuffers) 

Screen Resolution: 320x224 or 320x240 (PAL)
Color depth: Up to 15 bits, 32768 unique colors, two-bytes per pixel, can use paletted color mode, using up to 256 on-screen colors with one byte per pixel to save memory.

Sound: 

Stereo 2-channel PWM (Pulse Wave Modulation mixer)

And that's about it for the 32X. As I mentioned the 32X combines with the Genesis base, and a 32X game can actually leverage the Genesis hardware in addition to just the 32X components (as well as Sega CD). The Genesis specs are:

CPUs: Motorola 68000
Clock Speed: 7.67 MHz
Main Memory: 64Kb RAM
 

Video:
CPU: Dedicated "Video Display Processor" based on Texas Instruments TMS9918
Video Memory: 64Kb and 64 x 9-bits of CRAM (Color RAM)
Resolution:
Maximum same as 32X, 320x224, 256x224, 320x240 (PAL only), 256x240 (PAL only)
Supports 3 planes, 2 background layers and 1 sprite layer

Sound:
CPU: Z80 @ 4 MHz (Not Present in MK-1631)
Controls PSG (Programmable Sound Generator, TI 76489) & FM (Yamaha YM 2612) Chips
Sound Memory: 8Kb

Cartridge

32X cartridges although physically different are essentially the same as Genesis carts, and can hold typically 4Mb of ROM data although the size of ROM could be larger if used with bank switching capability to access a larger memory space.


Development

  Game software can either be developed in assembly language (a mix of SH2 assembly plus 68000 assembly for Genesis in the same game) or a higher level language such as C that is compiled into machine code for one or the other processor architecture. An "art" of the 32X development is being able to write software for both the Genesis and 32X that can coexist peacefully on the shared hardware.

There are no IDEs, there really isn't a standard SDK, toolkit or any libraries for the 32X available, other than a few home brew examples that are out there. If you can set up an IDE and configure a custom tool chain you may be able to use it to build your C source code into your game. There are appears to be more of a homebrew community for the Genesis. I used a combination of text editors with syntax highlighting and various command line tools and shell scripts for my own build environment which I will cover in Part 2 (coming soon)


Background Resources & Reading


It helps to have an overview of the hardware and reference material handy, there isn't much documentation or specific resources on the web for 32X development, so what is out there is gold.

Collection of Sega 32X Manuals including the most important "32X Hardware Manual".

Reverse engineered introduction to 32X capabilities and hardware.

Devster's site also has a few other documents, example homebrew ROMs and utilities.


"Project Mars: Anatomy of a Failure" – a good overview of the development, marketing and failure of the 32X and the impact it had on Sega.

"Hitachi SH7604 Hardware Manual" – The manufacturers manual for the main RISC CPUs used in the 32X aka SH2, Super-H. Has the details for all of the assembly language instructions for the processors.

Gallery: 32X Development – includes some utilities, assemblers and 32X BIOS files as well as more Hitachi SH2 documentation.



Places to get support


The only places to ask questions about 32X development are a few Sega/gamer enthusiast sites' forums where there is still a small homebrew scene of people who have taught themselves how to program.


Saturday, March 29, 2014

Malicious redirects from this blog (resolved)

Dear readers,

It has recently come to my attention that there was a problem when viewing my blog with javascript enabled in your browser where you would be redirected to some obvious spam/malware/phishing sites (fake Flash or Java download pages). This was happening due to a third party gadget that was part of my Blogger template and apparently had only recently been causing this behavior. My apologies for anyone whose browser was hijacked by this.

These third party gadgets are submitted to Google and available for a blogger to choose to add to their blog's layout template. All indications are that the blog has not been "hacked" and the problem is resolved now.

Information about this problem on the Google support forums seems to indicate that this has happened to many other bloggers as well. If you run a blog, you should remove the Sociable or Share It gadgets as they are known malware gadget.

https://productforums.google.com/d/msg/blogger/aLsGFogJraw/6eU71c8g9ZMJ



Oh Ubuntu, won't you ever win?

After several months of idling in my basement. I decided to fire up the ol' Ubuntu desktop in order to use one of the few apps I have on that OS that I don't currently have an equivalent on Windows. After successfully using the intended software, Ubuntu's Update Manager helpfully notified me that I needed hundreds of critical and recommended updates to software packages. I am fine with that, and figured it wouldn't hurt to update since it had been some months and I expected to need to use Ubuntu again more regularly.

After downloading and installing all the updates, I needed a reboot. After doing so, my desktop wouldn't come up due to errors like this: Xorg says the kernel module is of version 304.88 (The old version before I updated) but the driver components are of version 319.32 (The new version).

This isn't the first time I've gone down that road, and it usually doesn't end well. I don't know why security fixes can bring down the GUI of my desktop. But oh well.

Thankfully, to Google and AskUbuntu, the answer is so simple it brought tears to my weary eyes.

Thanks to a Mr. "Joren" for the solution:
 
First remove all the old drivers:
sudo apt-get purge nvidia*
Then reinstall the current drivers:
sudo apt-get install nvidia-current
Reboot, and your're good to go!
sudo reboot 

Worked like a charm.
 

Source: http://askubuntu.com/questions/349129/12-04-lts-wont-boot-after-nvidia-driver-upgrade