.fixed I/O access issues with devkitpro r18

.updated OGG support (compatibility with last libtremor + threading fixes from Tantric)
.improved controller auto-detection 
.added experimental support for cartridge hot swapping, check System Options Menu
.improved reset (soft/hard) emulation accuracy


BEFORE COMPILING, REMOVE THE FOLLOWING FILES:

*from ($DEVKITPRO)/libogc/lib/cube & /wii
-----------------------------------------
libpng.a
libtremor.a

*from ($DEVKITPRO)/libogc/include
---------------------------------
/tremor
png.h
pngconf.h


DOWNLOAD & INSTALL THE FOLLOWING PORTLIBS in ($DEVKITPRO)/portlibs/ppc
(PPC versions, from http://sourceforge.net/projects/devkitpro/files/)
*libpng
*libtremor
This commit is contained in:
ekeeke31 2009-10-16 11:32:55 +00:00
parent d129e7da94
commit fe055c2a2c
26 changed files with 493 additions and 180 deletions

View File

@ -34,13 +34,13 @@ LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lpng -lfat -ltremor -lasnd -logc -lm -lz
LIBS := -lpng -lfat -lvorbisidec -lasnd -logc -lm -lz
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
LIBDIRS := $(PORTLIBS)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
@ -88,7 +88,7 @@ export OFILES := $(addsuffix .o,$(BINFILES)) \
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD) \
-I$(LIBOGC_INC)
-I$(LIBOGC_INC) -I$(PORTLIBS)/include
#---------------------------------------------------------------------------------
# build a list of library paths

View File

@ -34,13 +34,13 @@ LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lpng -ldi -lfat -ltremor -lasnd -lwiiuse -lbte -logc -lm -lz
LIBS := -lpng -ldi -lfat -lvorbisidec -lasnd -lwiiuse -lbte -logc -lm -lz
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
LIBDIRS := $(PORTLIBS)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
@ -88,7 +88,7 @@ export OFILES := $(addsuffix .o,$(BINFILES)) \
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD) \
-I$(LIBOGC_INC)
-I$(LIBOGC_INC) -I$(PORTLIBS)/include
#---------------------------------------------------------------------------------
# build a list of library paths

View File

@ -595,7 +595,7 @@ static void special_mapper_w(uint32 address, uint32 data)
{
/* 1 x 32k bank */
m68k_memory_map[0].base = mem_chunk;
memcpy(mem_chunk,&cart.rom[(data & 0x7f) << 15],0x8000);
memcpy(mem_chunk,&cart.rom[(data & 0x7f) << 15],0x8000);
memcpy(mem_chunk+0x8000,cart.rom + 0x8000,0x8000);
}

View File

@ -39,6 +39,9 @@ static struct port_t
*****************************************************************************/
void io_init(void)
{
/* set region according to ROM header */
set_region();
/* restore previous setting */
if (old_system[0] != -1) input.system[0] = old_system[0];
if (old_system[1] != -1) input.system[1] = old_system[1];

View File

@ -140,15 +140,15 @@ void gen_reset(uint32 hard_reset)
count_m68k = 0;
count_z80 = 0;
gen_running = 1; /* System is running */
zreset = 0; /* Z80 is reset */
zbusreq = 0; /* Z80 has control of the Z bus */
zbusack = 1; /* Z80 is busy using the Z bus */
zirq = 0; /* No interrupts occuring */
zbank = 0; /* Assume default bank is $000000-$007FFF */
}
resetline = -1;
resetline = -1; /* clear !RESET */
gen_running = 1; /* System is running */
zreset = 0; /* Z80 is reset */
zbusreq = 0; /* Z80 has control of the Z bus */
zbusack = 1; /* Z80 is busy using the Z bus */
zirq = 0; /* No interrupts occuring */
zbank = 0; /* Assume default bank is $000000-$007FFF */
/* reset CPUs */
m68k_pulse_reset();

View File

@ -85,6 +85,7 @@ void config_default(void)
config.bios_enabled = 0;
config.lock_on = 0;
config.romtype = 0;
config.hot_swap = 0;
/* video options */
config.xshift = 0;
@ -107,7 +108,11 @@ void config_default(void)
gx_input_SetDefault();
/* menu options */
#ifdef HW_RVL
config.sram_auto = 0;
#else
config.sram_auto = -1;
#endif
config.state_auto = -1;
config.bg_color = 0;
config.screen_w = 658;

View File

@ -47,6 +47,7 @@ typedef struct
uint8 addr_error;
uint8 bios_enabled;
uint8 lock_on;
uint8 hot_swap;
uint8 romtype;
int16 xshift;
int16 yshift;

View File

@ -23,6 +23,7 @@
********************************************************************************/
#include "shared.h"
#include "file_dvd.h"
#include "gui.h"
#ifndef HW_RVL
@ -44,7 +45,7 @@ static u8 DVDreadbuffer[2048] ATTRIBUTE_ALIGN (32); /* data buffer for all DVD
u32 dvd_read (void *dst, u32 len, u64 offset)
{
/*** We only allow 2k reads **/
if (len > 2048) return 0;
if (len > DVDCHUNK) return 0;
/*** Let's not read past end of DVD ***/
if(offset < DvdMaxOffset)

View File

