Showing posts with label reverse-engineering. Show all posts
Showing posts with label reverse-engineering. Show all posts

Sunday, February 21, 2016

Hacking my own Arduino Mega


At Interlock, I was handed the old controller board for a gutted 3D printer that was being rebuilt. "Do whatever you want with this." A close inspection of the board showed that it had a main microcontroller of the ATmega 1280, which is the chip used in older Arduino Megas.  The interface to USB however was an ATmega 8u2, which is the chip used in newer Arduino Megas, and you may also know it from older Arduino Unos... modern Uno R3s use a 32u4.

This board had custom firmware on it so that it didn't look like an Arduino, or any sort of serial connection to the host computer it's plugged into... so as-is, it was useless for general use as an Arduino; taking advantage of the GUI and clicky-clicky programmer interface.

So my thought was, it might be nice to have my own 'Mega for testing and such.  Could this board be set up in a way that might make this process and outcome easy?  Turns out it mostly was.


The original board got its power from a power terminls on the board, 24V.  It needed to power the stepper motors, and such so it needed to be beefy.  This was dropped down to 5 and 3.3 on the board itself.

There is a USB B jack for connecting this to a host computer, which did not have its 5V connected, so my thought was, what if i hooked up this 5V to the USB jack.  would that be enough to power the chips?


I added this jumper, which connects the +5 on the USB jack to the 5v bus on the board, and plugged it in, and sure enough, it beeped and came to life without its host power supply.

Next up would be reprogramming the micros to have the arduino bootloader and code on them.


I hooked up my fairly cheesy Arduino D-15 (hacked stepper motor controller) ISP to the 6 pin header, which thankfully was already populated and labelled on the board!  I plugged it into the port labelled "1280 ISP", selected the Arduino Mega, with 1280 micro from the Arduino 1.6.6 menus, selected Arduino ISP for the programmer, then selected "load bootlader".  In about a minute, it seemed to have completed successfully.... if something didn't jive, it would spew out sync or device errors to the screen.  Seemed good so far!

Next, was hooking it up to the jack labelled 8u2 ISP.  This was a little trickier because I wasn't installing the bootloader (which the Arduino IDE makes REALLY easy to do), but rather the secondary micro's firmware, which basically was just a USB-Serial interface driver.

