1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 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
NDS_Available(void)59 static int NDS_Available(void)
60 {
61 return(1);
62 }
63
NDS_DeleteDevice(SDL_VideoDevice * device)64 static void NDS_DeleteDevice(SDL_VideoDevice *device)
65 {
66 SDL_free(device->hidden);
67 SDL_free(device);
68 }
69
on_irq_vblank()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
HWAccelBlit(SDL_Surface * src,SDL_Rect * srcrect,SDL_Surface * dst,SDL_Rect * dstrect)84 static int HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
85 SDL_Surface *dst, SDL_Rect *dstrect)
86 {
87 return 0;
88 }
89
CheckHWBlit(_THIS,SDL_Surface * src,SDL_Surface * dst)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
NDS_CreateDevice(int devindex)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);
NDS_VideoInit(_THIS,SDL_PixelFormat * vformat)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
NDS_ListModes(_THIS,SDL_PixelFormat * format,Uint32 flags)234 SDL_Rect **NDS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
235 {
236 return (SDL_Rect **) -1;
237 }
238
NDS_SetVideoMode(_THIS,SDL_Surface * current,int width,int height,int bpp,Uint32 flags)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
NDS_AllocHWSurface(_THIS,SDL_Surface * surface)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 }
NDS_FreeHWSurface(_THIS,SDL_Surface * surface)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 */
NDS_LockHWSurface(_THIS,SDL_Surface * surface)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
NDS_UnlockHWSurface(_THIS,SDL_Surface * surface)385 static void NDS_UnlockHWSurface(_THIS, SDL_Surface *surface)
386 {
387 return;
388 }
389
NDS_FlipHWSurface(_THIS,SDL_Surface * surface)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
NDS_UpdateRects(_THIS,int numrects,SDL_Rect * rects)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
NDS_SetColors(_THIS,int firstcolor,int ncolors,SDL_Color * colors)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 */
NDS_VideoQuit(_THIS)498 void NDS_VideoQuit(_THIS)
499 {
500 }
501