1 /*
2 * OpenBOR - http://www.LavaLit.com
3 * -----------------------------------------------------------------------
4 * Licensed under the BSD license, see LICENSE in OpenBOR root for details.
5 *
6 * Copyright (c) 2004 - 2011 OpenBOR Team
7 */
8
9 #include <stdio.h>
10 #include <stdarg.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <pspdisplay.h>
14 #include <psputils.h>
15 #include <pspgu.h>
16 #include "hankaku.c"
17 #include "image.h"
18 #include "types.h"
19 #include "vertex.h"
20 #include "graphics.h"
21 #include "kernel/kernel.h"
22 #include "dvemgr/dvemgr.h"
23
24 #define PSP_VRAM_BASE ((u32*)(0x40000000|0x04000000))
25 #define PSP_VRAM_ADDRESS(x) (x ? 0x0a000000 : 0x44000000)
26 #define PSP_LCD_TEXTURE_WIDTH 512
27 #define PSP_TV_TEXTURE_WIDTH 768
28 #define PSP_TV_WIDTH 720
29 #define PSP_TV_HEIGHT 480
30
31 typedef struct{
32 unsigned short u, v;
33 short x, y, z;
34 }Vertex;
35
36 typedef void (*BlitScreenToScreen)(int, int, s_screen*);
37 typedef void (*FlipScreen)();
38
39 void blitScreenToScreenRaw(int width, int height, s_screen* source);
40 void blitScreenToScreenPal(int width, int height, s_screen* source);
41 void flipScreenLCD();
42 void flipScreenTVI();
43
44 static BlitScreenToScreen pBlitScreenToScreen;
45 static FlipScreen pFlipScreen;
46
47 unsigned int __attribute__((aligned(16))) list[262144];
48
49 static int PSP_FRAMEBUFFER_SIZE;
50 static int PSP_TEXTURE_FILTER;
51 static int PSP_TEXTURE_WIDTH;
52 static int PSP_DISPLAY_HEIGHT;
53 static int PSP_DISPLAY_WIDTH;
54 static int PSP_BUFFER_SIZE;
55 static int PSP_COLOR_FORMAT;
56 static int tvOverScanBottom;
57 static int tvOverScanRight;
58 static int tvOverScanLeft;
59 static int tvOverScanTop;
60 static int tvAspectRatio;
61 static int screenHeight;
62 static int screenWidth;
63 static int screenLeft;
64 static int screenTop;
65 static int initialized;
66 static void* drawBuffer;
67 static void* dispBuffer;
68
69 char* displayName[PSP_DISPLAY_MODES] = {"LCD", "Composite", "Progressive", "Interlaced"};
70 int displayMode;
71
72 char* filterName[PSP_DISPLAY_FILTERS] = {"Linear", "Bilinear"};
73 DisplayFormat displayFormat[PSP_DISPLAY_FORMATS] = {{"320x240 (4x3)", 80, 16, 320, 240},
74 {"360x270 (4x3)", 60, 01, 360, 270},
75 {"384x272 (24x17)", 48, 00, 384, 272},
76 {"480x272 (16x9)", 00, 00, 480, 272}};
checkCable(int mode)77 int checkCable(int mode)
78 {
79 if(getHardwareModel()==1)
80 {
81 if(pspDveMgrCheckVideoOut() > 0) return mode;
82 else return 0;
83 }
84 return 0;
85 }
86
guStart()87 void guStart()
88 {
89 sceGuStart(GU_DIRECT, list);
90 }
91
guSetup()92 static void guSetup()
93 {
94 sceKernelDcacheWritebackInvalidateAll();
95 guStart();
96 sceGuDrawBuffer(GU_PSM_8888, 0, PSP_TEXTURE_WIDTH);
97 sceGuDispBuffer(PSP_DISPLAY_WIDTH, PSP_DISPLAY_HEIGHT, 0, PSP_TEXTURE_WIDTH);
98 sceGuOffset(2048 - (PSP_DISPLAY_WIDTH >> 1), 2048 - (PSP_DISPLAY_HEIGHT >> 1));
99 sceGuViewport(2048, 2048, PSP_DISPLAY_WIDTH, PSP_DISPLAY_HEIGHT);
100 sceGuScissor(0, 0, PSP_DISPLAY_WIDTH, PSP_DISPLAY_HEIGHT);
101 sceGuEnable(GU_SCISSOR_TEST);
102 sceGuDisable(GU_CULL_FACE);
103 sceGuDisable(GU_DEPTH_TEST);
104 sceGuDepthMask(GU_TRUE);
105 sceGuDisable(GU_COLOR_TEST);
106 sceGuDisable(GU_ALPHA_TEST);
107 sceGuDisable(GU_LIGHTING);
108 sceGuEnable(GU_TEXTURE_2D);
109 sceGuClearColor(0);
110 sceGuClear(GU_COLOR_BUFFER_BIT);
111 sceGuFinish();
112 sceGuSync(0, 0);
113 memset(drawBuffer, 0, PSP_BUFFER_SIZE);
114 memset(dispBuffer, 0, PSP_BUFFER_SIZE);
115 sceDisplayWaitVblankStart();
116 sceDisplaySetFrameBuf(drawBuffer, PSP_TEXTURE_WIDTH, PSP_DISPLAY_PIXEL_FORMAT_8888, PSP_DISPLAY_SETBUF_NEXTFRAME);
117 }
118
setGraphicsVideoMode(int mode)119 void setGraphicsVideoMode(int mode)
120 {
121 if(mode && getHardwareModel()==1)
122 {
123 PSP_BUFFER_SIZE = PSP_TV_TEXTURE_WIDTH * 4;
124 PSP_FRAMEBUFFER_SIZE = PSP_TV_TEXTURE_WIDTH * (mode%2?PSP_LCD_TEXTURE_WIDTH:PSP_TV_HEIGHT) * 4;
125 PSP_TEXTURE_WIDTH = PSP_TV_TEXTURE_WIDTH;
126 PSP_DISPLAY_WIDTH = PSP_TV_WIDTH;
127 PSP_DISPLAY_HEIGHT = PSP_TV_HEIGHT;
128 pspDveMgrSetVideoOut(mode!=1?0:2, mode%2?0x1D1:0x1D2, 720, mode%2?503:480, 1, 15, 0);
129 }
130 else
131 {
132 PSP_BUFFER_SIZE = PSP_LCD_TEXTURE_WIDTH * 4;
133 PSP_FRAMEBUFFER_SIZE = PSP_LCD_TEXTURE_WIDTH * PSP_LCD_HEIGHT * 4;
134 PSP_TEXTURE_WIDTH = PSP_LCD_TEXTURE_WIDTH;
135 PSP_DISPLAY_WIDTH = PSP_LCD_WIDTH;
136 PSP_DISPLAY_HEIGHT = PSP_LCD_HEIGHT;
137 if(getHardwareModel()==1) pspDveMgrSetVideoOut(0, 0, 480, 272, 1, 15, 0);
138 }
139 }
140
setGraphics(int mode,int pixel)141 void setGraphics(int mode, int pixel)
142 {
143 if(mode%2) pFlipScreen = flipScreenTVI;
144 else pFlipScreen = flipScreenLCD;
145 switch(pixel)
146 {
147 case PIXEL_32:
148 pBlitScreenToScreen = blitScreenToScreenRaw;
149 PSP_COLOR_FORMAT = GU_PSM_8888;
150 break;
151 case PIXEL_16:
152 pBlitScreenToScreen = blitScreenToScreenRaw;
153 PSP_COLOR_FORMAT = GU_PSM_5650;
154 break;
155 default:
156 pBlitScreenToScreen = blitScreenToScreenPal;
157 PSP_COLOR_FORMAT = GU_PSM_8888;
158 break;
159 }
160 }
161
initGraphics(int mode,int pixel)162 void initGraphics(int mode, int pixel)
163 {
164 displayMode = checkCable(mode);
165 setGraphicsTVAspectRatio(0);
166 setGraphicsVideoMode(displayMode);
167 drawBuffer = (void*)PSP_VRAM_ADDRESS(displayMode%2);
168 dispBuffer = (void*)PSP_VRAM_ADDRESS(displayMode%2) + PSP_FRAMEBUFFER_SIZE;
169 initialized = 1;
170 guSetup();
171 setGraphicsScreen(displayFormat[3], pixel, 0);
172 }
173
disableGraphics()174 void disableGraphics()
175 {
176 initialized = 0;
177 }
178
drawTexture(tVertexTexture * t)179 void drawTexture(tVertexTexture *t)
180 {
181 Vertex *vertex = sceGuGetMemory(2 * sizeof(Vertex));
182 vertex[0].u = t->output_texture_x_start;
183 vertex[0].v = t->output_texture_y_start;
184 vertex[0].x = t->output_vertex_x_start;
185 vertex[0].y = t->output_vertex_y_start;
186 vertex[0].z = 0;
187 vertex[1].u = t->output_texture_x_end;
188 vertex[1].v = t->output_texture_y_end;
189 vertex[1].x = t->output_vertex_x_end;
190 vertex[1].y = t->output_vertex_y_end;
191 vertex[1].z = 0;
192 sceGuDrawArray(GU_SPRITES, GU_TEXTURE_16BIT | GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, vertex);
193 }
194
drawVertex(tVertexTexture t)195 static inline void drawVertex(tVertexTexture t)
196 {
197 do{
198 getVertexTexture(&t);
199 drawTexture(&t);
200 }while(t.output_last == 0);
201 }
202
setGraphicsTVAspectRatio(int ar)203 void setGraphicsTVAspectRatio(int ar)
204 {
205 tvAspectRatio = ar;
206 }
207
setGraphicsTVOverScan(int left,int top,int right,int bottom)208 void setGraphicsTVOverScan(int left, int top, int right, int bottom)
209 {
210 tvOverScanLeft = left;
211 tvOverScanTop = top;
212 tvOverScanRight = right;
213 tvOverScanBottom = bottom;
214 }
215
setGraphicsScreen(DisplayFormat display,int pixel,int filter)216 void setGraphicsScreen(DisplayFormat display, int pixel, int filter)
217 {
218 setGraphics(displayMode, pixel);
219 PSP_TEXTURE_FILTER = filter;
220 screenTop = display.top;
221 screenLeft = display.left;
222 screenWidth = display.width;
223 screenHeight = display.height;
224 }
225
clearScreen(Color color)226 void clearScreen(Color color)
227 {
228 if(!initialized) return;
229 guStart();
230 sceGuClearColor(color);
231 sceGuClearDepth(color);
232 sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT);
233 sceGuFinish();
234 sceGuSync(0, 0);
235 }
236
flipScreen()237 void flipScreen()
238 {
239 pFlipScreen();
240 }
241
flipScreenLCD()242 void flipScreenLCD()
243 {
244 if(!initialized) return;
245 sceGuSwapBuffers();
246 }
247
flipScreenTVI()248 void flipScreenTVI()
249 {
250 if(!initialized) return;
251 sceKernelDcacheWritebackInvalidateAll();
252 guStart();
253 sceGuCopyImage(GU_PSM_8888, 0, 0, PSP_DISPLAY_WIDTH, PSP_DISPLAY_HEIGHT>>1, PSP_TEXTURE_WIDTH<<1, (void*)PSP_VRAM_BASE+PSP_BUFFER_SIZE, 0, 0, PSP_TEXTURE_WIDTH, drawBuffer);
254 sceGuCopyImage(GU_PSM_8888, 0, 0, PSP_DISPLAY_WIDTH, PSP_DISPLAY_HEIGHT>>1, PSP_TEXTURE_WIDTH<<1, PSP_VRAM_BASE, 0, 0, PSP_TEXTURE_WIDTH, (void*)drawBuffer+PSP_BUFFER_SIZE*262);
255 sceGuFinish();
256 sceGuSync(0, 0);
257 sceGuSwapBuffers();
258 }
259
blitImageToScreen(int sx,int sy,int width,int height,Image * source,int dx,int dy)260 void blitImageToScreen(int sx, int sy, int width, int height, Image* source, int dx, int dy)
261 {
262 if(!initialized) return;
263 sceKernelDcacheWritebackInvalidateAll();
264 guStart();
265 sceGuDisable(GU_BLEND);
266 sceGuTexMode(GU_PSM_8888, 0, 0, 0);
267 sceGuTexImage(0, source->textureWidth, source->textureHeight, source->textureWidth, source->data);
268 sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGB);
269 sceGuTexFilter(PSP_TEXTURE_FILTER, PSP_TEXTURE_FILTER);
270 sceGuTexWrap(GU_CLAMP, GU_CLAMP);
271 tVertexTexture texture;
272 setVertexTexture(&texture, width, height, 16, screenWidth+sx, screenHeight+sy, screenLeft+dx, screenTop+dy);
273 drawVertex(texture);
274 sceGuFinish();
275 sceGuSync(0, 0);
276 }
277
blitAlphaImageToScreen(int sx,int sy,int width,int height,Image * source,int dx,int dy)278 void blitAlphaImageToScreen(int sx, int sy, int width, int height, Image* source, int dx, int dy)
279 {
280 if(!initialized) return;
281 sceKernelDcacheWritebackInvalidateAll();
282 guStart();
283 sceGuEnable(GU_BLEND);
284 sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0);
285 sceGuTexMode(GU_PSM_8888, 0, 0, 0);
286 sceGuTexImage(0, source->textureWidth, source->textureHeight, source->textureWidth, source->data);
287 sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
288 sceGuTexFilter(PSP_TEXTURE_FILTER, PSP_TEXTURE_FILTER);
289 sceGuTexWrap(GU_CLAMP, GU_CLAMP);
290 tVertexTexture texture;
291 setVertexTexture(&texture, width, height, 16, screenWidth+sx, screenHeight+sy, screenLeft+dx, screenTop+dy);
292 drawVertex(texture);
293 sceGuFinish();
294 sceGuSync(0, 0);
295 }
296
blitScreenToScreen(int width,int height,s_screen * source)297 void blitScreenToScreen(int width, int height, s_screen* source)
298 {
299 pBlitScreenToScreen(width, height, source);
300 }
301
blitScreenToScreenRaw(int width,int height,s_screen * source)302 void blitScreenToScreenRaw(int width, int height, s_screen* source)
303 {
304 if(!initialized) return;
305 sceKernelDcacheWritebackInvalidateAll();
306 guStart();
307 sceGuCopyImage(PSP_COLOR_FORMAT, 0, 0, width, height, source->width, source->data, 0, 0, PSP_LCD_TEXTURE_WIDTH, dispBuffer);
308 sceGuTexMode(PSP_COLOR_FORMAT, 0, 0, 0);
309 sceGuTexImage(0, 512, 512, 512, dispBuffer);
310 sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGB);
311 sceGuTexFilter(PSP_TEXTURE_FILTER, PSP_TEXTURE_FILTER);
312 tVertexTexture texture;
313 setVertexTexture(&texture, width, height, 16, screenWidth, screenHeight, screenLeft, screenTop);
314 drawVertex(texture);
315 sceGuFinish();
316 }
317
blitScreenToScreenPal(int width,int height,s_screen * source)318 void blitScreenToScreenPal(int width, int height, s_screen* source)
319 {
320 if(!initialized) return;
321 sceKernelDcacheWritebackInvalidateAll();
322 guStart();
323 sceGuClutMode(PSP_COLOR_FORMAT, 0, 255, 0);
324 sceGuClutLoad((32), palette);
325 sceGuTexMode(GU_PSM_T8, 0, 0, 0);
326 sceGuTexImage(0, 512, 512, source->width, source->data);
327 sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGB);
328 sceGuTexFilter(PSP_TEXTURE_FILTER, PSP_TEXTURE_FILTER);
329 tVertexTexture texture;
330 setVertexTexture(&texture, width, height, 16, screenWidth, screenHeight, screenLeft, screenTop);
331 drawVertex(texture);
332 sceGuFinish();
333 sceGuSync(0, 0);
334 }
335
printText(Image * source,int x,int y,int col,int backcol,int fill,char * format,...)336 void printText(Image* source, int x,int y,int col,int backcol,int fill,char *format, ...)
337 {
338 Color data_ptr;
339 Color *data;
340 u8 *font;
341 int x1,y1,i;
342 unsigned char ch = 0;
343 char buf[128] = {""};
344 va_list arglist;
345 va_start(arglist, format);
346 vsprintf(buf, format, arglist);
347 va_end(arglist);
348 for(i=0; i<sizeof(buf); i++)
349 {
350 ch = buf[i];
351 // mapping
352 if (ch<0x20) ch = 0;
353 else if (ch<0x80) { ch -= 0x20; }
354 else if (ch<0xa0) { ch = 0; }
355 else ch -= 0x40;
356 font = (u8 *)&hankaku_font10[ch*10];
357 // draw
358 data = source->data + x + y * source->textureWidth;
359 for(y1=0;y1<10;y1++)
360 {
361 data_ptr = *font++;
362 for(x1=0;x1<5;x1++)
363 {
364 if (data_ptr & 1) *data = col;
365 else if (fill) *data = backcol;
366 data++;
367 data_ptr = data_ptr >> 1;
368 }
369 data += source->textureWidth-5;
370 }
371 x+=5;
372 }
373 }
374