Friday, December 29, 2017

Putting the Puzzle Together

Today's post is going to be a bit content-heavy. I finished up the font, kerned it, and then kerned it three times more just to get it to look right. Now it's a functional all-caps font. I decided not to add any extra letters or duplicate the lower case. I just needed something I use later. I still have to alter the Kenny font to fix the K and H. (The font is public domain, so good for that!).

My resolution boost isn't going to mean anything without HD assets to go with it. Now the conservative side of me should of just bumped the graphics I had to 400% and use them as place holders, but I was still in an Inkscape mood so I decided to re-render the 3D puzzle pieces for the original game.

The first thing I did was trace out the original puzzle piece in Inkscape. The logo uses two but it's really just the same turned on it's side. After the trace was done I imported the SVG into blender and extruded it into 3D followed by a tessellation so I could use it as a proper 3D object made out of triangles as opposed to spline paths.


After this I made up some basic materials and colored up the model. Eyeballing the original animation I set up a camera and a light to match the shadows as best I could. Then I rendered each frame of animation at 1920x1080. It was a little overkill, but it's best go to big and then drop the resolution later. You can't add data that's missing.

Click to Embiggen
After that it was a little work to remake the original graphics via scaling and placement. I think I did a good job with that, I'm not sure how accurate I was with placement until I actually animate the puzzle pieces in game. I can tweak later if I need to.

All in all, I was able to knock out the 3D stuff in about a day and a half. New years is coming up so I may go radio silent again, but I'll be ready and charged up for the new year.

Also, I decided with the graphic enhancements to bump the version of the game to 2.0 (It's currently at 1.09). All in all  I think this is looking really good.
 



Thursday, December 28, 2017

Keming

You know, there is a lot more to font making that I realized. Not much though. I had the basics down as I am used to vector art using Inkscape and SVG. There are a few twists with fonts as they are programmatically controlled. This is just learning a few rules. Holes in the font are dictated by if the drawing vector is clockwise or counter-clockwise. (i.e. if the surface normal is pointing up or down). I can see how font making can be a profession all on it's own, and with Unicode being a thing, you can't just get away with a Latin-1 charset anymore.

One of the A-HA moments I got was when I was able to tell the font how to do kerning properly. The text for the title fonts are mostly square, but not fixed with. The W, X, Z, and M were kind of a pain. that and I had to get the W and A to kern properly (WA) - see how the top of the W and the bottom of the A slot into each other. If you don't kern that right you get a space between the letters. I mostly eyeballed the original font, but in the end I do have my own TTF to use!

There are no lower case letters in this font, which is why it looks odd in preview.


How are the Holidays?

Like I said in my last post, I've been doing a little year-end personal time, and have been poking at things on and off. In this little space between Christmas and New Year I have been working on the logistics of the big resolution boost. One of the things I'm going to be replacing is the text system. I want to use nice and scaled TrueType Fonts, but I'm going to assume the original fonts are not available in TTF format. In this case I'll just roll my own. I have a screenshot below of the title font that I hand converted to SVG and I'm now importing it letter by letter into a foundry application to create the TTF. I couldn't do an auto-trace because the TTF strokes out the outline in particular way. TrueType is actually a language that describes the shape of the letters. In the U.S. you actually can't copyright a font. (You can most everywhere else in the world). That being said, you can copyright the program in the TTF file that draws the font. This is the work around for font licencing, but there is nothing stopping you from just drawing your own copy of the font and coding up the glyphs yourself.

Once this the font is converted over, things like the title sequence will be a dream to re-code. I found a TTF equivalent for the GUI font that is free to use, but the "K" looks like an "H" so I'll just fix that up in my foundry.

As always, screenshot of my work so far...


Thursday, December 21, 2017

Season Slowdown

I'm working on ROE every day, but as the holidays approach, there will be a little bit of a slowdown. First, I can only show so many screenshots of Doxygen as I fill out functions. Second, I'm pieceing together how to implement the graphic updates I want to do. ROE is a strange beast as it's screen is not rendered every frame. It only dynamically updates what's needed. This makes sense as ROE is largely a GUI game and this was written at a time where CPU time was best utilized elsewhere then rendering the screen if it wasn't needed. I would love to give this game a proper render loop, but I'm not sure the current state machine is compatible with that. Also the game does not have a good concept of transparencies in the 24 bit sense so blitting graphics as been proven to be an issue.

During my downtime I want to explore replacing the fonts with actual Truetype fonts. This will make making high-resolution replacement graphics much easier, and also I can replace some of the text print commands in the game with the Allegro TTF counterpart. I'm pretty OK with Inkscape so I can see how well the vector system translates to Truetype. In a perfect world if I can do an SVG import of fonts I would be happy.

Function mapping is taking a while. To best sum it up, I have a partial screenshot of a Doxegen graph for a function showing it's pathing to the endpoints.

And that is why it was called "Spaghetti code". It looks worse then it is. I have the pathing turned up pretty high. By the way, did you know there are other types of "pasta" code as well?

Ravioli code - A pejorative phrase for source code with lots of tiny, tightly-coupled objects.

Lasagna code - Multilayered object code where each layer interface is a near copy of the one above it with little change.

Macaroni code - Code with mixed languages within it, most often abusing the preprosseor # token

Fusilli code -  Pejorative phrase to describe marketer-driven programming with a spin to make bad code look good.

(The was shamelessly stolen from Wikipedia)


Tuesday, December 19, 2017

Graphic Experiments

More documentation. I've decided to merge Pass 2 and Pass 3 into one project. That is, I am now prepping to rewrite the lower level things, fixing the rendering pipeline, and updating the visuals. It was coming apparent that any further "fixing" of the code was going to detract me away from that goal.

So now I'm auditing and documenting. Each function, global and struct is going to get identified and tucked away. I'm trying not to suffer from "Analysis Paralysis" but I want an opportunity to look at each function and figure out what each does and where it fits. I have the maps to do so, now I's just a matter of writing a header and jotting down parameters and returns. (I have a handy code snippet that I wrote in XML to help)  

As the documentation was getting a little repetitious, I spent the other half of my day drawing up a few graphical prototypes. The question I had was this: How do I maintain the graphic look of ROE, but move it away from the LCARS Star Trek-ish interface. You can argue that the garish 16 color interface isn't exactly Star Trek, but I wanted to try some prototypes anyway.

Click to Embiggen
I did the following using Inkscape ind Gimp. I am still thinking of using 1280x800 as my "native" resolution I also created a "stretched" copy @ 1920x1080 to see what it looked liked. It was good, but I may need to pin down the underlying technology first before I start stretching things.  (You can click on the picture to get the full version.) This is going to deal with a lot of transparencies and I'm not quite sold on the starfield background. The buttons that you can push can stand to be brighter. I also haven't played with any of the font types or colors. I still want to maintain the old color scheme. It's cure in it 16-color kind of way. I also know the globe in the center isn't earth in the actual game. That will need to be rendered.

Speaking if rendering. I may turn the title sequence into an 3D FMV. I may experiment with that later, as long as it doesn't detract from my coding too much.  

Monday, December 18, 2017

Crossroads

As I tried to clean up the warnings, I am finding myself tying the game to the lower level library in ways I don't like. I'm beginning to emulate what some functions are expecting at the cost of future enhancement. For example, one of the reasons the game screenshots seem so small is because it's literally running in a 320x200 window. While I can "zoom" the final display at a higher resolution, that will impact what the mouse input routines are expecting. I want the game running at a higher resolution anyway, but there is so much that is hard-coded into the game. Glancing at the source code there 518 buttons that have locations set in a huge button struct. That's not including dynamic locations like lists or sprite placement.I'm planning on expanding the graphic fidelity, and I have two ways I want to try this...

First, my original idea of defining the display from 0 to 1 on the X and Y access. That will make the game display unlocked for any aspect ratio. This would kind of be a mess as the game itself does not have much in the way of vector graphics. All the the bitmaps will be stretched into whatever the game would feel appropriate.

My other idea is to keep the underlying "grid" at 320x200, and overlay the high resolution graphics on top. I would treat each "pixel" on the 320x200 grid as a "cell"  However I have now come to another conundrum. 320x200 is 16:10 and I would rather it be at 16x9. What would be the new "Native" resolution?

Doing some quick math here.

320x200 expanded by...
... 360% is 1152x720
... 400% is 1280x800 (nice and round)
... 540% is 1728x1080

So maybe "native" is 1280x800 and then I can stretch depending on the player's preference? Going "down" to 720 will afford me a little anti-aliasing. Maybe because the background is black, that might afford me a little leeway that no one is going not notice the black bars on the side.

Hmm. Oh well, back to documentation. I included a new animated GIF showing the 1Ch thread running. I now have animated blinkys and and decorations.


Friday, December 15, 2017

Whittling it Down

Progress report; I'm now down to 691 warnings. Pretty good score I think. All the unused variables are gone. It appears lots of functions were created with a template with a bunch of generic variables defined at the top. After I fixed that I went on to integrate rproto.h so I could include the function declarations. Turns out the version I had didn't match the current copy of the game, so I have to make my own. There were lots of functions that had a return type of int that didn't return anything. Looks like MSVC is not real fan of that. I squashed some warnings, and made sure the function returned the correct type. I just set most of the to void and went on. However, I am now running into functions where not every control path generates a return. Then, looking at the code, none of the calling routines do any assignment anyway. There are a lot of functions that are like this.

if(foo==0)

   return 0;
}
else
{
   //Do things, but don't return anything 
}


