Saturday, August 02, 2025

Yu Suzuki: Game Works [Chapter 2] - Hang-On


In July 1985, Yu Suzuki released Hang-On. The original plan was for the player to rock a bike-shaped cabinet, containing a CRT monitor.
 

The challenge I was set was to figure out how to turn this into a game. 
The initial concept proposed using a 'torsion bar'; technology which would have rotated and provided resistance. 

By tilting the cabinet, players control the on-screen rider. This marked the birth of the world's first full-body immersive experience in a game. 

Just two years after joining Sega Enterprises, how did Yu Suzuki come up with the idea for "Hang On" and make it a reality?

The development code for Hang-On was 'H.O.'

We refer to games in development by their codename, not by their product name. This is to prevent those outside of the company from establishing what we're working on. 

When asked, "What is 'HO'?", I'd say, "These are Hiromi Oka's initials..." [a real Japanese basketball player but also a fictional character from a manga] 

"What, the one from 'Aim for the Ace!'?" [the manga about a professional tennis player]

"Yeah, that's about it!"

And if I was asked, "Is it a tennis game?"

I'd try to evade the question by replying, "Hey, no more information than that..."

----

Major events in 1985

  • In March, the Science Expo 'Tsukuba 85' was held.
  • In August, 520 people are killed in the Japan Airlines jumbo jet crash.
  • The Hanshin Tigers win the Central League for the first time in two years and become Japan's first champions, sparking a "tiger fever" in the Kansai region.
  • In the world of J-Pop, Onyanko Club become a social phenomenon.
----

When a thick, springy, metal rod is twisted in one direction, it tends to return to its original orientation. We wondered if we could use this repulsive force.

However, during prototype testing, we found that it was difficult to maintain the angle of the bike with a torsion bar. Furthermore, I intuitively felt that it would be impossible to use a torsion bar in this game. In other words, the project began by rejecting the concept that was the starting point.

You might think that this decision was presumptuous, coming from a rookie who'd only been with the company for two years. But the reason I intuitively knew that torsion bars couldn't be used was because I used to ride motorbikes.

The term 'hang-on' refers to the posture a rider assumes when taking a corner at high speed on a bike. You lower your upper body as if hanging onto the handlebars, and spread your legs wide enough that your knees touch the ground on the inside of the corner. That's the hang-on posture.


A motorcycle cannot corner well unless it can support the rider leaning at the correct angle, to suit both the curvature of the corner and the speed at which it was taken. However, it was difficult to recreate this with a torsion bar. The movement of the torsion bar is sensitive and has a tendency to bounce back, causing ongoing vibration. It was difficult to lean and angle the bike consistently, which meant the experience and feel of riding a motorbike was lost. 

My first proposal was to install a gyroscope inside the cabinet. On a real bike, when you open the throttle, the body of the bike will rise up. I wanted to control the gyro through the game's throttle, so that the cabinet would lean like a real bike. In other words, it was an application of the "Chikyu Goma."

However, cost considerations made this idea unrealistic. Games for amusement centers have various constraints. Safety is of course paramount, but size and cost are also important. In the end, we settled on the idea of using human power to move the cabinet for Hang-On.

Hang-On, the world's first immersive game, was made possible only by Yu Suzuki, who rides motorcycles himself and knows all about the joys of riding them.

But the game isn't just a simulation of the feeling of riding a motorcycle; it allows you to do things that weren't possible on road bikes at the time. And for Suzuki, it's a tribute to the great Grand Prix rider Freddie Spencer.



Hang-On intentionally changes the way bikes behave compared to real road bikes. The game allows you to control the bike's drift, which was impossible with road bikes at the time.

On-road motorbikes can experience a phenomenon known as 'high siding'. When riding at high speeds that exceed the tires capabilities, they can lose grip. The rider then releases the throttle to regain control. However, the shock of regaining grip causes the motorcycle to lose balance and the rider is thrown over the handlebars. 

On an off-road bike, the tires don't grip the ground perfectly, so high siding is rare. Even if the tires start to slip, you can control the bike by working the throttle and shifting your center of gravity. For me, the pleasure of riding an off-road bike, using your whole body's sense of balance to ride through the centrifugal force and speed, is something I really enjoy.

