RAMBO-1 Mapper Investigation

Discuss hardware-related topics, such as development cartridges, CopyNES, PowerPak, EPROMs, or whatever.

Moderators: B00daW, Moderators

NewRisingSun
Posts: 1123
Joined: Thu May 19, 2005 11:30 am

Re: RAMBO-1 Mapper Investigation

Post by NewRisingSun » Sat Dec 07, 2019 4:27 pm

I think you should exclude that first sample from your measurements, because the vblank stuff is only making things more complicated than necessary.

User avatar
Ben Boldt
Posts: 486
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: RAMBO-1 Mapper Investigation

Post by Ben Boldt » Sat Dec 07, 2019 4:27 pm

NewRisingSun wrote:
Sat Dec 07, 2019 4:12 pm
Ben Boldt wrote:What do you mean by 21 -- is that 21 since the beginning of the scanline?
No, it means 21 M2 cycles since the last time that PA12 was high, whatever the reason for that was. WIth that particular write, the game just wants an IRQ to occur at around pixel 288 of scanline 0.
Okay, that makes sense. I am just happy to have figured that out, I was really stuck on that one, it took me a whole pot of coffee. I will go back and try to do your recent step-by-step next.

User avatar
Ben Boldt
Posts: 486
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: RAMBO-1 Mapper Investigation

Post by Ben Boldt » Sat Dec 07, 2019 7:46 pm

I kind of went off on my own a little bit here, sorry I didn't try your test yet newrisingsun.

I went back to my previous test method from before I shared my test code -- I have not described how it works yet. It has 4 variables, A, B, C1, and C2. This test loops, it is not a 1-shot, and it does not try to simulate a valid PPU sequence or v-blank, etc. Very low-level test.

PA12 starts as 0.

Step 1:
Write $04 to $C000: Set IRQ counter reload value to 4.

Step 2:
Write $00 to $C001: Set IRQ mode to scanline mode, reset counter.

Step 3:
Write $00 to $E001: Enable IRQ.

Step 4:
Read from $8000 'A' times. (Since Step 3 counted as an M2 cycle, it is actually A+1 M2 cycles here.)

Step 5:
Set PA12 = 1.

Step 6:
Read from $8000 'B' times.

Step 7:
Set PA12 = 0.

Step 8:
If scanline_count < 10: read from $8000 'C1' times. Then scanline_count++, go to step 3. (I was going back to step 4 here, which was inconsistent with the note in step 4, so I changed it to step 3, which made a difference in my results.)
else: read from $8000 'C2' times. Then scanline_count = 0, go to step 9.

Step 9:
Write $00 to $E000: Acknowledge and disable IRQ. Then go to step 2.


This is the test where I found the 'opposite of what we expect' numbers earlier. I tried a lot more values now.

- To trigger any scanlines, (A+1) + C1 must be at least 16.
- If C2 <= 14 *** AND *** (A+1) + C2 >= 14, you get a +1. (Both must be true at the same time to get a +1.)
- In all other cases I tried, you get a +2.

- B minimum = 1. No differences found with larger B values.
- C1 and C2 minimum = 0. Above equations hold true with C1 = 0 or C2 = 0.
- A minimum = 0. Above equations hold true with A=0, even when skipping the extra M2 from step 3.

User avatar
Ben Boldt
Posts: 486
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: RAMBO-1 Mapper Investigation

Post by Ben Boldt » Mon Dec 09, 2019 11:32 pm

I have been working on this a little bit, thinking about how these observations can be explained with some simple counters. Following through the sequence, this magic number 14 can probably turn into a 16 by counting or not counting the writes in steps 2, 3, and 9. It sure seems like there is a 4-bit M2 counter that feeds into an 8-bit scanline counter. I don't want to share my scribbles until I get things a little more refined, but what I am looking at points to this prediction: If the scanline counter is running with IRQ enabled, and you write $00 to $C001 (i.e. reset the counter with it already running with IRQ high), it seems you would immediately get an IRQ low. I will try this tomorrow to help verify I am on the right track.

User avatar
Ben Boldt
Posts: 486
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: RAMBO-1 Mapper Investigation

Post by Ben Boldt » Tue Dec 10, 2019 2:41 pm