Then, higher in the code, the 0 is never checked anyway. Do I just get rid of the conditional? Do I return 1 on exit? Guess it depends.

So now I just doing unglamorous job of tidying up the code. Each "missing" definition will need it's declaration entry into rproto.h and there are still 641 left of those.



Thursday, December 14, 2017

Digital Cartography

With nearly 1000 warnings to have to go though, I decided to turn on Doxygen's graphing system to help map out ROE. What I got back after about three minutes of number crunching was an unexpected surprise! Turns out it can generate really awesome call and caller maps. The means I can trace backwards from any call and go forward downstream. I can also find functions and where they are placed in the grand scheme of things. No more having to manually search and backtrack though the code manually. Some of the call paths are super wild, but that's what happens with spaghetti code sometimes. I included a map for the SetupEnemyForm() function that takes all the bits of aliens (arms, legs, head) and generates a graphical representation of the alien you are fighting in the game. As you can see, the execution path is as clear as a bell. I am so stoked about this.


I also decided to turn off the suppression of unsafe functions. (i.e. have the system generate an error  when it comes across a function that is prone to a buffer overrun). This resulted in 504 errors and another 3 warnings. I turned the suppression back on, and will deal with that later.So now I can go in a bunch of different directions. Now that I have a map, let's start to categorize those warnings and what I need to do about them. Using the magic of a spreadsheet and pivot table, I only have 11 types of warnings:


  1. <function> undefined; assuming extern returning int  (603 Warnings)
    1. Pie graph of all warnings
    2.  I have not included rproto.h into the main code yet. This has all the prototypes that need to be set during compile. However, my C++ compiler seem to be prototyping on the fly, I need to put the horse before the cart here and integrate rproto.h properly 
  2.  <expression>: signed/unsigned mismatch (20 Warnings)
    1. C++ has a type that is not in C called size_t, which is a unsigned int. There are several common functions such as strlen() that used to return type int that now return type size_t, which is unsigned. strlen() is also one of those functions that should be an error as it's not safe (Should be using strnlen_s()) so each function with this warning will need to be checked to make sure the variable can't go negative, and if it doesn't type it to an unsigned int
  3.   <function> : too many actual parameters (1 Warning) 
    1. I think this is a bad placeholder file function I put in. Will be converting this to AllegroFS anyway
  4.  <function> : different types for formal and actual parameter 'number' (1 Warning)
    1. Another type mismatch. I'll have to find it correct.
  5.  <identifier1> : 'operator' : different levels of indirection from 'identifier2' (3 Warnings)
    1. There is some hinky pointers referencing in funny ways. Will investigate. 
  6.  <identifier> : unreferenced local variable (241 Warnings)
    1. This is actually pretty easy. There are unused variables. Purge them if not needed.
  7.  <identifier1> differs in parameter lists from 'identifier2' (1 Warning)
    1. I have a function that is mismatching - Find and fix.
  8.  <var> : conversion from 'size_t' to 'type', possible loss of data (1 Warning)
    1. size_t again, I'm guessing that my 4 byte int is not fitting in somewhere
  9.  <function> : not enough arguments passed for format string (1 Warning)
    1. Another string function - those are going to get scrutinized 
  10.  <function> : not all control paths return a value (30 Warnings)
    1. Check execution paths. 
  11.  <function> must return a value (48 Warnings)
    1. Bad prototype, Check definitions