I wanted to bring that 
indescribable feeling of fun to life with Hang-On.

However, Hang-On is a game that simulates on-road motorcycles, not off-road motorcycles. This is because I was a big fan of Freddie Spencer, who was active in the GP500, and I had the deepest respect for him. 
Spencer was a star. He was bigger than anyone.

If we tried to simulate on-road behavior as closely as possible, it would be too difficult to play as a game and not much fun. So we decided to avoid high-siding.

Instead, Hang-On allows you to control the feeling of riding with half grip, or drifting.

With on-road racing, the only sensible option is the GP500. This style of racing does not involve drifting
, but we said, 'Let’s make it possible!'

So, without hesitation, we settled on the GP500 concept for the game bringing the fun of off-road riding to road bikes! It's also the best part of the game.

The time has come when lifts will be possible for real on-road bikes as well.



Later, in 1993, 
Shoichiro Irimajiri [former Honda engine developer] became vice president of Sega Enterprises. I was excited and exchanged words with Irimajiri-san.

"He's from Honda. He's been racing for a long time. I'd love to hear his story."

Before long, we started calling each other "Iri-san" and "Yutaka."

"You're Suzuki Yu, the creator of Hang-On. You created a really fun game!"

"Yes. I was obsessed with Freddie Spencer. That game was a gift to Spencer.

"Spencer? I was the one who invited him to Japan!"

After that, we had a great time talking about Spencer's memories. 
Iri said that Hang-On was a simulation of how motorbikes were set to evolve.

"Hang-On allows you to enter a corner while braking. If you had tried that with a bike of the era, you'd fly right off! What's more, in Hang-On, once the tires start to slip, you can use the throttle to control the corner. That's possible with today's road bikes, but when Yu developed the game, it was a technique that no one could pull off, except Spencer. Why did Yu do that? How did he have such a deep understanding of the future of bikes?

I asked Iri why it wasn't possible to drift on road bikes at the time. He explained,

"Old bikes had weak frames. They couldn't withstand the G-forces and would twist. When they twisted, a force was applied in the opposite direction, causing the vibrations to continue. This caused a high side."

It's the same concept as the torsion bar. Honda's engineers knew that if they could control drifting on road bikes, it would be an advantage in racing. They searched for a way to make it possible. The solution to that problem was to increase the strength of the frame.

"But increasing the frame strength by 30% or 50%, didn't help. Even doubling or tripling it didn't solve the problem! I finally gave up, wondering if increasing the frame strength was doable. Then one day a guy brought in a bike with a steel frame. I saw him race on the circuit. With this bike, he was able to control the throttle even when he started drifting. He was even able to enter corners while braking. It proved that if you have a strong frame, you can control the bike after all."

How strong should the frame be? Iri and his team arrived at an incredible figure of 20 times stronger than conventional frames.

----


Hang-On sported an incredibly luxurious cabinet. 
It was like a real Grand Prix bike of the era. However, Suzuki Yutaka was still not satisfied. His goal was not just to recreate a real motorbike, but to recreate the joy of riding a bike and the joy of maneuvering it successfully. 

During development, I was serious about putting a real engine in the cabinet, but people around me thought that was a stupid thing to suggest.

There are many things that make a bike so appealing. The speed at which it travels. The exhilaration of controlling the machine. The wind against your cheeks. The vibrations transmitted through the seat and handlebars. And the sound of the engine. We wanted to recreate all of that.

However, I just couldn't get the engine noise to sound realistic. So, rather than spending extra money, I thought it would be quicker to simply use a real engine, even if it was only 50cc. But then, how would I deal with the exhaust fumes? I seriously considered using a duct to vent them out of the amusement facility!

Additionally, I wanted to install a 40cm low-frequency sub-woofer in the tire area.

Furthermore, we wanted the sound to be loudest for the player, not those around them. We seriously contemplated how to achieve this. We even tried installing a duct and motor next to the monitor to blow air onto the player's face!

In the end, due to cost and other issues, we were only able to achieve a small part of what we had hoped to do.

