Jump to content





Reindeer Rescue Bug

Posted by , 15 December 2005 · 2,015 views

2600 Game Development Reindeer Rescue
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:Attached Image




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?
  • Report

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.
  • Report

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.
  • Report

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.
  • Report

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. :)
  • Report

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.
  • Report

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.
  • Report
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
  • Report
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
  • Report

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
  • Report

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

Interesting... this means my theory is wrong. As to why #3 would work and not the others, I haven't a clue.

But the score display thing reveals that the problem is with the EPROM mucking up the data bus. But this shouldn't happen...should it?

Anyway, I'd look into a hardware hack, as this doesn't appear to be software problem.

Try clipping a resistor (say 20-50k ohms) from D7 to Vcc (that's pin 19 to pin 28 on the EPROM.) Maybe this will give D7 enough boost to read the collisions properly.
  • Report
A quick note:

Thanks Al, for doing all this testing. :)

Second, I have played around more with forcing different values into SantaTemp in order to reproduce the weird behavior Al has seen. Short version: There is no way to reproduce any of the really weird behavior he has seen by putting different values into SantaTemp.

I tried this code:
  lda Counter     ;<--variable that is decremented once per frame
   and #$7F
   sta Temp
   lda CXP0FB
   and #$80
   ora Temp
   sta SantaTemp
   sta Score                 ;<---high two digits of score
I could see by looking at the score that the contents of SantaTemp were cycling rapidly through every possible value (0-127 when not hitting PF, 128-255 when hitting PF), but other than that the game played exactly as it should. I'm taking this as absolute confirmation that the code nowhere depends on any of the bits in CXP0FB/SantaTemp except bit 7.

I also tried this version:
  lda Counter
   and #$7F
   sta SantaTemp
   sta Score
I could see in the score that SantaTemp was holding all values between 0 and 127 in rapid succession, and (since I forced bit 7 to zero at all times) no collisions with the playfield were ever registered - but otherwise, the game played completely normally.

Also tried this version:
  lda Counter
   sta SantaTemp
   sta Score
So here every value was forced into SantaTemp in numerical order.
This behaved predictably - when bit 7 was zero, the game behaved as if Santa was not hitting the playfield; when the top bit was 1, Santa behaved as if he was hitting the playfield. Otherwise everything was completely normal. This version was not playable since when Santa "hits the playfield" for 127 consecutive frames he is rapidly pushed off the screen to the left. And since this happens every 4 seconds or so in this version, games end rather quickly. :D

But again, I have not been able to reproduce ANY of the weird behavior just by forcing different values into SantaTemp.

I stand by my conclusion that the CMOS EPROMs are somehow corrupting the address and/or opcode of the 'sta SantaTemp' instruction!
  • Report

I stand by my conclusion that the CMOS EPROMs are somehow corrupting the address and/or opcode of the 'sta SantaTemp' instruction!

I agree with you. The EPROM is supposed to float the data bus when reading/writing TIA regs or RAM. During this time, either /CE or /OE or both is supposed to go high.

Apparently it is not fully floating the bus - it must be weakly pulling data lines up or down, possibly depending on what data is located at the address on its address lines. I looked at the TIA schematics, and it only drives values low - high values are caused by pullup resistors.

It seems that loading from CXP0FB causes an incorrect value to be placed in the accumulator, but a correct value is placed in processor flags. Maybe a different mechanism is used in the 6507 for each - and the flaky value on D7 goes one way or the other.

I have two more suggestions, one hardware, one software. One is the pullup resistor on D7. If I am correct about this, all versions will work if this resistor is in place.

Another suggestion is to change the STA $1FF6's at the beginning of the banks to STA $FFF6. If this works, I'll explain my theory.
  • Report

Another suggestion is to change the STA $1FF6's at the beginning of the banks to STA $FFF6.  If this works, I'll explain my theory.

PMed a binary with this change to Al. We'll see.

EDIT: Here's a recap of where we're at right now:

The problem: on TI EPROMs, the game exhibits very strange behavior that has not been reproduced in emulation. This behavior includes what appears to be unintended writes to TIA registers and/or RAM locations, unintended changes in the PC and/or SP, and unintended bankswitches. Specifically, the music cuts out for no apparent reason, sprite-to-sprite collisions are inconsistently detected, sprite-to-playfield collisions are only detected once, initially, and then ignored thereafter, and the game resets to the title screen (as if the code executed a BRK) or freezes (as if the code executed a HLT opcode, e.g., $02). Most of this behavior is consistent, though unexplainable.

The issue perhaps lies with the sprite-to-playfield collision-reading code, which originally was this:
  lda CXP0FB
   sta SantaTemp
By changing this code (but only in certain ways!) we have gotten the game to run apparently correctly on the TI EPROMs - though no one is really sure why.
Here are the modifications that have worked:
;--batari solution that worked
  and #0
  clc
  adc CXP0FB
  STA SantaTemp

 ;--supercat solution that worked
  lda CXP0FB
  and #$C0
  ora #2
  jmp ImHere
