summaryrefslogtreecommitdiff
path: root/include/dolphin/gd/GDBase.h
blob: 313a2dc488ef41c818c8454a25627fdb7f9bbfed (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
138
139
140
141
142
143
144
145
146
#ifndef GDBASE_H
#define GDBASE_H

#include "dolphin/gx/GXAttr.h"
#include "dolphin/types.h"

#ifdef __cplusplus
extern "C" {
#endif

#define GX_LOAD_CP_REG         0x08
#define GX_LOAD_XF_REG         0x10
#define GX_LOAD_INDX_A         0x20
#define GX_LOAD_INDX_B         0x28
#define GX_LOAD_INDX_C         0x30
#define GX_LOAD_INDX_D         0x38
#define GX_LOAD_BP_REG         0x61

typedef struct _GDLObj {
    /* 0x0 */ u8* start;
    /* 0x4 */ u32 length;
    /* 0x8 */ u8* ptr;
    /* 0xC */ u8* top;
} GDLObj;  // Size: 0x10

extern GDLObj* __GDCurrentDL;

typedef void (*GDOverflowCallback)(void);

void GDInitGDLObj(GDLObj*, void*, u32);
void GDFlushCurrToMem(void);
void GDPadCurr32(void);
void GDOverflowed(void);
void GDSetVtxDescv(GXVtxDescList*);

inline void __GDWrite(u8 data) {
    *__GDCurrentDL->ptr++ = data;
}

inline void GDSetCurrent(GDLObj* obj) {
    __GDCurrentDL = obj;
}

inline u32 GDGetGDLObjOffset(GDLObj* obj) {
    return (u32)(obj->ptr - obj->start);
}

inline u8* GDGetCurrPointer() {
    return __GDCurrentDL->ptr;
}

inline s32 GDGetCurrOffset() {
    return __GDCurrentDL->ptr - __GDCurrentDL->start;
}

inline void GDSetCurrOffset(s32 offs) {
    __GDCurrentDL->ptr = __GDCurrentDL->start + offs;
}

inline void GDAdvCurrOffset(s32 offs) {
    __GDCurrentDL->ptr += offs;
}

/* Unused
inline GDLObj* GDGetCurrent() {
    return __GDCurrentDL;
} */

inline void GDOverflowCheck(u32 len) {
    if (__GDCurrentDL->ptr + len > __GDCurrentDL->top) {
        GDOverflowed();
    }
}

inline void GDWrite_u32(u32 v) {
    GDOverflowCheck(4);
    __GDWrite((v >> 24) & 0xff);
    __GDWrite((v >> 16) & 0xff);
    __GDWrite((v >> 8) & 0xff);
    __GDWrite((v >> 0) & 0xff);
}

inline void GDWrite_u16(u16 v) {
    GDOverflowCheck(2);
    __GDWrite(v >> 8);
    __GDWrite(v & 0xff);
}

inline void GDWrite_u8(u8 v) {
    GDOverflowCheck(1);
    __GDWrite(v);
}

inline static void GDWriteXFCmdHdr(u16 addr, u8 len) {
    GDWrite_u8(GX_LOAD_XF_REG);
    GDWrite_u16(len - 1);
    GDWrite_u16(addr);
}

inline static void GDWriteXFCmd(u16 addr, u32 val) {
    GDWrite_u8(GX_LOAD_XF_REG);
    GDWrite_u16(0);
    GDWrite_u16(addr);
    GDWrite_u32(val);
}

inline static void GDWriteXFIndxDCmd(u16 addr, u8 len, u16 index) {
    GDWrite_u8(GX_LOAD_INDX_D);
    GDWrite_u16(index);
    GDWrite_u16((len - 1) << 12 | addr);
}

inline static void GDWriteXFIndxACmd(u16 addr, u8 len, u16 index) {
    GDWrite_u8(GX_LOAD_INDX_A);
    GDWrite_u16(index);
    GDWrite_u16(((len - 1) << 12) | addr);
}

inline static void GDWriteXFIndxBCmd(u16 addr, u8 len, u16 index) {
    GDWrite_u8(GX_LOAD_INDX_B);
    GDWrite_u16(index);
    GDWrite_u16(((len - 1) << 12) | addr);
}

inline static void GDWriteXFIndxCCmd(u16 addr, u8 len, u16 index) {
    GDWrite_u8(GX_LOAD_INDX_C);
    GDWrite_u16(index);
    GDWrite_u16(((len - 1) << 12) | addr);
}

inline static void GDWriteCPCmd(u8 addr, u32 val) {
    GDWrite_u8(GX_LOAD_CP_REG);
    GDWrite_u8(addr);
    GDWrite_u32(val);
}

inline static void GDWriteBPCmd(u32 regval) {
    GDWrite_u8(GX_LOAD_BP_REG);
    GDWrite_u32(regval);
}

#ifdef __cplusplus
};
#endif

#endif /* GDBASE_H */