Sound effects are one of the most important parts of a game, as they provide the player with a sense of realism. Up until then, game sounds had consisted of sound effects rather than music, which I was not happy with.

Why do games only have sounds like 'beep' or 'bloop'? Are beeps the main sound? There are various issues, such as sample data size and sound chip limitations, but we have synthesizers and should be able to generate a richer variety of sounds. I knew it was possible with today's chips. It's just that no one had done it yet, or so I thought.

I think Hang-On was probably the first arcade game to have an entire song with proper music.


One game that Suzuki later created was F355 Challenge. This game faithfully reproduces the driving style of the Ferrari F355, and was of such high quality that Ferrari was the first to license it. It was so well-made that it was said that professional racing drivers would play it during the off-season to study the tracks.

So you could say that a good game is a good simulator. Is that really true?


There are very few complete simulators in the gaming world. I think F355 Challenge is the only one that can be called a true simulator.

What I wanted to achieve, for example, was to compare the performance of a professional racer with a boy who loves video games in the same environment. 

You can't recreate G-Forces in a simulator, even if you get the braking zones spot on. But you can supplement that missing information with visual cues - for example the car nose-diving on screen - to ensure the game works as an accurate simulation. 

Many think it's enough for a simulation game to partially represent the real thing, but that's not the case. The parts that cannot be represented 1:1, must be accounted for. And simulations must also pursue the fun of the experience itself.

If you were to ask me which is the most fun, racing a real Ferrari or playing F355 Challenge, I would answer without doubt - the Ferrari. Even if you want to make a game more enjoyable than a real car, you can't do that with a simulation. A simulation is an imitation of a real experience. It may come close to the real thing, but it will never surpass it.

With a simulation, a professional racer will get better results when playing. 
With games other than F355 Challenge, no matter how well they advertise themselves as simulations, a boy who is used to playing games will achiever a higher score. 

But with F355 Challengeif a gamer practices 50 times and Schumacher practices 50 times, Schumacher will always be faster. This game has finally made my dream come true.

----


This book contains five arcade games created by Yu 
Suzuki in the 1980s, contained on a Dreamcast game disc. In other words, they were originally arcade games that were ported to consumer consoles.

Arcade games and consumer games are on completely different levels.

Will there be more convergence between the two?


At the time we developed Hang-On, amusement facilities had just started to be called game centers. To be honest, they didn't have a very good image in society. They were somehow thought of as hangouts for undesirables, and indeed there was that aspect to them. Everyone wanted to change that image. We wanted to create a brighter space where women would feel comfortable visiting alone. We also wanted to create a space where parents wouldn't scold or worry if their children said, 'I want to go to the game center!'

To do that, I thought, 'I have no choice but to change the style of my games.'

When I make arcade games, I think, 'Let's create something that can never be expressed on a consumer device.' I believe that this is the added value of arcade games, and I have always tried to create something that consumer devices could never imitate. However, when porting arcade games to consumer devices, I make them with the mindset, 'The experience may differ but I'll faithfully reproduce the quality of the arcade version.'

The reason I was making games exclusively for arcades in the 1980s was because there was a huge difference in performance between commercial and home machines at the time.

If you create a game with the expectation that it will be converted to low-end hardware, you won't be able to take on new challenges.

I think that was basically the right way to think about it, but that way of thinking no longer applies because the performance of consumer devices has improved dramatically.

Of course, there are differences between arcade and consumer games, such as the lack of game time restrictions and the change in memory media to large-capacity CDs and DVDs. However, the essence of both arcade and consumer games is the same. The only difference between the two is input and output. 

The input device for arcade games is located on the panel of the cabinet. On home consoles, it is equivalent to a gamepad. There are many different types of input devices, including various sensors, but the fact that these inputs send signals to the heart of the computer to do something is the same for both arcade and home console games.

In the case of Hang-On, a sensor on the bike's cabinet detects the angle at which the player is leaning, and sends a signal in. The output device refers to the motor, hydraulic drive unit, or the cabinet itself.

The core of my work is what's between these input and output devices, and no matter what's connected to either side, it's essentially the same.

Rather than the difference between arcade and consumer games, the bigger difference is the difference between RPGs and driving games, and between puzzle games and shooting games.

For us developers, it's much more important to consider how to adapt the concept to suit the type of game.

----


The overnight success of Hang-On made Yu Suzuki's name well-known in the gaming world almost immediately. 

What kind of changes did this bring at the time?


After Hang-On came out, a company tried to poach me. In order to complete Hang On, I continuously 
worked overtime and barely made it home at the end of the day. 

This company offered to double my salary and also include overtime pay. Plus there was a surprisingly large sign-on bonus. They even said they would provide me with an apartment!

I wondered why he didn't accept the offer and resign from Sega.

I don't think it was a matter of loyalty to Sega or anything like that. I don't remember much about it. However, I do remember what I said when I turned him down.

'Is that what I'm worth?'

And that was it. I remember that even though I was feeling shaken, I replied very coolly, without changing my expression at all.

This may have be a youthful mistake. But, no matter how tough things get, there are times when a man feels like he has to endure the situation. It's not always like that. My feelings wavered whilst being 'poached', but I wanted to appear 'hard-boiled'!

After that, I was headhunted multiple times, but I don't recall all the details. 


----

Thursday, July 31, 2025

Yu Suzuki: Game Works [Chapter 1] - English Translation



Translation Preamble

I’ve owned this book for nearly 25 years, and only recently do I feel that machine translation has advanced to a standard where I’m comfortable using it as a basis to translate the text reliably into English.

I do not speak Japanese. I’ve translated this book using a combination of online tools and manual edits for clarity. It is possible I’ve misrepresented something that was said or unintentionally changed the tone of the dialogue. But overall, I think the results are perfectly enjoyable and enlightening.

I found Google translate reliable for what is a verbose text, containing a significant number of technical and cultural references. I did cross reference its output with LLM tooling, but I found the latter has a tendency to hallucinate information not present in the source material, despite producing more fluid prose. Therefore, I mostly used the former as a basis, before reworking some sections for readability.

I’ve removed small portions of text that were either repetitive or nonsensical after translation.

Personal editorial comments are [shown like this] and are not present in the original text.

Due to the more advanced layout of the original book, some footnotes may not appear in exactly the place they first appeared.

A PDF of the original book can be found here.

If you republish elements of this translation, please do post a credit back to this blog.

----

Monday, April 12, 2021

Ripping Sega System 16 Sprites & Palettes: A Brief Guide

I recently updated and released the source code to Sega Sprite Viewer. This tool allows you to view the contents of sprite roms from many popular Sega games of the era. 

Hardware that (should) be supported includes:

  • Sega Hang-On Hardware (including Enduro Racer & Space Harrier)
  • Sega System 16 (Golden Axe, Altered Beast, Shinobi etc.)
  • Sega System 18 (Moonwalker, Shadowdancer etc.)
  • Sega OutRun  (including Super Hang-On)
  • Sega X-Board (AfterBurner, Thunderblade etc.)
  • Sega Y-Board (Power Drift, G-Loc etc.)


Part 1: Viewing Sprites

Let's take an example System 16 game, in this case Altered Beast. First up, we can establish the configuration of the sprite roms by looking at the MAME System 16 driver here


We can see the sprite roms listed above in the highlighted yellow section. We can also see how these are configured in memory. The first step is to copy the sprite roms into their own directory. These should be referenced by creating an XML configuration file for the sprite viewer called altbeast.xml.

  • Format 0 specifies System 16 sprite format. 
  • This example places the sprite roms in a sub-directory named roms/altbeast/ 
  • The offset and length of the files are configured to match the MAME driver.
  • You can view the final configuration file here for reference. 
Now we can load the sprites into the viewer by passing the name of our XML file as a command line argument:
s16_viewer altbeast.xml


Everything looks good. And you could stop here if you wanted. But you might be curious as to why the graphics are greyscale...


Part 2: Extracting Palettes

The sprite roms themselves don't contain colour palette information, or in fact anything particularly useful beyond the raw pixels. Palettes are contained in the actual 68k CPU program code. The process for extracting the palette is different on a per-game basis. But the general principles remain the same. Here, I'll discuss how I extracted the palette data for Altered Beast.




Establish the location of Palette RAM