So Not bad, The "Big ones" is just janitorial work mostly type fixing and making sure functions match with how they are being called.  So the plan so far is to get the warnings squashed, Check for graphical bugs in Nermal, replace the 504 insecure functions, and move the filesystem functions into Allegro... I like that as a plan so far!

Wednesday, December 13, 2017

Doucmentation Pass

There was a file I forgot to un-comment when I was adding them yesterday and now have that included too. This brings the warning total up to 990! I have my work cut out for me I guess :) I also decided to turn profiling on just to see how fast it took the compile the whole project from scratch:

 That's 3.5 seconds in human terms. I can't even guess how long it would of taken to compile in 1990.  I going to guess that it would of been somewhere between five and fifteen minutes? I took a look at the original build folder and didn't find any profile info which would of been a treat to compare.

As I'm not tracing through the code anymore, the program runs on it's own terms. I am now going to start the task of documenting the code so I know where everything is. Then I will place it in Doxygen. When the documentation is done, I will be squashing the warnings. next. I'm looking for a clean compile. After that it will be the surgical removing of the legacy functionality and and moving what I can into Allego's native functions. This includes all timers, (for example the ones that rely on clock_t from "time.h"), memory allocation, filesystem calls, and many ugly graphics hacks. Allegro has the ability to stuff things like data files and graphic assets into a transparently packed data file. At that time, I'll also be giving the game a much needed resolution boost. For this I'm going to try an experiment where the "native" resolution will be from 0 to 1 on X and Y axis. On each draw it will apply a scalar to allow any size to the display. Sadly much of the graphics are hard coded in their positions so I may have to use 320x200 as my base and use fractional coordinates for higher resolution graphics. The good news is 320x200 is 16:10 aspect ratio because the pixels were not originally square.

For fun I created a vector of the background and scaled it up to 1920x1200 to see what it would look like. It's cooler, but still a but flat. Graphic passes isn't until phase three. The exported vector is below.
Click for full size



Tuesday, December 12, 2017

IT LIVES!!!!!

Info/Credit Screen
The Nermal library is so complete now I decided to dummy out the rest of the functions and import the rest of the ROE source into Visual Studio. After creating dummy functions for the unresolved externals and getting everything in the right order. The compiler went all the way though! This is not perfect by any stretch of the imagination. The interrupt is still offline. Turns out that if you look at the screenshot at the bottom, that displays "STANDBY" when the thread is not running. Pretty neat little helper.

F1 Help
The major graphical functions are there, but just because I can get 101 to function, does not mean there are dangerous pitfalls. For one I have not touched any of the filesystem code, which can be scary as I'm almost positive that it will take one look at NTFS and freak out. The best part though is my low-level changes to the input system means that the mouse is now no longer relative. The DOS version did not understand how to "snap" a mouse pointer to a particular part of the screen. It only measures relative distance the mouse moved since the last check (Measured in "Mickys", or about every 0.0039 inches.) What this means is that the game will be able to take explicit touch locations for "taps" as opposed to rolls and clicks.

That's right! 901 warnings.
The compiling didn't go without a hitch, though. There are 901 warnings about a myriad of things that I will have to look into. One of the quick bugs I cleaned up is that Quick C (The compiler used in the 1990s) auto initialized pointers to NULL. That's not really true. According the the C standard, pointers should be "undefined" when they are created. That way if you go though a program and the pointer was never initialized to anything, it will throw an error. Undefined pointers can be a huge problem as they could literally be anywhere en memory and once you reference it... *POP*...access violation.




For some reason there were functions names that had mixed case. C is supposed to be case sensitive, I fixed those too. One of the more interesting bugs came up as a direct result of me compiling C on a C++ compiler.