I think that this is close but needs more testing and tweaking, also more verification against known functions:

On M2 falling edge:
  • If PA12 = 0:
    • If 4-bit counter < 15: 4-bit counter++.
    • else stay at 15.
  • If PA12 = 1:
    • If 4-bit counter = 15: Clock the 8-bit counter.
    • Always reset 4-bit counter to 0.
On 8-bit counter clock:
  • If value = 0:
    • If IRQ is enabled, trigger IRQ
    • Always reload counter with value in $C000.
  • Else value--.
On Write to $C001:
  • Reload 8-bit counter with value in $C000
  • Do not reset the 4-bit counter, but do count it as an M2 cycle for that counter.

User avatar
Ben Boldt
Posts: 486
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: RAMBO-1 Mapper Investigation

Post by Ben Boldt » Wed Dec 11, 2019 10:23 am

Here is a diagram for the 4-bit counter. If you were to create the RAMBO-1 scanline counter out of 7400 logic using counter chips, etc, the transition from state 15 to state 0, causing a clock to the 8-bit counter, would be done by connecting the ripple output of the 4-bit counter to the clock input of the 8-bit counter.
RAMBO-1_4-bit_counter.png

User avatar
Ben Boldt
Posts: 486
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: RAMBO-1 Mapper Investigation

Post by Ben Boldt » Wed Dec 11, 2019 4:40 pm

Just to be clear, what I have described is a work-in-progress, it doesn't work yet but I think it is on the right track. I am working on simulating it, a program that takes in the A/B/C1/C2 values and counts the 15->0 transitions. My goal is to get the simulation to match the observations. When I explicitly follow what I shared here, I am having some trouble with it, I am getting +0 and +1 with other problems too, but should be easier to debug my logic now with this program.

User avatar
Ben Boldt
Posts: 486
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: RAMBO-1 Mapper Investigation

Post by Ben Boldt » Thu Dec 12, 2019 4:52 pm

Not really an update but sharing a screenshot of the GUI I'm using to do this. It is very confusing... Starting to think there is a state 16 in the diagram I shared earlier, some things make more sense that way. Anyway, I am still working on it. Shown in screenshot, 8/1/14/4 result should be 6... :?
test_gui.png

User avatar
Ben Boldt
Posts: 486
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: RAMBO-1 Mapper Investigation

Post by Ben Boldt » Fri Dec 13, 2019 10:26 am

Okay, this is really close now, it always works when B=1. I didn't think there was any dependence on B before but the result is +1 in many simulated tests with B > 1, where the real chip does +2. In summary of where I am at:
  • The 4-bit counter has 17 states, 0-16 (so not technically 4 bits anymore but still calling it that for simplicity.)
    • This doesn't mean it couldn't be implemented with an actual 4-bit counter configured in an interesting way, so let's not be discouraged by "17".
  • $C001 reset resets the 8-bit counter, does NOT reset the 4-bit counter, but does give a normal M2 cycle to the 4-bit counter
  • Every M2 cycle counts for the 4-bit counter, including all register writes, reload, reset, disable, enable
There is probably something wrong with this line in the code below:
numericUpDown4bit.Value = 0; // <<== *** Need to focus on this for B > 1. ***
Maybe it has to do a decrement instead of a clear, etc, will play with it.

