Jump to content
  • entries
    106
  • comments
    796
  • views
    139,598

Reindeer Rescue Bug

Sign in to follow this  
Guest

2,842 views

JUST WHEN I THOUGHT I WAS DONE it turns out I'm not. :|

 

Anyway, I'll just reproduce what Al wrote to me and ask: anybody have any explanations or a fix?

Hi Bob,When playing the game (NTSC) on a real 2600, I ran into an interesting bug. When starting the game, if you don't do anything, Santa ends up running right through the playfield, and the game shortly resets back to the title screen after that. I burned two games to boards to test, and only discovered this after I played int the third level. It was a fluke that I noticed this at all, but it's a pretty serious problem so I'm going to start erasing the 100 (well, uhhr, 98) EPROMs I burned.This does not happen in Stella, which is probably why nobody saw it. before. Do any of the other testers have Krokodile Carts or Cuttle Carts they can use to test this on a real 2600?

Message Two:

I did some more digging-- it seems that the game only fails on one type of EPROM, the Texas Instruments 27C128. This is strange, as I use these all the time for Thrust+ Platinum. The game does seem to work fine with all the other types of EPROMs I programmed (five other types). Unfortunately, the TI 27C128s are the ones I have the most of, and comprise probably 60 of the EPROMs I programmed. Really strange that this problem only occurs with this one part. I assume it's some kind of weird timing issue. I'm hoping that you might be able to come up with some theories as to why this might be happening and maybe a fix? I'm a bit nervous about soldering more boards until I hear back from you.

If anybody has a Kroc cart or a CC and want to test Reindeer Runner for me? Manuel, I'm assuming that you have already, since you ran this on a real TV to test the PAL colors.This has me baffled; it is beyond my "expertise."The only weird thing that the game does is hit HMOVE at an odd time and, as mentioned in Eric B's weblog, it outputs 270 scanlines (NTSC); I do store the value of CXP0FB in RAM halfway down the screen (right before drawing the string of Christmas lights) and then use that stored value to process collisions between Santa and the playfield; so I suppose that maybe that value is being corrupted or lost somehow...? I dunno.Help?

(Note: I'm going to post this same thing on the [stella] list...)

 

EDIT: This is the pic referred to in comment #58:blog-6060-1134888067_thumb.png

Sign in to follow this  


73 Comments


Recommended Comments



I have a dipswitch multicart, and if you switch games while one is running, quite often the new game will run for a while in some screwed up state.  But plasibility alone doesn't suggest that bankswitching is the cause - it shouldn't switch banks.

 

My money is still on the data bus.  Personally, I'd try burning Video Pinball copied 4 times on one of the EPROMs and see if it plays right.  IIRC, Videoball Pinball relies on data bus persistence.

 

Or maybe code like this, just to see what happens:

 

lda $3F

CMP #$3F

BNE bus_not_persistent

 

Or maybe a program that access TIA regs and displays their contents to the screen.

But...why should it matter whether or not the bus is persistent or not? The only bits I'm using are the ones that are driven by the TIA. ?

 

EDIT: Just for kicks, I used this CXP0FB-reading code:

   lda CXP0FB
  bpl NoCollision
  lda #$FF
  .byte $2C
NoCollision
  lda #0
  sta SantaTemp

And I changed the #$FF to different things. I changed it to a #$00, a #$80, a #$70, a #$60, and a #$8F. Testing in emulation, all behaved as you would expect - when the highest bit was set, the game played normally; no problems. When the highest bit was set, no collisions with the playfield were registered, so you could walk through walls, but none of the other weird effects were seen - all sprite-to-sprite collisions were detected appropriately, the music didn't cut out, you could jump if there was no platform immediately above his head, regardless of whether his feet were in the playfield or not, the game did not crash at any point. Obviously, you'd need to do an exhaustive test of every value between 0 and 255 for both the #$FF and the #$00 (stored when no collision is detected) to be completely sure, but I am pretty convinced that the code isn't depending on the bus being persistent (i.e., it truly doesn't matter what bits D0-D5 are in the code).

 

I really think that when a collision occurrs between the player and the playfield and then CXP0FB is read in certain ways afterwards that, somehow, really really weird things are happening - either an unintended bankswitch is happening, the PC is being changed, the decimal flag, or others, is being altered, the TIA is being randomly written to or corrupted in some way, or some combination of the above, or something equally weird is happening.

Share this comment


Link to comment
I have a dipswitch multicart, and if you switch games while one is running, quite often the new game will run for a while in some screwed up state.  But plasibility alone doesn't suggest that bankswitching is the cause - it shouldn't switch banks.

 

My money is still on the data bus.  Personally, I'd try burning Video Pinball copied 4 times on one of the EPROMs and see if it plays right.  IIRC, Videoball Pinball relies on data bus persistence.

 

Or maybe code like this, just to see what happens:

 

lda $3F

CMP #$3F

BNE bus_not_persistent

 

Or maybe a program that access TIA regs and displays their contents to the screen.

But...why should it matter whether or not the bus is persistent or not? The only bits I'm using are the ones that are driven by the TIA. ?

If the bus is not persistent, something is pulling it low or high, meaning it could be overpowering the TIA as well.

Share this comment


Link to comment
EDIT: one more request: what the physical address that DASM compiles LDA CXP0FB to? And is it the target of a branch/JMP?

Regarding the above: I asked because most bankswitching logic is asynchronous. It doesn't seem likely, but for example, suppose you JMP'ed from address FF17 to FEF7 or something, and A5, A6, and A7 changed 10ns before A8, a logical glitch will occur and possibly trigger a bankswitch. Again, it doesn't seem likely, but I thought I'd throw it out there.

Share this comment


Link to comment

First, please see my edit to the comment above about what happens when I manually change the lower 7 bits - in a nutshell, it behaves like you expect it would: either collisions are detected or not depending on only the top bit, the lower 7 bits have no effect. Furthermore, when I force it to never detect a collision, it behaves like you'd expect - but none of the really weird behavior that Al has reported, like the music cutting out, the program crashing, and other collisions being detected haphazardly.

 

Thoughts?

EDIT: one more request: what the physical address that DASM compiles LDA CXP0FB to? And is it the target of a branch/JMP?

Regarding the above: I asked because most bankswitching logic is asynchronous. It doesn't seem likely, but for example, suppose you JMP'ed from address FF17 to FEF7 or something, and A5, A6, and A7 changed 10ns before A8, a logical glitch will occur and possibly trigger a bankswitch. Again, it doesn't seem likely, but I thought I'd throw it out there.

It compiles to $4155 and is RORGed to $F155. EDIT: this is NTSC only.

 

The code looks like this:

    sta WSYNC
   lda #0
   sta COLUBK
 IF TV_MODE = PAL
       sta WSYNC
       sta WSYNC
 ENDIF

  lda CXP0FB        ;<---this is at $4155 and $4156
  sta SantaTemp

   lda EnergyExtraLives
   and #$F0
   lsr
   lsr
   lsr       ;energy times 2
   tax
   lda EnergyLookup0,X
   sta Temp
and etc.

So, no, it is not the target of a jump or a branch.

Share this comment


Link to comment

  lda CXP0FB        ;<---this is at $4155 and $4156

  sta SantaTemp

So where is SantaTemp? Perchance is it something like $F9 and being overwritten by the stack, or something odd like that?

Share this comment


Link to comment

Just a quick note here before I go to bed. I just tested the five latest binaries Bob sent me and they all failed. One of these was a suggestion from Dennis and the other four were from Supercat. They all fail in exactly the same way, and reset back to the title screen at the same exact moment. At least it's consistent. :)

 

Not sure what to do at this point. I do have a pair of NTSC/PAL binaries where this problem does not occur with the TI parts, but it would be nice to have a solution that we know fixes the problem, rather than just shots in the dark. I've never seen such a weird compatibility issue before, especially with a type of EPROM I have used on many other occasions without problems (hell, I had to make a few Thrust+ and Pick 'n' Piles today, using those same TI 27C128 parts, without problems).

 

..Al

Share this comment


Link to comment

Hi there!

 

How about some reversed thinking approach:

 

What do you have to do, to *force* the wrong behaviour as described in an emulator?

 

Will any immediate replacement for

 

lda CXP0FB

sta SantaTemp

 

like

 

lda #%00000000

sta SantaTemp

 

or

lda #%11111111

sta SantaTemp

 

do something odd?

 

Try at least these:

 

#%11111111

#%01111111

#%10111111

#%11011111

#%11101111

#%11110111

#%11111011

#%11111101

#%11111110

#%00000000

#%10000000

#%01000000

#%00100000

#%00010000

#%00001000

#%00000100

#%00000010

#%00000001

 

Did you already modify the binary to find out which value is read in case of an error, like Dennis suggested?

 

Once you manage to force the bug in Z26 or Stella, it should be easy to solve.

 

Why would the music stop? On which condition is that based? How could this happen while the game is running? Is it some RAM variable *near* SantaTemp?

 

Greetings,

Manuel

Share this comment


Link to comment
Just a quick note here before I go to bed.  I just tested the five latest binaries Bob sent me and they all failed.  One of these was a suggestion from Dennis and the other four were from Supercat.  They all fail in exactly the same way, and reset back to the title screen at the same exact moment.  At least it's consistent.  :)

 

I am sure I'm out of my league here, but have you tried it on another console? I had a problem running just one level of just one game (Thrust+) on my light 6 console that didn't occur on my 4. The light 6 works just fine for every other game I've ever played on it. If everybody's fix seems to work for them, but not for you, maybe it's because the problem only occurs on a few consoles?

Share this comment


Link to comment

A couple of notes here: first, the four supercat binaries were #s 2-5 in supercat's post above. The first one was tested previously and failed.

 

Dennis' suggestion was to change TIA_BASE_READ_ADDRESS to $30 but still use this code: lda CXP0FB sta SantaTemp (the original code)

 

SantaTemp should not be overwritten by the stack normally; its address is in the $D9-$E6 range.

 

Also, when I made a binary that did this:

 lda SomethingRandom
and #$3F
eor CXP0FB

I used the frame counter for SomethingRandom, which is decremented once per frame. No bugs of any kind were observed in an emulator with that particular binary.

 

As I tried to explain above, though I don't think I was very clear, I also made several binaries, which I tested in an emulator, which forced different values into SantaTemp instead of the contents of CXP0FB.

 

They all behaved as you would expect them to: every value with the top bit clear prevented PF collision from being acted on and every value with the top bit set acted as if Santa was constantly hitting the PF. But I was never able to reproduce any of the weird behavior - game resetting, crashing, music cutting out, sprite collisions not registering - in an emulator.

 

My current theory, based only on the symptoms, is that the EPROM does not like the floating bits in CXP0FB and when the code tries to write to RAM, in certain ways, after loading something with undefined bits, it is overwriting the bits in the opcode or the address, or both, of the following instruction.

 

I.e., after the lda CXP0FB, when the code tries to do a 'sta SantaTemp', i.e., sta $Dx, the EPROM is instead changing random bits in the address it is storing to; e.g., instead of sta $DC it is executing sta $1C or sta $36 - and perhaps also changing random bits in the 'sta' opcode, changing it to 'jmp' or something else odd. Or both.

 

This seems unlikely, I admit. But the effects Al has described sounds to me like TIA registers are being oddly written to, the PC is being changed in odd ways, odd bankswitches are happening, or the SP is being changed.

 

Maybe I'll try to test this in an emulator with this code...

   lda CXP0FB
  tax
  sta $00,X

And see what happens. :)

 

