1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - GX - demos - UnitTours/DEMOLib
3 File: DEMOBitmap.c
4
5 Copyright 2007-2008 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 $Date:: 2008-09-17 #$
14 $Rev: 8556 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17
18 #ifdef SDK_TWL
19 #include <twl.h>
20 #else
21 #include <nitro.h>
22 #endif
23 #include "DEMOBitmap.h"
24
25
26 typedef struct DEMOBitmapContext
27 {
28 u32 require_flip : 1;
29 u32 bitmap_modified : 1;
30 u32 main_bg_modified : 1;
31 u32 main_oam_modified : 1;
32 u32 sub_bg_modified : 1;
33 u32 sub_oam_modified : 1;
34 u32 : 26;
35 OSThreadQueue flip_wait_q[1];
36 void (*HookedConsole)(int console, const char *string);
37 GXRgb bitmap_ground_color;
38 GXRgb bitmap_text_color;
39 u8 padding[12];
40 GXRgb bitmap_frame[GX_LCD_SIZE_X * GX_LCD_SIZE_Y] ATTRIBUTE_ALIGN(32);
41 u16 main_bg[32 * 24] ATTRIBUTE_ALIGN(32);
42 GXOamAttr main_oam[128] ATTRIBUTE_ALIGN(32);
43 u16 sub_bg[32 * 24] ATTRIBUTE_ALIGN(32);
44 GXOamAttr sub_oam[128] ATTRIBUTE_ALIGN(32);
45 char sub_log[24][32 + 1];
46 int sub_log_count;
47 }
48 DEMOBitmapContext;
49
50 static DEMOBitmapContext bitmap ATTRIBUTE_ALIGN(32);
51
52 extern void VBlankIntr(void);
53
54 /*---------------------------------------------------------------------------*
55 Name: VBlankIntr
56
57 Description: V-Blank interrupt handler
58
59 Arguments: None
60
61 Returns: None
62 *---------------------------------------------------------------------------*/
VBlankIntr(void)63 SDK_WEAK_SYMBOL void VBlankIntr(void)
64 {
65 OS_SetIrqCheckFlag(OS_IE_V_BLANK);
66 }
67
68 /*---------------------------------------------------------------------------*
69 Name: LogConsole
70
71 Description: Accumulates printf output in a log and also outputs it to the original console
72
73 Arguments: string: Output string
74
75 Returns: None
76 *---------------------------------------------------------------------------*/
LogConsole(int console,const char * string)77 static void LogConsole(int console, const char *string)
78 {
79 DEMOBitmapContext *const context = &bitmap;
80 DEMOPutLog("%s", string);
81 (*context->HookedConsole)(console, string);
82 }
83
84 /*---------------------------------------------------------------------------*
85 Name: OnVBlank
86
87 Description: V-Blank processing
88
89 Arguments: None
90
91 Returns: None
92 *---------------------------------------------------------------------------*/
OnVBlank(void)93 static void OnVBlank(void)
94 {
95 DEMOBitmapContext *const context = &bitmap;
96 if (context->require_flip)
97 {
98 if (context->bitmap_modified)
99 {
100 context->bitmap_modified = 0;
101 GX_LoadBG3Bmp(context->bitmap_frame, 0, sizeof(context->bitmap_frame));
102 }
103 if (context->main_bg_modified)
104 {
105 context->main_bg_modified = 0;
106 GX_LoadBG1Scr(context->main_bg, 0, sizeof(context->main_bg));
107 }
108 if (context->main_oam_modified)
109 {
110 context->main_oam_modified = 0;
111 GX_LoadOAM(context->main_oam, 0, sizeof(context->main_oam));
112 }
113
114 if (context->sub_bg_modified)
115 {
116 context->sub_bg_modified = 0;
117 GXS_LoadBG0Scr(context->sub_bg, 0, sizeof(context->sub_bg));
118 }
119 if (context->sub_oam_modified)
120 {
121 context->sub_oam_modified = 0;
122 GXS_LoadOAM(context->sub_oam, 0, sizeof(context->sub_oam));
123 }
124 context->require_flip = 0;
125 OS_WakeupThread(context->flip_wait_q);
126 }
127 VBlankIntr();
128 }
129
130 /*---------------------------------------------------------------------------*
131 Name: DEMOInitDisplayBitmap
132
133 Description: Initializes the DEMO in bitmap render mode
134
135 Arguments: None
136
137 Returns: None
138 *---------------------------------------------------------------------------*/
DEMOInitDisplayBitmap(void)139 void DEMOInitDisplayBitmap(void)
140 {
141 // Initialize GX master settings
142 // VRAM-A: 3D 128kB (BG0)
143 // VRAM-B:
144 // VRAM-C: (ext) 128kB
145 // VRAM-D: main-BG 128kB (BG1=scr:2kB,chr:24kB) (BG3=scr:2kB,chr:96kB)
146 // VRAM-E: 3D-PLT 64kB (BG0)
147 // VRAM-FG: main-OBJ 32kB (OBJ)
148 // VRAM-H: sub-BG 32kB (BG0=scr:2kB,chr:24kB)
149 // VRAM-I: sub-OBJ 16kB (OBJ)
150 //
151 // main LCD: mode4,3D-on,BG0,BG1,BG3,OBJ
152 // BG0: 3D
153 // BG1: TXT-BG,256x256,4bit,scr=1E800,chr=18000
154 // BG3: BMP-BG,256x192,16bit,scr=1E000,chr=00000
155 // OBJ: multi-purpose
156 //
157 // sub LCD: mode0,BG0,OBJ
158 // BG0: TXT-BG,256x256,4bit,scr06000,chr00000
159 // OBJ: multi-purpose
160 G3X_Init();
161 G3X_InitMtxStack();
162 GX_SetBankForTex(GX_VRAM_TEX_0_A);
163 GX_SetBankForBG(GX_VRAM_BG_128_D);
164 GX_SetBankForTexPltt(GX_VRAM_TEXPLTT_0123_E);
165 GX_SetBankForOBJ(GX_VRAM_OBJ_32_FG);
166 GX_SetBankForSubBG(GX_VRAM_SUB_BG_32_H);
167 GX_SetBankForSubOBJ(GX_VRAM_SUB_OBJ_16_I);
168 GX_SetGraphicsMode(GX_DISPMODE_GRAPHICS, GX_BGMODE_4, GX_BG0_AS_3D);
169 GX_SetVisiblePlane(GX_PLANEMASK_BG0 | GX_PLANEMASK_BG1 | GX_PLANEMASK_BG3 | GX_PLANEMASK_OBJ);
170 GXS_SetGraphicsMode(GX_BGMODE_0);
171 GXS_SetVisiblePlane(GX_PLANEMASK_BG0 | GX_PLANEMASK_OBJ);
172 G2_BlendNone();
173 G2S_BlendNone();
174 GX_Power2DSub(TRUE);
175 // Main-3D
176 {
177 G2_SetBG0Priority(2);
178 G3X_SetShading(GX_SHADING_TOON);
179 G3X_AntiAlias(TRUE);
180 }
181 // Main-TXT-BG
182 {
183 G2_SetBG1Control(GX_BG_SCRSIZE_TEXT_256x256, GX_BG_COLORMODE_16,
184 GX_BG_SCRBASE_0xe800, GX_BG_CHARBASE_0x18000, GX_BG_EXTPLTT_01);
185 GX_SetBGScrOffset(GX_BGSCROFFSET_0x10000);
186 G2_SetBG1Priority(0);
187 G2_BG1Mosaic(FALSE);
188 }
189 // Main-BMP-BG
190 {
191 G2_SetBG3ControlDCBmp(GX_BG_SCRSIZE_DCBMP_256x256, GX_BG_AREAOVER_XLU, GX_BG_BMPSCRBASE_0x00000);
192 G2_SetBG3Priority(1);
193 }
194 // Sub-TXT-BG
195 {
196 G2S_SetBG0Control(GX_BG_SCRSIZE_TEXT_256x256, GX_BG_COLORMODE_16,
197 GX_BG_SCRBASE_0x6000, GX_BG_CHARBASE_0x00000, GX_BG_EXTPLTT_01);
198 G2S_SetBG0Priority(1);
199 G2S_BG0Mosaic(FALSE);
200 }
201 G3_SwapBuffers(GX_SORTMODE_AUTO, GX_BUFFERMODE_W);
202 G3X_SetClearColor(GX_RGB(0, 0, 0), 31, 0x7fff, 63, FALSE);
203 DEMOSetViewPort(0, 0, GX_LCD_SIZE_X, GX_LCD_SIZE_Y);
204
205 {
206 static const GXRgb pal[16] = { GX_RGB(0, 0, 0), GX_RGB(31, 31, 31), };
207 MI_CpuFill32(&bitmap, 0x00000000, sizeof(bitmap));
208 GX_LoadBGPltt(pal, 0x0000, sizeof(pal));
209 GX_LoadBG1Char(DEMOAsciiChr, 0x00000, sizeof(DEMOAsciiChr));
210 GXS_LoadBGPltt(pal, 0x0000, sizeof(pal));
211 GXS_LoadBG0Char(DEMOAsciiChr, 0x00000, sizeof(DEMOAsciiChr));
212 OS_InitThreadQueue(bitmap.flip_wait_q);
213 OS_SetIrqFunction(OS_IE_V_BLANK, OnVBlank);
214 (void)OS_EnableIrqMask(OS_IE_V_BLANK);
215 }
216 }
217
218 /*---------------------------------------------------------------------------*
219 Name: DEMO_DrawFlip
220
221 Description: Applies the current rendering content to VRAM
222
223 Arguments: None
224
225 Returns: None
226 *---------------------------------------------------------------------------*/
DEMO_DrawFlip()227 void DEMO_DrawFlip()
228 {
229 DEMOBitmapContext *const context = &bitmap;
230
231 if (context->bitmap_modified)
232 {
233 DC_StoreRange(context->bitmap_frame, sizeof(context->bitmap_frame));
234 }
235 if (context->main_bg_modified)
236 {
237 DC_StoreRange(context->main_bg, sizeof(context->main_bg));
238 }
239 if (context->main_oam_modified)
240 {
241 DC_StoreRange(context->main_oam, sizeof(context->main_oam));
242 }
243 if (context->sub_bg_modified)
244 {
245 const int visible_lines = 20;
246 const int palette = 0;
247 int offset = (context->sub_log_count + 1 > visible_lines) ? (context->sub_log_count + 1 - visible_lines) : 0;
248 int x, y;
249 for (y = 0; y < visible_lines; ++y)
250 {
251 u16 *dst = &context->sub_bg[y * 32];
252 const char *src = context->sub_log[(offset + y) % 24];
253 for (x = 0; (x < 32) && src[x] && (src[x] != '\n'); ++x)
254 {
255 dst[x] = (u16)((u8)src[x] | (palette << 12));
256 }
257 for (; x < 32; ++x)
258 {
259 dst[x] = (u16)(0 | (palette << 12));
260 }
261 }
262 DC_StoreRange(context->sub_bg, sizeof(context->sub_bg));
263 }
264 if (context->sub_oam_modified)
265 {
266 DC_StoreRange(context->sub_oam, sizeof(context->sub_oam));
267 }
268 DC_WaitWriteBufferEmpty();
269 {
270 OSIntrMode bak_intr = OS_DisableInterrupts();
271 context->require_flip = 1;
272 // while (context->require_flip)
273 // {
274 // OS_SleepThread(context->flip_wait_q);
275 // }
276 (void)OS_RestoreInterrupts(bak_intr);
277 }
278 }
279
280 /*---------------------------------------------------------------------------*
281 Name: DEMOVerifyGXRgb
282
283 Description: Checks the validity of color values.
284
285 Arguments: color: Color value that is thought to be within the GXRgb range
286
287 Returns: Returns color unchanged if it is a valid GXRgb value and 0xFFFF if it is out of range
288 *---------------------------------------------------------------------------*/
DEMOVerifyGXRgb(int color)289 GXRgb DEMOVerifyGXRgb(int color)
290 {
291 if((color < 0) || (color > 0xFFFF))
292 {
293 static BOOL once = FALSE;
294 if(!once)
295 {
296 OS_TWarning("color(%04X) exceeds GXRgb range.\n", color);
297 once = TRUE;
298 }
299 color = 0xFFFF;
300 }
301 return (GXRgb)color;
302 }
303
304 /*---------------------------------------------------------------------------*
305 Name: DEMOSetBitmapTextColor
306
307 Description: Sets the text color for bitmap rendering
308
309 Arguments: color: The color to set
310
311 Returns: None
312 *---------------------------------------------------------------------------*/
DEMOiSetBitmapTextColor(GXRgb color)313 void DEMOiSetBitmapTextColor(GXRgb color)
314 {
315 DEMOBitmapContext *context = &bitmap;
316 context->bitmap_text_color = color;
317 }
318
319 /*---------------------------------------------------------------------------*
320 Name: DEMOSetBitmapGroundColor
321
322 Description: Sets the background color for bitmap rendering
323
324 Arguments: color: The color to set
325
326 Returns: None
327 *---------------------------------------------------------------------------*/
DEMOiSetBitmapGroundColor(GXRgb color)328 void DEMOiSetBitmapGroundColor(GXRgb color)
329 {
330 DEMOBitmapContext *context = &bitmap;
331 context->bitmap_ground_color = color;
332 }
333
334 /*---------------------------------------------------------------------------*
335 Name: DEMOiFillRect
336
337 Description: Renders a rectangle to the bitmap.
338
339 Arguments: x: x coordinate for rendering
340 y: y coordinate for rendering
341 wx: x width for rendering
342 wy: y width for rendering
343 color: The color to set
344
345 Returns: None
346 *---------------------------------------------------------------------------*/
DEMOiFillRect(int x,int y,int wx,int wy,GXRgb color)347 void DEMOiFillRect(int x, int y, int wx, int wy, GXRgb color)
348 {
349 if ((x < GX_LCD_SIZE_X) && (y < GX_LCD_SIZE_Y))
350 {
351 if (wx > GX_LCD_SIZE_X - x)
352 {
353 wx = GX_LCD_SIZE_X - x;
354 }
355 if (wy > GX_LCD_SIZE_Y - y)
356 {
357 wy = GX_LCD_SIZE_Y - y;
358 }
359 if ((wx > 0) && (wy > 0))
360 {
361 DEMOBitmapContext *context = &bitmap;
362 GXRgb *dst = &context->bitmap_frame[x + y * GX_LCD_SIZE_X];
363 while (--wy >= 0)
364 {
365 MI_CpuFill16(dst, color, wx * sizeof(GXRgb));
366 dst += GX_LCD_SIZE_X;
367 }
368 context->bitmap_modified = 1;
369 }
370 }
371 }
372
373 /*---------------------------------------------------------------------------*
374 Name: DEMOBlitRect
375
376 Description: Transfers a rectangle to a bitmap
377
378 Arguments: x: x coordinate for rendering
379 y: y coordinate for rendering
380 wx: x width for rendering
381 wy: y width for rendering
382 image: The original image to transfer
383 stroke: Pixel count per each of the original lines to transfer
384
385 Returns: None
386 *---------------------------------------------------------------------------*/
DEMOBlitRect(int x,int y,int wx,int wy,const GXRgb * image,int stroke)387 void DEMOBlitRect(int x, int y, int wx, int wy, const GXRgb *image, int stroke)
388 {
389 if ((x < GX_LCD_SIZE_X) && (y < GX_LCD_SIZE_Y))
390 {
391 if (wx > GX_LCD_SIZE_X - x)
392 {
393 wx = GX_LCD_SIZE_X - x;
394 }
395 if (wy > GX_LCD_SIZE_Y - y)
396 {
397 wy = GX_LCD_SIZE_Y - y;
398 }
399 if ((wx > 0) && (wy > 0))
400 {
401 DEMOBitmapContext *context = &bitmap;
402 GXRgb *dst = &context->bitmap_frame[x + y * GX_LCD_SIZE_X];
403 while (--wy >= 0)
404 {
405 MI_CpuCopy16(image, dst, wx * sizeof(GXRgb));
406 image += stroke;
407 dst += GX_LCD_SIZE_X;
408 }
409 context->bitmap_modified = 1;
410 }
411 }
412 }
413
414 /*---------------------------------------------------------------------------*
415 Name: DEMOBlitTex16
416
417 Description: Transfers a 16-color texture to a bitmap
418
419 Arguments: x: x coordinate for rendering
420 y: y coordinate for rendering
421 wx: Rendering width in the x-direction (this must be an integer multiple of 8 pixels)
422 wy: Rendering width in the y-direction (this must be an integer multiple of 8 pixels)
423 chr: Character image (4x8x8 one-dimensional character format)
424 plt: Palette image (index 0 is treated as transparent)
425
426 Returns: None
427 *---------------------------------------------------------------------------*/
DEMOBlitTex16(int x,int y,int wx,int wy,const void * chr,const GXRgb * plt)428 void DEMOBlitTex16(int x, int y, int wx, int wy, const void *chr, const GXRgb *plt)
429 {
430 if ((x < GX_LCD_SIZE_X) && (y < GX_LCD_SIZE_Y))
431 {
432 int stroke = wx;
433 if (wx > GX_LCD_SIZE_X - x)
434 {
435 wx = GX_LCD_SIZE_X - x;
436 }
437 if (wy > GX_LCD_SIZE_Y - y)
438 {
439 wy = GX_LCD_SIZE_Y - y;
440 }
441 if ((wx > 0) && (wy > 0))
442 {
443 DEMOBitmapContext *context = &bitmap;
444 const u8 *src = (const u8 *)chr;
445 GXRgb *dst = &context->bitmap_frame[x + y * GX_LCD_SIZE_X];
446 int tx, ty, dx, dy, nx, ny;
447 for (ty = 0; ty < wy; ty += 8)
448 {
449 ny = MATH_MIN(wy - ty, 8);
450 for (tx = 0; tx < wx; tx += 8)
451 {
452 nx = MATH_MIN(wx - tx, 8);
453 for (dy = 0; dy < ny; ++dy)
454 {
455 for (dx = 0; dx < nx; ++dx)
456 {
457 u8 index = (u8)((src[(dy * 8 + dx) / 2] >> ((dx & 1) * 4)) & 0x0F);
458 if (index > 0)
459 {
460 dst[(ty + dy) * GX_LCD_SIZE_X + tx + dx] = (GXRgb)(plt[index] | 0x8000);
461 }
462 }
463 }
464 src += 8 * 8 / 2;
465 }
466 src += (stroke - tx) * 8 / 2;
467 }
468 context->bitmap_modified = 1;
469 }
470 }
471 }
472
473 /*---------------------------------------------------------------------------*
474 Name: DEMODrawLine
475
476 Description: Draws a line on a bitmap
477
478 Arguments: sx: X-coordinate of the starting point
479 sy: Y-coordinate of the starting point
480 tx : Width to the ending point in the x-direction
481 ty: Width to the ending point in the Y-direction
482 color: the color to set
483
484 Returns: None
485 *---------------------------------------------------------------------------*/
DEMOiDrawLine(int sx,int sy,int tx,int ty,GXRgb color)486 void DEMOiDrawLine(int sx, int sy, int tx, int ty, GXRgb color)
487 {
488 DEMOBitmapContext *context = &bitmap;
489 int tmp;
490 // Normalize in the x-direction
491 if (sx > tx)
492 {
493 tmp = sx + 1, sx = tx + 1, tx = tmp;
494 tmp = sy, sy = ty, ty = tmp;
495 }
496 {
497 GXRgb *dst = NULL;
498 int wx = tx - sx;
499 int wy = ty - sy;
500 // Optimize vertically
501 if (!wx)
502 {
503 if (wy < 0)
504 {
505 wy = -wy;
506 tmp = sy + 1, sy = ty + 1, ty = tmp;
507 }
508 if ((sx >= 0) && (sx < GX_LCD_SIZE_X) && (sy < GX_LCD_SIZE_Y))
509 {
510 if (sy < 0)
511 {
512 wy += sy, sy = 0;
513 }
514 if (wy > GX_LCD_SIZE_Y - sy)
515 {
516 wy = GX_LCD_SIZE_Y - sy;
517 }
518 dst = &context->bitmap_frame[sx + sy * GX_LCD_SIZE_X];
519 while (--wy >= 0)
520 {
521 *dst = color;
522 dst += GX_LCD_SIZE_X;
523 }
524 }
525 }
526 // Optimize horizontally
527 else if (!wy)
528 {
529 if ((sy >= 0) && (sy < GX_LCD_SIZE_Y) && (sx < GX_LCD_SIZE_X))
530 {
531 if (sx < 0)
532 {
533 wx += sx, sx = 0;
534 }
535 if (wx > GX_LCD_SIZE_X - sx)
536 {
537 wx = GX_LCD_SIZE_X - sx;
538 }
539 dst = &context->bitmap_frame[sx + sy * GX_LCD_SIZE_X];
540 MI_CpuFill16(dst, color, wx * sizeof(GXRgb));
541 }
542 }
543 // A general all-purpose line with a slope
544 else
545 {
546 int n, dx, dy;
547 int y_delta = +1;
548 int y_ofs = GX_LCD_SIZE_X;
549 dst = &context->bitmap_frame[sx + sy * GX_LCD_SIZE_X];
550 if (wy < 0)
551 {
552 wy = -wy;
553 y_delta = -y_delta;
554 y_ofs = -y_ofs;
555 }
556 dx = wy - 1, dy = wx - 1;
557 --sx, sy -= y_delta;
558 for (n = wx * wy; --n >= 0;)
559 {
560 BOOL moved = FALSE;
561 if (++dx >= wy)
562 {
563 moved = TRUE, dx = 0, ++sx, dst += 1;
564 }
565 if (++dy >= wx)
566 {
567 moved = TRUE, dy = 0, sy += y_delta, dst += y_ofs;
568 }
569 if (moved &&
570 (sx >= 0) && (sx < GX_LCD_SIZE_X) &&
571 (sy >= 0) && (sy < GX_LCD_SIZE_Y))
572 {
573 *dst = color;
574 }
575 }
576 }
577 }
578 }
579
580 /*---------------------------------------------------------------------------*
581 Name: DEMODrawFrame
582
583 Description: Renders a frame to the bitmap.
584
585 Arguments: x: x coordinate for rendering
586 y: y coordinate for rendering
587 wx: x width for rendering
588 wy: y width for rendering
589 color: The color to set
590
591 Returns: None
592 *---------------------------------------------------------------------------*/
DEMOiDrawFrame(int x,int y,int wx,int wy,GXRgb color)593 void DEMOiDrawFrame(int x, int y, int wx, int wy, GXRgb color)
594 {
595 DEMOiFillRect(x, y, wx, 1, color);
596 DEMOiFillRect(x, y + wy - 1, wx, 1, color);
597 DEMOiFillRect(x, y + 1, 1, wy - 1, color);
598 DEMOiFillRect(x + wx - 1, y + 1, 1, wy - 1, color);
599 }
600
601 /*---------------------------------------------------------------------------*
602 Name: DEMODrawText
603
604 Description: Renders a string on a bitmap
605
606 Arguments: x: x coordinate for rendering
607 y: y coordinate for rendering
608 format: Formatted character string
609
610 Returns: None
611 *---------------------------------------------------------------------------*/
DEMODrawText(int x,int y,const char * format,...)612 void DEMODrawText(int x, int y, const char *format, ...)
613 {
614 static char tmp[512];
615 {
616 va_list va;
617 va_start(va, format);
618 (void)OS_VSNPrintf(tmp, sizeof(tmp) - 2, format, va);
619 va_end(va);
620 }
621 {
622 DEMOBitmapContext *context = &bitmap;
623 const char *s = tmp;
624 int n = sizeof(tmp) - 1;
625 GXRgb *p = &context->bitmap_frame[x + y * GX_LCD_SIZE_X];
626 GXRgb txt = context->bitmap_text_color;
627 GXRgb gnd = context->bitmap_ground_color;
628 int px = 0;
629 int rep = 0;
630 for (; (n > 0) && *s; ++s, --n)
631 {
632 int c = (u8)*s;
633 if (STD_IsSjisLeadByte(c))
634 {
635 c = (c << 8) | (u8)*++s;
636 }
637 switch (c)
638 {
639 case '\0':
640 return;
641 case '\r':
642 c = s[1];
643 if (c == '\n')
644 {
645 ++s, --n;
646 }
647 case '\n':
648 y += 8;
649 p += GX_LCD_SIZE_X * 8;
650 px = 0;
651 break;
652 case '\t':
653 {
654 const int align = 4;
655 rep = align - ((px / 8) & (align - 1));
656 c = ' ';
657 }
658 goto put_char;
659 default:
660 rep = 1;
661 goto put_char;
662
663 put_char:
664 while (--rep >= 0)
665 {
666 int tx = x + px;
667 if ((tx > -8) && (tx < GX_LCD_SIZE_X) &&
668 (y > -8) && (y < GX_LCD_SIZE_Y))
669 {
670 int ox = 0, oy = 0;
671 int wx = 8, wy = 8;
672 if (tx < 0)
673 {
674 ox = -tx;
675 }
676 else
677 {
678 wx = MATH_MIN(wx, GX_LCD_SIZE_X - tx);
679 }
680 if (y < 0)
681 {
682 oy = -y;
683 }
684 else
685 {
686 wy = MATH_MIN(wy, GX_LCD_SIZE_Y - y);
687 }
688 {
689 const u32* DEMO_GetSjisFont(int code);
690 const u32 *src = DEMO_GetSjisFont(c);
691 GXRgb *dst = &p[GX_LCD_SIZE_X * oy + px];
692 int stroke = GX_LCD_SIZE_X;
693 for (; oy < wy; ++oy)
694 {
695 int i;
696 const u32 bits = src[oy];
697 for (i = ox; i < wx; ++i)
698 {
699 if (((bits >> (i * 4)) & 0xF) != 0)
700 {
701 dst[i] = txt;
702 }
703 else if (gnd != DEMO_RGB_NONE)
704 {
705 dst[i] = gnd;
706 }
707 }
708 dst += stroke;
709 }
710 }
711 }
712 px += 8;
713 }
714 break;
715 }
716 }
717 context->bitmap_modified = 1;
718 }
719 }
720
721 /*---------------------------------------------------------------------------*
722 Name: DEMOClearString
723
724 Description: Clears all BG text
725
726 Arguments: None
727
728 Returns: None
729 *---------------------------------------------------------------------------*/
DEMOClearString(void)730 void DEMOClearString(void)
731 {
732 DEMOBitmapContext *context = &bitmap;
733 MI_CpuFillFast(context->main_bg, 0x00000000, sizeof(context->main_bg));
734 context->main_bg_modified = 1;
735 }
736
737 /*---------------------------------------------------------------------------*
738 Name: DEMOPutString
739
740 Description: Renders BG text.
741
742 Arguments: x: x coordinate for rendering
743 y: y coordinate for rendering
744 format: Formatted character string
745
746 Returns: None
747 *---------------------------------------------------------------------------*/
DEMOPutString(int x,int y,const char * format,...)748 void DEMOPutString(int x, int y, const char *format, ...)
749 {
750 DEMOBitmapContext *context = &bitmap;
751 u16 *dst = &context->main_bg[y * 32];
752 const int palette = 0;
753 char tmp[32 + 1];
754 {
755 va_list va;
756 va_start(va, format);
757 (void)OS_VSNPrintf(tmp + x, sizeof(tmp) - x, format, va);
758 va_end(va);
759 }
760 for (; (x < 32) && tmp[x]; ++x)
761 {
762 dst[x] = (u16)((u8)tmp[x] | (palette << 12));
763 }
764 context->main_bg_modified = 1;
765 }
766
767 /*---------------------------------------------------------------------------*
768 Name: DEMOPutLog
769
770 Description: Displays a log string to the sub screen
771
772 Arguments: format: Formatted character string
773
774 Returns: None
775 *---------------------------------------------------------------------------*/
DEMOPutLog(const char * format,...)776 void DEMOPutLog(const char *format, ...)
777 {
778 DEMOBitmapContext *context = &bitmap;
779 static char tmp[512];
780 {
781 va_list va;
782 va_start(va, format);
783 (void)OS_VSNPrintf(tmp, sizeof(tmp), format, va);
784 va_end(va);
785 }
786 {
787 const char *src = tmp;
788 char *dst = context->sub_log[context->sub_log_count % 24];
789 int x = STD_GetStringLength(dst);
790 for (; *src; ++src)
791 {
792 switch (*src)
793 {
794 case '\r':
795 if (src[1] == '\n')
796 {
797 break;
798 }
799 // fall
800 case '\n':
801 dst[(x < 32) ? x : 32] = '\0';
802 ++context->sub_log_count;
803 dst = context->sub_log[context->sub_log_count % 24];
804 x = 0;
805 break;
806 default:
807 if (x < 32)
808 {
809 dst[x++] = *src;
810 }
811 break;
812 }
813 }
814 dst[x] = '\0';
815 }
816 context->sub_bg_modified = 1;
817 }
818
819 /*---------------------------------------------------------------------------*
820 Name: DEMOHookConsole
821
822 Description: Adds a hook with OS_PutString and configures output to also be sent to the log
823
824 Arguments: None
825
826 Returns: None
827 *---------------------------------------------------------------------------*/
DEMOHookConsole(void)828 void DEMOHookConsole(void)
829 {
830 #ifndef SDK_FINALROM
831 DEMOBitmapContext *context = &bitmap;
832 // Dummy output to fix the output target to an unchanging value
833 OS_FPutString(0, "");
834 // Switch the output function
835 context->HookedConsole = OS_FPutString;
836 OS_FPutString = LogConsole;
837 #endif // SDK_FINALROM
838 }
839
840 /*---------------------------------------------------------------------------*
841 Name: DEMOSetViewPort
842
843 Description: Configures the viewport and projection
844
845 Arguments: x: X-coordinate at the upper left
846 y: Y-coordinate at the upper left
847 wx: Width of the viewport in the x-direction
848 wy: Width of the viewport in the y-direction
849
850 Returns: None
851 *---------------------------------------------------------------------------*/
DEMOSetViewPort(int x,int y,int wx,int wy)852 void DEMOSetViewPort(int x, int y, int wx, int wy)
853 {
854 G3_ViewPort(x, (GX_LCD_SIZE_Y - (y + wy)), (x + wx) - 1, (GX_LCD_SIZE_Y - y) - 1);
855 {
856 fx32 right = FX32_ONE;
857 fx32 top = FX32_ONE * wy / wx;
858 fx32 near = FX32_ONE;
859 fx32 far = FX32_ONE * 400;
860 G3_Perspective(FX32_SIN30, FX32_COS30, FX32_ONE * wx / wy, near, far, NULL);
861 G3_StoreMtx(0);
862 }
863 }
864