On this page
  1. Related
  2. Games
  3. References
  4. Sources

Item distribution decides what an item box gives. Mario Kart 64 rolls a slot in a 100-slot row for the racer’s place in Grand Prix and Versus, and one row for everyone in Battle1. Mario Kart: Double Dash!! also reads a row for the place, as weights over nine common items and the driver’s own special, and the partner’s held item rules some of them out2. In Diddy Kong Racing no roll picks a balloon’s type: the track fixes it3.

  • PlacedDiddy Kong Racing (1997). Each balloon's color is fixed on the track, and taking the same color again raises the weapon up to a third level.3
  • FlatMario Kart 64 (1996). Battle reads one 100-slot row whatever the place.1
  • By placeMario Kart 64 (1996). Grand Prix and Versus read a 100-slot row for the driver's place, with separate tables for human and CPU drivers in Grand Prix.1Mario Kart: Double Dash!! (2003). Grand Prix and Versus weigh nine common items and the driver's own special by a row for the place, read from a disc file, with the partner's item ruling some out.2,4

Games

GameYearHowNote
Diddy Kong Racing1997Placedeach balloon's color is fixed on the track, and taking the same color again raises the weapon up to a third level
Mario Kart 641996FlatBattle reads one 100-slot row whatever the place
Mario Kart 641996By placeGrand Prix and Versus read a 100-slot row for the driver's place, with separate tables for human and CPU drivers in Grand Prix
Mario Kart: Double Dash!!2003By placeGrand Prix and Versus weigh nine common items and the driver's own special by a row for the place, read from a disc file, with the partner's item ruling some out
Every claim about this mechanic, by game (4)
Mario Kart 64 1996In the US version of Mario Kart 64, gen_random_item picks an item as one byte from a 100-byte row of a table, the row for the driver's current place. In Grand Prix, human players read common_grand_prix_human_item_curve and CPU drivers common_grand_prix_cpu_item_curve, and that branch reads no player count. Versus picks one of three tables by the number of players (two, three, or four), and Battle reads one row whatever the place. The slot is a random number from 0 to 100 (random_int(100)) plus the previous slot, a counter that held A, B, and R buttons advance, and the race frame counter, taken mod 100.Code
Diddy Kong Racing 1997In the US 1.0 version of Diddy Kong Racing, a weapon balloon's type is set by its entry in the track's object list, with no roll: the code names five types, boost, missile, trap, shield, and magnet, which the decompilers' names for the all-balloons cheats pair with blue, red, green, yellow, and rainbow. A racer that touches a balloon takes its type. If the racer already held the same type with any left, the weapon's level rises by one, up to the third (level 2); otherwise it starts at the first. In a challenge the level stops at the second, and trap balloons start there; the Maximum Power-up cheat makes every pickup third-level, and CPU-driven boss vehicles collect none. The weapon and its quantity come from a table the game loads as an asset, two bytes for each type and level, so they aren't in the repo. A CPU racer's driving routine func_80042D20 can also raise a first-level pickup by one, on a percent chance from the AI behavior table. Mario Kart 64 instead picks an item box's item in Grand Prix from a 100-slot row for the driver's place.Code
Mario Kart: Double Dash!! 2003In the doldecomp decompilation of Mario Kart: Double Dash!!, which builds a USA debug version (MarioClub_us) and whose item manager, Sato/ItemObjMgr.cpp, does not yet match the game's code, the item pick reads byte weights from a file on the disc, /Item/ItemSlotList.dat (or ItemSlotList1.dat or ItemSlotList2.dat, by the race's item-slot type). The file holds lists, each with a row of weights for every place, and a Grand Prix or Versus pick reads the row for the kart's place less one. Outside LAN play, Grand Prix reads a list by engine class (150cc and Mirror share one) for human players and the next list for CPU drivers, and Versus reads one list for every driver by the number of karts, two to four. The pick adds the row's weights for nine common kinds and for the driver's own special item, draws a whole number below the total (computed), and walks the running sum. The special's weight is multiplied by 1.5 when the two riders are a default pairing (isDefaultCharCombi), and the special is left out when the partner holds or stocks a special item, or when it is ItemHeart and the kart already has one; four common kinds (ItemThunder, ItemStar, ItemKinokoSuc, and ItemFlyTurtle, which the atlas reads as the Spiny Shell) are left out when the partner holds or stocks the same kind. startShuffle clears the flag the code calls _7, and startItemShuffleSingle sets it when its doShuffle argument is true; with it set, the pick first draws among the specials alone. setDynamicRate, which copies the weights the pick reads, writes 0 for any kind whose IsAbleToCreateItem is false (a function the decompilers comment as fabricated), and in Grand Prix multiplies the CPU list's ItemFlyTurtle weight by 1.5 while RivalBodyCtrl::isPlayerFirst() is true. In Grand Prix, Mario Kart 64 instead reads one byte from a 100-slot row for the place, from a human or a CPU table, with no partner or character in the pick.Code notes
In the doldecomp decompilation of Mario Kart: Double Dash!!, which builds a USA debug version (MarioClub_us) and whose item manager, Sato/ItemObjMgr.cpp, does not yet match the game's code, King Boo and Petey (character IDs 19 and 20) get an ItemRndSpecialShuffleMgr for their item picks, as every driver does in Balloon Battle and the battle the code calls ESCAPE_BATTLE; other drivers get the plain ItemShuffleMgr. Where the plain pick adds one special item, the driver's own, the random-special pick adds all nine specials, each weighted from the row's columns 18 to 26, counting from 0 (slotTable[1][i + 18] for i from 0 to 8, computed) and multiplied by 1.5 for a default pairing unless isMiniGame() is true, and leaves out the heart when the kart already has one. It leaves all nine out when the partner holds or stocks a special item. In Grand Prix, Mario Kart 64's pick takes only the place and whether the driver is a CPU.Code notes