Code: Select all

        private void dec8bit()
        {
            if( 0 == numericUpDown8bit.Value )
            {
                if (checkBoxIRQEnabled.Checked)
                {
                    checkBoxIRQAsserted.Checked = true;
                }
                numericUpDown8bit.Value = numericUpDownReload.Value;
            }
            else
            {
                numericUpDown8bit.Value--;
            }
        }

        private void m2_cycle()
        {
            if( checkBoxPA12.Checked )
            {
                if( 16 == numericUpDown4bit.Value )
                {
                    dec8bit();
                }
                numericUpDown4bit.Value = 0;  // <<== *** Need to focus on this for B > 1.  ***

                // This stuff is specifically for testing -- not a behavior of the chip.
                if (false == checkBoxIRQAsserted.Checked)
                {
                    irqTriggerCounted = false;
                }
                if ((0 == numericUpDown4bit.Value) && (false == irqTriggerCounted) && (false == irqA12Counted)) 
                {
                    numericUpDownResult.Value++;
                    if( true == checkBoxIRQAsserted.Checked )
                    {
                        irqTriggerCounted = true;
                    }
                    irqA12Counted = true;
                }
                // End testing specific stuff.

            }
            else
            {
                // This stuff is specifically for testing -- not a behavior of the chip.
                irqA12Counted = false;
                // End testing specific stuff.
                if( numericUpDown4bit.Value < 16 )
                {
                    numericUpDown4bit.Value++;
                }
            }
            logCycle();
        }

        private void reload()
        {
            operationText = "Reload";
            numericUpDownReload.Value = numericUpDownReloadGUI.Value;
            m2_cycle();
        }

        private void reset()
        {
            operationText = "Reset";
            numericUpDown8bit.Value = numericUpDownReload.Value;
            m2_cycle();
        }

        private void disable()
        {
            operationText = "Disable";
            checkBoxIRQEnabled.Checked = false;
            checkBoxIRQAsserted.Checked = false;
            m2_cycle();
        }

        private void enable()
        {
            operationText = "Enable";
            checkBoxIRQEnabled.Checked = true;
            m2_cycle();            
        }

Edit:
I have to take a step back because I just found that 10/1/15/15 simulation does not match the chip. Simulation says +1 and real chip says +2. So here is a failure with B=1.

NewRisingSun
Posts: 1123
Joined: Thu May 19, 2005 11:30 am

Re: RAMBO-1 Mapper Investigation

Post by NewRisingSun » Fri Dec 13, 2019 12:33 pm

Certainly looks nice, though I am not sure I follow all of your tests. But do not hesitate to ask if you need any specific input from me.

User avatar
Ben Boldt
Posts: 486
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: RAMBO-1 Mapper Investigation

Post by Ben Boldt » Fri Dec 13, 2019 2:03 pm

I found the problem causing this discrepancy. It is a known observation that C2>14 will always be a +2, but my approach has no upper bound on C2 in this way. The little curly loop with PA12=0 above state 15 (actually state "16" now) causes this -- that loop must not be quite right.

Code: Select all

A   B   C1  C2  Chip  Sim Success
10  1   5   3   +1    +1  :)
10  1   5   4   +1    +1  :)
10  1   5   2   +2    +2  :)
10  1   6   2   +2    +2  :)
10  1   15  2   +2    +2  :)
10  1   15  4   +1    +1  :)
10  1   15  5   +1    +1  :)
10  1   15  14  +1    +1  :)
10  1   15  15  +2    +1  FAIL!
9   1   15  14  +1    +1  :)
9   1   15  15  +2    +1  FAIL!
8   1   15  14  +1    +1  :)
8   1   15  15  +2    +1  FAIL!
8   2   15  14  +1    +1  :)
8   2   15  15  +2    +1  FAIL!
8   1   15  16  +2    +1  FAIL!
8   1   15  17  +2    +1  FAIL!
8   1   15  18  +2    +1  FAIL!
8   1   15  19  +2    +1  FAIL!
8   1   15  20  +2    +1  FAIL!
8   1   15  21  +2    +1  FAIL!
8   1   15  22  +2    +1  FAIL!
8   1   15  23  +2    +1  FAIL!
8   1   15  24  +2    +1  FAIL!
8   1   15  25  +2    +1  FAIL!
8   1   15  26  +2    +1  FAIL!
8   1   15  27  +2    +1  FAIL!
8   1   15  28  +2    +1  FAIL!
8   1   15  29  +2    +1  FAIL!
8   1   15  30  +2    +1  FAIL!
8   1   15  31  +2    +1  FAIL!
8   1   15  32  +2    +1  FAIL!
8   1   15  33  +2    +1  FAIL!
8   1   15  34  +2    +1  FAIL!
Edit:

Another problem with my simulation is that it triggers IRQ always 1 M2 cycle too early. It is supposed to wait until the next M2 cycle after the first one where PA12 is high, regardless of PA12 on that cycle. Nothing in my approach considers this known fact. Maybe I need another latch/flopflop somehow instead of adding this weird state 16.

User avatar
Ben Boldt
Posts: 486
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: RAMBO-1 Mapper Investigation

Post by Ben Boldt » Fri Dec 13, 2019 5:00 pm

