data/claims/mkdd.yamlMario Kart: Double Dash!! (the doldecomp decompilation, doldecomp/mkdd)
Game: Mario Kart: Double Dash!!.
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, 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. mkdd/item-slot
About: Mario Kart: Double Dash!! Item distribution
Value
{
"common-kinds": 9,
"special-kinds": 9,
"default-pair-factor": 1.5,
"cpu-spiny-factor-player-first": 1.5
}README.md#L13-L17WIP 1:1 Decompilation of Mario Kart Double Dash!!
…
Currently only the debug version is supported.mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · README.md#L80To use a version other than `MarioClub_us` (USA), specify it with `--version`.mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · configure.py#L357NonMatching = Falsemkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · configure.py#L1303Object(NonMatching, "Sato/ItemObjMgr.cpp"),mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · include/Sato/ItemObjMgr.h#L76-L89static const char *getSlotList(int slotType)
{
const char *ret = "/Item/ItemSlotList.dat";
switch (slotType)
{
case 2:
ret = "/Item/ItemSlotList1.dat";
break;
case 3:
ret = "/Item/ItemSlotList2.dat";mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L1638u8 *slotListData = (u8 *)ResMgr::getPtr(ResMgr::mcArcMRAM, getSlotList(RCMGetManager()->getItemSlotType()));mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L1647-L1662switch (RCMGetManager()->getRaceLevel())
{
case LVL_50CC:
slotCount = 0;
enemySlotCount = 1;
break;
case LVL_100CC:
slotCount = 2;
enemySlotCount = 3;
break;
case LVL_150CC:
case LVL_MIRROR:
…mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L1664-L1699if (RCMGetManager()->isLANMode())
…
isLanVs = true;
}
else
{
switch (RCMGetManager()->getRaceMode())
{
case VERSUS_RACE:
{
switch (RCMGetManager()->getKartNumber())
{
…mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L1719-L1749u8 *defaultSlotList = slotListData + calcBufOffset(slotListData + 1, slotCount);
setToList(defaultSlotList + 1, &mSlotList);
…
u8 *enemyList = slotListData;
if (RCMGetManager()->getRaceMode() == VERSUS_RACE)
{
enemyList += calcBufOffset(enemyList + 1, slotCount);
…
enemyList += calcBufOffset(enemyList + 1, enemySlotCount);
enemyList += 1;
}
setToList(enemyList, &mSlotListEnemy);mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L1753-L1763u32 ItemShuffleMgr::calcBufOffset(u8 *pData, int n)
…
u8 playerCount = *pData++;
u8 itemCount = *pData++;
offset += playerCount * itemCount + 2;mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L1766-L1795void ItemShuffleMgr::setToList(u8 *pData, ItemShuffleMgr::KartSlotData *slotData)
{
u8 playerCount = *pData++;
u8 itemCount = *pData++;
…
for (u8 itemIndex = 0; itemIndex < itemCount; itemIndex++)
{
for (u8 playerIndex = 0; playerIndex < playerCount; playerIndex++)
{
slotData->mList[playerIndex].slotTable[0][itemIndex] = *pData++;mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L1843-L1853int ItemShuffleMgr::SlotItem(const int kart_index, const u8 driver_index) {
bool hasEnemy = !ObjUtility::isPlayerDriver(kart_index);
…
if (!RCMGetManager()->isRaceModeGp()) {
hasEnemy = false;
…
const KartSlotData *slotList = hasEnemy ? &mSlotListEnemy : &mSlotList;
…
int specialKind = ItemObj::getSpecialKind(kart_index, driver_index);
int rankIdx = RCMGetKartChecker(kart_index)->getRank() - 1;mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L1881-L1900u8 swapped_idx = driver_index == 0 ? 1 : 0;
ItemObj *equipedItem = GetItemObjMgr()->getKartEquipItem(kart_index, swapped_idx);
…
normalKind = equipedItem->getKind();
…
normalKind = GetItemObjMgr()->getStockItem(kart_index, swapped_idx);
…
const bool combi = RCMGetManager()->getKartInfo(kart_index)->isDefaultCharCombi();
if (_7) {
int slot = calcRndSpecialSlot(rankIdx, *slotList, combi);
…
return calcSlot(rdata, specialKind, normalKind, combi);mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L1564-L1571int sSlotItemIndex[27] = {
0, 2, 13, 3,
5, 18, 6, 10,
15, 17, 1, 4,mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L371-L424case 6:
…
removeItem(new ItemStar(6));
…
case 10:
…
removeItem(new ItemThunder(0xa));
…
case 13:
…
removeItem(new ItemFlyTurtle(0xd));
…
…mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemFlyTurtle.cpp#L732-L737int CLPointControllerFlyTurtle::findNextPointNo(CLPoint *point) {
…
if(RCMGetKartChecker(i)->getRank() == 1)
groupID = GetKartCtrl()->GetKartCenterPtr(i)->getGroupID();mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L1957-L1966void ItemShuffleMgr::calcRaceUseNormalItem(u32 *pTotal, ItemShuffleMgr::KartSlotRankDataSet *rdata, int maxId)
{
for (int i = 0; i < sSlotNormalItemNum; i++)
{
int itemIdx = sSlotItemIndex[i];
if ((((itemIdx != 10) && (itemIdx != 6) && (itemIdx != 0x12)) && (itemIdx != 0xd)) || maxId != itemIdx)
{
*pTotal += rdata->slotData->mList[rdata->kart_rank].slotTable[1][i];mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L1974-L1995void ItemShuffleMgr::calcSpecialItemNum(u32 *pTotal, ItemShuffleMgr::KartSlotRankDataSet *data, int itemID1, int itemID2, bool charCombi)
…
for (int i = sSlotNormalItemNum; i < data->slotData->totalSlots; i++)
{
if (itemID1 == sSlotKindIndexArray[i]) {
…
if (ItemObj::IsSpecialItem(itemID2) || (itemID1 == 0xe && ItemObjMgr::getItemObjMgr()->getHeartItem(data->kart_index))) {
sTempSlotUseItem[sSlotNormalItemNum] = false;
…
u32 chance = data->slotData->mList[data->kart_rank].slotTable[1][i];
…
if (charCombi) {
…mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L2024-L2046int ItemShuffleMgr::calcRank(KartSlotRankDataSet rdata)
…
u32 randomNum = stGetRnd(0)->getRandomMax(rdata.total - 1);
…
for (int i = 0; i < sSlotNormalItemNum + 1; i++, prevTotalChance = totalChance)
…
totalChance += sTempSlotUseItem[i] ? itemChance : 0;
if ((prevTotalChance <= randomNum) && (totalChance > randomNum))
{
ret = sSlotKindIndexArray[itemIdx];mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L2059-L2070int ItemShuffleMgr::calcSlot(KartSlotRankDataSet &rdata, int p2, int p3, bool charCombi)
…
calcRaceUseNormalItem(&total, &rdata, p3);
calcSpecialItemNum(&total, &rdata, p2, p3, charCombi);
…
return calcRank(rdata);mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/stMath.cpp#L511-L513u32 stRandom::getRandomMax(u32 max)
{
return ((max + 1) * get_ufloat_1());mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · include/JSystem/JMath/JMath.h#L217-L228f32 get_ufloat_1()
…
out.s = (this->get() >> 9) | 0x3f800000;
return out.f - 1;mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Kaneshige/KartInfo.cpp#L526-L531bool KartInfo::isDefaultCharCombi()
…
if (mKartCharacters[0].getPartnerID() == mKartCharacters[1].getCharID())
ret = true;mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L1815-L1838void ItemShuffleMgr::setAllDynamicRate()
{
setDynamicRate(&mSlotList, false);
if (!RCMGetManager()->isLANMode() && RCMGetManager()->getRaceMode() == GRAND_PRIX)
setDynamicRate(&mSlotListEnemy, true);
…
if (GetItemObjMgr()->IsAbleToCreateItem(sSlotItemIndex[i]))
ableToCreate = true;
…
if (ableToCreate) {
slotData->mList[j].slotTable[1][i] = slotData->mList[j].slotTable[0][i];
if (isGrandPrix && RivalBodyCtrl::isPlayerFirst() && sSlotItemIndex[i] == 0xd) {
…mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L1224bool ItemObjMgr::IsAbleToCreateItem(int itemIdx) { // UNUSED, fabricated, size mismatchmkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · include/Sato/ItemObjMgr.h#L70-L73void startShuffle()
{
mRollFlags |= 1;
_7 = false;mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L1325-L1331void ItemObjMgr::startItemShuffleSingle(int kart_index, bool doShuffle) {
…
mShuffMgr[kart_index][driver_index]->startShuffle();
if(doShuffle) {
mShuffMgr[kart_index][driver_index]->set_7(true);mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L64f32 sGPEnemyFlyTurtleItemSlotRatio = 1.5f;mk64: a decompilation of Mario Kart 64 (n64decomp/mk64) · src/update_objects.c#L3665-L3671u8 gen_random_item(s16 rank, s16 isCpu) {
u16 rand = random_int(100);
…
sRandomItemIndex = ((u32) rand + (sRandomItemIndex + gControllerRandom) + gRaceFrameCounter) % 100U;mk64: a decompilation of Mario Kart 64 (n64decomp/mk64) · src/update_objects.c#L3687-L3696} else if (gModeSelection == BATTLE) {
curve = segmented_to_virtual((void*) common_battle_item_curve);
randomItem = curve[sRandomItemIndex];
} else { // GP Mode
if (isCpu == 0) {
curve = segmented_to_virtual((void*) common_grand_prix_human_item_curve);
} else {
curve = segmented_to_virtual((void*) common_grand_prix_cpu_item_curve);
}
randomItem = *((rank * 100) + curve + sRandomItemIndex);Checked by claude, 2026-10-22 — read loadSlotData whole, calcBufOffset, setToList, SlotItem whole, calcSlot and the three virtual steps it calls in ItemShuffleMgr, setAllDynamicRate and setDynamicRate, getRandomMax and get_ufloat_1, startShuffle and startItemShuffleSingle (the `_7` flag), IsAbleToCreateItem's commented signature, isDefaultCharCombi (both branches compare the first rider's default partner with the second rider), the item-kind switch that names each kind's class, and the ItemObjMgr.cpp entry in configure.py; for Mario Kart 64, gen_random_item at the pinned commitThe weights are data on the disc, so the chance of each item by place isn't read here; a USA disc's ItemSlotList.dat would give them. The nine common kinds are, by class, ItemGTurtle, ItemRTurtle, ItemFlyTurtle, ItemBanana, ItemKinoko, ItemKinokoSuc, ItemStar, ItemThunder, and ItemFakeItemBox (sSlotItemIndex[0..8] against the switch at L347-L432); the atlas reads them as the green and red shells, the Spiny Shell, the banana, the mushroom, triple mushrooms, the star, lightning, and the fake item box. Which special a driver has comes from ItemObj::getSpecialKind, still an empty file (src/Sato/ItemObj.cpp), so the character-to-item table isn't read. No caller of SlotItem or setAllDynamicRate is in the decompiled code, so when the copy is refreshed isn't shown, and who sets the isPlayerFirst bit (RivalBodyCtrl, NonMatching) isn't traced. LAN play remaps rows for five to seven karts (sSlotTblIndexForLAN_*); Balloon Battle picks a row by balloons behind the leader (capped at the third), and Bob-omb Blast always gives kind 8.
Cited by: Item distribution, Mario Kart: Double Dash!!
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. mkdd/random-specials
About: Mario Kart: Double Dash!! Item distribution
Value
{
"characters": [
19,
20
],
"specials": 9,
"default-pair-factor": 1.5
}README.md#L13-L17WIP 1:1 Decompilation of Mario Kart Double Dash!!
…
Currently only the debug version is supported.mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · configure.py#L1303Object(NonMatching, "Sato/ItemObjMgr.cpp"),mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · include/kartEnums.h#L101-L102KING_BOO = 19,
PETEY = 20,mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L176-L193void ItemObjMgr::createShuffleMgr()
…
if (GetGeoObjMgr()->isBalloonBattle() || GetGeoObjMgr()->isEscapeBattle())
{
mShuffMgr[i][j] = new ItemRndSpecialShuffleMgr();
}
else
{
s32 charID = RCMGetManager()->getKartInfo(i)->getDriverCharID(j);
mShuffMgr[i][j] = !IsSpecialCharacter(charID) ? new ItemShuffleMgr() : new ItemRndSpecialShuffleMgr();mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L1222bool ItemObjMgr::IsSpecialCharacter(s32 charID) { return charID == 0x13 || charID == 0x14; }mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · include/Sato/ItemObjMgr.h#L105-L133virtual ~ItemShuffleMgr(); // 08
virtual void calcRaceUseNormalItem(u32 *, KartSlotRankDataSet *, int); // 0C
virtual void calcSpecialItemNum(u32 *, KartSlotRankDataSet *, int, int, bool); // 10
virtual int calcRank(KartSlotRankDataSet); // 14
…
class ItemRndSpecialShuffleMgr : public ItemShuffleMgr
…
virtual void calcSpecialItemNum(u32 *, KartSlotRankDataSet *, int, int, bool);
virtual int calcRank(KartSlotRankDataSet);mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L1564-L1571int sSlotItemIndex[27] = {
0, 2, 13, 3,
5, 18, 6, 10,
15, 17, 1, 4,
21, 8, 11, 7,
12, 14, 17, 1,
4, 21, 8, 11,
7, 12, 14};mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L1974-L1995void ItemShuffleMgr::calcSpecialItemNum(u32 *pTotal, ItemShuffleMgr::KartSlotRankDataSet *data, int itemID1, int itemID2, bool charCombi)
…
if (itemID1 == sSlotKindIndexArray[i]) {
…
u32 chance = data->slotData->mList[data->kart_rank].slotTable[1][i];mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L2103-L2111void ItemRndSpecialShuffleMgr::calcSpecialItemNum(u32 *pTotal, ItemShuffleMgr::KartSlotRankDataSet *data, int itemID1, int itemID2, bool charCombi) {
if (ItemObj::IsSpecialItem(itemID2)) {
for (int i = 0; i < sSlotSpecialItemNum; i++) {
sTempSlotUseItem[i + sSlotNormalItemNum] = false;
}
return;
}
…
calcRndSpecialRatio(pTotal, data, charCombi);mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L2005-L2019void ItemShuffleMgr::calcRndSpecialRatio(u32 *pTotal, ItemShuffleMgr::KartSlotRankDataSet *data, bool charCombi) {
for (int i = 0; i < sSlotSpecialItemNum; i++) {
if ((sSlotKindIndexArray[i + sSlotNormalItemNum] == 0xe && ItemObjMgr::getItemObjMgr()->getHeartItem(data->kart_index))) {
…
u32 chance = data->slotData->mList[data->kart_rank].slotTable[1][i + sSlotNormalItemNum + sSlotSpecialItemNum];
…
if (!GetGeoObjMgr()->isMiniGame() && charCombi) {
chance *= 1.5f;
}
*pTotal += chance;mkdd: a decompilation of Mario Kart: Double Dash!! (doldecomp/mkdd) · src/Sato/ItemObjMgr.cpp#L2135-L2150int ItemRndSpecialShuffleMgr::calcRank(KartSlotRankDataSet slotRankData)
…
for (int idx = 0; idx < slotRankData.slotData->totalSlots; idx++, prevTotalChance = totalChance)
{
u32 itemChance = idx >= sSlotNormalItemNum ? sTempSpecialRatio[idx - sSlotNormalItemNum] : slotRankData.slotData->mList[slotRankData.kart_rank].slotTable[1][idx];
…
ret = sSlotKindIndexArray[idx];mk64: a decompilation of Mario Kart 64 (n64decomp/mk64) · src/update_objects.c#L3665-L3671u8 gen_random_item(s16 rank, s16 isCpu) {
u16 rand = random_int(100);mk64: a decompilation of Mario Kart 64 (n64decomp/mk64) · src/update_objects.c#L3690-L3696} else { // GP Mode
if (isCpu == 0) {
curve = segmented_to_virtual((void*) common_grand_prix_human_item_curve);
} else {
curve = segmented_to_virtual((void*) common_grand_prix_cpu_item_curve);
}
randomItem = *((rank * 100) + curve + sRandomItemIndex);Checked by claude, 2026-10-22 — read createShuffleMgr, IsSpecialCharacter, the character enum, the two classes' virtual tables, the subclass's calcRaceUseNormalItem (the same test as the base), calcSpecialItemNum, and calcRank, calcRndSpecialRatio, and calcSlot that dispatches to them; for Mario Kart 64, the signature of gen_random_item"Columns 18 to 26" is computed: calcRndSpecialRatio reads column i + 18 for the nine specials, and sSlotItemIndex repeats the nine special kinds at 18 to 26. The subclass's calcRank loop runs to totalSlots, past the 18 entries of sTempSlotUseItem, but the running sum reaches the total by the 18th entry, so a draw below the total stops there (computed). The atlas reads the nine special kinds, by class, as ItemGTurtleSuc, ItemGTurtleBig, ItemBananaBig, ItemFireBallSuc, ItemBomb, ItemYoshiEgg, ItemWanWanObj, ItemGoldenKinoko, and ItemHeart (src/Sato/ItemObjMgr.cpp#L347-L432). Which character holds which special isn't read (ItemObj::getSpecialKind is in the still-empty ItemObj.cpp).
Cited by: Mario Kart: Double Dash!!