n64main.c
3.76 KB
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
138
139
140
141
142
143
144
145
146
147
148
#include <ultra64.h>
#include <os.h>
#include <ultralog.h>
#include <assert.h>
#include "sched.h"
#include "gfx.h"
#include "spec.h"
/* Stacks for the threads and message queues */
u64 bootStack[STACKSIZE/8];
static void mainproc(char *);
static void gameproc(char *);
extern void midiproc(char *);
static OSThread rmonThread;
static OSThread mainThread;
static OSThread gameThread;
static OSThread midiThread;
static u64 rmonThreadStack[RMON_STACKSIZE/8];
static u64 mainThreadStack[STACKSIZE/8];
static u64 gameThreadStack[STACKSIZE/8];
static u64 midiThreadStack[STACKSIZE/8];
/* For PI manager */
#define PI_QUEUE_SIZE 256 /* You must specify this before you create the PI manager */
/* unfortunately, you don't know how many you really need. */
/* Go for a large number. It's a small amount for each */
static OSMesg PiMessages[PI_QUEUE_SIZE];
static OSMesgQueue PiMessageQ;
/**** Scheduler globals ****/
OSSched sc;
OSMesgQueue *sched_cmdQ;
u64 scheduleStack[OS_SC_STACKSIZE/8];
OSMesgQueue gfxFrameMsgQ;
OSMesg gfxFrameMsgBuf[8];
#define SCHEDULER_PRIORITY 10
#define NUM_FIELDS 1
extern GFXInfo gInfo[];
boot(void)
{
osInitialize();
osCreateThread(&mainThread, 1, (void(*)(void *))mainproc, 0,
(u8*)mainThreadStack+STACKSIZE, 10);
osStartThread(&mainThread);
}
static void mainproc(char *argv)
{
osCreateThread(&gameThread, 3, (void(*)(void *))gameproc, argv,
(u8*)gameThreadStack+STACKSIZE, 10);
/* Initialize video */
osCreateViManager(OS_PRIORITY_VIMGR);
osViSetMode(&osViModeTable[OS_VI_NTSC_LAN1]);
/* Start PI Mgr for access to cartridge & GIO */
osCreatePiManager(OS_PRIORITY_PIMGR, &PiMessageQ, PiMessages,
PI_QUEUE_SIZE);
osCreateThread(&rmonThread, 0, rmonMain, (void *)0,
(u8*)rmonThreadStack+ RMON_STACKSIZE, OS_PRIORITY_RMON );
osStartThread(&rmonThread);
osStartThread(&gameThread);
/* Become the idle thread */
osSetIntMask( OS_IM_ALL );
osSetThreadPri( 0, 0 );
for (;;);
}
static void gameproc(char *argv)
{
u32 drawbuffer = 0;
u32 pendingGFX = 0;
OSScClient gfxClient;
GFXMsg *msg;
/* osSetErrorHandler((OSErrorHandler)__assert); */
osCreateScheduler(&sc, (void *)(scheduleStack + OS_SC_STACKSIZE/8),
SCHEDULER_PRIORITY, OS_VI_NTSC_LAN1, NUM_FIELDS);
sched_cmdQ = osScGetCmdQ(&sc);
osCreateMesgQueue(&gfxFrameMsgQ, gfxFrameMsgBuf, 8);
osCreateThread(&midiThread, 4, (void(*)(void *))midiproc, argv,
(u8*)midiThreadStack+STACKSIZE, 8);
osStartThread(&midiThread);
osScAddClient(&sc, &gfxClient, &gfxFrameMsgQ);
initGFX();
while(1)
{
osRecvMesg(&gfxFrameMsgQ, (OSMesg *)&msg, OS_MESG_BLOCK);
switch (msg->gen.type)
{
case (OS_SC_RETRACE_MSG):
/**** Create a new gfx task unless we already have 2 ****/
if (pendingGFX < 2)
{
createGfxTask(&gInfo[drawbuffer]);
pendingGFX++;
drawbuffer ^= 1; /* switch the drawbuffer */
}
break;
case (OS_SC_DONE_MSG):
pendingGFX--; /* decrement number of pending tasks */
break;
case (OS_SC_PRE_NMI_MSG): /* stop creation of graphics tasks */
pendingGFX += 2;
break;
}
}
}
#if 0
extern u32 messageCt;
extern char *messageSt;
void __assert(const char* expr, const char *file, int linenum)
{
messageCt = 200;
osSetThreadPri( 0, 2 );
messageSt = file;
while(1)
;
}
#endif