ImHere
  sta SantaTemp

 ;--Manuel solution that worked
  lda CXP0FB
  bpl NoCollision
  lda #$FF
  .byte $2C
NoCollision
  lda #0
  sta SantaTemp

 ;--my solution that worked
  bit CXP0FB
  bpl NoCollision
  lda #$FF
  .byte $2C
NoCollision
  lda #0
  sta SantaTemp
All other suggested changes have not worked, including changing the TIA_BASE_READ_ADDRESS to $30.
  • Report

Apparently it is not fully floating the bus - it must be weakly pulling data lines up or down, possibly depending on what data is located at the address on its address lines.  I looked at the TIA schematics, and it only drives values low - high values are caused by pullup resistors.


Always-on pullup resistors? Hmm... I wonder how my 4A50 cart works then, since it relies upon the data bus to be floating when the processor isn't doing anything to it.

It seems that loading from CXP0FB causes an incorrect value to be placed in the accumulator, but a correct value is placed in processor flags.  Maybe a different mechanism is used in the 6507 for each - and the flaky value on D7 goes one way or the other.


How does the "Supercat" solution work, then (LDA, followed by masking)?
  • Report

It seems that loading from CXP0FB causes an incorrect value to be placed in the accumulator, but a correct value is placed in processor flags.  Maybe a different mechanism is used in the 6507 for each - and the flaky value on D7 goes one way or the other.


How does the "Supercat" solution work, then (LDA, followed by masking)?

I think that batari's diagnosis is a little off.
I think it is possible to get the correct value in the accumulator, but for whatever reason it needs a little help (i.e., supercat's AND/ORA/JMP combination) and, if it doesn't get that help, not only is an incorrect value stored in the accumulator but the following instruction(s) are corrupted in some way.

At least, that's my tentative theory, though I'm not sure how batari's working solution fits in. :)
  • Report

Apparently it is not fully floating the bus - it must be weakly pulling data lines up or down, possibly depending on what data is located at the address on its address lines.  I looked at the TIA schematics, and it only drives values low - high values are caused by pullup resistors.


Always-on pullup resistors? Hmm... I wonder how my 4A50 cart works then, since it relies upon the data bus to be floating when the processor isn't doing anything to it.

The pullups seem to only be on bits 6 and 7. They might not be always-on either. Look at the TIA schematics to see what I am referring to (in the collision registers, to the right there are two resistors tied to what looks like a circle with a plus in it (I assume this means +5v.) The rest of the bits are always floating.

It seems that loading from CXP0FB causes an incorrect value to be placed in the accumulator, but a correct value is placed in processor flags.  Maybe a different mechanism is used in the 6507 for each - and the flaky value on D7 goes one way or the other.


How does the "Supercat" solution work, then (LDA, followed by masking)?

Ok, so this guess is wrong. I was just speculating.
  • Report

Another suggestion is to change the STA $1FF6's at the beginning of the banks to STA $FFF6.  If this works, I'll explain my theory.

Al tested this; he said it did not work:

I see "33" when Santa is gleefully running along, and then a "stuck" digit (between 2 and 4 or something like that) and 3 when Santa is wedged in the poor playfield.

So there you go. Incidentally, I think by "stuck" digit between 2 and 4 he means this:

...


Oh yeah, can't attach things to comments. Well, I'll attach it to the original blog post at the top, you can see it there. In any case, my point was that this corresponds to: $B

So the value it is reporting is $33 when no collision between player 0 and the playfield and a $B3 when there is a collision...which makes sense. But notice the code that binary is using:
  lda CXP0FB
   sta SantaTemp
   sta Score
I bet all the weird stuff is happening during the 'sta SantaTemp' instruction and that everything is back to normal at the 'sta Score' instruction. So if you switched the code to this:
  lda CXP0FB
   sta Score
   sta SantaTemp
That SantaTemp would have the correct value stored, so the playfield-to-sprite collisions would be handled eventually, but we would still see weird behavior. Or...:)

BTW: I was able to check and SantaTemp is $DF
  • Report

Another suggestion is to change the STA $1FF6's at the beginning of the banks to STA $FFF6.  If this works, I'll explain my theory.

Al tested this; he said it did not work:

...

BTW: I was able to check and SantaTemp is $DF

$DF should properly register a collision but it doesn't? Why? :)

But as for additional suggestions, I have none except "use different EPROMS" or "send me a cart and I will hook it up to a logic analyzer" but there's not enough time for this...
  • Report

BTW: I was able to check and SantaTemp is $DF

$DF should properly register a collision but it doesn't? Why? :D

Um, maybe I wasn't clear. I meant that the address of SantaTemp is $DF. So sta SantaTemp is equivalent to sta $DF.

But as for additional suggestions, I have none except "use different EPROMS" or "send me a cart and I will hook it up to a logic analyzer" but there's not enough time for this...

Maybe there is. I think Al has enough non-TI EPROMs for a little while. I don't want to volunteer anybody or anything, but if you can do something with the actual cart that would tell us what is going on, you might ask Al to send you a cart. :)
  • Report