From fa6248b3b0a1db86922451d5a039fd93ef21ecf1 Mon Sep 17 00:00:00 2001 From: Patrice Mandin Date: Sat, 4 Nov 2017 23:25:48 +0100 Subject: [PATCH] atari:xbios: Add NOVA video card support for TT machines --- README.MiNT | 7 +- src/video/xbios/SDL_xbios_nova.c | 345 +++++++++++++++++++++++++++++++ src/video/xbios/SDL_xbios_nova.h | 120 +++++++++++ src/video/xbios/SDL_xbios_tt.c | 8 + 4 files changed, 477 insertions(+), 3 deletions(-) create mode 100644 src/video/xbios/SDL_xbios_nova.c create mode 100644 src/video/xbios/SDL_xbios_nova.h diff --git a/README.MiNT b/README.MiNT index 749c8a99d..d5f3c0bc9 100644 --- a/README.MiNT +++ b/README.MiNT @@ -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). @@ -50,7 +50,7 @@ III. Enjoy! :) can use the web interface: http://www.libsdl.org/mailman/listinfo/sdl - + ============================================================================== IV. What is supported: @@ -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. @@ -248,6 +249,6 @@ Audio drivers: X-Sound driver (GSXB compatible): http://www.uni-ulm.de/~s_thuth/atari/xsound_e.html --- +-- Patrice Mandin http://pmandin.atari.org/ diff --git a/src/video/xbios/SDL_xbios_nova.c b/src/video/xbios/SDL_xbios_nova.c new file mode 100644 index 000000000..bbbdd71a1 --- /dev/null +++ b/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 +#include +#include + +/* Mint includes */ +#include +#include +#include + +#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; imax_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=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; +} diff --git a/src/video/xbios/SDL_xbios_nova.h b/src/video/xbios/SDL_xbios_nova.h new file mode 100644 index 000000000..d4cbd240d --- /dev/null +++ b/src/video/xbios/SDL_xbios_nova.h @@ -0,0 +1,120 @@ +/* + 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 definitions + + Patrice Mandin +*/ + +#ifndef _SDL_xbios_nova_h +#define _SDL_xbios_nova_h + +/*--- Types ---*/ + +typedef struct { + unsigned char name[33]; /* Video mode name */ + unsigned char dummy1; + + unsigned short mode; /* Video mode type */ + /* 0=4 bpp */ + /* 1=1 bpp */ + /* 2=8 bpp */ + /* 3=15 bpp (little endian) */ + /* 4=16 bpp (little endian) */ + /* 5=24 bpp (BGR) */ + /* 6=32 bpp (RGBA) */ + unsigned short pitch; /* bpp<8: words/plane /line */ + /* bpp>=8: bytes /line */ + unsigned short planes; /* Bits per pixel */ + unsigned short colors; /* Number of colours */ + unsigned short hc_mode; /* Hardcopy mode */ + /* 0=1 pixel screen -> 1x1 printer screen */ + /* 1=1 pixel screen -> 2x2 printer screen */ + /* 2=1 pixel screen -> 4x4 printer screen */ + unsigned short max_x; /* Max x,y coordinates, values-1 */ + unsigned short max_y; + unsigned short real_x; /* Real max x,y coordinates, values-1 */ + unsigned short real_y; + + unsigned short freq; /* Pixel clock */ + unsigned char freq2; /* Another pixel clock */ + unsigned char low_res; /* Half of pixel clock */ + unsigned char r_3c2; + unsigned char r_3d4[25]; + unsigned char extended[3]; + unsigned char dummy2; +} nova_resolution_t; + +/* cookie NOVA points to this */ +typedef struct { + unsigned char version[4]; /* Version number */ + unsigned char resolution; /* Resolution number */ + unsigned char blnk_time; /* Time before blanking */ + unsigned char ms_speed; /* Mouse speed */ + unsigned char old_res; + + /* Pointer to routine to change resolution */ + void (*p_chres)(nova_resolution_t *nova_res, unsigned long offset); + + unsigned short mode; /* Video mode type: */ + /* 0=4 bpp */ + /* 1=1 bpp */ + /* 2=8 bpp */ + /* 3=15 bpp (little endian) */ + /* 4=16 bpp (little endian) */ + /* 5=24 bpp (BGR) */ + /* 6=32 bpp (RGBA) */ + unsigned short pitch; /* bpp<8: bytes per plane, per line */ + /* bpp>=8: bytes per line */ + unsigned short planes; /* Bits per pixel */ + unsigned short colours; /* Number of colours, unused */ + unsigned short hc; /* Hardcopy mode */ + /* 0=1 pixel screen -> 1x1 printer screen */ + /* 1=1 pixel screen -> 2x2 printer screen */ + /* 2=1 pixel screen -> 4x4 printer screen */ + unsigned short max_x, max_y; /* Resolution, values-1 */ + unsigned short rmn_x, rmx_x; + unsigned short rmn_y, rmx_y; + unsigned short v_top, v_bottom; + unsigned short v_left, v_right; + + /* Pointer to routine to set colours */ + void (*p_setcol)(unsigned short index, unsigned char *colors); + + void (*chng_vrt)(unsigned short x, unsigned short y); + void (*inst_xbios)(unsigned short on); + void (*pic_on)(unsigned short on); + void (*chng_pos)(nova_resolution_t *nova_res, unsigned short direction, unsigned short offset); + void (*p_setscr)(void *adr); /* Pointer to routine to change screen address */ + void *base; /* Address of screen #0 in video RAM */ + void *scr_base; /* Adress of video RAM */ + unsigned short scrn_cnt; /* Number of possible screens in video RAM */ + unsigned long scrn_sze; /* Size of a screen */ + void *reg_base; /* Video card I/O registers base */ + void (*p_vsync)(void); /* Pointer to routine to vsync */ + unsigned char name[36]; /* Video mode name */ + unsigned long mem_size; /* Global size of video memory */ +} nova_xcb_t; + +#endif /* _SDL_xbios_nova_h */ diff --git a/src/video/xbios/SDL_xbios_tt.c b/src/video/xbios/SDL_xbios_tt.c index 7c88f2006..e78b85cd9 100644 --- a/src/video/xbios/SDL_xbios_tt.c +++ b/src/video/xbios/SDL_xbios_tt.c @@ -33,6 +33,7 @@ #include "../SDL_sysvideo.h" #include "SDL_xbios.h" +#include "SDL_xbios_nova.h" static const xbiosmode_t ttmodes[]={ {TT_LOW,320,480,8, XBIOSMODE_C2P}, @@ -47,12 +48,19 @@ static int setColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); void SDL_XBIOS_VideoInit_TT(_THIS) { + long cookie_nova; + XBIOS_listModes = listModes; XBIOS_saveMode = saveMode; XBIOS_setMode = setMode; XBIOS_restoreMode = restoreMode; this->SetColors = setColors; + + /* NOVA card ? */ + if (Getcookie(C_NOVA, &cookie_nova) == C_FOUND) { + SDL_XBIOS_VideoInit_Nova(this, (void *) cookie_nova); + } } static void listModes(_THIS, int actually_add)