Search the Community
Showing results for tags 'reverse engineering'.
Found 4 results
I started looking at a disassembly of Melody Blaster, after I became curious as to which ECS games supported tape expansions. My hope is to create virtual tape images for jzintv that can be used to allow extra music into the game. As an intermediate step, I'll try creating a ROM hack with new music in it. The ROM follows the standard memory map for 12K Mattel games: 8K in the $5000-6FFF range, and 4K in the $Dxxx range. Most of what's in $6xxx is the Help text, and it overflows a little into $D0xx. After that is the 11 tunes. There are a bunch of calls in the code to functions at $40xx and $41xx, so the ECS "Executive ROM" must be located there. The ECS does have onboard RAM, and I'm pretty sure tunes are loaded there and then parsed by the ECS EXEC. The list of pointers to the starting addresses of each tune starts at $57E7 (cartridge ROM), with the low-order byte listed first, and the starting address for the current tune is loaded into $354 (16-bit system RAM address). The game allows for one extra tune to be loaded into memory, either from a tape or by playing a tune (one channel only). I hope tape tunes aren't limited to a single channel, but I don't know yet. All the music data fits into 8-bit words, probably because that's the width of the ECS RAM. As for the tunes, the first 18 bytes comprise the title. I looked at the first 2 tunes so far, which both had a 9-byte signature starting with 0 1 1 9 6 6 9 4. After that was the data for each of the 4 channels used by the game (2 sprite-based notes per channel). The channels' lines are listed separately, in order from low to high, and not all of them are used. The music data consists of byte pairs: a note ($18 is Middle-C) or $80 for a rest, and then a duration in "ticks". In most cases, channel data is separated by the signatue 1 1 $80 1, but I found an exception in Tune 2 "ROW,ROW THE BOAT". That signature appears twice in a row in Tune 1 "BLASTER'S BLUES" because one channel is not used. In many cases, channels' music data is prefaced with a rest, because another channel has a starting pick-up. The first channel for BLASTER'S BLUES is the left-hand harmony line, which has a small pause to allow the pickup in the right hand melody line. Then the channel-separator signature appears twice, followed by the melody line. Strangely, the fourth channel has a series of rests which add up to 234 ticks, where it is then used to play a second note in the right hand at the tune's end. There are a total of 9 consecutive rests here, the first 8 of which are 25 ticks each ("$19"), and the last of which is 34 ticks ("$22"). There's a little more data here which I haven't yet deciphered. ROW,ROW THE BOAT is played as a round, with the harmony line picking up a measure behind the melody line. The same value $18 is used for the C note in their respective octaves, which leaves me to believe that the ninth byte in the signature following the title contains bits to tell us which channels have octave offsets (in other words, are meant to be played by the left hand or the right hand). The end-of-channel signature is also absent at one point, so maybe the header signature tells us which channels are not used at all? That's as far as I got so far. I'll take the time to study the other tunes later today. Another interesting point is that there will sometimes be tiny spaces between notes at what appear to be arbitrary points: a note played for 2 ticks followed by a 1-tick rest in one hand and for the full 3 ticks in the other hand. That indicates to me that the music data was created by a device that a MIDI keyboard was connected to, and that data was only moderately cleaned up afterwards to get a consistent tempo across all channels.
Introduction Ok, so I spent a couple days reverse engineering Utopia. I now know pretty much how it all works, and now you can find out too. Here's some highlights, in case you don't want to wade through the code: Forts: Do protect a 1 unit radius against rebels Will protect parked ships that have the same owner as the fort. Radius of 1 card. Will protect both players ships when they're under active control. Radius of 1 card. Do not otherwise contribute to your score Bugs: Scoring will overflow, if you have more than 65 crops + fishing boats combined. It will also overflow if you earn more than 255 gold bars in a single turn. (Is that possible?) The "float off bottom of screen" bug is likely due to island/status collision detection interacting poorly with EXEC's boundary detection. The game can "nudge" a boat across the boundary the EXEC checks for. There is a check for this, but it only has been applied properly to the left/right edges. Delay loop in scoring display appear to want to update random number generator, but they don't actually. Code quality:Let's just say it's likely the priority was to have a compelling game, and have it out quickly, as opposed to writing the tightest, cleanest possible code. Miscellaneous: Pirates will never sail toward a parked PT boat on purpose. The "nudge" code, though, can nudge them through a tangle of PT boats. Hurricanes are 5 times more destructive than tropical storms. All three forms of weather water crops at the same rate, though. There's two copies of the "sinking fishing boat" animation in the ROM, due to how the EXEC distinguishes between background cards and MOB animations Each island has precisely 29 squares. When weather takes out something on your island, it will incur 0 to 101 casualties. If you want more details, you'll have to dig through the code unless it's covered in the slightly more detailed review below. :-) Code attached. Code Structure The bulk of the main game code can be put into one of three categories -- The Timer Tick Task, Dispatches, Scoring Logic. The rest of the code is either initialization code, or support code for those three categories. Timer Tick Task The bulk of the game logic hangs off the the Timer Tick Task. This task runs 20 times a second, and it handles everything from spawning weather to collision detection to animating certain sinking ships. It's quite a lot of code and is fairly linear. The rough order of execution: Update the weather, possibly creating new weather Update the fish, possibly creating new schools of fish Update the pirates, possibly spawning new pirates Island vs. boat collision detection Update the game clock If not end of round / end of game: Update the status line at bottom of screen Update parked sinking ships At end-of-round, fire off the scoring code and then show the scores At end-of-game, show final score and halt Dispatches The next big set of code is the set of Dispatches. The EXEC mostly works by calling various functions in response to various events. Dispatches fall into a few categories: Controller input dispatches. The action-button and disc handlers are pretty simple. The keypad dispatch is amazingly convoluted, but that makes sense when you consider everything that it has to account for. Object vs. object dispatches. These handle pirates vs. PT boats and similar such things. Object vs. land dispatches. This is what handles rain on crops, pirates sinking parked ships, or parked ships going fishing. Scoring Logic The final big piece of code is the scoring logic. Scoring happens in four phases: Income Computation, Population Update, Round Score Calculation, Rebellion. Income Computation During the round, every gold bar you earn (say due to fishing, rain on crops, etc.) gets tallied in this round's Gross Domestic Product (Round GDP), separate from your actual gold bar balance. That is, spending does not subtract from Round GDP even though it lowers your treasury balance. At the end of the round, you get awarded additional gold as follows. Each of these contributes to the Round GDP except for the "baseline 10 bars." 4 gold bars per factory 1 gold bar per fishing boat Productivity bonus: ((Schools + Hospitals) * Factories) + Hospitals, clamped to a maximum of 30 gold bars. 10 gold bars of baseline income (does not contribute to the Round GDP). Population computation -- expressed as a growth rate, resulting in exponential growth. Fertility computation Start with a baseline fertility rate of 5.0% Increase fertility by 0.3% for every crop Increase fertility by 0.3% for every hospital Increase fertility by 0.1% for every house Decrease fertility by 0.3% for every school Clamp fertility to a minimum of 4.0%. You can't have fertility below 4% even if you filled the island with schools. Mortality computation Start with a baseline mortality rate of 1.1% Decrease mortality by 0.3% for every hospital, but not below 0.2%. (This limit is applied before the next step.) Increase mortality by 0.1% for every factory. If you fill the island with factories, your mortality rate will be 4.0%, matching the minimum allowed fertility. New population: Population + Population * Fertility - Population * Mortality. Maximum allowed population is limited to 9999. Round Score Calculation -- roughly, "approval rating", 0-100% First compute the following four subscores: Housing score: ((Houses * 500) / (Population / 100)) / 3. If larger than 30, clamp it to 30. Per-capita GDP score: ((Round GDP * 100) / (Population / 100)) / 12. If larger than 30, clamp it at 30. Food supply score: (((Fishing boats + Crops) * 500) / (Population / 100)) / 3. If this value is larger than 30, clamp it to 30.Note: 65 * 500 = 32500. So, if you have more than 65 fishing boats + crops, this score can go negative. This is fixable by changing the BLE at $5B1E to a BNC, I think, so it treats the overflow case as a case that needs to clamp to 30. General welfare score: 1 point for every school or hospital Add up the four subscores, limiting the total to 100 or less. That's the per-round score. Rebellion Compare this round's score to the previous round, and consider it in absolute terms as well If it dropped by more than 10 points or is below 30 points, add a rebel If it increased by more than 10 points or is above 70 points, remove a rebel If you want to see the exact details of how these pieces work, look at the code. For example, in the scoring section, some divides are rounding divides, and some are truncating divides. The population computation is actually carried out with scaled arithmetic (ie. fertility/mortality rates are multiplied by 10, and population divided by 10 when computing numbers of births and deaths.) For anything else... see the code! ____ [Edited to fix some formatting issues in the nested bulleted lists.] utopia.asm
I stumbled across this video presentation about reverse engineering the MOS 6502, and of course I had to watch it. Quite an interesting watch! I always wondered about the LAX/SAX instructions, and why there aren't similar illegal opcodes for other register combinations. Turns out that the opcode's lower bits define which register is to be worked with, %00 for Y, %10 for A, and %01 for X. %11 is not intended to be used, but when it is used, it causes both A and X to be affected, explaining why we don't an opcode for, say, LAY. As stated in the video, visual6502.org has a lot of information about the 6502 line of processors, and many others, as well. The ultra-high-resolution images of the chip are there, and my nerd wants to print them up and frame them on a wall. I'm not really a hardware guy, more of a software guy, but for some reason I love learning how computers work (or trying to). I guess that's why I prefer the low-level programming languages. Assembly is about as low as you can get without getting into machine code, and it's a lot of fun for something like the Atari 2600. It brings you closer to the machine, and although it doesn't let you see the physical chip layout, it gives you an idea of how it must theoretically work. I would love to try programming for the other old 6502 systems like the NES after I have a 2600 game or two complete, but anything other than that is better suited to a higher-level language. C++ is my favorite language for programming, although Python is nice for simple tasks that you just want to write quickly without worrying about code efficiency.
I'm finally getting around to posting the Blue Whale / Black Whale reverse engineering document. The document calls it Black Whale. But, in talking with Steve Roney and Bill Fisher, nobody there remembers any name other than Blue Whale for this device. In any case, there's extensive reverse engineering notes including schematics, commented disassembly, a user's guide, and pictures. All in all, about 100 pages of goodies. There's one little bit of disassembly on the 6502 side I haven't 100% worked out: The code that stitches the debugger into the KC's menu. The rest, though, is pretty thoroughly understood. Enjoy! ____________ Revision History 2018-04-23, A: Initial public release, immediately withdrawn 2018-04-23, B: Regenerated to fix some last-minute formatting issues. 2018-04-24, A: Corrected descriptions of code that rewinds PC when hitting a breakpoint, and the code that interprets SDBD : [email protected] Rx, R7 when single stepping. Intellivision_Black_Whale_Reverse_Engineering_Report_20180423b.pdf Intellivision_Black_Whale_Reverse_Engineering_Report_20180424a.pdf