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)