Fixing E.T. The Extra-Terrestrial for the Atari 2600

If you're reading this page, chances are that you're already well aware that E.T. for the Atari 2600 is one of the most reviled games ever made. I never understood why. As a child, it was one of my favorite games. I still think it's a good game. Apparently, I'm not alone.

On this page I'm going to briefly explore why people hate E.T., and how the game can be fixed.

Contents:

In case you can't wait

Open your NTSC E.T. ROM in a hex editor and make the following changes:

------------------------------------------- - E.T. is Not Green ------------------------------------------- 17FA: FE FC F8 F8 F8 1DE8: 04 ------------------------------------------- - Difficulty Fix (Walk, Run, Hover) ------------------------------------------- 0707: A4 F8 071B: A4 F8 0685: A4 F8 0FEF: AD 82 02 29 08 4C 4E BB 0B4D: 60 4A 4A 4A 49 01 85 F8 04F0: A5 81 29 1E ------------------------------------------- - Falling Fix ------------------------------------------- 002A: 4C F6 BB 0BF6: A5 9C 69 07 85 F6 4C AB BC 1013: 05 D9 65 E3 65 F6 85 8B 4C 4B F0 101E: 08 E4 8B D0 06 24 13 70 02 85 2C E4 9E 08 E8 102D: A4 86 8A 1034: 85 02 84 1C 1060: A5 87 85 1B A5 88 85 06 8A A8 B1 BA 85 0E B1 BC 1070: 85 0F E4 9F 4C 1E F0 18F3: 2E F0 0B40: A9 EF 07ED: E9 04 0BA5: 22 -------------------------------------------- - BUG FIXES -------------------------------------------- - Don't Fall Leaving Forest on Right ------------------------------------------- 0D54: 4A 0D6C: 01 ------------------------------------------- - Ship Shouldn't Crush Elliott ------------------------------------------- 07BD: 4C D9 BA ------------------------------------------- - FIX SCORING TO MATCH MANUAL ------------------------------------------- 058E: 85 F4 A5 DD 85 F5 65 F4 85 DD 69 10 EA EA 1382: 4C 9D F3 1395: A9 99 85 D3 85 D4 D0 09 A5 F8 D0 02 AA A8 13BD: A9 01 05 DE 85 DE A2 07 A0 70 20 41 F3 EA 1341: A5 D2 C9 0A F0 08 E9 10 85 D2 A2 04 A0 90 A5 DD 1351: F8 4C E9 F7 17E9: C9 1F 90 0A 8A 09 10 AA A5 D3 E9 07 85 D3 D8 60 13FD: A9 99 85 D3 85 D4 A9 00 85 F4 85 E3 147A: A9 00 85 DD 85 D9 85 94 A5 29 C5 DC B0 02 A5 DC 148A: 4C A5 F4 Note: If you don't include the difficulty fix, make the following change to the scoring fix: 139D: EA EA EA EA EA EA ------------------------------------------- - Easter Egg - Ninja E.T. ------------------------------------------- 148A: A5 F4 C5 F5 D0 0C C9 03 D0 08 A9 AA 85 D2 85 D3 149A: 85 D4 4C A5 F4 EA EA EA -------------------------------------------- - Add Extra Game Option - Scientist Only -------------------------------------------- 0471: E0 05 02ED: 29 01 F0 09

Special thanks to AtariAge users Nukey Shay, Random Terrain, KevinMos3, iesposta, and roadrunner for their excellent comments and suggestions.

Downloads

If you don't know how to use a hex editor, or if you're just lazy, you can download a modified .bin file here:

NOTE: If you want to play the game with the original difficulty, set the B&W / Color switch to the B&W position. This will completely disable the difficulty fix, but leave the other changes in place.

Why do people hate E.T.?

So, why do people hate E.T.? When it was released, it was well ahead of its time. It pioneered a lot of concepts that we take for granted in games today, but were unheard of in 1982 (Atari's Adventure and Haunted House had some of these features, but not all):

It was one of the first home video games with a title screen.

It featured an open-ended world with gameplay focused on exploration.

It was completely non-violent. You can't hurt the bad-guys, and they can't hurt you. There isn't even any competition!

You could complete the game. There are also several goals that you need to complete to win the game.

There were multiple ways to complete goals. You can actually finish the game without falling in a single well.

The game not only had an ending, it also featured an animated cut-scene as a reward.

The game featured optional additional goals to complete (side quests).

While that seems like a great list of features, players in 1982 weren't prepared for that much change. You really needed to read the manual to understand the game and how to play it. As younger children were the primary audience, it's no surprise that it wasn't well received.

Of course, that doesn't explain why the game is so hated today. If we can identify the reasons why, we can try to address them. Here are the problems this page will address:

The game seems incredibly complex. This isn't a real problem. Once you learn how to play, it's really very simple. You just need to read the manual, or watch a tutorial video, to understand it.

The game is incredibly hard. It's difficult for novices to complete the game even on mode 3, the easiest setting. Fortunately, this can be fixed.

You spend a lot of time accidentally falling in to wells. I believe that I know reason why this happens to so many people, and what can be done to fix it.

falling in to wells. I believe that I know reason why this happens to so many people, and what can be done to fix it. E.T. is not green. I'm really surprised that this isn't a common complaint. We'll fix that as well.

Why people accidentally fall in to the wells

The myth: A lot of people blame poor collision detection for this problem. That is simply not true. The collision detection in E.T. is perfect. There are no bounding boxes like in more modern games. Collision detection happens at the pixel level. You can't get any better than that. If you fall in to a well, it's because your player character visually overlaps it.

The actual problem: We don't want pixel-perfect collision detection!

The reason that people so easily fall in to wells is that they don't expect to fall when, for example, E.T.'s head overlaps a well. After all, his feet are clearly on solid ground!



Figure 1: E.T. appears to be standing in front of a well. However, because collision detection is pixel perfect and some of the sprite pixels overlap the well pixels, E.T. is sure to fall. This is a bad thing.

E.T. uses a weird perspective not well suited for pixel-perfect collision detection. It's an overhead view, but we see E.T. and the other characters from the side. An article on tvtropes.org calls this "Three Quarters View" and describes it as a "tilted bird's eye view perspective".

Nintendo's The Legend of Zelda uses the same perspective, but you don't hear a lot of complaints about accidentally running in to enemies or obstacles.



Figure 2: A similar perspective is used in The Legend of Zelda though it somehow manages to be even stranger. The floor tiles and blocks, the outer walls, and the player character are all shown from different perspectives. This doesn't hurt the game in any way, it actually makes it better.

Zelda uses a neat trick to make the perspective feel more natural when playing and less like the characters are lying on their sides. Collision detection is designed around where your player character appears to be, not by what sprites happens to overlap. In Zelda, when you approach an obstacle from the south, for example, it doesn't obstruct your movement until about half of your sprite overlaps it.



Figure 3: (Left) Our player character appears to be standing in the row of floor tiles below the block. The player assumes that they are able to move forward as there are clearly no obstacles in the way. However, if collision detection was pixel-perfect they would be obstructed by the block. (Right) Thanks to good design, we can do the obvious: walk on the tiles in front of the block.

If we can modify the collision detection in E.T. so that it's not pixel perfect, but based on where the player character appears to be, we can give the player the same intuitive advantages that Zelda players enjoy. In the case of E.T., such a change is simple: we just need to ensure that only collisions with E.T.'s feet are detected. The game will feel much more natural, and players won't fall in to wells accidentally nearly as often.

Fixing the falling problem

The fix is pretty simple. All we need to do is clear the collision latches sometime before we finish drawing the E.T. sprite. One or two scan lines before the end should work out great. That may not seem like a lot, but it really is the most appropriate place. It'll also let us stand on the inner edge of the "v" shaped wells. I've always thought you should be able to do that.



Figure 4: Where no extra-terrestrial has gone before!

We don't have access to the game's source code and the disassembler I have for 2600 games won't work if the game is over 4k. If we're going to fix the problem, we've got to modify the ROM somehow. A good hex editor coupled with the nifty debugger included in Stella and we're ready to go. That may be a bit optimistic. As every Atari 2600 developer knows, you rarely have and abundance of free space on the ROM and routines (particularly in the kernel) are generally kept very tight with little or no wasted code.

To make matters worse, to implement our fix we'll need to add some code to the kernel. If you're following along, take a look at kernel code starting at 1006. As it's unlikely that Howard Scott Warshaw (the developer) included some useless code for us to replace, we may want to consider hijacking a jump, running our routine in some unused spot on the ROM, and returning. A quick look presents us with a candidate at 1074. We could run our routine and jump back to 1022. Unfortunately, time is also an important factor, especially in the kernel. We don't even have enough time to jump out and return, let alone run our routine. We could use an extra scan line, but that does far more harm than just making our graphics look blocky: candy won't appear and hint areas, for the most part, won't display the location of phone parts. Give it a try if you're feeling ambitious, just don't forget to increment X or you'll end up with a flickering mess!

Back to the kernel we go to see what we can change. A few rounds with the debugger and you'll notice that the code at 101C to 101E ultimately does nothing as there is a TXA right after the jump. Useless code in the kernel is unusual. Looking a little further back, we find that the code starting at 1013 sets COLUP0 to some inexplicably twisted value based on whatever is stored in 81. This is weird because 88 is used to hold that color, as we can see from the code at 1047 to 1049. Even stranger, this code is never called on lines where we draw GRP0. The code from 1013 to 101E appears to do nothing but burn a few cycles. (That's exactly what it's supposed to do, for timing.) After a good bit of double-checking, it becomes obvious that can safely replace it. This is great news for us as that means we have a whole 12 bytes we can change! Since X holds the current y position, that's more than we need for our routine. Lucky.

The idea is to strobe CXCLR before we draw the last line of the sprite so that any collisions recorded to that point are eliminated. The effect will be that only collisions with E.T.'s feet will be detected. The code is pretty simple, 9C holds E.T.'s y position so we just need to subtract some amount of E.T.'s height from our current y position and compare it to the value at 9C to see if we can safely clear the collision latches:

1013: TXA ; 2 ; 8A 1014: SBC #$08 ; 2 ; E9 08 1016: CMP $9C ; 3 ; C5 9C 1018: BCS $F01C ; 2 ; B0 02 101A: STA CXCLR ; 3 ; 85 2C

Give it a try. It looks like we're done, but there are still a few problems:

We can't pick-up phone parts. (We'll fix this a little later.)