Long story short, I grabbed the 8u2 code from github, "MEGA-dfu_and_usbserial_combined.hex", and used the following command line (using a mixture of the code on that page, with the parameters that my system used via the arduino IDE on my Mac:

    ./avrdude -p at90usb82 -F -cstk500v1 -P/dev/cu.usbserial-A800czia -b19200 -U flash:w:8u2.hex  -U lfuse:w:0xFF:m -U hfuse:w:0xD9:m -U efuse:w:0xF4:m -U lock:w:0x0F:m -C/Users/me/Library/Arduino15/packages/arduino/tools/avrdude/6.0.1-arduino5/etc/avrdude.conf

In short, it sets the CPU to at90usb82, uses the stk500v1 communications protocol over the /dev/cu.usbserial driver, at 19200 baud.... it programs the file 8u2.hex, sets fuses and sets other avrdude configuration stuff.

After lots of text scrolling by from running that, I was able to drop a program I was working on, onto it via the Arduino IDE directly, without any problems at all! I set the port to the serial Mega, set the board to "Arduino Mega", cpu set at "Mega 1280", clicked 'upload' and bam, fully functional serial communications from the serial montior down through to the '1280 on the board.


Whoo! Free Arduino Mega for me!

Edit: Here's the pinouts of stuff I beeped out.

 * 4 - Piezo +
 * 6 - heat
 * 7 - fan
 *
 * 24 - A Dir
 * 25 - A Step
 * 26 - A Enable
 * 27 - A Pot
 *
 * 28 - B Dir
 * 29 - B Step
 *
 * 36 - debug 2
 * 37 - debug 3
 * 38 - (nc)
 * 39 - B Enable
 * 40 - debug 4
 * 41 - PG0
 * 42 - TP33 / Z-MAX
 * 43 - TP32 / Z-MIN
 * 44 - Extra +/R85
 * 45 - bp heat
 * 46 - TP31 / Y-MAX
 * 47 - TP30 / Y-MIN
 * 48 - TP29 / X-MAX
 * 49 - TP28 / X-Min
 *
 * A0 - X Dir
 * A1 - X Step
 * A2 - X Enable
 * A3 - X Pot
 *
 * A4 - Y Dir
 * A5 - Y Step
 * A6 - Y Enable
 * A7 - Y Pot
 *
 * A8  - Z Dir
 * A9  - Z Step
 * A10 - Z Enable
 * A11 - Z Pot
 *
 * A12 - PK4 / JP7
 * A13 - PK5 / JP7
 * A14 - PK6 / JP6
 *
 * A15 - TP27 / HBP Therm

The molex switch connectors seem to have the pinout: (signal) (ground) (ground) (+5v)

Tuesday, August 18, 2015

Retro Challenge 2015/7: Post-Mortem and project notes...

Current Project State

For this Summer's Retro Challenge (2015/7), I worked on a small widget that lets you use an Amiga mouse, Atari ST mouse or Atari-style Joystick.  I was successful in building it and having it be manually configurable.  There's a shell based interface that you can use to select which input device and output style is used.

All of the code for this project as well as further and future documentation is available at the project's github repository.

There are a bunch of things that I did complete during the "challenge"...

  • Arduino Leonardo based firmware with simple direct connection to a single D9 male connector
  • Two versions of the hardware, one quick and dirty, the other optimized for the parts I had.
  • Designed to use minimal external parts - just the Arduino board and a D9.
  • Serial interface shell to configure which device it is
    • Amiga Mouse (fully tested)
    • Atari ST Mouse (fully tested)
    • Atari Digital Joystick (fully tested)
  • Serial interface to select which output the joystick provides
    • Mouse movements
    • WASD keypress input
    • Arrow Key keypress input
    • HJKL keypress input
    • etc.  (support for MAME, Stella, Vice, etc)
  • "Explorer" to experiment with input device auto detection algorithm (which does work)
  • Amiga 500 keyboard input header (incomplete)
  • Amiga 500 to Amiga 1000 keyboard adapter (to RJ-22 4P4C telephone handset jack)
  • Documented Amiga keyboard adaption 
  • Documented Amiga - Atari ST mouse differences
  • Documented other D9 joystick pinouts (and how they relate, etc)

There are two features that I did not complete before the end of the month...

First of all, I was unable to get the keyboard support working before the end of the month. I was having a hard time with it only to realize it was a power issue.  The keyboard was consuming more power than my widget could provide.  It will require a secondary power supply to give enough oomph to get it working.  I also was unable to read from it once I hacked in some power.

Secondly, I had designed an algorithm to autodetect between the three different supported input devices, but I was not able to integrate the code in before the end of the month.  At some point I'll mix it in, and it will switch the kind of device it will be based on analysis of the signals (and signal pairs) of data coming in when it detects "motion".

Next Steps

At this point, I'd like to take the codebase as it exists now, and change the program flow to do the auto-detection of the device type, and then do the "appropriate" thing with it.  "out of the box" it will just "do the right thing" when devices are plugged in. Namely:

  • Amiga mouse becomes USB HID Mouse
  • Atari ST mouse becomes USB HID Mouse
  • Atari Digital Joystick gets configured to send STELLA keypresses (arrow keys, etc)
I will implement this at some point, perhaps during the next Retro Challenge.

Monday, July 13, 2015

Retro Challenge 2015/7 Update 2: Keyboard And Joysticks

Space Invaders running in Stella on my Mac.  Jasper loved it!
(He also liked the green light-up USB cable.  That's my kid!)

As of last night, I have finished code for the joystick-to-keypress controller, as well as the ability to save the configuration in the EEPROM in the ATmega chip. As usual, the code is all available here on github.  What this basically means is that moving the joystick will send down keypress codes to the host computer... so the computer thinks that a keyboard is being used.  This means that applications like Stella, an Atari 2600 VCS emulator, which expect you to use the arrow keys and space bar in place of a real joystick, can see those key presses when you move your actual Atari joystick!

You can now pick from a list of keyboard mappings, including:

  • Stella (Atari 2600 emulator) (shown above)
  • Vice (Commodore 64 emulator)
  • Mame (Arcade game emulator)
  • WASD (general PC game usage)
  • HJKL (vi cursor movements (because why not!))

I have also implemented a basic settings system that saves settings to the EEPROM within the ATmega32u4 chip.  It currently has "slots" for a few things, but could be expanded with the above joystick-to-keyboard mapping, to send other keypresses from joystick movements or what have you.

The settings system works with 4 bytes in the EEPROM to determine what's going on with respect to saved settings. The first 3 bytes are a sentinel.  If the code does not read the sentinel, it will assume it's on a new device, and will install default values to the EEPROM.  The current sentinel are the three hex bytes: { 0x53, 0x44, 0x4c } which are the ASCII string "SDL", my initials. ;)  Next at setting slot [3] is the settings version number.  Currently this is just '1'.  Settings slot [4] contains the usage mode for the interface port. (Mouse/keyboard mapping, etc).

I attempted last week to get an Amiga Keyboard working with this.  I wired up an 8 position pin header to the interface board, using the Amiga 500 pinout:

  1. Data
  2. Clock
  3. Reset (toggled when Ctrl-A-A is pressed)
  4. +5v
  5. key (missing pin)
  6. Ground
  7. Status LED (power)
  8. In-Use LED (disk access)
I was going to just wire out the Data, Clock, +5 and ground but decided that it made more sense to use the actual A500 pinout. I ran into a problem on this though.  The interface can't provide enough power to drive the chips on the interface board.  I measured 4.5v at the pin header, then 3.2v down on the interface board itself.  This isn't good.  I will have to wire up a new interface connector with an external power connector, probably a USB-B jack, to provide dedicated power to the keyboard.

I did however find a phone being discarded, and retrieved the two 4P4C (RJ-22) connectors from it so that I can make a better A1000 keyboard jack.  The first one I made used an RJ-45 wall mount jack, which worked somewhat for RJ-22, but it was pretty hacked. ;)

Some thoughts for future additional expansion:

I'm currently going for the "cheap as chips" version of this, which is why there's no interface on it, and you have to connect via serial port to configure it.  This was all intentional to keep the build parts list down... to the point where the only necessary part is a D9 connector!  However, in using it, a few future revisions may offer more usability at the cost of parts expense:

  1. Multiple D9 jacks for multiple devices
    1. Ports dedicated for Mouse, Trackball, Multiple Joysticks, etc
    2. Could be just 2 that simulate Commodore/Amiga
    3. Could be 4 to simulate Atari 800 joystick ports
    4. Could be 1 for mouse, 5 for joysticks, so you never have to disconnect them.
    5. Would require a parallel-in, serial out shift register, or a port expander
    6. Expansion at the cost of a few cents, additional wiring, and time to read in the content
  2. (related) configuration for multiple ports
  3. User interface - Was thinking that this could be a variety of different methods:
    1. single pushbutton, Red/Green LED for indication codes (flashing colors)
    2. single or dual pushbutton, RGB color addressable LED for indication codes
      1. each could be wired directly to IO pins
    3. dual pushbutton, 7 segment LED display
      1. Could indicate use mode(s), etc
      2. 'C' for commodore mouse, 'A' for atari mouse
      3. '0'..'7' for joystick mode display
      4. Could flash multiple digits sequentially for info etc
      5. Would require LED driver chip
Obviously, all of these would require additional effort beyond the "let's get this working" and can be seen as stretch-stretch goals.  ;)


Tuesday, July 7, 2015

Retro Challenge 2015/7 - Amiga Mouse, Joystick, Keyboard USB interface

