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