We need to step on candy to collect it. (This is a problem we can't yet avoid.)

The routine isn't called when there is another character next to you. (Remember that we discovered the code we replaced was never called on lines where we draw GRP0?) If part of your sprite overlaps a well and another character approaches, the collision latches won't get cleared and you'll fall right it!

There isn't another junk spot we can dump our routine that is always called, so we'll need to find an additional 9 bytes that we can safely overwrite. Constraints are tighter here, as we'll need to find some code that we can eliminate that also happens to be called all the time, or when our other routine isn't. That's a pretty tall order. Could we really be that lucky or will we need to find some code that isn't essential to the game, and deal with any unwanted consequences?

A few rounds with the debugger turns up 8 whole bytes at 1062 that look redundant. Didn't we already handle that at 103B? It turns out that we didn't. Take a look at 1043. The next sprite row is read and saved for later use. Later, sadly, means at 1062. If we replace this code it means that we won't update GRP0 and COLUP0. That means we'll end up duplicating the previous row. We'll essentially be tossing out half of our sprite data. It will appear as though every other line in our sprite was overwritten by the previous line. That sounds bad, but in the end it means that we can use these bytes without fear as the only consequence will be that the other characters and the phone parts will look a bit pixelated (each row being four scan lines tall). Of course, on an Atari 2600, that's not exactly a major issue. We need at least 9 bytes for our routine, but our luck is holding out and we can safely eliminate the WSYNC at 1060 giving us a whole 10 bytes to use as we please. We'll also need to slightly modify our routine. If you've been following along with a debugger, you can probably guess why.

1060: NOP ; 2 ; EA 1061: TXA ; 2 ; 8A 1062: SBC #$07 ; 2 ; E9 07 1064: CMP $9C ; 3 ; C5 9C 1066: BCS $F06A ; 2 ; B0 02 1068: STA CXCLR ; 3 ; 85 2C Note: We subtract 7, not 8 like before.



Figure 5: The FBI Agent before and after. It looks worse when you put them side-by-side. Only die-hard E.T. fans will notice the change during actual play.

::UPDATE:: Thanks to the excellent suggestion of AtariAge user Nukey Shay, we can (mostly) save our sprites. (Apparently, the die-hard E.T. fans noticed and were not impressed!) Every other line will still be the same color, but at least they won't be a blocky mess.

Nukey Shay's idea was to precalculate the location where we want to strobe CXCLR. Instead calculating the position we're looking for on every line, we do it once per frame and store the result so that we can just do a quick CPX. This saves us a 3 bytes and 4 cycles. We can spend these (plus 2 cycles from the NOP) on an LDA and STA to update GRP0. That will make our sprites less blocky, but we'll still lose some color detail. Elliott's shirt will lose its stripes and the FBI agent will lose his hair.

Our second routine now looks like this:

1060: LDA $87 ; 3 ; A5 87 1062: STA GRP0 ; 3 ; 85 1B 1064: CPX $8B ; 3 ; E4 8B 1066: BCS $F06A ; 2 ; B0 02 1068: STA CXCLR ; 3 ; 85 2C Note: We'll save our precalculated location at 8B, which is unused.

Of course, we still need to precalculate the position and store it at 8B. We've got a little free ROM space in Bank 0, and tons of time during VBLANK, so we can run our routine just before we wait out the timer. We'll steal the jump to 0CAB at 002A, call our routine at 0FF0, and then jump to 0CAB to wait out the timer.

002A: JMP $BFF0 ; 3 ; 4C F0 BF 0FF0: LDA $9C ; 3 ; A5 9C 0FF2: ADC #$07 ; 3 ; 69 07 0FF4: STA $8B ; 3 ; 85 8B 0FF6: JMP $BCAB ; 3 ; 4C AB BC

That solves the problem. Now E.T. won't fall in to a well unless his feet are over the hole. Moving around in the game feels a lot more natural. Of course, it doesn't matter how great the controls are if we can't collect phone parts to complete the game!

If you've been following along, you've probably already figured out that the reason we can't collect phone parts is because E.T.'s feet never touch them. Hovering up to make E.T.'s feet touch them doesn't work, which seems obvious in retrospect.

The simplest solution is to just move the phone parts down the screen a little bit so that they're lying on the ground and not hovering in mid-air. It's an easy fix, just one byte. Change 0BEE from 32 to 36.

0BED: LDA #$36 ; 2 ; A9 36

That's all there is to it. It's not perfect, but we'll improve it later.

Dealing with the difficulty

The game is now actually easy to complete on easy mode and much more fun to play in the other game modes. It may still be a bit too difficult for some, so let's see what we can do to make the game less punishing.

E.T. focuses heavily on exploration. Not only do you need to find the phone parts, but also a location for your ship to land, and a suitable spot to "phone home". There is also strategic exploration to identify the spots where you can call Elliott, eat candy, and send the scientist and FBI agent back to their respective buildings. Let's not forget side quests. The problem, of course, is that the game punishes you for exploring. Every step you take uses precious energy. Rather than a fun activity, exploration is something to avoid whenever possible.

As there are plenty of other ways to lose energy aside from just moving around, we can reduce the amount of energy it takes to move around to zero without making ourselves invincible. The game will still be challenging, just not nearly as frustrating.

E.T. loses energy by moving around in three different ways: walking, running, and hovering upward. Using our debugger, we can step through the code to find the place or places where we lose energy. Some people may think that running or hovering should still take energy away. Conveniently, there are three places we need to change. Each line presented below is independent of the others, so just don't make the changes for running or hovering if you don't want them.

The Original code: 0707: LDY #$01 ; 3 ; A0 01 ; Lose energy Walking 071B: LDY #$01 ; 3 ; A0 01 ; Lose energy Running 0685: LDY #$01 ; 3 ; A0 01 ; Lose energy Hovering The New code: 0707: LDY #$00 ; 3 ; A0 00 ; Lose no energy Walking 071B: LDY #$00 ; 3 ; A0 00 ; Lose no energy Running 0685: LDY #$00 ; 3 ; A0 00 ; Lose no energy Hovering

It's easy to see how to change the code to take more energy away if you're after additional challenge. You could, for example, double the energy you use when running by changing 071C to 02.

::UPDATE:: AtariAge user Random Terrain noticed that there is a problem with the sound that plays when E.T. is hovering.

That particular problem is caused by the seemingly simple difficulty fix for hovering. It turns out that the routine that plays the hovering sound uses the lower part of your energy (the last digit, masked off with an AND #$0F) to pace the tones. If we set 0686 to 0, you'll either hear an annoying tone or no sound at all, depending on the last digit of your energy counter when you start hovering. To fix this, we'll need modify that routine at 04EE.

We'll need to replace the reference to D4 with another memory location with a value that changes regularly. 81 is a good candidate, but it changes a bit too frequently. We can slow the pace to match the original fairly well by changing the mask to 1E.

04F0: LDA $81 ; 3 ; A5 81 04F2: AND #$1E ; 2 ; 29 1E

If you still think the game is too difficult, you can skip the changes above (except the sound fix) and make the following change:

0FD5: LDA $D3 ; 3 ; A5 D3

This change copies the upper part of your energy counter to the lower part, making energy a non-issue. You only lose energy if you fall in to a well and fail to catch yourself. You'd need to make that mistake 99 times before you pass-out, assuming that you don't eat any candy between falls. If that wasn't enough, you still won't lose as Elliott will come to revive you a few times. I don't recommend this change.

E.T. is NOT green!

Why is E.T. green? You need to ask Howard Scott Warshaw about that. E.T. is brown, however, not green. There is absolutely no reason why the game shouldn't use a proper color for E.T.

Here's what we know:

The E.T. sprite uses GRP1.

COLUP1 is not set anywhere in the kernel

E.T.'s color changes as he loses energy

Our energy level is stored across D3 and D4

The values at D3 and D4 are stored as BCD

We don't know, but can assume, that GRP1 and, consequently, COLUP1 are used in the top-bar. (It turns out that they are.) With our debugger, we can step through the code called after the top bar has been rendered and before we enter the kernel at 102E. We're looking for anything that checks our energy level or that sets COLUP1. It's not long before we find this gem:

165E: LDA $D3 ; 3 ; A5 D3 1660: LSR A ; 2 ; 4A 1661: LSR A ; 2 ; 4A 1662: LSR A ; 2 ; 4A 1663: LSR A ; 2 ; 4A 1664: LSR A ; 2 ; 4A 1665: TAX ; 2 ; AA 1666: INX ; 2 ; E8 1667: LDA F7F9, X ; 4 ; BD F9 F7 166A: STA COLUP1 ; 3 ; 85 07

It does everything: It reads the upper part of our energy level and sets COLUP1. We now know that E.T.'s colors are stored starting at 17F9, but how many of those bytes do we need to change? Remembering that the value stored at D3 is BCD we know that after 1163 we'll have a value between 0 and 9. One more shift (to divide by 2) and we're left with one of 5 possible values: 0, 1, 2, 3, and 4. Clever, isn't it?

Why the INX? You'd think that it was unnecessary as we'd need only change F7F9 to F7FA to skip the instruction and save a precious byte of ROM space and two cycles. If you take a look at the code a little farther back you'll find that the byte at index 0 is used as a color, but in a special case. (When E.T. has passed-out, if you're curious). The important thing here is that we now know that to change E.T.'s color, we need only change those 6 bytes starting at 17F9.

We'll need to consult a TIA color chart to figure out what colors we should use.

Original Colors: 17F9: 0E DE DC DA DA DA New Colors: 17F9: 0E FE FC F8 F8 F8

I changed the luminance and not just the hue as FA looked too light. Unfortunately, that choice makes E.T. practically invisible against the gray background in the wells. Rather than give-in and use the lighter color, we can just make the background of the well a bit darker. It's a small difference that won't be noticeable during play.

As you've already guessed, the code to change COLUPF and COLUBK ought to be near the code to set COLUP1: after we draw the top bar but before we enter the main kernel. No surprise, we find the code we're interested in just a few bytes down at 166E to 1680. The code works the same way, reading a color from a byte array. COLUPF from 1DD9 and COLUBK from 1DE2. Play until you fall in to a well and then take a look at the value stored at 80 when we get to 166E to get the index we need. (For the lazy: It's 6, giving us 1DE8.)

Between the color chart and our understanding of the code starting at 166E we can change the well foreground and background colors to anything that we want. Gray always seemed to me to be an odd choice, but I'll stick with tradition here and just make the background a shade darker so that E.T. stands out.

1DE8: 04

If you want to change the well foreground color, that value is stored at 1DDF.



Figure 6: E.T. looking sharp with his fancy new color.

Spit and Polish - Finishing the Project

Things are looking good, but they're not good enough. Let's see if we can polish this up and make it ready for production.

Here are the problems:

Elliott's Shirt has no stripes

The FBI Agent lost his hair

E.T. loses detail on the right side of the screen

Candy Pieces are much more difficult to collect

Objects in wells are drawn too far down, making the flower look odd

A Big One: Elliott can't revive E.T.

As a Bonus, let's also make our difficulty fix a selectable option.

Finding some space

What purpose does M0 serve? I have absolutely no idea. It's only set to one of two fixed vertical positions (7F and 33), and only at two fixed horizontal positions. It's displayed only when E.T. is dead (on the sad ending scene), about half-way across the the bottom of the play area. It changes to various shades of red. That's from the code, I've never actually seen it during play. I've taken the time to see if that really does happen, and what it looks like. M0 shows up directly over a dead E.T., giving him the appearance of being fatally wounded.

While I was hoping for a no-compromise solution, this is something I'm willing to remove. It won't be missed. We'll trade it for an improved kernel and a new feature much better than a bleeding E.T.

With that gone, we free up 3 bytes and 6 cycles in our kernel at 1028. Looking a few bytes down at 102F, you'll see an obviously useless SEC. It's actually used for timing, but we'll make up for that with our new changes anyway. For now, it can be considered 1 free byte and 2 precious cycles. Coupled with the WSYNC we can remove at 1060, that gives us 6 free bytes and 11 cycles. We'll use these to make a change to our kernel to implement our falling fix while preserving sprite colors and making it easier to collect candy.

The idea is simple: We have a lot of stuff to draw early, so do that first. With the extra space and time, we'll check to see if we're on the line we'd normally strobe CXCLR for our falling fix. Instead of clearing it right away, check to make sure we haven't touched any candy. That's going to take a whopping 10 bytes and 12 cycles.

CPX $8B ; 3 ; E4 8B BNE +6 ; 2 ; D0 06 BIT CXP1FB ; 2 ; 24 13 BVS +2 ; 2 ; 70 02 STA CXCLR ; 3 ; 85 2C

Thankfully, we can spare the extra cycle. Though where are we going to find an extra 4 bytes?

Remember all that dead code at 1013 we used for the first version of our falling fix? It's just timing code, there to waste some cycles so that everything is drawn at just the right place. We don't ultimately need it for our falling fix (though we left it in anyway) so we're free to use it for something else, provided we're careful about our timing. The code we're going to change starts at 1060 and branches in to the code at 1022. That puts us directly below the useless code at 1013. We can snag a few bytes from there and just adjust the jump at 1074.

To start, we'll kill the WSYNC at 1060 and move everything before the jump to 1022 (at 1074) up two bytes. We'll move the CPX at 1022 to the hole we created at 1072 giving us:

1060: LDA $87 ; 3 ; A5 87 1062: STA GRP0 ; 3 ; 85 1B 1064: LDA $88 ; 3 ; A5 88 1066: STA COLUP0 ; 3 ; 85 06 1068: TXA ; 2 ; 8A 1069: TAY ; 2 ; A8 106A: LDA $BA, Y ; 5 ; B1 BA 106C: STA PF1 ; 3 ; 85 0E 106E: LDA $BC, Y ; 5 ; B1 BC 1070: STA PF2 ; 3 ; 85 0F 1072: CPX $9F ; 3 ; E4 9F

Next, we'll grab four bytes from our dead code by moving the jump at 101F to 101B. We'll then update our jump at 1074 (that used to point to 1022) to point to 101E.

101B: JMP F04B ; 3 ; 4C 4B F0 1074: JMP F01E ; 3 ; 4C 1E F0

Now we can clear a 10 byte spot for our routine. Move the PHP at 1024 to 101E. (We can get away with this as JMP doesn't affect any flags.) Now move everything from the CPX at 1025 to the TXA at 102E down a byte, overwriting the useless SEC at 102F.

Popping in our new routine at 101F, we get:

101B: JMP F04B ; 3 ; 4C 4B F0 101E: PHP ; 3 ; 08 101F: CPX $8B ; 3 ; E4 8B 1021: BNE +6 ; 2 ; D0 06 1023: BIT CXP1FB ; 2 ; 24 13 1025: BVS +2 ; 2 ; 70 02 1027: STA CXCLR ; 3 ; 85 2C 1029: CPX $9E ; 3 ; E4 9E 102B: PHP ; 3 ; 08 102C: INX ; 2 ; E8 102D: LDY $86 ; 2 ; A4 86 102F: TXA ; 2 ; 8A

If we try the game now, it'll crash. The kernel entry point is at 102E, which now in the middle of an instruction! The CPU will think that we're trying to STX $8A and who knows what else afterward! We'll need to adjust our entry point down a byte. It's buried in a table at 18F3. The address is loaded at 16A0 and shoved on to the stack. We jump in to the kernel with an RTS at 16B5. The RTS instruction pops the address off the stack as sets the PC, but inexplicably adds 1 in the process. That means we'll need to specify an address 1 byte before the one we want. It's weird. We jump to our new address ... by specifying our old one.

18F3: $F02F ; - ; 2E F0

Now if we replace the 8 bytes from 1013 to 101A with NOP's (EA, using up 16 cycles) we can try out our new kernel. A quick test shows that we're clearly not done. E.T. still loses resolution on the right side of the screen! Remember that useless SEC? We needed it to delay updating GRP1 at 1034 until we were finished drawing the play area. The fix is easy, just swap it with the WYSNC at 1036.

1034: STA WSYNC ; 3 ; 85 02 1036: STY GRP1 ; 3 ; 84 1C

That's a lot better, but we're still not done. Elliott still can't revive E.T., and we still need to touch phone parts with our feet, meaning we still need to push objects in wells down a few lines. We've also introduced a new problem: E.T. isn't centered in the spaceship on landing or take-off. At least that one is easy to fix. All we need to do is adjust the starting position of the spaceship for landing (at 0B40) and take-off (at 07ED):

0B40: LDA #$EF ; 2 ; A9 EF 07ED: SBC #$04 ; 2 ; E9 04

So, why can't Elliott revive E.T.? To revive E.T., Elliott needs to touch him. Unfortunately, the "E.T. has passed-out" sprite is much shorter than the normal E.T. sprite, and we clear the collision latches well below the last line. It doesn't matter where Elliott is positioned, he'll never touch E.T. after we strobe CXCLR as there will be nothing for him to touch.

There are a couple things we could do. Instead of adding 7 when we calculate the position to clear the collision latches, we could do the sensible thing and add E.T.'s height and position, then subtract 2 before storing it in 8B. That way we'll have a line for Elliott to touch on the much shorter E.T. sprite. Unfortunately, that won't work. Even if we move the code to calculate the position just above E.T.'s feet to the 10 free bytes at 0BF6 (which we will anyway) we'll need 8 bytes for the math and three to jump to 0CAB. That's 11 bytes. Our luck isn't holding out, as there doesn't seem to be any useless bytes to spare. All the same, let's move that routine anyway in preparation for our cool new feature.

002A: JMP $BBF6 ; 3 ; 4C F6 BB 0BF6: LDA $9C ; 3 ; A5 9C 0BF8: ADC 07 ; 3 ; 69 07 0BFA: STA $F6 ; 3 ; 85 F6 0BFC: JMP $BCAB ; 3 ; 4C AB BC

(Wait a minute! Why are we storing the result at F6 when our new kernel is expecting that at 8B? There is a reason, as we'll soon see.)

We could alternately check to see if E.T. has passed-out, and skip strobing CXCLR. The same trick would work for Phone Parts as well, by checking to see if E.T. is in a well. Of course, there's absolutely no way we can do that at the same place we do our other checks at 1023. That shouldn't be a problem, as we only really need to do those checks once as they're not dependent on E.T.'s vertical position. That's great, but how do we skip clearing the collision latches? There's not enough room for even one extra check.

We could modify our calculated value to point to some other location. Setting it to 0 would be ideal, but what about this process has been ideal? We also need a place to stuff our checks. A check usually costs us a good 4 bytes, two to set flags and another two to branch. That would make it seem like we'd need at least 10 bytes (another 2 bytes to zero 8B). Naturally, we don't have 10 usable bytes plus 1 or 3 extra bytes for a return. Not anywhere.

Now, we do have 8 bytes at 1013, for timing, just begging to be used in our kernel. The problem is that not only do we need to squeeze our routine in to 8 bytes, we must also burn through 12 to 16 cycles (no more, no less) to keep our timing right.

Here's what we know:

D9 is normally 0, but is set to 40 when we're hovering over a well, 20 when we're at the bottom of a well, and 80 while we're falling in.

E3 is normally 0, but is set to C0 when E.T. has passed out

E.T.'s vertical position will never exceed 3A

E.T.'s vertical position will never fall below 30 while standing in a well

E.T. will never collect anything or fall in a well when his vertical position is 0

We only draw GRP0 on the first scanline when the mothership is taking off or landing

That means our timing code at 1013, for all practical purposes, will always be called on the first scanline.

What can we do with this? Adding D9 and E3 to 8B will normally do nothing. If we're at the bottom of a well, D9 will be set to 20, and E3 will be 0 (if E.T. is healthy) and C0 (if not) That means 8B will be around 10 (+16) or 50 (+80), in any case, well outside the area we care about. (It'll be well above E.T. or below the play area). If we're not in a well, D9 will be 0 and adding C0 (-64) to any possible E.T. position will always result in a value in the range FA(-6) to C0(-64).

This is great. We can do that in 8 bytes and in precisely 12 cycles (the minimum we need to burn). The only problem is that our little routine will be called more than once. We can't just keep modifying 8B and hope for the best. The simple solution is to keep an original copy of our calculated value in a different location, run our routine using that value, and store the result in 8B. (That's why we stored our calculated value in F6 instead of 8B when we moved the routine to calculate the position we want to strobe CXCLR.) Our slick little routine looks like this:

1013: ORA $D9 ; 3 ; 05 D9 1015: ADC $E3 ; 3 ; 65 E3 1017: ADC $F6 ; 3 ; 65 F6 1019: STA $8B ; 3 ; 85 8B

Why ORA and not LDA? A will always be 0 at this point so the effect will be the same. With needlessly cryptic things (like the SEC used like a NOP) scattered around the code, it seemed to fit with H.S.W.'s style.

Update: AtariAge user iesposta noticed that it's possible for E.T. to fall in to a well if he's touching both a well and a piece of candy. This only happens in one spot (on the screen with the "V"-shaped wells) and you've got to be lined up near perfectly. We can prevent that from happening by pushing that candy down a tiny bit.

0BA5: 22 ; - ; 22

We did it! The game is now virtually identical to the original except for the changes that we wanted to make. The gore is the only exception, but it was worth removing it for...

Our new feature

As promised, we're going to make our difficulty fix optional. No longer will skilled E.T. players need to give up our much-needed changes in exchange for a more challenging game. Both difficulty switches are already used, but the B&W / Color switch is unused. All we need to do is find a place to put our routine.

We'll need to first modify our old difficulty fix to read from a byte in memory, rather than our explicit 1 or 0. That's the easy part. We'll use F8, for no real reason.

0707: LDY $F8 ; 3 ; A4 F8 071B: LDY $F8 ; 3 ; A4 F8 0685: LDY $F8 ; 3 ; A4 F8

The state of the color switch is at bit 3 in SWCHB. We'll need to load that in to memory, mask off bit 3, and check the state against that. Naturally, we don't have the space to do all of that and store it. We'd need 13 bytes for the obvious routine, if we magically found a place to stuff our routine that didn't require we hijack a jump. That's not going to happen.

The smallest routine I could manage works like this: read SWCHB, mask off bit 3, shift right three times, store the result. That'll take 10 bytes, not including a return jump. Even if we had the 10 bytes, that also would mean that the difficulty fix would be off by default (the switch is set to color) which isn't optimal.

We have what appears to be 10 bytes, but is really 8 bytes, free at 0FF0 where we used to have the 9-byte routine used to calculate the position to clear the collision latches. (I don't know how we got away with it.) We also have the 8 bytes that set M0's horizontal and vertical position for the gory ending scene at 0B4D. If we switch from one group to the other, it could be enough.

We'll likely need to use 6 of those bytes just for jumps, once to switch between our open areas, and once to complete the jump we hijack. Luckily, the routine just before our 8 free bytes at 0FF0 ends with an RTS. It turns out that this is the routine that decrements E.T.'s energy. It's a bit of good luck, and a nice match for our difficulty fix. To make things even better, there's an RTS at the end of our other 8 bytes (that set M0's position). With 16 bytes, and a return that's ready-made, we can implement our routine, swap the functions of the Color and B&W settings (so that Color is easy), all with a byte to spare.

We'll overwrite the RTS at 0FEF to allow the routine to continue in to our routine, grab SWCHB, and mask off bit 3 before the jump. We could do an LSR here, but we'll save it for after the jump to make our routine line-up with the existing RTS at 0B55.

0FEF: LDA SWCHB ; 4 ; AD 82 02 0FF2: AND #$08 ; 2 ; 29 08 0FF4: JMP $BB4E ; 6 ; 4C 4E BB

We'll need to use a byte to cap-off the checks to run the old routine so that our routine doesn't accidentally run. That's why we'll enter the second part at 0B4E instead of 0B4D.

0B4D: RTS ; 6 ; 60 0B4E: LSR ; 2 ; 4A 0B4F: LSR ; 2 ; 4A 0B50: LSR ; 2 ; 4A 0B51: EOR #$01 ; 2 ; 49 01 0B53: STA $F8 ; 3 ; 85 F8

Bit 3 of SWCHB is 1 if the B&W / Color switch is in the Color position, 0 otherwise. The EOR at 0B51 will reverse that so that we store a 0 in F8 when the switch is set to Color instead of 1.

That's all there is to it.

Squashing some 30-year-old Bugs

E.T. has a reputation for being loaded with bugs. Bugs that make the game "virtually unplayable". This just isn't true. There aren't actually that many bugs, and only one that seems to impact normal gameplay.

Bug myths and facts

There are a few oft-cited bugs that, well, aren't bugs at all. Before we begin, let's set the record straight on the most common non-bugs:

Myth: Some game-state variables aren't cleared when starting a new game as evidenced by the appearance of the Scientist and FBI agent after starting a new game on mode 3. This simply isn't true. The Scientist and FBI agent always appear regardless of the game mode. In every mode, all the humans are shown returning to their respective buildings -- that includes mode 3, even from power-on. The difference, of course, is that in mode 3 they never leave.

Myth: The first count-down timer doesn't finish ticking down like the second, faster, timer. This is just a misunderstanding of what the "two" timers represent. The timer takes 64 "ticks" to complete. Every 8 ticks, a section disappears. The second timer is a "close-up" of the last section of the first timer. It ticks off one of its eight sections every "tick". It's like the first timer is minutes, and the second timer seconds. There really is just one 64-tick timer, we just see the higher-precision ("second") view when we get to the end (the last "minute").

Myth: The number of times Elliott can revive E.T. is incorrect / can be exploited to gain and extra revival. This is simply not true. The manual states that "Elliott can merge with E.T. three times per game." Which is correct. It also states that "Once during a round, however, E.T. can encounter a wilted flower hidden in the bottom of a well. If E.T. is revives the flower, Elliott is given the ability to merge with E.T. one extra time." This is also correct. Extra merges / lives accumulate as you would expect from the description, though that's not explicitly stated in the manual. In short, there are no bugs related to the number of times Elliott can revive E.T. (Not under any normal play circumstances anyhow. If you accumulate more than 127 "lives", Elliott will not revive E.T. I doubt that has ever happened!)

Real Bugs

Bug 1: On difficulty modes where Elliott is allowed to be on-screen when the ship lands, the Ship Crushes Elliott.

This bug happens because the ship's position is overwritten by Elliott's position immediately after the ship's position is set to start the landing animation. The fix is simple, just skip over the code that updates the current objects on-screen position after we start initialize the ship landing sequence.

07BD: JMP $BAD9 ; 3 ; 4C D9 BA

Bug 2: You always fall in to a well when exiting the forest on the right, and when exiting the city on the left

This is also an easy fix. The falling fix automatically takes care of the bug when exiting left from the city screen. For the forest, we just need to slightly adjust E.T.'s starting position on the next screen. The player will be pushing right on the joystick, so we'll just move E.T. a tiny bit up and to the right to avoid immediately falling in to the top-center well on the screen with eight pits. E.T.'s starting position is read from a table, so we just need to update a couple of values:

0D54: 3A +10 ; - ; 4A 0D6C: 04 -3 ; - ; 01

We'll move E.T. 16 units to the left, and 3 units up from the original positions.

Bug 3: Scoring is wildly incorrect.

It's consistent, for the most part, but it's very confusing. It also doesn't even come close to matching the manual. There are some more serious problems, however. Collecting more than 31 pieces of candy will cause an error, often leading to the famous "Ninja E.T." bug. The starting energy penalty and candy bonuses are also incorrect.

The code for scoring also determines other things, like E.T.'s energy when starting a new game, so we'll need to be careful making drastic changes to make sure we don't accidentally break anything. Of cousre, the code is also a mess, so we will be making some rather dramatic changes.

Right now, points for candy E.T. brings on the ship, bonus points for candy collected beyond a certain amount, and the energy penalty are determined by table look-ups. Normally, a look-up table is used to save ROM space, time, or both to avoid a complex calculation or provide a more accurate calculation. These tables just waste space as time isn't an important factor here. Even worse, only points for E.T.'s candy are scored correctly! We'll eliminate these awful tables and put those bytes to better use.

Currently, scoring follows this sequence: After the ending animation starts, you are given 1 point for every unit of remaining energy, then 490 points for every candy brought on to the ship. The candy munching part of the animation then begins, netting you 770 points for each candy held by Elliott; one at a time while the animation runs. When a new round starts, you're given bonus points for collected candy above a certain amount (21 pieces, not 31 as specified in the manual) and the energy penalty determines your starting energy for the round.

We're going to change that. We'll start off the same way, giving one point for every unit of remaining energy. We'll then set E.T.'s energy to 9999. As the munching animation runs, we'll deduct energy for the penalty, add bonus points for candies collected over a certain amount, and add the normal 490 or 770 points for collected candy to your score.

The energy penalty code also sets E.T.'s energy at the start of a new game. We'll need to remember that code that begins a new round is also called when a new game starts, and add some code to make sure E.T.'s starting energy is set to 9999 at the beginning of a new game.

Fixing the scoring code will also fix the Ninja E.T. bug. As it's become a popular, if unintended, Easter Egg in its own right, we'll add it to the game as an intentional effect. (Without the other strange artifacts, of course).

Since we're fixing the scoring, it makes sense to make the scoring match the manual. This means we'll also need to make a small change to how much candy can be found during a round so that you can meaningfully collect more than 31 pieces. There is technically a bug here, as the flags that show which well screens currently have candy is never cleared. The counter that holds how much additional candy can be found during the round often doesn't reach zero. We'll leave this in as it adds a nice bit of pseudo-randomness to the amount of candy you can find.

Wait. What? There's effectively a potential +4 or -3 to the amount of candy than can appear during a round. Remembering that candy left on the ground from the previous round isn't cleared, there can be as many as four pieces left on the ground from a previous round. Those won't be deducted from the counter, effectively increasing the potential amount of candy by as much as four pieces. The -3 is a bit more complicated. When candy appears, it appears on every well screen. The value at DC is reduced by the amount of candy needed to add a candy to every screen. (If all four screens need candy, DC is reduced by four. If three screens need candy, DC is reduced by three, and so on.) If there isn't enough candy left to place a candy on every screen, according to DC, then no candy is added. That means that DC can get "stuck" at 3, 2, or 1. (If all four well screens need candy when DC is less than four, no candy is added. If three screens need candy when DC is less than 3, no candy will be added, and so on.) If you're looking to maximize the amount of candy you can collect, collect only one candy at a time, allowing the candy to replenish in-between, when you get close to the maximum.

Without further exposition, let's get started. The first thing we'll do is make a change to the code that runs right after we finish a round. The code we're interested in initializes the counter for remaining candy for the next round and totals the collected candy (what Elliott is holding plus what E.T. is holding.)

058E: STA $F4 ; 3 ; 85 F4 0590: LDA $DD ; 3 ; A5 DD 0592: STA $F5 ; 3 ; 85 F5 0594: ADC $F4 ; 3 ; 65 F4 0596: STA $DD ; 3 ; 85 DD 0598: ADC 16 ; 3 ; 69 10 059A: NOP ; 2 ; EA 059B: NOP ; 2 ; EA

Memory location DD holds the amount of candy held by Elliott, which will now be set to the total amount of candy collected. F4 and F5 hold the amount of candy held by E.T. and Elliott, respectively. At 0598, we set the amount of candy available in the next round to 16 plus the total amount of candy collected. (It will be stored in DC just after the two NOP's). We'll come back to that later.

We only need F4 and F5 to implement the Ninja E.T. bug as an Easter Egg, so this routine could be made much simpler.

With that out of the way, let's kill the code that scores E.T.'s candy as we'll handle that in our new scoring routine. As we'll be deducting energy for the penalty in our new score routine, we'll use this opportunity to set E.T.'s energy to 9999.

1395: LDA #$99 ; 2 ; A9 99 1397: STA $D3 ; 3 ; 85 D3 1399: STA $D4 ; 3 ; 85 D4 139B: BNE +9 ; 3 ; D0 09 139D: NOP ; 2 ; EA 139E: NOP ; 2 ; EA 139F: NOP ; 2 ; EA 13A0: NOP ; 2 ; EA 13A1: NOP ; 2 ; EA 13A2: NOP ; 2 ; EA

The branch at the end skips over the jump to the routine that updates our score.

Those six bytes are just begging to be used! As we're fixing the scoring, let's take this opportunity to address a scoring issue with the difficulty fix. Normally, you get 1 bonus point for every remaining unit of energy that E.T. has at the end of a round. With the difficulty fix in place, players essentially get tons of free points. It hardly seems fair, so we'll add a check so that the players taking advantage of the difficulty switch receive no bonus points for remaining energy.

139D: LDA $F8 ; 3 ; A5 F8 139F: BNE +2 ; 2 ; D0 02 13A1: TAX ; 2 ; AA 13A2: TAY ; 2 ; A8

We'll hijack the jump at 1382, pushing it back a bit so that our routine is actually called. The routine to increment our score will be called directly afterward like normal, only with X and Y set to 0 instead of E.T.'s remaining energy, if the difficulty fix is enabled.

1382: JMP 13A3 -6 ; 6 ; 4C 9D F3

Now we've freed up the 20 bytes that make up the table at 1341. We'll free up the 16 bytes at 17E9 used for the energy penalty later when we update the code that start a new round. For now, we'll assume that they're free. That should give us 36 bytes for our new scoring routine.

We'll call our new scoring routine from the munching routine at 13AC. We'll need to either hijack a jump or find some free bytes for our own. Luckily, we've got four useless bytes at 13BD. All those do are store the number 6 in 8B. It's the only place in the ROM that does anything with 8B (our changes excepted, of course) so it's essentially useless. We'll use those four bytes for our jump.

13BD: LDA #$01 ; 2 ; A9 01 13BF: ORA $DE ; 2 ; 05 DE 13C1: STA $DE ; 3 ; 85 DE 13C3: LDX #$07 ; 2 ; A2 07 13C5: LDY #$70 ; 2 ; A0 70 13C7: JSR $1341 ; 6 ; 20 41 F3 13CA: NOP ; 2 ; EA

We'll want to take advantage of the LDX and LDY (which hold the number of points to score) to save a few bytes, so we'll just push everything before that up in to the four-byte hole we made at 13BD and add our jump. Our jump only takes three bytes, so we'll fill that extra byte with a NOP.

Finally, we can add our new score routine! The idea here is simple. Assume from 13C5 and 13C7 that the candy we're munching is worth 770 points. If E.T. is holding any candy, reduce that amount by one and change the points to score to 490. Finally, check to see if the current candy is one of the candies collected after the 31st piece. If so, add 1000 points to whatever we've planned to score and deduct 700 units of energy as the penalty. This matches the scoring described in the manual. The points will actually be added to the score after we return from our routine.

1341: LDA $D2 ; 2 ; A5 D2 1343: CMP #$0A ; 2 ; C9 0A 1345: BEQ +8 ; 2 ; F0 08 1347: SBC 16 ; 3 ; E9 10 1349: STA $D2 ; 3 ; 85 D2 134B: LDX #$04 ; 2 ; A2 04 134D: LDY #$90 ; 2 ; A0 90 134F: LDA $DD ; 2 ; A5 DD 1351: SED ; 2 ; F8 1352: JMP $17E9 ; 6 ; 4C E9 F7 ----------------------------------- 17E9: CMP #$1F ; 2 ; C9 1F 17EB: BCC +10 ; 2 ; 90 0A 17ED: TXA ; 2 ; 8A 17EE: ORA #$10 ; 2 ; 09 10 17EF: TAX ; 2 ; AA 17F1: LDA $D3 ; 2 ; A5 D3 17F3: SBC 7 ; 3 ; E9 07 17F5: STA $D3 ; 3 ; 85 D3 17F7: CLD ; 2 ; D8 17F8: RET ; 6 ; 60

Now we need to update the code that starts a new round to keep it from scoring bonus points and issuing a penalty. There is an additional problem, as the code that determines the energy penalty also sets E.T.'s energy to 9999 for the first round, we'll need to also modify the code that starts a new game or E.T. will start the game without any energy!

Looking at the new game code at 13DC we initialize a lot of stuff to zero, including things that are set later or can be set later. We won't need the STA $EB (ship status) as that's set later. We can also safely set DD, D9, and 94 (Elliot's candy, well flags, and E.T.'s neck height) at the start of each round. That'll free up a few bytes to set E.T.'s starting energy at the beginning of a new game.

13FD: LDA #$99 ; 2 ; A9 99 13FF: STA $D3 ; 3 ; 85 D3 1401: STA $D4 ; 3 ; 85 D4 1403: LDA #0 ; 2 ; A9 00 1405: STA $F4 ; 2 ; 85 F4 1407: STA $E3 ; 3 ; 85 E3

We'll also want to reset F4 (which holds the total candy collected used for our Ninja E.T. Easter Egg) so we'll include that between the old 13FD and 13FF (now 1403 and 1407) that we pushed down to make room for our new code.

We still need to set DD, D9, and 94 to 0 so we we'll do that at the start of a new round. (The new round code is also called when we start a new game.) Everything from 147A to the jump at 14A2 is free for us to use, thanks to our new scoring routine.

147A: LDA #$0 ; 2 ; A9 00 147C: STA $DD ; 3 ; 85 DD 147E: STA $D9 ; 3 ; 85 D9 1480: STA $94 ; 3 ; 85 94

We also need to limit the amount of candy available in the next round so that our energy penalty doesn't "wrap around" and start deducting from the max again. Remember that DC holds the amount of candy that can appear in the next round. We'll cap it off at 41 pieces, giving us potentially 38 to 45 pieces in the next round. At 45 pieces our penalty will be (45-31)*700 or 9800. Any more than that and E.T.'s energy would wrap to 9300.

1482: LDA #$29 ; 3 ; A5 29 1484: CMP $DC ; 3 ; C5 DC 1486: BCS +2 ; 3 ; B0 02 1488: STA $DC ; 2 ; A5 DC 148A: JMP $14A5 ; 6 ; 4C A5 F4

Now scoring works exactly as stated in the manual. There's just one thing left to do.

Adding the Ninja E.T. Easter Egg

Ninja E.T. wasn't an intentional easter egg in the original game, it was a bug. If you collected too much candy (most sources say 33 pieces) on the next round, E.T. would turn black and your energy would show part of H.S.W.'s initials and other junk. This happens because a value other than 0-9 appears in the upper nibble in the upper part of E.T.'s energy, which will make the code "point" to the wrong image. As E.T. changes color depending the amount of remaining energy, the color selected will be outside of the color table, which just happens to have a few 0's around it. We'll take advantage of that to implement Ninja E.T. though we'll make sure that the energy counter doesn't look broken.

With the scoring fixed, collecting 33 pieces of candy seems like a perfectly reasonable, and likely common, amount. An easter egg shouldn't be triggered so easily. Echoing the oft-cited trigger, we'll enable Ninja E.T. only if a player completes a round with both E.T. and Elliott in posession of exactly three candies.

As a bonus, we'll give Ninja E.T. ten pieces of candy to make up for the previous candy-poor round. It'll also let Ninja E.T. make a quick trade with Elliott for a phone part.

148A: LDA $F4 ; 2 ; A5 F4 148C: CMP $F5 ; 2 ; C5 F5 148E: BNE +12 ; 3 ; D0 0C 1490: CMP #$03 ; 2 ; C9 03 1492: BNE +8 ; 2 ; D0 08 1494: LDA #$AA ; 2 ; A9 AA 1496: STA $D2 ; 3 ; 85 D2 1498: STA $D3 ; 3 ; 85 D3 149A: STA $D4 ; 3 ; 85 D4 149C: JMP $14A5 ; 6 ; 4C A5 F4 149F: NOP ; 2 ; EA 14A0: NOP ; 2 ; EA 14A1: NOP ; 2 ; EA

Why AA? That will both give Ninja E.T. 10 pieces of candy and make the energy counter appear to be empty. As E.T. loses energy, the counter will return to normal, one digit at a time. When all four digits of the counter are back to normal, Ninja E.T. will also return to normal.

An Extra Game Mode

Players looking for additional challenge above game mode 3, but not quite as challenging as game mode 2 (with the nasty FBI Agent) have always felt left out. AtariAge user roadrunner suggested that an extra game mode that included just the scientist would be a welcome addition.

The various game modes remove humans by sending the Scientist or the FBI agent home repeatedly so that they don't appear in-game. To allow an extra mode to be selected, we just need to change the maximum game mode from 3 to 4. The game checks to see if the current mode is one higher than the maximum before setting the game mode back to 1, so we'll check to see if the the game mode is 5. We'll also need to modify the check to send the scientist back home. If we make the scientist only option game mode 3 and push the "no humans" option to game mode 4, we can check to see if we need to send the scientist home with an AND and by changing the branch instruction. Ultimately, it's a four-byte change.

0471: CPX #$05 ; 2 ; E0 05 -------------------------------------------- 02ED: AND #$01 ; 2 ; 29 01 02EF: BEQ +9 ; 2 ; F0 09

All of the Final Changes

Here are all the final changes:

--------------------------------------------- - E.T. Fixed Final Version (NTSC) 2013-02-01 --------------------------------------------- ------------------------------------------- - E.T. is Not Green ------------------------------------------- 17FA: ET Colors ; - ; FE FC F8 F8 F8 1DE8: Well BG ; - ; 04 ------------------------------------------- - Difficulty Fix (Walk, Run, Hover) ------------------------------------------- 0707: LDY $F8 ; 3 ; A4 F8 071B: LDY $F8 ; 3 ; A4 F8 0685: LDY $F8 ; 3 ; A4 F8 ------------------------------------------ 0FEF: LDA SWCHB ; 4 ; AD 82 02 0FF2: AND #$08 ; 2 ; 29 08 0FF4: JMP $BB4E ; 6 ; 4C 4E BB ------------------------------------------ 0B4D: RTS ; 6 ; 60 0B4E: LSR ; 2 ; 4A 0B4F: LSR ; 2 ; 4A 0B50: LSR ; 2 ; 4A 0B51: EOR #$01 ; 2 ; 49 01 0B53: STA $F8 ; 3 ; 85 F8 ------------------------------------------ - Hovering Sound Fix ------------------------------------------ 04F0: LDA $81 ; 3 ; A5 81 04F2: AND #$1E ; 2 ; 29 1E ------------------------------------------- - Falling Fix ------------------------------------------- 002A: JMP $BBF6 ; 3 ; 4C F6 BB 0BF6: LDA $9C ; 3 ; A5 9C 0BF8: ADC 07 ; 3 ; 69 07 0BFA: STA $F6 ; 3 ; 85 F6 0BFC: JMP $BCAB ; 3 ; 4C AB BC ------------------------------------------ 1013: ORA $D9 ; 3 ; 05 D9 1015: ADC $E3 ; 3 ; 65 E3 1017: ADC $F6 ; 3 ; 65 F6 1019: STA $8B ; 3 ; 85 8B 101B: JMP F04B ; 3 ; 4C 4B F0 ------------------------------------------ 101E: PHP ; 3 ; 08 101F: CPX $8B ; 3 ; E4 8B 1021: BNE +6 ; 2 ; D0 06 1023: BIT CXP1FB ; 2 ; 24 13 1025: BVS +2 ; 2 ; 70 02 1027: STA CXCLR ; 3 ; 85 2C 1029: CPX $9E ; 3 ; E4 9E 102B: PHP ; 3 ; 08 102C: INX ; 2 ; E8 102D: LDY $86 ; 2 ; A4 86 102F: TXA ; 2 ; 8A ------------------------------------------- 1034: STA WSYNC ; 3 ; 85 02 1036: STY GRP1 ; 3 ; 84 1C ------------------------------------------- 1060: LDA $87 ; 3 ; A5 87 1062: STA GRP0 ; 3 ; 85 1B 1064: LDA $88 ; 3 ; A5 88 1066: STA COLUP0 ; 3 ; 85 06 1068: TXA ; 2 ; 8A 1069: TAY ; 2 ; A8 106A: LDA $BA, Y ; 5 ; B1 BA 106C: STA PF1 ; 3 ; 85 0E 106E: LDA $BC, Y ; 5 ; B1 BC 1070: STA PF2 ; 3 ; 85 0F 1072: CPX $9F ; 3 ; E4 9F 1074: JMP F01E ; 3 ; 4C 1E F0 ------------------------------------------- - Change Kernel Entry Point ------------------------------------------- 18F3: $F02F ; - ; 2E F0 ------------------------------------------- - Landing / Launching Ship Position Fix ------------------------------------------- 0B40: LDA #$EF ; 2 ; A9 EF 07ED: SBC #$04 ; 2 ; E9 04 ------------------------------------------- - Move Candy on V Screen To Prevent Falls ------------------------------------------- 0BA5: 22 ; - ; 22 ------------------------------------------- -------------------------------------------- - BUG FIXES -------------------------------------------- - Don't Fall Leaving Forest on Right ------------------------------------------- 0D54: 3A +10 ; - ; 4A 0D6C: 04 -3 ; - ; 01 ------------------------------------------- - Ship Shouldn't Crush Elliott ------------------------------------------- 07BD: JMP $BAD9 ; 3 ; 4C D9 BA ------------------------------------------- ------------------------------------------- - FIX SCORING TO MATCH MANUAL ------------------------------------------- 058E: STA $F4 ; 3 ; 85 F4 0590: LDA $DD ; 3 ; A5 DD 0592: STA $F5 ; 3 ; 85 F5 0594: ADC $F4 ; 3 ; 65 F4 0596: STA $DD ; 3 ; 85 DD 0598: ADC 16 ; 3 ; 69 10 059A: NOP ; 2 ; EA 059B: NOP ; 2 ; EA ------------------------------------------- 1382: JMP 13A3 -6 ; 6 ; 4C 9D F3 ------------------------------------------- 1395: LDA #$99 ; 2 ; A9 99 1397: STA $D3 ; 3 ; 85 D3 1399: STA $D4 ; 3 ; 85 D4 139B: BNE +9 ; 3 ; D0 09 139D: NOP ; 2 ; EA 139E: NOP ; 2 ; EA 139F: NOP ; 2 ; EA 13A0: NOP ; 2 ; EA 13A1: NOP ; 2 ; EA 13A2: NOP ; 2 ; EA ------------------------------------------- - Score no points for remaining energy - with the difficulty fix enabled (6 bytes) ------------------------------------------- 139D: LDA $F8 ; 3 ; A5 F8 139F: BNE +2 ; 2 ; D0 02 13A1: TAX ; 2 ; AA 13A2: TAY ; 2 ; A8 ------------------------------------------- 13BD: LDA #$01 ; 2 ; A9 01 13BF: ORA $DE ; 2 ; 05 DE 13C1: STA $DE ; 3 ; 85 DE 13C3: LDX #$07 ; 2 ; A2 07 13C5: LDY #$70 ; 2 ; A0 70 13C7: JSR $1341 ; 6 ; 20 41 F3 13CA: NOP ; 2 ; EA ------------------------------------------- 1341: LDA $D2 ; 2 ; A5 D2 1343: CMP #$0A ; 2 ; C9 0A 1345: BEQ +8 ; 2 ; F0 08 1347: SBC 16 ; 3 ; E9 10 1349: STA $D2 ; 3 ; 85 D2 134B: LDX #$04 ; 2 ; A2 04 134D: LDY #$90 ; 2 ; A0 90 134F: LDA $DD ; 2 ; A5 DD 1351: SED ; 2 ; F8 1352: JMP $17E9 ; 6 ; 4C E9 F7 ------------------------------------------- 17E9: CMP #$1F ; 2 ; C9 1F 17EB: BCC +10 ; 2 ; 90 0A 17ED: TXA ; 2 ; 8A 17EE: ORA #$10 ; 2 ; 09 10 17EF: TAX ; 2 ; AA 17F1: LDA $D3 ; 2 ; A5 D3 17F3: SBC 7 ; 3 ; E9 07 17F5: STA $D3 ; 3 ; 85 D3 17F7: CLD ; 2 ; D8 17F8: RET ; 6 ; 60 ------------------------------------------ 13FD: LDA #$99 ; 2 ; A9 99 13FF: STA $D3 ; 3 ; 85 D3 1401: STA $D4 ; 3 ; 85 D4 1403: LDA #0 ; 2 ; A9 00 1405: STA $F4 ; 2 ; 85 F4 1407: STA $E3 ; 3 ; 85 E3 ------------------------------------------ 147A: LDA #$0 ; 2 ; A9 00 147C: STA $DD ; 3 ; 85 DD 147E: STA $D9 ; 3 ; 85 D9 1480: STA $94 ; 3 ; 85 94 1482: LDA #$29 ; 3 ; A5 29 1484: CMP $DC ; 3 ; C5 DC 1486: BCS +2 ; 3 ; B0 02 1488: STA $DC ; 2 ; A5 DC 148A: JMP $14A5 ; 6 ; 4C A5 F4 ------------------------------------------- ------------------------------------------- - Easter Egg - Ninja E.T. ------------------------------------------- 148A: LDA $F4 ; 2 ; A5 F4 148C: CMP $F5 ; 2 ; C5 F5 148E: BNE +12 ; 3 ; D0 0C 1490: CMP #$03 ; 2 ; C9 03 1492: BNE +8 ; 2 ; D0 08 1494: LDA #$AA ; 2 ; A9 AA 1496: STA $D2 ; 3 ; 85 D2 1498: STA $D3 ; 3 ; 85 D3 149A: STA $D4 ; 3 ; 85 D4 149C: JMP $14A5 ; 6 ; 4C A5 F4 149F: NOP ; 2 ; EA 14A0: NOP ; 2 ; EA 14A1: NOP ; 2 ; EA -------------------------------------------- -------------------------------------------- - Add Extra Game Option - Scientist Only -------------------------------------------- 0471: CPX #$05 ; 2 ; E0 05 -------------------------------------------- 02ED: AND #$01 ; 2 ; 29 01 02EF: BEQ +9 ; 2 ; F0 09 --------------------------------------------

Conclusion

It turns out that E.T. isn't a bad game after all. With a few simple changes we were able to dramatically improve an already good game by eliminating the most common complaints. With a few additional changes, we were able to clear up any confusion for players who care about the score, and were confused by the differences between what the manual claims and what actually happens in-game. Next time someone tells you that "E.T. for the Atari 2600 is the worst game ever made" you can tell them that this is not the case. It's been fixed, and you know how.