References

  1. ^ abcIn the US version of Mario Kart 64, gen_random_item picks an item as one byte from a 100-byte row of a table, the row for the driver's current place. In Grand Prix, human players read common_grand_prix_human_item_curve and CPU drivers common_grand_prix_cpu_item_curve, and that branch reads no player count. Versus picks one of three tables by the number of players (two, three, or four), and Battle reads one row whatever the place. The slot is a random number from 0 to 100 (random_int(100)) plus the previous slot, a counter that held A, B, and R buttons advance, and the race frame counter, taken mod 100.Coden64decomp/mk64revised
    How we know
    3665u8 gen_random_item(s16 rank, s16 isCpu) {
    3666    u16 rand = random_int(100);
    ⋮
    3671    sRandomItemIndex = ((u32) rand + (sRandomItemIndex + gControllerRandom) + gRaceFrameCounter) % 100U;
    
    src/update_objects.c lines 3665–3671 at 58cfcb0 · upstream ↗
    3673    if (gModeSelection == VERSUS) {
    3674        switch (gPlayerCountSelection1) {
    3675            case TWO_PLAYERS_SELECTED:
    ⋮
    3678            case THREE_PLAYERS_SELECTED:
    ⋮
    3681            case FOUR_PLAYERS_SELECTED:
    ⋮
    3685        randomItem = *((rank * 100) + curve + sRandomItemIndex);
    
    src/update_objects.c lines 3673–3685 at 58cfcb0 · upstream ↗
    3687    } else if (gModeSelection == BATTLE) {
    3688        curve = segmented_to_virtual((void*) common_battle_item_curve);
    3689        randomItem = curve[sRandomItemIndex];
    3690    } else { // GP Mode
    3691        if (isCpu == 0) {
    3692            curve = segmented_to_virtual((void*) common_grand_prix_human_item_curve);
    3693        } else {
    3694            curve = segmented_to_virtual((void*) common_grand_prix_cpu_item_curve);
    ⋮
    3696        randomItem = *((rank * 100) + curve + sRandomItemIndex);
    
    src/update_objects.c lines 3687–3696 at 58cfcb0 · upstream ↗
    3702u8 gen_random_item_human(UNUSED s16 arg0, s16 rank) {
    3703    return gen_random_item(rank, false);
    ⋮
    3706u8 cpu_gen_random_item(UNUSED s32 arg0, s16 rank) {
    3707    return gen_random_item(rank, true);
    ⋮
    3714    randomItem = gen_random_item_human(gLapCountByPlayerId[arg1], gGPCurrentRaceRankByPlayerId[arg1]);
    
    src/update_objects.c lines 3702–3714 at 58cfcb0 · upstream ↗
    3918                cpu_decisions_branch_item(playerId, &cpuStrategy->branch,
    3919                                            cpu_gen_random_item((s16) gLapCountByPlayerId[playerId],
    3920                                                                gGPCurrentRaceRankByPlayerId[playerId]));
    
    src/cpu_vehicles_camera_path.c lines 3918–3920 at 58cfcb0 · upstream ↗
    1205void randomize_seed_from_controller(s32 arg0) {
    ⋮
    1208    if ((controller->button & A_BUTTON) != 0) {
    1209        gControllerRandom++;
    ⋮
    1211    if ((controller->button & B_BUTTON) != 0) {
    1212        gControllerRandom++;
    ⋮
    1214    if ((controller->button & R_TRIG) != 0) {
    1215        gControllerRandom++;
    
    src/code_80057C60.c lines 1205–1215 at 58cfcb0 · upstream ↗
    1269u16 random_int(u16 arg0) {
    1270    return arg0 * (((f32) random_u16()) / 65535.0);
    
    src/racing/math_util.c lines 1269–1270 at 58cfcb0 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-22.

    Revised after a check by a second AI model, 2026-10-22.

    In the claim ledger

  2. ^ abIn the doldecomp decompilation of Mario Kart: Double Dash!!, which builds a USA debug version (MarioClub_us) and whose item manager, Sato/ItemObjMgr.cpp, does not yet match the game's code, the item pick reads byte weights from a file on the disc, /Item/ItemSlotList.dat (or ItemSlotList1.dat or ItemSlotList2.dat, by the race's item-slot type). The file holds lists, each with a row of weights for every place, and a Grand Prix or Versus pick reads the row for the kart's place less one. Outside LAN play, Grand Prix reads a list by engine class (150cc and Mirror share one) for human players and the next list for CPU drivers, and Versus reads one list for every driver by the number of karts, two to four. The pick adds the row's weights for nine common kinds and for the driver's own special item, draws a whole number below the total (computed), and walks the running sum. The special's weight is multiplied by 1.5 when the two riders are a default pairing (isDefaultCharCombi), and the special is left out when the partner holds or stocks a special item, or when it is ItemHeart and the kart already has one; four common kinds (ItemThunder, ItemStar, ItemKinokoSuc, and ItemFlyTurtle, which the atlas reads as the Spiny Shell) are left out when the partner holds or stocks the same kind. startShuffle clears the flag the code calls _7, and startItemShuffleSingle sets it when its doShuffle argument is true; with it set, the pick first draws among the specials alone. setDynamicRate, which copies the weights the pick reads, writes 0 for any kind whose IsAbleToCreateItem is false (a function the decompilers comment as fabricated), and in Grand Prix multiplies the CPU list's ItemFlyTurtle weight by 1.5 while RivalBodyCtrl::isPlayerFirst() is true. In Grand Prix, Mario Kart 64 instead reads one byte from a 100-slot row for the place, from a human or a CPU table, with no partner or character in the pick.Code notesdoldecomp/mkdd · n64decomp/mk64revised
    How we know
    13WIP 1:1 Decompilation of Mario Kart Double Dash!!
    ⋮
    17Currently only the debug version is supported.
    
    README.md lines 13–17 at 1d2918c · upstream ↗
    80  To use a version other than `MarioClub_us` (USA), specify it with `--version`.
    
    README.md line 80 at 1d2918c · upstream ↗
    NonMatching = False
    configure.py#L357 · upstream ↗
    1303            Object(NonMatching, "Sato/ItemObjMgr.cpp"),
    
    configure.py line 1303 at 1d2918c · upstream ↗
    76    static const char *getSlotList(int slotType)
    ⋮
    78        const char *ret = "/Item/ItemSlotList.dat";
    79        switch (slotType)
    ⋮
    81        case 2:
    82            ret = "/Item/ItemSlotList1.dat";
    83            break;
    84        case 3:
    85            ret = "/Item/ItemSlotList2.dat";
    86            break;
    
    include/Sato/ItemObjMgr.h lines 76–89 at 1d2918c · upstream ↗
    1638    u8 *slotListData = (u8 *)ResMgr::getPtr(ResMgr::mcArcMRAM, getSlotList(RCMGetManager()->getItemSlotType()));
    
    src/Sato/ItemObjMgr.cpp line 1638 at 1d2918c · upstream ↗
    1647    switch (RCMGetManager()->getRaceLevel())
    ⋮
    1649    case LVL_50CC:
    1650        slotCount = 0;
    1651        enemySlotCount = 1;
    1652        break;
    1653    case LVL_100CC:
    1654        slotCount = 2;
    1655        enemySlotCount = 3;
    1656        break;
    1657    case LVL_150CC:
    1658    case LVL_MIRROR:
    1659        slotCount = 4;
    ⋮
    
    src/Sato/ItemObjMgr.cpp lines 1647–1662 at 1d2918c · upstream ↗
    1664    if (RCMGetManager()->isLANMode())
    ⋮
    1666        switch (RCMGetManager()->getKartNumber())
    ⋮
    1668        case 2:
    1669            slotCount = 6;
    1670            break;
    1671        case 3:
    1672            slotCount = 7;
    1673            break;
    1674        case 4:
    1675            slotCount = 8;
    1676            break;
    ⋮
    1679            break;
    ⋮
    
    src/Sato/ItemObjMgr.cpp lines 1664–1699 at 1d2918c · upstream ↗
    1719    u8 *defaultSlotList = slotListData + calcBufOffset(slotListData + 1, slotCount);
    1720    setToList(defaultSlotList + 1, &mSlotList);
    ⋮
    1738        u8 *enemyList = slotListData;
    1739        if (RCMGetManager()->getRaceMode() == VERSUS_RACE)
    ⋮
    1741            enemyList += calcBufOffset(enemyList + 1, slotCount);
    1742            enemyList += 1;
    ⋮
    1746            enemyList += calcBufOffset(enemyList + 1, enemySlotCount);
    1747            enemyList += 1;
    ⋮
    1749        setToList(enemyList, &mSlotListEnemy);
    
    src/Sato/ItemObjMgr.cpp lines 1719–1749 at 1d2918c · upstream ↗
    1753u32 ItemShuffleMgr::calcBufOffset(u8 *pData, int n)
    ⋮
    1758        u8 playerCount = *pData++;
    1759        u8 itemCount = *pData++;
    1760        offset += playerCount * itemCount + 2;
    
    src/Sato/ItemObjMgr.cpp lines 1753–1763 at 1d2918c · upstream ↗
    1766void ItemShuffleMgr::setToList(u8 *pData, ItemShuffleMgr::KartSlotData *slotData)
    ⋮
    1768    u8 playerCount = *pData++;
    1769    u8 itemCount = *pData++;
    ⋮
    1776    for (u8 playerIndex = 0; playerIndex < playerCount; playerIndex++)
    ⋮
    1789    for (u8 itemIndex = 0; itemIndex < itemCount; itemIndex++)
    ⋮
    1791        for (u8 playerIndex = 0; playerIndex < playerCount; playerIndex++)
    ⋮
    1793            slotData->mList[playerIndex].slotTable[0][itemIndex] = *pData++;
    
    src/Sato/ItemObjMgr.cpp lines 1766–1795 at 1d2918c · upstream ↗
    1843int ItemShuffleMgr::SlotItem(const int kart_index, const u8 driver_index) {
    1844    bool hasEnemy = !ObjUtility::isPlayerDriver(kart_index);
    ⋮
    1846    if (!RCMGetManager()->isRaceModeGp()) {
    1847        hasEnemy = false;
    ⋮
    1850    const KartSlotData *slotList = hasEnemy ? &mSlotListEnemy : &mSlotList;
    ⋮
    1852    int specialKind = ItemObj::getSpecialKind(kart_index, driver_index);
    1853    int rankIdx = RCMGetKartChecker(kart_index)->getRank() - 1;
    
    src/Sato/ItemObjMgr.cpp lines 1843–1853 at 1d2918c · upstream ↗
    1881    u8 swapped_idx = driver_index == 0 ? 1 : 0;
    1882    ItemObj *equipedItem = GetItemObjMgr()->getKartEquipItem(kart_index, swapped_idx);
    ⋮
    1885        normalKind = equipedItem->getKind();
    ⋮
    1888        normalKind = GetItemObjMgr()->getStockItem(kart_index, swapped_idx);
    ⋮
    1890    const bool combi = RCMGetManager()->getKartInfo(kart_index)->isDefaultCharCombi();
    1891    if (_7) {
    1892        int slot = calcRndSpecialSlot(rankIdx, *slotList, combi);
    ⋮
    1900    return calcSlot(rdata, specialKind, normalKind, combi);
    
    src/Sato/ItemObjMgr.cpp lines 1881–1900 at 1d2918c · upstream ↗
    1564    int sSlotItemIndex[27] = {
    1565        0, 2, 13, 3,
    1566        5, 18, 6, 10,
    1567        15, 17, 1, 4,
    
    src/Sato/ItemObjMgr.cpp lines 1564–1571 at 1d2918c · upstream ↗
    371            case 6:
    ⋮
    373                    removeItem(new ItemStar(6));
    ⋮
    387            case 10:
    ⋮
    389                    removeItem(new ItemThunder(0xa));
    ⋮
    399            case 13:
    ⋮
    401                    removeItem(new ItemFlyTurtle(0xd));
    ⋮
    403            case 14:
    ⋮
    405                    removeItem(new ItemHeart(0xe));
    ⋮
    422            case 18:
    ⋮
    424                    removeItem(new ItemKinokoSuc(18));
    
    src/Sato/ItemObjMgr.cpp lines 371–424 at 1d2918c · upstream ↗
    732int CLPointControllerFlyTurtle::findNextPointNo(CLPoint *point) {
    ⋮
    736        if(RCMGetKartChecker(i)->getRank() == 1)
    737            groupID = GetKartCtrl()->GetKartCenterPtr(i)->getGroupID();
    
    src/Sato/ItemFlyTurtle.cpp lines 732–737 at 1d2918c · upstream ↗
    1957void ItemShuffleMgr::calcRaceUseNormalItem(u32 *pTotal, ItemShuffleMgr::KartSlotRankDataSet *rdata, int maxId)
    ⋮
    1959    for (int i = 0; i < sSlotNormalItemNum; i++)
    ⋮
    1961        int itemIdx = sSlotItemIndex[i];
    1962        if ((((itemIdx != 10) && (itemIdx != 6) && (itemIdx != 0x12)) && (itemIdx != 0xd)) || maxId != itemIdx)
    ⋮
    1964            *pTotal += rdata->slotData->mList[rdata->kart_rank].slotTable[1][i];
    
    src/Sato/ItemObjMgr.cpp lines 1957–1966 at 1d2918c · upstream ↗
    1974void ItemShuffleMgr::calcSpecialItemNum(u32 *pTotal, ItemShuffleMgr::KartSlotRankDataSet *data, int itemID1, int itemID2, bool charCombi)
    ⋮
    1978    for (int i = sSlotNormalItemNum; i < data->slotData->totalSlots; i++)
    ⋮
    1980        if (itemID1 == sSlotKindIndexArray[i]) {
    ⋮
    1983            if (ItemObj::IsSpecialItem(itemID2) || (itemID1 == 0xe && ItemObjMgr::getItemObjMgr()->getHeartItem(data->kart_index))) {
    1984                sTempSlotUseItem[sSlotNormalItemNum] = false;
    ⋮
    1988                u32 chance = data->slotData->mList[data->kart_rank].slotTable[1][i];
    ⋮
    1990                if (charCombi) {
    1991                    chance *= 1.5f;
    ⋮
    1993                *pTotal += chance;
    
    src/Sato/ItemObjMgr.cpp lines 1974–1995 at 1d2918c · upstream ↗
    2024int ItemShuffleMgr::calcRank(KartSlotRankDataSet rdata)
    ⋮
    2027    u32 randomNum = stGetRnd(0)->getRandomMax(rdata.total - 1);
    ⋮
    2032    for (int i = 0; i < sSlotNormalItemNum + 1; i++, prevTotalChance = totalChance)
    ⋮
    2042        totalChance += sTempSlotUseItem[i] ? itemChance : 0;
    2043        if ((prevTotalChance <= randomNum) && (totalChance > randomNum))
    ⋮
    2045            ret = sSlotKindIndexArray[itemIdx];
    
    src/Sato/ItemObjMgr.cpp lines 2024–2046 at 1d2918c · upstream ↗
    2059int ItemShuffleMgr::calcSlot(KartSlotRankDataSet &rdata, int p2, int p3, bool charCombi)
    ⋮
    2065    calcRaceUseNormalItem(&total, &rdata, p3);
    2066    calcSpecialItemNum(&total, &rdata, p2, p3, charCombi);
    ⋮
    2070    return calcRank(rdata);
    
    src/Sato/ItemObjMgr.cpp lines 2059–2070 at 1d2918c · upstream ↗
    511u32 stRandom::getRandomMax(u32 max)
    ⋮
    513    return ((max + 1) * get_ufloat_1());
    
    src/Sato/stMath.cpp lines 511–513 at 1d2918c · upstream ↗
    217        f32 get_ufloat_1()
    ⋮
    226            out.s = (this->get() >> 9) | 0x3f800000;
    227            return out.f - 1;
    
    include/JSystem/JMath/JMath.h lines 217–228 at 1d2918c · upstream ↗
    526bool KartInfo::isDefaultCharCombi()
    ⋮
    530    if (mKartCharacters[0].getPartnerID() == mKartCharacters[1].getCharID())
    531        ret = true;
    
    src/Kaneshige/KartInfo.cpp lines 526–531 at 1d2918c · upstream ↗
    1815void ItemShuffleMgr::setAllDynamicRate()
    ⋮
    1817    setDynamicRate(&mSlotList, false);
    1818    if (!RCMGetManager()->isLANMode() && RCMGetManager()->getRaceMode() == GRAND_PRIX)
    1819        setDynamicRate(&mSlotListEnemy, true);
    ⋮
    1826        if (GetItemObjMgr()->IsAbleToCreateItem(sSlotItemIndex[i]))
    1827            ableToCreate = true;
    ⋮
    1830            if (ableToCreate) {
    1831                slotData->mList[j].slotTable[1][i] = slotData->mList[j].slotTable[0][i];
    1832                if (isGrandPrix && RivalBodyCtrl::isPlayerFirst() && sSlotItemIndex[i] == 0xd) {
    1833                    slotData->mList[j].slotTable[1][i] *= sGPEnemyFlyTurtleItemSlotRatio;
    ⋮
    1836            else {
    1837                slotData->mList[j].slotTable[1][i] = 0;
    
    src/Sato/ItemObjMgr.cpp lines 1815–1838 at 1d2918c · upstream ↗
    1224bool ItemObjMgr::IsAbleToCreateItem(int itemIdx) { // UNUSED, fabricated, size mismatch
    
    src/Sato/ItemObjMgr.cpp line 1224 at 1d2918c · upstream ↗
    70    void startShuffle()
    ⋮
    72        mRollFlags |= 1;
    73        _7 = false;
    
    include/Sato/ItemObjMgr.h lines 70–73 at 1d2918c · upstream ↗
    1325void ItemObjMgr::startItemShuffleSingle(int kart_index, bool doShuffle) {
    ⋮
    1329    mShuffMgr[kart_index][driver_index]->startShuffle();
    1330    if(doShuffle) {
    1331        mShuffMgr[kart_index][driver_index]->set_7(true);
    
    src/Sato/ItemObjMgr.cpp lines 1325–1331 at 1d2918c · upstream ↗
    64    f32 sGPEnemyFlyTurtleItemSlotRatio = 1.5f;
    
    src/Sato/ItemObjMgr.cpp line 64 at 1d2918c · upstream ↗
    3665u8 gen_random_item(s16 rank, s16 isCpu) {
    3666    u16 rand = random_int(100);
    ⋮
    3671    sRandomItemIndex = ((u32) rand + (sRandomItemIndex + gControllerRandom) + gRaceFrameCounter) % 100U;
    
    src/update_objects.c lines 3665–3671 at 58cfcb0 · upstream ↗
    3687    } else if (gModeSelection == BATTLE) {
    3688        curve = segmented_to_virtual((void*) common_battle_item_curve);
    3689        randomItem = curve[sRandomItemIndex];
    3690    } else { // GP Mode
    3691        if (isCpu == 0) {
    3692            curve = segmented_to_virtual((void*) common_grand_prix_human_item_curve);
    3693        } else {
    3694            curve = segmented_to_virtual((void*) common_grand_prix_cpu_item_curve);
    ⋮
    3696        randomItem = *((rank * 100) + curve + sRandomItemIndex);
    
    src/update_objects.c lines 3687–3696 at 58cfcb0 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-22.

    Revised after a check by a second AI model, 2026-10-22.

    In the claim ledger

  3. ^ abIn the US 1.0 version of Diddy Kong Racing, a weapon balloon's type is set by its entry in the track's object list, with no roll: the code names five types, boost, missile, trap, shield, and magnet, which the decompilers' names for the all-balloons cheats pair with blue, red, green, yellow, and rainbow. A racer that touches a balloon takes its type. If the racer already held the same type with any left, the weapon's level rises by one, up to the third (level 2); otherwise it starts at the first. In a challenge the level stops at the second, and trap balloons start there; the Maximum Power-up cheat makes every pickup third-level, and CPU-driven boss vehicles collect none. The weapon and its quantity come from a table the game loads as an asset, two bytes for each type and level, so they aren't in the repo. A CPU racer's driving routine func_80042D20 can also raise a first-level pickup by one, on a percent chance from the AI behavior table. Mario Kart 64 instead picks an item box's item in Grand Prix from a 100-slot row for the driver's place.CodeDavidSM64/Diddy-Kong-Racing · n64decomp/mk64revised
    How we know
    120typedef enum BalloonType {
    121    BALLOON_TYPE_BOOST,
    122    BALLOON_TYPE_MISSILE,
    123    BALLOON_TYPE_TRAP,
    124    BALLOON_TYPE_SHIELD,
    125    BALLOON_TYPE_MAGNET
    
    include/enums.h lines 120–126 at a5eb080 · upstream ↗
    193typedef struct LevelObjectEntry_WeaponBalloon {
    ⋮
    196    /* 0x09 */ u8 balloonType; Hint((Enum:BalloonType))
    
    include/level_object_entries.h lines 193–196 at a5eb080 · upstream ↗
    4658    if (cheats & CHEAT_ALL_BALLOONS_ARE_BLUE) {
    4659        entry->balloonType = BALLOON_TYPE_BOOST;
    4660    } else if (cheats & CHEAT_ALL_BALLOONS_ARE_RED) {
    4661        entry->balloonType = BALLOON_TYPE_MISSILE;
    4662    } else if (cheats & CHEAT_ALL_BALLOONS_ARE_GREEN) {
    4663        entry->balloonType = BALLOON_TYPE_TRAP;
    4664    } else if (cheats & CHEAT_ALL_BALLOONS_ARE_YELLOW) {
    4665        entry->balloonType = BALLOON_TYPE_SHIELD;
    4666    } else if (cheats & CHEAT_ALL_BALLOONS_ARE_RAINBOW) {
    4667        entry->balloonType = BALLOON_TYPE_MAGNET;
    
    src/object_functions.c lines 4658–4667 at a5eb080 · upstream ↗
    4679    obj->modelIndex = entry->balloonType;
    4680    obj->properties.weaponBalloon.balloonID = obj->modelIndex;
    
    src/object_functions.c lines 4679–4680 at a5eb080 · upstream ↗
    4745                if (racer->vehicleID < VEHICLE_BOSSES || racer->playerIndex != PLAYER_COMPUTER) {
    4746                    prevBalloonType = racer->balloon_type;
    4747                    racer->balloon_type = weaponBalloonObj->properties.weaponBalloon.balloonID;
    4748                    if (prevBalloonType == racer->balloon_type && racer->balloon_quantity != 0) {
    4749                        racer->balloon_level++;
    4750                    } else {
    4751                        racer->balloon_level = 0;
    ⋮
    4754                    if (level_type() & RACETYPE_CHALLENGE) {
    4755                        if (racer->balloon_level > 1) {
    4756                            racer->balloon_level = 1;
    ⋮
    4759                        if (racer->balloon_type == BALLOON_TYPE_TRAP) {
    4760                            racer->balloon_level = 1;
    ⋮
    
    src/object_functions.c lines 4745–4775 at a5eb080 · upstream ↗
    7009            miscAsset = (s8 *) get_misc_asset(ASSET_MISC_BALLOON_DATA);
    7010            weaponID = miscAsset[(racer->balloon_type * 10) + (racer->balloon_level * 2)];
    
    src/racer.c lines 7009–7010 at a5eb080 · upstream ↗
    327    sp38 = sp54->percentages[1][0] + (((sp54->percentages[1][1] - sp54->percentages[1][0]) * (7 - var_t5)) / 7);
    ⋮
    332    if (racer->unk209 & 1) {
    333        if (racer->unk201 == 0) {
    334            if (racer->balloon_level == 0) {
    335                if (roll_percent_chance(sp38)) {
    336                    racer->balloon_level++;
    
    src/racer.c lines 327–337 at a5eb080 · upstream ↗
    4303        } else {
    4304            racer_AI_pathing_inputs(obj, tempRacer, updateRate);
    
    src/racer.c lines 4303–4304 at a5eb080 · upstream ↗
    750    gAIBehaviourTable = mempool_alloc_safe(temp, COLOUR_TAG_YELLOW);
    751    asset_load(ASSET_AI_BEHAVIOUR, (u32) gAIBehaviourTable, temp2, temp);
    
    src/game.c lines 750–751 at a5eb080 · upstream ↗
    3687    } else if (gModeSelection == BATTLE) {
    3688        curve = segmented_to_virtual((void*) common_battle_item_curve);
    3689        randomItem = curve[sRandomItemIndex];
    3690    } else { // GP Mode
    3691        if (isCpu == 0) {
    3692            curve = segmented_to_virtual((void*) common_grand_prix_human_item_curve);
    3693        } else {
    3694            curve = segmented_to_virtual((void*) common_grand_prix_cpu_item_curve);
    ⋮
    3696        randomItem = *((rank * 100) + curve + sRandomItemIndex);
    
    src/update_objects.c lines 3687–3696 at 58cfcb0 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-22.

    Revised after a check by a second AI model, 2026-10-22.

    In the claim ledger

  4. ^In the doldecomp decompilation of Mario Kart: Double Dash!!, which builds a USA debug version (MarioClub_us) and whose item manager, Sato/ItemObjMgr.cpp, does not yet match the game's code, King Boo and Petey (character IDs 19 and 20) get an ItemRndSpecialShuffleMgr for their item picks, as every driver does in Balloon Battle and the battle the code calls ESCAPE_BATTLE; other drivers get the plain ItemShuffleMgr. Where the plain pick adds one special item, the driver's own, the random-special pick adds all nine specials, each weighted from the row's columns 18 to 26, counting from 0 (slotTable[1][i + 18] for i from 0 to 8, computed) and multiplied by 1.5 for a default pairing unless isMiniGame() is true, and leaves out the heart when the kart already has one. It leaves all nine out when the partner holds or stocks a special item. In Grand Prix, Mario Kart 64's pick takes only the place and whether the driver is a CPU.Code notesdoldecomp/mkdd · n64decomp/mk64revised
    How we know
    13WIP 1:1 Decompilation of Mario Kart Double Dash!!
    ⋮
    17Currently only the debug version is supported.
    
    README.md lines 13–17 at 1d2918c · upstream ↗
    1303            Object(NonMatching, "Sato/ItemObjMgr.cpp"),
    
    configure.py line 1303 at 1d2918c · upstream ↗
    101    KING_BOO = 19,
    102    PETEY = 20,
    
    include/kartEnums.h lines 101–102 at 1d2918c · upstream ↗
    176void ItemObjMgr::createShuffleMgr()
    ⋮
    182            if (GetGeoObjMgr()->isBalloonBattle() || GetGeoObjMgr()->isEscapeBattle())
    ⋮
    184                mShuffMgr[i][j] = new ItemRndSpecialShuffleMgr();
    ⋮
    186            else
    ⋮
    188                s32 charID = RCMGetManager()->getKartInfo(i)->getDriverCharID(j);
    189                mShuffMgr[i][j] = !IsSpecialCharacter(charID) ? new ItemShuffleMgr() : new ItemRndSpecialShuffleMgr();
    
    src/Sato/ItemObjMgr.cpp lines 176–193 at 1d2918c · upstream ↗
    1222bool ItemObjMgr::IsSpecialCharacter(s32 charID) { return charID == 0x13 || charID == 0x14; }
    
    src/Sato/ItemObjMgr.cpp line 1222 at 1d2918c · upstream ↗
    105    virtual ~ItemShuffleMgr();                                                     // 08
    106    virtual void calcRaceUseNormalItem(u32 *, KartSlotRankDataSet *, int);         // 0C
    107    virtual void calcSpecialItemNum(u32 *, KartSlotRankDataSet *, int, int, bool); // 10
    108    virtual int calcRank(KartSlotRankDataSet);                                     // 14
    ⋮
    125class ItemRndSpecialShuffleMgr : public ItemShuffleMgr
    ⋮
    131    virtual void calcRaceUseNormalItem(u32 *, KartSlotRankDataSet *, int);
    132    virtual void calcSpecialItemNum(u32 *, KartSlotRankDataSet *, int, int, bool);
    133    virtual int calcRank(KartSlotRankDataSet);
    
    include/Sato/ItemObjMgr.h lines 105–133 at 1d2918c · upstream ↗
    1564    int sSlotItemIndex[27] = {
    1565        0, 2, 13, 3,
    1566        5, 18, 6, 10,
    1567        15, 17, 1, 4,
    1568        21, 8, 11, 7,
    1569        12, 14, 17, 1,
    1570        4, 21, 8, 11,
    1571        7, 12, 14};
    
    src/Sato/ItemObjMgr.cpp lines 1564–1571 at 1d2918c · upstream ↗
    1974void ItemShuffleMgr::calcSpecialItemNum(u32 *pTotal, ItemShuffleMgr::KartSlotRankDataSet *data, int itemID1, int itemID2, bool charCombi)
    ⋮
    1980        if (itemID1 == sSlotKindIndexArray[i]) {
    ⋮
    1988                u32 chance = data->slotData->mList[data->kart_rank].slotTable[1][i];
    
    src/Sato/ItemObjMgr.cpp lines 1974–1995 at 1d2918c · upstream ↗
    2103void ItemRndSpecialShuffleMgr::calcSpecialItemNum(u32 *pTotal, ItemShuffleMgr::KartSlotRankDataSet *data, int itemID1, int itemID2, bool charCombi) {
    2104    if (ItemObj::IsSpecialItem(itemID2)) {
    2105        for (int i = 0; i < sSlotSpecialItemNum; i++) {
    2106            sTempSlotUseItem[i + sSlotNormalItemNum] = false;
    ⋮
    2108        return;
    ⋮
    2111    calcRndSpecialRatio(pTotal, data, charCombi);
    
    src/Sato/ItemObjMgr.cpp lines 2103–2111 at 1d2918c · upstream ↗
    2005void ItemShuffleMgr::calcRndSpecialRatio(u32 *pTotal, ItemShuffleMgr::KartSlotRankDataSet *data, bool charCombi) {
    2006    for (int i = 0; i < sSlotSpecialItemNum; i++) {
    2007        if ((sSlotKindIndexArray[i + sSlotNormalItemNum] == 0xe && ItemObjMgr::getItemObjMgr()->getHeartItem(data->kart_index))) {
    ⋮
    2012            u32 chance = data->slotData->mList[data->kart_rank].slotTable[1][i + sSlotNormalItemNum + sSlotSpecialItemNum];
    ⋮
    2014            if (!GetGeoObjMgr()->isMiniGame() && charCombi) {
    2015                chance *= 1.5f;
    ⋮
    2017            *pTotal += chance;
    
    src/Sato/ItemObjMgr.cpp lines 2005–2019 at 1d2918c · upstream ↗
    2135int ItemRndSpecialShuffleMgr::calcRank(KartSlotRankDataSet slotRankData)
    ⋮
    2143    for (int idx = 0; idx < slotRankData.slotData->totalSlots; idx++, prevTotalChance = totalChance)
    ⋮
    2145        u32 itemChance = idx >= sSlotNormalItemNum ? sTempSpecialRatio[idx - sSlotNormalItemNum] : slotRankData.slotData->mList[slotRankData.kart_rank].slotTable[1][idx];
    ⋮
    2150            ret = sSlotKindIndexArray[idx];
    
    src/Sato/ItemObjMgr.cpp lines 2135–2150 at 1d2918c · upstream ↗
    3665u8 gen_random_item(s16 rank, s16 isCpu) {
    3666    u16 rand = random_int(100);
    
    src/update_objects.c lines 3665–3671 at 58cfcb0 · upstream ↗
    3690    } else { // GP Mode
    3691        if (isCpu == 0) {
    3692            curve = segmented_to_virtual((void*) common_grand_prix_human_item_curve);
    3693        } else {
    3694            curve = segmented_to_virtual((void*) common_grand_prix_cpu_item_curve);
    ⋮
    3696        randomItem = *((rank * 100) + curve + sRandomItemIndex);
    
    src/update_objects.c lines 3690–3696 at 58cfcb0 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-22.

    Revised after a check by a second AI model, 2026-10-22.

    In the claim ledger

Sources

Code