Mercurial > sdl-ios-xcode
comparison src/video/nds/SDL_ndsvideo.c @ 3976:8582c6a5ca16 SDL-1.2
Added initial support for Nintendo DS, based on the work by Troy Davis (GPF)
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 25 Jun 2007 00:50:20 +0000 |
parents | |
children | 722db1bd733c |
comparison
equal
deleted
inserted
replaced
3975:e85e65aec22f | 3976:8582c6a5ca16 |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997-2006 Sam Lantinga | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Lesser General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2.1 of the License, or (at your option) any later version. | |
9 | |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Lesser General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Lesser General Public | |
16 License along with this library; if not, write to the Free Software | |
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@libsdl.org | |
21 */ | |
22 #include "SDL_config.h" | |
23 | |
24 #include <nds.h> | |
25 #include <nds/registers_alt.h> | |
26 #include "SDL.h" | |
27 #include "SDL_error.h" | |
28 #include "SDL_video.h" | |
29 #include "SDL_mouse.h" | |
30 #include "../SDL_sysvideo.h" | |
31 #include "../SDL_pixels_c.h" | |
32 #include "../../events/SDL_events_c.h" | |
33 | |
34 #include "SDL_ndsvideo.h" | |
35 #include "SDL_ndsevents_c.h" | |
36 #include "SDL_ndsmouse_c.h" | |
37 | |
38 #define NDSVID_DRIVER_NAME "nds" | |
39 | |
40 /* Initialization/Query functions */ | |
41 static int NDS_VideoInit(_THIS, SDL_PixelFormat *vformat); | |
42 static SDL_Rect **NDS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); | |
43 static SDL_Surface *NDS_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); | |
44 static int NDS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); | |
45 static void NDS_VideoQuit(_THIS); | |
46 | |
47 /* Hardware surface functions */ | |
48 static int NDS_AllocHWSurface(_THIS, SDL_Surface *surface); | |
49 static int NDS_LockHWSurface(_THIS, SDL_Surface *surface); | |
50 static int NDS_FlipHWSurface(_THIS, SDL_Surface *surface); | |
51 static void NDS_UnlockHWSurface(_THIS, SDL_Surface *surface); | |
52 static void NDS_FreeHWSurface(_THIS, SDL_Surface *surface); | |
53 | |
54 /* etc. */ | |
55 static void NDS_UpdateRects(_THIS, int numrects, SDL_Rect *rects); | |
56 | |
57 /* NDS driver bootstrap functions */ | |
58 | |
59 static int NDS_Available(void) | |
60 { | |
61 return(1); | |
62 } | |
63 | |
64 static void NDS_DeleteDevice(SDL_VideoDevice *device) | |
65 { | |
66 SDL_free(device->hidden); | |
67 SDL_free(device); | |
68 } | |
69 | |
70 void on_irq_vblank() | |
71 { | |
72 // Disable interrupts | |
73 //REG_IME = 0; | |
74 scanKeys(); | |
75 | |
76 // VBLANK_INTR_WAIT_FLAGS |= IRQ_VBLANK; | |
77 // REG_IF |= IRQ_VBLANK; | |
78 //REG_IF = REG_IF; | |
79 | |
80 // Enable interrupts | |
81 //REG_IME = 1; | |
82 } | |
83 | |
84 static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, | |
85 SDL_Surface *dst, SDL_Rect *dstrect) | |
86 { | |
87 return 0; | |
88 } | |
89 | |
90 static int CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) | |
91 { | |
92 if (src->flags & SDL_SRCALPHA) return false; | |
93 if (src->flags & SDL_SRCCOLORKEY) return false; | |
94 if (src->flags & SDL_HWPALETTE ) return false; | |
95 if (dst->flags & SDL_SRCALPHA) return false; | |
96 if (dst->flags & SDL_SRCCOLORKEY) return false; | |
97 if (dst->flags & SDL_HWPALETTE ) return false; | |
98 | |
99 if (src->format->BitsPerPixel != dst->format->BitsPerPixel) return false; | |
100 if (src->format->BytesPerPixel != dst->format->BytesPerPixel) return false; | |
101 | |
102 src->map->hw_blit = HWAccelBlit; | |
103 return true; | |
104 } | |
105 | |
106 static SDL_VideoDevice *NDS_CreateDevice(int devindex) | |
107 { | |
108 SDL_VideoDevice *device=0; | |
109 | |
110 | |
111 /* Initialize all variables that we clean on shutdown */ | |
112 device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); | |
113 if ( device ) { | |
114 SDL_memset(device, 0, (sizeof *device)); | |
115 device->hidden = (struct SDL_PrivateVideoData *) | |
116 SDL_malloc((sizeof *device->hidden)); | |
117 } | |
118 if ( (device == NULL) || (device->hidden == NULL) ) { | |
119 SDL_OutOfMemory(); | |
120 if ( device ) { | |
121 SDL_free(device); | |
122 } | |
123 return(0); | |
124 } | |
125 SDL_memset(device->hidden, 0, (sizeof *device->hidden)); | |
126 | |
127 /* Set the function pointers */ | |
128 device->VideoInit = NDS_VideoInit; | |
129 device->ListModes = NDS_ListModes; | |
130 device->SetVideoMode = NDS_SetVideoMode; | |
131 device->CreateYUVOverlay = NULL; | |
132 device->SetColors = NDS_SetColors; | |
133 device->UpdateRects = NDS_UpdateRects; | |
134 device->VideoQuit = NDS_VideoQuit; | |
135 device->AllocHWSurface = NDS_AllocHWSurface; | |
136 device->CheckHWBlit = CheckHWBlit; | |
137 device->FillHWRect = NULL; | |
138 device->SetHWColorKey = NULL; | |
139 device->SetHWAlpha = NULL; | |
140 device->LockHWSurface = NDS_LockHWSurface; | |
141 device->UnlockHWSurface = NDS_UnlockHWSurface; | |
142 device->FlipHWSurface = NDS_FlipHWSurface; | |
143 device->FreeHWSurface = NDS_FreeHWSurface; | |
144 device->SetCaption = NULL; | |
145 device->SetIcon = NULL; | |
146 device->IconifyWindow = NULL; | |
147 device->GrabInput = NULL; | |
148 device->GetWMInfo = NULL; | |
149 device->InitOSKeymap = NDS_InitOSKeymap; | |
150 device->PumpEvents = NDS_PumpEvents; | |
151 device->info.blit_hw=1; | |
152 | |
153 device->free = NDS_DeleteDevice; | |
154 return device; | |
155 } | |
156 | |
157 VideoBootStrap NDS_bootstrap = { | |
158 NDSVID_DRIVER_NAME, "SDL NDS video driver", | |
159 NDS_Available, NDS_CreateDevice | |
160 }; | |
161 | |
162 u16* frontBuffer;// = (u16*)(0x06000000); | |
163 u16* backBuffer;// = (u16*)(0x06000000 + 256 * 256 * 2); | |
164 int NDS_VideoInit(_THIS, SDL_PixelFormat *vformat) | |
165 { | |
166 //printf("WARNING: You are using the SDL NDS video driver!\n"); | |
167 | |
168 /* Determine the screen depth (use default 8-bit depth) */ | |
169 /* we change this during the SDL_SetVideoMode implementation... */ | |
170 vformat->BitsPerPixel = 16; // mode 3 | |
171 vformat->BytesPerPixel = 2; | |
172 vformat->Rmask = 0x0000f800; | |
173 vformat->Gmask = 0x000007e0; | |
174 vformat->Bmask = 0x0000001f; | |
175 powerON(POWER_ALL); | |
176 irqInit(); | |
177 irqSet(IRQ_VBLANK, on_irq_vblank); | |
178 irqEnable(IRQ_VBLANK); | |
179 | |
180 //set the mode for 2 text layers and two extended background layers | |
181 //videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE); | |
182 videoSetMode(MODE_6_2D| DISPLAY_BG2_ACTIVE); | |
183 | |
184 //set the sub background up for text display (we could just print to one | |
185 //of the main display text backgrounds just as easily | |
186 videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE); //sub bg 0 will be used to print text | |
187 | |
188 //set the first two banks as background memory and the third as sub background memory | |
189 //D is not used..if you need a bigger background then you will need to map | |
190 //more vram banks consecutivly (VRAM A-D are all 0x20000 bytes in size) | |
191 //vramSetMainBanks(VRAM_A_MAIN_BG_0x6000000, VRAM_B_MAIN_BG_0x6020000,VRAM_C_SUB_BG , VRAM_D_LCD); | |
192 vramSetMainBanks(VRAM_A_MAIN_BG,VRAM_B_MAIN_BG,VRAM_C_MAIN_BG,VRAM_D_MAIN_BG); | |
193 //vramSetBankA(VRAM_A_MAIN_BG); | |
194 //vramSetBankB(VRAM_B_MAIN_BG); | |
195 //vramSetBankC(VRAM_C_MAIN_BG); | |
196 //vramSetBankD(VRAM_D_MAIN_BG); | |
197 //vramSetBankE(VRAM_E_MAIN_BG); | |
198 //vramSetBankF(VRAM_F_MAIN_BG); | |
199 //vramSetBankG(VRAM_G_MAIN_BG); | |
200 vramSetBankH(VRAM_H_SUB_BG); | |
201 vramSetBankI(VRAM_I_LCD); | |
202 | |
203 ////////////////set up text background for text///////////////////// | |
204 SUB_BG0_CR = BG_MAP_BASE(8); | |
205 | |
206 BG_PALETTE_SUB[255] = RGB15(31,31,31);//by default font will be rendered with color 255 | |
207 ///////////////set up our bitmap background/////////////////////// | |
208 | |
209 //BG3_CR = BG_BMP16_512x512; | |
210 | |
211 //these are rotation backgrounds so you must set the rotation attributes: | |
212 //these are fixed point numbers with the low 8 bits the fractional part | |
213 //this basicaly gives it a 1:1 translation in x and y so you get a nice flat bitmap | |
214 /* BG3_XDX = 1<<8; | |
215 BG3_XDY = 0; | |
216 BG3_YDX = 0; | |
217 BG3_YDY = 1<<8; | |
218 //our bitmap looks a bit better if we center it so scroll down (256 - 192) / 2 | |
219 BG3_CX = 0; | |
220 BG3_CY = 0; | |
221 */ | |
222 //consoleInit() is a lot more flexible but this gets you up and running quick | |
223 consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(8), (u16*)CHAR_BASE_BLOCK_SUB(0), 16); | |
224 | |
225 | |
226 frontBuffer =(u16*)(0x06000000); | |
227 //backBuffer =(u16*)(0x06000000 + 1024 * 512*2); | |
228 | |
229 //lcdSwap(); | |
230 /* We're done! */ | |
231 return(0); | |
232 } | |
233 | |
234 SDL_Rect **NDS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) | |
235 { | |
236 return (SDL_Rect **) -1; | |
237 } | |
238 | |
239 SDL_Surface *NDS_SetVideoMode(_THIS, SDL_Surface *current, | |
240 int width, int height, int bpp, Uint32 flags) | |
241 { | |
242 Uint32 Rmask, Gmask, Bmask, Amask; | |
243 | |
244 //if(width > 1024 || height > 512 || bpp > 16) | |
245 // return(NULL); | |
246 | |
247 if(bpp >8) { | |
248 bpp=16; | |
249 Rmask = 0x0000001F; | |
250 Gmask = 0x000003E0; | |
251 Bmask = 0x00007C00; | |
252 Amask = 0x00008000; | |
253 | |
254 videoSetMode(MODE_5_2D| DISPLAY_BG2_ACTIVE); | |
255 | |
256 vramSetMainBanks(VRAM_A_MAIN_BG,VRAM_B_MAIN_BG,VRAM_C_MAIN_BG,VRAM_D_MAIN_BG); | |
257 | |
258 BG2_CR = BG_BMP16_512x512; | |
259 BG2_XDX = ((width / 256) << 8) | (width % 256) ; | |
260 BG2_XDY = 0; | |
261 BG2_YDX = 0; | |
262 BG2_YDY = ((height / 192) << 8) | ((height % 192) + (height % 192) / 3) ; | |
263 BG2_CX = 0; | |
264 BG2_CY = 0; | |
265 // for (i=0;i<256*192;i++) | |
266 // frontBuffer[i] = RGB15(31,0,0)|BIT(15); | |
267 } | |
268 else | |
269 if(bpp <= 8) { | |
270 bpp=8; | |
271 Rmask = 0x00000000; | |
272 Gmask = 0x00000000; | |
273 Bmask = 0x00000000; | |
274 BG2_CR = BG_BMP8_1024x512; | |
275 BG2_XDX = ((width / 256) << 8) | (width % 256) ; | |
276 BG2_XDY = 0; | |
277 BG2_YDX = 0; | |
278 BG2_YDY = ((height / 192) << 8) | ((height % 192) + (height % 192) / 3) ; | |
279 | |
280 } | |
281 else | |
282 if(bpp < 15) bpp=15; | |
283 if(width<=256) width=256; | |
284 else | |
285 if(width<256) width=256; | |
286 if(height<=192) height=192; | |
287 else | |
288 if(height<192) height=192; | |
289 | |
290 if(bpp==8) | |
291 { | |
292 if(width<256) width=256; | |
293 if(height<192) height=192; | |
294 this->hidden->ndsmode=4; | |
295 } | |
296 | |
297 if(bpp==15) | |
298 { | |
299 if(width<256) this->hidden->ndsmode=5; | |
300 else this->hidden->ndsmode=3; | |
301 } | |
302 | |
303 this->hidden->buffer= frontBuffer;//NDS_VRAM_BASE; | |
304 | |
305 //NDS_DISPCNT = NDS_DISP_MODE(this->hidden->ndsmode)|NDS_DISP_BG2; | |
306 | |
307 //fprintf(stderr,"Setting mode %dx%d (ndsmode %d)\n", width, height,this->hidden->ndsmode); | |
308 | |
309 // FIXME: How do I tell that 15 bits mode is 555? | |
310 | |
311 SDL_memset(this->hidden->buffer, 0, 1024 * 512* ((this->hidden->ndsmode==4 || this->hidden->ndsmode==5) ? 2 : 1 ) * ((bpp+7) / 8)); | |
312 | |
313 /* Allocate the new pixel format for the screen */ | |
314 if ( ! SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, Amask) ) { | |
315 this->hidden->buffer = NULL; | |
316 SDL_SetError("Couldn't allocate new pixel format for requested mode"); | |
317 return(NULL); | |
318 } | |
319 | |
320 /* Set up the new mode framebuffer */ | |
321 current->flags = flags | SDL_FULLSCREEN | SDL_HWSURFACE | (this->hidden->ndsmode > 0 ? SDL_DOUBLEBUF : 0); | |
322 this->hidden->w = current->w = width; | |
323 this->hidden->h = current->h = height; | |
324 current->pixels = frontBuffer; | |
325 | |
326 if (flags & SDL_DOUBLEBUF) { | |
327 this->hidden->secondbufferallocd=1; | |
328 backBuffer=(u16*)SDL_malloc(1024*512*2); | |
329 current->pixels = backBuffer; | |
330 } | |
331 if(bpp==8) | |
332 current->pitch =1024; | |
333 else | |
334 current->pitch =1024*2; | |
335 | |
336 /* We're done */ | |
337 return(current); | |
338 } | |
339 | |
340 static int NDS_AllocHWSurface(_THIS, SDL_Surface *surface) | |
341 { | |
342 if(this->hidden->secondbufferallocd) { | |
343 //printf("double double buffer alloc\n"); | |
344 return -1; | |
345 } | |
346 //if(this->hidden->ndsmode==3) | |
347 //{ | |
348 // printf("no 2nd buffer in mode3\n"); | |
349 // return -1; | |
350 //} | |
351 //printf("second buffer\n"); | |
352 //this->hidden->secondbufferallocd=1; | |
353 //backBuffer=(u16*)malloc(1024*512*2); | |
354 //surface->pixels = backBuffer; | |
355 | |
356 return(0); | |
357 } | |
358 static void NDS_FreeHWSurface(_THIS, SDL_Surface *surface) | |
359 { | |
360 //free(backBuffer); | |
361 this->hidden->secondbufferallocd=0; | |
362 } | |
363 int z=0; | |
364 /* We need to wait for vertical retrace on page flipped displays */ | |
365 static int NDS_LockHWSurface(_THIS, SDL_Surface *surface) | |
366 { | |
367 /* | |
368 uint8* a = surface->pixels; | |
369 int i,j; | |
370 a += 5 * SCREEN_WIDTH + 5; | |
371 for( i = 0; i < 195; ++i) { | |
372 uint16* line = a + (SCREEN_WIDTH * i); | |
373 for( j = 0; j < 158; ++j) { | |
374 *line++ = RGB15(155,155,25); | |
375 } | |
376 } | |
377 */ | |
378 //if (z <256) | |
379 // BG_PALETTE[z++]=RGB15(255-z,z,255-z); | |
380 | |
381 | |
382 return(0); | |
383 } | |
384 | |
385 static void NDS_UnlockHWSurface(_THIS, SDL_Surface *surface) | |
386 { | |
387 return; | |
388 } | |
389 | |
390 static int NDS_FlipHWSurface(_THIS, SDL_Surface *surface) | |
391 { | |
392 if(this->hidden->secondbufferallocd){ | |
393 while(DISP_Y!=192); | |
394 while(DISP_Y==192); | |
395 //printf("flip"); | |
396 | |
397 dmaCopyAsynch(backBuffer,frontBuffer,1024*512); | |
398 } | |
399 //printf("flip\n"); | |
400 //u16* temp = surface->pixels; | |
401 //surface->pixels = frontBuffer; | |
402 //frontBuffer = temp; | |
403 /* u8* vram=BG_GFX; | |
404 int x,y; | |
405 for(y = 0; y < 512; y++) | |
406 dmaCopy(&frontBuffer[y*rects->w], &vram[y*512],512); | |
407 //unsigned char buf; | |
408 | |
409 //printf("NDS_FlipHWSurface\n"); | |
410 //printf("ptr now: 0x%x\n",surface->pixels); | |
411 | |
412 while(DISP_Y!=192); | |
413 while(DISP_Y==192); | |
414 //swap | |
415 u16* temp = frontBuffer; | |
416 frontBuffer = backBuffer; | |
417 backBuffer = temp; | |
418 | |
419 //flip | |
420 //base is 16KB and screen size is 256x256x2 (128KB) | |
421 BG2_CR ^= BG_BMP_BASE( 512 / 16 ); */ | |
422 /* | |
423 if(surface->pixels == frontBuffer)//NDS_VRAM_BASE) | |
424 { | |
425 while(DISP_Y!=192); | |
426 while(DISP_Y==192); | |
427 //swap | |
428 u16* temp = backBuffer; | |
429 backBuffer = frontBuffer; | |
430 frontBuffer = temp; | |
431 | |
432 //flip | |
433 //base is 16KB and screen size is 256x256x2 (128KB) | |
434 BG3_CR ^= BG_BMP_BASE( 128 / 16 ); | |
435 } | |
436 else | |
437 { | |
438 | |
439 while(DISP_Y!=192); | |
440 while(DISP_Y==192); | |
441 //swap | |
442 u16* temp = frontBuffer; | |
443 frontBuffer = backBuffer; | |
444 backBuffer = temp; | |
445 | |
446 //flip | |
447 //base is 16KB and screen size is 256x256x2 (128KB) | |
448 BG3_CR ^= BG_BMP_BASE( 128 / 16 ); | |
449 | |
450 } | |
451 */ | |
452 //printf("ptr then: 0x%x\n",surface->pixels); | |
453 | |
454 //printf("setting dispcnt to 0x%x\n",NDS_DISPCNT = NDS_DISP_MODE(this->hidden->ndsmode)|NDS_DISP_BG2| buf); | |
455 return(0); | |
456 } | |
457 | |
458 static void NDS_UpdateRects(_THIS, int numrects, SDL_Rect *rects) | |
459 { | |
460 //fprintf(stderr,"update\n"); | |
461 /* do nothing. */ | |
462 //dmaCopy(frontBuffer,BG_GFX,512*512); | |
463 /* | |
464 u8* vram=(u8*)BG_GFX; | |
465 int x,y; | |
466 for(y = 0; y < 512; y++) | |
467 dmaCopy(&frontBuffer[y*rects->w], &vram[y*512],512); | |
468 */ | |
469 | |
470 } | |
471 | |
472 int NDS_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) | |
473 { | |
474 //printf("SetColors\n"); | |
475 short r,g,b; | |
476 | |
477 if(this->hidden->ndsmode != 4) | |
478 { | |
479 printf("This is not a palettized mode\n"); | |
480 return -1; | |
481 } | |
482 | |
483 int i,j=firstcolor+ncolors; | |
484 for(i=firstcolor;i<j;i++) | |
485 { | |
486 r=colors[i].r>>3; | |
487 g=colors[i].g>>3; | |
488 b=colors[i].b>>3; | |
489 BG_PALETTE[i]=RGB15(r, g, b); | |
490 } | |
491 | |
492 return(0); | |
493 } | |
494 | |
495 /* Note: If we are terminated, this could be called in the middle of | |
496 another SDL video routine -- notably UpdateRects. | |
497 */ | |
498 void NDS_VideoQuit(_THIS) | |
499 { | |
500 } |