Okay, I have the simulator working for every single case I have thrown at it now, most stubborn of which happened to be 171/214/56/56. With so many counts on each variable (very realistic), and still resulting in a "missed scanline", aka +2, it made it obvious that another non-counting state must be happening here for that to be possible. My simulator still has IRQ on the first CPU cycle with PA12 high instead of the next one. Here are the rules:

On M2 falling edge:
  • If PA12 = 0:
    • If 4-bit counter < 16: 4-bit counter++.
    • else keep the same value.
  • If PA12 = 1:
    • If 4-bit counter = 16: Clock the 8-bit counter.
    • Always reset 4-bit counter to 0.
On 8-bit counter clock:
  • If value = 0:
    • If IRQ is enabled, trigger IRQ (wait 1 more cycle before doing that though, regardless of PA12 next cycle...)
    • Always reload counter with value in $C000.
  • Else value--.
On Write to $C001 (reset):
  • Reload 8-bit counter with value in $C000
  • Do not reset the 4-bit counter, but do count it as an M2 cycle for that counter.
  • Set 4-bit counter to 17.
Though this might be refined to use an actual 4-bit counter (values 0-15 only, plus another state machine for example), and share its parts with the M2 counter mode, I think that following these rules will result in the correct number of scanlines generating IRQ.

User avatar
Ben Boldt
Posts: 486
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: RAMBO-1 Mapper Investigation

Post by Ben Boldt » Sat Dec 14, 2019 9:26 am

Here is a diagram of how you could implement the scanline detection in hardware. This may well have errors in it, but I think it can demonstrate the concepts of what is going on better.
rambo-1_state_machines.png
If these types of state diagrams don't make sense, it really is worth learning. This is the way they teach it in engineering school, and it is very powerful once you understand. Basically, you have to follow an arrow each falling edge of M2. Each circle represents a "state", which end up being combinations of flip-flop outputs. For this reason, there is always a 2^n number of states in every state machine. So if you ever see a state machine with 3 states, you KNOW that there is a 4th state! :) Whether it does anything or is reachable or not, it is guaranteed to exist. ;) Either that or there are only really 2 states and 1 of them doesn't really exist, etc. These are the kinds of tools and tricks we can use to reverse engineer stuff like this.

I will try to simulate the diagram next week some time to debug it. Very doubtful that it works perfectly yet, but I still believe the method with counts 16 and 17 described earlier should work in every case.


Edit:
Something that I have never tried is writing to $C0001 with PA12 = 1. My diagram is ambiguous in this way -- you don't necessarily know which arrow to follow when this happens. For all I know, it might need more arrows added for this. All inputs should be labeled on all arrows, my bad. I will have to experiment to figure out what happens.

User avatar
Ben Boldt
Posts: 486
Joined: Tue Mar 22, 2016 8:27 pm
Location: Minnesota, USA

Re: RAMBO-1 Mapper Investigation

Post by Ben Boldt » Tue Dec 17, 2019 11:35 am

I am having some trouble getting it to work with simulating the diagram. Definitely the top input of the 4-bit counter's AND gate needs to be inverted in the diagram. The intention there was to prevent incrementing when the value is 15.

Edit:
Also, the comment where it says "4-bit counter rolls over to 0" is not correct, it was intended to stay at 15 there.


Edit 2:
I got it running but there are a lot of +2s that come out as +1s when following this diagram. In a sense, it is "better" than the real thing but that is not what we are after here. I think I will create a nice diagram showing states 0-17 and put that in the wiki. Even though that might not technically be the way they implemented it, it exactly emulates the behavior afaik and I think that is probably all that really matters.


Edit 3:
I am not going to be able to make that diagram with all 18 states, there are too many arrows to be readable. I need to step away from it for a while and keep trying later to get my newer diagram to work properly. I put what we have so far into the wiki. Hopefully we can clean that up soon.

NewRisingSun
Posts: 1123
Joined: Thu May 19, 2005 11:30 am

Re: RAMBO-1 Mapper Investigation

Post by NewRisingSun » Tue Dec 17, 2019 1:50 pm

Does this state diagram explain why writing to $C001 within the 16-M2-cycle time window since the last PA12=1 causes N+1 instead of N+2 behavior?

Post Reply