port-work; won't compile or even work
[ppcskel.git] / console.c
1 /*
2         BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader.
3         Requires mini.
4
5 Copyright (C) 2009              bLAStY <blasty@bootmii.org>
6 Copyright (C) 2009              John Kelley <wiidev@kelley.ca>
7
8 # This code is licensed to you under the terms of the GNU GPL, version 2;
9 # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
10 */
11
12 #include "bootmii_ppc.h"
13
14 #include "video_low.h"
15 #include "console.h"
16 #include "string.h"
17 #include "printf.h"
18 #include "malloc.h"
19
20 #include <stdarg.h>
21
22 typedef struct {
23         u32 x, y;
24         u32 width, height;
25         u8 *raw_data;
26         u32 *yuv_data;  
27         u32 active;
28         u8 has_alpha;
29 } gfx_rect;
30
31 #define CONSOLE_WIDTH 500
32 #define CONSOLE_LINES 10
33 #define CONSOLE_Y 100
34
35 #define CONSOLE_X  58
36 #define CONSOLE_CHAR_HEIGHT 16
37 #define CONSOLE_ROW_HEIGHT (CONSOLE_CHAR_HEIGHT + 1) 
38
39 static u32 *xfb = NULL;
40 static int y_add = 0;
41
42 u32 *font_yuv[255];
43
44 u32 *get_xfb(void) {
45         return xfb;
46 }
47
48 static void memcpy32(u32 *dst, u32 *src, u32 count) {
49         while(count--) {
50                 *dst = *src;
51                 sync_after_write((const void *)dst, 4);
52
53                 dst++;
54                 src++;
55         }
56 }
57
58 static void memset32(u32 *dst, u32 setval, u32 count) {
59         while(count--) {
60                 *dst = setval;
61                 sync_after_write((const void *)dst, 4);
62
63                 dst++;
64         }
65 }
66
67 u32 pal_idx(int i, u8 *pal, u8 *gfx) { 
68         u32 pidx = gfx[i];
69         pidx *= 3;
70
71         return (pal[pidx+0] << 16) | (pal[pidx+1] << 8) | (pal[pidx+2]);
72 }
73
74 int make_yuv(u8 r1, u8 g1, u8 b1, u8 r2, u8 g2, u8 b2) {
75   int y1, cb1, cr1, y2, cb2, cr2, cb, cr;
76  
77   y1 = (299 * r1 + 587 * g1 + 114 * b1) / 1000;
78   cb1 = (-16874 * r1 - 33126 * g1 + 50000 * b1 + 12800000) / 100000;
79   cr1 = (50000 * r1 - 41869 * g1 - 8131 * b1 + 12800000) / 100000;
80  
81   y2 = (299 * r2 + 587 * g2 + 114 * b2) / 1000;
82   cb2 = (-16874 * r2 - 33126 * g2 + 50000 * b2 + 12800000) / 100000;
83   cr2 = (50000 * r2 - 41869 * g2 - 8131 * b2 + 12800000) / 100000;
84  
85   cb = (cb1 + cb2) >> 1;
86   cr = (cr1 + cr2) >> 1;
87  
88   return ((y1 << 24) | (cb << 16) | (y2 << 8) | cr);
89 }
90
91 void fill_rect(int x, int y, int w, int h, u8 r, u8 g, u8 b) {
92         u32 *fb = xfb;
93         u32 col = make_yuv(r,g,b, r,g,b);
94
95         fb += ((y + y_add) * (640 >> 1));
96         fb += (x >> 1);
97
98         for(y = 0; y < h; y++) {
99                 memset32(fb, col, w >> 1);
100                 fb += (640 >> 1);
101         }
102 }
103
104 void gfx_draw_rect(gfx_rect *n) {
105         u32 y;
106         gfx_rect *d_rect;
107         u32 *fb = xfb;
108
109         d_rect = n;
110
111         fb += ((d_rect->y + y_add) * (640 >> 1));
112         fb += (d_rect->x >> 1);
113
114         for(y = 0; y < d_rect->height; y++) {
115                 memcpy32(fb, d_rect->yuv_data + ((d_rect->width >> 1) * y), d_rect->width >> 1);
116                 fb += (640 >> 1);
117         }
118 }
119
120 void scroll(void) {
121         unsigned int y;
122         u32 *fb = xfb;
123
124         fb += ((CONSOLE_Y+y_add) * (640 >> 1));
125         fb += (CONSOLE_X >> 1);
126
127         fb += (CONSOLE_ROW_HEIGHT * (640 >> 1));
128
129         for (y = 0; y < CONSOLE_LINES*CONSOLE_ROW_HEIGHT; y++) {
130                 memcpy32(fb - (CONSOLE_ROW_HEIGHT * 320), fb, CONSOLE_WIDTH >> 1);
131                 fb += 320;
132         }
133         
134         fill_rect(CONSOLE_X, CONSOLE_Y+(CONSOLE_LINES-1)*CONSOLE_ROW_HEIGHT,
135                 CONSOLE_WIDTH, CONSOLE_ROW_HEIGHT, 0, 0, 0);
136 }
137
138 void print_str_noscroll(int x, int y, char *str) {
139         unsigned int i;
140         gfx_rect d_char;
141
142         d_char.x = x;
143
144         for (i = 0; i < strlen(str); i++) {
145                 d_char.width  = 8;
146                 d_char.height = CONSOLE_CHAR_HEIGHT;
147                 d_char.y = y;
148
149                 if (str[i] == '\n') {
150                         y += CONSOLE_CHAR_HEIGHT;
151                         d_char.x = x;
152                         continue;
153                 }       
154
155                 d_char.yuv_data = font_yuv[ (int)str[i] ];
156                 gfx_draw_rect(&d_char);
157                 d_char.x += 10;
158         }
159 }
160
161 void print_str(const char *str, size_t len) {
162         unsigned int i;
163         gfx_rect d_char;
164
165         scroll();
166         d_char.width  = 8;
167         d_char.height = CONSOLE_CHAR_HEIGHT;
168         d_char.y = CONSOLE_Y + ((CONSOLE_LINES - 1) * CONSOLE_ROW_HEIGHT);
169
170         for (i = 0; i < len; i++) {
171                 d_char.x = CONSOLE_X + (i * 10);
172                 d_char.yuv_data = font_yuv[(int) str[i]];
173                 gfx_draw_rect(&d_char);
174         }
175 }
176
177 int gfx_printf(const char *fmt, ...)
178 {
179         va_list args;
180         char buffer[40];
181         int i;
182
183         memset(buffer, 0, sizeof buffer);
184         va_start(args, fmt);
185         i = vsnprintf(buffer, sizeof(buffer), fmt, args);
186         va_end(args);
187
188         if (i > 0) {
189                 print_str(buffer, i);
190                 printf("%s\n", buffer);
191         } else
192                 scroll();
193
194         return i;
195 }
196
197 void font_to_yuv(void) {
198         int i, x, y;
199         u8 lr,lg,lb, rr,rg,rb;
200
201         for (i = 0; i < 255; i++) {
202                 font_yuv[i] = (u32*)malloc(8*CONSOLE_CHAR_HEIGHT*2);
203
204                 for (y = 0; y < CONSOLE_CHAR_HEIGHT; y++) {
205                         for (x = 0; x < 8; x+=2) {
206                                 if (((console_font_8x16[(i*CONSOLE_CHAR_HEIGHT)+y] >> (7-x)) & 0x01) == 1) {
207                                         lr = 255; lg = 255; lb = 255;
208                                 } else {
209                                         lr = 0; lg = 0; lb = 0;
210                                 }
211
212                                 if (((console_font_8x16[(i*CONSOLE_CHAR_HEIGHT)+y] >> (7-(x+1))) & 0x01) == 1) {
213                                         rr = 255; rg = 255; rb = 255;
214                                 } else {
215                                         rr = 0; rg = 0; rb = 0;
216                                 }
217
218                                 font_yuv[i][(y<<2)+(x>>1)] = make_yuv(lr, lg, lb, rr, rg, rb);
219                         }
220                 }
221         }
222 }
223
224 void init_fb(int vmode) {
225         int i;
226         u32 *fb;
227         u32 fill_col = make_yuv(0,0,0, 0,0,0);
228
229         font_to_yuv();
230
231         switch(vmode) {
232         case VIDEO_640X480_NTSCi_YUV16:
233         case VIDEO_640X480_PAL60_YUV16:
234         case VIDEO_640X480_NTSCp_YUV16:
235                 y_add = 0;
236                 break;
237
238         case VIDEO_640X480_PAL50_YUV16:
239                 y_add = 48;
240                 break;
241         }
242
243         xfb = memalign(32, 640 * (480 + (y_add*2)) * 2);
244
245         fb  = xfb;
246         for (i = 0; i < (480 + (y_add*2)) * 2 * (640 >> 1); i++) {
247                 *fb = fill_col;
248                 sync_after_write(fb, 4);
249                 fb++;
250         }
251 }
252