Altered Beast is a System 16 based game. For System 16 games, the location of palette RAM is allocated dynamically at run-time by the Sega 315-5195 Memory Mapper. (Note, that other Sega hardware titles will configure the location of palette RAM differently - the point is that it's a sensible first step to determine its location).

Using the MAME debugger we can view the configuration of the memory mapper once the game is running:


  • View the 315-5195 Memory Mapper m_regs configuration.
  • The yellow highlighted value ($84) at offset $1d contains the details we are interested in.
  • This value is left shifted by $10, giving us the location of palette RAM: $840000
  • Often the sprite palette is at offset +$800 within the palette RAM. Therefore $840800. (I know this part through pattern recognition, but it can also be established from decompiling the code further, as we shall see later.)
I can sanity check $840800 is the right location for sprite palettes by filling its contents with garbage whilst the game is running.


Here, I've filled the fast part of RAM with the value "$1111" repeatedly. As you can see from the circled sprites, these have lost their palette information and are rendered as black silhouettes.

Now, we could just save the contents of palette RAM at $840800 into a file and load that directly in the sprite viewer. However, this wouldn't contain all the palettes the game uses - only the ones loaded into memory at this moment in time. Therefore, it wouldn't be particularly comprehensive. We would find that many palettes were missing.

Establish where Palette RAM is populated from

If we can establish where the palette RAM is populated from within the code, then we are highly likely to locate the data table containing all the palette information. We can set a memory watch point at $840800. This will informs us when palette RAM is written to, and the part of code responsible for this.


I've set a watchpoint at $840800-$840804. Whenever a value is written to this address program execution halts. 

We can now view this section of code that copies data into sprite palette RAM in more detail in the MAME disassembler. I've annotated this with some comments, in green, on the right hand side. 


The main takeaways from this section of code are as follows:
  • Address register A2 points to a table of address information containing the source address in ROM and destination address in palette RAM to move the values between.
  • Address register A0 is loaded with the source address. (a location in the program ROM)
  • Address register A1 is loaded with the destination address. (sprite palette RAM)
  • It should be noted that 28 bytes are copied, not the full 32 bytes required by sprite hardware. This is important palette format information we will need later.
Now we can step through this routine to get some clues as to where the palette data is originally located. However, as all addresses are setup from address register A2, we need to mine deeper into the code still, to establish where this table of pointers is first configured. 

By watching the memory location specified by A2, we can work our way back to the following program code:


From this section of code we can not only establish where the first palette entry is stored in rom, but also the total number of entries. This key points are as follows:
  • A byte is used (0-255) as an index into the table of entries. So we can assume that the palette table contains 255 entries max (highlighted in yellow and loaded to D0).
  • This routine specifies $242a0 as the first sprite palette entry (highlighted in yellow and loaded to A1).   
  • We established each entry was 28 bytes previously. This means the table is $1be4 in length (28 bytes * 255 entries).

This gives us the final solution to our puzzle. We know where all the palette entries are first stored, before palette RAM is even accessed. We also know how many entries are in the table. 

Save the Palette table to a Binary file

We can now save the palette as follows using the MAME debugger:
save altbeast.pal, 0x242a0, 0x1be4, 0

This can be added to our sprite viewer XML configuration as follows:


We specify the number of bytes per entry, and the fact that the palette data is offset by 1 word when displayed by hardware. Essentially, the sprite hardware expects 32 bytes per entry, but the first and last words are not populated in the palette data.

Viewing the Palette

Finally, we can load the sprite data and view it in glorious colour by cycling through our 255 palettes. One limitation is that we still have no way of automatically connecting a palette to a sprite. This information is also contained in the 68k program code and is unique on a per-game basis.


I hope this has been informative! If you successfully create both a palette and configuration file, let me know and I'll add them to the source code repository. 

Monday, March 15, 2021

CannonBall V0.31 - Maintenance Release


This release focuses on upgrading the libraries and compilation tools CannonBall uses, as I hadn't maintained the codebase in a number of years. Most of these changes will be invisible to most users. Right now, I'm trying to get the house in order as opposed to add lots of wild new features! :)

The most exciting news is the upcoming SmartyPi support, but until the hardware is released, that's kind of a mute point!