Once again, it is time for the Retro Challenge! This time around... well, I wasn't sure what I was going to work on,... In my "I want to partake" email, I listed projects such as working on an SD-card based storage drive for the KIM-Uno, my "Bare Metal C64" long term project.. which will likely wait until I retire, as well as working on the Interlock Homebrew Computer System.

Then I started to get parts from an aliexpress order that I placed.  I received my Arduino Pro Micro which is the teeny tiny version of the Arduino Leonardo.  What makes this special is that the main chip on it is the ATmega 32u4. This is the USB interface chip used in the Arduino Uno.  It has all of the standard IO of the 168/328, but with USB HID support.  This means that it can pretend to be a USB keyboard, mouse, etc.  This is a HUGE feature if you want to make standard computer peripherals.


For some reason, it clicked that I wanted to make a USB HID interface for my Amiga mice.  Long story short, within an hour, I had a functional prototype. I was moving my Amiga mouse, and the cursor on my MacBook's screen was moving.

I figure that this will be great for using the Amiga emulators. It'll be nice to use an authentic mouse, joystick and maybe keyboard with UAE, Vice or just for fun for regular usage.  I know that there are other projects out there or products that do this kind of thing, but they're a bit pricey to have a widget that I can't expand or repurpose... and besides at its core, this is not really a difficult or expensive product.  The most expensive single part so far is the microcontroller, and that was $3.

A little background on the Amiga's mouse...

The way old optical ball mice work is that they have two rollers that sit on a weighted ball, one for the horizontal, and one for the vertical.  As the mouse moves horizontally, the horizontal roller moves, and the ball slips on the vertical one.  The rollers have an encoding wheel with little windows that make and break optical connections with a pair of sensors.  These two sensors generate two bits of data for each direction. (four total.)  These two rotary encoders generate a gray code quadrature output.

Movement in one direction outputs:  00  01  11 10  00
Movement in the other direction outputs: 00 10 11 01 00

So, if you read these in a tight loop, and detect changes you can detect movements in the horizontal and vertical directions. In the same loop, if you look at the button inputs, you can determine if the buttons are pressed.

This is the basis for this project.  By reading these values from a dumb (no internal processing) Amiga mouse, I can generate vertical and horizontal motion values.  I can then send these down the USB HID stack through the Arduino libraries, and voilĂ , we have an Amiga Mouse to HID USB mouse adapter.  NOTE: PS2 and ADB mice have more smarts in them and output movement deltas rather than optical sensor pulses.  Reading either of those requires serial communications and protocol decoding instead.

My cheat sheet for pinouts and connection information.


Within an hour of this brainstorm, I had this prototype:

Arduino Pro Micro (ATmega32u4), with headers and D9 cable attached.

Commodore Amiga mouse plugged into a spare serial cable re-used as a D9 cable.

Unfortunately, the serial cable I was using had all of the wires connected except for the line used for the right mouse button.  Oh well... For the "what's available on my desk" approach, it was good enough for a proof of concept.

From there, some simple acceleration was added to convert "quick" movements of the mouse to "large deltas" sent down as mouse movements...

The way I implemented acceleration was that each time through the loop, i check for Horizontal or Vertical ticks.  I store the ticks as +1, 0, or -1 in an array of the last 128 readings.  Then, I sum the entire 128 elements of each (horizontal and vertical) array, and use that as the mouse movement.  The faster the mouse is being moved, the more +1s or -1s there will be, so it sends a larger number.  It was a quick hack that I thought might work, that turned out to work perfectly!

Some upcoming additions that I might / probably will do:

- Atari ST Mouse Support.  The only difference between an Atari and Amiga mouse are that two of the lines (specifically D9 pins 1 and 4) are swapped. This is an easy change in software.  The difficult part is tracking down an Atari ST mouse to test with!

- Atari (Digital) Joystick Support.  By combining the button read code with the acceleration code hinted at above, I can convert Joystick movements to HID mouse movements

And really, from that point, it would be near trivial to add in HID keyboard support as well... I can send down WASD key presses for joystick movements... or really any other key presses based on joystick movements.

Additional features may include support for Amiga keyboards as HID keyboard, joystick as HID gamepad, etc.  In preparation for working with one of my old Amiga 1000 keyboards, I cleaned one up to get the years of finger grime of of it...

The right side has been cleaned using my proprietary cleaning technique described below.