The keyword "new" is reserved in C++. This is an example of C code that is incompatible with it's superset. This means C and C++ are not the same language, just very, very similar. Kind of like American English and British English. Very similar, but if you get a chance, ask an American, Brit, or Aussie what's the difference between a turtle, tortoise, and terrapin. You will probably be surprised by the answer. (It's also why herpetologists call them "Testudines")

Monday, December 11, 2017

Deleting the useful.

Remember that post was I was all like Tony Stark and dumping things in the trash. Well, it's pretty humbling when you have to go into the bin and dig things back out. Early on when I was organizing everything, I decided to delete things I knew I wouldn't need. (Note to self: comment blocks are there for a reason). I removed things like the register structs for calling interrupts, and the GIF helper functions. I am using Allegro's built in PNG support, so that wasn't needed. However, I also ditched some of the interrupt control variables and original code for functions I was planning on replacing. My new 1Ch thread needed those variables to keep it from spinlocking forever. There is a debug flag that is passed to the game via an argument. When debug is turned on the 1Ch interrupt, (on in my case the thread) is turned off. I've hard coded the thread off for now as the loop has a few unresolved functions I have yet to implement and don't want to dummy out. I'm getting to the point where when I implement a low level Nermal function, the code I'm dropping in from the original source is just working.

Also when I dummy out a function, I'm now making extra sure that the original is in a comment block underneath. That way I'm not going to the original archive to figure out what it's supped to do.

Upshot: The buttons on the main screen (Called 101) flash when you click them and attempt to run the appropriate function. I'll be implementing the quit routine tomorrow, and will be attaching that to the actual "close" button on the window. After that., I'll get the Help (F1) and  Info screens.

Still nothing glamorous as screenshots go. The code back end isn't very sexy I do have the following little graph though.

Nermal library Functions -- Green is implemented : Red is still unresolved
I have more than half of Nermal implemented. The 1Ch interrupt replacement was the big hurdle. Now it's a matter of  dropping in code until I hit another unresolved extern, implement and carry on.

I wonder if another programmer would of just ran down the Nermal and functions one by one and just implement them. I was contemplating doing that myself, but with no real API, I'm not sure how the output is handled by the game until I see it. I tell you what though, when I do figure it out, lots of those random variable names start making sense. In fact, it allows me to reuse many of them too.

I've been reading up on "Anti-patterns" as of late. I'll think I'll chat about those tomorrow.

Saturday, December 9, 2017

INT 1Ch, Interrrupted

When a PC is running in real mode, there is a timer that fires an interrupt every 55 milliseconds. By default it does nothing, and gives control back to the system. A programmer can commandeer  this interrupt, and assign it to some kind of repeatable routine. As long as it hands control back to the system, everything is fine. Other minicomputers back in the day had some kind of mechanism like this. In the case of the Nintendo Entertainment System, the 6502 interrupt line was tied the the vsync of the TV. This fired every 16.66 milliseconds. Every time the system was ready to paint a new screen the interrupt would fire and you could do things like update the music, change the graphics, and other pseudo-mutitasking stuff.

Once again, Windows does not allow you to grab hardware interrupts. Allegro does have a timer service, but you have to check a queue to see of the timer has triggered. In a perfect world, your game would have input/update/render loop in step with the framerate. Here you could check the queue every loop and see if your timer fired and then do the things you need.  ROE doesn't have a loop like that. It's more a GUI that arbitrarily updates based on player input, not on framerate.When the timer fires in this game, everything is halted no matter what the game is doing and then the interrupt does all the game updating. After that it gives control back to the game. The game itself never knew the interrupt happened. As far is it's concerned a bunch of global variables were magically changed behind the scenes.

I was stuck. I couldn't use Allegro's queues to check for a timer because ROE doesn't have a mechanism to actively do that. It's all passive. I'm trying to change as little of the game code as possible for now. Ripping everything apart and writing a new program loop is not an attractive prospect on this pass. I want to keep my wanton destruction to the Nermal driver and maybe rarely insert or comment out a single line of code if it's in the main game.

My solution:  Threads to the rescue!.

Turns out Allegro has platform-independent thread services. Well, it requires that your OS offers pthreads, which is POSIX. In the case of Windows, Allegro will use it's thread service thingy just as well.

Inter-process communication will be handled the same way as the original game.. There are global interrupt flags that is read by the interrupt routine dictating how it was supposed to update things. My thread will just hang out, come to life every 55 milliseconds, check the flags and other globals, do it's thing and go to sleep. I will need a mechanism to kill the thread when the game is exited. I've discovered that if I kill my game before the thread, I'm stuck with a zombie process that's super hard to kill.

As much as I am having fun doing this. I'll be taking a day off tomorrow and probably just muse a bit on the blog here instead.
 

Friday, December 8, 2017

Keyboard mapping

I forget there are 104 keys sometimes
Hey, guess who has two thumbs and just got finished mapping out BIOS scan codes from hex to decimal to ASCII, to ROE mappings to Allegro scan codes to ASCII and then back to ROE mappings.

Yea, this guy.

In testing my totally awesome new keyboard input system, I discovered that it was outputting totally awesome garbage. Turns out that the scan codes emitted from Allegro are not the same as the scan codes emitted by the BIOS.  How it's supposed to work is simple. ROE retrieves a BIOS scan code from the keyboard queue and processes it into ASCII. If the key doesn't have a ASCII equivalent, like a function key, it's assigned a special number. This is done with a lookup table. The problem was that I didn't understand what the BIOS was supposed to be emitting so I could get Allegro to emulate it. You see a BIOS keyboard scan code has a surprising amount of data stuffed inside it. None of it being the actual letter (glyph) you typed. It's more like what was the location of the key you interacted with and if it was being pressed (a "make" in mechanical keyboard terms)  or coming up (a "break"). It makes no distinction between a lower-case "a" or an upper case "A"  It's up to the programmer to put together the keyboard state (as it came from a mechanical device) to generate the character you want.

I had to manually map this keymap too.
For example:

BIOS scan code for the "A" key : 30
Allegro scan code for the "A" key: 01
ASCII code for capital "A" : 65
ASCII code for lowercase "a" :  97

Luckily, ROE does not use lower case letters. But keep in mind it was written before F11 and F12 was a standard thing!  But what the BIOS was actually generating on each key press was kind of an enigma. Different libraries process scan codes different ways. Is it one bye? Three byes? Two? Does it need to be bit shifted? What being shifted out? Is that important?

So the only way to figure it out was to ask the BIOS directly. But, remember, interrupt vectors are not allowed in Windows. So what do I do? Well, fire up DOS!

Hello 80x53 text, how have you been?
In my tool box I have copy of Freedos in a Virtual machine that has an oldskool compiler on it.. Well, kind of.. It's actually a DOS port of GCC that is current as of 2017. I just fired it up and coded  a few experiments with the BIOS there. From that, I got the info I needed and now I could map Allegro properly to what ROE is expecting.

After input is complete, I should be getting into the realm of dropping in functions. I'm about 80% complete with Nermal, which means I have about 90% left to go.




Thursday, December 7, 2017

Of Mice and Men

The game isn't going to look very glamorous as I continue to work on the back end. Now that I'm in the program loop proper, I have to start giving the game the event queues it's expecting. First of which is the mouse queue. The rendering of the mouse pointer is handled by Allegro all automatically. It kind of makes me feel guilty when I have replacement code that looks like this.

void ShowCursor()
{
    al_show_mouse_cursor(DISPLAY);
}


This is a little more tricky when I have functions that rely on real mode interrupt vectors. Namely INT 33h (mouse)  and INT 16h (keyboard). This is pretty much the whole input system I will have to rewrite. The way that these interrupts work was like this;  In DOS is that there used to be a table in memory that pointed to useful routines that hung out in RAM and ROM. The table was numbered 00h to FFh (0 to 255 in decimal)  It's one of the reasons why the 8088 could only do 640k of memory, even though it had enough address lines for 1 megabyte. The BIOS took up that extra 384k with things like keyboard (INT 16h) and video control (INT 10h). That's why it's was the Basic Input and Output System. DOS hung out on INT 21h and other things, like the printers used 17h for it's own.

What made these interrupts so useful was it gave DOS pseudo-mutitaksing. All you had to do was fire off in interrupt, and the whole system would come to a screeching halt as that interrupt was serviced. After it was done, the program continued, never knowing what happened. In the case of the keyboard and mouse, these interrupts managed a queue.

Underscore function, we meet again!
In the case of the keyboard, every time a key is pressed, INT 09h was fired by a physical wire (IRQ1) This paused the system, took the key, and put it into a queue. Later on, you could read back the queue of keys by calling INT 16h to see what has been pressed, or see what was pressed right now.

The mouse was the same way. Every movement of the mouse was queued, and you could ask the driver later if something moved and what the status was, or what the status is now.

Allegro has the ability to create event queues and can hawk various channels for events. You can look over the queue later. Normally, you would make one event queue and just register everything to it. Keyboard, mouse, display, sound, really anything including your own stuff. What I decided to do was create two event queues because that's what ROE kind of expects. (One for keyboard and one for mouse, as they both come in on their own channels asynchronously.) It makes it easier because I can just have the original code pull from the queue as opposed to having to write my own queue manager.

As an example I  have posed the old and new mouse event handler. They both do the same thing and return the data. Because the old handler uses some older interrupt functions, I commented what each line does. In the new handler, the code is a little more self explanatory. Truthfully speaking, it's finding elegant solutions to each of these commands I find extremely satisfying. Even better when the game just tools along with the new code, not knowing that the underpinnings have changed at all.
The new hotness

Old Mouse Handler 








Wednesday, December 6, 2017

Dispatch Loop

Using a liberal amount of dummy functions, I was able to get to the man input loop of the game. The road to get it this far required me to get the filesystem code (rules1.c) operational. For the most part that was a drop-in, but there were two things that I found worrisome.

First I had to replace some of the legacy dos library functions with the POSIX counterpart. In this case _dos_findfirst() and _dos_findnext() had to be replaced. The POSIX _findfirst() and _findnext() returns a file object, and not an int like it's dos counterparts. (The return is not needed, the game just checks if the file exists and then makes some bold assumptions about it after that point). Basically if I see any function that starts with an underscore, it raises a red flag. Functions and variables that start with an underscore are a little too chummy to the compiler/library and when switching platforms may be a headache. After fixing that, the filesystem code didn't seem to rise any intellisense errors, but we will see what happens when they start being used.

The Second worrisome thing is that the legacy ATARI and AMIGA #ifdefs have a lot of byte swap code associated with them. I'm assuming because these endianness of their CPUs. This may be an issue when I switch platforms so I'm going to leave that in and dummied out. There is a larger problem than that though. ROE makes the assumption that an int are two bytes. This breaks one of the cardinal rules of C.

Never assume the size of an int!

In my system int is 4 bytes, and I use other compilers (for 8 bit machines), where it's only one. I've already have run into this snag where I tried to read the config file and it was reading in way too many bytes. That was strange as the data I was trying to retrieve was only used three bits max, the var should of been typed as an unsigned char. I typed the misbehaving variable as __int16 (Ohh! two underscores! That's even more sticky to my platform!) I could of used int16_t, but I'm keeping the double-underscore so I can get that on my second pass.

Got the mouse going, though it doesn't pass anything to Nermal's pointer struct yet, but is has the goofy hand pointer though.



Tuesday, December 5, 2017

Title sequence is done

The credits go 100% through now. I can implement the music next, but I'll hold off and get to the game proper. Next thing is the main program loop. I do have the original MIDI used in the game. Right now I have a mp3 of the original Soundbaster audio that I'm going to shim in later. I can render what was given me through an actual wavetable synthesizer, and see if I can make it sound better. (I can also edit it down to a few triangle and square waves for fun to see how it would sound on my fantasy NES port :)  

It's a little closer now...
I know my first goal was get this to run as out of the box as possible without making any cosmetic updates. However, while I was adding a proper title and icon to the window, I corrected the age of the universe. It said it was 16 billion years and it's actually 13.82 billion years. I rounded it to 14 billion, but I bet it's going to bug me to correct it once more to 13,820,000,000 in the title sequence later.

The faders are hacky, and I had to make a tiny change to the title code to get the white fade to work right. Also most of Nermal functions I do have working are half-implemented, but it's functional and it compiles. When I start in on the main game loop, I'll see how much trouble I've gotten myself into. 

Monday, December 4, 2017

Made it though the credits!

I can pull data from the legacy .cfg file too!
I have now implemented enough bare bones functions to get my way through the credits without crashing. It's not pretty, mind you. But, now I have a good idea of how some of my stubbed functions are supposed to work.  I'm going to go back and do the faders properly, also I'm also going to re-work the graphics. I've just been doing "hard blits" and now have discovered that I need to factor in transparencies. The original graphics used 15 colors with the first channel being transparent. I'm converting the graphics from 4 bit to 32 bit and I have to clear channel 0 to transparent (It's currently black)

I was also monkeying around with the silly idea that this game would of been awesome on the original NES. The only thing really stopping it is the RAM. You can probably squeeze out 8K from a car it you tried. May not seem like much, but that's 8,192 bytes! With a little bit of packing with chars, int16s and maybe bitwise booleans you might be able to squish everything in like a Tokyo subway.

That's just me playing fantasy for now.

As I'm filling out the Nermal API, one of the neat things about MSVC intellisense is that it will look at your code and flag what externals are not implemented without even compiling it. This gives me a checklist of what functions are outright missing. From there I can at least semi-implement it or stub it out. As they are externs, the compiler doen't really care if they are actually there or not, and considers it someone else's problem. (As long as you don't try and call it) The linker, on the other hand, gives me the stink-eye every time I rebuild the solution.  I told it to ignore those warnings for now and it just yells into the void in the meantime.

