summaryrefslogtreecommitdiff
path: root/src/boot/idle.c
blob: c49ba5b5964f15b634f192dc13cf27b12b0964fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "stdbool.h"

#include "buffers.h"
#include "main.h"
#include "segment_symbols.h"
#include "stack.h"
#include "libu64/stackcheck.h"
#include "viconfig.h"
#include "z64dma.h"
#include "z64thread.h"

#pragma increment_block_number "n64-us:128"

// Variables are put before most headers as a hacky way to bypass bss reordering
struct IrqMgr gIrqMgr;
STACK(sIrqMgrStack, 0x500);
StackEntry sIrqMgrStackInfo;
OSThread sMainThread;
STACK(sMainStack, 0x900);
StackEntry sMainStackInfo;
OSMesg sPiMgrCmdBuff[50];
OSMesgQueue gPiMgrCmdQueue;
OSViMode gViConfigMode;
u8 gViConfigModeType;

#include "idle.h"
#include "irqmgr.h"

u8 D_80096B20 = 1;
vu8 gViConfigUseBlack = true;
u8 gViConfigAdditionalScanLines = 0;
u32 gViConfigFeatures = OS_VI_DITHER_FILTER_ON | OS_VI_GAMMA_OFF;
f32 gViConfigXScale = 1.0f;
f32 gViConfigYScale = 1.0f;

void Main_ClearMemory(void* begin, void* end) {
    if (begin < end) {
        bzero(begin, (uintptr_t)end - (uintptr_t)begin);
    }
}

void Main_InitFramebuffer(u32* framebuffer, size_t numBytes, u32 value) {
    for (; numBytes > 0; numBytes -= sizeof(u32)) {
        *framebuffer++ = value;
    }
}

void Main_InitScreen(void) {
    Main_InitFramebuffer((u32*)gLoBuffer.framebuffer, sizeof(gLoBuffer.framebuffer),
                         (GPACK_RGBA5551(0, 0, 0, 1) << 16) | GPACK_RGBA5551(0, 0, 0, 1));
    ViConfig_UpdateVi(false);
    osViSwapBuffer(gLoBuffer.framebuffer);
    osViBlack(false);
}

void Main_InitMemory(void) {
    void* memStart = (void*)BOOT_ADDRESS_ULTRA;
    void* memEnd = OS_PHYSICAL_TO_K0(osMemSize);

    Main_ClearMemory(memStart, SEGMENT_START(framebuffer_lo));

    // Clear the rest of the buffer that was not initialized by Main_InitScreen
    Main_ClearMemory(&gLoBuffer.skyboxBuffer, SEGMENT_END(framebuffer_lo));

    // Clear all the buffers after the `code` segment, up to the end of the available RAM space
    Main_ClearMemory(SEGMENT_END(code), memEnd);
}

void Main_Init(void) {
    DmaRequest dmaReq;
    OSMesgQueue mq;
    OSMesg msg[1];
    size_t prevSize;

    osCreateMesgQueue(&mq, msg, ARRAY_COUNT(msg));

    prevSize = gDmaMgrDmaBuffSize;
    gDmaMgrDmaBuffSize = 0;

    DmaMgr_RequestAsync(&dmaReq, SEGMENT_START(code), SEGMENT_ROM_START(code), SEGMENT_ROM_SIZE_ALT(code), 0, &mq,
                        NULL);
    Main_InitScreen();
    Main_InitMemory();
    osRecvMesg(&mq, NULL, OS_MESG_BLOCK);

    gDmaMgrDmaBuffSize = prevSize;

    Main_ClearMemory(SEGMENT_BSS_START(code), SEGMENT_BSS_END(code));
}

void Main_ThreadEntry(void* arg) {
    StackCheck_Init(&sIrqMgrStackInfo, sIrqMgrStack, STACK_TOP(sIrqMgrStack), 0, 0x100, "irqmgr");
    IrqMgr_Init(&gIrqMgr, STACK_TOP(sIrqMgrStack), Z_PRIORITY_IRQMGR, 1);
    DmaMgr_Init();
    Main_Init();
    Main(arg);
    DmaMgr_Stop();
}

void Idle_InitVideo(void) {
    osCreateViManager(OS_PRIORITY_VIMGR);

    gViConfigFeatures = OS_VI_DITHER_FILTER_ON | OS_VI_GAMMA_OFF;
    gViConfigXScale = 1.0f;
    gViConfigYScale = 1.0f;

    switch (osTvType) {
        case OS_TV_NTSC:
            gViConfigModeType = OS_VI_NTSC_LAN1;
            gViConfigMode = osViModeNtscLan1;
            break;

        case OS_TV_MPAL:
            gViConfigModeType = OS_VI_MPAL_LAN1;
            gViConfigMode = osViModeMpalLan1;
            break;

        case OS_TV_PAL:
            gViConfigModeType = OS_VI_FPAL_LAN1;
            gViConfigMode = osViModeFpalLan1;
            gViConfigYScale = 0.833f;
            break;
    }

    D_80096B20 = 1;
}

void Idle_ThreadEntry(void* arg) {
    Idle_InitVideo();
    osCreatePiManager(OS_PRIORITY_PIMGR, &gPiMgrCmdQueue, sPiMgrCmdBuff, ARRAY_COUNT(sPiMgrCmdBuff));
    StackCheck_Init(&sMainStackInfo, sMainStack, STACK_TOP(sMainStack), 0, 0x400, "main");
    osCreateThread(&sMainThread, Z_THREAD_ID_MAIN, Main_ThreadEntry, arg, STACK_TOP(sMainStack), Z_PRIORITY_MAIN);
    osStartThread(&sMainThread);
    osSetThreadPri(NULL, OS_PRIORITY_IDLE);

    for (;;) {}
}