Keyboard in the process of being cleaned. More like CLEANBOARD. HAHAHA. :(

Here's the (yellowed) keyboard with some keys removed. (The 'X' key has been missing for years, sadly.)  The proprietary cleaning solution is in that "Cascade" container.  I would use that dental pick tool and my hand noodles to pop the keys off of the keyboard.  Then I dropped them into the cleaning solution.  After about 30 minutes, I pulled each one out, wiped it off with my fingers, rinsed it off, and they were as clean as new.  The proprietary cleaning solution is one squirt of dish soap with some warm water. ;)

NOTE: Not shown is the process of removing all of the lint, hair and other bits of whatever that were stuck between the keys because that's kinda gross and you don't really want to see that anyway..

More on this project to come...

I briefly explored the idea of supporting Mac/Apple IIgs ADB mouse and keyboard support, but I quickly learned the complexity of the ADB spec, and am putting that safely outside of the scope of this project!

The code for this project and other development details are available on github in the AmigaInputToUSB repository.

Monday, November 10, 2014

Flat panel light box


I've been getting into making stained glass pieces, as I've been taking a class at the Rochester Memorial Art Gallery.  One of the tools they have available there is a light box, which I have used to make the template for the macaw piece I'm making.  I used it to help me adapt a pattern I found online into something that better suits my needs.  I traced it, then retraced that sketch.

The light box also works well to see how things look with light behind them, however it's not something I can use a lot for this, since my project is a couple dozen pieces of glass and we have to share the light box.


On the recycle pile at work was a couple of old, broken laptops.  I snagged two of them; one with an LED backlight, and one with a CCFT backlight.  I thought that the LED one would be easier to get working.


Over at Interlock, I tore apart the screens, tossing out the LCD panel, so I was left with just the light source, light guide, diffusion screens, and control circuitry.  Its control/driver board also managed the LCD itself.  There were many test points on the back, so I applied power to the "LED PWR" pin, ground to a ground point, then about +5 volts to the BLEN (assuming it to be "backlight enable") as well as the "PWM" test point. After futzing with it for a little bit, I gave up and focused efforts on the CCFT-based one.

The slightly larger CCFT (Fluorescent) based one had a single board that connected to the backlight tube through standard white/pink silicone-insulated wiring.  The board itself had one tiny connector on one side with a few pins that seemed to have obvious use.  V+, which assumably powers the backlight circuitry, should be connected to +5 or maybe +12.  GND, which of course is ground. Then two other connections "EN" and "CTRL", which I guessed to be "Enable" and "Control".  A guess would be to tie these to a logic "high" which might maybe enable the thing.

I connected just the V+ and GND to a power supply, and applied power.  Ranging from 0v up through 12v yielded no results. I connected the other two logic lines to power too, and started ramping up the power.  At around 7v, the backlight flickered on, but then wouldn't do anything until I brought the power back to 0v, and then back up again.

On a hunch, I figured that the backlight needs a higher voltage, and the logic stays at TTL levels.  Applying the same power to both would give a possible point between the two where both kinda worked, which is where I saw the flicker.  I hacked together two power supplies, with grounds tied together, 5v from one power brick, and the V+ to the variable supply.


I ramped up the voltage, and sure enough, it would get dim around 7v, then go full brightness around 12v.  It seemed to use about 300mA to drive it too. Good to know.  I found a 12v power brick and.. it would light for about 20 seconds then power itself off.  The 12v brick put out 18v.

I eventually found a brick that worked, so i hooked up two supplies, a 5v and a 12v and it was stable and bright.  Next would be the task to put in a 5v regulator to provide the 5v it needs, so i can run it all on one single power supply.


A simple circuit using a 7805 and two capacitors later, and I have 12v in, and a backlight lit!  I wrapped the circuit in tape (purple because it was there), hooked it up to a power connector, and reassembled the case.


Best of all, it all managed to fit within the old plastics. Huzzah!

Now I just need to put something on the diffusers to protect them from cut glass, maybe a piece of plexi, or even a large Ziplock or plastic wrap, and I'll be set!

Saturday, April 19, 2014

The Otto Project


I've been trying to figure out the angle I should take on this post, and I've decided to focus on my effort here, rather than a history lesson more than a brief overview about who "Crazy Otto" was... but here's the quick recap...

In 1980, General Computer Corp (GenComp/GCC) was making mod kits for games, including one for Missile Command, and one for Pac-Man. Their Pac-Man add-on was quite innovative.  It brought four new mazes to the game, a new lead character with legs and feet, a new intro sequence, and monsters with antennae instead of ghosts.  If this sounds somewhat familiar, it should.  This mod kit became "Ms. Pac-Man", but before it was Ms, it was "Crazy Otto".  It went through a few steps in the progression, all of which I will cover below.

If you want a more comprehensive history of Ms. Pac-Man, you should watch the video of Steve Golson's presentation "From Crazy Otto to Ms. Pac-Man".  It covers many of the details that I used to create these.  Links to the PAX-2012 and MIT-2014 presentations of this are available at the bottom of this post, and are well worth your time to watch.  All of the sets I present here are directly based on sets that he described, demoed, or showed screenshots of, in an attempt to recapture the history of this iconic video game.

The tools I used to create this are:
  • ASZ80 - assembler (ASM to IHX)
  • genroms - converts IHX to binary rom files, capable of patching over source images
  • Turaco - arcade game graphics editor for MS-DOS
  • Boxer/Dos Box - MS-DOS emulator so that I could run Turaco on my Mac. ;)
  • mspacman.asm - Our well documented Ms Pac disassembly
All of these are available either through online repositories.  Links for all are at the bottom of this post.

None of this is to be used or repackaged for profit.  This is all for educational and historical reasons.  It's okay to drop it into a free-play machine as a museum piece... It is NOT okay to include it with a multigame that you're selling, etc.  Don't be a jerk.

Okay... All of that is out of the way. Let's get into the differences between the romsets, and the patches necessary to make them happen.  I'm going to use the names I came up with for the sets to differentiate them here.  Details of differences and dates were gleaned from Steve Golson's presentations.

Information gleaned from his pre-PAX-2012 talk: (Time magazine photo and rumors)
  • Approximate image of Otto, one frame of 16, no animations
  • Approximate image of monster sprites, one frame of two
  • The fact that this existed at all
Information gleaned from the PAX-2012 talk:
  • Dates of ROM releases
  • Attract sequence differences (Pac-Man, Ms. Pac Marquee, Pac-Woman additional movement)
  • Ghost name differences
  • Crazy Otto exact graphics romset (shown as two screenshots, recreated using Turaco)
  • Monster exact graphics
  • Pac-Woman exact character graphics (recreated using Turaco)
  • Character coloring (for the "alternate" character in intermissions)
  • Intermission structure (short bits of original asm code were displayed, providing a rosetta stone)
  • Lack of monster "eyes" after monster death
  • Death animations for all 
The following ROMsets were released by me (version 05) on April 19th, 2014.  They were playable on a 13" JAMMA test rig (on a Yenox bootleg mspac board) in the lobby of BarCamp Rochester on this day as well.  I switched the ROMs back and forth between the "PZ" set, and the "Pac-Woman" set.

And now I'll list off details about what makes each particular release distinct, as well as some info about recreating it, backwards, from a standard "mspacmab" bootleg ROMset.

OttoP1 - 1981-Oct-12