I will try and do an update ~10pm at night. Here's hoping for daily updates.

Back to the faders I guess.


Sunday, December 3, 2017

Now full time!

I am now in a unique position where I can now work on this project full time and give it 100% of my attention. Progress is being made, but it's interesting to see various limitations and strengths of Allegro and Nermal as I try wrap one around the other. I ran into a rather nasty issue when Nermal made an intresting assumption about computers that isn't true nowadays.

You can't read or write directly to video memory anymore. :(

Back in the day, if you wanted to put a dot on the screen, you just put a byte in the video memory area. On the next vsync, the graphics chip would scan the memory and put your byte on the screen in the appropriate spot as a dot. On the reverse, of you wanted to know if a dot was on the screen, you would just look at video memory, and if the byte was looking for was there, then that meant the dot on the screen was there.

As Video memory was just like "normal" memory, there was nothing stopping you from copying chunks of ram in and out of the video section. That's how animation worked. You would draw in "normal" memory and then, when you wanted to show your screen, you would block copy the whole chunk into video ram. BAM! Instant picture.

PCs nowadays run in something called "protected mode" This means the operating system controls what memory you have and what you can do with it. If you try and access memory that isn't yours, thee OS will catch that exception, and then (normally) shut down your program. It doesn't give you the pointer back, pat you on the head, and ask you to be more careful next time. The default behavior is to terminate with extreme prejudice.

