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 |
Download the configuration file here.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!
Creating your own MAME Arcade Controllers
Right, now for something completely different... The following article goes out to all those 80s kids who remember that familiar clicking sound of real mechanical microswitches. We all spent our pocketmoney on Bubble Bobble, Snow Bros, Rampage, Street Fighter; but now you don't have to. Just install MAME and build the following controllers...
Here's the photo album of the construction of the controllers...
Note, before starting this, you should really just skip the keyboard hacking and buy one of these.
Also, for a LOT of information on doing this, visit Arcade Controls.
Initial thinking...
All peripherals for a computer need to connect via an I/O port. Although there are quite a few available on most modern machines, the one we will use is USB. I've chosen this port because they will be around for decades and the old style Serial, LPT and Gameports have pretty much already been phased out.
Now, there are many options once we choose USB:
- My Arduino to accept all the inputs and feed them to a computer...
- One of the many off-the-shelf 'keyboard' emulators...
- or I could just rip open a cheap USB Keyboard and wire up the keys...
From the above, the cheapest method is to rip open a keyboard. Officeworks here in Australia was selling the Microsoft Wired Keyboard 600 for AUD$11.97 and I couldn't resist.
One big question here was cabling. Once I'd hacked a keyboard apart and wired up one controller.. would I then use other keys from that first keyboard and run a cable to the second controller? I looked at the price of data cabling and realised it was cheaper to buy another USB keyboard than it was to rig up a sophisticated central box that both controllers ran to.
I therefore bought 2 USB keyboards.
Now, there is an issue here... I will be 'emulating' keyboard buttons presses when the joystick buttons are pressed. Since once computer can accept multiple different keypresses at once, this will work, but it cannot distinguish multiple presses of the same letter/key from different keyboards (i.e. if the 'A' key is pressed from two different devices.) This means that the second controller will have to be mapped to a different set of keys... pretty obvious, yes?
Update/Note that buttons 5 and 6 for Player 2 aren't set by default... I've set these to I and K as they were free... for some reasons I didn't check Player 3 and 4 controls first and this is a direct conflict with Player 3 directional keys! So, you can use the below but be careful... in my this blog post I've remapped them to U and O respectively.
| Button | Keymapping 1 | Pins | Keymapping 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 | L-CTRL | 13, 25 | A | 18, 21 |
| Button 2 | L-ALT | 9, 24 | S | 17, 24 |
| Button 3 | SPACE | 1, 26 | Q | 18, 22 |
| Button 4 | L-SHIFT | 10, 23 | W | 17, 23 |
| Button 5 | Z | 18, 20 | I | 6, 22 |
| Button 6 | X | 17, 20 | K | 6, 21 |
| Player Button | 1 | 18, 19 | 2 | 17, 19 |
| Insert Coin | 5 | 11, 25 | 6 | 7, 25 |
Hardware
So, from the above, you'll need 2 USB keyboards for the PC interface. You'll then need the actual arcade joysticks and controls. Below is the kit I found recently on eBay for around AUD$50. I'm sure you could get it cheaper; my purchase was on a very large impulse and I had a few regrets afterwards as there were better joysticks on offer for the same price.
The buttons themselves are exactly what you'd find in real arcade machines... the microswitches make their motion feel perfect as well.
So, with all the components, it's now time to get it connected together. Start by ripping open the keyboard...
Decoding a USB Keyboard
Keyboards are built on a matrix. Just like the LED project previously with the Arduino, each button on a keyboard is connected to one row and one column of the circuit board inside. The circuit board will scan each row and column hundreds of times a second to check which buttons are pressed and then report this back to the computer.
As you can see above, the controller inside the keyboard is not soldered to the matrix. This is great news as I was expecting to have had to solder to fiddly little wires instead of the nice connection pads that you can see.
Firstly I pulled out the multimeter and started decoding the keys I'd need to use. To do this I put one probe on the pad circle of the key and I then ran the other probe across the connection to see which wire it connected to... I then recorded all of my findings:
The data I gathered is in the table above. Each key has two pins and these map from left to right on the controller connection seen above. I have only decoded the keys that I need, but it's easy enough to work out the rest when you have an opened keyboard in front of you.
I then began to wire up the controllers. One the first attempt, I thought I would solder short wires to the controller and then use these for connection points. This worked OK until I was up to the final wires. It seems that constant moving around of the controller puts pressure on the soldered joints and I ripped many of the tracks off. I then had to get my tiny copper wire and re-solder the tracks as the pads were gone. This became quite tedious, but I learnt my lesson very quickly.
I got enough of the wires connected for the first joystick and then quickly connected it to test. I then managed to play a quick game of Bubble Bobble. Impressive! You can see below my initial prototype housing for the controls. The washing basket was the worst idea on earth... but it was a cheap mistake.
Building real housing
I ended up at Bunnings looking for ideas for a box to house the controls. There was nothing off-the-shelf, so I opted for enough wood to make a deep enough box for the controls. This was a pretty simple and ugly construction... but it did the job.
Finished products
After testing, I put backing panels on both of the controllers.
Each controller can only ever be used as Player 1 and Player 2 respectively as they are mapped to specific keys on the keyboard.
Of course, you could change the configuration of MAME, but that would be tedious... Although sometimes on games it'd be nice to be able to play as one of the other 2 players (3 or 4) ... but I'll create two more controllers for that.
Future plans
I want to build two more of these (actualy, I did, here's the link!)... 'The Simpsons' arcade and 'Teenage Mutant Ninja Turtles' require 4 players for the most amount of fun, and 'Rampage' needs all three creatures bashing up buildings.
Sending full bytes over .NET Serial Ports to the Arduino
Ok, I have just spent a good two nights of my life diagnosing why I could send all bytes up to value '127' and no higher. In hindsight, it all makes perfect sense and the documentation is clear, but when you've been taught to think in strings, you might hit this very quickly.
The Scenario
I have my MAX7219 + LedControl Library set up on my Arduino and all works fine. I use two functions to control it: setLed and setRow. setLed simply takes a boolean to determine if the LED you are pointing at is to be on or off, but setRow requires a byte. This is all fairly straight-forward as each 'row' in the LED matrix has 8 LEDs, and a byte has 8 bits. So, starting from the lowest significant bit, a value of b00000001 will turn on the first LED in a specified row. (i.e. setRow(DEVICE,ROW,BITS);).
All communications between my application and the Arduino had been based on strings and so I had previously been using one character (one byte) to set one LED. Due to this being a complete waste of bandwidth, I decided that each byte I sent through the channel should be a byte to control full row of LEDs. This meant that I could therefore no longer 'see' the output as a string (or ASCII), as the characters I would create from setting the bits may no longer be in ASCII range... this was no big deal, as I could just view the byte values and decode it all myself.
So, on the client end (C#.NET Application) I started encoding the bytes from bit values. This all worked until I tried to set the last bit...
byte b = 1 | (1 < < 7); //let's set the first and last LED. string buffer = (char)b + "\0"; serialPort.WriteLine(buffer);
| Data Sent | LEDs lit | Correct? |
|---|---|---|
| b00000001 | 1st | OK |
| b01010101 | 1st, 3rd, 5th, 7th | OK |
| b10101010 | 1st, 2nd, 3rd, 4th, 5th, 6th | WRONG |
| b10000001 | 1st, 2nd, 3rd, 4th, 5th, 6th | WRONG |
| b01000000 | 7th | OK |
| b10000000 | 1st, 2nd, 3rd, 4th, 5th, 6th | WRONG |
What the hell was going on? That 8th bit is fishy!
The Answer
So, after reading numerous blogs and not finding my answer, I went to the Arduino Forums and posted a topic asking for help. I was given advice to write a very simple test app to work out where the bytes were failing... but I never did get to write that app, instead I went to the MSDN site as soon as I saw that the Write() procedure could be overloaded.
And look what I found at the article on MSDN:
By default, SerialPort uses ASCIIEncoding to encode the characters. ASCIIEncoding encodes all characters greater than 127 as (char)63 or '?'. To support additional characters in that range, set Encoding to UTF8Encoding, UTF32Encoding, or UnicodeEncoding.
And guess what... ASCII Character ? is 63 in decimal and therefore b00111111 in binary!
So, whenever I was setting the 8th bit, the .NET Framework (in all its wisdom) would translate this to a question mark as it was not expecting to send an invalid ASCII character. Ladies and Gentlemen, ASCII is only 7 bits!
The work-around?
byte[] b = new byte[] { 1, 127, 128, 129, 255 }; //let's set the first bit, last bit, etc...
serialPort.Write(b, 0, b.Length);
And then everything just worked. Do not send chars to your port if your receiver wants bytes.
Ugh… Taiwanese Components…
PLEASE be careful when you buy cheap and nasty electronic components from eBay... This is a public service announcement.
Check the photos below and tell me what's wrong:
Yes, that's right, the legs are different on both items (the Anode and Cathode are REVERSED)... they came from the same packet and I, prior to using macro on my camera, thought they were a lot more similar than they actually are. Either way, you have been warned.
This all came about whilst wiring up these sensors and receiving zero readings.... bastards....


Melbourne BG SCS Train Timetable 