Character and sprite roms for OttoP1.  These are pixel-for-pixel copies of the original.
The character graphics (top) are based on Pac-Man (Notice the score graphics)

  • Pixel perfect Crazy Otto graphics rom (characters moved around)
  • Pac-Man intro sequence (stationary ghosts) showing their names
  • GENCOMP logo, rather than Midway logo/copyright
  • Remap movement animation frames (characters, stork, baby, etc)
  • Remap of characters and colors for intermissions

This one was one of the more interesting hacks to work on.  A lot of what makes this one unique was to be eventually obliterated by Ms Pac patches.  At first I tried reversing the one patch in Pac-Man that jumps to Ms Pac romspace, where the new "marquee" intro happens, and just let it fall back on original code.  This kind-of worked.  The problem is that it used quite a few of the text slots, which were re-used for the new marquee introduction.  To fix this, I reverted many of the text strings to their modified Pac-Man versions, eg Mad Dog, Killer, etc instead of Inky, Blinky, etc.

The GENCOMP logo was already in the character set, so i just needed to remove the jump to the Midway logo and copyrights, and replaced one of the copyright strings with the characters necessary to draw out "GENCOMP" ("pqrstuv").  I also used a feature of the text render routine that I'm fairly certain no one else uses anywhere else, and that lets you draw the text out in multiple colors, rather than just one color for the entire text string.

Remapping the movement frames was fairly straightforward once I replaced the original math-based routine with my table-based routine.  This is discussed in the section below "Player Sprite Picker".

Remapping the colors, characters, and sprite frames was fairly easy once I was able to use the rosetta from Golson's talk to figure out some of the animation format.  Past that, It was a bunch of experimenting to determine what parameters did what (color, speed, location, etc)  The 'female' character from the intermissions required more attention, since it now uses a different palette color (red), so all occurrences of the color (12 of them) are replaced from 0x09 (yellow) to 0x01 (red).


In Golson's talk, as you can see in the above image, he had a couple of pages of code snippets.  The one above is showing the animation format.  Thanks to him publishing his presentation materials, we can see that up close:

With a little bit of sleuthing, I was able to use this as a kind of rosetta stone, to figure out the animation format.  These animation scripts are used for the intermissions, as well as the introduction attract "marquee" screen.  This becomes more important with the P5 (Pac-Woman) hack below.

For the record, here's the above code chunk, but in the mspac.asm disassembly project, showing that we have a better grasp on how these scripts work.

OttoP2 - 1981-Oct-20




The graphics roms for P2 are similar to P1.  The sprite rom (second) is identical.  The character rom (first) is upgraded to the MsPac version. Notice the marquee graphic instead of the scores in the character rom.

  • Everything from P1 except for:
  • Marquee intro sequence, with "Bonnie" instead of "Sue"
  • "MIDWAY MFG. CO" with Midway Logo
Replacing "Sue" with "Bonnie" was a simple text replacement.  Same with the Midway logo.  The year line was removed from the final product, and the other line was just moved down, and changed to the text seen above.  Nothing really major.  All of the guts of this was accomplished in the P1 variant.

OttoP3 - 1981-Oct-29


  • Everything from P2 exept for:
  • "(c) MIDWAY MFG CO"
  • "1980"
Again, this was just further text changes and tweaks. Nothing major here.

SuperP4M, SuperP4G - 1981-Oct-29

   

This one signifies two different graphics rom sets with the same code underneath it. "P4M" specifies the version with Crazy Otto Monsters, while "P4G" specifies the standard ghosts.




For this version, the character ROM is basically the same as P2 above.
I switched the layout for Super Pac0Man to be closer to the Pac-Man layout.

  • Graphics Rom is closer to Pac-Man than Ms. Pac, to retain the Pac-Man death animation
  • Many similarities with P1-P3
  • Copyright string from P3
  • Game and character names on marquee introduction changed to "Super Pac-Man"
  • Character sprite table for movement and animations changed to Pac-Man
  • Stork and baby sprites in the table were also remapped
All of the changes here were explained in previous sections.  The character movement table was used to tweak the frames of animation to the Pac-Man standard.  The death animation frames were remapped to what Pac originally had.  Also the color of the "female" for the intermissions was retained as red as in the above, but is now a red Pac-Man puck, rather than an Otto with legs (AKA "Anna").

WomanP5 - 1981-Nov-12






The Pac-Woman set is based on Ms. Pac-Man.  The orientations for the death animation are the same as in the final MsPac.  I've included this in yellow so you can see the woman graphics appropriately.  The red/blue/white version is included for comparison with the above examples.

This one got a bit interesting. Golson didn't have any demonstration of this other than a screenshot of "Pac-Woman" in the graphics ROM, and the intro screen animation.  I interpolated this up from what I had for P3, as well as putting her in place of Ms. Pac-Man in her romset.  He even said that there wasn't a playable version of the ROMs that existed... which makes my P5 set even more interesting, since we can now actually try it out.
  • Ms Pac graphics rom with "woman" in place of Ms. pac
  • other character in animations was Pac-Man, like in the final version
  • Animation frame indexing changed from Ms. Pac to use the tables, as explained above
  • Additional animation added to the intro sequence
Since I now knew most of the animation format, as explained earlier, I was able to tweak the animation segment table to point to a new section for Pac-Woman's introduction.  It does the same thing as before, where she walks in from the right side, and stops in the middle of the screen.  But from there, she turns and moves down a little bit.  I did a bunch of tweaking to the speed, distance, and ending frame to try to make this look as much like the demonstration video as possible.

He stated that this version was abandoned due to the fact that when she's moving away from you, it's easy to confuse her with the red ghost.  And he's absolutely right.

From this stage, they generated a slightly different character, again with a bow on her, and she became the Ms. Pac-Man that we all know and love.

OttoPZ




The PZ variant brought forward a bunch of problems.  The main screen needed to have the monster graphics, as well as both logos and the marquee for the Pac-Man and Ms. Pac-Man introduction screen.  The sprite rom is basically the same as the above P2 version

