Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
draw_img_util.c
Go to the documentation of this file.
1#include "common.h"
2
3s32 draw_image_with_clipping(IMG_PTR raster, u32 width, u32 height, s32 fmt, s32 bitDepth, s16 posX, s16 posY,
4 u16 clipX, u16 clipY, u16 clipWidth, u16 clipHeight);
5
6s32 draw_ci_image_with_clipping(IMG_PTR raster, s32 width, s32 height, s32 fmt, s32 bitDepth, PAL_PTR palette, s16 posX,
7 s16 posY, u16 clipULx, u16 clipULy, u16 clipLRx, u16 clipRLy, u8 opacity) {
8 s32 ret = 1;
9
10 gDPPipeSync(gMainGfxPos++);
11 gDPSetCycleType(gMainGfxPos++, G_CYC_1CYCLE);
12 gDPSetTextureFilter(gMainGfxPos++, G_TF_POINT);
13 gDPSetTexturePersp(gMainGfxPos++, G_TP_NONE);
14
15 if (opacity == 255) {
16 gDPSetRenderMode(gMainGfxPos++, G_RM_TEX_EDGE, G_RM_TEX_EDGE2);
17 gDPSetCombineMode(gMainGfxPos++, G_CC_DECALRGBA, G_CC_DECALRGBA);
18 } else if (opacity == 0) {
19 return ret;
20 } else {
21 gDPSetRenderMode(gMainGfxPos++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
22 gDPSetCombineMode(gMainGfxPos++, PM_CC_02, PM_CC_02);
23 gDPSetPrimColor(gMainGfxPos++, 0, 0, 0, 0, 0, opacity);
24 }
25
26 if (fmt == G_IM_FMT_CI) {
27 gDPSetTextureLUT(gMainGfxPos++, G_TT_RGBA16);
28 if (bitDepth == G_IM_SIZ_4b) {
29 gDPLoadTLUT_pal16(gMainGfxPos++, 0, palette);
30 } else {
31 gDPLoadTLUT_pal256(gMainGfxPos++, palette);
32 }
33 } else {
34 gDPSetTextureLUT(gMainGfxPos++, G_TT_NONE);
35 }
36 ret = draw_image_with_clipping(raster, width, height, fmt, bitDepth, posX, posY, clipULx, clipULy, clipLRx, clipRLy);
37 gDPPipeSync(gMainGfxPos++);
38 return ret;
39}
40
41typedef struct Rect2b {
42 /* 0x00 */ s16 ulx;
43 /* 0x02 */ s16 uly;
44 /* 0x04 */ s16 lrx;
45 /* 0x06 */ s16 lry;
46} Rect2b; // size = 0x08
47
48s32 draw_image_with_clipping(IMG_PTR raster, u32 width, u32 height, s32 fmt, s32 bitDepth,
49 s16 posX, s16 posY,
50 u16 clipX, u16 clipY,
51 u16 clipWidth, u16 clipHeight) {
52 Rect2b texRect;
53 Rect2b drawRect;
54 u8 stopDrawing;
55 u8 stopDrawingLine;
56 s8 zero = 0; // required to match
57
58 u16 texOffsetX, texOffsetY;
59
60 if (posX >= clipX + clipWidth || posY >= clipY + clipHeight) {
61 return FALSE;
62 }
63 if (clipX >= (s16)(posX + width)) {
64 return FALSE;
65 }
66 if (clipY >= (s16)(posY + height)) {
67 return FALSE;
68 }
69
70 texRect.uly = 0;
71 drawRect.uly = posY;
72 stopDrawing = FALSE;
73
74 while (TRUE) {
75 texRect.lry = texRect.uly + 31;
76 drawRect.lry = drawRect.uly + 32;
77 texOffsetY = 0;
78 if (drawRect.lry <= clipY) {
79 do {
80 texRect.uly += 32;
81 drawRect.uly = drawRect.lry;
82 drawRect.lry += 32;
83 } while (drawRect.lry < clipY);
84 texRect.lry = texRect.uly + 31;
85 }
86
87 if (drawRect.uly < clipY) {
88 texOffsetY = abs(posY - clipY);
89 drawRect.uly = clipY;
90 }
91
92 if (drawRect.lry >= clipY + clipHeight) {
93 texRect.lry = clipY + clipHeight - posY - 1;
94 stopDrawing = TRUE;
95 drawRect.lry = clipY + clipHeight;
96 }
97
98 if (texRect.lry + 1 >= height) {
99 texRect.lry = height - 1;
100 drawRect.lry = texRect.lry + posY + 1;
101 stopDrawing = TRUE;
102 }
103
104 texRect.ulx = zero;
105 drawRect.ulx = posX;
106 stopDrawingLine = FALSE;
107
108 while (TRUE) {
109 texRect.lrx = texRect.ulx + 63;
110 drawRect.lrx = drawRect.ulx + 64;
111 texOffsetX = 0;
112
113 if (drawRect.lrx <= clipX) {
114 do {
115 texRect.ulx += 64;
116 drawRect.ulx = drawRect.lrx;
117 drawRect.lrx += 64;
118 } while (drawRect.lrx < clipX);
119 texRect.lrx = texRect.ulx + 63;
120 }
121
122 if (drawRect.ulx < clipX) {
123 texOffsetX = abs(posX - clipX);
124 drawRect.ulx = clipX;
125 }
126
127 if (drawRect.lrx >= clipX + clipWidth) {
128 texRect.lrx = clipX + clipWidth - posX - 1;
129 stopDrawingLine = TRUE;
130 drawRect.lrx = clipX + clipWidth;
131 }
132
133 if (texRect.lrx + 1 >= width) {
134 texRect.lrx = width - 1;
135 drawRect.lrx = texRect.lrx + posX + 1;
136 stopDrawingLine = TRUE;
137 }
138
139 if (bitDepth == G_IM_SIZ_4b) {
140 gDPLoadTextureTile_4b(gMainGfxPos++, raster, fmt, width, height,
141 texRect.ulx, texRect.uly, texRect.lrx, texRect.lry, 0,
142 G_TX_WRAP, G_TX_WRAP, 6, 5, G_TX_NOLOD, G_TX_NOLOD);
143 } else if (bitDepth == G_IM_SIZ_16b) {
144 gDPLoadTextureTile(gMainGfxPos++, raster, fmt, G_IM_SIZ_16b, width, height,
145 texRect.ulx, texRect.uly, texRect.lrx, texRect.lry, 0,
146 G_TX_WRAP, G_TX_WRAP, 6, 5, G_TX_NOLOD, G_TX_NOLOD);
147 } else if (bitDepth == G_IM_SIZ_8b) {
148 gDPLoadTextureTile(gMainGfxPos++, raster, fmt, G_IM_SIZ_8b, width, height,
149 texRect.ulx, texRect.uly, texRect.lrx, texRect.lry, 0,
150 G_TX_WRAP, G_TX_WRAP, 6, 5, G_TX_NOLOD, G_TX_NOLOD);
151 }
152
153 gSPTextureRectangle(gMainGfxPos++, drawRect.ulx * 4, drawRect.uly * 4, drawRect.lrx * 4, drawRect.lry * 4,
154 0, texOffsetX * 32, texOffsetY * 32, 1024, 1024);
155
156 if (stopDrawingLine) {
157 break;
158 }
159 texRect.ulx += 64;
160 drawRect.ulx = drawRect.lrx;
161 }
162
163 if (stopDrawing) {
164 break;
165 }
166 texRect.uly += 32;
167 drawRect.uly = drawRect.lry;
168 }
169
170 return TRUE;
171}
172
173s32 draw_tiled_image(IMG_PTR raster, u32 width, u32 height, u8 fmt, u8 bitDepth,
174 s16 posX, s16 posY,
175 u16 clipX, u16 clipY, u16 clipWidth, u16 clipHeight,
176 f32 scaleX, f32 scaleY) {
177 Rect texRect;
178 Rect drawRect;
179 s32 dsdx, dtdy;
180 s32 texOffsetX, texOffsetY;
181 u8 stopDrawing;
182 u8 stopDrawingLine;
183
184 if (scaleX < 0.01 || scaleY < 0.01) {
185 return 0;
186 }
187
188 if (posX >= clipX + clipWidth || posY >= clipY + clipHeight) {
189 return 0;
190 }
191
192 if (clipX >= (s16)(posX + width * scaleX)) {
193 return 0;
194 }
195
196 if (clipY >= (s16)(posY + height * scaleY)) {
197 return 0;
198 }
199
200 stopDrawing = 0;
201 texRect.uly = 0;
202 drawRect.uly = posY;
203 dsdx = 1.0f / scaleX * 1024.0f;
204 dtdy = 1.0f / scaleY * 1024.0f;
205 while (TRUE) {
206 texRect.lry = texRect.uly + 31;
207 drawRect.lry = drawRect.uly + (scaleY * 32.0 + 0.5);
208 texOffsetY = 0;
209 if (drawRect.lry <= clipY) {
210 do {
211 texRect.uly += 32;
212 drawRect.uly = drawRect.lry;
213 drawRect.lry += scaleY * 32.0f;
214 } while (drawRect.lry < clipY);
215 texRect.lry = texRect.uly + 31;
216 }
217
218 if (drawRect.uly < clipY) {
219 drawRect.uly = clipY;
220 texOffsetY = abs(posY - clipY) / scaleY * 32.0f;
221 }
222
223 if ((u32)(texRect.lry + 1) >= height) {
224 texRect.lry = height - 1;
225 stopDrawing = 1;
226 drawRect.lry = posY + (s16)(texRect.lry * scaleY);
227 drawRect.lry += scaleY;
228 }
229
230 if (drawRect.lry > clipY + clipHeight) {
231 drawRect.lry = clipY + clipHeight;
232 if (!stopDrawing) {
233 drawRect.lry = clipY + clipHeight;
234 stopDrawing = 1;
235 }
236 }
237
238 stopDrawingLine = 0;
239 texRect.ulx = 0;
240 drawRect.ulx = posX;
241 while (TRUE) {
242 texRect.lrx = texRect.ulx + 63;
243 drawRect.lrx = drawRect.ulx + (scaleX * 64.0 + 0.3);
244 texOffsetX = 0;
245
246 if (drawRect.lrx <= clipX) {
247 do {
248 texRect.ulx += 64;
249 drawRect.ulx = drawRect.lrx;
250 drawRect.lrx += scaleX * 64.0f;
251 } while (drawRect.lrx < clipX);
252 texRect.lrx = texRect.ulx + 63;
253 }
254
255 if (drawRect.ulx < clipX) {
256 drawRect.ulx = clipX;
257 texOffsetX = abs(posX - clipX) / scaleX * 32.0f;
258 }
259
260 if ((u32)(texRect.lrx + 1) >= width) {
261 texRect.lrx = width - 1;
262 stopDrawingLine = TRUE;
263 drawRect.lrx = posX + (s16)(texRect.lrx * scaleX);
264 drawRect.lrx = drawRect.lrx + scaleX + 0.3;
265 }
266
267 if (drawRect.lrx > clipX + clipWidth) {
268 drawRect.lrx = clipX + clipWidth;
269 stopDrawingLine = TRUE;
270 }
271
272 if (bitDepth == G_IM_SIZ_16b) {
273 gDPLoadTextureTile(gMainGfxPos++, raster, fmt, G_IM_SIZ_16b, width, height,
274 texRect.ulx, texRect.uly, texRect.lrx, texRect.lry, 0,
275 G_TX_WRAP, G_TX_WRAP, 6, 5, G_TX_NOLOD, G_TX_NOLOD);
276 } else if (bitDepth == G_IM_SIZ_4b) {
277 gDPLoadTextureTile_4b(gMainGfxPos++, raster, fmt, width, height,
278 texRect.ulx, texRect.uly, texRect.lrx, texRect.lry, 0,
279 G_TX_WRAP, G_TX_WRAP, 6, 5, G_TX_NOLOD, G_TX_NOLOD);
280 }
281
282 gSPTextureRectangle(gMainGfxPos++, drawRect.ulx * 4, drawRect.uly * 4, (drawRect.lrx - stopDrawingLine) * 4, drawRect.lry * 4,
283 0, texOffsetX, texOffsetY, dsdx, dtdy);
284
285 if (stopDrawingLine) {
286 break;
287 }
288 texRect.ulx += 64;
289 drawRect.ulx = drawRect.lrx;
290 };
291
292 if (stopDrawing) {
293 break;
294 }
295 texRect.uly += 32;
296 drawRect.uly = drawRect.lry;
297 };
298
299 return 1;
300}
301
302s32 integer_log(s32 number, u32 base) {
303 f32 fNumber = number;
304 s32 ret = 1;
305
306 while (TRUE) {
307 fNumber /= base;
308 if (fNumber <= 1.0) {
309 return ret;
310 }
311
312 ret++;
313 }
314}
315
316s32 draw_adjustable_tiled_image(IMG_PTR raster, u32 width, u32 height, u8 fmt, u8 bitDepth,
317 s16 posX, s16 posY,
318 u16 clipX, u16 clipY, u16 clipWidth, u16 clipHeight,
319 f32 scaleX, f32 scaleY) {
320 Rect texRect;
321 Rect drawRect;
322 u16 overlap;
323 s32 dsdx, dtdy;
324 s32 texOffsetX, texOffsetY;
325 u8 stopDrawing;
326
327 u16 masks, maskt;
328
329 u16 texelNum;
330 u16 lineHeight;
331
332 f32 temp;
333
334 if (scaleX < 0.01 || scaleY < 0.01) {
335 return 0;
336 }
337
338 if (posX >= clipX + clipWidth || posY >= clipY + clipHeight) {
339 return 0;
340 }
341
342 if (clipX >= (s16)(posX + width * scaleX)) {
343 return 0;
344 }
345
346 if (clipY >= (s16)(posY + height * scaleY)) {
347 return 0;
348 }
349 if (bitDepth == G_IM_SIZ_4b) {
350 if (fmt == G_IM_FMT_IA || fmt == G_IM_FMT_I) {
351 texelNum = 0x2000;
352 } else if (fmt == G_IM_FMT_CI) {
353 texelNum = 0x1000;
354 } else {
355 return 0;
356 }
357 } else if (bitDepth == G_IM_SIZ_8b) {
358 if (fmt == G_IM_FMT_IA || fmt == G_IM_FMT_I) {
359 texelNum = 0x1000;
360 } else if (fmt == G_IM_FMT_CI) {
361 texelNum = 0x800;
362 } else {
363 return 0;
364 }
365 } else if (bitDepth == G_IM_SIZ_16b) {
366 if (fmt == G_IM_FMT_RGBA) {
367 texelNum = 0x800;
368 } else if (fmt == G_IM_FMT_IA) {
369 texelNum = 0x800;
370 } else {
371 return 0;
372 }
373 } else if (bitDepth == G_IM_SIZ_32b) {
374 if (fmt == G_IM_FMT_RGBA) {
375 texelNum = 0x400;
376 } else {
377 return 0;
378 }
379 } else {
380 return 0;
381 }
382
383 dsdx = 1.0f / scaleX * 1024.0f;
384 dtdy = 1.0f / scaleY * 1024.0f;
385 lineHeight = texelNum / width;
386 if (lineHeight > height) {
387 lineHeight = height;
388 } else if (lineHeight <= 1) {
389 return 0;
390 }
391 if (scaleY <= 1.0) {
392 overlap = 0;
393 } else {
394 overlap = scaleY;
395 }
396
397 masks = integer_log(width, 2);
398 maskt = integer_log(height, 2);
399
400 stopDrawing = 0;
401
402 texRect.ulx = 0;
403 texRect.uly = 0;
404 drawRect.ulx = posX;
405 drawRect.uly = posY;
406
407 while (TRUE) {
408 texRect.lrx = width - 1;
409 texRect.lry = texRect.uly + lineHeight - 1;
410 drawRect.lry = drawRect.uly + lineHeight * scaleY;
411 drawRect.lrx = (s16)(drawRect.ulx + width * scaleX);
412
413
414 texOffsetX = texOffsetY = 0;
415
416 if (drawRect.lry <= clipY) {
417 do {
418 texRect.uly += lineHeight;
419 drawRect.uly = drawRect.lry;
420 drawRect.lry += lineHeight * scaleY;
421 } while (drawRect.lry < clipY);
422 texRect.lry = texRect.uly + lineHeight - 1;
423 }
424
425 if (drawRect.uly < clipY) {
426 drawRect.uly = clipY;
427 temp = abs(posY - clipY);
428 temp /= scaleY;
429 texOffsetY = temp * 32.0f;
430 }
431 if (texRect.lry + 1 == height){
432 stopDrawing = 1;
433 } else if (height < texRect.lry + 1) {
434 s32 temp;
435 texRect.lry = height - 1;
436 temp = height * scaleY;
437 stopDrawing = 1;
438 drawRect.lry = drawRect.uly + temp;
439 }
440
441 if (drawRect.lry >= clipY + clipHeight) {
442 if (!stopDrawing) {
443 drawRect.lry = clipY + clipHeight;
444 stopDrawing = 1;
445 } else if (drawRect.lry > clipY + clipHeight) {
446 drawRect.lry = clipY + clipHeight;
447 }
448 }
449 if (drawRect.ulx < clipX) {
450 drawRect.ulx = clipX;
451 temp = abs(posX - clipX);
452 temp /= scaleX;
453 texOffsetX = temp * 32.0f;
454 }
455 if (drawRect.lrx >= clipX + clipWidth) {
456 drawRect.lrx = clipX + clipWidth;
457 }
458
459 if (bitDepth == G_IM_SIZ_4b) {
460 gDPLoadTextureTile_4b(gMainGfxPos++, raster, fmt, width, height,
461 texRect.ulx, texRect.uly, texRect.lrx, texRect.lry, 0,
462 G_TX_WRAP, G_TX_WRAP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
463 } else if (bitDepth == G_IM_SIZ_8b) {
464 gDPLoadTextureTile(gMainGfxPos++, raster, fmt, G_IM_SIZ_8b, width, height,
465 texRect.ulx, texRect.uly, texRect.lrx, texRect.lry, 0,
466 G_TX_WRAP, G_TX_WRAP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
467 } else if (bitDepth == G_IM_SIZ_16b) {
468 gDPLoadTextureTile(gMainGfxPos++, raster, fmt, G_IM_SIZ_16b, width, height,
469 texRect.ulx, texRect.uly, texRect.lrx, texRect.lry, 0,
470 G_TX_WRAP, G_TX_WRAP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
471 } else if (bitDepth == G_IM_SIZ_32b) {
472 gDPLoadTextureTile(gMainGfxPos++, raster, fmt, G_IM_SIZ_32b, width, height,
473 texRect.ulx, texRect.uly, texRect.lrx, texRect.lry, 0,
474 G_TX_WRAP, G_TX_WRAP, masks, maskt, G_TX_NOLOD, G_TX_NOLOD);
475 }
476 gSPTextureRectangle(gMainGfxPos++, drawRect.ulx * 4, drawRect.uly * 4, drawRect.lrx * 4, drawRect.lry * 4,
477 0, texOffsetX, texOffsetY, dsdx, dtdy);
478
479 if (stopDrawing) {
480 break;
481 }
482
483 texRect.uly += lineHeight - overlap;
484 drawRect.uly = drawRect.lry - overlap * scaleY;
485 };
486
487 return 1;
488}
#define PAL_PTR
#define IMG_PTR
s32 integer_log(s32 number, u32 base)
s32 draw_image_with_clipping(IMG_PTR raster, u32 width, u32 height, s32 fmt, s32 bitDepth, s16 posX, s16 posY, u16 clipX, u16 clipY, u16 clipWidth, u16 clipHeight)
s32 draw_tiled_image(IMG_PTR raster, u32 width, u32 height, u8 fmt, u8 bitDepth, s16 posX, s16 posY, u16 clipX, u16 clipY, u16 clipWidth, u16 clipHeight, f32 scaleX, f32 scaleY)
s32 draw_adjustable_tiled_image(IMG_PTR raster, u32 width, u32 height, u8 fmt, u8 bitDepth, s16 posX, s16 posY, u16 clipX, u16 clipY, u16 clipWidth, u16 clipHeight, f32 scaleX, f32 scaleY)
s32 draw_ci_image_with_clipping(IMG_PTR raster, s32 width, s32 height, s32 fmt, s32 bitDepth, PAL_PTR palette, s16 posX, s16 posY, u16 clipULx, u16 clipULy, u16 clipLRx, u16 clipRLy, u8 opacity)
#define PM_CC_02
Definition macros.h:277
Gfx * gMainGfxPos
Definition cam_main.c:15