Changes:

[audio] Audio updates at the correct rate and resolves the longstanding issue with music and sound being very slightly 'off'

[roms] ROMs are now read by CRC 32 value. Filenames no longer matter - so long as they are present they can be renamed to anything.

[roms] Fixed expected Z80 rom file length

[controls] Start Button behaviour less 'sticky' and buggy

[controls] Analog axis for accelerate and brake can now be configured via the in-built menu system

[menu] Reduced delay when scrolling through menu with analog controls

[config] ROMs and save data can be relocated to separate locations

[bug fix] Time Trial mode no longer crashes if used as the first mode played

[timing] Code tries to use V-Sync for timing OR internal timing, as opposed to both at once

[source] SDL 2 used by default. SDL 1 removed from codebase. This appears to have fixed compatibility bugs for some people

[source] Added compatibility for upcoming SmartyPi hardware (Pi 4 based) to run on original arcade hardware

[source] A general clean-up in many areas

Friday, May 29, 2020

Sega X-Board Memory Test Software

A set of ROM images to test the RAM ICs and custom chips on Sega X-Board hardware (AfterBurner, Thunderblade etc.). It is more robust than the on-board tests and stands a better chance of running on a dead boardset.

  • It does not require working main RAM to actually run the main RAM test.
  • Remove all sub CPU EPROMs when installing (IC 20, IC 29 etc), as these interfere with the results.
  • It requires a vanilla 68K CPU to be installed, not the FD1094 security processor present on some X-Board games.
  • The palette will be incorrect when used on games other than AfterBurner. But it should still operate correctly. 

This was not previously released, because I hadn't verified the IC labeling on hardware. However, a number of people have already used this software to successfully fix PCBs. Therefore, I figured I should get this out there and address problems as they are reported.

This is based on the OutRun Memory Test. The modified (and messy) source code is available here

The compiled ROM images can be downloaded here

Wednesday, April 29, 2020

OutRun: Enhanced Edition 2.02

OUTRUN: ENHANCED EDITION V2.02

OutRun: Enhanced Edition is a set of 7 replacement EPROMs intended for use on original OutRun arcade hardware. 




It fixes many bugs present in the final official codebase (Rev. B), and introduces new features to extend the life of the game, including: 

  • Working Free Play Mode
  • High Score Saving
  • Additional High Score tables
  • 3 additional in-game audio tracks
  • Best Track Time (aka ‘Lap Time’) records
  • New and old course layouts
  • Software DIP Switch support
  • Cheats - including infinite time and the ability to disable traffic
  • Optional car handling modifications

Full documentation and installation instructions


To register:
1/ Complete this form

Sunday, March 08, 2020

Space Harrier: The protection strikes back!

This is a guest post from Adrian Smethurst

It was back in January 2015 when I first started looking into the Space Harrier code on reports of a ‘bug’ which gave the player ‘extra' lives when they lost a life.  This ‘bug' only affected the game when played in either MAME, on an Enduro Racer converted board or a bootleg Space Harrier board.  It turns out that it wasn’t a bug but rather a time delayed protection mechanism created by Sega to try and hit the arcade operators, who bought bootleg Space Harrier boards back in the mid 80’s, in the pocket.  You can read more about that here.

Space Harrier PCB with Intel 8751 Microcontroller

Fast forward 5 years and a conversation I was having with respected indie game dev and creator of Fortress Craft, Adam Sawkins (ex. Criterion and Codemasters) about Space Harrier, at Arcade Club Leeds.  He asked me why, after the game had been powered up for a while, the enemy shots would start to come at the player faster and faster, to the point where you’d need lightning quick reflexes to simply avoid them.  He also told me that a reboot of the game would reset the enemy shot speed back to normal again, for a short while.  Hearing this news immediately sent my mind drifting off to a time 5 years previously when I’d investigated (and presumably fully defeated) the time delayed protection in Space Harrier.

So that night I went home and stated looking further into the Space Harrier code…

