SDL-1.2.14
[sdl_omap.git] / src / video / nds / SDL_ndsvideo.c
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 }