src/video/nds/SDL_ndsvideo.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 15 Feb 2011 16:41:04 -0800
changeset 5301 248c5c7d6e29
parent 5297 1800dc39b74c
child 5423 b69fa50e80d7
permissions -rw-r--r--
Patch to fix includes from Frank Zago
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2011 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 /* SDL Nintendo DS video driver implementation
    25  * based on dummy driver:
    26  *  Initial work by Ryan C. Gordon (icculus@icculus.org). A good portion
    27  *  of this was cut-and-pasted from Stephane Peter's work in the AAlib
    28  *  SDL video driver.  Renamed to "DUMMY" by Sam Lantinga.
    29  */
    30 
    31 #include <stdio.h>
    32 #include <stdlib.h>
    33 #include <nds.h>
    34 #include <nds/arm9/video.h>
    35 
    36 #include "SDL_video.h"
    37 #include "SDL_mouse.h"
    38 #include "../SDL_sysvideo.h"
    39 #include "../SDL_pixels_c.h"
    40 #include "../../events/SDL_events_c.h"
    41 #include "SDL_render.h"
    42 #include "SDL_ndsvideo.h"
    43 #include "SDL_ndsevents_c.h"
    44 
    45 #define NDSVID_DRIVER_NAME "nds"
    46 
    47 /* Per Window information. */
    48 struct NDS_WindowData {
    49     int hw_index;               /* index of sprite in OAM or bg from libnds */
    50 	int bg;						/* which bg is that attached to (2 or 3) */
    51     int pitch, bpp;             /* useful information about the texture */
    52     struct {
    53         int x, y;
    54     } scale;                    /* x/y stretch (24.8 fixed point) */
    55     struct {
    56         int x, y;
    57     } scroll;                   /* x/y offset */
    58     int rotate;                 /* -32768 to 32767, texture rotation */
    59     u16 *vram_pixels;           /* where the pixel data is stored (a pointer into VRAM) */
    60 };
    61 
    62 /* Per device information. */
    63 struct NDS_DeviceData {
    64 	int has_bg2;				/* backgroud 2 has been attached */
    65 	int has_bg3;				/* backgroud 3 has been attached */
    66     int sub;
    67 };
    68 
    69 /* Initialization/Query functions */
    70 static int NDS_VideoInit(_THIS);
    71 static int NDS_SetDisplayMode(_THIS, SDL_VideoDisplay *display,
    72 							  SDL_DisplayMode *mode);
    73 static void NDS_VideoQuit(_THIS);
    74 
    75 
    76 /* SDL NDS driver bootstrap functions */
    77 static int
    78 NDS_Available(void)
    79 {
    80     return (1);                 /* always here */
    81 }
    82 
    83 static int NDS_CreateWindowFramebuffer(_THIS, SDL_Window * window,
    84 									   Uint32 * format, void ** pixels,
    85 									   int *pitch)
    86 {
    87 	struct NDS_DeviceData *data = _this->driverdata;
    88 	struct NDS_WindowData *wdata;
    89     int bpp;
    90     Uint32 Rmask, Gmask, Bmask, Amask;
    91 	int whichbg = -1;
    92 
    93 	*format = SDL_PIXELFORMAT_BGR555;
    94 
    95     if (!SDL_PixelFormatEnumToMasks
    96         (*format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
    97         SDL_SetError("Unknown texture format");
    98         return -1;
    99     }
   100 
   101 	if (!data->has_bg2)
   102 		whichbg = 2;
   103 	else if (!data->has_bg3)
   104 		whichbg = 3;
   105 	else {
   106 		SDL_SetError("Out of NDS backgrounds.");
   107 		return -1;
   108 	}
   109 
   110 	wdata = SDL_calloc(1, sizeof(struct NDS_WindowData));
   111 	if (!wdata) {
   112 		SDL_OutOfMemory();
   113 		return -1;
   114 	}
   115 
   116 	if (!data->sub) {
   117 		if (bpp == 8) {
   118 			wdata->hw_index =
   119 				bgInit(whichbg, BgType_Bmp8, BgSize_B8_256x256, 0, 0);
   120 		} else {
   121 			wdata->hw_index =
   122 				bgInit(whichbg, BgType_Bmp16, BgSize_B16_256x256, 0,
   123 					   0);
   124 		}
   125 	} else {
   126 		if (bpp == 8) {
   127 			wdata->hw_index =
   128 				bgInitSub(whichbg, BgType_Bmp8, BgSize_B8_256x256, 0,
   129 						  0);
   130 		} else {
   131 			wdata->hw_index =
   132 				bgInitSub(whichbg, BgType_Bmp16, BgSize_B16_256x256,
   133 						  0, 0);
   134 		}
   135 	}
   136 
   137 	wdata->bg = whichbg;
   138 	wdata->pitch = (window->w) * ((bpp+1) / 8);
   139 	wdata->bpp = bpp;
   140 	wdata->rotate = 0;
   141 	wdata->scale.x = 0x100;
   142 	wdata->scale.y = 0x100;
   143 	wdata->scroll.x = 0;
   144 	wdata->scroll.y = 0;
   145 	wdata->vram_pixels = (u16 *) bgGetGfxPtr(wdata->hw_index);
   146 
   147 	bgSetCenter(wdata->hw_index, 0, 0);
   148 	bgSetRotateScale(wdata->hw_index, wdata->rotate, wdata->scale.x,
   149 					 wdata->scale.y);
   150 	bgSetScroll(wdata->hw_index, wdata->scroll.x, wdata->scroll.y);
   151 	bgUpdate();
   152 
   153 	*pixels = wdata->vram_pixels;
   154 	*pitch = wdata->pitch;
   155 
   156 	if (!data->has_bg2)
   157 		data->has_bg2 = 1;
   158 	else 
   159 		data->has_bg3 = 1;
   160 
   161 	window->driverdata = wdata;
   162 
   163 	return 0;
   164 }
   165 
   166 static int NDS_UpdateWindowFramebuffer(_THIS, SDL_Window * window,
   167 									   SDL_Rect * rects, int numrects)
   168 {
   169 	/* Nothing to do because writes are done directly into the
   170 	 * framebuffer. */
   171     return 0;
   172 }
   173 
   174 static void NDS_DestroyWindowFramebuffer(_THIS, SDL_Window * window)
   175 {
   176 	struct NDS_DeviceData *data = _this->driverdata;
   177     struct NDS_WindowData *wdata = window->driverdata;
   178 
   179 	if (wdata->bg == 2)
   180 		data->has_bg2 = 0;
   181 	else
   182 		data->has_bg3 = 0;
   183 
   184     SDL_free(wdata);
   185 }
   186 
   187 static void
   188 NDS_DeleteDevice(SDL_VideoDevice * device)
   189 {
   190     SDL_free(device);
   191 }
   192 
   193 static SDL_VideoDevice *
   194 NDS_CreateDevice(int devindex)
   195 {
   196     SDL_VideoDevice *device;
   197 
   198     /* Initialize all variables that we clean on shutdown */
   199     device = SDL_calloc(1, sizeof(SDL_VideoDevice));
   200     if (!device) {
   201         SDL_OutOfMemory();
   202         return NULL;
   203     }
   204 
   205 	device->driverdata = SDL_calloc(1, sizeof(SDL_VideoDevice));
   206     if (!device) {
   207 		SDL_free(device);
   208         SDL_OutOfMemory();
   209         return NULL;
   210     }
   211 
   212     /* Set the function pointers */
   213     device->VideoInit = NDS_VideoInit;
   214     device->VideoQuit = NDS_VideoQuit;
   215     device->SetDisplayMode = NDS_SetDisplayMode;
   216     device->PumpEvents = NDS_PumpEvents;
   217 	device->CreateWindowFramebuffer = NDS_CreateWindowFramebuffer;
   218 	device->UpdateWindowFramebuffer = NDS_UpdateWindowFramebuffer;
   219 	device->DestroyWindowFramebuffer = NDS_DestroyWindowFramebuffer;
   220 
   221     device->num_displays = 2;   /* DS = dual screens */
   222 
   223     device->free = NDS_DeleteDevice;
   224 
   225     return device;
   226 }
   227 
   228 VideoBootStrap NDS_bootstrap = {
   229     NDSVID_DRIVER_NAME, "SDL NDS video driver",
   230     NDS_Available, NDS_CreateDevice
   231 };
   232 
   233 int
   234 NDS_VideoInit(_THIS)
   235 {
   236     SDL_DisplayMode mode;
   237 
   238     /* simple 256x192x16x60 for now */
   239     mode.w = 256;
   240     mode.h = 192;
   241     mode.format = SDL_PIXELFORMAT_ABGR1555;
   242     mode.refresh_rate = 60;
   243     mode.driverdata = NULL;
   244 
   245     if (SDL_AddBasicVideoDisplay(&mode) < 0) {
   246         return -1;
   247     }
   248 
   249     SDL_zero(mode);
   250 	SDL_AddDisplayMode(&_this->displays[0], &mode);
   251 
   252     powerOn(POWER_ALL_2D);
   253     irqEnable(IRQ_VBLANK);
   254     NDS_SetDisplayMode(_this, &_this->displays[0], &mode);
   255 
   256     return 0;
   257 }
   258 
   259 static int
   260 NDS_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
   261 {
   262     /* right now this function is just hard-coded for 256x192 ABGR1555 */
   263     videoSetMode(MODE_5_2D | DISPLAY_BG2_ACTIVE | DISPLAY_BG3_ACTIVE | DISPLAY_BG_EXT_PALETTE | DISPLAY_SPR_1D_LAYOUT | DISPLAY_SPR_1D_BMP | DISPLAY_SPR_1D_BMP_SIZE_256 |      /* (try 128 if 256 is trouble.) */
   264                  DISPLAY_SPR_ACTIVE | DISPLAY_SPR_EXT_PALETTE); /* display on main core
   265                                                                    with lots of flags set for
   266                                                                    flexibility/capacity to render */
   267 
   268     /* hopefully these cover all the various things we might need to do */
   269     vramSetBankA(VRAM_A_MAIN_BG_0x06000000);
   270     vramSetBankB(VRAM_B_MAIN_BG_0x06020000);
   271     vramSetBankC(VRAM_C_SUB_BG_0x06200000);
   272     vramSetBankD(VRAM_D_MAIN_BG_0x06040000);    /* not a typo. vram d can't sub */
   273     vramSetBankE(VRAM_E_MAIN_SPRITE);
   274     vramSetBankF(VRAM_F_SPRITE_EXT_PALETTE);
   275     vramSetBankG(VRAM_G_BG_EXT_PALETTE);
   276     vramSetBankH(VRAM_H_SUB_BG_EXT_PALETTE);
   277     vramSetBankI(VRAM_I_SUB_SPRITE);
   278 
   279     videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);    /* debug text on sub
   280                                                            TODO: this will change
   281                                                            when multi-head is
   282                                                            introduced in render */
   283 
   284     return 0;
   285 }
   286 
   287 void
   288 NDS_VideoQuit(_THIS)
   289 {
   290     videoSetMode(DISPLAY_SCREEN_OFF);
   291     videoSetModeSub(DISPLAY_SCREEN_OFF);
   292     vramSetMainBanks(VRAM_A_LCD, VRAM_B_LCD, VRAM_C_LCD, VRAM_D_LCD);
   293     vramSetBankE(VRAM_E_LCD);
   294     vramSetBankF(VRAM_F_LCD);
   295     vramSetBankG(VRAM_G_LCD);
   296     vramSetBankH(VRAM_H_LCD);
   297     vramSetBankI(VRAM_I_LCD);
   298 }
   299 
   300 /* vi: set ts=4 sw=4 expandtab: */