The only way that the code has been executed successfully is when, after loading CXP0FB, the program only depends on the flags and immediately overwrites the accumulator with some other value (i.e., with #$FF) or, in one other case, when the code loads CXP0FB, clears the floating bits (and #$C0), sets one of the floating bits (ora #$02), then waits 3 more cycles (jmp NextInstruction), and then writes the value in the accumulator to RAM.

 

Just waiting 14 cycles after loading CXP0FB (with 7 nops) didn't work. Just overwriting the accumulator (supercat's other ideas above) didn't work.

 

I told my dad about this problem (he's a mechanical engineer, so take what you will from this), and his first reaction was to wonder if the batch of EPROMs are bad.

 

A few other answers:

 

The music could stop in two ways: there is a GlobalVolume variable; if that is set > 15 then the music will not be heard. If the right difficulty switch is set to A then the music will stop. GlobalVolume is about 6 bytes after SantaTemp. GlobalVolume is also not touched except when Santa dies, when a level is over, and when RESET is pressed. So if GlobalVolume was overwritten with something greater than 15 (actually, greater than 8 would do it as well), then the music would come off and not return until one of those conditions. A related question for Al: do the sound effects cut out as well, or just the music?

 

And no, I haven't yet modified a binary to write the contents of CXP0FB to the screen somehow. Maybe I'll work on that. The easiest way would be to convert the binary value to two bcd bytes and then write that to the score. Anybody have a nice, short routine that can do that?

Share this comment


Link to comment
I told my dad about this problem (he's a mechanical engineer, so take what you will from this), and his first reaction was to wonder if the batch of EPROMs are bad.

These EPROMs are not all from the same "batch", but they are all TI 27C128 parts, of various speeds (most are 100ns). All of these EPROMs behave the same way, and it's obvious they were manufactured at different times by TI (the printing is different, the ceramic casing is physically different, the speeds are different, and so forth). So they all behave consistently, regardless of when they were manufactured by TI, so I'd have to say they were built as TI intended them. Whether or not they fall out of the official 27128 spec is beyond me.

 

I am going to dig up a few additional 2600 systems and some other power supplies in a few minutes to check and see if this problem occurs on other 2600 systems. The system I've been using is a vader 2600, so I'll grab a six switch and a wood-grain 4 switch as well, and two more power supplies. Will report my findings back here in an hour or two.

 

..Al

Share this comment


Link to comment
And no, I haven't yet modified a binary to write the contents of CXP0FB to the screen somehow.  Maybe I'll work on that.  The easiest way would be to convert the binary value to two bcd bytes and then write that to the score.  Anybody have a nice, short routine that can do that?

Not nice or short. This code is horribly inefficient, actually, but it think it might work. Count1-2 are temp vars, and the result is two BCD bytes 00 00 to 02 55 in scorehigh and scorelow.

 

 lda #0
 sta count1
 sta count2
 lda SantaTemp
 sec
div100
 cmp #100
 bcc div10
 sbc #100
 inc count1
 jmp div100
div10
 cmp #10
 bcc donediv
 sbc #10
 inc count2
 jmp div10
donediv
 asl count2
 asl count2
 asl count2
 asl count2
 ora count2
 sta scorelow
 lda count1
 sta scorehigh

Share this comment


Link to comment
And no, I haven't yet modified a binary to write the contents of CXP0FB to the screen somehow.  Maybe I'll work on that.  The easiest way would be to convert the binary value to two bcd bytes and then write that to the score.  Anybody have a nice, short routine that can do that?

 

You're handling the score in BCD, right? Just write the byte value directly to the score. If a nybble is 0-9 it will show up as a digit. If it's A-F it'll show up as some garbage character. If that happens, look through the code to figure out what it is.

Share this comment


Link to comment

Okay, just did some testing on three different Atari 2600 systems using three different power supplies. The game behaves the same on each of them, using the original version with the TI 27C128 EPROMs. I took some video so you can see exactly what is taking place:

 

http://www.atariage.com/temp/reindeer_1.avi

 

If you have your volume turned up, you can hear exactly when the audio cuts out.

 

..Al

Share this comment


Link to comment
Just a quick note - you can get better video by recording from the 2600 straight into a VCR. :)

You're right, but then I have to get the video into my computer and I don't have a way to do that right now. And I'd use one of my TiVos instead of a VCR. :D

 

..Al

Share this comment


Link to comment

Since everyone's baffled at this point, I have a crazy suggestion... but I suspect y'all are up for any half-baked idea at this point if it works.

 

In place of LDA CXP0FB .. STA SantaTemp, try these:

1.

 and #$0
 ora CXP0FB
 STA SantaTemp

2.

 and #0
 eor CXP0FB
 STA SantaTemp

3.

 and #0
 clc
 adc CXP0FB
 STA SantaTemp

4.

 asl CXP0FB+$30; no physical write reg at $32
 ror SantaTemp

5.

 lsr
 ora CXP0FB
 sta SantaTemp

If my wild conjecture is correct, then all of the above will work. Can anyone guess what all of the above have in common?

Share this comment


Link to comment
If my wild conjecture is correct, then all of the above will work.  Can anyone guess what all of the above have in common?

 

They'll all put bit 7 of CXP0PF into bit 7 of SantaTemp. Not sure what else they have in common. If you're looking for weird and wacky ways to do that, how about:

 lda #128
 cmp CXP0PF
 adc #127 ; Decimal mode must be clear

That's an approach I just thought of for turning a bit into a 00 or FF. Actually, it might be useful for a number of things.

Share this comment


Link to comment
If my wild conjecture is correct, then all of the above will work.  Can anyone guess what all of the above have in common?

I'm in the process of creating these binaries, and I will send them to Al when I've got them. I will also create a binary with the original code (lda CXP0FB sta SantaTemp) that writes the contents to the score so you can see what's going on.

 

Plus, I will try out some of my crazy ideas for reproducing the behavior on an emulator. Unfortunately, while I'm on dialup (for the next 2 weeks :)) I can't devote 2+ hours of phone time in order to download the video Al posted, so I'm depending on descriptions here.

 

I'll email those to Al hopefully within a couple of hours.

 

Also, one thing they all have in common is that none of them LDA CXP0FB.

Share this comment


Link to comment
If my wild conjecture is correct, then all of the above will work.  Can anyone guess what all of the above have in common?

 

They'll all put bit 7 of CXP0PF into bit 7 of SantaTemp.

The answer is more subtle than that. If I am correct, it is also the reason why BIT worked but not LDA.

Not sure what else they have in common.  If you're looking for weird and wacky ways to do that, how about:

 lda #128
 cmp CXP0PF
 adc #127; Decimal mode must be clear

That's an approach I just thought of for turning a bit into a 00 or FF.  Actually, it might be useful for a number of things.

If my guess is correct, then the above code will not work. My guess is a total shot in the dark, but if it is correct, it just points to the cause and doesn't necessarily offer a solution.

Share this comment


Link to comment
If my wild conjecture is correct, then all of the above will work.  Can anyone guess what all of the above have in common?

 

They'll all put bit 7 of CXP0PF into bit 7 of SantaTemp.

The answer is more subtle than that. If I am correct, it is also the reason why BIT worked but not LDA.

Not sure what else they have in common.  If you're looking for weird and wacky ways to do that, how about:

 lda #128
 cmp CXP0PF
 adc #127; Decimal mode must be clear

That's an approach I just thought of for turning a bit into a 00 or FF.  Actually, it might be useful for a number of things.

If my guess is correct, then the above code will not work. My guess is a total shot in the dark, but if it is correct, it just points to the cause and doesn't necessarily offer a solution.

A few notes:

 

First of all - LDA did work! But only when used like this:

   lda CXP0FB
  bpl NoCollision
  lda #$FF
  .byte $2C
NoCollision
  lda #0
  sta SantaTemp

 

Second, I'm making a package of 7 binaries to PM to Al. I'm sending him all five of batari's latest, supercat's weird 'n' wacky method, and one with this:

   lda CXP0FB
  sta SantaTemp
  sta Score          ;<--this is the left-most two digits of the score

They all work in emulation as they should.

 

I also tried doing some crazy things to reproduce the weird behavior Al has seen, without much luck. I think this probably is because the floating bits in CXP0FB are consistent in z26 and Stella. But who knows. If anybody has any ideas of what code could produce the weird behavior in emulation, please let me know and I'll try it out. Thanks everyone. :)

Share this comment


Link to comment
If you're looking for weird and wacky ways to do that, how about:

 lda #128
 cmp CXP0PF
 adc #127; Decimal mode must be clear

That's an approach I just thought of for turning a bit into a 00 or FF.  Actually, it might be useful for a number of things.

 

I just realized, it should be:

 lda #127
 cmp CXP0PF
 adc #128

That way, if CXP0PF happens to yield exactly 128 this will still work. Don't think it matters for this, but if one's using the trick for other purposes it might.

Share this comment


Link to comment
I just realized, it should be:

 lda #127
 cmp CXP0PF
 adc #128

That way, if CXP0PF happens to yield exactly 128 this will still work.  Don't think it matters for this, but if one's using the trick for other purposes it might.

Yeah, I thought that it might not work in all cases, but I didn't take time to check.

Share this comment


Link to comment

Okay, Bob sent me seven binaries to test a few hours ago, and I was just able to spend some quality time testing them. The results are interesting. Here's part of the PM I sent to Bob:

 

Results of my testing:

 

rr_batari1.bin - fails

rr_batari2.bin - fails

rr_batari3.bin - worked - played into level 2, no problems

rr_batari4.bin - fails

rr_batari5.bin - fails

rr_supercatwildnwacky.bin - fails

 

rr_scoredisplay.bin -

 

First, here's what Bob said about the special "rr_scoredisplay.bin":

 

One of them has the original code but also writes the contents of CXP0FB to the highest 2 digits of the score. In z26 it writes 02 or 82 depending on whether Santa is hitting the playfield or not. Could you let me know what values it is showing there in other cases? It might show weird graphics instead of numerals if the high/low nibbles are > 9.

Starts with 33, then flickers a bit when Santa first hits the playfield, and then the first digit gets stuck between 2 and 4 while Santa is behind the playfield. The second digit remains 3 the entire time. I then tried this binary with a non-TI EPROM and I see what you described in z26-- when Santa is not hitting the playfield, it displays " 2" (a space and 2, not "02") and when Santa is bumping up against the playfield, I see "82".

 

Okay, so I got curious and I tested EVERY type of 27128 EPROM I have. The following parts behave as Bob saw in z26:

 

SEEQ 27128

Toshiba TMM27128AD

Hitachi HN4827128G

Mitsubishi M5L27128K

ST M27128A

NEC D27128D

Intel D27128A

 

The last one I tried was a General Instruments 27C128. When I fired this up with the rr_scoredisplay.bin, I saw different results. I see " 7" when Santa isn't hitting the playfield and then "87" when Santa hits the playfield. The *first* time I put this board in I saw different numbers, but I cannot reproduce that and now it's consistently showing "07" and "87".

 

So, this reveals something--the only parts that are acting differently are CMOS parts.. Specifically the TI 27C128 and GI 27C128 parts. The game still works with the GI part, even though the values you're expecting are a bit different. Those who understand the internal electronics behind the EPROMs could perhaps discern something from this.

 

..Al

Share this comment


Link to comment

Hi there!

 

The whole thing reminds me of an old usenet signature:

 

"I don't have a solution, but I admire the problem"

 

Pretty much how I feel now :)

 

Greetings,

Manuel

Share this comment


Link to comment
The whole thing reminds me of an old usenet signature:

 

"I don't have a solution, but I admire the problem"

 

I may have to steal that. :)

 

Here's one I use at work:

 

"Technology is a matter of trial and error. Right now, we're doing 'error'."

 

:D

Share this comment


Link to comment

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...