In Windows, video memory is an absolute no-no to touch. Allegro, however, goes though the proper channels and gives me a reasonable facsimile of video memory to play with. It's called an ALLEGRO_DISPLAY object. It's not real video memory, but close enough that Allegro can work behind the scenes to display what I want.

One caveat;

The Display object is write only. You put what you want on the canvas, push a button, and it goes on the screen in a little window. If you want to alter what is on the screen, you have to send it another drawing. If you try and read the screen, then *CRASH* Windows will shut down my naughty program.

Nermal assumes that you can read and write to video memory. It likes to be able to swap out what's there arbitrarily. This had me stuck for a bit, but I got around it by creating a "virtual screen". Now, if my virtual screen is touched in any way, there is a trigger that immediately mirrors the changes on the actual screen.

Later on I discovered that I can't Cut/Paste video data to the same canvas either. That's my current hill I'm battling on.

However, my poorly converted GIF shows that there is progress being made....(And then crashes to a white screen)

Monday, November 27, 2017

Little Steps

This took me much longer than it should have. I wanted to get the graphic fade in/fade out functions done.Because I'm not using color palettes I thought I would be cheeky and try my own implementation of fading in and out the graphics. Nermal has the following API functions. 

void FadeBlack();
void FadeIn(int mapnum);
void FadeOut();
void FadePunchIn();
void FadePunchOut(int newmap);
void FadeWhite();


I thought I would be clever and just cover whatever is being displayed with a transparent blank bitmap and then turn the opacity up with the alpha channel to fade to black/white/whatever. Turns out ROE preloads the graphics to the screen with all the colors turned off. Then it turns on the colors without page flipping. When I use my opaque bitmap method, I overwrite the graphic on the screen.

