Skip to content

Commit

Permalink
atari:xbios: Add NOVA video card support for TT machines
Browse files Browse the repository at this point in the history
  • Loading branch information
pmandin committed Nov 4, 2017
1 parent e56481f commit fa6248b
Show file tree
Hide file tree
Showing 4 changed files with 477 additions and 3 deletions.
7 changes: 4 additions & 3 deletions README.MiNT
Expand Up @@ -5,7 +5,7 @@ Using the Simple DirectMedia Layer on Atari

If you want to build SDL from sources to create SDL programs on Atari:
see sections I - II.

If you want to create SDL programs on Atari using SDL binary build,
download it from my web site (URL at end of this file).

Expand Down Expand Up @@ -50,7 +50,7 @@ III. Enjoy! :)
can use the web interface:

http://www.libsdl.org/mailman/listinfo/sdl

==============================================================================
IV. What is supported:

Expand Down Expand Up @@ -185,6 +185,7 @@ Xbios video:
of testing SDL.
TT:
320x480x8 and 320x240x8 (software double-lined mode).
NOVA video card: All modes with 8 bits or higher depth.
Falcon:
All modes supported by the current monitor (RVB or VGA).
BlowUp and Centscreen: Extended modes.
Expand Down Expand Up @@ -248,6 +249,6 @@ Audio drivers:
X-Sound driver (GSXB compatible):
http://www.uni-ulm.de/~s_thuth/atari/xsound_e.html

--
--
Patrice Mandin <patmandin@gmail.com>
http://pmandin.atari.org/
345 changes: 345 additions & 0 deletions src/video/xbios/SDL_xbios_nova.c
@@ -0,0 +1,345 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2012 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"

/*
Nova video card driver
Patrice Mandin
*/

#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

/* Mint includes */
#include <mint/cookie.h>
#include <mint/sysvars.h>
#include <mint/osbind.h>

#include "SDL_video.h"

#include "../ataricommon/SDL_atarimxalloc_c.h"
#include "../ataricommon/SDL_atarisuper.h"
#include "SDL_xbios.h"
#include "SDL_xbios_nova.h"

#define NOVA_FILENAME "\\auto\\sta_vdi.bib"

/*--- ---*/

static nova_xcb_t *NOVA_xcb; /* Pointer to Nova infos */
static nova_resolution_t *NOVA_modes; /* Video modes loaded from a file */
static int NOVA_modecount; /* Number of loaded modes */

/*--- Functions ---*/

static void XBIOS_DeleteDevice_NOVA(_THIS);

static void listModes(_THIS, int actually_add);
static void saveMode(_THIS, SDL_PixelFormat *vformat);
static void setMode(_THIS, xbiosmode_t *new_video_mode);
static void restoreMode(_THIS);
static void vsync_NOVA(_THIS);
static void getScreenFormat(_THIS, int bpp, Uint32 *rmask, Uint32 *gmask, Uint32 *bmask, Uint32 *amask);
static int getLineWidth(_THIS, xbiosmode_t *new_video_mode, int width, int bpp);
static void swapVbuffers(_THIS);
static int allocVbuffers(_THIS, int num_buffers, int bufsize);
static void freeVbuffers(_THIS);
static int setColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);

/* Internal functions */

static void NOVA_SetMode(_THIS, int num_mode);
static void NOVA_SetScreen(_THIS, void *screen);
static void NOVA_SetColor(_THIS, int index, int r, int g, int b);
static nova_resolution_t *NOVA_LoadModes(int *num_modes);

/* Nova driver bootstrap functions */

void SDL_XBIOS_VideoInit_Nova(_THIS, void *cookie_nova)
{
NOVA_xcb = (nova_xcb_t *) cookie_nova;
NOVA_modes = NULL;
NOVA_modecount = 0;

this->free = XBIOS_DeleteDevice_NOVA;

/* Initialize video mode list */
NOVA_modes = NOVA_LoadModes(&NOVA_modecount);
if (!NOVA_modes) {
return;
}

XBIOS_listModes = listModes;
XBIOS_saveMode = saveMode;
XBIOS_setMode = setMode;
XBIOS_restoreMode = restoreMode;
XBIOS_vsync = vsync_NOVA;
XBIOS_getScreenFormat = getScreenFormat;
XBIOS_getLineWidth = getLineWidth;
XBIOS_swapVbuffers = swapVbuffers;
XBIOS_allocVbuffers = allocVbuffers;
XBIOS_freeVbuffers = freeVbuffers;

this->SetColors = setColors;
}

static void XBIOS_DeleteDevice_NOVA(_THIS)
{
if (NOVA_modes) {
SDL_free(NOVA_modes);
}

SDL_free(this->hidden);
SDL_free(this);
}

static void listModes(_THIS, int actually_add)
{
int i;
xbiosmode_t modeinfo;

for (i=0; i<NOVA_modecount; i++) {
int width = NOVA_modes[i].max_x + 1;
int height = NOVA_modes[i].max_y + 1;
int bpp = NOVA_modes[i].planes;

/* Only 8, 16, 24, 32,bpp modes */
if ((NOVA_modes[i].mode <= 1 ) || (NOVA_modes[i].mode == 3 ))
continue;

modeinfo.number = i;
modeinfo.width = width;
modeinfo.height = height;
modeinfo.depth = bpp;
modeinfo.flags = 0;

SDL_XBIOS_AddMode(this, actually_add, &modeinfo);
}
}