The heart of the protection is built around the ‘in-game’ timer.  This is a 6-byte timer located at address $40020 in main CPU address space.  The first 4 bytes of the timer represent the ‘seconds’ of in-game time played and the final 2 bytes represent the sub-second (frame) timer.  The timer is reset to zero at the start of each new game.  The timer is only incremented during normal gameplay, attract mode gameplay doesn’t increment the timer.  Every vertical blank the sub-second timer is incremented and compared with a value of 61 (yes, it’s a bug!).  If the sub-second timer is greater than 61 then it’s reset to zero and the ‘seconds’ part of the timer is incremented.  This means that, due to the bug, 1 second on the ‘in-game’ timer is actually 62 frames of gameplay, rather than 60.  The code that increments the ‘in-game’ timer is at address $1514 (it also updates the power-on timer located at memory address $40000 at the same time).

During every frame of normal gameplay code at address $4aae checks if the ‘in-game’ timer is at a multiple of $200 (this should, in theory, have been every 512 seconds but due to the bug mentioned above is actually every 529 seconds) and if it is the following code is executed :-

004ACC: move.w  $12444e.l, D0   
004AD2: move.w  $404ee.l, D1
; d0 and d1 never seems to contain a value other than 0 after many hours of gameplay testing
004AD8: eor.w   D1, D0          ; d0 = d1 XOR d0               
004ADA: cmp.w   $40090.l, D0    ; compare d0 with value at $40090.w
004AE0: blt     $4af0           ; branch if d0 < contents of $40090.w

If the 'branch less than’ condition is false (i.e. IF d0 < contents of the word memory @ $40090) then

004AE4: addq.w  #1, $4008e.l    ; trigger ‘previously unknown’ protection
004AEA: addq.w  #1, $400f0.l    ; trigger the 'increase lives' protection

When I was investigating the protection routine 5 years ago I completely failed to consider the first of these 2 instructions and only concentrated my efforts on investigating the second one.  This is because, at the time, I’d only been made aware of the ‘increasing lives’ issue.  So at the time I worked backwards from the ‘number of lives' counter to find out what was increasing the number of lives.  From there my investigations led me back to the instruction at address $4aea.  At that point I wrongly assumed that the ‘increasing lives’ issue was the only side effect of the protection routine.

How wrong I was…

The word value at address $4008e is directly related to the game difficulty.  It’s a value that's set initially by the boot-up code reading the ‘difficulty’ settings from dip switch B and is set as follows :-

EASY/MEDIUM     0
HARD            1
HARDEST         2

The code which does this is at address $2d7c.  This value is then subsequently used as part of the calculations in the routine which handles the enemy shots at address $b9d2.  It’s easy to tell that that routine handles enemy shots as if you change the first word of the routine from $08ed to $4e75 (RTS) the enemies will no longer fire shots at the player during gameplay.  The higher the value at address $4008e, the faster the enemy shots head towards the player.

Ordinarily the difficulty value at address $4008e would NEVER change after boot, assuming the game code is running on a genuine Space Harrier board with the 8751 MCU present.

However, as you can see from above, the instruction that I completely ignored 5 years ago, INCREMENTS that value (and hence the difficulty level) every 529 seconds of in-game play.

What this effectively means is this - if you power up the board from cold, ensure the difficulty setting on dip switch B is set to EASY and complete the game (assuming roughly 18 minutes for a full playthrough, although I have seen people complete the game in around 17 minutes) then the difficulty will be at the HARDEST level by the time the game completes.

And it will keep getting harder for each 529 seconds of completed ‘in-game’ time.  This is because the value at $4008e is only reset by either rebooting the game or dropping in and out of service mode.  It ISN’T reset at the start of each new game.

It’s very easy to see the results of a higher value at address $4008e by simply changing it via the MAME debugger and playing the game.  Values of 6 and above (which would represent just 3 or 4 full playthroughs from starting on EASY difficulty) make the game almost impossible to play as the enemy shots head towards the player with such high velocity..

Taking a step back, I feel it’s likely that the 8751 MCU probably exposes a value of 1 at address $40090 (it could in theory be any value between 1 and $7fff for the conditional branch instruction at address $4ae0 to pass but 1 is the most likely value, IMHO).  The updated patch has been added to the Sega Enhanced package here.

I hope that this finally lays to rest the protection in Space Harrier.