@ -48,7 +48,7 @@ static int rootdirlength = 0;
static int IsJoliet = 0;
static int diroffset = 0;
static int haveDVDdir = 0;
static char dvdbuffer[2048];
static char dvdbuffer[DVDCHUNK];
/****************************************************************************
* Primary Volume Descriptor
@ -67,7 +67,7 @@ static int getpvd()
/** Look for Joliet PVD first **/
while (sector < 32)
{
if (dvd_read (&dvdbuffer, 2048, (u64)(sector << 11)))
if (dvd_read (&dvdbuffer, DVDCHUNK, (u64)(sector << 11)))
{
if (memcmp (&dvdbuffer, "\2CD001\1", 8) == 0)
{
@ -89,7 +89,7 @@ static int getpvd()
sector = 16;
while (sector < 32)
{
if (dvd_read (&dvdbuffer, 2048, (u64)(sector << 11)))
if (dvd_read (&dvdbuffer, DVDCHUNK, (u64)(sector << 11)))
{
if (memcmp (&dvdbuffer, "\1CD001\1", 8) == 0)
{
@ -126,7 +126,7 @@ static int getentry(int entrycount)
/* Basic checks */
if (entrycount >= MAXFILES) return 0;
if (diroffset >= 2048) return 0;
if (diroffset >= DVDCHUNK) return 0;
/** Decode this entry **/
if (dvdbuffer[diroffset]) /* Record length available */
@ -139,7 +139,7 @@ static int getentry(int entrycount)
/* Check for wrap round - illegal in ISO spec,
* but certain crap writers do it! */
if ((diroffset + dvdbuffer[diroffset]) > 2048) return 0;
if ((diroffset + dvdbuffer[diroffset]) > DVDCHUNK) return 0;
if (*filenamelength)
{
@ -252,7 +252,7 @@ int DVD_ParseDirectory(void)
/*** Get as many files as possible ***/
while (len < pdlength)
{
if (dvd_read (&dvdbuffer, 2048, pdoffset) == 0) return 0;
if (dvd_read (&dvdbuffer, DVDCHUNK, pdoffset) == 0) return 0;
diroffset = 0;
@ -262,7 +262,7 @@ int DVD_ParseDirectory(void)
filecount++;
}
len += 2048;
len += DVDCHUNK;
pdoffset = rdoffset + len;
}
@ -288,9 +288,9 @@ int DVD_LoadFile(u8 *buffer, u32 selection)
if (length > 0)
{
/* Read first data chunk */
char readbuffer[2048];
char readbuffer[DVDCHUNK];
u64 discoffset = filelist[selection].offset;
dvd_read (&readbuffer, 2048, discoffset);
dvd_read (&readbuffer, DVDCHUNK, discoffset);
/* determine file type */
if (!IsZipFile ((char *) readbuffer))
@ -299,24 +299,24 @@ int DVD_LoadFile(u8 *buffer, u32 selection)
sprintf(msg,"Loading %d bytes...", length);
GUI_MsgBoxOpen("Information",msg,1);
/* How many 2k blocks to read */
int blocks = length / 2048;
int blocks = length / DVDCHUNK;
int readoffset = 0;
int i;
/* read data chunks */
for (i = 0; i < blocks; i++)
{
dvd_read(readbuffer, 2048, discoffset);
discoffset += 2048;
memcpy (buffer + readoffset, readbuffer, 2048);
readoffset += 2048;
dvd_read(readbuffer, DVDCHUNK, discoffset);
discoffset += DVDCHUNK;
memcpy (buffer + readoffset, readbuffer, DVDCHUNK);
readoffset += DVDCHUNK;
}
/* final read */
i = length % 2048;
i = length % DVDCHUNK;
if (i)
{
dvd_read (readbuffer, 2048, discoffset);
dvd_read (readbuffer, DVDCHUNK, discoffset);
memcpy (buffer + readoffset, readbuffer, i);
}

View File

@ -25,6 +25,8 @@
#ifndef _FILE_DVD_H
#define _FILE_DVD_H
#define DVDCHUNK (2048)
extern void DVD_ClearDirectory(void);
extern int DVD_UpdateDirectory(bool go_up,u64 offset, u32 length);
extern int DVD_ParseDirectory(void);

View File

@ -181,8 +181,8 @@ int FAT_LoadFile(u8 *buffer, u32 selection)
}
/* Read first data chunk */
unsigned char temp[2048];
fread(temp, 1, 2048, sdfile);
unsigned char temp[FATCHUNK];
fread(temp, FATCHUNK, 1, sdfile);
fclose(sdfile);
/* determine file type */
@ -195,9 +195,16 @@ int FAT_LoadFile(u8 *buffer, u32 selection)
char msg[50];
sprintf(msg,"Loading %d bytes ...", length);
GUI_MsgBoxOpen("Information",msg,1);
fread(buffer, 1, length, sdfile);
int i = 0;
while (length > FATCHUNK)
{
fread(buffer+i, FATCHUNK, 1, sdfile);
length -= FATCHUNK;
i += FATCHUNK;
}
fread(buffer+i, length, 1, sdfile);
fclose(sdfile);
return length;
return filelist[selection].length;
}
}
else

View File

@ -31,6 +31,8 @@
#define TYPE_USB 2
#endif
#define FATCHUNK (2048)
extern void FAT_ClearDirectory(void);
extern int FAT_UpdateDirectory(bool go_up, char *filename);
extern int FAT_ParseDirectory(void);

View File

@ -24,10 +24,11 @@
#include "shared.h"
#include "file_mem.h"
#include "file_fat.h"
#include "dvd.h"
#include "gui.h"
#include "filesel.h"
#include "saveicon.h"
#include "dvd.h"
/* Global ROM filename */
char rom_filename[MAXJOLIET];
@ -85,15 +86,22 @@ static int FAT_ManageFile(char *filename, u8 direction, u8 filetype)
}
else filesize = state_save(savebuffer); /* STATE */
/* write buffer */
done = fwrite(savebuffer, 1, filesize, fp);
/* write buffer (2k blocks) */
while (filesize > FATCHUNK)
{
fwrite(savebuffer + done, FATCHUNK, 1, fp);
filesize -= FATCHUNK;
done += FATCHUNK;
}
done += fwrite(savebuffer + done, filesize, 1, fp);
fclose(fp);
if (done < filesize)
{
GUI_WaitPrompt("Error","Unable to write file !");
return 0;
}
fclose(fp);
sprintf (fname, "Saved %d bytes successfully", done);
GUI_WaitPrompt("Information",fname);
return 1;
@ -105,14 +113,21 @@ static int FAT_ManageFile(char *filename, u8 direction, u8 filetype)
filesize = ftell (fp);
fseek(fp, 0, SEEK_SET);
/* read into buffer (32k blocks) */
done = fread(savebuffer, 1, filesize, fp);
/* read into buffer (2k blocks) */
while (filesize > FATCHUNK)
{
fread(savebuffer + done, FATCHUNK, 1, fp);
filesize -= FATCHUNK;
done += FATCHUNK;
}
done += fread(savebuffer + done, filesize, 1, fp);
fclose(fp);
if (done < filesize)
{
GUI_WaitPrompt("Error","Unable to read file !");
return 0;
}
fclose(fp);
if (filetype) /* SRAM */
{

View File

@ -28,6 +28,8 @@
#include "shared.h"
#include "dvd.h"
#include "file_dvd.h"
#include "file_fat.h"
#include "gui.h"
/*
@ -120,11 +122,11 @@ int UnZipBuffer (unsigned char *outbuffer, u64 discoffset, char *filename)
if (fatfile)
{
fseek(fatfile, 0, SEEK_SET);
fread(readbuffer, 1, 2048, fatfile);
fread(readbuffer, FATCHUNK, 1, fatfile);
}
else
{
dvd_read (&readbuffer, 2048, discoffset);
dvd_read (&readbuffer, DVDCHUNK, discoffset);
}
/*** Copy PKZip header to local, used as info ***/
@ -188,12 +190,12 @@ int UnZipBuffer (unsigned char *outbuffer, u64 discoffset, char *filename)
if (fatfile)
{
fread(readbuffer, 1, 2048, fatfile);
fread(readbuffer, FATCHUNK, 1, fatfile);
}
else
{
discoffset += 2048;
dvd_read (&readbuffer, 2048, discoffset);
discoffset += DVDCHUNK;
dvd_read (&readbuffer, DVDCHUNK, discoffset);
}
}
while (res != Z_STREAM_END);

View File

@ -232,13 +232,14 @@ static gui_item items_audio[10] =
};
/* System options menu */
static gui_item items_system[6] =
static gui_item items_system[7] =
{
{NULL,NULL,"Console Region: AUTO", "Select system region", 52,132,276,48},
{NULL,NULL,"System Lockups: OFF", "Enable/disable original system lock-ups", 52,132,276,48},
{NULL,NULL,"68k Address Error: ON", "Enable/disable 68k Address Error", 52,132,276,48},
{NULL,NULL,"System BIOS: OFF", "Enable/disable TMSS BIOS support", 52,132,276,48},
{NULL,NULL,"Lock-on: OFF", "Select Lock-On cartridge type", 52,132,276,48},
{NULL,NULL,"Cartridge Swap: OFF", "Enable/disable cartridge hot swap", 52,132,276,48},
{NULL,NULL,"SVP Cycles: 1500", "Adjust SVP chip emulation speed", 52,132,276,48}
};
@ -880,16 +881,17 @@ static void systemmenu ()
else if (config.lock_on == TYPE_AR) sprintf (items[4].text, "Lock-On: ACTION REPLAY");
else if (config.lock_on == TYPE_SK) sprintf (items[4].text, "Lock-On: SONIC & KNUCKLES");
else sprintf (items[4].text, "Lock-On: OFF");
sprintf (items[5].text, "Cartridge Swap: %s", config.hot_swap ? "ON":"OFF");
if (svp)
{
sprintf (items[5].text, "SVP Cycles: %d", SVP_cycles);
m->max_items = 6;
sprintf (items[6].text, "SVP Cycles: %d", SVP_cycles);
m->max_items = 7;
}
else
{
m->max_items = 5;
if (m->offset > 1) m->offset =1;
m->max_items = 6;
if (m->offset > 2) m->offset--;
}
GUI_InitMenu(m);
@ -973,9 +975,14 @@ static void systemmenu ()
}
break;
case 5: /*** SVP emulation ***/
case 5: /*** Cartridge Hot Swap ***/
config.hot_swap ^= 1;
sprintf (items[5].text, "Cartridge Swap: %s", config.hot_swap ? "ON":"OFF");
break;
case 6: /*** SVP emulation ***/
GUI_OptionBox(m,0,"SVP Cycles",(void *)&SVP_cycles,1,1,1500,1);
sprintf (items[5].text, "SVP Cycles: %d", SVP_cycles);
sprintf (items[6].text, "SVP Cycles: %d", SVP_cycles);
break;
case -1:
@ -1193,10 +1200,7 @@ static void ctrlmenu(void)
gui_item *items = NULL;
u8 *special = NULL;
char msg[16];
#ifdef HW_RVL
u32 exp;
#endif
/* System devices */
gui_item items_sys[2][7] =
@ -1528,20 +1532,45 @@ static void ctrlmenu(void)
break;
case 11: /* input controller selection */
#ifdef HW_RVL
/* no input device */
if (config.input[player].device > 0)
if (config.input[player].device < 0)
{
/* use next port */
config.input[player].port ++;
/* try gamecube controllers */
config.input[player].device = 0;
config.input[player].port = 0;
}
else
{
/* use gamecube pad */
config.input[player].device ++;
config.input[player].port = config.input[player].device ? 0 : (player%4);
/* try next port */
config.input[player].port ++;
}
/* autodetect connected gamecube controllers */
if (config.input[player].device == 0)
{
exp = 0;
while ((config.input[player].port<4) && !exp)
{
exp = PAD_ScanPads() & (1<<config.input[player].port);
if (!exp) config.input[player].port ++;
}
if (config.input[player].port >= 4)
{
#ifdef HW_RVL
/* no gamecube controller found, try wiimote */
config.input[player].port = 0;
config.input[player].device = 1;
#else
/* no input controller left */
config.input[player].device = -1;
config.input[player].port = player%4;
#endif
}
}
#ifdef HW_RVL
/* autodetect connected wiimotes (without nunchuk) */
if (config.input[player].device == 1)
{
@ -1622,8 +1651,8 @@ static void ctrlmenu(void)
if (config.input[player].port >= 4)
{
/* no classic controller found, use default gamecube pad */
config.input[player].device = 0;
/* no input controller left */
config.input[player].device = -1;
config.input[player].port = player%4;
}
}
@ -1634,11 +1663,6 @@ static void ctrlmenu(void)
config.input[player].padtype = DEVICE_3BUTTON;
memcpy(&m->items[10],&items[*special],sizeof(gui_item));
}
#else
/* use gamecube pad */
config.input[player].device = 0;
config.input[player].port = player%4;
#endif
/* update menu items */
@ -1670,6 +1694,7 @@ static void ctrlmenu(void)
break;
}
}
else if (update < 0)
{
if (m->bg_images[7].state & IMAGE_VISIBLE)
@ -1702,6 +1727,32 @@ static void ctrlmenu(void)
update = 0;
}
}
/* check we have at least one connected input before leaving */
if (update < 0)
{
old_player = player;
player = 0;
for (i=0; i<MAX_DEVICES; i++)
{
/* check inputs */
if (input.dev[i] != NO_DEVICE)
{
if (config.input[player].device != -1)
break;
player++;
}
}
player = old_player;
/* no input connected */
if (i == MAX_DEVICES)
{
/* stay in menu */
GUI_WaitPrompt("Error","No input connected !");
update = 0;
}
}
}
/* remove duplicate assigned inputs before leaving */
@ -2224,13 +2275,16 @@ void MainMenu (void)
GUI_InitMenu(m);
break;
case 4: /*** Emulator Reset ***/
case 4: /*** System Power Off/On ***/
if (!cart.romsize) break;
GUI_DrawMenuFX(m,10,1);
GUI_DeleteMenu(m);
gxClearScreen((GXColor)BLACK);
gxSetScreen();
system_reset();
system_init();
audio_init(48000);
system_reset();
memfile_autoload(config.sram_auto,-1);
quit = 1;
break;