This one is a multigame version of P1-P3, plus an additional fictitious mode not based on any single romset.  It also has additional patches for playability.  You select at startup time which variant (P1, P2, P3, PZ) you want to play as well as whether you want the fast or regular variant of it.  Once you pick that, it behaves like any game above.

While it's running, holding P1 and P2 start and pressing the joystick up "drops a quarter".  Holding those and pressing the joystick down resets the machine, so you can pick a different variant.

This one is perfect for your home arcade, MAME machine or other emulator.
  • Switchable Pac-Man intro and Ms Pac-Man marquee intro
  • General playability of P1-P3 above
  • Fast mode selectable at bootup time too
  • PZ mode also selectable - Ms Pac marquee intro, with GENCOMP logo.
This one got a little complicated.  In P1 above, I was able to just swap out the Ms Pac text table and restore the Pac-Man one.  I didn't have that luxury this time, since we needed the Ms Pac text table to be intact for the P2, P3 and PZ versions of the game.  I implemented this by hooking in to the actual text rendering routine.   It skips out and goes to my own routine which checks to see if the current game is P1.  If it is, it uses a reproduction of the Pac-Man table, but out in my memory space, and with a few strings restored to the OttoP1 versions.  This one has the original P1 strings, rather than the re-used/remapped strings that are used for the Marquee introduction.

One other modification done in this patch is the check for if the game is trying to render string 0x13 (copyright) or 0x35 (copyright year).  Since each variant has different versions of these, the routine uses the variant number as an index into its own string table, and draws the appropriate-looking text to the screen.

This does get into something though.  How do we know which game and variant we're playing. We need to store it in RAM somewhere nonvolatile.  We can pick someplace unused, but it might get used and we haven't figured out the documentation yet.  Or we can use a trick that I figured out while working on a multigame Ms. Pac a few years ago.  The stack pointer always starts at 0x4fc0, and works down from there.  Nothing ever  goes above it other than sprite registers.  So, if we just patch the game code to start the stack pointer down a little bit, we have a few bytes that we can use for our own storage.  

The test for the coin drop and reset hack was hooked in to the routine that checks the coin slot switches.  This gets called often while the game is running, so it seemed like the most comprehensive place to insert our routine.  Before it checks the coin slot switch, it will check to see if P1 and P2 are being pressed.  If the joystick is also being pressed up also, we "drop a coin", and if it's pressed down, we reset the machine, so that the player can pick a different variant to play.

This set also drops the "jumble of characters" standard MsPac startup tests. 

All of the patched romsets mentioned in this post are available through links at the bottom of this post.

Common patches applied

There are a few patches that got applied to just about all of the sets in one way or another.  I didn't want to change any of the gameplay behaviors, so I didn't fix the killscreen at level 240ish.  I also didn't apply the "Fast" hack to any of these sets, since I wanted to reproduce the original gameplay, not a "comfortable playable set". If you want that, use the "OttoPZ" multigame, which is tweaked for general "daily" use.

Memory Mirror Fix

First of all, due to nothing being mapped in memory space above 0xAFFF, writes to those locations map down to lower memory.  That is to say that writes to 0xB000 will acutally occur at 0x4000.  The emulators do something weird with this, and the writes disappear into unreferenced 'ram' space.  This is a problem because the text rendering routine (at 0x2c5e) does something weird with it.  You call this routine with a number, an index into a list of pointers to text structures.  The first item in the text structure is the offset into video memory that the text should start.  The upper two and lower two lines use a different arrangement of bytes, so they need to behave differently.  This behavior is signified by setting the high bit (0x8000) on the offset.  Well, if we now have text that was supposed to be at offset 0x00FF, but it is in that region so the high bit is set (0x80ff).  This offset added to memory space at 0x4000 produces 0xC0FF as the starting location.  In real hardware, this is fine, since the high bit is not connected, so the write actually happens to (0x4000 + 0x00ff), but in emulators, it actually happens at 0xC0FF.  There's a patch that fixes this -- it masks off that high bit when adding in the offset to the video base pointer.

Player Sprite Picker

Another patch standard on all of these is replacing the original function that determines what sprite to display for Pac/Ms.Pac/Otto.  The original did some sort of weird math to determine the sprite number.  I replaced all of that with four hooks into my code that loads the appropriate four-entry table (four hooks; one for North, South, East, and West.)  This code actually fits over the original code, without needing any extra space... in fact, it's smaller and more efficient than the original at 58 bytes instead of 81 bytes... plus, and more importantly, it's MUCH easier to hack in different sprite characters for different graphics sets, which I needed to do.  I'm actually kinda surprised that Otto/Msp didn't use a table for this.

Splash Intro Page

One obvious modification is that all romsets have a splash screen on startup. I didn't want my reproduction sets to be mistaken for the real thing, should it ever be released.  At the end of the startup tests, just after the test grid is drawn, it is cleared, and then my own routine occurs.  This one has its own text string table for the standard text routine at 0x2c5e, so as to not need entries in the standard string table.  It will draw out info about the romset, my email address, and after a moment, it prompts the user to press a button (or move the joystick.) (The "clear screen" routine was also re-added as a patch, since the original wasn't easily callable.

Links


NOTE:  I pursued this project on my own, using only publicly available information.  No direct contact was made during development by anyone involved with GENCOMP nor Midway nor Namco.  This is meant to be a historical/educational project, not for profit.  The use of copyrighted materials is covered by fair use, as this is for educational use.  It is fine to use this for museum-type displays, but not included in a multigame that you're selling.  Don't be a jerk.

NONE OF THESE WORKS ARE TO EVER BE DISTRIBUTED FOR PROFIT, EITHER ALONE, OR REPACKAGED. 

Friday, May 17, 2013

11 Digit, 7 Segment Display

An early test result, showing text and millseconds since power-on.

About a year ago, I bought a few 11 digit, 7 segment red LED displays from Active Surplus up on Queen Street in Toronto. (Excellent store.  If you're into hacking stuff at all, it's well worth the trip. Look for the monkey on Queen street to find their entrance.)

This past week, I wasn't sure what to do at Interlock on Tuesday night, but I had recently re-found these displays, so I figured I would finally get them working.  I hit Radio Shack to get a Seeed Studio Arduino Shield ($10 with a mess of components, probably the best deal in all of Radio Shack.)

The display with a header soldered on, and the shield with its assorted parts.

I was all set to figure out how to reverse-engineer the pinout on the bottom of the display; I googled for the LED module, and found specs on those, and then on a whim, decided to check on the entire module board, a Rohm LU-3011, and found the jackpot, this post about figuring out the pinout.  It suddenly became very easy to do this project.

The two key things gleaned from that above post, which I have mirrored here, are this table of enables for each of the 11 digits:

Digit1234567891011
Pin1234681012141618

and this image, showing the pin mappings of the segments:
Mapping of the segments to the pins on the header.

The basic way these displays work is that all of the 7 segments (plus one decimal point) are all tied together to the pins specified above.  Then the anodes for each of the displays are broken out to the pins in the table above.  So to draw a '7', you would set all of the segments to LOW, except for pins 11, 19, and 7 which you set HIGH.  Then to turn on a specific digit, let's say digit 11 (rightmost), you set the digit enable pin 18 to be an output, and set it LOW.  Set all of the other digit enables to be inputs (tri-state, not low or high), and only position 11 will show a "7".  You repeat this for all of the 11 digits in the display, and you can display 11 full digits from just those 19 pins. 

In my code (available below) I start at digit 1, and work down to digit 11, enabling each one, in turn, showing its segments, waiting 1 millisecond, then disable that digit, move on to the next one.  Because of this quick display time, and to preserve brightness, I did not put any current limiting resistors in the mix.  Perhaps this was a bad idea, but it works great for now. ;)

I soldered a pin header on the display, and built up a shield to plug it into.

All of the digit enables wired up.  The top ones are a bit messy. Sorry about that.

I wired it up such that the digit enables and segments are wired directly to IO lines on my Arduino.  This used all of the IO lines, minus the D13 pin, which has an on-board LED.

The code that I wrote (available below) lets you do arbitrary digits per character, so that i can do (primitive) alphanumerics, or do animation patterns, etc.  I also store the decimal point as a separate character going in to the display code, so "3.141" is five ascii characters going in, but a flag is set on the '3' position saying that this digit should also display its decimal point, so it only consumes four digits in the display.

just testing out all of the segments and digits

For now, it displays a nice clock and some animations on my desk, but I plan on changing it around a little in the near future.  I want to use the D13 line as one of the segment enables (probably decimal point) and move the segment enables off of the Serial Receive line.  That way i will be able to control it via serial to display patterns, animations or text content.  Since the hardware serial port is hardwired to 0 and 1, and I will be using the TX line for the LED displays, I'll have to instead use the Software Serial, with only its Receive line mapped to an IO pin, and its Transmit line mapped to junk. I've done this before and it works well.



This project was constructed and started at the Interlock Rochester hackerspace.

Monday, November 5, 2012

Reverse Engineering a Stepper Motor Controller


I often check the recycle pile on the loading dock at work.  I sometimes find smallish hard drives, old laptops, and various other bits and bobs that I might use for various projects.  Often, most of them are useless, broken, beyond any sort of repair, but occasionally, I find something that is really useful to me, or I see the potential in something I find there.


One day, I went back there and found a few boxes of stepper motors attached to motor controller widgets.  There were a few different models of these widgets, but they all seemed similar.  They have a standard D-15 connector on one end and a 4 pin Molex pin connector on the other side.  When the guy who put them out there saw that I had grabbed a lot of them, his only comment was "You don't want those... they're (explative deleted)!"  I was about to prove him wrong.

The little stepper motor controller widgets intrigued me.  I figured that I could use them to drive the motors or do something interesting along those lines.  Turns out that the motors themselves are in fact... garbage, but the controllers would show to be very useful.  I got access to some code that would talk to them, along with a few of the original wiring adpaters as seen above, with a D9 for serial RS232 control, and a two pin molex for power.  I figured I could hook up power and drive them directly.


There are two different versions of the D15 widgets.  One has a metalized plastic shell, the other has a metal shield wrapped around it and appears to have been potted with epoxy or hot glue.  I cracked open one of the plastic shelled ones, and was checking out the innards.  I figured i had a lot of them, might as well see what was in there.  Both of these different styles have the same inner board.


As you can see, there is a power regulator (8 pin package), power transistors for the stepper motor coils, an LED, a 7.37 MHz crystal and a micro.  The micro is an ATMega 168. This is the same chip used in the older Arduino boards, albiet at 7.37MHz instead of 8, 16, or 20 MHz.  If I could figure out a way to get the Arduino bootloader onto one, or just make a programmer interface for one, then I could use them all as Arduino-compatible micros.

At this point, the possibilities of use for these things became apparent.   I went back to the loading dock recycle pile and snagged the rest of the widgets, leaving the (mostly broken) stepper motors there to be recycled.


I sat down and with very sharp eyes, traced out the wiring of the ATMega chip to the D15 header, the various components and everything.  I also mapped out what the components on the widget are in Arduino parlance.  In retrospect, I should have taken a photo or scanned the board and enlarged the image on my monitor.  Live and learn.



As you can see, there's a few pins missing, such as most of the analog inputs (lower left) but there's a lot that's there.  The important things to note are that the D15 carries all of the things important to reprogram these things, as well as to make them useful for other projects.  Power, D0/D1 for serial, reset, a couple analog, and the programmer header pins D10-D13.  I color coded the pins on the D15 connector side to match the wiring harnesses I made.  L is the LED. 0,1,2,3 are the stepper motor outputs, and T is a test point header on the board.



The first thing that I made is pictured above.  It's a D15 to FTDI header cable.  This would let me find out a few important things.  First of all, I can power it, and talk with it via Serial to see if i can even
do that much.  Sure enough, I set the Arduino IDE's serial monitor to 57600 baud, and was seeing text have affect.  If nothing else, I can use these as stepper motor controllers.

I had a few concerns about reprogramming these things.  First of all, I wasn't sure if the chips have had their write protect fuses burned or not.  This would prevent me from shoving any code of any kind onto them.  The other major concern was that with the crystal at 7.37 MHz, it was an unknown if the Arduino bootloader would even operate correctly.  It requires a RS232 connection to the host computer.  If I were to use an 8mhz crystal on it, the baud rates would be outside of the RS232 tolerances and it wouldn't work. (It would be about 9% off.)

I decided that for this whole exercise, the best plan of attack was to do each step along the way with minimal effort, so in case I hit a dealbreaker snag, I could just walk away from the project without too much loss of effort.


The next step was to make the above cable.  This let me program a D15 with minimal effort.  The idea is that I would install the "ArduinoISP" software on a "host" Arduino, and just plug this, with a D15, directly into it.

I loaded up the host with the programmer, and plugged this in to the D15.  I was able to program the widget with an 8mhz Arduino bootloader. (select the proper device type, then "Tools", "Burn Bootloader")  Sure enough, it worked!  Well, it wasn't able to run properly when hooked up through direct FTDI, because of the baud rate issue I mentioned being concerned about earlier.  I took the "Blink" sample code, changed it to use D8 for the LED, held SHIFT while hitting the upload button to upload through ISP programmer, and bam!  The LED was blinking (although slightly slow).  Needless to say, I was very excited at this point.  If nothing else, I could program my own code from the Arduino IDE using this method..


There was a problem though.  It was only able to successfully program about 1/4 of the widgets I tried.  3 out of 12 worked, the rest failed.  Even at this rate, I'd still have 25 widgets I could use.  I looked into the problem more, and it turned out that the issue was with the programmer itself.

The problem was that as the Arduino interface connected to the host Arduino, so that it can send the new firmware through it and down to the target widget, the act of it connecting to the programmer forced a reboot onto the host Arduino, shoving it into an awkward state, unable to react properly.  After some scouring the net (the use of Arduinos as host programmers is fairly scarce.. It's mostly in forums in the form of "I can't get this to work" ... "nevermind. I got it to work.")

I came to the realization that I had to somehow prevent the host from resetting.  There were two different versions of this that I've found.  One is using a 120 ohm resistor to power, or a 10 uF capacitor to power.  I deicded to combine the two, because why not, and came up with the right top portion of the following diagram:


The right side of this also shows the indicator LEDs, which show what the programmer is doing.  I figured I had to make a board for the reset circuit, I might as well add the indicator LEDs too.  I unfortunately arranged the board poorly.



I later rearranged it to have space on the board for a ZIF socket to direclty program ATMega or ATTiny chips, which I'll show in a future post. (Yes, the layout bugged me to the point that I wanted to rearrange it.)

In any event, using this new circuit was easy.  Plug the board in. remove the 3 pin jumper, dump the ArduinoISP project onto the host.  Then shove the jumper back in place, plug in the target, select the target device type, and shift-click "upload", and I was able to get 100% success rate on every single widget I wanted to program.

The next issue was the crystal speed.  I posted to the Arduino forums, asking how to rebuild the bootloader myself.  Long story short (which you can read there), after some suggestions for replacing crystal and such, which I was about to do, Tom Carpenter responded with not only a compiled bootloader for this specific frequency, but with very detailed instructions about how to get it working.  Thanks again, Tom!

I got this all set up on my system, downloaded the firmware to the widget, then plugged it in through the original FTDI cable I made earlier, and I was able to get the modified blink code above to work, while programming it through the standard Arduino interface without issues!  I then extended the code to read and write serial to control the LED, just to prove that I was able to do everything on this.

I felt that the next important step was what I call "self hosting".  This step replaces the host Arduino, the one that runs the ArduinoISP software, with another D15 widget.  With the help of getting the definition of the board above, this was just as hard as making up a wiring harness.  On this one, since I could disable the reset line by simply disconnecting it, I did this instead.  On the FTDI interface board, there's a small white jumper that I can remove or install if I want to enable or disable the reset from the host computer.

This gets a little complicated to look at, but basically the top D15 connector is the host that runs the ArduinoISP software, and the bottom is the target device that will be getting programmed. If you notice D10-D13 are connected from the target (pins 4-7) directly up to 5-8.  The reset line of the target is connected to D10 on the programmer, so that it can reset the target.



In execution, it's a little easier to understand.  The above shows the FTDI board connected to a USB cable on the left, and the interface board with its white jumper in the top center.  Next is the host device in the bottom right, which contains the programmer software.  Then the center-left connector is where the target plugs in.

I was concerned about the timing being slightly slow (9% as mentioned above) affecting programming of the target devices, but it turned out to not be an issue.  Like the above one, using a shield and a real Arduino, this is also 100% reliable as far as reprogramming target devices.





At this point, it's basically done.  I've fully documented the widgets, I'm able to reliably program them... Next up was to show off a bit.  The first thing I did was the above. I wrote a simple Arduino sketch that rotates the stepper 360 degrees, then rotates it the other direction a random amount, blinking the LED.  I set this on my desk at work with a Tron Light Cycle, using a stepper that mostly worked, just as a slap in the face to them saying "look... these things are actually usable!"



I decided I wanted to play with charlieplexing some LEDs, (article to come in the future), so I made the above interface board (which I could also plug into a standard Arduino for debugging it).  I plugged this one in to a 9V battery, and left it on my desk.  On the display I had it flashing the text "(company name) RULES! !"


All of this happened a couple hours here and there, a few hours at the workbench at home, a few hours at the workbench at Interlock.  Probably 20 hours total, stretched out over a couple of weeks, with the end result that I now have a huge amount of Arduino-programmer-compatible microcontrollers for free!

Soon, I'll tell you about a project to use these things; using dental floss containers as project boxes!


NOTE: There is an addendum to the circuits in this post over here.