net.tcp and IIS Express does not work
I've just spent time trying to rig up a test to get a working net.tcp server. Turns out that, in Visual Studio 2012 (and just about every other VS version), the IIS Express Server that one usually debugs through CANNOT support anything other than HTTPS and HTTP.
Q: Does IIS Express support non-HTTP protocols such as net.tcp or MSMQ?
A: No. IIS Express only supports HTTP and HTTPS as its protocol.
Please do not waste your time... When you hit debug on your net.tcp service, IIS Express will instantiate and you'll be thrown to your favourite web browser, staring at your root folder which is readable. You'll note that you'll also be on a port that has nothing to do with your web.config. This is because IIS Express has generated a random port and not cared one iota for your port configurations in web.config. You'll get nothing but connection refused when you try to connect to net.tcp://localhost:PORT/Service.
I was about to whinge that this tutorial on configuring a net.tcp service on IIS7 doesn't mention anything about incompatibilities with IIS Express. I suppose that one must assume by the header that the article is only for IIS7. A footnote would still be greatly appreciated for those trying to develop their code before deploying it!
If you ever want to get this to work, deploy and test your server on a real IIS instance and run from there... IIS7 preferably.
Note, if you need to debug... bring the server up, hit it with a simple query to make sure the app pool is active, and use Debug -> Attach to Process from Visual Studio. You'll find w3wp.exe way down the list with your Website's 'name' next to it. Highlight it and hit Attach to debug pesky server-side problems.
Once debugging in Visual Studio, you'll then need to open your source files (they can be in any folder, VS initially wont find them automatically) to set breakpoints. Note that exceptions will be caught in VS whilst debugging and will halt execution on IIS for all users. I have, once or twice, accidentally left the debugger attached overnight and had very angry clients in the morning with stalled connections.
FileSystemWatcher isn’t watching your files?
Quick note that just stole 2 hours of my weekend; of which I'll never get back... It seems that the FileSystemWatcher in C# it capable of watching files... yes.... but it turns out that the filters aren't as simple as you'd think.
Say you want to watch for new or changed text files in a folder? Filter = "*.txt" right? And the folder has a crapload of *.txt files? that's how it displays in Explorer? Right?
Wrong... Check out this sample code... yes, I'm holding the files open in my own source, but this is just a dirty way to show what's happening:
static void Main(string[] args) { string folder = @"d:\temp\fileWatcherFolder\"; FileSystemWatcher fsw = new FileSystemWatcher(folder, "*.txt"); fsw.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.LastAccess; fsw.Changed += fsw_Changed; fsw.EnableRaisingEvents = true; using (StreamWriter file = new StreamWriter(folder + "test5.txt")) { Console.WriteLine("["); for (int i = 0; i < 10; i++) { file.WriteLine("test line " + i); Console.WriteLine("."); Thread.Sleep(1000); } Console.WriteLine("]"); } Console.ReadKey(); } static void fsw_Changed(object sender, FileSystemEventArgs e) { Console.WriteLine(e.Name + " was changed!"); }
From above, you can see that I start a watcher on a known folder, I then start a new file and write to it. The output should always show that updates are occurring. The updates never come... and this is symptomatic of what I had with another external application that was holding files open. It also then presented a bigger issue of adding tildes to the end of the extensions.
It seems that this is an issue in .NET regarding file flushing. The application with the file handles open must flush the data out for a FileSystemWatcher to pick it up. Depending on the speed and quantity of files being flushed, the watcher may have to be customised to cope with the load. Check out the InternalBufferSize parameter.
Note in the above code, you can force a file.Flush() after the file.WriteLine, you'll get a single event. If you use file.FlushAsync() then you'll get ALL of the events! There is no threading in my example code, so the fact that async works makes sense. Of course, if you have no control over the application that is writing the files (as I didn't) then you're stuck trying your hardest to watch the files.
I still can't see my files?!
It gets better though... on some versions of windows, you may will not even see the filename with the expected extension... there may actually be a tilde at the end of the name... invisible to the naked eye. Explorer will show "test5.txt" but the watcher will see "test5.txt~"! It seems that if another application has the file open, the operating system keeps the filename with a tilde at the end until 'flushed' to disk. I haven't been able to reproduce this via the source above, using notepad to hold files open... but I know it happens. The application I had to deal with spewed files out quickly, holding them open, and the watcher only saw "txt~" extensions...
If this is the case, then you can loosen your filter to "*.txt*". Note that if you have a LOT of files being created, then this will slow down the watcher considerably. I actually recommend that you set up a second watcher, one for "*.txt" and the other for "*.txt~".
It's only when you watch the files with a filter of *.* that you'll see the crappy extension names. So when trying to debug this... set your filter as 'relaxed' as possible to capture changes and tighten it when you know what you are looking for.
Be careful! It seems others have had the same problems: FileSystemWatcher class does not fire Change events when NotifyFilters.Size is used.
Migrated WordPress database; Theme mods are gone!
This was fun... I just helped a friend migrate their database. The DB export and import was fine; just don't try and paste the SQL into the query window all at once... go to the import page on PHPMyAdmin and upload it there!
Meanwhile, once uploaded, all the custom settings on the themes (it inherited from a base theme) were lost! I watched the database and the fields were actually reset! There must have been an error parsing the data. It has to be noted that I had to change data in the database during the migration. As that I was changing from one domain to another, the hard-coded URLs needed to be migrated.
In the source database, the row in the wp_options table with key 'theme_mods_Divi' looked like this:
a:8:{ i:0;b:0;s:30:"et_pb_predefined_layouts_added";s:2:"on"; s:36:"et_pb_predefined_layouts_updated_2_0"; s:2:"on";s:16:"background_color";s:6:"ffffff"; s:49:"http://old_domain.com/images/background_image.jpg";s:17:"background_repeat"; }
I don't know what the first a:8 stands for, but all the s values inside mean string, followed by the length, then the data.
I actually, as a migration task, had to change the strings from one URL to another (as part of the domain shift.) Turns out that when you do this, if the URLs being replaced aren't the exact length, then the string lengths will change .... of course, this is obvious now .... WordPress was then trying to parse the values and overrunning/underrunning the values. In the end it just gives up and resets the custom mods.
So, when changing the strings, you need to change something like:
s:49:"http://old_domain.com/images/background_image.jpg";
to:
s:62:"http://google_is_the_best.com/images/zebra_in_a_tree_image.jpg";
...the key being that you've adjusted the length to the new variable.
Once this is done: drop all the tables, re-import them via the script and WordPress should then load the mods correctly! I hope this prevents at least one other person from wasting the 2 hours that I just did. Never lose your custom theme settings/mods when migrating ever again!
A quick note on interfacing with JSON services via C#
I'm sure there are 100s of ways to manually create classes for JSON objects and then decipher them upon web-service response, but I've just stumbled across a fantastic site called 'json 2 csharp' that creates the classes for you. Just slap in your response (try to get a fully-fleshed out one with as fewer nulls as possible) and it'll generate the class structure.
You can then use the NewtonSoft JsonConvert deserialiser to populate it.
An example
Here's a link: jsontest 'date' example. It produces the following response:
{ "time": "05:13:02 AM", "milliseconds_since_epoch": 1425532382121, "date": "03-05-2015" }
From here, you just copy the entire response and paste it into the text field on the json2csharp site.
Hit 'Generate' and the site will spit out the following:
public class RootObject //rename this! { public string time { get; set; } public long milliseconds_since_epoch { get; set; } public string date { get; set; } }
Note that 'RootObject' is a little boring... rename it to 'DateResponse'
Add a helper library to your code to easily pull JSON responses (and POST):
public static class JSONUtilities { public static string GetJSON(string url) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); try { WebResponse response = request.GetResponse(); using (Stream responseStream = response.GetResponseStream()) { StreamReader reader = new StreamReader(responseStream, Encoding.UTF8); return reader.ReadToEnd(); } } catch (WebException ex) { WebResponse errorResponse = ex.Response; using (Stream responseStream = errorResponse.GetResponseStream()) { StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8")); Console.WriteLine(reader.ReadToEnd()); } throw; } } public static Tuple<HttpStatusCode, String> PostJSON(string url, string jsonContent) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding(); Byte[] byteArray = encoding.GetBytes(jsonContent); request.ContentLength = byteArray.Length; request.ContentType = @"application/json"; using (Stream dataStream = request.GetRequestStream()) { dataStream.Write(byteArray, 0, byteArray.Length); } long length = 0; try { using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { length = response.ContentLength; using (var reader = new System.IO.StreamReader(response.GetResponseStream(), encoding)) { return new Tuple<HttpStatusCode, string>(response.StatusCode, reader.ReadToEnd()); } } } catch (WebException ex) { // Log exception and throw as for GET example above Console.WriteLine("ERROR: " + ex.Message); throw ex; } } }
And now you can bring it all together:
private bool Get() { var result = JSONUtilities.GetJSON("http://date.jsontest.com/"); var dateResponse = JsonConvert.DeserializeObject<DateResponse>(result); Console.WriteLine("Got Response: " + dateResponse.date + " [" + dateResponse.time + "]"); }
Too easy!
Misfiring AW11 4AGZE Supercharger
Just got my car back from the mechanic... he does a really good job, but I'll leave the name out of it for all intents and purposes.
Turns out I'd done too much off-roading in my poor little MR2 and had filled the engine bay with dirt/dust/grime. Mechanic took the liberty to wash it all out... looks great!
Unfortunately, it didn't run so good anymore.
Symptom
Upon acceleration, the tacho would get to 1,500rpm and then it felt like the rev-limiter kicked in. The engine would burst about 100rpm, then drop back to 1,500, then back up and down, on and off.
It felt terrible to drive... if you timed it right, you could stop accelerating at 1,459rpm then gun it and it'd jump to 2,000rpm and continue... BUT THE SUPERCHARGER LIGHT STAYED OFF.
Something had gotten into the wiring and was going haywire. Stopped the car, got a torch and checked everything. All was connected apart from a cracked up vacuum tube. Thought it was the culprit, but upon sealing the connection it was still failing.
I could see the supercharger clutch engaging when I feathered the throttle, but it would pop back out just as quick when the engine dropped revs.
So... resorted to Google and found this: http://forums.club4ag.com/zerothread?id=89527
Reading the second post, the user indicates that the TPS was causing his engine to start/fail/start/fail... same symptom as mine.
So, went back to the engine and popped off the TPS connector.
FULL OF WATER.
Solution
Dried it up and ... the MR2 is back to bat-out-of-hell status... I love my little green Supercharger light!
I'm only posting this so that other people can find this information easier.
OpenLCB: Controlling Your Model Railroad
It's been a while since anything remotely home-brew/electronic for model railways has appeared on this blog... but this is about to change. It's now time to try a third method of electronic control after previous attempts of controlling via DCC Boosters and then Arduino Microprocessors.
Don E. Goodman-Wilson, who you would've seen commenting on a few of my posts here regarding DCC and Arduino, has gone all-out and started production of some pretty amazing technology. He's started a company called railstars which is currently providing DCC boosters, central units and throttles. Not only are these perfectly marketed and designed, they also now incorporate a new concept known as OpenLCB.
OpenLCB
OpenLCB is an initiative by the OpenLCB team to define a network (protocol and required hardware) to control pretty much everything on your model railway. The end result is layout control and automation which is easy to install, configure and extend. As of the 9th of February 2012, there are motions for NMRA to work closely with the OpenLCB project in a venture named NMRAnet... stay tuned for more information on that!
It should be noted that the OpenLCB team is still in the early stages of design work and, although prototypes have been built and tested, there is a lot of work to do to get final products to market.
The basic concept consists of a control bus with nodes located along a network bus, terminated at each end. Each node has it's own processor that can create and respond to events. Events can be anything from controlling accessories and trains on your layout to sending informational messages to remote displays. With this, you can have a node controlling points around your layout, a node controlling trains indirectly via DCC and a final node acting as a control panel with buttons and switches configured to send specific events.
In case you were wondering, the OpenLCB venture has no intention to interact with DCC. Other parties, such as Don with his railstars products, are currently bringing DCC in as an option, but do not intend to outright replace it! Don's efforts with railstars OpenLCB components will allow DCC commands to be transmitted over the OpenLCB protocol allowing each node on the network to respond appropriately. A lot of opportunities will open up with this as you will then be able to use the OpenLCB network to transmit DCC information, allowing completely separate DCC blocks on your layout.
You can find a lot more information about OpenLCB here at their 'First Look' page.
I want to control my DC Layout?
There are currently no nodes designed for use as standard DC throttles; fortunately, controlling DC layouts via the OpenLCB bus should be completely feasible! As per my previous articles on Arduino control of model railways, a simple PWM motor controller is all that is required to supply a model railway with the appropriate power levels. Since OpenLCB is also very compatible with Arduino, it would also therefore be quite practical to transform an Arduino+Motor Controller into an OpenLCB 'node'. This would mean that any 'controller node' could then send 'events' to the 'pwm node' which would then act accordingly... be that 'supply 50% throttle'.
I'd spoken to Don on this concept and he indicated that the OpenLCB key concept was to control 'Trains' rather than 'Blocks'. This is the same as DCC... as you supply the same power+data to all rails on your layout and the locomotives respond only when called. The issue then with DC control is that trains, sitting in blocks, will respond as soon as you apply power. One answer would be to have detection circuits around the layout which would follow movement and assume where each train was. Another would be to have the 'pwm nodes' act simply as 'accessories' that supply power to each block. This concept is still under discussion.
What's Next...
I really do want to get into development and testing of the OpenLCB system. Fortunately the whole lot is open source and one can even use standard Arduinos as 'nodes' based on the code available in the OpenLCB repository. Once I have enough components I'll be building and connecting a few nodes to test the communications functionality. After that I'll go ahead and design a block-controller and pwm node. At the least this will allow me to prototype some ideas whilst controlling my latest n-scale-in-a-table layout.
The OpenLCB project will also shortly be offering a 'dev kit' to parties interested in developing for the OpenLCB project. It will have enough components to create a local network able to control a layout. You can find out more information on the Japanese Modelling & Japan Rail Enthusiasts Forum.
I intend on keeping everyone updated as I tackle the concept of DC in the newly formed OpenLCB realm.
Ruby on Rails – Disturbing Errors
Excuse my efforts in going slightly off topic in an attempt to help out anyone else who may have struck this issue.
I'd been given a good challenge by a friend: mimic an install of ruby on rails on a local VM. I'd never worked with ruby before and google'd for a tutorial. Before I knew it I had Turnkey Linux's Ruby Appliance up and running on Oracle's Virtual Box on 64-Bit Windows 7.
I wont go in to deployment steps here... it's all covered on the web. The basic concepts were to point an apache virtual host at a new directory in /var/www and then browse to the application. To my delight it started, throwing an error. I hadn't even configured a thing yet, so how could I expect it to run?
After configuring the Facebook connector and the database connection the site came up and I could log in and muck around. It wasn't long until I hit the following error. It was only on a specific data class that extended the ActiveRecord interface and only when checking if the data was valid or trying to save it. I could happily create the class and change attributes...
Wrong number of arguments (1 of 0)
What the hell... I hadn't seen ruby exceptions before, so I started to dig. The RAILS_ENV environment variable was set to 'development' and so there was a 'development.log' file sitting in the 'log' directory inside the application. This provided a stack trace and a few other bits and pieces.
After a lot of code commenting and uncommenting I narrowed it down to the 'save' method of the specific data item class. This was inherited from the ActiveRecord::base class and I had no say in what it did or how it did it. I did know that it was expecting no arguments, so that's where the '0' came from in the error, but I was also not passing it any arguments, so where the hell did the '1' come from!?!?!
I then tried the 'valid?' call as well... same result.
I chose to override the 'save' function in the model file by using a pass through... all of a sudden the code continued (after hours of exceptions) and the next related table row creation had a null foreign key for the item that should have been saved. It turns out that by creating a pass through I bypassed the entire 'save' method and therefore didn't attempt to write anything to the db. As soon as I tried to use the base 'save'I got the same error but now in the model file.
I was stuck... so I tried to bring up the debugger via the mini WEBrick server. It, unfortunately, didn't give me any more information than what the development.log file had provided.
Next I tried downgrading and upgrading ruby and rails. I was impressed with the 'gem' system... but nothing helped.
The final step was to google more and more... I had already tried gutting my model implementation (there was extra code in the for other tasks) but none of this changed the inability to call 'save'. All of a sudden one google search came across someone mentioning something about a 'reserved word'.... I google'd further.
Reserved Words
It seems that Ruby has a few words that you MUST NOT GO NEAR if you want your code to work. The main issue is that, when you do, you'll have no idea what you have done as the error message that results has NOTHING TO DO WITH the actual problem. It turns out that after browsing to a post by someone with a similar problem I saw the comment stating that they had used the word 'notify' for a column name.
... so had the original developer of the code I had worked on ...
There was no response to the post that pointed this out in the previous link, so that either means the original author was too ashamed and it was the correct fix, or they found the real fix and never got back to this.
Either way, I corrected my database by changing 'notify' to 'notify_opp' and ... fkn presto ... 10 hours of debugging resulted in a SUCCESS!
Further information on these magical reserved creatures
Ok, the fun part... in hind-sight I've done a little research and there are sites indicating what 'words' are 'reserved' for ruby. Unfortunately, not all of them say that 'notify' is!
- Ruby QuickRef [does not]
- Ruby's reserved words [does not]
- Ruby on Rails - ReservedWords [does]
References:
- [Problem] wrong number of arguments (1 for 0)
- Wrong number of arguments (0 for 1) on notifiy method in Ruby on Rails
I imagine the title should have been '(1 of 0)' ... but it is still the same issue - Problem saving model in Rails
- rails forum: wrong number of arguments error ... same error, different reserved word.
Conclusion
Be bloody careful with errors from ruby that don't make sense and don't spend too long digging in to a dead end.
Be diligent with your google searches too.
I spent a lot of time debugging this and I hope this post helps out others in the same scenario.
Commandos – Behind Enemy Lines Resolution Fix
Unofficial STEAM support:
Scroll to the bottom and find the comment by Tonelotto with instructions on how to get it going.
You can also use this patch to carry out the Locale hack described here.
Skip straight to the bottom of this post if you just want the application!
An Introduction to the game
A friend and I recently stumbled across the Commandos Ammo Pack ('Behind Enemy Lines' and it's expansion pack 'Beyond The Call Of Duty') at Good Old Games.com and we just couldn't resist downloading it. It did cost US$5.99, but that's absolutely chicken feed when compared to the awesomness of this game.
It's an old game, created in 1999, and could handle resolutions up to 1024x768 for single player; but for multiplayer the resolution was fixed at 640x480. I google'd around a little and saw that one person on a forum had created the Mysoft - Commandos Loader v0.8 which seemed to hoist the application in to memory and then hacked around with variables. I wasn't sure this was the best method and had the main Commandos EXE in IDA Free before too long.
I'd read that it used DirectDraw/3D and started searching for the appropriate functions. Before long I had the AdjustWindowRectEx, DirectDrawCreate and other functions under the microscope. I then opened the EXE up in OllyDbg and started slapping breakpoints everywhere. Before long I'd noticed the pattern:
push 10h push 1E0h push 280h
This seemed to be popping up everywhere and co-incidently 280h x 1E0h = 640x480 pixels... the default for the game. I then found code that set the resolution based on those shown in the video settings menu and then the game was doing what I told it.
After a little more google'ing I found that someone else had already gotten to this point. Ferdinand had the hacks there to change the resolutions, but did not have the final piece to ensure that re-loading the game brought the resolution back.
After a little more disassembling I found that the resolution was being loaded at startup from a file on disk... this turned out to be "COMANDOS.CFG" in My Documents. The exact line from the config was:
.SIZE [ .INITSIZE 2 ]
From the config it was obvious that the game was using 'index 2' from the resolution list. Of course, it also meant that it knew how to decipher that '2' to a real resolution from the list in the code. After a little forward and reverse searching from the file loading to the resolution setting I came to the switch statement in the code which had the values hard-coded. I now had 3 points per resolution setting in the code that needed to be changed if I was to write my own utility.
Commandos Resolution Hack Alpha 1
I hadn't liked anything that was already available to do this and so I chose to wrote my own. The application loaded the EXE into memory, read out the resolutions stored, audited that they were all in sync and then allowed the user to select a new resolution per slot. If the resolutions weren't the same then you would get a warning, but this would have been corrected on the next resolution hack.
This worked fine, but I found it pointless to specify four separate resolutions when you only really needed to specify one. I was more in for the challenge of allowing all four to change, rather than the practicality.
Testing and more bugs
So, it all worked... I then closed the game, re-opened it and found that it loaded up at 1024x768 instead of the 1680x1050 resolution I had set. I closed it again and looked at the configuration file; the setting had indeed changed back to '2' instead of '4'... but I hadn't touched it! I then loaded the game again and it was back to 1680x1050... closing and opening brought it back to 1024x768... the flip-flop continued.
So... what did this seem to mean? I had overlooked the storage of the resolution configuration. If the indexed resolution was read from the file, then it would have to be written back as an index. I went back in to the disassembler and searched for anything relating to writing 'SIZE' into the configuration file. The logic in the game was then obvious: it carried out an "if less than X but greater than Y" across the 'stock' resolutions and then stored the relevant index. This complicated my approach and confirmed that I really should only bother adjusting the 'fourth' resolution in the list. There was no point allowing the user to re-order the resolutions as this code then wouldn't work. The fourth resolution would need to be the only one customisable and the value must be greater than the third resolution at 800x600.
Commandos Resolution Hack Alpha 2
So, with this in mind, I wound the application down to just editing one resolution that had to be higher than 800x600. This meant that the internal configuration saving would work and the user would just have to select the final resolution in the list. Note that this only affected single player... the multi player resolution would still be a separate setting.
Everything was now working great... except the drawing issues above 1024 resolutions...
Drawing bugs
So, the game obviously wasn't meant to be played with a horizontal resolution greater than 1024 pixels; rendering artifacts started appearing when higher resolutions were used. Fortunately, the game is quite dynamic when it comes to rendering the screen and menus. Trawling through the code I could see that it was trying to find a BMP that matched the resolution, even using the resolution as the file name. Ferdinand had also worked this out and even has a list of assets downloadable for higher resolutions.
Commandos stores all of its graphical assets in a file named 'WARGAME.DIR' and references this when the game loads. I started looking into modifying this file via my program but realised it would be wuite a task to decipher and re-pack. Fortunately, some clever fellows across the world have created the necessary tools to extract these files. DirExtractor allows us to expand the DIR files and, once in the Commandos directory, the game itself will actually use the extracted versions if you remove the WARGAME.DIR file. This then meant that I could use my app to call DirExtractor, extract the files and then modify them where required to ease the majority of graphical glitches.
Required Graphical Modifications
- A single change to the fourth resolution string in DATOS\MISIONES\GLOBAL.STR to whatever the custom resolution has been set to. This can be found by searching for the token OVI4 and then replacing the string following.
- The creation of the menu background. This has to be a Bitmap file named MENU####.BMP where the #### is the horizontal resolution of the screen.
- Build a WAD file for the game-play interface. This WAD is named via the resolution (i.e. 1024X768.WAD) and contains values that tell the game how to render the interface. I created a one-size-fits-all file that ensures that the graphics are wide/long enough for the screen resolutions (max 1920x1920) and the application simply renames the file and ensures that it is available to the game.
A final glitch
There was only one drawing issue remaining after this... any resolution over 1400 meant that maps thinner than the overall monitor width would not re-draw the areas that they could not cover. You can see this in the following screen shots.
Fortunately you can press '+' and '-' in-game to zoom in and out. What this meant was that the user could stop the map from clipping by adjusting the zoom. I took this as a suitable workaround at the time.
Smeared resolution?
It seems that some laptop resolutions are a little out-of-whack. I previously had a Samsung Ultranote with resolution of 1366x768, but windows reported that it could also run at a resolution of 1360x768.
It turns out that if you choose the wrong one (although it may seem the right one if that's your current windows resolution) that you'll get the following display:
Simple fix: Try another resolution... it'll work eventually!
And you thought it was going to be this easy?
So, I had the app working great for the modification of the GOG version of the EXE. It turns out that there are many more versions in the wild. It also gets worse as there is another patch here that fixes up a whole lot of other issues in the game. Fortunately it seems that the EXE from the above link is the exact same as the EXE from GOG? Either way, I've tested it and my hack works on it perfectly.
Due to the above, I started a list of EXEs for the game and then began deciphering them (as I knew the basic items to change) to allow my application to work with them.
Items in bold are those that come from GOG.com.
Game | Version | File Size | Supported |
---|---|---|---|
Commandos - BEL Demo | 2,452,992 bytes | Works.. | |
Commandos - BEL German | v1.0 | 2,469,376 bytes | Works, Asks for CD (Language issues, I'd imagine) |
Commandos - BEL Spanish | v1.0 | 2,469,376 bytes | Works? |
Commandos - BEL Spanish | v1.05 | 2,469,888 bytes | Works? |
Commandos - BTCOD Spanish | ? | 2,696,600 bytes | Works? |
'Sold Out' | v1.1 | 2,479,104 bytes | Works fine. Speed issues with game (known issue) |
GOG.com Ammo Pack | v1.1 | 3,715,072 bytes | Works perfectly! |
Commandos Ultimate Fix | v1.1 | 3,715,072 bytes | Works perfectly! |
Commandos - Beyond the call of duty | ? | 3,133,440 bytes | Works perfectly! |
Commandos - BEL Russian | ? | 2,470,400 bytes | Works fine. Speed issues with game (known issue) |
Commandos - BTCOD Russian | ? | 2,968,576 bytes | Works fine. Speed issues with game (known issue) |
Commandos - SINP | v2.3 | 2,482,688 bytes | Works perfectly. |
Commandos - SINP Chinese | v2.3 | 2,313,216 bytes | Does not write out chosen resolution to configuration file. You should only change the resolution via this hack! |
My application was then built to determine the EXE via file size (of course, this isn't fool-proof) and then hack appropriately.
Commandos - Beyond The Call Of Duty
So, this was just an update to the main game... turns out the code was slightly different, but still workable with my current program structure. After about 6 hours debugging all was working! Enjoy!
Commandos Hack v1.2
The final release contains the following features:
- Support for all versions known above. (Note that the Demo and German versions don't actually save their configs to disk; we therefore hack the initial startup resolution.)
- Resolution list options based on monitor capabilities.
- Both EXE and WARGAME.DIR are backed up.
- A one-size-fits-all menu background has been included.
- German file encoding is preserved when the text is changed.
- Resolution menu text shows the selected resolution.
- Compatibility mode now checked to allow proper resolution and disable scaling.
- The Locale hack from here has also been added.
Download the application here.
And you can also download the .NET source code here.
Meanwhile, if you got a lot out of this app, then feel free to donate!
And that's a wrap... go use every pixel your monitor can produce and play the game!
Creating two more MAME Controllers
I've since realised that, after building the original two MAME Arcade Controllers, I've needed two more to really re-live the old classic games. I suppose one more would've been OK for games like Rampage, but TMNT, Simpsons Arcade and Sunset Riders need all four players... so... the following lists the relevant information to build controllers 3 and 4.
Sunset Riders
It turns out F12 saves snapshots of MAME games... so I couldn't resist...
Key Mapping
Below lists the mapping for the two new controllers to be created. I went ahead and used the default keys from MAME plus whatever else was free...
NOTE: Out-of-the-box MAME does not specify buttons 4,5,6 for Players 3 and 4! You can set these very easily in the 'default' config by using the basic MAME GUI (run mame.exe without any command line options)...
Button | Player 3 | Pins | Player 4 | Pins |
---|---|---|---|---|
Joy UP | I | 6, 22 | Numpad 8 | 8, 22 |
Joy LEFT | J | 7, 21 | Numpad 4 | 4, 23 |
Joy DOWN | K | 6, 21 | Numpad 2 | 8, 21 |
Joy RIGHT | L | 5, 21 | Numpad 6 | 14, 23 |
Button 1 | R-CTRL | 13, 20 | Numpad 0 | 8, 24 |
Button 2 | R-SHIFT | 10, 20 | Numpad . | 14, 24 |
Button 3 | ENTER | 1, 20 | Numpad ENTER | 12, 21 |
Button 4 | / | 3, 26 | Numpad + | 12, 22 |
Button 5 | . | 5, 20 | Numpad - | 12, 26 |
Button 6 | , | 6, 20 | Numpad * | 12, 20 |
Player Button | 3 | 16, 19 | 4 | 11, 19 |
Insert Coin | 7 | 7, 19 | 8 | 6, 19 |
Building the other two controllers
I bought cheaper controls for these two... but to no real benefit. I did save AUD$10, but I don't really like the button microswitches. The buttons aren't as tall and they do look cheaper. They're also a lot less 'clickier'. On the positive side: the short-stick joysticks feel nicer during game-play and are a lot more sensitive.
The build of these two followed the exact same path as the previous two (see the previous post) using cheap Microsoft Keyboards. It turns out that they were now a different colour (White vs. Black) and I decided to replace my current keyboards on other computers with the new ones. I therefore used a standard black MS Keyboard for Player 3 and a 'Microsoft Comfort Curve' for Player 4.
The MS Comfort Curve had a completely different matrix and the circuit board inside was much easier to solder to. Either way, the process was still the same in determining the pins and then wiring everything up. Testing was made a lot easier as well as I found the below testing applications to work out exactly what I'd messed up :)
After running out of solder and then later butane I got them together and we gave them a go. All went well until Players 1 and 4 hit magical key combinations... It seems that, although the keyboards are separate devices, you can still produce an ALT-ENTER or CTRL-ALT-DEL by having each player pressing each of the keys separately. This has since been remedied in the final section of this post!
Testing your new creation
I found out that Windows 7 (and possibly Windows Vista?) but not Windows XP has the mskey.exe keyboard test application (I have since found out that you can Download the Intellisense Software here which contains this application.) It came in very handy until I plugged 12v into a USB hub and cooked the HDD in my TV-pc (luckily only the HD, the PSU managed to protect everything else!) and lost my Windows 7 install. For Windows XP systems (of which all my computers are now back to) I downloaded and used the PassMark KeyboardTest application. At first, the Google search result made the application look like a typing tutor, but after downloading I realised it was exactly what I needed.
MAME Configuration
So, as previously mentioned, MAME doesn't specify Buttons 4,5,6 for Players 3 and 4 by default. I suppose there aren't many games that have more than 3 buttons for all four players? I can't think of any... but my memory is quite hazy as to what 4-player games Combat Zone had back at Tuggeranong Hyperdome.
Either way, we've specified them above and we also need to make sure they map to the correct player/keys in MAME. Here's a snippet for Player 4 in my default.cfg:
<input> <port type="P4_JOYSTICKRIGHT_UP"> <newseq type="standard">KEYCODE_6PAD KEYCODE_8PAD</newseq> </port> <port type="P4_JOYSTICKRIGHT_DOWN"> <newseq type="standard">KEYCODE_2PAD KEYCODE_6PAD</newseq> </port> <port type="P4_JOYSTICKLEFT_UP"> <newseq type="standard">KEYCODE_4PAD KEYCODE_8PAD</newseq> </port> <port type="P4_JOYSTICKLEFT_DOWN"> <newseq type="standard">KEYCODE_2PAD KEYCODE_4PAD</newseq> </port> <port type="P4_BUTTON4"> <newseq type="standard">KEYCODE_PLUSPAD</newseq> </port> <port type="P4_BUTTON5"> <newseq type="standard">KEYCODE_MINUSPAD</newseq> </port> <port type="P4_BUTTON6"> <newseq type="standard">KEYCODE_ASTERISK</newseq> </port> </input>
As you can see, the default.cfg only adds in controls we have overridden... the others must be hard-coded into mame.exe. Drop the configuration file in to your mame/cfg directory (note that you may want to check your file first as you could have other customisations!) and then you'll have the appropriate settings ready to go!
Diagonals and 4-Way Joysticks
Right, I couldn't work out why I couldn't get 'Steve' in 'Sunset Riders' to shoot on the diagonal... usually this was carried out by holding down the Up and Left (or Right) keys on the Keyboard, but it wasn't working. I scoured the internet and initially thought it was an issue with the way I'd wired up the joysticks.
It turns out that MAME has added in the ability to assign a separate key for the diagonal movements. This is great if you have an 8-way Joystick with actual individual microswitches on the diagonals, but I have a 4-way and I cannot, without logic circuits, wire up another key to activate when two of the direction microswitches are closed. I did actually start thinking of logical OR/AND gates to fire the specific keys when the direction goes diagonal, but this would require re-work on the sealed controllers. :)
So, I went in to MAME and then mashed the keyboard on the configuration screen. It turns out that you can assign multiple keys to a direction. This then made life easy... I would make Player 1's "Up/Left" key 'Up' + 'Left' instead of the 'I' key on the keyboard.
After testing this new configuration I realised it wasn't actually MAME that was the problem! It turns out that there was an actual physical issue with the initial two joysticks I bought when compared to the second two...
Arcade Joystick differences
So, the diagonals worked on the new joysticks I bought... they seemed to be a lot happier at pressing two directions at once. Unfortunately, the original joysticks only really wanted to go one way at once... After a little investigation it turns out that the plastic spacer/washer that slides onto the joystick stem was not wide enough (circumference-wise) to actually activate two microswitches at once. I'd also misplaced the original 'extra' components from the intial build and therefore didn't know if wider spacers existed? Either way, I had to make the spacers fatter to ensure that diagonal movements could be easily made.
In the end I cheated and used duct tape around the spacer at the bottom of the stick to make it's circumference wider. This meant it was more keen to press two microswitches at once and the world was a happier place!
The sticky-tape-fix was then tested for Player 1 and worked. I then did the same for Player 2 but had the controller back open in seconds after playing Bomberman as it turns out it was now too happy to go diagonal instead of 4-Way. Removing just over one layer of tape from the spacer on the joystick balanced out the circumference vs. microswitch equation and made the joystick much more responsive. Your mileage will vary with how much tape is required based on the sensitivity of the microswitches and how much travel/space you have between them and the center stick.
The verdict: Windows short-cut keys kill gameplay
The next step was to reconfigure any keys on the controllers to not use any modifier key (CTRL,ALT,SHIFT,ENTER) so as to not activate shortcuts during gameplay. When Player 1 and Player 4 pressed certain buttons (specifically ALT-ENTER) the MAME window would restore and, of course, it was possible that all four players could do a perfectly orchestrated CTRL-ALT-DEL and throw Windows XP to the Task Manager.
To do this I had to re-solder buttons on Controllers 1, 2, 3 and 4 to the nearest free keyboard button. Fortunately the Numpad had more than enough nearby keys free and there are still letters of the alphabet unused near Player 1's keys. The layout of buttons on the keyboard did not have to make sense to a human user and so any free buttons were used if the wiring was easier.
The Final Re-Mapping
So, in the end I re-mapped the modifier keys and also removed the duplicates between Players 2 and 3. Edits are in bold... NOTE: You must UNMAP 'T' from the 'Other Controls' area otherwise when Player 1 hits Button 2 you may receive a 'Tilt' message and game restart.
Button | Player 1 | Pins | Player 2 | Pins |
---|---|---|---|---|
Joy UP | UP | 12, 24 | R | 11, 22 |
Joy LEFT | LEFT | 12, 26 | D | 16, 21 |
Joy DOWN | DOWN | 4, 26 | F | 11, 21 |
Joy RIGHT | RIGHT | 8, 26 | G | 11, 24 |
Button 1 | E | 16, 22 | A | 18, 21 |
Button 2 | T | 11, 23 | S | 17, 24 |
Button 3 | C | 16, 20 | Q | 18, 22 |
Button 4 | V | 11, 20 | W | 17, 23 |
Button 5 | Z | 18, 20 | U | 7, 22 |
Button 6 | X | 17, 20 | O | 5, 22 |
Player Button | 1 | 18, 19 | 2 | 17, 19 |
Insert Coin | 5 | 11, 25 | 6 | 7, 25 |
Button | Player 3 | Pins | Player 4 | Pins |
Joy UP | I | 6, 22 | Numpad 8 | 8, 22 |
Joy LEFT | K | 6, 21 | Numpad 4 | 4, 23 |
Joy DOWN | J | 7, 21 | Numpad 2 | 8, 21 |
Joy RIGHT | L | 5, 21 | Numpad 6 | 14, 23 |
Button 1 | B | 11, 26 | Numpad 0 | 8, 24 |
Button 2 | N | 7, 26 | Numpad . | 14, 24 |
Button 3 | M | 7, 20 | Numpad / | 8, 20 |
Button 4 | / | 3, 26 | Numpad + | 12, 22 |
Button 5 | . | 5, 20 | Numpad - | 12, 26 |
Button 6 | , | 6, 20 | Numpad * | 12, 20 |
Player Button | 3 | 16, 19 | 4 | 11, 19 |
Insert Coin | 7 | 7, 19 | 8 | 6, 19 |
This configuration overwrites the diagonals for Player 1 and adds/corrects all of the other mappings listed above.
And this is now to be tested in gameplay... I've done the re-wiring and have tested individually but have done no actual thrashing with MAME.
The End
And that's that... it was enough fun playing with Player 1 and 4 making sure not to mash the same buttons at the same time... but it should be a lot better now once I organise the beer and the people to play... will see how we go!