sm64

A Super Mario 64 decompilation
Log | Files | Refs | README | LICENSE

intro_geo.c (17802B)


      1 #include <PR/ultratypes.h>
      2 
      3 #include "game/memory.h"
      4 #include "game/segment2.h"
      5 #include "game/segment7.h"
      6 #include "intro_geo.h"
      7 #include "sm64.h"
      8 #include "textures.h"
      9 #include "types.h"
     10 #include "buffers/framebuffers.h"
     11 #include "game/game_init.h"
     12 #include "audio/external.h"
     13 
     14 // frame counts for the zoom in, hold, and zoom out of title model
     15 #define INTRO_STEPS_ZOOM_IN 20
     16 #define INTRO_STEPS_HOLD_1 75
     17 #define INTRO_STEPS_ZOOM_OUT 91
     18 
     19 // background types
     20 #define INTRO_BACKGROUND_SUPER_MARIO 0
     21 #define INTRO_BACKGROUND_GAME_OVER 1
     22 
     23 struct GraphNodeMore {
     24     /*0x00*/ struct GraphNode node;
     25     /*0x14*/ void *todo;
     26     /*0x18*/ u32 unk18;
     27 };
     28 
     29 // intro geo bss
     30 #if defined(VERSION_SH) || defined(VERSION_CN)
     31 static u16 *sFramebuffers[3];
     32 #endif
     33 static s32 sGameOverFrameCounter;
     34 static s32 sGameOverTableIndex;
     35 static s16 sIntroFrameCounter;
     36 static s32 sTmCopyrightAlpha;
     37 
     38 /**
     39  * Geo callback to render the "Super Mario 64" logo on the title screen
     40  */
     41 Gfx *geo_intro_super_mario_64_logo(s32 state, struct GraphNode *node, UNUSED void *context) {
     42     struct GraphNode *graphNode = node;
     43     Gfx *dl = NULL;
     44     Gfx *dlIter = NULL;
     45     Mtx *scaleMat;
     46     f32 *scaleTable1 = segmented_to_virtual(intro_seg7_table_0700C790);
     47     f32 *scaleTable2 = segmented_to_virtual(intro_seg7_table_0700C880);
     48     f32 scaleX;
     49     f32 scaleY;
     50     f32 scaleZ;
     51 
     52     if (state != 1) {
     53         sIntroFrameCounter = 0;
     54     } else if (state == 1) {
     55         graphNode->flags = (graphNode->flags & 0xFF) | (LAYER_OPAQUE << 8);
     56         scaleMat = alloc_display_list(sizeof(*scaleMat));
     57         dl = alloc_display_list(4 * sizeof(*dl));
     58         dlIter = dl;
     59 
     60         // determine scale based on the frame counter
     61         if (sIntroFrameCounter >= 0 && sIntroFrameCounter < INTRO_STEPS_ZOOM_IN) {
     62             // zooming in
     63             scaleX = scaleTable1[sIntroFrameCounter * 3];
     64             scaleY = scaleTable1[sIntroFrameCounter * 3 + 1];
     65             scaleZ = scaleTable1[sIntroFrameCounter * 3 + 2];
     66         } else if (sIntroFrameCounter >= INTRO_STEPS_ZOOM_IN && sIntroFrameCounter < INTRO_STEPS_HOLD_1) {
     67             // holding
     68             scaleX = 1.0f;
     69             scaleY = 1.0f;
     70             scaleZ = 1.0f;
     71         } else if (sIntroFrameCounter >= INTRO_STEPS_HOLD_1 && sIntroFrameCounter < INTRO_STEPS_ZOOM_OUT) {
     72             // zooming out
     73             scaleX = scaleTable2[(sIntroFrameCounter - INTRO_STEPS_HOLD_1) * 3];
     74             scaleY = scaleTable2[(sIntroFrameCounter - INTRO_STEPS_HOLD_1) * 3 + 1];
     75             scaleZ = scaleTable2[(sIntroFrameCounter - INTRO_STEPS_HOLD_1) * 3 + 2];
     76         } else {
     77             // disappeared
     78             scaleX = 0.0f;
     79             scaleY = 0.0f;
     80             scaleZ = 0.0f;
     81         }
     82         guScale(scaleMat, scaleX, scaleY, scaleZ);
     83 
     84         gSPMatrix(dlIter++, scaleMat, G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_PUSH);
     85         gSPDisplayList(dlIter++, &intro_seg7_dl_logo);  // draw model
     86         gSPPopMatrix(dlIter++, G_MTX_MODELVIEW);
     87         gSPEndDisplayList(dlIter);
     88 
     89         sIntroFrameCounter++;
     90     }
     91     return dl;
     92 }
     93 
     94 /**
     95  * Geo callback to render TM and Copyright on the title screen
     96  */
     97 Gfx *geo_intro_tm_copyright(s32 state, struct GraphNode *node, UNUSED void *context) {
     98     struct GraphNode *graphNode = node;
     99     Gfx *dl = NULL;
    100     Gfx *dlIter = NULL;
    101 
    102     if (state != 1) {  // reset
    103         sTmCopyrightAlpha = 0;
    104     } else if (state == 1) {  // draw
    105         dl = alloc_display_list(5 * sizeof(*dl));
    106         dlIter = dl;
    107         gSPDisplayList(dlIter++, dl_proj_mtx_fullscreen);
    108         gDPSetEnvColor(dlIter++, 255, 255, 255, sTmCopyrightAlpha);
    109         switch (sTmCopyrightAlpha) {
    110             case 255: // opaque
    111                 graphNode->flags = (graphNode->flags & 0xFF) | (LAYER_OPAQUE << 8);
    112                 gDPSetRenderMode(dlIter++, G_RM_AA_OPA_SURF, G_RM_AA_OPA_SURF2);
    113                 break;
    114             default: // blend
    115                 graphNode->flags = (graphNode->flags & 0xFF) | (LAYER_TRANSPARENT << 8);
    116                 gDPSetRenderMode(dlIter++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2);
    117                 break;
    118         }
    119         gSPDisplayList(dlIter++, &intro_seg7_dl_copyright);  // draw model
    120         gSPEndDisplayList(dlIter);
    121 
    122         // Once the "Super Mario 64" logo has just about zoomed fully, fade in the "TM" and copyright text
    123         if (sIntroFrameCounter >= 19) {
    124             sTmCopyrightAlpha += 26;
    125             if (sTmCopyrightAlpha > 255) {
    126                 sTmCopyrightAlpha = 255;
    127             }
    128         }
    129     }
    130     return dl;
    131 }
    132 
    133 /**
    134  * Generates a display list for a single background tile
    135  *
    136  * @param index            which tile to render (value from 0 to 11)
    137  * @param backgroundTable  array describing which image to use for each tile (0 denotes a "Super Mario 64" image, and 1 denotes a "Game Over" image)
    138  */
    139 static Gfx *intro_backdrop_one_image(s32 index, s8 *backgroundTable) {
    140     // intro screen background display lists for each of four 80x20 textures
    141     static const Gfx *introBackgroundDlRows[] = { title_screen_bg_dl_0A000130, title_screen_bg_dl_0A000148,
    142                                                   title_screen_bg_dl_0A000160, title_screen_bg_dl_0A000178 };
    143 
    144     // intro screen background texture X offsets
    145     static float xCoords[] = {
    146         0, 80, 160, 240,
    147         0, 80, 160, 240,
    148         0, 80, 160, 240,
    149     };
    150 
    151     // intro screen background texture Y offsets
    152     static float yCoords[] = {
    153         160, 160, 160, 160,
    154         80,  80,  80,  80,
    155         0,   0,   0,   0,
    156     };
    157 
    158     // table that points to either the "Super Mario 64" or "Game Over" tables
    159     static const u8 *const *textureTables[] = { mario_title_texture_table, game_over_texture_table };
    160 
    161     Mtx *mtx = alloc_display_list(sizeof(*mtx));
    162     Gfx *displayList = alloc_display_list(36 * sizeof(*displayList));
    163     Gfx *displayListIter = displayList;
    164     const u8 *const *vIntroBgTable = segmented_to_virtual(textureTables[backgroundTable[index]]);
    165     s32 i;
    166 
    167     guTranslate(mtx, xCoords[index], yCoords[index], 0.0f);
    168     gSPMatrix(displayListIter++, mtx, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH);
    169     gSPDisplayList(displayListIter++, &title_screen_bg_dl_0A000118);
    170     for (i = 0; i < 4; i++) {
    171         gDPLoadTextureBlock(displayListIter++, vIntroBgTable[i], G_IM_FMT_RGBA, G_IM_SIZ_16b, 80, 20, 0,
    172                             G_TX_CLAMP, G_TX_CLAMP, 7, 6, G_TX_NOLOD, G_TX_NOLOD)
    173         gSPDisplayList(displayListIter++, introBackgroundDlRows[i]);
    174     }
    175     gSPPopMatrix(displayListIter++, G_MTX_MODELVIEW);
    176     gSPEndDisplayList(displayListIter);
    177     return displayList;
    178 }
    179 
    180 static s8 introBackgroundIndexTable[] = {
    181     INTRO_BACKGROUND_SUPER_MARIO, INTRO_BACKGROUND_SUPER_MARIO, INTRO_BACKGROUND_SUPER_MARIO,
    182     INTRO_BACKGROUND_SUPER_MARIO, INTRO_BACKGROUND_SUPER_MARIO, INTRO_BACKGROUND_SUPER_MARIO,
    183     INTRO_BACKGROUND_SUPER_MARIO, INTRO_BACKGROUND_SUPER_MARIO, INTRO_BACKGROUND_SUPER_MARIO,
    184     INTRO_BACKGROUND_SUPER_MARIO, INTRO_BACKGROUND_SUPER_MARIO, INTRO_BACKGROUND_SUPER_MARIO,
    185 };
    186 
    187 // only one table of indexes listed
    188 static s8 *introBackgroundTables[] = { introBackgroundIndexTable };
    189 
    190 /**
    191  * Geo callback to render the intro background tiles
    192  */
    193 Gfx *geo_intro_regular_backdrop(s32 state, struct GraphNode *node, UNUSED void *context) {
    194     struct GraphNodeMore *graphNode = (struct GraphNodeMore *) node;
    195     s32 index = graphNode->unk18 & 0xff; // TODO: word at offset 0x18 of struct GraphNode (always ends up being 0)
    196     s8 *backgroundTable = introBackgroundTables[index];
    197     Gfx *dl = NULL;
    198     Gfx *dlIter = NULL;
    199     s32 i;
    200 
    201     if (state == 1) {  // draw
    202         dl = alloc_display_list(16 * sizeof(*dl));
    203         dlIter = dl;
    204         graphNode->node.flags = (graphNode->node.flags & 0xFF) | (LAYER_OPAQUE << 8);
    205         gSPDisplayList(dlIter++, &dl_proj_mtx_fullscreen);
    206         gSPDisplayList(dlIter++, &title_screen_bg_dl_0A000100);
    207         for (i = 0; i < 12; i++) {
    208             gSPDisplayList(dlIter++, intro_backdrop_one_image(i, backgroundTable));
    209         }
    210         gSPDisplayList(dlIter++, &title_screen_bg_dl_0A000190);
    211         gSPEndDisplayList(dlIter);
    212     }
    213     return dl;
    214 }
    215 
    216 static s8 gameOverBackgroundTable[] = {
    217     INTRO_BACKGROUND_GAME_OVER, INTRO_BACKGROUND_GAME_OVER, INTRO_BACKGROUND_GAME_OVER,
    218     INTRO_BACKGROUND_GAME_OVER, INTRO_BACKGROUND_GAME_OVER, INTRO_BACKGROUND_GAME_OVER,
    219     INTRO_BACKGROUND_GAME_OVER, INTRO_BACKGROUND_GAME_OVER, INTRO_BACKGROUND_GAME_OVER,
    220     INTRO_BACKGROUND_GAME_OVER, INTRO_BACKGROUND_GAME_OVER, INTRO_BACKGROUND_GAME_OVER,
    221 };
    222 
    223 /**
    224  * Geo callback to render the Game Over background tiles
    225  */
    226 Gfx *geo_intro_gameover_backdrop(s32 state, struct GraphNode *node, UNUSED void *context) {
    227     struct GraphNode *graphNode = node;
    228     Gfx *dl = NULL;
    229     Gfx *dlIter = NULL;
    230     s32 j;
    231     s32 i;
    232 
    233     if (state != 1) {  // reset
    234         sGameOverFrameCounter = 0;
    235         sGameOverTableIndex = -2;
    236         for (i = 0; i < ARRAY_COUNT(gameOverBackgroundTable); i++) {
    237             gameOverBackgroundTable[i] = INTRO_BACKGROUND_GAME_OVER;
    238         }
    239     } else {  // draw
    240         dl = alloc_display_list(16 * sizeof(*dl));
    241         dlIter = dl;
    242         if (sGameOverTableIndex == -2) {
    243             if (sGameOverFrameCounter == 180) {
    244                 sGameOverTableIndex++;
    245                 sGameOverFrameCounter = 0;
    246             }
    247         } else {
    248             // transition tile from "Game Over" to "Super Mario 64"
    249             if (sGameOverTableIndex != 11 && !(sGameOverFrameCounter & 0x1)) {
    250                 // order of tiles that are flipped from "Game Over" to "Super Mario 64"
    251                 static s8 flipOrder[] = { 0, 1, 2, 3, 7, 11, 10, 9, 8, 4, 5, 6 };
    252 
    253                 sGameOverTableIndex++;
    254                 gameOverBackgroundTable[flipOrder[sGameOverTableIndex]] =
    255                     INTRO_BACKGROUND_SUPER_MARIO;
    256             }
    257         }
    258         if (sGameOverTableIndex != 11) {
    259             sGameOverFrameCounter++;
    260         }
    261         graphNode->flags = (graphNode->flags & 0xFF) | (LAYER_OPAQUE << 8);
    262 
    263         // draw all the tiles
    264         gSPDisplayList(dlIter++, &dl_proj_mtx_fullscreen);
    265         gSPDisplayList(dlIter++, &title_screen_bg_dl_0A000100);
    266         for (j = 0; j < ARRAY_COUNT(gameOverBackgroundTable); j++) {
    267             gSPDisplayList(dlIter++, intro_backdrop_one_image(j, gameOverBackgroundTable));
    268         }
    269         gSPDisplayList(dlIter++, &title_screen_bg_dl_0A000190);
    270         gSPEndDisplayList(dlIter);
    271     }
    272     return dl;
    273 }
    274 
    275 #if defined(VERSION_SH) || defined(VERSION_CN)
    276 
    277 extern Gfx title_screen_bg_dl_0A0065E8[];
    278 extern Gfx title_screen_bg_dl_0A006618[];
    279 extern Gfx title_screen_bg_dl_0A007548[];
    280 
    281 // Data
    282 s8 sFaceVisible[] = {
    283     1, 1, 1, 1, 1, 1, 1, 1,
    284     1, 1, 1, 1, 1, 1, 1, 1,
    285     1, 1, 0, 0, 0, 0, 1, 1,
    286     1, 1, 0, 0, 0, 0, 1, 1,
    287     1, 1, 1, 1, 1, 1, 1, 1,
    288     1, 1, 1, 1, 1, 1, 1, 1,
    289 };
    290 
    291 s8 sFaceToggleOrder[] = {
    292      0,  1,  2,  3,  4,  5,  6,  7,
    293     15, 23, 31, 39, 47, 46, 45, 44,
    294     43, 42, 41, 40, 32, 24, 16,  8,
    295      9, 10, 11, 12, 13, 14, 22, 30,
    296     38, 37, 36, 35, 34, 33, 25, 17,
    297 };
    298 
    299 s8 sFaceCounter = 0;
    300 
    301 void intro_gen_face_texrect(Gfx **dlIter) {
    302     s32 x;
    303     s32 y;
    304 
    305     for (y = 0; y < 6; y++) {
    306         for (x = 0; x < 8; x++) {
    307             if (sFaceVisible[y*8 + x] != 0) {
    308                 gSPTextureRectangle((*dlIter)++, (x * 40) << 2, (y * 40) << 2, (x * 40 + 39) << 2, (y * 40 + 39) << 2, 0,
    309                                     0, 0, 4 << 10, 1 << 10);
    310             }
    311         }
    312     }
    313 }
    314 
    315 Gfx *intro_draw_face(u16 *image, s32 imageW, s32 imageH) {
    316     Gfx *dl;
    317     Gfx *dlIter;
    318 
    319     dl = alloc_display_list(110 * sizeof(Gfx));
    320 
    321     if (dl == NULL) {
    322         return dl;
    323     } else {
    324         dlIter = dl;
    325     }
    326 
    327     gSPDisplayList(dlIter++, title_screen_bg_dl_0A0065E8);
    328 
    329     gDPLoadTextureBlock(dlIter++, VIRTUAL_TO_PHYSICAL(image), G_IM_FMT_RGBA, G_IM_SIZ_16b, imageW, imageH, 0, G_TX_CLAMP | G_TX_NOMIRROR, G_TX_CLAMP | G_TX_NOMIRROR, 6, 6, G_TX_NOLOD, G_TX_NOLOD);
    330 
    331     intro_gen_face_texrect(&dlIter);
    332 
    333     gSPDisplayList(dlIter++, title_screen_bg_dl_0A006618);
    334 
    335     gSPEndDisplayList(dlIter++);
    336 
    337     return dl;
    338 }
    339 
    340 #ifdef VERSION_CN
    341 
    342 // TODO: See whether this matches other game versions too, clearly there was no actual
    343 //       substantive change in this function
    344 u16 *intro_sample_framebuffer(s32 imageW, s32 imageH, s32 sampleW, s32 sampleH) {
    345     u16 *fb;
    346     u16 *image;
    347     s32 xIndex;
    348     s32 yIndex;
    349     f32 size;
    350     f32 r, g, b;
    351     s32 iy, ix, sy, sx;
    352     s32 xOffset, yOffset;
    353     u16 fbr, fbg, fbb;
    354     f32 f1, f2, f3;
    355 
    356     fb = sFramebuffers[sRenderingFramebuffer];
    357     image = alloc_display_list(imageW * imageH * sizeof(u16));
    358 
    359     if (image == NULL) {
    360         return image;
    361     }
    362 
    363     for (iy = 0; iy < imageH; iy++) {
    364         yOffset = 80;
    365 
    366         for (ix = 0; ix < imageW; ix++) {
    367             xOffset = 120;
    368 
    369             r = 0;
    370             g = 0;
    371             b = 0;
    372 
    373             for (sy = 0; sy < sampleH; sy++) {
    374                 for (sx = 0; sx < sampleW; sx++) {
    375                     yIndex = (sampleH * iy + yOffset) + sy;
    376                     xIndex = (sampleW * ix + xOffset) + sx;
    377 
    378                     fbr = fb[320 * yIndex + xIndex];
    379                     fbg = fb[320 * yIndex + xIndex];
    380                     fbb = fb[320 * yIndex + xIndex];
    381 
    382                     f1 = (fbr >> 0xB) & 0x1F;
    383                     f2 = (fbg >> 0x6) & 0x1F;
    384                     f3 = (fbb >> 0x1) & 0x1F;
    385 
    386                     r += f1;
    387                     g += f2;
    388                     b += f3;
    389                 }
    390             }
    391 
    392             size = sampleW * sampleH;
    393 
    394             fbr = ((u16) (r / size + 0.5) << 0xB) & 0xF800;
    395             fbg = ((u16) (g / size + 0.5) << 0x6) &  0x7C0;
    396             fbb = ((u16) (b / size + 0.5) << 0x1) &   0x3E;
    397 
    398             image[imageH * iy + ix] = fbr + fbg + fbb + 1;
    399         }
    400     }
    401 
    402     return image;
    403 }
    404 
    405 #else
    406 
    407 u16 *intro_sample_framebuffer(s32 imageW, s32 imageH, s32 sampleW, s32 sampleH) {
    408     u16 *fb;
    409     u16 *image;
    410     s32 pixel;
    411     f32 size;
    412     f32 r, g, b;
    413     s32 iy, ix, sy, sx;
    414 
    415     s32 xOffset = 120;
    416     s32 yOffset = 80;
    417 
    418     fb = sFramebuffers[sRenderingFramebuffer];
    419     image = alloc_display_list(imageW * imageH * sizeof(u16));
    420 
    421     if (image == NULL) {
    422         return image;
    423     }
    424 
    425     for (iy = 0; iy < imageH; iy++) {
    426         for (ix = 0; ix < imageW; ix++) {
    427             r = 0;
    428             g = 0;
    429             b = 0;
    430 
    431             for (sy = 0; sy < sampleH; sy++) {
    432                 for (sx = 0; sx < sampleW; sx++) {
    433                     u16 fbr, fbg, fbb;
    434                     f32 f1, f2, f3;
    435                     pixel = 320 * (sampleH * iy + sy + yOffset) + (sampleW * ix + xOffset) + sx;
    436 
    437                     fbr = fb[pixel];
    438                     fbg = fb[pixel];
    439                     fbb = fb[pixel];
    440 
    441                     f1 = ((fbr >> 0xB) & 0x1F);
    442                     f2 = ((fbg >> 0x6) & 0x1F);
    443                     f3 = ((fbb >> 0x1) & 0x1F);
    444 
    445                     r += f1;
    446                     g += f2;
    447                     b += f3;
    448                 }
    449             }
    450 
    451             size = sampleW * sampleH;
    452             image[imageH * iy + ix] = ((((u16) (r / size + 0.5) << 0xB) & 0xF800) & 0xffff) +
    453                                       ((((u16) (g / size + 0.5) << 0x6) &  0x7C0) & 0xffff) +
    454                                       ((((u16) (b / size + 0.5) << 0x1) &   0x3E) & 0xffff) + 1;
    455         }
    456     }
    457 
    458     return image;
    459 }
    460 
    461 #endif
    462 
    463 Gfx *geo_intro_face_easter_egg(s32 state, struct GraphNode *node, UNUSED void *context) {
    464     struct GraphNodeGenerated *genNode;
    465     u16 *image;
    466     Gfx *dl = NULL;
    467     s32 i;
    468 
    469     genNode = (struct GraphNodeGenerated *) node;
    470 
    471     if (state != 1) {
    472         sFramebuffers[0] = gFramebuffer0;
    473         sFramebuffers[1] = gFramebuffer1;
    474         sFramebuffers[2] = gFramebuffer2;
    475 
    476         for (i = 0; i < 48; i++) {
    477             sFaceVisible[i] = 0;
    478         }
    479     } else if (state == 1) {
    480         if (sFaceCounter == 0) {
    481             if (gPlayer1Controller->buttonPressed & Z_TRIG) {
    482                 play_sound(SOUND_MENU_STAR_SOUND, gGlobalSoundSource);
    483                 sFaceVisible[0] ^= 1;
    484                 sFaceCounter++;
    485             }
    486         } else {
    487             sFaceVisible[sFaceToggleOrder[sFaceCounter++]] ^= 1;
    488             if (sFaceCounter >= 40) {
    489                 sFaceCounter = 0;
    490             }
    491         }
    492 
    493         // Draw while the first or last face is visible.
    494         if (sFaceVisible[0] == 1 || sFaceVisible[17] == 1) {
    495             image = intro_sample_framebuffer(40, 40, 2, 2);
    496             if (image != NULL) {
    497                 genNode->fnNode.node.flags = (genNode->fnNode.node.flags & 0xFF) | (LAYER_OPAQUE << 8);
    498                 dl = intro_draw_face(image, 40, 40);
    499             }
    500         }
    501     }
    502 
    503     return dl;
    504 }
    505 
    506 Gfx *geo_intro_rumble_pak_graphic(s32 state, struct GraphNode *node, UNUSED void *context) {
    507     struct GraphNodeGenerated *genNode = (struct GraphNodeGenerated *)node;
    508     Gfx *dlIter;
    509     Gfx *dl;
    510     s32 introContext;
    511     s8 backgroundTileSix;
    512 #ifdef AVOID_UB
    513     dl = NULL;
    514     backgroundTileSix = 0;
    515 #endif
    516 
    517     if (state != 1) {
    518         dl = NULL;
    519     } else if (state == 1) {
    520         genNode->fnNode.node.flags = (genNode->fnNode.node.flags & 0xFF) | (LAYER_OPAQUE << 8);
    521         introContext = genNode->parameter & 0xFF;
    522         if (introContext == 0) {
    523             backgroundTileSix = introBackgroundIndexTable[6];
    524         } else if (introContext == 1) {
    525             backgroundTileSix = gameOverBackgroundTable[6];
    526         }
    527         if (backgroundTileSix == INTRO_BACKGROUND_SUPER_MARIO) {
    528             dl = alloc_display_list(3 * sizeof(*dl));
    529             if (dl != NULL) {
    530                 dlIter = dl;
    531                 gSPDisplayList(dlIter++, &title_screen_bg_dl_0A007548);
    532                 gSPEndDisplayList(dlIter);
    533             }
    534         } else {
    535             dl = NULL;
    536         }
    537     }
    538     return dl;
    539 }
    540 
    541 #endif