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