e14743d1 |
1 | /* |
2 | SDL - Simple DirectMedia Layer |
3 | Copyright (C) 1997-2009 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 =512*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 | } |