hide results

    Rank Calculation Guide by FerneuMKSC

    Version: 1.1 | Updated: 10/15/17 | Search Guide | Bookmark Guide

    .--------.
    | Index |
    `--------´
    
    Just search for one of these in order to jump to the desired section
    - PRAISES AND RANTS
    - CONTACT INFO
    - STATS
    - THE RANK FORMULA
    - MEMORY ADDRESSES
    - GAME CODE
    - THANKS
    
    .--------------------.
    | PRAISES AND RANTS |
    `--------------------´
    Hello there. If you, like me, have been a fan of Mario Kart ever since it first
    appeared on SNES you probably appreciate how good the GBA entry of the series
    is. It is like the developers of Mario Kart Super Circuit have taken everything
    that was good about the original (including its great tracks) and removed
    (almost) everything that was bad, making it not only of (if not THE) best games
    of the series, but also one of the best racing games ever. Could you imagine how
    awesome it would be if the technology back in the Game Boy Advance days allowed
    us to race against 7 people from around the world? That would be great, but it
    is something for us t want and Nintendo to decide. You are reading this guide
    for another reason, so let's carry on.
    
    Have you ever wondered why sometimes you thought you performed very bad and
    still got the 3 star rank, and sometimes you thought you made the best races of
    your life and ended up with 2 stars, or even worse? You are not alone. If there
    is one thing I have learned ever since I started seeking information about this
    matter is that there are lots of people out there searching for the same thing.
    
    One thing that really bothers me is that there are some web sites out there
    holding information that is completely wrong about how the rank is calculated.
    We all knew that your race time and coins seemed to have some influence on the
    ranks, but some bright fella decided to take the matter on his on hands and
    started pulling values from his a... who knows where and said things like: "in
    order to get the *** rank you need to get at least 150 coins and beat all the
    default time trial times for the races of that cup"
    
    The funny thing is that this type of person also goes on and claim that he has
    thoroughly tested it and it is perfectly accurate. Why, I ask, why post
    something like that? Obviously it was not because of money, because the
    information was posted on a public server. Perhaps it is some sort of disturb
    where the guy needs the satisfaction of helping people, even if that means
    providing them with the wrong information. Let's just hope this guy is not a
    teacher and really, really hope he is not the one walking on the side walk when
    you pull over to ask for directions...
    
    Fortunately there are people out there with a different attitude. People who
    will say "you know what? I do not know. But let's try to find out!". During my
    searches I have found a couple of communities with this type of people. And
    among those communities I saw the mariokart64.com forum. For those who do not
    know MarioKart64.com is a site where the best Mario Kart players of the world
    get together and compete among themselves. Do not let the web site name fool
    you though, it is not only about Mario Kart64, it is about all Mario Kart games
    out there. There is a section for each Mario Kart ever released. And a forum
    too. And it was on that forum that I have found the biggest attempt people had
    ever did at solving this rank calculation riddle. So, I decided to join them.
    
    The original version of this FAQ was created in 2013. It was almost complete.
    There was only one criterion the game used to calculate the player final rank
    that I was not able to figure out. This missing criterion was also the most
    valuable one but no matter what I did, I was never able to figure out what the
    player was supposed to do in order to get it. But now, 4 years later, the truth
    has been uncovered. All thanks to a guy named Airship804.
    
    First of all I would like to say sorry to Airship804. It has been almost 8
    months since he gave us the required information. At first I thought he had just
    recently posted it at the forums, but I was wrong. The forum showed the post
    date as "02/11/17" and thanks to that crazy date format Americans love use where
    they put the months before the days, what I thought was November the 2nd was, in
    fact, February 11. The United States may be a great place and Americans have
    certainly done a lot of things right, but the choice of a sane date format was
    not one of them. And let's not even start about their refusal to switch to the
    metric system...
    
    Granted, I am writing this on 2017-10-15 (October 15, 2017) which kind of make
    it impossible for Airship804 post to exist had the date be what I had originally
    interpreted, which is very stupid on my part. And stupid people should not be
    criticizing date format choices of others. But I digress...
    
    Anyway, Airship804 posted on the Super Circuit Forums that according to a guide
    released in 2001 in Japan, your number of skill points will increase if you get
    hit by the lightning bolt item. That is, getting hit by lightning bolts is a
    good thing. It is not something that happens very often, but when it does, it
    should be a good thing, at least according to the guide. So Airship804 suggested
    it might be the missing piece of our puzzle. And it made a lot of sense!
    
    You see, my test methodoly usually consisted of parking my kart near an item
    block, bump my head against walls, drive outside the track, dive into the water,
    throw myself into holes and things like that. As one can imagine, doing stuff
    like that meant that I was usually in the last place, being constantly lapped by
    the AI players. The methodoly worked fine and helped me to discover most of the
    used values, but nothing I ever did changed one specific "unknown value". If
    getting hit by lightning was the key to affect that value, the flaw was in the
    methodology itself. Of all items the AI use, lightning bolts must be one of the
    rarest ones. The AI barely uses lightning bolts when you are in first place so
    one can only imagine how rare, if not downright impossible, it is to get hit by
    it when you are last and have been lapped a few times.
    
    But now, thanks to Airship804, I knew what I was after. I had 3 choices:
    1. debug the code and discover what happens when you get struck by lightning.
    2. debug the code in order to figure out how to force the AI to use lightning.
    3. play the game normally and wait until someone uses the lightning bolt.
    
    Options 1 and 2 were kind of out of the question because it would take too much
    time to debug the game code (in ARM assembly!!!). So I went for #3 and...
    
    Remember when I told you that getting hit by lightning was rare? The truth is
    that it is way rarer than that! It took so long for the AI to use lightning
    against me that I was almost giving the idea up. Several times I wondered if
    things would not have been faster had I went for the other options.
    
    Anyway, after some hours playing around, it finally happened. I got hit by
    lightning and, yes! It does affect your skill points. Thank you very much
    Airship804!
    
    And special thanks to Etch, for being the first to test Airship804 hypotesis on
    real hardware and confirm it did affect your skill points. And also for using
    the information we uncovered to perform all kinds of crazy stuff. I truly
    recommend you guys to visit the forums and see what he (she? it???) has done.
    It is really impressive!
    
    .--------------.
    | CONTACT INFO |
    `--------------´
    The address of the Mario Kart Super Circuit forum I just mentioned is
    http://www.mariokart64.com/cgi-bin/yabb2/YaBB.pl?board=MKSC
    
    And the address of the topic where the biggest study mankind has ever conducted
    about how the heck does this game calculate you final rank is
    http://www.mariokart64.com/cgi-bin/yabb2/YaBB.pl?num=1053815139/0
    
    If you have any questions, discovered something new or even if you want me to
    write something using different words because it is wrong, confusing or both,
    just drop by that topic I just mentioned and post something there. That is way
    better than trying to reach me by e-mail because I seldom check my web mail, but
    I do drop on that topic from time to time.
    
    
    .-------.
    | STATS |
    `-------´
    Your final rank for a cup, as you might have guessed by now, is calculated
    according to your performance during the races. The game measures your
    performance by looking at some stats it records during each race. I will show
    some of those stats. There might be more, but only these ones are used for
    calculating your final rank.
    
    Coins:
        number of coins you got during the race.
    
    LightningHits
        number of times you were hit by the lighning bolt item. This value has
    	eluded me for some years and it was only with the help of the user
    	Airship804 on the Mario Kart Super Circuit forumns at MarioKart64.com that I
    	was able to	figure it out. Thank you Airship804, and thanks Etch for testing
    	it.
    
    LapTime1
        first lap time. The time is encoded like this: cents + seconds * 100. So
        let's suppose your lap was 0'12"34. The value stored here would then be
        1234 ((12 seconds * 100) + 34 cents).
    
    LapTime2
        second lap time. See LapTime1 for more info.
    
    LapTime3
        third lap time. See LapTime1 for more info.
    
    LapTime4
        fourth lap time. 0 if the race had only 3 laps. See LapTime1 for more info.
    
    LapTime5
        fifth lap time. 0 if the race had only 3 laps. See LapTime1 for more info.
    
    FramesNotHittingGas
        how many animation frames you spent not hitting the gas. Remember that this
        game runs at 60 frames per second!
    
    FramesHittingBrakes
        how many animation frames you spent hitting the brakes. Remember that this
        game runs at 60 frames per second!
    
    Item3RedSheelsUseCount
        how many times you used the 3 red shells item. Does not increment if you
        got the item but have not used it.
    
    ItemStarUseCount
        how many times you used the star item. Does not increment if you got the
        item but have not used it.
    
    ItemLightningUseCount
        how many times you used the lightning item. Does not increment if you got
        the item but have not used it.
    
    LakituRescueCount
        number of times Lakitu placed you back on the track.
    
    EntityHitCount
        increments every time you hit another driver or one of those creatures
        wandering on the track, like crabs, rats etc.
    
    WallHitCount
        increments every time you bump into a wall.
    
    GotHitAndSpunCount
        increments any time you hit something that makes you spin and lose coins.
        Might be an enemy shell or even a wandering crab. Does not increment if
        you managed to avoid spinning, like braking a little when you hit a banana
        or creature. Getting "hit" by ghosts does not increment this value.
    
    RemainingLifes
        never retried? So this has the value 3. Retried once? 2, and so on.
    
    StartMiniturboCount
        mini turbos at the start of the race or when dropped by Lakitu.
    
    DriftMiniturboCount
        mini turbos activated by drifting
    
    ItemBoxWhileFullHitCount
        increments each time you have an item on the item slot and touch another
        item box. You must have an item on the slot! Holding a banana or having 3
        shells circling you does not count as having an item on the slot,
        although there is no problem at all in doing so if you do manage to get
        another item on the slot.
    
    FramesOutsideTrack
        how many animation frames you spent outside the track. Remember that the
        game runs at 60 frames per second! This one needs a couple of important
        remarks and, as you will see, is probably the reason why getting the 3
        star rank on Extra Lightning is so hard:
            1. If the track does not have an "outside", like the Bowser Castle
            levels, this value increments each time you hit a wall.
            2. Some tracks, specially the SNES' ones, are glitched when the game
            calculates this value. I will write a few of them that were of interest
            for me while researching for this FAQ, but there might be more. Feel
            free to test:
                - RMC2: you can spend as much time as you want outside the track
                because the game will not count it. Beware of hitting the  walls
                though, since the game behaves as if this was a Bowser Castle
                track, and will count twice, once as a wall bump and once as if you
                have spent 1 frame outside the track
                - RKB1: touched the water? Then you are totally outside of the
                track. It does not matter if the puddle is right in the middle of
                the track. Hopping over it also does not help. At all! Although not
                really a glitch here, since this seems to be applied for all beach
                tracks.
                - RCI2: same rules applied on RMC2 are also applied here, but with
                a VERY IMPORTANT twist - the big mud pool in the middle of the track
                is counted as if you were out of the track!
    
    PositionPoints
        you receive a different value according to position you end a race and your
        difference in cup points from the second top computer controlled opponent.
        Here is a little table showing what you can get
    
        1st, 2nd etc: the position you finish the race
        Difference:   difference in cup points from the best placed CPU opponent
    
         -------------------------------------------------
        |PositionPoints           | 1st | 2nd | 3rd | 4th |
        |-------------------------|-----|-----|-----|-----|
        |Difference <= 2          |  20 |  10 |   0 |   0 |
        |-------------------------|-----|-----|-----|-----|
        |Difference >= 3 and <= 8 |  40 |  20 |  10 |   0 |
        |-------------------------|-----|-----|-----|-----|
        |Difference > 8           |  60 |  30 |  20 |  10 |
         -------------------------------------------------
    
    ccWeight
         each cc has a different value. Higher the cc, smaller the value
         150cc = 143
         100cc = 157
          50cc = 167
    
    TrackValue
        fixed values according to the track (at 150cc, I do not know if they change
        at any other cc). I did not waste my time getting the values for all tracks
        I only got the ones from the two cups I used as test bed. It is pretty easy
        to get those values though. I will teach how to retrieve them (and any
        other value presented here, of course) later, for anyone who is
        interested. Just take a peek at the GAME CODE section of this FAQ
        - Mushroom
            track 1: 47
            track 2: 53
            track 3: 65
            track 4: 50
        - Extra Lightning
            track 1: 52
            track 2: 40
            track 3: 26
            track 4: 27
    
    CharacterEndRaceValue
        each driver receives a different, but constant value at the end of the
        race. It seems to be connected to how hard it is to race using him/her. The
        harder the driver is to master, the greater the reward is. If this whole
        "the X guy is harder to master than the Y guy" somehow offends you, think
        of this values as a grip indicator. The higher the value, less grip the
        driver has. I have not compared the exact grip capacity of each driver, but
        in my experience, this listing seems to be accurate, having the ones with
        less grip being the ones who receive more points. These are the points each
        driver receives
            Mario  = 30
            Luigi  = 30
            Bowser = 45
            Peach  = 10
            DK     = 40
            Wario  = 40
            Toad   = 10
            Yoshi  =  0
    
    .------------------.
    | THE RANK FORMULA |
    `------------------´
    NOTICE: I will be using a C language notation for the SkillPoint calculation
    formulas below. Math people usually cringe when they see it, because stuff like
    x = x + 1
    is not only valid, but it is very, very common. Anyway, it is very simple to
    understand: what is on the left side of the = sign receives the result of the
    operation on the right side. That is it. Simple as that. So
    x = 1 + 2
    means that the value of x is now 3, because the result of the operation on
    the right side, 1 + 2, is 3. Also
    x = x + 1
    means that the value of x is now whatever value x had plus 1. This kind of
    operation is used a lot. In fact, it is used so much that the C language guys
    created a little "shortcut" for it, which consists in placing the operator
    just before the = sign, like this
    x += 2
    which means that x now have whatever value it had, plus 2, and is the same as
    x = x + 2
    If we change the operator, the operation changes (obviously), so
    x -= 2
    means that x now have whatever value it had, minus 2. All the conventional
    math rules apply so
    x += -3
    is the same as
    x = x + (-3)
    which is the same as
    x = x - 3
    And just to avoid any confusion, let me give you a little more complicated
    example. When you see things like
    x += y * 3
    it means that we will increment x with the result of the right hand side
    operation. So x will be incremented by the result of (y * 3). YOU DO NOT
    increment x by y and then multiply the result by 3. ALWAYS REMEMBER: the right
    hand side operation must be dealt with first.
    
    Below you will also see that I usually place a ; at the end of each statement,
    like this
    x = 4 + 56;
    Do not worry about it. Ignore the ; char. It has no meaning. It is a C thingy
    that tells the compiler where the end of the statement is. Line breaks have no
    meaning for a C compiler on many cases, so that char has to be used. But really,
    just ignore it. I am only mentioning it because I have just seen that I have
    used it below and I am too lazy to fix it. Sorry about that, it is just that I
    work with the C language all the time and it was kind of an automatic thing by
    now.
    
    And last, but not least, two slashes denotes a comment. Everything written from
    there until the end of the line is a comment. Comments have absolutely no
    influence in the code, but programmers usually place them near a certain lines
    in order to explain what exactly that code is doing. For instance
    
    // here I will increment x by 4
    x += 4;
    
    Well, that is it for your quick C language tutorial. I believe it is pretty
    easy to understand, and that is why it is the notation I will be using below.
    But have no fear of raising your hand and asking me a question, if you have not
    understood it yet. I will try to explain it again as best as I can. Beware
    though, if there is one thing I have learned, one thing that life has taught
    me, is that I am one lousy teacher. But I promise I will try my best. OK? Great!
    
    
    SkillPoints
        The stats mentioned above are tracked during a race and then, right when
        you cross the finish line, the game calculates what I am going to call
        SkillPoints. The higher your SkillPoints the better. Some stats increment
        those points, and some decrement them. I think it is pretty clear which is
        which, but what is not clear is by how much they increase or decrease those
        points. I mean, what WAS not clear, because here we go.
    
    // the skill points for the track always start at zero.
    SkillPoints = 0;
    
    // add the position points
    SkillPoints += PositionPoints;
    
    // yes coins ARE important :)
    // This operation means "multiply the number of coins you finished the race by
    // 4 and then increment SkillPoints with the result of that multiplication"
    SkillPoints += Coins * 4;
    
    // the number of times you got struck by the lightning item. It seems to be the
    // most valuable positive stat of all, but the AI seldom uses it. Which is kind
    // of a good thing. It would be very annoying if the AI used it all the time.
    // And now that we know all the other criteria for acquiring skill points, this
    // one should not matter much. Anyway, the great thing about this discovery is
    // that it will totally change the way players look at being hit by lightning.
    // The ignorant masses will curse saying stuff like
    // "great... that was just what I needed..."
    //
    // while the few and proud enlightened ones will yell
    // "Great! That was just what I needed!"
    SkillPoints += LightningHits * 40;
    
    // here the game used the ccWeight and the TrackValue to create some sort of a
    // PAR time for the track. If you beat this time you win some skill points.
    // Unfortunately  many times this PAR value is insanely low. Lower than some
    // records, so do not feel bad for not beating it. Here, in order to get your
    // total race time the game will sum all your lap times. If that sum is greater
    // than 59999 (9 minutes, 59 seconds and 99 cents), it is set to 59999. Also,
    // if the result of the whole calculation below is less than 0 it is set to 0.
    // That means that while your lap times MIGHT increase your skill points, they
    // WILL NEVER decrease them. If it was not for that, getting the 3 star rank on
    // Extra Lightning would be even harder
    RaceTime     = LapTime1 + LapTime2 + LapTime3 + LapTime4 + LapTime5;
    SkillPoints += ((ccWeight * TrackValue) - RaceTime) / 8;
    
    // you picked Bowser? Good for you!
    SkillPoints += CharacterEndRaceValue;
    
    // if you need to stop hitting the gas, be quick about it
    SkillPoints -= FramesNotHittngGas / 4;
    
    // unless you hit a banana, do not touch the brake pedal. It will hurt your hard
    // earned skill points bad. I am one of the worst MKSC players out there and
    // even I have no need for brakes
    SkillPoints -= FramesHittingBrake * 2;
    
    // fortunately you will only get these items when you are not in 1st. Well...
    // at least in most cases.
    SkillPoints -= Item3RedSheelsUseCount *  5;
    SkillPoints -= ItemStarUseCount       * 30
    SkillPoints -= ItemLightningUseCount  *  5;
    
    // Lakitu is NOT your friend
    SkillPoints -= LakituRescueCount * 30;
    
    // thou shalt hit no one! Nor anything!
    SkillPoints -= EntityHitCount * 15;
    
    // Bowser Castle levels can be harmful
    SkillPoints -= WallHitCount * 20;
    
    // So KartSeven, what did you say? That princess hitting me with 3 dozen red
    // shells per lap would not take my 3 star rank away? Was that it? hehe
    SillPoints -= GotHitAndSpunCount * 15;
    
    // retrying does not automatically take away your 3 star rank. Well... in
    // theory. In practice it hurts. Bad! (3 - RemainingLifes) is how the game
    // calculates your retry count. If you never retried, it will be 0 (you start
    // with 3 lives, remember?)
     SkillPoints -= (3 - RemainingLifes) * 120;
    
    // thou shalt master the start mini turbo. When Lakitu rescues you, doing a
    // mini turbo when he puts you back on the track ALMOST takes away the
    // SkillPoints you just lost
    SkillPoints += StartMiniturboCount * 25;
    
    // no surprise here
    SkilPoints += DriftMiniturboCount * 15;
    
    // well well well... Look at what we got here! I my opinion, this was one of the
    // biggest surprises when I debugged the game code. What we usually thought
    // before checking the game code was that if using items was bad thing, it was
    // because it would take points from you (which is pretty much what happens
    // when you use any of those items I mentioned above), but I doubt that anyone
    // ever thought that you would be gaining skill points for passing on a ? block
    // while already having an item on the item slot. And if you had ever thought
    // about that, then... KUDOS! You were right!
    SkillPoints += ItemBoxHitCountWhileFull * 15;
    
    // I just wish the game would differentiate between being outside the track and
    // being on water spots in the middle of the track on the beach races.
    SkillPoints -= FramesOutsideTrack / 4;
    
    // that is it. This is how the game calculates your skill points. It does it
    // once for each race of a cup and store the value. Then, at the end of the 4th
    // race, the game reads the SkillPoints that were calculated for each of track
    // and then take the arithmetic mean of them
    SkillLevel = (SkillPoints1 + SkillPoints2 + SkillPoints3 + SkillPoints4) / 4;
    
    // and now it compares the result to a couple of fixed values. If you made
    // enough points to stay above a certain fixed value, then that is your rank.
    // There is one last thing though. You can only get the 3 star rank if you got
    // first place on all 4 tracks.
    
    // if you got the first place on all 4 tracks...
    if SkillLevel > 329 then Rank = ***
    if SkillLevel > 199 then Rank =  **
    if SkillLevel >  99 then Rank =   *
    if SkillLevel >  29 then Rank =   A
    ...
    
    // if you did not get 1st place on all races, then the game checks if you made
    // at least 27 points
    if SkillLevel > 329 then Rank =  **
    if SkillLevel > 199 then Rank =   *
    if SkillLevel >  99 then Rank =   A
    ...
    
    // not even 27? Please tell me you made at least 21...
    if SkillLevel > 329 then Rank =  *
    ...
    
    .------------------.
    | MEMORY ADDRESSES |
    `------------------´
    It is obviously hard, if not practically impossible, to keep track of all those
    statistics by yourself. So here are the memory positions where the game stores
    them. These memory positions are in hexadecimal (base 16). I use the C language
    notation to represent them. In C, when you want to say that a certain value is
    in base 16 all you have to do is t place an 0x in front of the value.
    
    The easiest way to check these memory positions is by using an emulator. You
    will need one that allows you to see the game memory and one of the best for
    that task is the Visual Boy Advance. I used it to check these addresses and it
    handled the task perfectly. Currently the VBA emulator development is stopped,
    but truth be told, I am yet to find something I needed to do that it was not
    able to perform. Some guys seem to have taken the project in their own hands,
    creating the VBA-M branch. I have never tried it. I only used the original VBA.
    
    So, if you have chosen to use VBA to see these values, all you have to do is to
    load the game ROM, click on the "Tools" menu and then choose "Memory viewer..."
    You will probably want to click on the "Automatic update" check box, otherwise
    the values will not get updated as you play the game. Having the memory viewer
    up, all you need to do now is to type one of the addresses below on the text
    box near the "Go" button and then hit the Enter key or press the "Go" button in
    order to go to that memory address. On VBA you do not need to type the 0x of
    the memory address. It already knows you are inputting a base 16 value.
    
    I will use the term BYTE for values that are stored using 8 bits and WORD for
    values stored using 16 bits. For those of you who have no idea of what I am
    talking about, when you open the memory viewer of the emulator you will see
    that the values are stored in little pairs. Each pair is a BYTE and two pairs
    make a WORD.
    
    Another little thing: when the value is stored in a WORD, the least significant
    BYTE will appear first, so you will have to invert the pairs in order to see
    the correct value. I mean, the value 0xABCD will appear on the emulator memory
    viewer as: CD AB
    
    This happens because of something called endianness. Google it for more info.
    In the end, just remember to always invert the pairs and you are good to go.
    
    - Race #1 total time
    Address:  0x02033100
    Size:     WORD
    Comments: See the comments for 1st lap time (0x03003C74) for details on
              the time encoding
    
    
    - Race #1 position
    Address:  0x02033102
    Size:     BYTE
    Comments: The position you ended the race at. This value is zero based.
    
    
    - Race #1 coins
    Address:  0x02033103
    Size:     BYTE
    Comments: The number of coins you've finished the race with.
    
    
    - Race #2 total time
    Address:  0x02033104
    Size:     WORD
    Comments: See the comments for 1st lap time (0x03003C74) for details on
              the time encoding
    
    
    - Race #2 position
    Address:  0x02033106
    Comments: The position you ended the race at. This value is zero based.
    
    
    - Race #2 coins
    Address:  0x02033107
    Comments: The number of coins you've finished the race with.
    
    
    - Race #3 total time
    Address:  0x02033108
    Size:     WORD
    Comments: See the comments for 1st lap time (0x03003C74) for details on the
              time encoding
    
    
    - Race #3 position
    Address:  0x0203310A
    Size:     BYTE
    Comments: The position you ended the race at. This value is zero based.
    
    
    - Race #3 coins
    Address:  0x0203310B
    Size:     BYTE
    Comments: The number of coins you've finished the race with.
    
    
    - Race #4 total time
    Address:  0x0203310C
    Size:     WORD
    Comments: See the comments for 1st lap time (0x03003C74) for details on the
              time encoding
    
    
    - Race #4 position
    Address:  0x0203310E
    Size:     BYTE
    Comments: The position you ended the race at. This value is zero based.
    
    
    - Race #4 coins
    Address:  0x0203310F
    Size:     BYTE
    Comments: The number of coins you've finished the race with.
    
    
    - Global Track Index
    Address:  0x03000008
    Size:     BYTE
    Comments: Mushroom cup first track is 0, second 1, third 2 and fourth 3. Then,
              Flower cup starts from there. The count is reset for the extra cups,
              so both Mushroom and Extra Mushroom starts at 0, both Flowers start
              at 4 and so on. Summing up:
              Mushroom:  0,  1,  2,  3
              Flower:    4,  5,  6,  7
              Lightning: 8,  9, 10, 11
              Star:     12, 13, 14, 15
              Special:  16, 17, 18, 19
    
    
    - Lives Remaining
    Address:  0x0300000C
    Size:     BYTE
    Comments: Number of lives (retries) you still have
    
    
    - Race position
    Address:  0x030023B4
    Size      BYTE
    Comments: Your position on the current race. This is a zero based index (0
              means you are the first). This is not the only address your position
              is stored and do not bother changing it since the game will change it
              back to the correct value
    
    
    - cc ID
    Address:  0x03003620
    Size:     BYTE
    Comments:  50cc: 0x00
              100cc: 0x01
              150cc: 0x02
    
    
    - Race ID ????
    Address:  0x03003621
    Size:     BYTE
    Comments: It got the value 0x4 when I went to 150cc Mushroom. Changed to 0x5
              when I went to the second race, 0x9 when I went to the third and 0x7
              on the fourth race and to 0x1C on the podium screen. All races
              finished on 1st place.
              Flower
                0x0C // track 1
                0x11 // track 2
                0x12 // track 3
                0x0B // track 4
                0x1C // podium
    
    
    - Skill Points for track 1
    Address:  0x03003AD0
    Size:     WORD (signed)
    Comments: How well you have performed on the first track of a certain cup. This
              value is calculated and stored here right after you cross the finish
              line. The greater this value, the better your performance was.
    
    
    - Skill Points for track 2
    Address:  0x03003AD2
    Size:     WORD (signed)
    Comments: How well you have performed on the second track of a certain cup.
              This value is calculated and stored here right after you cross the
              finish line. The greater this value, the better your performance was.
    
    
    - Skill Points for track 3
    Address:  0x03003AD4
    Size:     WORD (signed)
    Comments: How well you have performed on the third track of a certain cup. This
              value is calculated and stored here right after you cross the finish
              line. The greater this value, the better your performance was.
    
    
    - Skill Points for track 4
    Address:  0x03003AD6
    Size:     WORD (signed)
    Comments: How well you have performed on the third track of a certain cup. This
              value is calculated and stored here right after you cross the finish
              line. The greater this value, the better your performance was.
    
    
    - Skill Points Average
    Address:  0x03003AD8
    Size:     WORD (signed)
    Comments: How well you have performed on the the whole cup. This value is
              calculated and stored here right after you cross the finish line of
              the fourth (last) race of the cup. It is simply the arithmetic mean
              of your skill points for each track, i.e.,
              (SkillPoints1 + SkillPoints2 + SkillPoints3 + SkillPoints4) / 4
              The greater this value, the better your performance was. And if it is
              greater than 0x13F and you got first place on all four races, you
              will receive the 3 star rank. Notice that the calculation happens
              right when you cross the finish line, so if you want to cheat, you
              must edit this (or any other of the SkillPoints) before crossing it.
    
    
    - Frames not hitting the gas
    Address:  0x3003ADC
    Size:     WORD
    Comments: Number of frames you spent without hitting the accelerator! If you
              overflow this WORD, the game sets this value to 0 and the BYTE at
              position 0x3003ADE to 1
    
    
    - Too many frames not hitting the gas
    Address:  0x3003ADE
    Size:     BYTE
    Comments: When the variable at 0x3003ADC overflows (you did not hit the gas
              stopped for more than 65535 frames), this byte is flagged.
    
    
    - Brake usage
    Address:  0x03003AE0
    Size:     WORD
    Comments: Number of frames you spent hitting the brakes
    
    
    - Too much brake use
    Address:  0x03003AE2
    Size:     BYTE
    Comments: When I tried to overflow the variable holding the brake usage
              (0x03003AE0), it got zeroed and this byte was set to 1.
    
    
    - Number of times you used the 3 red shells item
    Address:  0x03003AE4
    Size:     Byte
    Comments: Increment each time you used the 3 red shells item
    
    
    - Number of times you used a star item
    Address:  0x03003AE5
    Size:     Byte
    Comments: Increment whenever you use the star item
    
    
    - Number of times you used the lightning item
    Address: 0x03003AE6
    Size: Byte
    Comments: Incremented when I used the lightning
    
    
    - Number of times rescued by Lakitu
    Address:  0x03003AE7
    Size:     BYTE
    Comments: Starts counting from zero after overflowing.
    
    
    - Number of times you hit a driver or creature
    Address:  0x3003AE8
    Size:     BYTE
    Comments: Number of times you hit someone or something besides a wall, like
              other drives or one of those creatures walking on the track
    
    
    - Wall bump count
    Address:  0x03003AE9
    Size:     BYTE
    Comments: This is just incremented when you hit a wall. It does not change when
              you hit another player neither a tree nor a stomp. The "good" thing
              is that it is not protected against overflow, i.e. hit your head for
              the 256th time and you're as good as new :)
    
    
    - GotHitAndSpun
    Address:  0x03003AEA
    Size:     BYTE
    Comments: Increment every you get hit by something that makes you spin and lose
              coins, like an enemy shell or even a creature on the track. If you
              brake so you do not spin, it does not count
    
    
    - Start Mini Turbo Count
    Address:  0x03003AEB
    Size:     BYTE
    Comments: Increment every time you execute a mini turbo start. It can be either
              the one at the start of the race or the ones you do after Lakitu
              rescues you. Zeroed when overflowed.
    
    
    - Drift Mini Turbo count
    Address:  0x03003AEC
    Size:     BYTE
    Comments: Increment every time you execute a mini turbo while drifting. Zeroed
              when overflows.
    
    
    - Frames outside the track
    Address:  0x03003AF0
    Size:     WORD
    Comments: Frames spent outside the track, like on the grass. Falling on the
              water, lava or in a bottomless haunted pit does not seem to affect
              this. Neither does the frames Lakitu spend rescuing you. See the
              comments on the Stats session for more details about this value,
              since it is kind of glitched.
    
    
    - Too many frames outside the track
    Address:  0x3003AF2
    Size:     BYTE
    Comments: When I tried to overflow the above address (Frames spent outside the
              track, it "zeroed", set this byte to 1 and did not increment any
              longer. So, basically if you spent more than 0xFFFF frames outside
              the track, this byte probably tells the game that the current player
              sucks too much and it should not waste its time counting the frames
              he spent outside the track
    
    
    - Item Box Hit Count While Full
    Address:  0x03003AF4
    Size:     BYTE
    Comments: Increments every time you hit an item box while you are already with
              an item on the slot. Hitting it while having a "triggered item"
              (banana or shell being held behind your kart) does not count
    
    
    SkillPoints+    PositionPoints
    Address:  0x3003AF6 + 0x20 * (cupTrackIndex - 1)
    Size:     Byte
    Comments: Fixed value according to the position you end the race. The
              ( + 0x20 * (cupTrackIndex - 1)) part in the address field means that
              you must offset that address by 0x20 in order to get the values for
              the second track, then by more 0x20 for the third and 0x20 again for
              the fourth. So:
              Track 1: 0x3003AF6 + 0x20 * 0 == 0x3003AF6
              Track 2: 0x3003AF6 + 0x20 * 1 == 0x3003B16
              Track 3: 0x3003AF6 + 0x20 * 2 == 0x3003B36
              Track 4: 0x3003AF6 + 0x20 * 3 == 0x3003B56
    
    
    SkillPoints+    Coins * 4
    Address:  0x03003AF8 + 0x20 * (cupTrackIndex - 1)
    Size:     WORD
    Comments: The number of coins you got during the race, times 4
    
    
    SkillPoints+    LightningHits * 40
    Address:  0x03003AFA + 0x20 * (cupTrackIndex - 1)
    Size:     WORD
    Comments: Number of times hit by the lightning item. It is the most valuable
              positive statistic. The game grabs it from 0x03003ADA, multiplies it
    		  by 40 and add it to your SkillPoints. Because the AI seldom uses
    		  lightning bolts, this value that was multiplied by 40 remained unknown
    		  for quite a few years. In fact, if it wasn't for Airship804 of the
    		  Mario Kart Super Circuit forum (at MarioKart64.com), I would never
    		  have figured this out. Airship804 mentioned that according to a guide
    		  released in 2001 in Japan, your skill points are increased if you get
    		  hit by lightning.	Thank you very much Airship804! 4 years after the
              initial release of this FAQ we have finally uncovered all the
    		  criteria the game uses to judge your performance.
    
    
    SkillPoints+    Good Race Time
    Address:  0x03003AFC + 0x20 * (cupTrackIndex - 1)
    Size:     WORD
    Comments: the games does the following calculation
              TotalRaceTime = LapTime1 + LapTime2 + LapTime3 + LapTime4 + LapTime5;
              x             = ((ccWeight * TrackValue) - TotalRaceTime) / 8;
              The x value is then added to your skill points. It x less than 0, it
              is set to 0
    
    
    SkillPoints+    Character End Race Value
    Address:  0x03003AFE + 0x20 * (cupTrackIndex - 1)
    Size:     BYTE
    Comments: constant value you receive at the end of each race for using a
              certain driver. Bowser is the one who gives you the most (0x2D),
              Yoshi the least (0)
    
    
    SkillPoints-    FramesNotHittingGas / 4
    Address:  0x03003B00 + 0x20 * (cupTrackIndex - 1)
    Size:     WORD
    Comments: the number of frames you did not hold the accelerator button,
              divided by 4
    
    
    SkillPoints-    FramesHittingBrakes * 2
    Address:  0x03003B02 + 0x20 * (cupTrackIndex - 1)
    Size:     WORD
    Comments: number of frames you were holding the brake button, times 2
    
    
    SkillPoints-    Bad item usage
    Address:  0x03003B04 + 0x20 * (cupTrackIndex - 1)
    Size:     WORD
    Comments: Item3RedSheelsUseCount * 5 +
              ItemStarUseCount * 15 +
              ItemLightningUseCount * 5
    
    
    SkillPoints-    Bad driving
    Address:  0x03003B06 + 0x20 * (cupTrackIndex - 1)
    Size:     WORD
    Comments: LakituRescueCount  * 30 +
              EntityHitCount     * 15 +
              WallHitCount       * 20 +
              GotHitAndSpunCount * 15
    
    
    SkillPoints-    RetryCount * 120
    Address:  0x03003B08 + 0x20 * (cupTrackIndex - 1)
    Size:     WORD
    Comments: (3 - LifesRemaining) * 120
    
    
    SkillPoints+    Good Driving
    Address:  0x03003B0A + 0x20 * (cupTrackIndex - 1)
    Size:     WORD
    Comments: StartMiniturboCount      * 25 +
              DriftMiniturboCount      * 15 +
              ItemBoxHitCountWhileFull * 15
    
    
    SkillPoints-    FramesOutsideTrack / 4
    Address:  0x03003B0C + 0x20 * (cupTrackIndex - 1)
    Size:     WORD
    Comments: Number of frames outside the track (or on certain areas, due to what
              I think to be glitches - see the comments for the FramesOutsideTrack
              value on the stats section) divided by 4
    
    
    SkillPoints For The Track
    Address:  0x03003B0E + 0x20 * (cupTrackIndex - 1)
    Size:     WORD
    Comments: Your resulting skill points for the track.
    
    
    - Character ID
    Address:  0x3003BE4
    Size:     Byte
    Comments: 0x0 == Mario
              0x1 == Luigi
              0x2 == Bowser
              0x3 == Peach
              0x4 == DK
              0x5 == Wario
              0x6 == Toad
              0x7 == Yoshi
    
    
    - Points
    Address:  0x03003C5C
    Size:     BYTE
    Comments: Your total number of points. Jump 0x1A0 for the other racers'
    
    
    - 1st lap time
    Address:  0x03003C74
    Size:     WORD
    Comments: Current race's 1st lap time. The time is coded like this:
              cents + seconds * 100. So if you lap was 0'12"34, the value
              on this address will be 1234 (34 cents + (12 seconds * 100)),
              which will be this hexadecimal WORD 0x04D2 (0xD2 - 0x04 on
              default endianness)
    
    
    - 2nd lap time
    Address:  0x03003C76
    Size:     WORD
    Comments: See the comments for 1st lap time (0x03003C74) for details on the
              time encoding
    
    
    - 3rd lap time:
    Address:  0x03003C78
    Size:     WORD
    Comments: See the comments for 1st lap time (0x03003C74) for details on the
              time encoding
    
    
    - Current race coin count
    Address:  0x03003D10
    Size:     BYTE
    Comments: The number of coins you have on the current race
    
    
    - Current item
    Address:  0x03003D12
    Size:     BYTE
    Comments: the byte at 0x03003D13 must be set to 0x10 otherwise changing these
              values will not give you the desired item. Also, if changed during a
    		  race, you will get the item, but the item box at the top of the screen
    		  will be empty. Here are the values you can use in order to get all
    		  known items:
    			0x01: randomizing. The game sets the value to this when you touch an
    			      item box and it will remain 0x01 until the actual item is
    				  chosen
    			0x02: 1 red shell
    			0x03: 3 red shells
    			0x04: blue shell
    			0x05: banana
    			0x06: ?
    			0x07: mushroom
    			0x08: 3 mushrooms. Value changes to 0x0F when you use the first,
    			      and then to 0x07 when you use the second.
    			0x09: golden mushroom. Value changes to 0x0E while active. Lasts 10
    			      seconds
    			0x0A: star
    			0x0B: ghost
    			0x0C: lightning bolt
    
    - You have an item on the item slot
    Address:  03003D13
    Comments: BYTE
    Comments: it seems to be 0 when you got no item and 0x10 when you got one
    
    - Remaining "shots"
    Address:  03003D14
    Size:     BYTE
    Comments: Number of remaining shots you have for the selected item. I.e., it
              will be 3 if you got 3 shells surrounding you, 2 if you got 2 shells
    		  and so on
    
    
    .-----------.
    | GAME CODE |
    `-----------´
    Here you will see how I knew how your SkillPoints were calculated. This is
    pretty low level stuff and basically it was a pre-translation of the game code
    from ARM assembly to a C like language so I could understand it better. THERE
    IS NO GAME CODE HERE (I think that would be illegal), but I have written the
    exact positions where the game code that handles your rank calculation is. So if
    you have a debugger, all you have to do is to set a code break point at the
    instruction at 0x0804314C and follow from there.
    
    I do not know if this pseudo code will be of help for anyone out there, but it
    did help me to understand some stuff so I decided to leave it here. It is also
    great you want to verify my SkillPoints calculation algorithm, since I have
    written the addresses of important code areas. These code addresses are the
    first value you will see above the comments on each section below.
    
    One cool thing I show here is that the game not only calculates your skill
    points, but it also stores the results of some preliminary calculations it has
    done. So even if you have no access to a debugger, you can still load an
    emulator like VBA and check a couple of interesting memory areas in order to
    see if I got everything right. For instance:
    - one of the first things the game will use during the skill points calculation
    is the PositionPoints. This value is added to the skill points and stored at
    0x3003AF6, so if you go to that memory address you will see the value the game
    has used
    
    - the second thing added to your skill points is the number of coins you got
    during the race time 4. At 0x03003AF8 the game stores that value (coins * 4)
    
    - 0x3003AFC is where the game will store the result of that whole calculation
    it does with your race time
    
    So as you will see, each "section" I present below holds a little part of the
    skill points calculation. All of them ends with R6 being updated and then with
    some value being stored at the memory position pointed by R7. R6 is the guy
    storing your skill points and R7 is pointing to those cool memory positions I
    told you above where the game stores the results of the calculations done with
    your stats before updating your skill points with them.
    
    // I will mention this below. Nothing special here though that I have not
    // pointed out in the memory areas section
    struct RaceTimes 0x03003C74
    {
        Word RaceLap1;   // 0x03003C74 == [mem]
        Word RaceLap2;   // 0x03003C76 == [mem + 0x2]
        Word RaceLap3;   // 0x03003C78 == [mem + 0x4]
        Word RaceLap4;   // 0x03003C7A == [mem + 0x6]
        Word RaceLap5;   // 0x03003C7C == [mem + 0x8]
        Byte Unknown[2]; // 0x03003C7E -> 0x03003C7F
        Word RaceTime;   // 0x03003C80 == [mem + 0xC]
    };
    
    
    // 0x0804314C
    // where the game gets the PositionPoints (see constants above). Here R0 will
    // get the track index (zero based) and R1 holds the race ending position
    // (zero based). This is called right after you cross the finish line.
    // The PositionPoints value is stored at R2 and then we jump to 08043176
    
    // 0x08043176
    // r5 = 0x03003AD0 all races
    // r7 = 0x03003AF6, 0x03003B16, 0x03003B36, 0x03003B56 (that is right, the
    //      position is offset by 0x20 per track)
    // r6 = accumulator for your skill points. Good things are added, bad are
    //      removed
    r2   = PositionPoints;
    r6  += r2;              // r6 is 0 before this. So r6 == PositionPoints
    r7   = 0x03003AF6;      // 0x03003AF6 for track1, 0x03003B16 for track2,
                            // 0x03003B36 for track3 and 0x03003B56 for track4
    [r7] = r2               // 0x03003AF6 = PositionPoints
    
    r0  = Coins;    // [0x03003D10]
    r2  = r0 << 2;  // r0 * 4
    r6 += r2;
    [r7 + 2] = r2;  // [0x03003AF8] = (Word)(coins * 4)
    
    r1 = [0x03003ADA]; // number of times you were hit by the lightning item
    r0 =  r1 << 2;     // r0 = r1 * 4
    r0 += r1;          // r0 += r1
    r2 = r0 << 3;      // r2 =  r0 * 8;
    r6 += r2;
    [r7 + 0x4] = r2;   // 0x03003AFA = ((LightningHits << 2) + LightningHits) << 3
    
    // At 0x8043196 a BL made us jump to 0x0803DAC4
    
    // 0x0803DAC4: AddAllLapTimes()
    // r0 exits here with the sum of all 5 laps (the last two are 0 if the race had
    // only 3 laps). Only the lower 16bits are taken, anything above is discarded
    // (i.e., a cast to Word)
    r3 = 0;
    r2 = 4;
    r1 = struct RaceTimes // [0x03003C74]
    int i = 0;
    do
    {
        r0 = RaceTimes.Lap[i] // [0x03003C74 + 2 * i] (WORD)
        r3 += r0;
        ++i;
        r2 -= 1;
    }while(r2 >= 0)
    
    r0 = 0xEA5F;    // if the sum of all laps is greater than 59999
    if(r3 > r0)     // set the sum to
        r3 = r0;    // 59999
    r0 = r3 << 16   // move the value to the upper 16 bits
    r0 = r0 >> 16   // move it back (Probably just a cast to smaller data type)
    goto 0x0804319B // BX r14 (0x0804319A)
    
    // 0x0804319A
    r0 = r8;         // r0 = 0x03003B98
    call 0x0803DAC4; // BL 0x0803DAC4
    
    // 0x0803DAC4 AddAllLapTimes()
    // as seen above,  AddAllLapTimes() to R0. Again? Probably just a
    // harmless mistake by the programmers
    r0 = AddAllLapTimes()
    goto 0x080431A0
    
    // 0x080431A0
    r2 = (Word)r0; // r2 == sum of all lap times (cast to Word)
    r1 = 0x080ECD30;
    r0 = ccID;     // [0x03003620] the current cc. Can be 0, 1 or 2 (50, 100, 150)
    r0 = r0 << 2;  // r0 *= 4;
    r0 += r1;
    ro = [r0];     // [080ECD38] == 0x8F for 150cc, 0x9D for 100cc and 0xA7 for
                   // 50cc
    r1 = r10;      // TrackValue (see more info on the "stats" section)
    r1 = r1 * r0;
    r0 = r1
    r0 -= r2       // r2 had the sum of all lap times
    if(r0 < 0)
        r0 += 0x7  // cmp r0,0x0; bge 0x80431C0; add r0,0x7; instruction 0x80431C0
    r2 = r0 >> 3;  // r2 = r0 / 8 (arithmetic shift)
    if(r2 < 0)
        r2 = 0;
    r6 += r2;
    [r7 + 0x6] = r2;  // [0x03003AF6 + 0x6] = r2 -> [0x03003AFC] = r2
    
    r2 = 0x080ECD3C;
    r1 = CharacterID; // [0x03003B98 + 0x4C] == [0x03003BE4] == Character ID
    r0 = 0x7;
    r0 &= r1;         // clearing any garbage from the character ID value?
                      // It is never greater than 7, so this is simply r0 = r1
                      // Well... how knows...
    r0 <<= 0x2        // r0 = r0 * 4
    r0 += r2;         // r0 = 0x080ECD3C + CharacterID * 4 == CharacterEndRaceValue
    r2 = [r0];        // r2 = CharacterEndRaceValue (0x2D for bowser)
    r6 += r2;
    [r7 + 0x8] = (Word)r2;  // [0x03003AF6 + 0x8] = (Word)CharacterEndRaceValue
                            // [0x03003AFE] = CharacterEndRaceValue
    
    r0 = [r5 + 0xC];                 // r0 = [0x3003AD0 + 0xC]
                                     // r0 = [0x3003ADC] == FramesNotHittingGas
    r2 = FramesNotHittingGas >> 0x2; // r2 = FramesNotHittingGas / 4;
    r6 -= r2;
    [r7 + 0xA] = (Word store)r2; // [0x03003AF6 + 0xA] = r2;
                                 // [0x03003B00] = FramesNotHittingGas / 4
    
    r0 = FramesHittingBrake; // [0x03003AD0 + 0x10]
                             // [0x03003AE0] == FramesHittngBrake
    r2 = r0 << 0x1;          // r2 = FramesHittingBrake * 2
    r6 -= r2;
    [r7 + 0xC] = (Word store)r2; // [0x03003AF6 + 0xC] = FramesHittingBrake * 2
                                 // [0x03003B02] = FramesHittingBrake * 2;
    
    r1 = UseCountItem3RedShells; // [0x03003AD0 + 0x14] == [0x03003AE4]
    r0 = r1 << 0x2;
    r2 = r0 + r1                 // r2 = (UseCountItem3RedShells * 5
    r1 = UseCountItemStar;       // [0x03003AD0 + 0x15] == [0x03003AE5]
    r0 = r1 << 0x4;              // r0 = UseCountItemStar * 16
    r0 -=  UseCountItemStar      // r0 = r0 - UseCountItemStar;
    r0 = r0 << 0x1               // r0 = r0 * 2
                                 // so, r0 = UseCountItemStar * 30
    r2 += r0;                    // r2 = CalcWith_UseCountItem3RedShells +
                                 //      CalcWith_UseCountItemStar
    r1 = UseCountItemLightning;  // [0x03003AD0 + 0x16] == [0x03003AE6]
    r0 = r1 << 0x2;              // r0 = UseCountItemLightning * 4
    r0 += r1;                    // r0 = r0 + UseCountItemLightning;
                                 // so, r0 = UseCountItemLightning * 5
    r2 += r0;                    // r2 = CalcWith_UseCountItem3RedShells +
                                 //      CalcWith_UseCountItemStar +
                                 //      CalcWith_UseCountItemLightning
    r6 -= r2;
    [r7 + 0xE] = (Word store)r2; // [0x03003AF6 + 0xE] = r2;
                                 // [0x03003B04] = (Word store)r2;
    
    r1 = LakituRescueCount;      // [0x03003AD0 + 0x17] == [0x03003AE7]
    r0 = r1 << 0x4
    r0 -= LakituRescueCount;
    r2 = r0 << 0x1;              // r2 = LakituRescueCount * 30
    r1 = EntityHitCount;         // [0x03003AD0 + 0x18] == [0x03003AE8]
    r0 = r1 << 0x4;
    r0 -= EntityHitCount;        // r0 = EntityHitCount * 15
    r2 += r0                     // r2 = CalcWith_LakituRescueCount +
                                 //      CalcWith_EntityHitCount
    r1 = WallHitCount;           // [0x03003AD0 + 0x19] == [0x03003AE9]
    r0 = r1 << 0x2;
    r0 += WallHitCount;
    r0 = r0 << 0x2;              // r0 = WallHitCount * 20
    r2 += r0;                    // r2 = CalcWith_LakituRescueCount +
                                 //      CalcWith_EntityHitCount +
                                 //       alcWith_WallHitCount
    r1 = GotHitAndSpunCount;     // [0x03003AD0 + 0x1A] == [0x03003AEA]
    r0 = r1 << 0x4;
    r0 -= GotHitAndSpunCount;    // r0 = GotHitAndSpunCount * 15
    r2 += r0;                    // r2 = CalcWith_LakituRescueCount +
                                 //      CalcWith_EntityHitCount +
                                 //      CalcWith_WallHitCount +
                                 //      CalcWith_GotHitAndSpunCount
    r6 -= r2;
    [r7 + 0x10] = (Word store)r2; // [0x03003AF6 + 0x10] = r2
                                  // [0x03003B06] = (Word store)r2
    goto 0x08002C3C;              // 0x08043234: bl 0x8002C3C
    
    // 0x08002C3C
    r0 = LifesRemaining; // [0x0300000C]
    bx r14
    
    // 0x08043238
    r1 = 0x3;
    r2 = r1 - r0; // r2 = 0x3 - LifesRemaining, so r2 == RetryCount
    if(r2 > 0)
    {
        // 0x08043240
        // in case you retried on the race
        r0 = r2 << 0x4; // r0 = RetryCount * 16
        r0 -= r2;       // r0 = (RetryCount * 16) - RetryCount
        r0 = r0 << 0x3; // r0 = ((RetryCount * 16) - RetryCount) * 8;
    }
    else
    {
        // 0x08043254
        r0 = 0;
    }
    // 0x08043256
    r2 = r0;        // r2 = CalcWith_Retry
    r6 -= r2;
    [r7 + 12] = r2; // [0x03003AF6 + 0x12] = r2; -> [0x03003B08] = r2;
    
    r1 = StartMiniturboCount;      // [0x03003AD0 + 0x1B] == [0x03003AEB]
    r0 = r1 << 0x1;
    r0 += StartMiniturboCount;
    r0 = r0 << 0x3;
    r2 = r0 + r1;                  // r2 = StartMiniturboCount * 25;
    r1 = DriftMiniturboCount;      // [0x03003AD0 + 0x1C] == [0x03003AEC]
    r0 = r1 << 0x4;
    r0 -= r1;                      // r0 = DriftMiniturboCount * 15
    r2 += r0;                      // r2 = CalcWith_StartMiniturboCount +
                                   //      CalcWith_DriftMiniturboCount
    r1 = ItemBoxHitCountWhileFull; // [0x03003AD0 + 0x24] == [0x03003AF4]
    r0 = r1 << 0x4;
    r0 -= r1;                      // r0 = ItemBoxHitCountWhileFull * 15
    r2 += r0;                      // r2 = CalcWith_StartMiniturboCount +
                                   //      CalcWith_DriftMiniturboCount +
                                   //      CalcWith_ItemBoxHitCountWhileFull;
    r6 += r2;
    [r7 + 0x14] = r2;              // [0x03003AF6 + 0x14] = r2;
                                   // [0x03003B0A] = r2;
    
    r0 = c;            // [0x03003AD0 + 0x20] == [0x03003AF0] == FramesOutsideTrack
    r2 = r0 >> 0x2;    // r2 = FramesOutsideTrack / 4
    r6 -= r2;
    [r7 + 0x16] = r2;  // [0x03003AF6 + 0x16] = r2; -> [0x03003B0C] = r2
    CALL 0x08002C24    // 08043286: bl 0x8002C24
    
    // 0x08002C24
    r0 = GlobalTrackIndex; // [0x03000008] see the constant GlobaTrackIndex above
    END CALL               // go back to 0x0804328A
    
    // 0x0804328A
    r4 = 0x3;
    r0 &= r4;
    r0 = r0 << 0x1;               // r0 = r0 * 2;
    r0 = r5 + r0;                 // [0x3003AD0 + r0]
    [r0] = r6;                    // r6 seems to be your skill points for this race
    [r7 + 0x18] = (Word store)r6; // [0x03003AF6 + 0x18] = r6
                                  // [0x03003B0E] = (Word store)r6
    CALL 0x08002C24;              // 0x08043296: bl 0x08002C24
    
    // 0x08002C24
    r0 = GlobalTrackIndex; // [0x03000008] see the constant GlobaTrackIndex above
    END CALL               // go back to 0x0804329A
    
    // 0x0804329A
    r0 &= r4;                      // r0 = GlobalTrackIndex & 0x3
    if(r0 != 0x3) goto 0x080432C6; // so it seems that 0x080432A0 is the code path
                                   // taken at the end of the cup
    
    // 0x080432A0
    // path take when finishing the last track of a cup
    r2 = 0;
    r0 = (signed word)SkillTrack1; // [0x03003AD0 + r2] == [0x03003AD0]
    r3 = 0x2;
    r1 = (signed word)SkillTrack2; // [0x03003AD0 + r3] == [0x03003AD2]
    r0 += r1;                      // r0 = SkillTrack1 + SkillTrack2;
    r2 = 0x4;
    r1 = (signed word)SkillTrack3; // [0x03003AD0 + r2] == [0x03003AD4]
    r0 += r1;                      // r0 = SkillTrack1 + SkillTrack2 + SkillTrack3;
    r3 = 0x6;
    r1 = (signed word)SkillTrack4; // [0x03003AD0 + r3] == [0x03003AD6]
    r0 += r1;                      // r0 = SkillAllTracks
    if(r0 < 0)
        r0 += 0x3;
    r2 = r0 >> 0x2;               // r2 = SkillAllTracks / 4
    [r5+0x8] = (word store)r2;    // [0x03003AD8] = (SkillAllTracks / 4);
    r0 = r5;
    r0 += 0xBE;
    [r0] = (word store)r2;        // [0x03003B8E] = (SkillAllTracks / 4);
    
    // 0x0804355C
    // 1. get your total number of points and see if it is greater than 35
    // 2. compare your skill points (SkillAllTracks/ 4) with
        if total > 0x13F then ***
        if total >  0xC7 then  **
        if total >  0x63 then   *
        if total >  0x1D then   A
    
    // 1. if you made less than 36, check if you made more than 27
    // 2. compare your skill points (SkillAllTracks/ 4) with
        if total > 0x13F then  **
        if total >  0xC7 then   *
        if total >  0x63 then   A
        ...
    
    // 1. if you made less than 36, check if you made more than 21
    // 2. compare your skill points (SkillAllTracks/ 4) with
        if total > 0x13F then   *
        if total >  0xC7 then   A
        ...
    
    
    .---------.
    | THANKS  |
    `---------´
    None of this would be possible without the help of
    - Forgotten and the VBA Team. Thank you guys so much for the Visual Boy Advance
    - NOCASH for the NO$GBA emulator/debugger
    - The Mario Kart elite at MarioKart64.com
    - Airship804 for the hint about the infamous "unknown value"
    - Etch for testing everything on real hardware and doing the craziest things

    View in: