Commit 3ee2de05 authored by Sam Lantinga's avatar Sam Lantinga

Added initial support for Dreamcast (thanks HERO!)

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40510
parent 148a1a64
...@@ -25,6 +25,7 @@ EXTRA_DIST = \ ...@@ -25,6 +25,7 @@ EXTRA_DIST = \
README \ README \
README.AmigaOS \ README.AmigaOS \
README.CVS \ README.CVS \
README.DC \
README.Epoc \ README.Epoc \
README.MacOS \ README.MacOS \
README.MacOSX \ README.MacOSX \
...@@ -40,6 +41,7 @@ EXTRA_DIST = \ ...@@ -40,6 +41,7 @@ EXTRA_DIST = \
VisualC.html \ VisualC.html \
VisualC.zip \ VisualC.zip \
VisualCE.zip \ VisualCE.zip \
Makefile.dc \
MPWmake.sea.bin \ MPWmake.sea.bin \
CWprojects.sea.bin \ CWprojects.sea.bin \
PBProjects.tar.gz \ PBProjects.tar.gz \
......
#GL=1
CC = sh-elf-gcc -ml -m4-single-only
AR = sh-elf-ar
KOS_BASE=/prog/kos-1.1.7
INCS = -I$(KOS_BASE)/libc/include -I$(KOS_BASE)/include -I$(KOS_BASE)/kernel/arch/dreamcast/include
DEFS =-DNO_SIGNAL_H -DENABLE_DC
ifdef GL
DEFS += -DHAVE_OPENGL
TARGET = libSDL_gl.a
else
TARGET = libSDL.a
endif
OPTFLAGS=-O2 -fomit-frame-pointer
CFLAGS=-D_arch_dreamcast $(DEFS) $(INCS) -Iinclude -Isrc -Isrc/audio -Isrc/cdrom -Isrc/endian -Isrc/events -Isrc/joystick -Isrc/thread/dc -Isrc/thread -Isrc/timer -Isrc/video $(OPTFLAGS)
SRCS = \
src/audio/dc/SDL_dcaudio.c \
src/audio/dc/aica.c \
src/audio/SDL_audio.c \
src/audio/SDL_audiocvt.c \
src/audio/SDL_audiodev.c \
src/audio/SDL_audiomem.c \
src/audio/SDL_mixer.c \
src/audio/SDL_wave.c \
src/cdrom/dc/SDL_syscdrom.c \
src/cdrom/SDL_cdrom.c \
src/endian/SDL_endian.c \
src/events/SDL_active.c \
src/events/SDL_events.c \
src/events/SDL_expose.c \
src/events/SDL_keyboard.c \
src/events/SDL_mouse.c \
src/events/SDL_quit.c \
src/events/SDL_resize.c \
src/file/SDL_rwops.c \
src/joystick/dc/SDL_sysjoystick.c \
src/joystick/SDL_joystick.c \
src/SDL.c \
src/SDL_error.c \
src/SDL_fatal.c \
src/SDL_getenv.c \
src/SDL_loadso.c \
src/thread/dc/SDL_syscond.c \
src/thread/dc/SDL_sysmutex.c \
src/thread/dc/SDL_syssem.c \
src/thread/dc/SDL_systhread.c \
src/thread/SDL_thread.c \
src/timer/dc/SDL_systimer.c \
src/timer/SDL_timer.c \
src/video/dc/SDL_dcevents.c \
src/video/dc/SDL_dcvideo.c \
src/video/SDL_blit.c \
src/video/SDL_blit_0.c \
src/video/SDL_blit_1.c \
src/video/SDL_blit_A.c \
src/video/SDL_blit_N.c \
src/video/SDL_bmp.c \
src/video/SDL_cursor.c \
src/video/SDL_gamma.c \
src/video/SDL_pixels.c \
src/video/SDL_RLEaccel.c \
src/video/SDL_stretch.c \
src/video/SDL_surface.c \
src/video/SDL_video.c \
src/video/SDL_yuv.c \
src/video/SDL_yuv_sw.c \
OBJS = $(SRCS:.c=.o)
TEST = \
test/checkkeys.c \
test/graywin.c \
test/loopwave.c \
test/testalpha.c \
test/testbitmap.c \
test/testcdrom.c \
test/testerror.c \
test/testgamma.c \
test/testgl.c \
test/testhread.c \
test/testjoystick.c \
test/testkeys.c \
test/testlock.c \
test/testoverlay.c \
test/testpalette.c \
test/testsem.c \
test/testsprite.c \
test/testtimer.c \
test/testtypes.c \
test/testver.c \
test/testvidinfo.c \
test/testwin.c \
test/testwm.c \
test/threadwin.c \
test/torturethread.c \
clean:
rm $(OBJS)
$(TARGET) : $(OBJS)
$(AR) rcs $(TARGET) $(OBJS)
SDL for Dreamcast (beta2)
BERO
bero@geocities.co.jp
http://www.geocities.co.jp/Playtown/2004/
this work with kos-newlib
http://sourceforge.net/projects/dcquake/
compile
- edit KOS_BASE in Makefie.dc for your enviroment
- make -f Makefile.dc
FIXME: The KOS thread files can be found on HERO's site - not in the SDL source.
- overwrite thread/*.c to kos-1.1.7/kernel/thread
- rebuild kos
compile with gl support
- install latest libgl from http://sourceforge.net/projects/dcquake/
- uncomment GL=1 in Makefile.dc
- make -f Makefile.dc clean
- make -f Makefile.dc
install
- copy include/*.h and libSDL.a or libSDL_gl.a for your enviroment
changelog:
beta2
- OpenGL support
- Hardware page flip support
beta
- thread, timer don't tested so much.
- not support OpenGL
...@@ -16,6 +16,7 @@ be found at the <A HREF="http://www.libsdl.org/"> main SDL page</A>. ...@@ -16,6 +16,7 @@ be found at the <A HREF="http://www.libsdl.org/"> main SDL page</A>.
Major changes since SDL 1.0.0: Major changes since SDL 1.0.0:
</H2> </H2>
<UL> <UL>
<LI> 1.2.5: Added initial support for Dreamcast (thanks HERO!)
<LI> 1.2.5: Updated Borland projects for Kylix 3 (thanks Dominique) <LI> 1.2.5: Updated Borland projects for Kylix 3 (thanks Dominique)
<LI> 1.2.5: Added project files for embedded Visual C++ 4.0 <LI> 1.2.5: Added project files for embedded Visual C++ 4.0
<LI> 1.2.5: Added SDL_BUTTON_WHEELUP (4) and SDL_BUTTON_WHEELDOWN (5) <LI> 1.2.5: Added SDL_BUTTON_WHEELUP (4) and SDL_BUTTON_WHEELDOWN (5)
......
...@@ -6,7 +6,7 @@ noinst_LTLIBRARIES = libaudio.la ...@@ -6,7 +6,7 @@ noinst_LTLIBRARIES = libaudio.la
# Define which subdirectories need to be built # Define which subdirectories need to be built
SUBDIRS = @AUDIO_SUBDIRS@ SUBDIRS = @AUDIO_SUBDIRS@
DIST_SUBDIRS = alsa arts baudio dma dmedia dsp esd macrom nas nto openbsd \ DIST_SUBDIRS = alsa arts baudio dma dmedia dsp esd macrom nas nto openbsd \
paudio sun ums windib windx5 disk mint paudio sun ums windib windx5 disk mint dc
DRIVERS = @AUDIO_DRIVERS@ DRIVERS = @AUDIO_DRIVERS@
......
...@@ -88,6 +88,9 @@ static AudioBootStrap *bootstrap[] = { ...@@ -88,6 +88,9 @@ static AudioBootStrap *bootstrap[] = {
#endif #endif
#ifdef DISKAUD_SUPPORT #ifdef DISKAUD_SUPPORT
&DISKAUD_bootstrap, &DISKAUD_bootstrap,
#endif
#ifdef ENABLE_DC
&DCAUD_bootstrap,
#endif #endif
NULL NULL
}; };
......
...@@ -153,6 +153,9 @@ extern AudioBootStrap MINTAUDIO_bootstrap; ...@@ -153,6 +153,9 @@ extern AudioBootStrap MINTAUDIO_bootstrap;
#ifdef DISKAUD_SUPPORT #ifdef DISKAUD_SUPPORT
extern AudioBootStrap DISKAUD_bootstrap; extern AudioBootStrap DISKAUD_bootstrap;
#endif #endif
#ifdef ENABLE_DC
extern AudioBootStrap DCAUD_bootstrap;
#endif
/* This is the current audio device */ /* This is the current audio device */
extern SDL_AudioDevice *current_audio; extern SDL_AudioDevice *current_audio;
......
Makefile.in
Makefile
.libs
*.o
*.lo
*.la
## Makefile.am for SDL on the Dreamcast console
noinst_LTLIBRARIES = libaudio_dc.la
libaudio_dc_la_SOURCES = $(SRCS)
# The SDL audio driver sources
SRCS = SDL_dcaudio.c \
SDL_dcaudio.h \
aica.c \
aica.h
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
BERO <bero@geocities.co.jp>
based on SDL_diskaudio.c by Sam Lantinga <slouken@libsdl.org>
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
/* Output dreamcast aica */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "SDL_audio.h"
#include "SDL_error.h"
#include "SDL_audiomem.h"
#include "SDL_audio_c.h"
#include "SDL_timer.h"
#include "SDL_audiodev_c.h"
#include "SDL_dcaudio.h"
#include "aica.h"
#include <dc/spu.h>
/* Audio driver functions */
static int DCAUD_OpenAudio(_THIS, SDL_AudioSpec *spec);
static void DCAUD_WaitAudio(_THIS);
static void DCAUD_PlayAudio(_THIS);
static Uint8 *DCAUD_GetAudioBuf(_THIS);
static void DCAUD_CloseAudio(_THIS);
/* Audio driver bootstrap functions */
static int DCAUD_Available(void)
{
return 1;
}
static void DCAUD_DeleteDevice(SDL_AudioDevice *device)
{
free(device->hidden);
free(device);
}
static SDL_AudioDevice *DCAUD_CreateDevice(int devindex)
{
SDL_AudioDevice *this;
/* Initialize all variables that we clean on shutdown */
this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
if ( this ) {
memset(this, 0, (sizeof *this));
this->hidden = (struct SDL_PrivateAudioData *)
malloc((sizeof *this->hidden));
}
if ( (this == NULL) || (this->hidden == NULL) ) {
SDL_OutOfMemory();
if ( this ) {
free(this);
}
return(0);
}
memset(this->hidden, 0, (sizeof *this->hidden));
/* Set the function pointers */
this->OpenAudio = DCAUD_OpenAudio;
this->WaitAudio = DCAUD_WaitAudio;
this->PlayAudio = DCAUD_PlayAudio;
this->GetAudioBuf = DCAUD_GetAudioBuf;
this->CloseAudio = DCAUD_CloseAudio;
this->free = DCAUD_DeleteDevice;
spu_init();
return this;
}
AudioBootStrap DCAUD_bootstrap = {
"dcaudio", "Dreamcast AICA audio",
DCAUD_Available, DCAUD_CreateDevice
};
/* This function waits until it is possible to write a full sound buffer */
static void DCAUD_WaitAudio(_THIS)
{
if (this->hidden->playing) {
/* wait */
while(aica_get_pos(0)/this->spec.samples == this->hidden->nextbuf) {
thd_pass();
}
}
}
#define SPU_RAM_BASE 0xa0800000
static void spu_memload_stereo8(int leftpos,int rightpos,void *src0,size_t size)
{
uint8 *src = src0;
uint32 *left = (uint32*)(leftpos +SPU_RAM_BASE);
uint32 *right = (uint32*)(rightpos+SPU_RAM_BASE);
size = (size+7)/8;
while(size--) {
unsigned lval,rval;
lval = *src++;
rval = *src++;
lval|= (*src++)<<8;
rval|= (*src++)<<8;
lval|= (*src++)<<16;
rval|= (*src++)<<16;
lval|= (*src++)<<24;
rval|= (*src++)<<24;
g2_write_32(left++,lval);
g2_write_32(right++,rval);
g2_fifo_wait();
}
}
static void spu_memload_stereo16(int leftpos,int rightpos,void *src0,size_t size)
{
uint16 *src = src0;
uint32 *left = (uint32*)(leftpos +SPU_RAM_BASE);
uint32 *right = (uint32*)(rightpos+SPU_RAM_BASE);
size = (size+7)/8;
while(size--) {
unsigned lval,rval;
lval = *src++;
rval = *src++;
lval|= (*src++)<<16;
rval|= (*src++)<<16;
g2_write_32(left++,lval);
g2_write_32(right++,rval);
g2_fifo_wait();
}
}
static void DCAUD_PlayAudio(_THIS)
{
SDL_AudioSpec *spec = &this->spec;
unsigned int offset;
if (this->hidden->playing) {
/* wait */
while(aica_get_pos(0)/spec->samples == this->hidden->nextbuf) {
thd_pass();
}
}
offset = this->hidden->nextbuf*spec->size;
this->hidden->nextbuf^=1;
/* Write the audio data, checking for EAGAIN on broken audio drivers */
if (spec->channels==1) {
spu_memload(this->hidden->leftpos+offset,this->hidden->mixbuf,this->hidden->mixlen);
} else {
offset/=2;
if ((this->spec.format&255)==8) {
spu_memload_stereo8(this->hidden->leftpos+offset,this->hidden->rightpos+offset,this->hidden->mixbuf,this->hidden->mixlen);
} else {
spu_memload_stereo16(this->hidden->leftpos+offset,this->hidden->rightpos+offset,this->hidden->mixbuf,this->hidden->mixlen);
}
}
if (!this->hidden->playing) {
int mode;
this->hidden->playing = 1;
mode = (spec->format==AUDIO_S8)?SM_8BIT:SM_16BIT;
if (spec->channels==1) {
aica_play(0,mode,this->hidden->leftpos,0,spec->samples*2,spec->freq,255,128,1);
} else {
aica_play(0,mode,this->hidden->leftpos ,0,spec->samples*2,spec->freq,255,0,1);
aica_play(1,mode,this->hidden->rightpos,0,spec->samples*2,spec->freq,255,255,1);
}
}
}
static Uint8 *DCAUD_GetAudioBuf(_THIS)
{
return(this->hidden->mixbuf);
}
static void DCAUD_CloseAudio(_THIS)
{
aica_stop(0);
if (this->spec.channels==2) aica_stop(1);
if ( this->hidden->mixbuf != NULL ) {
SDL_FreeAudioMem(this->hidden->mixbuf);
this->hidden->mixbuf = NULL;
}
}
static int DCAUD_OpenAudio(_THIS, SDL_AudioSpec *spec)
{
switch(spec->format&0xff) {
case 8: spec->format = AUDIO_S8; break;
case 16: spec->format = AUDIO_S16LSB; break;
default:
SDL_SetError("Unsupported audio format");
return(-1);
}
/* Update the fragment size as size in bytes */
SDL_CalculateAudioSpec(spec);
/* Allocate mixing buffer */
this->hidden->mixlen = spec->size;
this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
if ( this->hidden->mixbuf == NULL ) {
return(-1);
}
memset(this->hidden->mixbuf, spec->silence, spec->size);
this->hidden->leftpos = 0x11000;
this->hidden->rightpos = 0x11000+spec->size;
this->hidden->playing = 0;
this->hidden->nextbuf = 0;
/* We're ready to rock and roll. :-) */
return(0);
}
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
BERO <bero@geocities.co.jp>
based on SDL_diskaudio.h by Sam Lantinga <slouken@libsdl.org>
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
#ifndef _SDL_diskaudio_h
#define _SDL_diskaudio_h
#include "SDL_sysaudio.h"
/* Hidden "this" pointer for the video functions */
#define _THIS SDL_AudioDevice *this
struct SDL_PrivateAudioData {
/* The file descriptor for the audio device */
Uint8 *mixbuf;
Uint32 mixlen;
int playing;
int leftpos,rightpos;
int nextbuf;
};
#endif /* _SDL_diskaudio_h */
/* This file is part of the Dreamcast function library.
* Please see libdream.c for further details.
*
* (c)2000 Dan Potter
* modify BERO
*/
#include "aica.h"
/* #define dc_snd_base ((volatile unsigned char *)0x00800000) */ /* arm side */
#define dc_snd_base ((volatile unsigned char *)0xa0700000) /* dc side */
/* Some convienence macros */
#define SNDREGADDR(x) (0xa0700000 + (x))
#define CHNREGADDR(ch,x) SNDREGADDR(0x80*(ch)+(x))
#define SNDREG32(x) (*(volatile unsigned long *)SNDREGADDR(x))
#define SNDREG8(x) (*(volatile unsigned char *)SNDREGADDR(x))
#define CHNREG32(ch, x) (*(volatile unsigned long *)CHNREGADDR(ch,x))
#define CHNREG8(ch, x) (*(volatile unsigned long *)CHNREGADDR(ch,x))
#define G2_LOCK(OLD) \
do { \
if (!irq_inside_int()) \
OLD = irq_disable(); \
/* suspend any G2 DMA here... */ \
while((*(volatile unsigned int *)0xa05f688c) & 0x20) \
; \
} while(0)
#define G2_UNLOCK(OLD) \
do { \
/* resume any G2 DMA here... */ \
if (!irq_inside_int()) \
irq_restore(OLD); \
} while(0)
void aica_init() {
int i, j, old;
/* Initialize AICA channels */
G2_LOCK(old);
SNDREG32(0x2800) = 0x0000;
for (i=0; i<64; i++) {
for (j=0; j<0x80; j+=4) {
if ((j&31)==0) g2_fifo_wait();
CHNREG32(i, j) = 0;
}
g2_fifo_wait();
CHNREG32(i,0) = 0x8000;
CHNREG32(i,20) = 0x1f;
}
SNDREG32(0x2800) = 0x000f;
g2_fifo_wait();
G2_UNLOCK(old);
}
/* Translates a volume from linear form to logarithmic form (required by
the AICA chip */
/* int logs[] = {
0, 40, 50, 58, 63, 68, 73, 77, 80, 83, 86, 89, 92, 94, 97, 99, 101, 103,
105, 107, 109, 111, 112, 114, 116, 117, 119, 120, 122, 123, 125, 126, 127,
129, 130, 131, 133, 134, 135, 136, 137, 139, 140, 141, 142, 143, 144, 145,
146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159,
160, 161, 162, 162, 163, 164, 165, 166, 166, 167, 168, 169, 170, 170, 171,
172, 172, 173, 174, 175, 175, 176, 177, 177, 178, 179, 180, 180, 181, 182,
182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 188, 189, 190, 190, 191,
191, 192, 193, 193, 194, 194, 195, 196, 196, 197, 197, 198, 198, 199, 199,
200, 201, 201, 202, 202, 203, 203, 204, 204, 205, 205, 206, 206, 207, 207,
208, 208, 209, 209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215,
215, 216, 216, 217, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222,
222, 222, 223, 223, 224, 224, 225, 225, 225, 226, 226, 227, 227, 228, 228,
228, 229, 229, 230, 230, 230, 231, 231, 232, 232, 232, 233, 233, 234, 234,
234, 235, 235, 236, 236, 236, 237, 237, 238, 238, 238, 239, 239, 240, 240,
240, 241, 241, 241, 242, 242, 243, 243, 243, 244, 244, 244, 245, 245, 245,
246, 246, 247, 247, 247, 248, 248, 248, 249, 249, 249, 250, 250, 250, 251,
251, 251, 252, 252, 252, 253, 253, 253, 254, 254, 254, 255
}; */
const static unsigned char logs[] = {
0, 15, 22, 27, 31, 35, 39, 42, 45, 47, 50, 52, 55, 57, 59, 61,
63, 65, 67, 69, 71, 73, 74, 76, 78, 79, 81, 82, 84, 85, 87, 88,
90, 91, 92, 94, 95, 96, 98, 99, 100, 102, 103, 104, 105, 106,
108, 109, 110, 111, 112, 113, 114, 116, 117, 118, 119, 120, 121,
122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
135, 136, 137, 138, 138, 139, 140, 141, 142, 143, 144, 145, 146,
146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 156,
157, 158, 159, 160, 160, 161, 162, 163, 164, 164, 165, 166, 167,
167, 168, 169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176,
177, 178, 178, 179, 180, 181, 181, 182, 183, 183, 184, 185, 185,
186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, 193, 194,
195, 195, 196, 197, 197, 198, 199, 199, 200, 200, 201, 202, 202,
203, 204, 204, 205, 205, 206, 207, 207, 208, 209, 209, 210, 210,
211, 212, 212, 213, 213, 214, 215, 215, 216, 216, 217, 217, 218,
219, 219, 220, 220, 221, 221, 222, 223, 223, 224, 224, 225, 225,
226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 232, 232, 233,
233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 239, 239, 240,
240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246,
247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 254, 255
};
/* For the moment this is going to have to suffice, until we really
figure out what these mean. */
#define AICA_PAN(x) ((x)==0x80?(0):((x)<0x80?(0x1f):(0x0f)))
#define AICA_VOL(x) (0xff - logs[128 + (((x) & 0xff) / 2)])
//#define AICA_VOL(x) (0xff - logs[x&255])
static inline unsigned AICA_FREQ(unsigned freq) {
unsigned long freq_lo, freq_base = 5644800;
int freq_hi = 7;
/* Need to convert frequency to floating point format
(freq_hi is exponent, freq_lo is mantissa)
Formula is ferq = 44100*2^freq_hi*(1+freq_lo/1024) */
while (freq < freq_base && freq_hi > -8) {
freq_base >>= 1;
--freq_hi;
}
while (freq < freq_base && freq_hi > -8) {
freq_base >>= 1;
freq_hi--;
}
freq_lo = (freq<<10) / freq_base;
return (freq_hi << 11) | (freq_lo & 1023);
}
/* Sets up a sound channel completely. This is generally good if you want
a quick and dirty way to play notes. If you want a more comprehensive
set of routines (more like PC wavetable cards) see below.
ch is the channel to play on (0 - 63)
smpptr is the pointer to the sound data; if you're running off the
SH4, then this ought to be (ptr - 0xa0800000); otherwise it's just
ptr. Basically, it's an offset into sound ram.
mode is one of the mode constants (16 bit, 8 bit, ADPCM)
nsamp is the number of samples to play (not number of bytes!)
freq is the sampling rate of the sound
vol is the volume, 0 to 0xff (0xff is louder)
pan is a panning constant -- 0 is left, 128 is center, 255 is right.
This routine (and the similar ones) owe a lot to Marcus' sound example --
I hadn't gotten quite this far into dissecting the individual regs yet. */
void aica_play(int ch,int mode,unsigned long smpptr,int loopst,int loopend,int freq,int vol,int pan,int loopflag) {
int i;
int val;
int old;
/* Stop the channel (if it's already playing) */
aica_stop(ch);
/* doesn't seem to be needed, but it's here just in case */
/*
for (i=0; i<256; i++) {
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
*/
G2_LOCK(old);
/* Envelope setup. The first of these is the loop point,
e.g., where the sample starts over when it loops. The second
is the loop end. This is the full length of the sample when
you are not looping, or the loop end point when you are (though
storing more than that is a waste of memory if you're not doing
volume enveloping). */
CHNREG32(ch, 8) = loopst & 0xffff;
CHNREG32(ch, 12) = loopend & 0xffff;
/* Write resulting values */
CHNREG32(ch, 24) = AICA_FREQ(freq);
/* Set volume, pan, and some other things that we don't know what
they do =) */
CHNREG32(ch, 36) = AICA_PAN(pan) | (0xf<<8);
/* Convert the incoming volume and pan into hardware values */
/* Vol starts at zero so we can ramp */
vol = AICA_VOL(vol);
CHNREG32(ch, 40) = 0x24 | (vol<<8);
/* Convert the incoming volume and pan into hardware values */
/* Vol starts at zero so we can ramp */
/* If we supported volume envelopes (which we don't yet) then
this value would set that up. The top 4 bits determine the
envelope speed. f is the fastest, 1 is the slowest, and 0
seems to be an invalid value and does weird things). The
default (below) sets it into normal mode (play and terminate/loop).
CHNREG32(ch, 16) = 0xf010;
*/
CHNREG32(ch, 16) = 0x1f; /* No volume envelope */
/* Set sample format, buffer address, and looping control. If
0x0200 mask is set on reg 0, the sample loops infinitely. If
it's not set, the sample plays once and terminates. We'll
also set the bits to start playback here. */
CHNREG32(ch, 4) = smpptr & 0xffff;
val = 0xc000 | 0x0000 | (mode<<7) | (smpptr >> 16);
if (loopflag) val|=0x200;
CHNREG32(ch, 0) = val;
G2_UNLOCK(old);
/* Enable playback */
/* CHNREG32(ch, 0) |= 0xc000; */
g2_fifo_wait();
#if 0
for (i=0xff; i>=vol; i--) {
if ((i&7)==0) g2_fifo_wait();
CHNREG32(ch, 40) = 0x24 | (i<<8);;
}
g2_fifo_wait();
#endif
}
/* Stop the sound on a given channel */
void aica_stop(int ch) {
g2_write_32(CHNREGADDR(ch, 0),(g2_read_32(CHNREGADDR(ch, 0)) & ~0x4000) | 0x8000);
g2_fifo_wait();
}
/* The rest of these routines can change the channel in mid-stride so you
can do things like vibrato and panning effects. */
/* Set channel volume */
void aica_vol(int ch,int vol) {
// g2_write_8(CHNREGADDR(ch, 41),AICA_VOL(vol));
g2_write_32(CHNREGADDR(ch, 40),(g2_read_32(CHNREGADDR(ch, 40))&0xffff00ff)|(AICA_VOL(vol)<<8) );
g2_fifo_wait();
}
/* Set channel pan */
void aica_pan(int ch,int pan) {
// g2_write_8(CHNREGADDR(ch, 36),AICA_PAN(pan));
g2_write_32(CHNREGADDR(ch, 36),(g2_read_32(CHNREGADDR(ch, 36))&0xffffff00)|(AICA_PAN(pan)) );
g2_fifo_wait();
}
/* Set channel frequency */
void aica_freq(int ch,int freq) {
g2_write_32(CHNREGADDR(ch, 24),AICA_FREQ(freq));
g2_fifo_wait();
}
/* Get channel position */
int aica_get_pos(int ch) {
#if 1
/* Observe channel ch */
g2_write_32(SNDREGADDR(0x280c),(g2_read_32(SNDREGADDR(0x280c))&0xffff00ff) | (ch<<8));
g2_fifo_wait();
/* Update position counters */
return g2_read_32(SNDREGADDR(0x2814)) & 0xffff;
#else
/* Observe channel ch */
g2_write_8(SNDREGADDR(0x280d),ch);
/* Update position counters */
return g2_read_32(SNDREGADDR(0x2814)) & 0xffff;
#endif
}
#ifndef _AICA_H_
#define _AICA_H_
#define AICA_MEM 0xa0800000
#define SM_8BIT 1
#define SM_16BIT 0
#define SM_ADPCM 2
void aica_play(int ch,int mode,unsigned long smpptr,int looptst,int loopend,int freq,int vol,int pan,int loopflag);
void aica_stop(int ch);
void aica_vol(int ch,int vol);
void aica_pan(int ch,int pan);
void aica_freq(int ch,int freq);
int aica_get_pos(int ch);
#endif
...@@ -5,7 +5,7 @@ noinst_LTLIBRARIES = libcdrom.la ...@@ -5,7 +5,7 @@ noinst_LTLIBRARIES = libcdrom.la
# Define which subdirectories need to be built # Define which subdirectories need to be built
SUBDIRS = @CDROM_SUBDIRS@ SUBDIRS = @CDROM_SUBDIRS@
DIST_SUBDIRS = aix beos bsdi dummy freebsd linux macos openbsd qnx win32 DIST_SUBDIRS = aix beos bsdi dc dummy freebsd linux macos openbsd qnx win32
DRIVERS = @CDROM_DRIVERS@ DRIVERS = @CDROM_DRIVERS@
......
Makefile.in
Makefile
.libs
*.o
*.lo
*.la
## Makefile.am for the Dreamcast cdrom driver for SDL
noinst_LTLIBRARIES = libcdrom_dc.la
libcdrom_dc_la_SOURCES = $(SRCS)
# The SDL cdrom driver sources
SRCS = SDL_syscdrom.c
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
BERO
bero@geocities.co.jp
based on win32/SDL_syscdrom.c by
Sam Lantinga
slouken@libsdl.org
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
/* Functions for system-level CD-ROM audio control */
#include <stdlib.h>
#include <stdio.h>
#include <dc/cdrom.h>
#include <dc/spu.h>
#include "SDL_error.h"
#include "SDL_cdrom.h"
#include "SDL_syscdrom.h"
/* The system-dependent CD control functions */
static const char *SDL_SYS_CDName(int drive);
static int SDL_SYS_CDOpen(int drive);
static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
static int SDL_SYS_CDPause(SDL_CD *cdrom);
static int SDL_SYS_CDResume(SDL_CD *cdrom);
static int SDL_SYS_CDStop(SDL_CD *cdrom);
static int SDL_SYS_CDEject(SDL_CD *cdrom);
static void SDL_SYS_CDClose(SDL_CD *cdrom);
int SDL_SYS_CDInit(void)
{
/* Fill in our driver capabilities */
SDL_CDcaps.Name = SDL_SYS_CDName;
SDL_CDcaps.Open = SDL_SYS_CDOpen;
SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
SDL_CDcaps.Status = SDL_SYS_CDStatus;
SDL_CDcaps.Play = SDL_SYS_CDPlay;
SDL_CDcaps.Pause = SDL_SYS_CDPause;
SDL_CDcaps.Resume = SDL_SYS_CDResume;
SDL_CDcaps.Stop = SDL_SYS_CDStop;
SDL_CDcaps.Eject = SDL_SYS_CDEject;
SDL_CDcaps.Close = SDL_SYS_CDClose;
return(0);
}
static const char *SDL_SYS_CDName(int drive)
{
return "/cd";
}
static int SDL_SYS_CDOpen(int drive)
{
return(drive);
}
#define TRACK_CDDA 0
static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
{
CDROM_TOC toc;
int ret,i;
ret = cdrom_read_toc(&toc,0);
if (ret!=ERR_OK) {
return -1;
}
cdrom->numtracks = TOC_TRACK(toc.last)-TOC_TRACK(toc.first)+1;
for(i=0;i<cdrom->numtracks;i++) {
unsigned long entry = toc.entry[i];
cdrom->track[i].id = i+1;
cdrom->track[i].type = (TOC_CTRL(toc.entry[i])==TRACK_CDDA)?SDL_AUDIO_TRACK:SDL_DATA_TRACK;
cdrom->track[i].offset = TOC_LBA(entry)-150;
cdrom->track[i].length = TOC_LBA((i+1<toc.last)?toc.entry[i+1]:toc.dunno)-TOC_LBA(entry);
}
return 0;
}
/* Get CD-ROM status */
static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
{
CDstatus status;
int ret,dc_status,disc_type;
ret = cdrom_get_status(&dc_status,&disc_type);
if (ret!=ERR_OK) return CD_ERROR;
switch(dc_status) {
// case CD_STATUS_BUSY:
case CD_STATUS_PAUSED:
return CD_PAUSED;
case CD_STATUS_STANDBY:
return CD_STOPPED;
case CD_STATUS_PLAYING:
return CD_PLAYING;
// case CD_STATUS_SEEKING:
// case CD_STATUS_SCANING:
case CD_STATUS_OPEN:
case CD_STATUS_NO_DISC:
return CD_TRAYEMPTY;
default:
return CD_ERROR;
}
}
/* Start play */
static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
{
int ret = cdrom_cdda_play(start-150,start-150+length,1,CDDA_SECTORS);
return ret==ERR_OK?0:-1;
}
/* Pause play */
static int SDL_SYS_CDPause(SDL_CD *cdrom)
{
int ret=cdrom_cdda_pause();
return ret==ERR_OK?0:-1;
}
/* Resume play */
static int SDL_SYS_CDResume(SDL_CD *cdrom)
{
int ret=cdrom_cdda_resume();
return ret==ERR_OK?0:-1;
}
/* Stop play */
static int SDL_SYS_CDStop(SDL_CD *cdrom)
{
int ret=cdrom_spin_down();
return ret==ERR_OK?0:-1;
}
/* Eject the CD-ROM */
static int SDL_SYS_CDEject(SDL_CD *cdrom)
{
return -1;
}
/* Close the CD-ROM handle */
static void SDL_SYS_CDClose(SDL_CD *cdrom)
{
}
void SDL_SYS_CDQuit(void)
{
}
...@@ -5,7 +5,7 @@ noinst_LTLIBRARIES = libjoystick.la ...@@ -5,7 +5,7 @@ noinst_LTLIBRARIES = libjoystick.la
# Define which subdirectories need to be built # Define which subdirectories need to be built
SUBDIRS = @JOYSTICK_SUBDIRS@ SUBDIRS = @JOYSTICK_SUBDIRS@
DIST_SUBDIRS = dummy amigaos beos bsd darwin linux macos mint win32 DIST_SUBDIRS = dummy amigaos beos bsd darwin dc linux macos mint win32
DRIVERS = @JOYSTICK_DRIVERS@ DRIVERS = @JOYSTICK_DRIVERS@
......
Makefile.in
Makefile
.libs
*.o
*.lo
*.la
## Makefile.am for the Dreamcast joystick driver for SDL
noinst_LTLIBRARIES = libjoystick_dc.la
libjoystick_dc_la_SOURCES = $(SRCS)
# The SDL joystick driver sources
SRCS = SDL_sysjoystick.c
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
BERO
bero@geocities.co.jp
based on win32/SDL_mmjoystick.c
Sam Lantinga
slouken@libsdl.org
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
/* Win32 MultiMedia Joystick driver, contributed by Andrei de A. Formiga */
#include <stdlib.h>
#include <stdio.h> /* For the definition of NULL */
#include "SDL_error.h"
#include "SDL_joystick.h"
#include "SDL_sysjoystick.h"
#include "SDL_joystick_c.h"
#include <dc/maple.h>
#include <dc/maple/controller.h>
#define MAX_JOYSTICKS 8 /* only 2 are supported in the multimedia API */
#define MAX_AXES 6 /* each joystick can have up to 6 axes */
#define MAX_BUTTONS 8 /* and 8 buttons */
#define MAX_HATS 2
#define JOYNAMELEN 8
/* array to hold joystick ID values */
static uint8 SYS_Joystick_addr[MAX_JOYSTICKS];
/* The private structure used to keep track of a joystick */
struct joystick_hwdata
{
cont_cond_t prev_cond;
int prev_buttons;
};
/* Function to scan the system for joysticks.
* This function should set SDL_numjoysticks to the number of available
* joysticks. Joystick 0 should be the system default joystick.
* It should return 0, or -1 on an unrecoverable fatal error.
*/
int SDL_SYS_JoystickInit(void)
{
int numdevs;
int p,u;
numdevs = 0;
for(p=0;p<MAPLE_PORT_COUNT;p++) {
for(u=0;u<MAPLE_UNIT_COUNT;u++) {
if (maple_device_func(p,u)&MAPLE_FUNC_CONTROLLER) {
SYS_Joystick_addr[numdevs] = maple_addr(p,u);
numdevs++;
}
}
}
return(numdevs);
}
/* Function to get the device-dependent name of a joystick */
const char *SDL_SYS_JoystickName(int index)
{
maple_device_t *dev;
if (maple_compat_resolve(SYS_Joystick_addr[index],&dev,MAPLE_FUNC_CONTROLLER)!=0) return NULL;
return dev->info.product_name;
}
/* Function to open a joystick for use.
The joystick to open is specified by the index field of the joystick.
This should fill the nbuttons and naxes fields of the joystick structure.
It returns 0, or -1 if there is an error.
*/
int SDL_SYS_JoystickOpen(SDL_Joystick *joystick)
{
/* allocate memory for system specific hardware data */
joystick->hwdata = (struct joystick_hwdata *) malloc(sizeof(*joystick->hwdata));
if (joystick->hwdata == NULL)
{
SDL_OutOfMemory();
return(-1);
}
memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
/* fill nbuttons, naxes, and nhats fields */
joystick->nbuttons = MAX_BUTTONS;
joystick->naxes = MAX_AXES;
joystick->nhats = MAX_HATS;
return(0);
}
/* Function to update the state of a joystick - called as a device poll.
* This function shouldn't update the joystick structure directly,
* but instead should call SDL_PrivateJoystick*() to deliver events
* and update joystick device state.
*/
void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
{
const int sdl_buttons[] = {
CONT_C,
CONT_B,
CONT_A,
CONT_START,
CONT_Z,
CONT_Y,
CONT_X,
CONT_D
};
uint8 addr;
cont_cond_t cond,*prev_cond;
int buttons,prev_buttons,i,changed;
addr = SYS_Joystick_addr[joystick->index];
if (cont_get_cond(addr,&cond)<0) return;
buttons = cond.buttons;
prev_buttons = joystick->hwdata->prev_buttons;
changed = buttons^prev_buttons;
if ((changed)&(CONT_DPAD_UP|CONT_DPAD_DOWN|CONT_DPAD_LEFT|CONT_DPAD_RIGHT)) {
int hat = SDL_HAT_CENTERED;
if (buttons&CONT_DPAD_UP) hat|=SDL_HAT_UP;
if (buttons&CONT_DPAD_DOWN) hat|=SDL_HAT_DOWN;
if (buttons&CONT_DPAD_LEFT) hat|=SDL_HAT_LEFT;
if (buttons&CONT_DPAD_RIGHT) hat|=SDL_HAT_RIGHT;
SDL_PrivateJoystickHat(joystick, 0, hat);
}
if ((changed)&(CONT_DPAD2_UP|CONT_DPAD2_DOWN|CONT_DPAD2_LEFT|CONT_DPAD2_RIGHT)) {
int hat = SDL_HAT_CENTERED;
if (buttons&CONT_DPAD2_UP) hat|=SDL_HAT_UP;
if (buttons&CONT_DPAD2_DOWN) hat|=SDL_HAT_DOWN;
if (buttons&CONT_DPAD2_LEFT) hat|=SDL_HAT_LEFT;
if (buttons&CONT_DPAD2_RIGHT) hat|=SDL_HAT_RIGHT;
SDL_PrivateJoystickHat(joystick, 1, hat);
}
for(i=0;i<sizeof(sdl_buttons)/sizeof(sdl_buttons[0]);i++) {
if (changed & sdl_buttons[i]) {
SDL_PrivateJoystickButton(joystick, i, (buttons & sdl_buttons[i])?SDL_PRESSED:SDL_RELEASED);
}
}
prev_cond = &joystick->hwdata->prev_cond;
if (cond.joyx!=prev_cond->joyx)
SDL_PrivateJoystickAxis(joystick, 0, cond.joyx-128);
if (cond.joyy!=prev_cond->joyy)
SDL_PrivateJoystickAxis(joystick, 1, cond.joyy-128);
if (cond.rtrig!=prev_cond->rtrig)
SDL_PrivateJoystickAxis(joystick, 2, cond.rtrig);
if (cond.ltrig!=prev_cond->ltrig)
SDL_PrivateJoystickAxis(joystick, 3, cond.ltrig);
if (cond.joy2x!=prev_cond->joy2x)
SDL_PrivateJoystickAxis(joystick, 4, cond.joy2x-128);
if (cond.joy2y!=prev_cond->joy2y)
SDL_PrivateJoystickAxis(joystick, 5, cond.joy2y-128);
joystick->hwdata->prev_buttons = buttons;
joystick->hwdata->prev_cond = cond;
}
/* Function to close a joystick after use */
void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
{
if (joystick->hwdata != NULL) {
/* free system specific hardware data */
free(joystick->hwdata);
}
}
/* Function to perform any system-specific joystick related cleanup */
void SDL_SYS_JoystickQuit(void)
{
return;
}
...@@ -7,6 +7,7 @@ ARCH_SUBDIRS = $(srcdir)/generic \ ...@@ -7,6 +7,7 @@ ARCH_SUBDIRS = $(srcdir)/generic \
$(srcdir)/amigaos \ $(srcdir)/amigaos \
$(srcdir)/beos \ $(srcdir)/beos \
$(srcdir)/bsdi \ $(srcdir)/bsdi \
$(srcdir)/dc \
$(srcdir)/epoc \ $(srcdir)/epoc \
$(srcdir)/irix \ $(srcdir)/irix \
$(srcdir)/linux \ $(srcdir)/linux \
......
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
/* An implementation of condition variables using semaphores and mutexes */
/*
This implementation borrows heavily from the BeOS condition variable
implementation, written by Christopher Tate and Owen Smith. Thanks!
*/
#include <stdio.h>
#include <stdlib.h>
#include "SDL_error.h"
#include "SDL_thread.h"
struct SDL_cond
{
SDL_mutex *lock;
int waiting;
int signals;
SDL_sem *wait_sem;
SDL_sem *wait_done;
};
/* Create a condition variable */
SDL_cond * SDL_CreateCond(void)
{
SDL_cond *cond;
cond = (SDL_cond *) malloc(sizeof(SDL_cond));
if ( cond ) {
cond->lock = SDL_CreateMutex();
cond->wait_sem = SDL_CreateSemaphore(0);
cond->wait_done = SDL_CreateSemaphore(0);
cond->waiting = cond->signals = 0;
if ( ! cond->lock || ! cond->wait_sem || ! cond->wait_done ) {
SDL_DestroyCond(cond);
cond = NULL;
}
} else {
SDL_OutOfMemory();
}
return(cond);
}
/* Destroy a condition variable */
void SDL_DestroyCond(SDL_cond *cond)
{
if ( cond ) {
if ( cond->wait_sem ) {
SDL_DestroySemaphore(cond->wait_sem);
}
if ( cond->wait_done ) {
SDL_DestroySemaphore(cond->wait_done);
}
if ( cond->lock ) {
SDL_DestroyMutex(cond->lock);
}
free(cond);
}
}
/* Restart one of the threads that are waiting on the condition variable */
int SDL_CondSignal(SDL_cond *cond)
{
if ( ! cond ) {
SDL_SetError("Passed a NULL condition variable");
return -1;
}
/* If there are waiting threads not already signalled, then
signal the condition and wait for the thread to respond.
*/
SDL_LockMutex(cond->lock);
if ( cond->waiting > cond->signals ) {
++cond->signals;
SDL_SemPost(cond->wait_sem);
SDL_UnlockMutex(cond->lock);
SDL_SemWait(cond->wait_done);
} else {
SDL_UnlockMutex(cond->lock);
}
return 0;
}
/* Restart all threads that are waiting on the condition variable */
int SDL_CondBroadcast(SDL_cond *cond)
{
if ( ! cond ) {
SDL_SetError("Passed a NULL condition variable");
return -1;
}
/* If there are waiting threads not already signalled, then
signal the condition and wait for the thread to respond.
*/
SDL_LockMutex(cond->lock);
if ( cond->waiting > cond->signals ) {
int i, num_waiting;
num_waiting = (cond->waiting - cond->signals);
cond->signals = cond->waiting;
for ( i=0; i<num_waiting; ++i ) {
SDL_SemPost(cond->wait_sem);
}
/* Now all released threads are blocked here, waiting for us.
Collect them all (and win fabulous prizes!) :-)
*/
SDL_UnlockMutex(cond->lock);
for ( i=0; i<num_waiting; ++i ) {
SDL_SemWait(cond->wait_done);
}
} else {
SDL_UnlockMutex(cond->lock);
}
return 0;
}
/* Wait on the condition variable for at most 'ms' milliseconds.
The mutex must be locked before entering this function!
The mutex is unlocked during the wait, and locked again after the wait.
Typical use:
Thread A:
SDL_LockMutex(lock);
while ( ! condition ) {
SDL_CondWait(cond);
}
SDL_UnlockMutex(lock);
Thread B:
SDL_LockMutex(lock);
...
condition = true;
...
SDL_UnlockMutex(lock);
*/
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
{
int retval;
if ( ! cond ) {
SDL_SetError("Passed a NULL condition variable");
return -1;
}
/* Obtain the protection mutex, and increment the number of waiters.
This allows the signal mechanism to only perform a signal if there
are waiting threads.
*/
SDL_LockMutex(cond->lock);
++cond->waiting;
SDL_UnlockMutex(cond->lock);
/* Unlock the mutex, as is required by condition variable semantics */
SDL_UnlockMutex(mutex);
/* Wait for a signal */
if ( ms == SDL_MUTEX_MAXWAIT ) {
retval = SDL_SemWait(cond->wait_sem);
} else {
retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
}
/* Let the signaler know we have completed the wait, otherwise
the signaler can race ahead and get the condition semaphore
if we are stopped between the mutex unlock and semaphore wait,
giving a deadlock. See the following URL for details:
http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html
*/
SDL_LockMutex(cond->lock);
if ( cond->signals > 0 ) {
/* If we timed out, we need to eat a condition signal */
if ( retval > 0 ) {
SDL_SemWait(cond->wait_sem);
}
/* We always notify the signal thread that we are done */
SDL_SemPost(cond->wait_done);
/* Signal handshake complete */
--cond->signals;
}
--cond->waiting;
SDL_UnlockMutex(cond->lock);
/* Lock the mutex, as is required by condition variable semantics */
SDL_LockMutex(mutex);
return retval;
}
/* Wait on the condition variable forever */
int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
{
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
}
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
BERO
bero@geocities.co.jp
based on generic/SDL_sysmutex.c
Sam Lantinga
slouken@libsdl.org
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
/* An implementation of mutexes using semaphores */
#include <stdio.h>
#include <stdlib.h>
#include "SDL_error.h"
#include "SDL_thread.h"
#include "SDL_systhread_c.h"
#include <arch/spinlock.h>
struct SDL_mutex {
int recursive;
Uint32 owner;
spinlock_t mutex;
};
/* Create a mutex */
SDL_mutex *SDL_CreateMutex(void)
{
SDL_mutex *mutex;
/* Allocate mutex memory */
mutex = (SDL_mutex *)malloc(sizeof(*mutex));
if ( mutex ) {
spinlock_init(&mutex->mutex);
mutex->recursive = 0;
mutex->owner = 0;
} else {
SDL_OutOfMemory();
}
return mutex;
}
/* Free the mutex */
void SDL_DestroyMutex(SDL_mutex *mutex)
{
if ( mutex ) {
free(mutex);
}
}
/* Lock the semaphore */
int SDL_mutexP(SDL_mutex *mutex)
{
#ifdef DISABLE_THREADS
return 0;
#else
Uint32 this_thread;
if ( mutex == NULL ) {
SDL_SetError("Passed a NULL mutex");
return -1;
}
this_thread = SDL_ThreadID();
if ( mutex->owner == this_thread ) {
++mutex->recursive;
} else {
/* The order of operations is important.
We set the locking thread id after we obtain the lock
so unlocks from other threads will fail.
*/
spinlock_lock(&mutex->mutex);
mutex->owner = this_thread;
mutex->recursive = 0;
}
return 0;
#endif /* DISABLE_THREADS */
}
/* Unlock the mutex */
int SDL_mutexV(SDL_mutex *mutex)
{
#ifdef DISABLE_THREADS
return 0;
#else
if ( mutex == NULL ) {
SDL_SetError("Passed a NULL mutex");
return -1;
}
/* If we don't own the mutex, we can't unlock it */
if ( SDL_ThreadID() != mutex->owner ) {
SDL_SetError("mutex not owned by this thread");
return -1;
}
if ( mutex->recursive ) {
--mutex->recursive;
} else {
/* The order of operations is important.
First reset the owner so another thread doesn't lock
the mutex and set the ownership before we reset it,
then release the lock semaphore.
*/
mutex->owner = 0;
spinlock_unlock(&mutex->mutex);
}
return 0;
#endif /* DISABLE_THREADS */
}
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
BERO
bero@geocities.co.jp
based on generic/SDL_syssem.c
Sam Lantinga
slouken@libsdl.org
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
/* An implementation of semaphores using mutexes and condition variables */
#include <stdlib.h>
#include "SDL_error.h"
#include "SDL_timer.h"
#include "SDL_thread.h"
#include "SDL_systhread_c.h"
#ifdef DISABLE_THREADS
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
{
SDL_SetError("SDL not configured with thread support");
return (SDL_sem *)0;
}
void SDL_DestroySemaphore(SDL_sem *sem)
{
return;
}
int SDL_SemTryWait(SDL_sem *sem)
{
SDL_SetError("SDL not configured with thread support");
return -1;
}
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
{
SDL_SetError("SDL not configured with thread support");
return -1;
}
int SDL_SemWait(SDL_sem *sem)
{
SDL_SetError("SDL not configured with thread support");
return -1;
}
Uint32 SDL_SemValue(SDL_sem *sem)
{
return 0;
}
int SDL_SemPost(SDL_sem *sem)
{
SDL_SetError("SDL not configured with thread support");
return -1;
}
#else
#include <kos/sem.h>
struct SDL_semaphore
{
semaphore_t sem;
};
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
{
return (SDL_sem *)sem_create(initial_value);
}
/* WARNING:
You cannot call this function when another thread is using the semaphore.
*/
void SDL_DestroySemaphore(SDL_sem *sem)
{
if ( ! sem ) {
SDL_SetError("Passed a NULL semaphore");
return;
}
sem_destroy(&sem->sem);
}
int SDL_SemTryWait(SDL_sem *sem)
{
int retval;
if ( ! sem ) {
SDL_SetError("Passed a NULL semaphore");
return -1;
}
retval = sem_trywait(&sem->sem);
if (retval==0) return 0;
else return SDL_MUTEX_TIMEDOUT;
return retval;
}
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
{
int retval;
if ( ! sem ) {
SDL_SetError("Passed a NULL semaphore");
return -1;
}
/* A timeout of 0 is an easy case */
if ( timeout == 0 ) {
return SDL_SemTryWait(sem);
}
retval = sem_wait_timed(&sem->sem,timeout);
if (retval==-1) retval= SDL_MUTEX_TIMEDOUT;
return retval;
}
int SDL_SemWait(SDL_sem *sem)
{
if ( ! sem ) {
SDL_SetError("Passed a NULL semaphore");
return -1;
}
sem_wait(&sem->sem);
return 0;
}
Uint32 SDL_SemValue(SDL_sem *sem)
{
if ( ! sem ) {
SDL_SetError("Passed a NULL semaphore");
return -1;
}
return sem_count(&sem->sem);
}
int SDL_SemPost(SDL_sem *sem)
{
if ( ! sem ) {
SDL_SetError("Passed a NULL semaphore");
return -1;
}
sem_signal(&sem->sem);
return 0;
}
#endif /* DISABLE_THREADS */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
BERO
bero@geocities.co.jp
based on generic/SDL_thread.c
Sam Lantinga
slouken@libsdl.org
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
/* Thread management routines for SDL */
#include "SDL_error.h"
#include "SDL_thread.h"
#include "SDL_systhread.h"
#include <kos/thread.h>
#ifdef DISABLE_THREADS
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
{
SDL_SetError("Threads are not supported on this platform");
return(-1);
}
void SDL_SYS_SetupThread(void)
{
return;
}
Uint32 SDL_ThreadID(void)
{
return(0);
}
void SDL_SYS_WaitThread(SDL_Thread *thread)
{
return;
}
void SDL_SYS_KillThread(SDL_Thread *thread)
{
return;
}
#else
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
{
thread->handle = thd_create(SDL_RunThread,args);
if (thread->handle == NULL) {
SDL_SetError("Not enough resources to create thread");
return(-1);
}
return(0);
}
void SDL_SYS_SetupThread(void)
{
return;
}
Uint32 SDL_ThreadID(void)
{
return (Uint32)thd_get_current();
}
void SDL_SYS_WaitThread(SDL_Thread *thread)
{
thd_wait(thread->handle);
}
void SDL_SYS_KillThread(SDL_Thread *thread)
{
thd_destroy(thread->handle);
}
#endif
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
*/
/* Stub until we implement threads on this platform */
typedef struct kthread* SYS_ThreadHandle;
/*
#ifndef DISABLE_THREADS
#define DISABLE_THREADS
#endif
*/
...@@ -5,6 +5,7 @@ noinst_LTLIBRARIES = libtimer.la ...@@ -5,6 +5,7 @@ noinst_LTLIBRARIES = libtimer.la
ARCH_SUBDIRS = $(srcdir)/amigaos \ ARCH_SUBDIRS = $(srcdir)/amigaos \
$(srcdir)/beos \ $(srcdir)/beos \
$(srcdir)/dc \
$(srcdir)/epoc \ $(srcdir)/epoc \
$(srcdir)/linux \ $(srcdir)/linux \
$(srcdir)/macos \ $(srcdir)/macos \
......
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
BERO
bero@geocities.co.jp
based on win32/SDL_systimer.c
Sam Lantinga
slouken@libsdl.org
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
#include <kos.h>
#include "SDL_thread.h"
#include "SDL_timer.h"
#include "SDL_error.h"
#include "SDL_timer_c.h"
static unsigned start;
/*
jif = ms * HZ /1000
ms = jif * 1000/HZ
*/
void SDL_StartTicks(void)
{
/* Set first ticks value */
start = jiffies;
}
Uint32 SDL_GetTicks(void)
{
return((jiffies-start)*1000/HZ);
}
void SDL_Delay(Uint32 ms)
{
thd_sleep(ms);
}
/* Data to handle a single periodic alarm */
static int timer_alive = 0;
static SDL_Thread *timer = NULL;
static int RunTimer(void *unused)
{
while ( timer_alive ) {
if ( SDL_timer_running ) {
SDL_ThreadedTimerCheck();
}
SDL_Delay(10);
}
return(0);
}
/* This is only called if the event thread is not running */
int SDL_SYS_TimerInit(void)
{
timer_alive = 1;
timer = SDL_CreateThread(RunTimer, NULL);
if ( timer == NULL )
return(-1);
return(SDL_SetTimerThreaded(1));
}
void SDL_SYS_TimerQuit(void)
{
timer_alive = 0;
if ( timer ) {
SDL_WaitThread(timer, NULL);
timer = NULL;
}
}
int SDL_SYS_StartTimer(void)
{
SDL_SetError("Internal logic error: DC uses threaded timer");
return(-1);
}
void SDL_SYS_StopTimer(void)
{
return;
}
...@@ -9,7 +9,7 @@ DIST_SUBDIRS = dummy x11 dga nanox fbcon directfb vgl svga ggi aalib \ ...@@ -9,7 +9,7 @@ DIST_SUBDIRS = dummy x11 dga nanox fbcon directfb vgl svga ggi aalib \
wincommon windib windx5 \ wincommon windib windx5 \
maccommon macdsp macrom quartz \ maccommon macdsp macrom quartz \
bwindow ps2gs photon cybergfx epoc picogui \ bwindow ps2gs photon cybergfx epoc picogui \
ataricommon xbios gem XFree86 ataricommon xbios gem dc XFree86
DRIVERS = @VIDEO_DRIVERS@ DRIVERS = @VIDEO_DRIVERS@
......
...@@ -406,6 +406,9 @@ extern VideoBootStrap Qtopia_bootstrap; ...@@ -406,6 +406,9 @@ extern VideoBootStrap Qtopia_bootstrap;
#ifdef ENABLE_PICOGUI #ifdef ENABLE_PICOGUI
extern VideoBootStrap PG_bootstrap; extern VideoBootStrap PG_bootstrap;
#endif #endif
#ifdef ENABLE_DC
extern VideoBootStrap DC_bootstrap;
#endif
/* This is the current video device */ /* This is the current video device */
extern SDL_VideoDevice *current_video; extern SDL_VideoDevice *current_video;
......
...@@ -116,6 +116,9 @@ static VideoBootStrap *bootstrap[] = { ...@@ -116,6 +116,9 @@ static VideoBootStrap *bootstrap[] = {
#endif #endif
#ifdef ENABLE_PICOGUI #ifdef ENABLE_PICOGUI
&PG_bootstrap, &PG_bootstrap,
#endif
#ifdef ENABLE_DC
&DC_bootstrap,
#endif #endif
NULL NULL
}; };
......
Makefile.in
Makefile
.libs
*.o
*.lo
*.la
## Makefile.am for SDL using the Dreamcast video driver
noinst_LTLIBRARIES = libvideo_dc.la
libvideo_dc_la_SOURCES = $(SRCS)
# The SDL Dreamcast video driver sources
SRCS = \
SDL_dcevents.c \
SDL_dcevents_c.h \
SDL_dcmouse.c \
SDL_dcmouse_c.h \
SDL_dcvideo.c \
SDL_dcvideo.h
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
BERO
bero@geocities.co.jp
based on SDL_nullevents.c by
Sam Lantinga
slouken@libsdl.org
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
/* Being a null driver, there's no event stream. We just define stubs for
most of the API. */
#include "SDL.h"
#include "SDL_sysevents.h"
#include "SDL_events_c.h"
#include "SDL_dcvideo.h"
#include "SDL_dcevents_c.h"
#include <dc/maple.h>
#include <dc/maple/mouse.h>
#include <dc/maple/keyboard.h>
const static unsigned short sdl_key[]= {
/*0*/ 0, 0, 0, 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z',
/*1e*/ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
/*28*/ SDLK_RETURN, SDLK_ESCAPE, SDLK_BACKSPACE, SDLK_TAB, SDLK_SPACE, SDLK_MINUS, SDLK_PLUS, SDLK_LEFTBRACKET,
SDLK_RIGHTBRACKET, SDLK_BACKSLASH , 0, SDLK_SEMICOLON, SDLK_QUOTE,
/*35*/ '~', SDLK_COMMA, SDLK_PERIOD, SDLK_SLASH, SDLK_CAPSLOCK,
SDLK_F1, SDLK_F2, SDLK_F3, SDLK_F4, SDLK_F5, SDLK_F6, SDLK_F7, SDLK_F8, SDLK_F9, SDLK_F10, SDLK_F11, SDLK_F12,
/*46*/ SDLK_PRINT, SDLK_SCROLLOCK, SDLK_PAUSE, SDLK_INSERT, SDLK_HOME, SDLK_PAGEUP, SDLK_DELETE, SDLK_END, SDLK_PAGEDOWN, SDLK_RIGHT, SDLK_LEFT, SDLK_DOWN, SDLK_UP,
/*53*/ SDLK_NUMLOCK, SDLK_KP_DIVIDE, SDLK_KP_MULTIPLY, SDLK_KP_MINUS, SDLK_KP_PLUS, SDLK_KP_ENTER,
SDLK_KP1, SDLK_KP2, SDLK_KP3, SDLK_KP4, SDLK_KP5, SDLK_KP6,
/*5f*/ SDLK_KP7, SDLK_KP8, SDLK_KP9, SDLK_KP0, SDLK_KP_PERIOD, 0 /* S3 */
};
const static unsigned short sdl_shift[] = {
SDLK_LCTRL,SDLK_LSHIFT,SDLK_LALT,0 /* S1 */,
SDLK_RCTRL,SDLK_RSHIFT,SDLK_RALT,0 /* S2 */,
};
#define MOUSE_WHEELUP (1<<4)
#define MOUSE_WHEELDOWN (1<<5)
static void mouse_update(void)
{
const static char sdl_mousebtn[] = {
MOUSE_LEFTBUTTON,
MOUSE_RIGHTBUTTON,
MOUSE_SIDEBUTTON,
MOUSE_WHEELUP,
MOUSE_WHEELDOWN
};
uint8 addr;
mouse_cond_t cond;
static int prev_buttons;
int buttons,changed;
int i;
if ((addr = maple_first_mouse())==0 || mouse_get_cond(addr, &cond)<0) return;
buttons = cond.buttons^0xff;
if (cond.dz<0) buttons|=MOUSE_WHEELUP;
if (cond.dz>0) buttons|=MOUSE_WHEELDOWN;
if (cond.dx||cond.dy) SDL_PrivateMouseMotion(0,1,cond.dx,cond.dy);
changed = buttons^prev_buttons;
for(i=0;i<sizeof(sdl_mousebtn);i++) {
if (changed & sdl_mousebtn[i]) {
SDL_PrivateMouseButton((buttons & sdl_mousebtn[i])?SDL_PRESSED:SDL_RELEASED,i,0,0);
}
}
prev_buttons = buttons;
}
static void keyboard_update(void)
{
static kbd_state_t old_state;
static uint8 old_addr;
kbd_state_t *state;
uint8 addr;
int port,unit;
int shiftkeys;
SDL_keysym keysym;
int i;
addr = maple_first_kb();
if (addr==0) return;
if (addr!=old_addr) {
old_addr = addr;
memset(&old_state,0,sizeof(old_state));
}
maple_raddr(addr,&port,&unit);
state = kbd_get_state(port,unit);
if (!state) return;
shiftkeys = state->shift_keys ^ old_state.shift_keys;
for(i=0;i<sizeof(sdl_shift);i++) {
if ((shiftkeys>>i)&1) {
keysym.sym = sdl_shift[i];
SDL_PrivateKeyboard(((state->shift_keys>>i)&1)?SDL_PRESSED:SDL_RELEASED,&keysym);
}
}
for(i=0;i<sizeof(sdl_key);i++) {
if (state->matrix[i]!=old_state.matrix[i]) {
int key = sdl_key[i];
if (key) {
keysym.sym = key;
SDL_PrivateKeyboard(state->matrix[i]?SDL_PRESSED:SDL_RELEASED,&keysym);
}
}
}
old_state = *state;
}
void DC_PumpEvents(_THIS)
{
keyboard_update();
mouse_update();
}
void DC_InitOSKeymap(_THIS)
{
/* do nothing. */
}
/* end of SDL_dcevents.c ... */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
BERO
bero@geocities.co.jp
based on SDL_nullevents.h by
Sam Lantinga
slouken@libsdl.org
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
#include "SDL_dcvideo.h"
/* Variables and functions exported by SDL_sysevents.c to other parts
of the native video subsystem (SDL_sysvideo.c)
*/
extern void DC_InitOSKeymap(_THIS);
extern void DC_PumpEvents(_THIS);
/* end of SDL_dcevents_c.h ... */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
BERO
bero@geocities.co.jp
based on SDL_nullvideo.h by
Sam Lantinga
slouken@libsdl.org
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
#include <stdio.h>
#include "SDL_error.h"
#include "SDL_mouse.h"
#include "SDL_events_c.h"
#include "SDL_dcmouse_c.h"
/* The implementation dependent data for the window manager cursor */
struct WMcursor {
int unused;
};
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
BERO
bero@geocities.co.jp
based on SDL_nullmouse.h by
Sam Lantinga
slouken@libsdl.org
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
#include "SDL_dcvideo.h"
/* Functions to be exported */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
BERO
bero@geocities.co.jp
based on SDL_nullvideo.c by
Sam Lantinga
slouken@libsdl.org
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
/* Dummy SDL video driver implementation; this is just enough to make an
* SDL-based application THINK it's got a working video driver, for
* applications that call SDL_Init(SDL_INIT_VIDEO) when they don't need it,
* and also for use as a collection of stubs when porting SDL to a new
* platform for which you haven't yet written a valid video driver.
*
* This is also a great way to determine bottlenecks: if you think that SDL
* is a performance problem for a given platform, enable this driver, and
* then see if your application runs faster without video overhead.
*
* Initial work by Ryan C. Gordon (icculus@linuxgames.com). A good portion
* of this was cut-and-pasted from Stephane Peter's work in the AAlib
* SDL video driver. Renamed to "DC" by Sam Lantinga.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDL.h"
#include "SDL_error.h"
#include "SDL_video.h"
#include "SDL_mouse.h"
#include "SDL_sysvideo.h"
#include "SDL_pixels_c.h"
#include "SDL_events_c.h"
#include "SDL_dcvideo.h"
#include "SDL_dcevents_c.h"
#include "SDL_dcmouse_c.h"
#include <dc/video.h>
#include <dc/pvr.h>
#ifdef HAVE_OPENGL
#include <GL/gl.h>
#endif
/* Initialization/Query functions */
static int DC_VideoInit(_THIS, SDL_PixelFormat *vformat);
static SDL_Rect **DC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
static SDL_Surface *DC_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
static int DC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
static void DC_VideoQuit(_THIS);
/* Hardware surface functions */
static int DC_AllocHWSurface(_THIS, SDL_Surface *surface);
static int DC_LockHWSurface(_THIS, SDL_Surface *surface);
static void DC_UnlockHWSurface(_THIS, SDL_Surface *surface);
static void DC_FreeHWSurface(_THIS, SDL_Surface *surface);
static int DC_FlipHWSurface(_THIS, SDL_Surface *surface);
/* etc. */
static void DC_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
/* OpenGL */
static void *DC_GL_GetProcAddress(_THIS, const char *proc);
static int DC_GL_LoadLibrary(_THIS, const char *path);
static int DC_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value);
static void DC_GL_SwapBuffers(_THIS);
/* DC driver bootstrap functions */
static int DC_Available(void)
{
return 1;
}
static void DC_DeleteDevice(SDL_VideoDevice *device)
{
free(device->hidden);
free(device);
}
static SDL_VideoDevice *DC_CreateDevice(int devindex)
{
SDL_VideoDevice *device;
/* Initialize all variables that we clean on shutdown */
device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
if ( device ) {
memset(device, 0, (sizeof *device));
device->hidden = (struct SDL_PrivateVideoData *)
malloc((sizeof *device->hidden));
}
if ( (device == NULL) || (device->hidden == NULL) ) {
SDL_OutOfMemory();
if ( device ) {
free(device);
}
return(0);
}
memset(device->hidden, 0, (sizeof *device->hidden));
/* Set the function pointers */
device->VideoInit = DC_VideoInit;
device->ListModes = DC_ListModes;
device->SetVideoMode = DC_SetVideoMode;
device->CreateYUVOverlay = NULL;
device->SetColors = DC_SetColors;
device->UpdateRects = DC_UpdateRects;
device->VideoQuit = DC_VideoQuit;
device->AllocHWSurface = DC_AllocHWSurface;
device->CheckHWBlit = NULL;
device->FillHWRect = NULL;
device->SetHWColorKey = NULL;
device->SetHWAlpha = NULL;
device->LockHWSurface = DC_LockHWSurface;
device->UnlockHWSurface = DC_UnlockHWSurface;
device->FlipHWSurface = DC_FlipHWSurface;
device->FreeHWSurface = DC_FreeHWSurface;
#ifdef HAVE_OPENGL
device->GL_LoadLibrary = DC_GL_LoadLibrary;
device->GL_GetProcAddress = DC_GL_GetProcAddress;
device->GL_GetAttribute = DC_GL_GetAttribute;
device->GL_MakeCurrent = NULL;
device->GL_SwapBuffers = DC_GL_SwapBuffers;
#endif
device->SetCaption = NULL;
device->SetIcon = NULL;
device->IconifyWindow = NULL;
device->GrabInput = NULL;
device->GetWMInfo = NULL;
device->InitOSKeymap = DC_InitOSKeymap;
device->PumpEvents = DC_PumpEvents;
device->free = DC_DeleteDevice;
return device;
}
VideoBootStrap DC_bootstrap = {
"dcvideo", "Dreamcast Video",
DC_Available, DC_CreateDevice
};
int DC_VideoInit(_THIS, SDL_PixelFormat *vformat)
{
/* Determine the screen depth (use default 8-bit depth) */
/* we change this during the SDL_SetVideoMode implementation... */
vformat->BitsPerPixel = 16;
vformat->Rmask = 0x0000f800;
vformat->Gmask = 0x000007e0;
vformat->Bmask = 0x0000001f;
/* We're done! */
return(0);
}
const static SDL_Rect
RECT_800x600 = {0,0,800,600},
RECT_640x480 = {0,0,640,480},
RECT_320x240 = {0,0,320,240};
const static SDL_Rect *vid_modes[] = {
&RECT_800x600,
&RECT_640x480,
&RECT_320x240,
NULL
};
SDL_Rect **DC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
{
switch(format->BitsPerPixel) {
case 15:
case 16:
return &vid_modes;
case 32:
if (!(flags & SDL_OPENGL))
return &vid_modes;
default:
return NULL;
}
// return (SDL_Rect **) -1;
}
pvr_init_params_t params = {
/* Enable opaque and translucent polygons with size 16 */
{ PVR_BINSIZE_16, PVR_BINSIZE_0, PVR_BINSIZE_16, PVR_BINSIZE_0, PVR_BINSIZE_16 },
/* Vertex buffer size */
512*1024
};
#ifdef HAVE_OPENGL
static int pvr_inited;
#endif
SDL_Surface *DC_SetVideoMode(_THIS, SDL_Surface *current,
int width, int height, int bpp, Uint32 flags)
{
int disp_mode,pixel_mode,pitch;
Uint32 Rmask, Gmask, Bmask;
if (width==320 && height==240) disp_mode=DM_320x240;
else if (width==640 && height==480) disp_mode=DM_640x480;
else if (width==800 && height==600) disp_mode=DM_800x608;
else {
SDL_SetError("Couldn't find requested mode in list");
return(NULL);
}
switch(bpp) {
case 15: pixel_mode = PM_RGB555; pitch = width*2;
/* 5-5-5 */
Rmask = 0x00007c00;
Gmask = 0x000003e0;
Bmask = 0x0000001f;
break;
case 16: pixel_mode = PM_RGB565; pitch = width*2;
/* 5-6-5 */
Rmask = 0x0000f800;
Gmask = 0x000007e0;
Bmask = 0x0000001f;
break;
case 24: bpp = 32;
case 32: pixel_mode = PM_RGB888; pitch = width*4;
Rmask = 0x00ff0000;
Gmask = 0x0000ff00;
Bmask = 0x000000ff;
#ifdef HAVE_OPENGL
if (!(flags & SDL_OPENGL))
#endif
break;
default:
SDL_SetError("Couldn't find requested mode in list");
return(NULL);
}
// if ( bpp != current->format->BitsPerPixel ) {
if ( ! SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0) ) {
return(NULL);
}
// }
/* Set up the new mode framebuffer */
current->flags = (SDL_FULLSCREEN|SDL_HWSURFACE);
current->w = width;
current->h = height;
current->pitch = pitch;
#ifdef HAVE_OPENGL
if (pvr_inited) {
pvr_inited = 0;
pvr_shutdown();
}
#endif
vid_set_mode(disp_mode,pixel_mode);
current->pixels = vram_s;
#ifdef HAVE_OPENGL
if (flags & SDL_OPENGL) {
this->gl_config.driver_loaded = 1;
current->flags = SDL_FULLSCREEN | SDL_OPENGL;
current->pixels = NULL;
pvr_inited = 1;
pvr_init(&params);
glKosInit();
glKosBeginFrame();
} else
#endif
if (flags | SDL_DOUBLEBUF) {
current->flags |= SDL_DOUBLEBUF;
current->pixels = (void*)((int)current->pixels | 0x400000);
}
/* We're done */
return(current);
}
/* We don't actually allow hardware surfaces other than the main one */
static int DC_AllocHWSurface(_THIS, SDL_Surface *surface)
{
return(-1);
}
static void DC_FreeHWSurface(_THIS, SDL_Surface *surface)
{
return;
}
/* We need to wait for vertical retrace on page flipped displays */
static int DC_LockHWSurface(_THIS, SDL_Surface *surface)
{
return(0);
}
static void DC_UnlockHWSurface(_THIS, SDL_Surface *surface)
{
return;
}
static int DC_FlipHWSurface(_THIS, SDL_Surface *surface)
{
if (surface->flags & SDL_DOUBLEBUF) {
vid_set_start((int)surface->pixels & 0xffffff);
surface->pixels = (void*)((int)surface->pixels ^ 0x400000);
}
return(0);
}
static void DC_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
{
/* do nothing. */
}
static int DC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
{
/* do nothing of note. */
return(1);
}
/* Note: If we are terminated, this could be called in the middle of
another SDL video routine -- notably UpdateRects.
*/
static void DC_VideoQuit(_THIS)
{
#ifdef HAVE_OPENGL
if (pvr_inited) {
pvr_inited = 0;
pvr_shutdown();
}
#endif
}
#ifdef HAVE_OPENGL
void dmyfunc(void) {}
typedef void (*funcptr)();
const static struct {
char *name;
funcptr addr;
} glfuncs[] = {
#define DEF(func) {#func,&func}
DEF(glBegin),
DEF(glBindTexture),
DEF(glBlendFunc),
DEF(glColor4f),
// DEF(glCopyImageID),
DEF(glDisable),
DEF(glEnable),
DEF(glEnd),
DEF(glFlush),
DEF(glGenTextures),
DEF(glGetString),
DEF(glLoadIdentity),
DEF(glMatrixMode),
DEF(glOrtho),
DEF(glPixelStorei),
// DEF(glPopAttrib),
// DEF(glPopClientAttrib),
{"glPopAttrib",&dmyfunc},
{"glPopClientAttrib",&dmyfunc},
DEF(glPopMatrix),
// DEF(glPushAttrib),
// DEF(glPushClientAttrib),
{"glPushAttrib",&dmyfunc},
{"glPushClientAttrib",&dmyfunc},
DEF(glPushMatrix),
DEF(glTexCoord2f),
DEF(glTexEnvf),
DEF(glTexImage2D),
DEF(glTexParameteri),
DEF(glTexSubImage2D),
DEF(glVertex2i),
DEF(glViewport),
#undef DEF
};
static void *DC_GL_GetProcAddress(_THIS, const char *proc)
{
void *ret;
int i;
ret = glKosGetProcAddress(proc);
if (ret) return ret;
for(i=0;i<sizeof(glfuncs)/sizeof(glfuncs[0]);i++) {
if (strcmp(proc,glfuncs[i].name)==0) return glfuncs[i].addr;
}
return NULL;
}
static int DC_GL_LoadLibrary(_THIS, const char *path)
{
this->gl_config.driver_loaded = 1;
return 0;
}
static int DC_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value)
{
GLenum mesa_attrib;
int val;
switch(attrib) {
case SDL_GL_RED_SIZE:
val = 5;
break;
case SDL_GL_GREEN_SIZE:
val = 6;
break;
case SDL_GL_BLUE_SIZE:
val = 5;
break;
case SDL_GL_ALPHA_SIZE:
val = 0;
break;
case SDL_GL_DOUBLEBUFFER:
val = 1;
break;
case SDL_GL_DEPTH_SIZE:
val = 16; /* or 32? */
break;
case SDL_GL_STENCIL_SIZE:
val = 0;
break;
case SDL_GL_ACCUM_RED_SIZE:
val = 0;
break;
case SDL_GL_ACCUM_GREEN_SIZE:
val = 0;
case SDL_GL_ACCUM_BLUE_SIZE:
val = 0;
break;
case SDL_GL_ACCUM_ALPHA_SIZE:
val = 0;
break;
default :
return -1;
}
*value = val;
return 0;
}
static void DC_GL_SwapBuffers(_THIS)
{
glKosFinishFrame();
glKosBeginFrame();
}
#endif
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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
BERO
bero@geocities.co.jp
based on SDL_nullvideo.h by
Sam Lantinga
slouken@libsdl.org
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
#ifndef _SDL_dcvideo_h
#define _SDL_dcvideo_h
#include "SDL_mouse.h"
#include "SDL_sysvideo.h"
#include "SDL_mutex.h"
/* Hidden "this" pointer for the video functions */
#define _THIS SDL_VideoDevice *this
/* Private display data */
struct SDL_PrivateVideoData {
int w, h;
void *buffer;
};
#endif /* _SDL_dcvideo_h */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment