d07c171f |
1 | /* |
2 | Copyright (C) 2002 Rice1964 |
3 | |
4 | This program is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU General Public License |
6 | as published by the Free Software Foundation; either version 2 |
7 | of the License, or (at your option) any later version. |
8 | |
9 | This program is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | GNU General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU General Public License |
15 | along with this program; if not, write to the Free Software |
16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
17 | |
18 | */ |
19 | |
20 | |
21 | // This file implements the S2DEX ucode, Yoshi story is using this ucodes |
22 | |
23 | #include "UcodeDefs.h" |
24 | #include "Render.h" |
25 | #include "Timing.h" |
26 | |
27 | uObjTxtr *gObjTxtr = NULL; |
28 | uObjTxtrTLUT *gObjTlut = NULL; |
29 | uint32 gObjTlutAddr = 0; |
30 | uObjMtx *gObjMtx = NULL; |
31 | uObjSubMtx *gSubObjMtx = NULL; |
32 | uObjMtxReal gObjMtxReal = {1, 0, 0, 1, 0, 0, 0, 0}; |
33 | Matrix g_MtxReal(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1); |
34 | |
35 | uint32 g_TxtLoadBy = CMD_LOAD_OBJ_TXTR; |
36 | |
37 | |
38 | // Yoshi's Story uses this - 0x02 |
39 | void RSP_S2DEX_BG_COPY(Gfx *gfx) |
40 | { |
41 | SP_Timing(DP_Minimal16); |
42 | DP_Timing(DP_Minimal16); |
43 | |
44 | uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); |
45 | uObjBg *sbgPtr = (uObjBg*)(g_pRDRAMu8+dwAddr); |
46 | CRender::g_pRender->LoadObjBGCopy(*sbgPtr); |
47 | CRender::g_pRender->DrawObjBGCopy(*sbgPtr); |
48 | } |
49 | |
50 | // Yoshi's Story uses this - 0x03 |
51 | void RSP_S2DEX_OBJ_RECTANGLE(Gfx *gfx) |
52 | { |
53 | uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); |
54 | uObjSprite *ptr = (uObjSprite*)(g_pRDRAMu8+dwAddr); |
55 | |
56 | uObjTxSprite objtx; |
57 | memcpy(&objtx.sprite,ptr,sizeof(uObjSprite)); |
58 | |
59 | if( g_TxtLoadBy == CMD_LOAD_OBJ_TXTR ) |
60 | { |
61 | memcpy(&(objtx.txtr.block),&(gObjTxtr->block),sizeof(uObjTxtr)); |
62 | CRender::g_pRender->LoadObjSprite(objtx,true); |
63 | } |
64 | else |
65 | { |
66 | PrepareTextures(); |
67 | } |
68 | CRender::g_pRender->DrawSprite(objtx, false); |
69 | //printf("*SEB* at RSP_S2DEX_OBJ_RECTANGLE\nptr=%08X, img=%08X, Tmem=%08X", dwAddr,objtx.txtr.block.image, ptr->imageAdrs); |
70 | |
71 | #ifdef DEBUGGER |
72 | if( (pauseAtNext && (eventToPause == NEXT_OBJ_TXT_CMD||eventToPause == NEXT_FLUSH_TRI)) || logTextures ) |
73 | { |
74 | if( debuggerPauseCount > 0 ) |
75 | debuggerPauseCount--; |
76 | if( debuggerPauseCount == 0 ) |
77 | { |
78 | eventToPause = false; |
79 | debuggerPause = true; |
80 | TRACE3("Paused at RSP_S2DEX_OBJ_RECTANGLE\nptr=%08X, img=%08X, Tmem=%08X\n", |
81 | dwAddr,objtx.txtr.block.image, ptr->imageAdrs); |
82 | CGraphicsContext::g_pGraphicsContext->UpdateFrame(); |
83 | } |
84 | } |
85 | #endif |
86 | } |
87 | |
88 | // Yoshi's Story uses this - 0x04 |
89 | void RSP_S2DEX_OBJ_SPRITE(Gfx *gfx) |
90 | { |
91 | uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); |
92 | uObjSprite *info = (uObjSprite*)(g_pRDRAMu8+dwAddr); |
93 | |
94 | uint32 dwTile = gRSP.curTile; |
95 | status.bAllowLoadFromTMEM = false; // Because we need to use TLUT loaded by ObjTlut cmd |
96 | PrepareTextures(); |
97 | status.bAllowLoadFromTMEM = true; |
98 | |
99 | //CRender::g_pRender->SetCombinerAndBlender(); |
100 | |
101 | uObjTxSprite drawinfo; |
102 | memcpy( &(drawinfo.sprite), info, sizeof(uObjSprite)); |
103 | //printf("*SEB* at RSP_S2DEX_OBJ_SPRITE size=%ix%i\n",drawinfo.sprite.imageW/32, drawinfo.sprite.imageH/32); |
104 | CRender::g_pRender->DrawSpriteR(drawinfo, false, dwTile, 0, 0, drawinfo.sprite.imageW/32, drawinfo.sprite.imageH/32); |
105 | |
106 | |
107 | /* |
108 | static BOOL bWarned = FALSE; |
109 | //if (!bWarned) |
110 | { |
111 | RSP_RDP_NOIMPL("RDP: RSP_S2DEX_OBJ_SPRITE (0x%08x 0x%08x)", (gfx->words.w0), (gfx->words.w1)); |
112 | bWarned = TRUE; |
113 | } |
114 | */ |
115 | |
116 | #ifdef DEBUGGER |
117 | if( (pauseAtNext && (eventToPause == NEXT_OBJ_TXT_CMD||eventToPause == NEXT_FLUSH_TRI)) || logTextures ) |
118 | { |
119 | eventToPause = false; |
120 | debuggerPause = true; |
121 | TRACE0("Paused at RSP_S2DEX_OBJ_SPRITE"); |
122 | CGraphicsContext::g_pGraphicsContext->UpdateFrame(); |
123 | } |
124 | #endif |
125 | } |
126 | |
127 | // Yoshi's Story uses this - 0xb0 |
128 | void RSP_S2DEX_SELECT_DL(Gfx *gfx) |
129 | { |
130 | //static BOOL bWarned = FALSE; |
131 | //if (!bWarned) |
132 | { |
133 | RSP_RDP_NOIMPL("RDP: RSP_S2DEX_SELECT_DL (0x%08x 0x%08x)", (gfx->words.w0), (gfx->words.w1)); |
134 | //bWarned = TRUE; |
135 | } |
136 | |
137 | DEBUGGER_PAUSE_AND_DUMP_COUNT_N(NEXT_OBJ_TXT_CMD, {DebuggerAppendMsg("Paused at RSP_S2DEX_SELECT_DL");}); |
138 | } |
139 | |
140 | void RSP_S2DEX_OBJ_RENDERMODE(Gfx *gfx) |
141 | { |
142 | /* |
143 | static BOOL bWarned = FALSE; |
144 | //if (!bWarned) |
145 | { |
146 | RSP_RDP_NOIMPL("RDP: RSP_S2DEX_OBJ_RENDERMODE (0x%08x 0x%08x)", (gfx->words.w0), (gfx->words.w1)); |
147 | bWarned = TRUE; |
148 | } |
149 | */ |
150 | } |
151 | |
152 | // Yoshi's Story uses this - 0xb1 |
153 | void RSP_GBI1_Tri2(Gfx *gfx); |
154 | void RSP_S2DEX_OBJ_RENDERMODE_2(Gfx *gfx) |
155 | { |
156 | if( ((gfx->words.w0)&0xFFFFFF) != 0 || ((gfx->words.w1)&0xFFFFFF00) != 0 ) |
157 | { |
158 | // This is a TRI2 cmd |
159 | RSP_GBI1_Tri2(gfx); |
160 | return; |
161 | } |
162 | |
163 | RSP_S2DEX_OBJ_RENDERMODE(gfx); |
164 | } |
165 | |
166 | #ifdef DEBUGGER |
167 | void DumpBlockParameters(uObjTxtrBlock &ptr) |
168 | { |
169 | /* |
170 | typedef struct { //Intel format |
171 | uint32 type; // S2DEX_OBJLT_TXTRBLOCK divided into types. |
172 | uint64 *image; // The texture source address on DRAM. |
173 | |
174 | uint16 tsize; // The Texture size. Specified by the macro GS_TB_TSIZE(). |
175 | uint16 tmem; // The transferred TMEM word address. (8byteWORD) |
176 | |
177 | uint16 sid; // STATE ID Multipled by 4. Either one of 0,4,8 and 12. |
178 | uint16 tline; // The width of the Texture 1-line. Specified by the macro GS_TB_TLINE() |
179 | |
180 | uint32 flag; // STATE flag |
181 | uint32 mask; // STATE mask |
182 | } uObjTxtrBlock; // 24 bytes |
183 | */ |
184 | |
185 | DebuggerAppendMsg("uObjTxtrBlock Header in RDRAM: 0x%08X", (uint32) ((char *) &ptr - (char *) g_pRDRAMu8)); |
186 | DebuggerAppendMsg("ImgAddr=0x%08X(0x%08X), tsize=0x%X, \nTMEM=0x%X, sid=%d, tline=%d, flag=0x%X, mask=0x%X\n\n", |
187 | RSPSegmentAddr(ptr.image), ptr.image, ptr.tsize, ptr.tmem, ptr.sid/4, ptr.tline, ptr.flag, ptr.mask); |
188 | } |
189 | |
190 | void DumpSpriteParameters(uObjSprite &ptr) |
191 | { |
192 | /* |
193 | typedef struct { // Intel format |
194 | uint16 scaleW; // Scaling of the u5.10 width direction. |
195 | short objX; // The x-coordinate of the upper-left end. s10.2 OBJ |
196 | |
197 | uint16 paddingX; // Unused. Always 0. |
198 | uint16 imageW; // The width of the u10.5 texture. (The length of the S-direction.) |
199 | |
200 | uint16 scaleH; // Scaling of the u5.10 height direction. |
201 | short objY; // The y-coordinate of the s10.2 OBJ upper-left end. |
202 | |
203 | uint16 paddingY; // Unused. Always 0. |
204 | uint16 imageH; // The height of the u10.5 texture. (The length of the T-direction.) |
205 | |
206 | uint16 imageAdrs; // The texture header position in TMEM. (In units of 64bit word.) |
207 | uint16 imageStride; // The folding width of the texel. (In units of 64bit word.) |
208 | |
209 | uint8 imageFlags; // The display flag. S2DEX_OBJ_FLAG_FLIP* |
210 | uint8 imagePal; //The pallet number. 0-7 |
211 | uint8 imageSiz; // The size of the texel. TXT_SIZE_* |
212 | uint8 imageFmt; // The format of the texel. TXT_FMT_* |
213 | } uObjSprite; // 24 bytes |
214 | */ |
215 | |
216 | if( logTextures || (pauseAtNext && eventToPause == NEXT_OBJ_TXT_CMD) ) |
217 | { |
218 | DebuggerAppendMsg("uObjSprite Header in RDRAM: 0x%08X", (uint32) ((char *) &ptr - (char *) g_pRDRAMu8)); |
219 | DebuggerAppendMsg("X=%d, Y=%d, W=%d, H=%d, scaleW=%f, scaleH=%f\n" |
220 | "TAddr=0x%X, Stride=%d, Flag=0x%X, Pal=%d, Fmt=%s-%db\n\n", |
221 | ptr.objX/4, ptr.objY/4, ptr.imageW/32, ptr.imageH/32, ptr.scaleW/1024.0f, ptr.scaleH/1024.0f, |
222 | ptr.imageAdrs, ptr.imageStride, ptr.imageFlags, ptr.imagePal, pszImgFormat[ptr.imageFmt], pnImgSize[ptr.imageSiz]); |
223 | } |
224 | } |
225 | |
226 | void DumpTileParameters(uObjTxtrTile &tile) |
227 | { |
228 | } |
229 | |
230 | void DumpTlutParameters(uObjTxtrTLUT &tlut) |
231 | { |
232 | /* |
233 | typedef struct { // Intel Format |
234 | uint32 type; // S2DEX_OBJLT_TLUT divided into types. |
235 | uint32 image; |
236 | |
237 | uint16 pnum; // The loading pallet number -1. |
238 | uint16 phead; // The pallet number of the load header. Between 256 and 511. |
239 | |
240 | uint16 sid; // STATE ID Multiplied by 4. Either one of 0,4,8 and 12. |
241 | uint16 zero; // Assign 0 all the time. |
242 | |
243 | uint32 flag; // STATE flag |
244 | uint32 mask; // STATE mask |
245 | } uObjTxtrTLUT; // 24 bytes |
246 | */ |
247 | DebuggerAppendMsg("ImgAddr=0x%08X(0x%08X), pnum=%d, phead=%d, sid=%d, flag=0x%X, mask=0x%X\n\n", |
248 | RSPSegmentAddr(tlut.image), tlut.image, tlut.pnum+1, tlut.phead, tlut.sid/4, tlut.flag, tlut.mask); |
249 | } |
250 | |
251 | |
252 | void DumpTxtrInfo(uObjTxtr *ptr) |
253 | { |
254 | if( logTextures || (pauseAtNext && eventToPause == NEXT_OBJ_TXT_CMD) ) |
255 | { |
256 | DebuggerAppendMsg("uObjTxtr Header in RDRAM: 0x%08X", (uint32) ((char *) ptr - (char *) g_pRDRAMu8)); |
257 | switch( ptr->block.type ) |
258 | { |
259 | case S2DEX_OBJLT_TXTRBLOCK: |
260 | TRACE0("Loading ObjTxtr: type=BLOCK"); |
261 | DumpBlockParameters(ptr->block); |
262 | break; |
263 | case S2DEX_OBJLT_TXTRTILE: |
264 | TRACE0("Loading ObjTxtr: type=TILE"); |
265 | DumpTileParameters(ptr->tile); |
266 | break; |
267 | case S2DEX_OBJLT_TLUT: |
268 | TRACE0("Loading ObjTxtr: type=TLUT"); |
269 | DumpTlutParameters(ptr->tlut); |
270 | break; |
271 | } |
272 | } |
273 | } |
274 | |
275 | void DumpObjMtx(bool fullmtx = true) |
276 | { |
277 | if( logTextures || (pauseAtNext && eventToPause == NEXT_OBJ_TXT_CMD) ) |
278 | { |
279 | if( fullmtx ) |
280 | DebuggerAppendMsg("A=%X, B=%X, C=%X, D=%X, X=%X, Y=%X, BaseX=%X, BaseY=%X", |
281 | gObjMtx->A, gObjMtx->B, gObjMtx->C, gObjMtx->D, gObjMtx->X, gObjMtx->Y, gObjMtx->BaseScaleX, gObjMtx->BaseScaleY); |
282 | else |
283 | DebuggerAppendMsg("SubMatrix: X=%X, Y=%X, BaseX=%X, BaseY=%X", gSubObjMtx->X, gSubObjMtx->Y, gSubObjMtx->BaseScaleX, gSubObjMtx->BaseScaleY); |
284 | |
285 | DebuggerAppendMsg("A=%f, B=%f, C=%f, D=%f, X=%f, Y=%f, BaseX=%f, BaseY=%f", |
286 | gObjMtxReal.A, gObjMtxReal.B, gObjMtxReal.C, gObjMtxReal.D, gObjMtxReal.X, gObjMtxReal.Y, gObjMtxReal.BaseScaleX, gObjMtxReal.BaseScaleY); |
287 | } |
288 | } |
289 | |
290 | #endif |
291 | |
292 | void ObjMtxTranslate(float &x, float &y) |
293 | { |
294 | float x1 = gObjMtxReal.A*x + gObjMtxReal.B*y + gObjMtxReal.X; |
295 | float y1 = gObjMtxReal.C*x + gObjMtxReal.D*y + gObjMtxReal.Y; |
296 | |
297 | x = x1; |
298 | y = y1; |
299 | } |
300 | |
301 | void RSP_S2DEX_SPObjLoadTxtr(Gfx *gfx) |
302 | { |
303 | gObjTxtr = (uObjTxtr*)(g_pRDRAMu8+(RSPSegmentAddr((gfx->words.w1))&(g_dwRamSize-1))); |
304 | if( gObjTxtr->block.type == S2DEX_OBJLT_TLUT ) |
305 | { |
306 | gObjTlut = (uObjTxtrTLUT*)gObjTxtr; |
307 | gObjTlutAddr = (uint32)(RSPSegmentAddr(gObjTlut->image)); |
308 | |
309 | // Copy tlut |
310 | int size = gObjTlut->pnum+1; |
311 | int offset = gObjTlut->phead-0x100; |
312 | |
313 | if( offset+size>0x100) |
314 | { |
315 | size = 0x100 - offset; |
316 | } |
317 | |
318 | uint32 addr = (gObjTlutAddr);//&0xFFFFFFFC); |
319 | //if( addr & 3 ) addr = (addr&0xFFFFFFF0)+8;; |
320 | //uint16 *srcPal = (uint16*)(g_pRDRAMu8 + (addr& (g_dwRamSize-1)) ); |
321 | |
322 | for( int i=offset; i<offset+size; i++ ) |
323 | { |
324 | g_wRDPTlut[i^1] = RDRAM_UHALF(addr); |
325 | addr += 2; |
326 | //g_wRDPTlut[i] = (*(uint16 *)(addr+g_pRDRAMu8)); |
327 | //g_wRDPTlut[i] = *(srcPal++); |
328 | } |
329 | } |
330 | else |
331 | { |
332 | // Loading ObjSprite |
333 | g_TxtLoadBy = CMD_LOAD_OBJ_TXTR; |
334 | } |
335 | |
336 | DEBUGGER_PAUSE_AT_COND_AND_DUMP_COUNT_N((eventToPause == NEXT_OBJ_TXT_CMD||eventToPause == NEXT_FLUSH_TRI), |
337 | { |
338 | DumpTxtrInfo(gObjTxtr); |
339 | TRACE0("Paused at RSP_S2DEX_SPObjLoadTxtr"); |
340 | } |
341 | ); |
342 | } |
343 | |
344 | // Yoshi's Story uses this - 0xc2 |
345 | void RSP_S2DEX_SPObjLoadTxSprite(Gfx *gfx) |
346 | { |
347 | uObjTxSprite* ptr = (uObjTxSprite*)(g_pRDRAMu8+(RSPSegmentAddr((gfx->words.w1))&(g_dwRamSize-1))); |
348 | gObjTxtr = (uObjTxtr*)ptr; |
349 | |
350 | //Now draw the sprite |
351 | //printf("*SEB* at RSP_S2DEX_SPObjLoadTxSprite\n"); // used on intro, gives just white rectangles |
352 | CRender::g_pRender->LoadObjSprite(*ptr); |
353 | CRender::g_pRender->DrawSpriteR(*ptr); |
354 | |
355 | DEBUGGER_PAUSE_AT_COND_AND_DUMP_COUNT_N((eventToPause == NEXT_OBJ_TXT_CMD||eventToPause == NEXT_FLUSH_TRI), |
356 | { |
357 | DumpTxtrInfo(gObjTxtr); |
358 | DumpSpriteParameters(ptr->sprite); |
359 | TRACE0("Paused at RSP_S2DEX_SPObjLoadTxSprite"); |
360 | } |
361 | ); |
362 | } |
363 | |
364 | |
365 | // Yoshi's Story uses this - 0xc3 |
366 | void RSP_S2DEX_SPObjLoadTxRect(Gfx *gfx) |
367 | { |
368 | |
369 | |
370 | |
371 | uObjTxSprite* ptr = (uObjTxSprite*)(g_pRDRAMu8+(RSPSegmentAddr((gfx->words.w1))&(g_dwRamSize-1))); |
372 | gObjTxtr = (uObjTxtr*)ptr; |
373 | |
374 | //Now draw the sprite |
375 | CRender::g_pRender->LoadObjSprite(*ptr); |
376 | CRender::g_pRender->DrawSprite(*ptr, false); |
377 | |
378 | DEBUGGER_PAUSE_AT_COND_AND_DUMP_COUNT_N((eventToPause == NEXT_OBJ_TXT_CMD||eventToPause == NEXT_FLUSH_TRI), |
379 | { |
380 | DumpTxtrInfo(gObjTxtr); |
381 | DumpSpriteParameters(ptr->sprite); |
382 | TRACE0("Paused at RSP_S2DEX_SPObjLoadTxRect"); |
383 | } |
384 | ); |
385 | } |
386 | |
387 | // Yoshi's Story uses this - 0xc4 |
388 | void RSP_S2DEX_SPObjLoadTxRectR(Gfx *gfx) |
389 | { |
390 | uObjTxSprite* ptr = (uObjTxSprite*)(g_pRDRAMu8+(RSPSegmentAddr((gfx->words.w1))&(g_dwRamSize-1))); |
391 | gObjTxtr = (uObjTxtr*)ptr; |
392 | |
393 | //Now draw the sprite |
394 | CRender::g_pRender->LoadObjSprite(*ptr); |
395 | CRender::g_pRender->DrawSprite(*ptr, true); |
396 | |
397 | DEBUGGER_PAUSE_AT_COND_AND_DUMP_COUNT_N((eventToPause == NEXT_OBJ_TXT_CMD||eventToPause == NEXT_FLUSH_TRI), |
398 | { |
399 | DumpTxtrInfo(gObjTxtr); |
400 | DumpSpriteParameters(ptr->sprite); |
401 | TRACE0("Paused at RSP_S2DEX_SPObjLoadTxRect"); |
402 | } |
403 | ); |
404 | } |
405 | |
406 | void DLParser_TexRect(Gfx *gfx); |
407 | // Yoshi's Story uses this - 0xe4 |
408 | void RSP_S2DEX_RDPHALF_0(Gfx *gfx) |
409 | { |
410 | //RDP: RSP_S2DEX_RDPHALF_0 (0xe449c0a8 0x003b40a4) |
411 | //0x001d3c88: e449c0a8 003b40a4 RDP_TEXRECT |
412 | //0x001d3c90: b4000000 00000000 RSP_RDPHALF_1 |
413 | //0x001d3c98: b3000000 04000400 RSP_RDPHALF_2 |
414 | |
415 | uint32 dwPC = gDlistStack[gDlistStackPointer].pc; // This points to the next instruction |
416 | uint32 dwNextUcode = *(uint32 *)(g_pRDRAMu8 + dwPC); |
417 | |
418 | if( (dwNextUcode>>24) != S2DEX_SELECT_DL ) |
419 | { |
420 | // Pokemom Puzzle League |
421 | if( (dwNextUcode>>24) == 0xB4 ) |
422 | { |
423 | DLParser_TexRect(gfx); |
424 | } |
425 | else |
426 | { |
427 | RSP_RDP_NOIMPL("RDP: RSP_S2DEX_RDPHALF_0 (0x%08x 0x%08x)", (gfx->words.w0), (gfx->words.w1)); |
428 | } |
429 | } |
430 | else |
431 | { |
432 | RSP_RDP_NOIMPL("RDP: RSP_S2DEX_RDPHALF_0 (0x%08x 0x%08x)", (gfx->words.w0), (gfx->words.w1)); |
433 | DEBUGGER_PAUSE_COUNT_N(NEXT_OBJ_TXT_CMD); |
434 | } |
435 | } |
436 | |
437 | // Yoshi's Story uses this - 0x05 |
438 | void RSP_S2DEX_OBJ_MOVEMEM(Gfx *gfx) |
439 | { |
440 | uint32 dwCommand = ((gfx->words.w0)>>16)&0xFF; |
441 | uint32 dwLength = ((gfx->words.w0)) &0xFFFF; |
442 | uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); |
443 | |
444 | if( dwAddr >= g_dwRamSize ) |
445 | { |
446 | TRACE0("ObjMtx: memory ptr is invalid"); |
447 | } |
448 | |
449 | if( dwLength == 0 && dwCommand == 23 ) |
450 | { |
451 | gObjMtx = (uObjMtx *)(dwAddr+g_pRDRAMu8); |
452 | gObjMtxReal.A = gObjMtx->A/65536.0f; |
453 | gObjMtxReal.B = gObjMtx->B/65536.0f; |
454 | gObjMtxReal.C = gObjMtx->C/65536.0f; |
455 | gObjMtxReal.D = gObjMtx->D/65536.0f; |
456 | gObjMtxReal.X = float(gObjMtx->X>>2); |
457 | gObjMtxReal.Y = float(gObjMtx->Y>>2); |
458 | gObjMtxReal.BaseScaleX = gObjMtx->BaseScaleX/1024.0f; |
459 | gObjMtxReal.BaseScaleY = gObjMtx->BaseScaleY/1024.0f; |
460 | |
461 | #ifdef DEBUGGER |
462 | DumpObjMtx(); |
463 | #endif |
464 | } |
465 | else if( dwLength == 2 && dwCommand == 7 ) |
466 | { |
467 | gSubObjMtx = (uObjSubMtx*)(dwAddr+g_pRDRAMu8); |
468 | gObjMtxReal.X = float(gSubObjMtx->X>>2); |
469 | gObjMtxReal.Y = float(gSubObjMtx->Y>>2); |
470 | gObjMtxReal.BaseScaleX = gSubObjMtx->BaseScaleX/1024.0f; |
471 | gObjMtxReal.BaseScaleY = gSubObjMtx->BaseScaleY/1024.0f; |
472 | |
473 | #ifdef DEBUGGER |
474 | DumpObjMtx(false); |
475 | #endif |
476 | } |
477 | |
478 | g_MtxReal._11 = gObjMtxReal.A; |
479 | g_MtxReal._12 = gObjMtxReal.C; |
480 | g_MtxReal._13 = 0; |
481 | g_MtxReal._14 = 0;//gObjMtxReal.X; |
482 | |
483 | g_MtxReal._21 = gObjMtxReal.B; |
484 | g_MtxReal._22 = gObjMtxReal.D; |
485 | g_MtxReal._23 = 0; |
486 | g_MtxReal._24 = 0;//gObjMtxReal.Y; |
487 | |
488 | g_MtxReal._31 = 0; |
489 | g_MtxReal._32 = 0; |
490 | g_MtxReal._33 = 1.0; |
491 | g_MtxReal._34 = 0; |
492 | |
493 | g_MtxReal._41 = gObjMtxReal.X; |
494 | g_MtxReal._42 = gObjMtxReal.Y; |
495 | g_MtxReal._43 = 0; |
496 | g_MtxReal._44 = 1.0; |
497 | |
498 | DEBUGGER_PAUSE_COUNT_N(NEXT_OBJ_TXT_CMD); |
499 | } |
500 | |
501 | // Yoshi's Story uses this - 0x01 |
502 | extern void RSP_GBI0_Mtx(Gfx *gfx); |
503 | |
504 | void RSP_S2DEX_BG_1CYC(Gfx *gfx) |
505 | { |
506 | SP_Timing(DP_Minimal16); |
507 | DP_Timing(DP_Minimal16); |
508 | |
509 | uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); |
510 | uObjScaleBg *sbgPtr = (uObjScaleBg *)(dwAddr+g_pRDRAMu8); |
511 | CRender::g_pRender->LoadObjBG1CYC(*sbgPtr); |
512 | CRender::g_pRender->DrawObjBG1CYC(*sbgPtr); |
513 | |
514 | DEBUGGER_PAUSE_AT_COND_AND_DUMP_COUNT_N((eventToPause == NEXT_OBJ_TXT_CMD||eventToPause == NEXT_FLUSH_TRI||eventToPause == NEXT_OBJ_BG), |
515 | { |
516 | DebuggerAppendMsg("S2DEX BG 1CYC: %08X-%08X\n", (gfx->words.w0), (gfx->words.w1) ); |
517 | TRACE0("Paused at RSP_S2DEX_BG_1CYC"); |
518 | } |
519 | ); |
520 | } |
521 | |
522 | void RSP_S2DEX_BG_1CYC_2(Gfx *gfx) |
523 | { |
524 | if( ((gfx->words.w0)&0x00FFFFFF) != 0 ) |
525 | { |
526 | RSP_GBI0_Mtx(gfx); |
527 | return; |
528 | } |
529 | |
530 | RSP_S2DEX_BG_1CYC(gfx); |
531 | } |
532 | |
533 | |
534 | // Yoshi's Story uses this - 0xb2 |
535 | void RSP_S2DEX_OBJ_RECTANGLE_R(Gfx *gfx) |
536 | { |
537 | uint32 dwAddr = RSPSegmentAddr((gfx->words.w1)); |
538 | uObjSprite *ptr = (uObjSprite*)(g_pRDRAMu8+dwAddr); |
539 | |
540 | uObjTxSprite objtx; |
541 | memcpy(&objtx.sprite,ptr,sizeof(uObjSprite)); |
542 | |
543 | |
544 | //uObjTxSprite* ptr = (uObjTxSprite*)(g_pRDRAMu8+(RSPSegmentAddr((gfx->words.w1))&(g_dwRamSize-1))); |
545 | //gObjTxtr = (uObjTxtr*)ptr; |
546 | |
547 | //Now draw the sprite |
548 | if( g_TxtLoadBy == CMD_LOAD_OBJ_TXTR ) |
549 | { |
550 | memcpy(&(objtx.txtr.block),&(gObjTxtr->block),sizeof(uObjTxtr)); |
551 | //CRender::g_pRender->LoadObjSprite(*ptr,true); |
552 | CRender::g_pRender->LoadObjSprite(objtx,true); |
553 | } |
554 | else |
555 | { |
556 | PrepareTextures(); |
557 | } |
558 | //CRender::g_pRender->DrawSprite(*ptr, true); |
559 | CRender::g_pRender->DrawSprite(objtx, true); |
560 | |
561 | DEBUGGER_PAUSE_AT_COND_AND_DUMP_COUNT_N((eventToPause == NEXT_OBJ_TXT_CMD||eventToPause == NEXT_FLUSH_TRI), |
562 | { |
563 | DumpTxtrInfo(gObjTxtr); |
564 | DumpSpriteParameters(*ptr); |
565 | TRACE0("Paused at RSP_S2DEX_OBJ_RECTANGLE_R"); |
566 | } |
567 | ); |
568 | } |
569 | |