View File

@ -2,6 +2,9 @@
Copyright (c) 2008 Francisco Muñoz 'Hermes' <www.elotrolado.net>
All rights reserved.
Proper (standard) vorbis usage by Tantric, 2009
Threading modifications/corrections by Tantric, 2009
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
@ -24,10 +27,212 @@
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef NO_SOUND
#include "oggplayer.h"
#include <gccore.h>
#include <unistd.h>
#include <string.h>
/* functions to read the Ogg file from memory */
static struct
{
char *mem;
int size;
int pos;
} file[4];
static int f_read(void * punt, int bytes, int blocks, int *f)
{
int b;
int c;
int d;
if (bytes * blocks <= 0)
return 0;
blocks = bytes * blocks;
c = 0;
while (blocks > 0)
{
b = blocks;
if (b > 4096)
b = 4096;
if (*f >= 0x666 && *f <= 0x669)
{
d = (*f) - 0x666;
if (file[d].size == 0)
return -1;
if ((file[d].pos + b) > file[d].size)
b = file[d].size - file[d].pos;
if (b > 0)
{
memcpy(punt, file[d].mem + file[d].pos, b);
file[d].pos += b;
}
}
else
b = read(*f, ((char *) punt) + c, b);
if (b <= 0)
{
return c / bytes;
}
c += b;
blocks -= b;
}
return c / bytes;
}
static int f_seek(int *f, ogg_int64_t offset, int mode)
{
if(f==NULL) return(-1);
int k, d;
mode &= 3;
if (*f >= 0x666 && *f <= 0x669)
{
d = (*f) - 0x666;
k = 0;
if (file[d].size == 0)
return -1;
if (mode == 0)
{
if ((offset) >= file[d].size)
{
file[d].pos = file[d].size;
k = -1;
}
else if ((offset) < 0)
{
file[d].pos = 0;
k = -1;
}
else
file[d].pos = offset;
}
if (mode == 1)
{
if ((file[d].pos + offset) >= file[d].size)
{
file[d].pos = file[d].size;
k = -1;
}
else if ((file[d].pos + offset) < 0)
{
file[d].pos = 0;
k = -1;
}
else
file[d].pos += offset;
}
if (mode == 2)
{
if ((file[d].size + offset) >= file[d].size)
{
file[d].pos = file[d].size;
k = -1;
}
else if ((file[d].size + offset) < 0)
{
file[d].pos = 0;
k = -1;
}
else
file[d].pos = file[d].size + offset;
}
}
else
k = lseek(*f, (int) offset, mode);
if (k < 0)
k = -1;
else
k = 0;
return k;
}
static int f_close(int *f)
{
int d;
if (*f >= 0x666 && *f <= 0x669)
{
d = (*f) - 0x666;
file[d].size = 0;
file[d].pos = 0;
if (file[d].mem)
{
file[d].mem = (void *) 0;
}
return 0;
}
else
return close(*f);
return 0;
}
static long f_tell(int *f)
{
int k, d;
if (*f >= 0x666 && *f <= 0x669)
{
d = (*f) - 0x666;
k = file[d].pos;
}
else
k = lseek(*f, 0, 1);
return (long) k;
}
static int mem_open(char * ogg, int size)
{
static int one = 1;
int n;
if (one)
{
one = 0;
for (n = 0; n < 4; n++)
file[n].size = 0;
}
for (n = 0; n < 4; n++)
{
if (file[n].size == 0)
{
file[n].mem = ogg;
file[n].size = size;
file[n].pos = 0;
return (0x666 + n);
}
}
return -1;
}
static int mem_close(int fd)
{
if (fd >= 0x666 && fd <= 0x669) // it is a memory file descriptor?
{
fd -= 0x666;
file[fd].size = 0;
return 0;
}
else
return f_close(&fd);
}
static ov_callbacks callbacks = {
(size_t (*)(void *, size_t, size_t, void *)) f_read,
(int (*)(void *, ogg_int64_t, int)) f_seek,
(int (*)(void *)) f_close,
(long (*)(void *)) f_tell
};
/* OGG control */
@ -61,15 +266,15 @@ static private_data_ogg private_ogg;
#define STACKSIZE 8192
static u8 oggplayer_stack[STACKSIZE];
static lwpq_t oggplayer_queue;
static lwp_t h_oggplayer;
static lwpq_t oggplayer_queue = LWP_TQUEUE_NULL;
static lwp_t h_oggplayer = LWP_THREAD_NULL;
static int ogg_thread_running = 0;
static void ogg_add_callback(int voice)
{
if (ogg_thread_running <= 0)
if (!ogg_thread_running)
{
SND_StopVoice(0);
ASND_StopVoice(0);
return;
}
@ -78,7 +283,7 @@ static void ogg_add_callback(int voice)
if (private_ogg.pcm_indx >= READ_SAMPLES)
{
if (SND_AddVoice(0,
if (ASND_AddVoice(0,
(void *) private_ogg.pcmout[private_ogg.pcmout_pos],
private_ogg.pcm_indx << 1) == 0)
{
@ -101,14 +306,14 @@ static void ogg_add_callback(int voice)
static void * ogg_player_thread(private_data_ogg * priv)
{
int first_time = 1;
long ret;
ogg_thread_running = 0;
/* init */
LWP_InitQueue(&oggplayer_queue);
priv[0].vi = ov_info(&priv[0].vf, -1);
SND_Pause(0);
ASND_Pause(0);
priv[0].pcm_indx = 0;
priv[0].pcmout_pos = 0;
@ -118,22 +323,15 @@ static void * ogg_player_thread(private_data_ogg * priv)
ogg_thread_running = 1;
while (!priv[0].eof)
while (!priv[0].eof && ogg_thread_running)
{
long ret;
if (ogg_thread_running <= 0)
break;
if (priv[0].flag)
LWP_ThreadSleep(oggplayer_queue); /* wait only when i have samples to send */
if (ogg_thread_running <= 0)
break;
if (priv[0].flag == 0) /* wait to all samples are sended */
{
if (SND_TestPointer(0, priv[0].pcmout[priv[0].pcmout_pos])
&& SND_StatusVoice(0) != SND_UNUSED)
if (ASND_TestPointer(0, priv[0].pcmout[priv[0].pcmout_pos])
&& ASND_StatusVoice(0) != SND_UNUSED)
{
priv[0].flag |= 64;
continue;
@ -187,12 +385,12 @@ static void * ogg_player_thread(private_data_ogg * priv)
if (priv[0].flag == 1)
{
if (SND_StatusVoice(0) == SND_UNUSED || first_time)
if (ASND_StatusVoice(0) == SND_UNUSED || first_time)
{
first_time = 0;
if (priv[0].vi->channels == 2)
{
SND_SetVoice(0, VOICE_STEREO_16BIT, priv[0].vi->rate, 0,
ASND_SetVoice(0, VOICE_STEREO_16BIT, priv[0].vi->rate, 0,
(void *) priv[0].pcmout[priv[0].pcmout_pos],
priv[0].pcm_indx << 1, priv[0].volume,
priv[0].volume, ogg_add_callback);
@ -202,7 +400,7 @@ static void * ogg_player_thread(private_data_ogg * priv)
}
else
{
SND_SetVoice(0, VOICE_MONO_16BIT, priv[0].vi->rate, 0,
ASND_SetVoice(0, VOICE_MONO_16BIT, priv[0].vi->rate, 0,
(void *) priv[0].pcmout[priv[0].pcmout_pos],
priv[0].pcm_indx << 1, priv[0].volume,
priv[0].volume, ogg_add_callback);
@ -211,48 +409,47 @@ static void * ogg_player_thread(private_data_ogg * priv)
priv[0].flag = 0;
}
}
else
{
/* all samples sended */
/* if(priv[0].pcm_indx==0) priv[0].flag=0; */
}
}
usleep(10);
}
ov_clear(&priv[0].vf);
priv[0].fd = -1;
priv[0].pcm_indx = 0;
ogg_thread_running = 0;
/* free */
LWP_CloseQueue(oggplayer_queue);
return 0;
}
void StopOgg()
{
SND_StopVoice(0);
if (ogg_thread_running > 0)
{
ogg_thread_running = -2;
LWP_ThreadSignal(oggplayer_queue);
LWP_JoinThread(h_oggplayer, NULL);
ASND_StopVoice(0);
ogg_thread_running = 0;
while (((volatile int) ogg_thread_running) != 0)
{
;;;
}
if(h_oggplayer != LWP_THREAD_NULL)
{
if(oggplayer_queue != LWP_TQUEUE_NULL)
LWP_ThreadSignal(oggplayer_queue);
LWP_JoinThread(h_oggplayer, NULL);
h_oggplayer = LWP_THREAD_NULL;
}
if(oggplayer_queue != LWP_TQUEUE_NULL)
{
LWP_CloseQueue(oggplayer_queue);
oggplayer_queue = LWP_TQUEUE_NULL;
}
}
int PlayOgg(int fd, int time_pos, int mode)
int PlayOgg(char * buf, int buflen, int time_pos, int mode)
{
StopOgg();
ogg_thread_running = 0;
private_ogg.fd = mem_open(buf, buflen);
if (private_ogg.fd < 0)
{
private_ogg.fd = -1;
return -1;
}
private_ogg.fd = fd;
private_ogg.mode = mode;
private_ogg.eof = 0;
private_ogg.volume = 127;
@ -262,32 +459,22 @@ int PlayOgg(int fd, int time_pos, int mode)
if (time_pos > 0)
private_ogg.seek_time = time_pos;
if (fd < 0)
{
private_ogg.fd = -1;
return -1;
}
if (ov_open((void *) &private_ogg.fd, &private_ogg.vf, NULL, 0) < 0)
if (ov_open_callbacks((void *) &private_ogg.fd, &private_ogg.vf, NULL, 0, callbacks) < 0)
{
mem_close(private_ogg.fd); /* mem_close() can too close files from devices */
private_ogg.fd = -1;
ogg_thread_running = -1;
ogg_thread_running = 0;
return -1;
}
if (LWP_CreateThread(&h_oggplayer, (void *) ogg_player_thread,
&private_ogg, oggplayer_stack, STACKSIZE, 80) == -1)
{
ogg_thread_running = -1;
ogg_thread_running = 0;
ov_clear(&private_ogg.vf);
private_ogg.fd = -1;
return -1;
}
while (((volatile int) ogg_thread_running) == 0)
{
;;;
}
LWP_ThreadSignal(oggplayer_queue);
return 0;
}
@ -306,39 +493,33 @@ void PauseOgg(int pause)
if (ogg_thread_running > 0)
{
LWP_ThreadSignal(oggplayer_queue);
/* while(((volatile int )private_ogg.flag)!=1 && ((volatile int )ogg_thread_running)>0) {;;;} */
}
}
}
}
int StatusOgg()
{
if (ogg_thread_running <= 0)
if (ogg_thread_running == 0)
return -1; /* Error */
if (private_ogg.eof)
else if (private_ogg.eof)
return 255; /* EOF */
if (private_ogg.flag & 128)
else if (private_ogg.flag & 128)
return 2; /* paused */
return 1; /* running */
else
return 1; /* running */
}
void SetVolumeOgg(int volume)
{
private_ogg.volume = volume;
SND_ChangeVolumeVoice(0, volume, volume);
ASND_ChangeVolumeVoice(0, volume, volume);
}
s32 GetTimeOgg()
{
int ret;
if (ogg_thread_running <= 0)
return 0;
if (private_ogg.fd < 0)
if (ogg_thread_running == 0 || private_ogg.fd < 0)
return 0;
ret = ((s32) ov_time_tell(&private_ogg.vf));
if (ret < 0)
@ -353,4 +534,3 @@ void SetTimeOgg(s32 time_pos)
private_ogg.seek_time = time_pos;
}
#endif

View File

@ -58,7 +58,9 @@ extern "C"
-- Params ---
fd: file descriptor from open() or mem_open()
buf: pointer to sound data
buflen: buffer size in bytes
time_pos: initial time position in the file (in milliseconds). For example, use 30000 to advance 30 seconds
@ -68,7 +70,7 @@ extern "C"
*/
int PlayOgg(int fd, int time_pos, int mode);
int PlayOgg(char * buf, int buflen, int time_pos, int mode);
/*------------------------------------------------------------------------------------------------------------------------------------------------------*/

View File

@ -196,7 +196,7 @@ void gx_audio_Stop(void)
if (Bg_music_ogg && !Shutdown)
{
PauseOgg(0);
PlayOgg(mem_open((char *)Bg_music_ogg, Bg_music_ogg_size), 0, OGG_INFINITE_TIME);
PlayOgg((char *)Bg_music_ogg, Bg_music_ogg_size, 0, OGG_INFINITE_TIME);
SetVolumeOgg(((int)config.bgm_volume * 255) / 100);
}
}

View File

@ -559,10 +559,30 @@ static void wpad_update(s8 chan, u8 i, u32 exp)
else if (input.analog[2][1] < -255) input.analog[2][1] = -255;
/* default button */
if (p & WPAD_BUTTON_B) input.pad[i] |= INPUT_B;
if (p & WPAD_BUTTON_B) input.pad[i] |= INPUT_B;
}
}
#ifdef USB_MOUSE
if (MOUSE_IsConnected())
{
/* USB Mouse support */
mouse_event event;
MOUSE_GetEvent(&event);
MOUSE_FlushEvents();
/* relative X/Y position: (-128;+127) -> (-255;+255) */
if (event.rx) input.analog[2][0] = (event.rx * 2) + 1;
else input.analog[2][0] = 0;
if (event.ry) input.analog[2][1] = (event.ry * 2) + 1;
else input.analog[2][1] = 0;
/* buttons pressed */
if (event.button & 1) input.pad[i] |= INPUT_A;
if (event.button & 2) input.pad[i] |= INPUT_B;
}
#endif
/* Invert Y coordinate */
if (!config.invert_mouse) input.analog[2][1] = -input.analog[2][1];
}
@ -651,7 +671,7 @@ void gx_input_SetDefault(void)
#endif
/* Default player inputs */
for (i=0; i<MAX_DEVICES; i++)
for (i=0; i<MAX_INPUTS; i++)
{
config.input[i].device = -1;
config.input[i].port = i%4;
@ -697,7 +717,7 @@ void gx_input_SetDefault(void)
/* check if Gamecube Controller is connected */
if (exp & (1 << i))
{
for (j=0; j<MAX_DEVICES; j++)
for (j=0; j<MAX_INPUTS; j++)
{
/* look for the first unassigned player */
if (config.input[j].device == -1)

View File

@ -588,7 +588,6 @@ static void gxDrawCrosshair(gx_texture *texture, int x, int y)
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(0.0, 0.0);
GX_End ();
GX_DrawDone();
/* restore GX rendering */
gxResetRendering(0);
@ -625,7 +624,6 @@ void gxDrawRectangle(s32 x, s32 y, s32 w, s32 h, u8 alpha, GXColor color)
GX_Position2s16(x,y);
GX_Color4u8(color.r,color.g,color.b,alpha);
GX_End ();
GX_DrawDone();
/* restore GX rendering */
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
@ -664,7 +662,6 @@ void gxDrawTexture(gx_texture *texture, s32 x, s32 y, s32 w, s32 h, u8 alpha)
GX_Color4u8(0xff,0xff,0xff,alpha);
GX_TexCoord2f32(0.0, 0.0);
GX_End ();
GX_DrawDone();
}
}
@ -709,7 +706,6 @@ void gxDrawTextureRotate(gx_texture *texture, s32 x, s32 y, s32 w, s32 h, f32 an
GX_Color4u8(0xff,0xff,0xff,alpha);
GX_TexCoord2f32(0.0, 1.0);
GX_End ();
GX_DrawDone();
/* restore default Modelview */
guLookAt(mv, &cam.pos, &cam.up, &cam.view);
@ -752,7 +748,6 @@ void gxDrawTextureRepeat(gx_texture *texture, s32 x, s32 y, s32 w, s32 h, u8 alp
GX_Color4u8(0xff,0xff,0xff,alpha);
GX_TexCoord2f32(0.0, 0.0);
GX_End ();
GX_DrawDone();
}
}
@ -796,7 +791,6 @@ void gxDrawScreenshot(u8 alpha)
GX_Color4u8(0xff,0xff,0xff,alpha);
GX_TexCoord2f32(0.0, 0.0);
GX_End ();
GX_DrawDone();
}
void gxCopyScreenshot(gx_texture *texture)
@ -829,7 +823,6 @@ void gxCopyScreenshot(gx_texture *texture)
GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(0.0, 0.0);
GX_End ();
GX_DrawDone();
/* copy EFB to texture */
texture->format = GX_TF_RGBA8;
@ -838,6 +831,7 @@ void gxCopyScreenshot(gx_texture *texture)
texture->data = screenshot;
GX_SetTexCopySrc(0, 0, texture->width * 2, texture->height * 2);
GX_SetTexCopyDst(texture->width, texture->height, texture->format, GX_TRUE);
GX_DrawDone();
GX_CopyTex(texture->data, GX_TRUE);
GX_Flush();
@ -847,6 +841,7 @@ void gxCopyScreenshot(gx_texture *texture)
GX_PixModeSync();
GX_LoadTexObj(&texobj, GX_TEXMAP0);
GX_InvalidateTexAll();
GX_Flush();
DCFlushRange(texture->data, texture->width * texture->height * 4);
}
@ -869,6 +864,7 @@ void gxSaveScreenshot(char *filename)
void gxSetScreen(void)
{
GX_DrawDone();
GX_CopyDisp(xfb[whichfb], GX_FALSE);
GX_Flush();
VIDEO_SetNextFramebuffer (xfb[whichfb]);
@ -1396,7 +1392,6 @@ void gx_video_Update(void)
/* render textured quad */
draw_square();
GX_DrawDone();
/* LightGun marks */
if (crosshair[0]) gxDrawCrosshair(crosshair[0], input.analog[0][0],input.analog[0][1]);
@ -1406,6 +1401,7 @@ void gx_video_Update(void)
whichfb ^= 1;
/* copy EFB to XFB */
GX_DrawDone();
GX_CopyDisp(xfb[whichfb], GX_TRUE);
GX_Flush();
VIDEO_SetNextFramebuffer(xfb[whichfb]);

View File

@ -110,12 +110,26 @@ static void init_machine(void)
***************************************************/
void reloadrom (int size, char *name)
{
/* cartridge hot-swap support */
uint8 hotswap = 0;
if (cart.romsize) hotswap = config.hot_swap;
/* Load ROM */
cart.romsize = size;
load_rom(name); /* Load ROM */
system_init (); /* Initialize System */
audio_init(48000); /* Audio System initialization */
ClearGGCodes (); /* Clear Game Genie patches */
system_reset (); /* System Power ON */
load_rom(name);
if (hotswap)
{
cart_hw_init();
cart_hw_reset();
}
else
{
system_init (); /* Initialize System */
audio_init(48000); /* Audio System initialization */
ClearGGCodes (); /* Clear Game Genie patches */
system_reset (); /* System Power ON */
}
}
/**************************************************

View File

@ -33,9 +33,9 @@
#define SK_UPMEM "/genplus/sk2chip.bin"
#ifdef HW_RVL
#define VERSION "version 1.3.XW"
#define VERSION "version 1.3.2W"
#else
#define VERSION "version 1.3.XG"
#define VERSION "version 1.3.2G"
#endif
#define osd_input_Update() gx_input_UpdateEmu()

View File

@ -267,7 +267,7 @@ int load_rom(char *filename)
free(ptr);
#endif
/* detect interleaved roms (.smd format) */
/* detect interleaved format (.SMD) */
if (strncmp((char *)(cart.rom + 0x100),"SEGA", 4) && ((size / 512) & 1))
{
size -= 512;
@ -288,9 +288,9 @@ int load_rom(char *filename)
/* clear unused ROM space */
memset (cart.rom + size, 0xff, MAXROMSIZE - size);
getrominfo((char *)cart.rom); /* get infos from ROM header */
set_region(); /* set game region (PAL/NTSC, JAP/USA/EUR) */
/* get infos from ROM header */
getrominfo((char *)cart.rom);
#ifdef LSB_FIRST
/* Byteswap ROM */
uint8 temp;
@ -380,10 +380,6 @@ void set_region ()
else if (config.region_detect == 2) region_code = REGION_EUROPE;
else if (config.region_detect == 3) region_code = REGION_JAPAN_NTSC;
else if (config.region_detect == 4) region_code = REGION_JAPAN_PAL;
/* set cpu/vdp speed: PAL or NTSC */
if ((region_code == REGION_EUROPE) || (region_code == REGION_JAPAN_PAL)) vdp_pal = 1;
else vdp_pal = 0;
}
/****************************************************************************

View File

@ -199,7 +199,7 @@ int Fir_Resampler_read( sample_t** out, unsigned long count )
{
sample_t* out_l = out[0];
sample_t* out_r = out[1];
const sample_t* in = buffer;
sample_t* in = buffer;
sample_t* end_pos = write_pos;
unsigned long skip = skip_bits >> imp_phase;
sample_t const* imp = impulses [imp_phase];

View File

@ -210,9 +210,9 @@ void system_init (void)
{
/* Genesis hardware */
gen_init();
io_init();
vdp_init();
render_init();
io_init();
/* Cartridge hardware */
cart_hw_init();
@ -229,9 +229,9 @@ void system_reset (void)
/* Genesis hardware */
gen_reset(1);
SN76489_Reset();
io_reset();
vdp_reset();
render_reset();
io_reset();
/* Clear Sound Buffers */
if (snd.psg.buffer) memset (snd.psg.buffer, 0, SND_SIZE);

View File

@ -142,8 +142,21 @@ static inline void dma_fill(unsigned int data);
void vdp_init(void)
{
/* PAL/NTSC timings */
vdp_rate = vdp_pal ? 50 : 60;
lines_per_frame = vdp_pal ? 313 : 262;
switch (region_code)
{
case REGION_EUROPE:
case REGION_JAPAN_PAL:
vdp_pal = 1;
vdp_rate = 50;
lines_per_frame = 313;
break;
default:
vdp_pal = 0;
vdp_rate = 60;
lines_per_frame = 262;
break;
}
}
void vdp_reset(void)
@ -443,7 +456,7 @@ unsigned int vdp_ctrl_r(void)
if (!(reg[1] & 0x40)) temp |= 0x8;
/* HBLANK flag (Sonic 3 and Sonic 2 "VS Modes", Lemmings 2, Mega Turrican) */
if ((count_m68k <= (line_m68k + 84)) || (count_m68k > (line_m68k + m68cycles_per_line))) temp |= 0x4;
if ((count_m68k % m68cycles_per_line) < 84) temp |= 0x4;
/* clear pending flag */
pending = 0;