The upshot is I can fade out and fade to black, but I can't fade in because I overwrite the graphic that was there. I will need to mix the original graphic and the alpha on the fly. I'll wage that battle later as I sunk too much time into this is the first place.  I just turned off the faders for now and marked them a TODO. (CGA doesn't use them anyway).

(Also The TODOs are just reminders that the Nermal function is not all the way implemented yet. Most often it's just single argument being ignored that is used later in the game. When I come across the need to use that argument, I'll come back and refactor)

I spent the rest of my evening fleshing out some of the other required functions to get the title sequence going. Not done yet, but getting closer.

Clock timers work, which is what the title sequence is based on. The master INT 1Ch timer (used for mater event handling) does not yet, but that will be handled by an ALLEGRO_EVENT event handler.

Things will be a little slow until my "Day Job" winds down later on this week.  

Saturday, November 25, 2017

Breaking Down and Building Up.

This is me
You know that scene in Iron Man when Tony Stark starts to make the Mark II suit by virtually taking the Mark I  apart and tossing what he didn't need into a trashcan? Yea, that's how I feel. ROE has a thing going for it where it interfaced into a graphics library called "Nermal 2". (I'm assuming named after Jon's second cat in the "Garfield" comic.)

I'm basically writing a Nermal wrapper around Allegro, but there is so much legacy stuff that needs to be rifled though. Many variables are no longer needed and much of the internal Nermal API can be replaced with a one or two line Allegro equivalent. As Allegro uses 32 bit graphics (24 bit + 8 alpha), I still have to work out the color mapping. Amusingly enough, I find myself cribbing from the 4-color CGA code because of it's straightforward video memory mapping. I may also steal the CGA "color" code as EGA and VGA rely on palette cycles that I won't be using in 24 bit mode.

Also, Allegro does not have a GIF loader like what ROE used to load it's graphics Allegro's GIF loader was most likely not implemented due to patents, and when they expired Allegro became TrueColor anyway. I'll be converting the graphics to 32 bit PNG files. That said, my goal for this first pass is to get everything running as close as stock as possible. After that, then I hone the presentation a smidgen.

One of the more amusing things I ran across is what I've had to do to the prepossessor so that it can compile. In the years since 1991, C compilers go nuts if you try and use string commands that are prone to buffer overruns. For example scanf() as opposed  to sscanf(). I had to put a prepossessor directive in MSVC to allow me to use them anyway. (Which I will remove when I do my second pass). Also there are #ifdefs for three architectures in there, IBM, Amiga, and Atari. Visual Studio does not recognize "IBM" as a predefined macro, as that would mean something profoundly different nowadays, so I had to put it in  there so I have at least one valid codepath.

It loads data though, so that's cool.



Friday, November 24, 2017

Setting Up the Enviroment

My first goal was to pull the code for ROE into a modern development environment. Even though I want to use POSIX as my baseline, I decided to pick Visual Studio 2015 as my IDE. It has a few things going for it. First, some of the legacy headers originally developed for QuickC are still hanging around. Direct.h is one example (used for directory management). However, it appears that Allegro also has wrappers for filesystems too. I may have to do a pass to see if most of my POSIX stuff may have an Allegro equivalent. I may have to retarget later on.

The Allegro libraries are available via NuGet, which makes life much easier. On a previous project, I literally spent two days trying to get Allegro to work with Code::Blocks under Win10, which is my preferred IDE for GCC. Visual Studio is great, but it’s compiler has some glaring deficiencies. Two of my favorites is as follows:

1) In 2017, MSVC STILL can not process Unicode string literals. You want to see the IDE go bananas? Plop an emoji into the source. (It’s a valid Unicode character). It will stop everything telling you that there is an invalid character from the current codepage and it’s unable to save. That’s right, Microsoft still uses codepages for non-Latin text. This shouldn’t be a huge problem as I don’t plan on using Unicode (for now)


2) Microsoft absolutely, positively refuses to support C99 and above. It’s considers C a “deprecated” language. Now I know that this may seem a strange thing for whine about, as C++ is a superset of C. However there exists little things that can be irksome such as.

-Bool support (Not really needed as the ROE typedef’ed it’s own Boolean type.)

-Universal character names, for example...
 int 番号 = 1;
 ..is invalid. That's might be a good thing though.

-Variable length arrays

-Etc…

To Microsoft’s credit, they recommend that if you need to use an actual C compiler, it does have front-end support for Clang. As ROE was written in 1991, I don’t think I need to rip out half my toolchain be able to create obnoxious variable names.

Other than that, I’ve also put the code into an honest-to-goodness version control system. The Git support in 2015 is pretty sweet. I’m keeping the repo local for now, I can probably spin up a git server on a Linux kick-box I have hanging around if I feel inclined to work remotely.

One of the last things I’ve also set up is Doxygen. It basically scans the source tree and auto-generates documentation so I can follow where everything is. ROE was written before Object Orientated Programming was a mainstream thing. Globals Globals Gobals! Lots of them. Encapsulation? What’s that? Doxygen helps by giving me a local web-based source code search engine. I don’t have to put on snorkel gear and dive in to see where some pesky extern was declared at. I'm planning to merge into Doxygen most of the documenttation that was graciously given to me by OTSW. This means not only will there be living, portable code, but with plethora of inline documentation to go with it.

Looking good so far.

Thursday, November 23, 2017

Assesment

Before I given the whole Rules of Engagement project, I was given a few code files at first to gauge the feasibility of porting this old game to modern architectures. This consisted of a section of the graphics library and a bit of the tactical display code. The idea was that I needed to gauge if the game was too tied to legacy libraries or some kind of paradigm what would be simply unworkable in modern systems. I also was keen to see if I could forge it into some kind of POSIX compliance to make it a little more targetable to other platforms. The idea is that I plan to use a C game library named “Allegro” that I’ve been using on and off since the 90s for little game projects of mine. It’s in it’s 5th iteration now and still maintains much of it’s legacy DOS concepts but adapted to a little more modern and platform neutral. Many of the old DOS/Real Mode interrupt calls have been replaced with legitimate functions, but are still single-fire methods with striking similarity. This makes sense because when Allegro was young, it wrapped it’s library functions around basic DOS calls such as INT 21h(filesystem), INT 33h(mouse), and INT 10h(video).

