1 /*---------------------------------------------------------------------------*
2 Project: Dolphin GD library
3 File: GDBase.h
4
5 Copyright 2001 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Log: GDBase.h,v $
14 Revision 1.3 2006/03/20 11:22:57 hiratsu
15 Fixed unsafe macro.
16
17 Revision 1.2 2006/02/04 11:56:46 hashida
18 (none)
19
20 Revision 1.1.1.1 2005/05/12 02:41:07 yasuh-to
21 Ported from dolphin source tree.
22
23
24 4 2002/08/05 19:49 Hirose
25 Const type specifier support.
26
27 3 2001/09/19 3:28p Carl
28 Changed overflow checking in functions that alter the offset.
29
30 2 2001/09/12 3:56p Carl
31 Renamed some functions to make it clear which act on "current".
32 Added some new defines for command lengths.
33
34 1 2001/09/12 1:55p Carl
35 Initial revision of GD: Graphics Display List Library.
36
37 $NoKeywords: $
38 *---------------------------------------------------------------------------*/
39
40 #ifndef __GDBASE_H__
41 #define __GDBASE_H__
42
43 /*---------------------------------------------------------------------------*/
44 #include <revolution/types.h>
45 #include <revolution/gx/GXEnum.h>
46 #include <revolution/gx/GXCommandList.h>
47 /*---------------------------------------------------------------------------*/
48
49 #ifdef __cplusplus
50 extern "C" {
51 #endif
52
53 /*---------------------------------------------------------------------------*/
54
55 // Graphics Display-list object
56 //
57 // Note that no "end of data" marker is kept. If you modify the ptr
58 // and intend to later reset it to the end of data, you must keep track
59 // of that value prior to changing the ptr.
60 //
61 typedef struct _GDLObj {
62 u8 *start;
63 u32 length;
64 u8 *ptr;
65 u8 *top;
66 } GDLObj;
67
68 typedef void (*GDOverflowCallback)(void);
69
70 extern GDLObj *__GDCurrentDL;
71
72 /****************************************************************************/
73 /* Function Declarations */
74 /****************************************************************************/
75
76 // Initialize/get GDL object parameters.
77 void GDInitGDLObj(GDLObj *dl, void *start, u32 length);
78 static inline void *GDGetGDLObjStart(const GDLObj *dl);
79 static inline u32 GDGetGDLObjLength(const GDLObj *dl);
80 static inline void *GDGetGDLObjPointer(const GDLObj *dl);
81 static inline u32 GDGetGDLObjOffset(const GDLObj *dl); // For convenience
82
83 // Manipulate "current" GDL object.
84 static inline void GDSetCurrent(GDLObj *dl);
85 static inline GDLObj *GDGetCurrent();
86 static inline GXBool GDIsCurrent(const GDLObj *dl);
87
88 // This next series of functions all apply to the "current" GDL object.
89
90 // Makes sure current GDL is flushed out of cache (needed for HW-side only).
91 void GDFlushCurrToMem();
92
93 // Get the current offset of the write ptr within DL.
94 static inline u32 GDGetCurrOffset();
95
96 // Reposition the write ptr within current GDL.
97 static inline void GDSetCurrOffset(u32 offset);
98
99 // Move offset forward by delta for current GDL.
100 static inline void GDAdvCurrOffset(s32 delta);
101
102 // For cache-flushing purposes, return actual pointer (start + offset).
103 static inline void *GDGetCurrPointer();
104
105 // Convenience functions for getting current GDLObj parameters.
106 static inline void *GDGetCurrStart();
107 static inline u32 GDGetCurrLength();
108
109 // Pads current GDL out to 32B.
110 void GDPadCurr32();
111
112 // Overflow-related functions.
113 void GDSetOverflowCallback(GDOverflowCallback callback);
114
115 GDOverflowCallback GDGetOverflowCallback( void );
116
117 //----------------------------------------------------------------------------
118 // "Internal" Functions
119 //----------------------------------------------------------------------------
120
121 void GDOverflowed();
122 static inline void GDOverflowCheck(u32 size);
123
124 // Raw write-byte function: No overflow checking
125 static inline void __GDWrite(u8 data);
126
127 // Low-level functions for writing every kind of data
128 static inline void GDWrite_u8(u8 data);
129 static inline void GDWrite_s8(s8 data);
130 static inline void GDWrite_u16(u16 data);
131 static inline void GDWrite_s16(s16 data);
132 static inline void GDWrite_u32(u32 data);
133 static inline void GDWrite_s32(s32 data);
134 static inline void GDWrite_f32(f32 data);
135 static inline void GDWrite_u24(u32 data);
136
137 // Mid-level write functions for writing specific command structures
138 static inline void GDWriteBPCmd(u32 regval);
139 static inline void GDWriteCPCmd(u8 addr, u32 val);
140 static inline void GDWriteXFCmd(u16 addr, u32 val);
141 static inline void GDWriteXFCmdHdr(u16 addr, u8 len);
142 static inline void GDWriteXFIndxACmd(u16 addr, u8 len, u16 index);
143 static inline void GDWriteXFIndxBCmd(u16 addr, u8 len, u16 index);
144 static inline void GDWriteXFIndxCCmd(u16 addr, u8 len, u16 index);
145 static inline void GDWriteXFIndxDCmd(u16 addr, u8 len, u16 index);
146
147 /****************************************************************************/
148 /* Inline Function Definitions */
149 /****************************************************************************/
150
151 // "Get" (from object) functions
GDGetGDLObjStart(const GDLObj * dl)152 static inline void *GDGetGDLObjStart(const GDLObj *dl)
153 {
154 return (void *) dl->start;
155 }
156
GDGetGDLObjLength(const GDLObj * dl)157 static inline u32 GDGetGDLObjLength(const GDLObj *dl)
158 {
159 return dl->length;
160 }
161
GDGetGDLObjPointer(const GDLObj * dl)162 static inline void *GDGetGDLObjPointer(const GDLObj *dl)
163 {
164 return dl->ptr;
165 }
166
GDGetGDLObjOffset(const GDLObj * dl)167 static inline u32 GDGetGDLObjOffset(const GDLObj *dl)
168 {
169 return (u32) (dl->ptr - dl->start);
170 }
171
172 // Manipulate "current" DL buffer
GDSetCurrent(GDLObj * dl)173 static inline void GDSetCurrent(GDLObj *dl)
174 {
175 __GDCurrentDL = dl;
176 }
177
GDGetCurrent()178 static inline GDLObj *GDGetCurrent()
179 {
180 return __GDCurrentDL;
181 }
182
GDIsCurrent(const GDLObj * dl)183 static inline GXBool GDIsCurrent(const GDLObj *dl)
184 {
185 return (dl == __GDCurrentDL);
186 }
187
188 // Get the current offset of the write ptr within DL
GDGetCurrOffset()189 static inline u32 GDGetCurrOffset()
190 {
191 return (u32) (__GDCurrentDL->ptr - __GDCurrentDL->start);
192 }
193
194 // Reposition the write ptr within DL
GDSetCurrOffset(u32 offset)195 static inline void GDSetCurrOffset(u32 offset)
196 {
197 // Note: we do not check the validity of offset here.
198 // That is done only when you try to write data into the DL.
199 // You can change this if you find it necessary.
200 __GDCurrentDL->ptr = __GDCurrentDL->start + offset;
201 }
202
203 // Move offset forward by delta
GDAdvCurrOffset(s32 delta)204 static inline void GDAdvCurrOffset(s32 delta)
205 {
206 // Note: see the note in GDSetCurrOffset.
207 __GDCurrentDL->ptr += delta;
208 }
209
210 // For cache-flushing purposes, return actual pointer (start + offset)
GDGetCurrPointer()211 static inline void *GDGetCurrPointer()
212 {
213 return (void *) __GDCurrentDL->ptr;
214 }
215
216 // Convenience functions
GDGetCurrStart()217 static inline void *GDGetCurrStart()
218 {
219 return (void *) __GDCurrentDL->start;
220 }
221
GDGetCurrLength()222 static inline u32 GDGetCurrLength()
223 {
224 return __GDCurrentDL->length;
225 }
226
227 // Overflow check
GDOverflowCheck(u32 size)228 static inline void GDOverflowCheck(u32 size)
229 {
230 if (__GDCurrentDL->ptr + size > __GDCurrentDL->top)
231 {
232 GDOverflowed();
233 }
234 }
235
236 // Raw write-byte function: No overflow checking
__GDWrite(u8 data)237 static inline void __GDWrite(u8 data)
238 {
239 *__GDCurrentDL->ptr++ = data;
240 }
241
242 // Low-level functions for writing every kind of data
243 //----------------------------------------------------------------------------
244
GDWrite_u8(u8 data)245 static inline void GDWrite_u8(u8 data)
246 {
247 GDOverflowCheck(1);
248 __GDWrite(data);
249 }
250
GDWrite_s8(s8 data)251 static inline void GDWrite_s8(s8 data)
252 {
253 GDWrite_u8((u8) data);
254 }
255
GDWrite_u16(u16 data)256 static inline void GDWrite_u16(u16 data)
257 {
258 GDOverflowCheck(2);
259 __GDWrite((u8) (data >> 8));
260 __GDWrite((u8) (data & 0xff));
261 }
262
GDWrite_s16(s16 data)263 static inline void GDWrite_s16(s16 data)
264 {
265 GDWrite_u16((u16) data);
266 }
267
GDWrite_u32(u32 data)268 static inline void GDWrite_u32(u32 data)
269 {
270 GDOverflowCheck(4);
271 __GDWrite((u8) ((data >> 24) & 0xff));
272 __GDWrite((u8) ((data >> 16) & 0xff));
273 __GDWrite((u8) ((data >> 8) & 0xff));
274 __GDWrite((u8) ((data >> 0) & 0xff));
275 }
276
GDWrite_s32(s32 data)277 static inline void GDWrite_s32(s32 data)
278 {
279 GDWrite_u32((u32) data);
280 }
281
GDWrite_f32(f32 data)282 static inline void GDWrite_f32(f32 data)
283 {
284 typedef union {
285 f32 f;
286 u32 u;
287 } _FloatInt;
288
289 _FloatInt fid;
290
291 fid.f = data;
292
293 GDWrite_u32(fid.u);
294 }
295
GDWrite_u24(u32 data)296 static inline void GDWrite_u24(u32 data)
297 {
298 GDOverflowCheck(3);
299 __GDWrite((u8) ((data >> 16) & 0xff));
300 __GDWrite((u8) ((data >> 8) & 0xff));
301 __GDWrite((u8) ((data >> 0) & 0xff));
302 }
303
304 // Mid-level write functions for writing specific command structures
305 //----------------------------------------------------------------------------
306
307 // This is for sending BP (raster state) commands.
308 // All BP commands have the form:
309 //
310 // | 8 bits | 8 bits | 24 bits |
311 // | cmd. token | reg. addr. | reg. value |
312 //
313 // We combine the register address and value together into a single u32 value.
314
GDWriteBPCmd(u32 regval)315 static inline void GDWriteBPCmd(u32 regval)
316 {
317 GDWrite_u8(GX_LOAD_BP_REG);
318 GDWrite_u32(regval);
319 }
320
321 // This is for sending CP (command processor) commands.
322 // All CP commands have the form:
323 //
324 // | 8 bits | 8 bits | 32 bits |
325 // | cmd. token | reg. addr. | reg. value |
326 //
327 // CP has a different register address space than BP or XF.
328
GDWriteCPCmd(u8 addr,u32 val)329 static inline void GDWriteCPCmd(u8 addr, u32 val)
330 {
331 GDWrite_u8(GX_LOAD_CP_REG);
332 GDWrite_u8(addr);
333 GDWrite_u32(val);
334 }
335
336 // This is for sending immediate XF (transform unit) commands.
337 // All immediate XF commands have the form:
338 //
339 // | 8 bits | 16 bits | 16 bits | 32 bits * length |
340 // | cmd. token | length - 1 | 1st addr. | reg. value(s) |
341 //
342 // Length (the number of values being sent) can be up to 16 only.
343 //
344 // XF has a different register address space than BP or CP.
345
GDWriteXFCmd(u16 addr,u32 val)346 static inline void GDWriteXFCmd(u16 addr, u32 val)
347 {
348 GDWrite_u8(GX_LOAD_XF_REG);
349 GDWrite_u16(0); // 0 means one value follows
350 GDWrite_u16(addr);
351 GDWrite_u32(val);
352 }
353
354 // When using this function, follow it with (len) 32-bit writes.
GDWriteXFCmdHdr(u16 addr,u8 len)355 static inline void GDWriteXFCmdHdr(u16 addr, u8 len)
356 {
357 GDWrite_u8(GX_LOAD_XF_REG);
358 GDWrite_u16((u16) ((len) - 1));
359 GDWrite_u16(addr);
360 }
361
362 // This is used internally below for XF indexed load commands:
363 #define __XFAddrLen(addr, len) ((u16) (((len) << 12) | (addr)))
364
365 // This is for sending indexed XF (transform unit) commands.
366 // There are 4 different XF index units, which are typically used as follows:
367 // A: pos. mtx's B: nrm. mtx's C: tex. mtx's D: light obj's.
368 // All indexed XF commands have the form:
369 //
370 // | 8 bits | 16 bits | 4 bits | 12 bits |
371 // | cmd. token | index value | length - 1 | 1st addr. |
372 //
373 // Length (the number of values being sent) can be up to 16 only.
374 //
375 // XF has a different register address space than BP or CP.
376
GDWriteXFIndxACmd(u16 addr,u8 len,u16 index)377 static inline void GDWriteXFIndxACmd(u16 addr, u8 len, u16 index)
378 {
379 GDWrite_u8(GX_LOAD_INDX_A);
380 GDWrite_u16(index);
381 GDWrite_u16(__XFAddrLen((addr), ((len)-1)) );
382 }
383
GDWriteXFIndxBCmd(u16 addr,u8 len,u16 index)384 static inline void GDWriteXFIndxBCmd(u16 addr, u8 len, u16 index)
385 {
386 GDWrite_u8(GX_LOAD_INDX_B);
387 GDWrite_u16(index);
388 GDWrite_u16(__XFAddrLen((addr), ((len)-1)) );
389 }
390
GDWriteXFIndxCCmd(u16 addr,u8 len,u16 index)391 static inline void GDWriteXFIndxCCmd(u16 addr, u8 len, u16 index)
392 {
393 GDWrite_u8(GX_LOAD_INDX_C);
394 GDWrite_u16(index);
395 GDWrite_u16(__XFAddrLen((addr), ((len)-1)) );
396 }
397
GDWriteXFIndxDCmd(u16 addr,u8 len,u16 index)398 static inline void GDWriteXFIndxDCmd(u16 addr, u8 len, u16 index)
399 {
400 GDWrite_u8(GX_LOAD_INDX_D);
401 GDWrite_u16(index);
402 GDWrite_u16(__XFAddrLen((addr), ((len)-1)) );
403 }
404
405 /*---------------------------------------------------------------------------*/
406
407 // This is the BP mask register that may be used to limit which bits
408 // of a BP register get written to. It only affects the very next BP
409 // command that follows it (the mask automatically resets). It is sent
410 // down as a BP command itself: GDWriteBPCmd(SS_MASK(mask));
411
412 #define SS_MASK(mask) ((u32)((0xfe << 24) | (mask)))
413
414 // These defines are intended to help make patching more clear.
415 // The CMD_LENGTH describes the total length of each basic command type.
416 // (For XF commands, this only applies to commands where length = 1.)
417 // The DATA_OFFSET describes the number of bytes to skip from the start
418 // of the command until you reach the actual register data value.
419 // The DATA_LENGTH describes how many bytes long the register data value is.
420 // In the case of XF commands, this is the minimum multiple (length = 1).
421
422 #define BP_CMD_LENGTH 5
423 #define BP_DATA_OFFSET 2
424 #define BP_DATA_LENGTH 3
425
426 #define CP_CMD_LENGTH 6
427 #define CP_DATA_OFFSET 2
428 #define CP_DATA_LENGTH 4
429
430 #define XF_CMD_LENGTH 9
431 #define XF_DATA_OFFSET 5
432 #define XF_DATA_LENGTH 4
433
434 // For XF indexed commands, we describe the index field offset & length.
435
436 #define XF_INDX_CMD_LENGTH 5
437 #define XF_INDX_OFFSET 1
438 #define XF_INDX_LENGTH 2
439
440 /*---------------------------------------------------------------------------*/
441 #ifdef __cplusplus
442 }
443 #endif
444
445 /*---------------------------------------------------------------------------*/
446
447 #endif // __GDBASE_H__
448