Home | History | Annotate | Download | only in nds
      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 (at) 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 }
    501