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