static void saveMode(_THIS, SDL_PixelFormat *vformat)
{
int curwidth, curheight, curbpp;

curwidth = NOVA_xcb->max_x + 1;
curheight = NOVA_xcb->max_y + 1;
curbpp = NOVA_xcb->planes;
if (NOVA_xcb->mode == 3 ) {
curbpp = 15;
}

/* Determine the current screen size */
this->info.current_w = curwidth;
this->info.current_h = curheight;

/* Determine the screen depth (use default 8-bit depth) */
vformat->BitsPerPixel = curbpp;

/* Update hardware info */
this->info.hw_available = 1;
this->info.video_mem = NOVA_xcb->mem_size;

XBIOS_oldvmode = NOVA_xcb->resolution;
XBIOS_oldvbase = NOVA_xcb->base;

/* TODO: save palette ? */
}

static void setMode(_THIS, xbiosmode_t *new_video_mode)
{
NOVA_SetMode(this, new_video_mode->number);
}

static void restoreMode(_THIS)
{
NOVA_SetScreen(this, XBIOS_oldvbase);
NOVA_SetMode(this, XBIOS_oldvmode);

/* TODO: restore palette ? */
}

static void vsync_NOVA(_THIS)
{
NOVA_xcb->p_vsync();
}

static void getScreenFormat(_THIS, int bpp, Uint32 *rmask, Uint32 *gmask, Uint32 *bmask, Uint32 *amask)
{
*rmask = *gmask = *bmask = *amask = 0;

switch(bpp) {
case 15:
*rmask = 31<<2;
*gmask = 3;
*bmask = 31<<8;
*amask = 1<<7;
break;
case 16:
*rmask = 31<<3;
*gmask = 7;
*bmask = 31<<8;
break;
case 24:
*rmask = 255;
*gmask = 255<<8;
*bmask = 255<<16;
break;
case 32:
*rmask = 255<<24;
*gmask = 255<<16;
*bmask = 255<<8;
*amask = 255;
break;
}
}

static int getLineWidth(_THIS, xbiosmode_t *new_video_mode, int width, int bpp)
{
return (NOVA_modes[new_video_mode->number].pitch);
}

static void swapVbuffers(_THIS)
{
NOVA_SetScreen(this, XBIOS_screens[XBIOS_fbnum]);
}

static int allocVbuffers(_THIS, int num_buffers, int bufsize)
{
XBIOS_screens[0] = NOVA_xcb->base;
if (num_buffers>1) {
XBIOS_screens[1] = XBIOS_screens[0] + NOVA_xcb->scrn_sze;
}

return(1);
}

static void freeVbuffers(_THIS)
{
}

static int setColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
{
int i;

for (i=0; i<ncolors; i++) {
NOVA_SetColor(this, firstcolor+i, colors[i].r, colors[i].g, colors[i].b);
}

return(1);
}

static void NOVA_SetMode(_THIS, int num_mode)
{
if ((num_mode<0) || (num_mode>=NOVA_modecount)) {
return;
}

__asm__ __volatile__ (
"moveql #0,d0\n\t"
"movel %0,a0\n\t"
"movel %1,a1\n\t"
"jsr a1@"
: /* no return value */
: /* input */
"g"(&NOVA_modes[num_mode]), "g"(NOVA_xcb->p_chres)
: /* clobbered registers */
"d0", "d1", "d2", "a0", "a1", "cc", "memory"
);
}

static void NOVA_SetScreen(_THIS, void *screen)
{
__asm__ __volatile__ (
"movel %0,a0\n\t"
"movel %1,a1\n\t"
"jsr a1@"
: /* no return value */
: /* input */
"g"(screen), "g"(NOVA_xcb->p_setscr)
: /* clobbered registers */
"d0", "d1", "d2", "a0", "a1", "cc", "memory"
);
}

static void NOVA_SetColor(_THIS, int index, int r, int g, int b)
{
Uint8 color[3];

color[0] = r;
color[1] = g;
color[2] = b;

__asm__ __volatile__ (
"movel %0,d0\n\t"
"movel %1,a0\n\t"
"movel %2,a1\n\t"
"jsr a1@"
: /* no return value */
: /* input */
"g"(index), "g"(color), "g"(NOVA_xcb->p_setcol)
: /* clobbered registers */
"d0", "d1", "d2", "a0", "a1", "cc", "memory"
);
}

static nova_resolution_t *NOVA_LoadModes(int *num_modes)
{
char filename[32];
unsigned char bootdrive;
void *oldstack;
int handle, length;
nova_resolution_t *buffer;

/* Find boot drive */
oldstack = (void *)Super(NULL);
bootdrive='A'+ *((volatile unsigned short *)_bootdev);
SuperToUser(oldstack);

sprintf(&filename[0], "%c:" NOVA_FILENAME, bootdrive);

/* Load file */
handle = open(filename, O_RDONLY);
if (handle<0) {
SDL_SetError("Unable to open %s\n", filename);
return NULL;
}

length = lseek(handle, 0, SEEK_END);
lseek(handle, 0, SEEK_SET);

buffer = (nova_resolution_t *)SDL_malloc(length);
if (buffer==NULL) {
SDL_SetError("Unable to allocate %d bytes\n", length);
return NULL;
}

read(handle, buffer, length);
close(handle);

if (num_modes!=NULL) {
*num_modes=length/sizeof(nova_resolution_t);
}

return buffer;
}

0 comments on commit fa6248b

Please sign in to comment.