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