Still seeing some of the old library headers in the ROE was kind of a nostalgic walk down memory lane. It was also quite pleasant to see that many of them can be tossed as modern systems handle the more low-level stuff automatically, or there is a simple POSIX equivalent. Here is a quick copy/paste from the graphics lib.

#include "stdio.h" <-- POSIX
#include "stdlib.h" <-- POSIX
#include "dos.h" <-- Delays and sound are Allegro - Time Functions are POSIX
#include "time.h" <-- POSIX
#include "malloc.h" <-- Allegro has malloc wrappers so that it’s platform independent
#include "graph.h" <-- Allegro handles low-level graphics
#include "string.h" <-- POSIX
#include "conio.h" <-- Text I/O interrupt wrappers - Allegro handles this now
#include "bios.h" <-- No need to make BIOS calls anymore – Allegro has equivalents
#include "xmm.h" <-- We use a Protected mode flat memory model now. No need for XMM
#include "rules.h" <-- This in turn has direct.h, this can be replaced with unistd.h (POSIX)

Real mode interrupt calls do not function in protected mode, and is DOS legacy anyway. The other thing that will make live much easier is that ROE can be a monolithic executable. For space reasons, the game was broken up into pieces called “overlays” would block swap parts of itself into memory from disk while it was running. Nowadays we have virtual memory and shared runtime libraries (.dll /.so files) that manged by the OS.

This caught my eye too…

#define DPI 6.283185308

This can now be defined as TAU and hopefully won’t break much :)

One final though as that Allegro handles bitmaps in a device independent way so gone are the legacy bitplanes of CGA/EGA/VGA of old. Also mp3s and GIF files are out of patent.

Wednesday, November 22, 2017

Introduction

The Button Pad
Star Raiders
In the very early 80s when I was around eight or nine, my family had come across the pinnacle of home video game entertainment. It was an Atari 2600, and it had with it the staple of your classic games. Of these, the one that really stood out for me was a game called “Star Raiders”. What made it so engaging was how revolutionary the interface was. Here your TV became the forward view of a star fighter. You could see stars whiz past your ship in 3D as you took the joystick and jockeyed for position to fire upon hapless aliens. What made the game truly amazing was a special button pad that came with it. Here you could open up a galaxy map, set your course, and engage hyperdrive to other sectors. While barreling at light speed to you destination, you could go back to you forward view screen and watch even more stars fly past you until you arrived. One dropping out of hyperdrive you were often greeted with an alarm klaxon and more enemy alien ships to destroy.

I remember taking all the couch cushions, pillows, and blankets I had access to and constructing an elaborate pillow-ship in front of the TV. I draped the blankets around the television, blocking out the outside world. Once ensconced within my fluffy cockpit, my imagination went wild. To me I was in space. My spaceship held the battle lines until it was ultimately destroyed. Not by the alien invaders, but by my little sister who was mad I was “hogging the TV” and wanted to watch “Land of the Lost”

I’ve been told I’m not the first person to do this.

Rules of Engagement
Fast forward about 10 years and now it’s the early 90s. To set the stage Star Trek: The Next Generation was in full swing and I came across a game called “Rules of Engagement”. Once again the box art showed you could pilot a spaceship, but this time using a snazzy touch screen interface much like the starships of Next Gen. Keep in mind this was around 1992 and touch screens being commonplace was more then 20 years off. The “touch” interface in this game was a mouse pointer that looked like a hand with fingers splayed open. (Keep in mind, the hand/index finger mouse pointer was not really standardized at this time yet.)


“Rules” was a deeply engrossing game for me. I would play on my 8088 PC and from time to time I would pretend my CRT was an actual touch screen; tapping the screen with my left hand while my right hand moved the mouse and did the actual articulation. I felt like I was in control of a starship fleet, issuing commands on my screen and battling 16 color alien races.

Jumping time once again, let’s skip to a few months ago. Somehow Rules of Engagement popped in my head I decided to see whatever happened to the company that made the game. As it would seem they are still around. The company appeared to have moved on to making communications software, and the old games they used was nowhere on their website. On a whim I decided to send an email to the generic looking sales@ email address and asked of the game even existed anymore or if anyone at the company even heard of it.

I was thinking to myself, “If they still had the source code, couldn’t it be pretty cool to port this game to a device with touch screen, or at least get it into a state where it was playable again?” You see the game itself has not fared well with time. It’s a 16-bit DOS game that will simply not execute under 64-bit windows. Graphics chips nowadays are beginning to drop lots of the old legacy video modes like the 2-bit CGA and 4-bit EGA. Heck, I’m beginning to see 8-bit VGA modes being depreciated too. Another issue is that it runs very poorly in both virtual and emulated environments. If I was a betting person, it’s most likely due to the frame rate limiter. Hedging all my bets there is probably an interrupt that’s firing that’s a bit time-sensitive and causing the system to hang on the opening credits.

This next bit of the store is going to be a bit vague as it deals with company email correspondence that I’m not sure I’m allowed to divulge. The upshot was I able to contact one of the original developers of ROE. Though what I can only guess as my winning charm, I was able to procure the original C source code and project files for the game. I pitched that the idea of porting this game to modern architectures and giving it a bit of a face lift is a good idea, and they agreed.

This blog is going to be my adventure as I port a professionally developed and sold video game from 1991 to something platform independent. Trust me, having looked behind the curtain a little, it’s time capsule of glorious treasure. Old programming philosophies came flooding back at me as I did my assessment of the code. This is going to be a fun ride I think..

Thanks again Tom, for the opportunity to do this.