.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 # 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 # list of directories containing libraries, this must be the top level containing
# include and lib # include and lib
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
LIBDIRS := LIBDIRS := $(PORTLIBS)
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional # 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)) \ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD) \ -I$(CURDIR)/$(BUILD) \
-I$(LIBOGC_INC) -I$(LIBOGC_INC) -I$(PORTLIBS)/include
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# build a list of library paths # 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 # 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 # list of directories containing libraries, this must be the top level containing
# include and lib # include and lib
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
LIBDIRS := LIBDIRS := $(PORTLIBS)
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional # 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)) \ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD) \ -I$(CURDIR)/$(BUILD) \
-I$(LIBOGC_INC) -I$(LIBOGC_INC) -I$(PORTLIBS)/include
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# build a list of library paths # build a list of library paths

View File

@ -39,6 +39,9 @@ static struct port_t
*****************************************************************************/ *****************************************************************************/
void io_init(void) void io_init(void)
{ {
/* set region according to ROM header */
set_region();
/* restore previous setting */ /* restore previous setting */
if (old_system[0] != -1) input.system[0] = old_system[0]; if (old_system[0] != -1) input.system[0] = old_system[0];
if (old_system[1] != -1) input.system[1] = old_system[1]; 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_m68k = 0;
count_z80 = 0; count_z80 = 0;
}
resetline = -1; /* clear !RESET */
gen_running = 1; /* System is running */ gen_running = 1; /* System is running */
zreset = 0; /* Z80 is reset */ zreset = 0; /* Z80 is reset */
zbusreq = 0; /* Z80 has control of the Z bus */ zbusreq = 0; /* Z80 has control of the Z bus */
zbusack = 1; /* Z80 is busy using the Z bus */ zbusack = 1; /* Z80 is busy using the Z bus */
zirq = 0; /* No interrupts occuring */ zirq = 0; /* No interrupts occuring */
zbank = 0; /* Assume default bank is $000000-$007FFF */ zbank = 0; /* Assume default bank is $000000-$007FFF */
}
resetline = -1;
/* reset CPUs */ /* reset CPUs */
m68k_pulse_reset(); m68k_pulse_reset();

View File

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

View File

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

View File

@ -23,6 +23,7 @@
********************************************************************************/ ********************************************************************************/
#include "shared.h" #include "shared.h"
#include "file_dvd.h"
#include "gui.h" #include "gui.h"
#ifndef HW_RVL #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) u32 dvd_read (void *dst, u32 len, u64 offset)
{ {
/*** We only allow 2k reads **/ /*** We only allow 2k reads **/
if (len > 2048) return 0; if (len > DVDCHUNK) return 0;
/*** Let's not read past end of DVD ***/ /*** Let's not read past end of DVD ***/
if(offset < DvdMaxOffset) if(offset < DvdMaxOffset)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -232,13 +232,14 @@ static gui_item items_audio[10] =
}; };
/* System options menu */ /* 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,"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,"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,"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,"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,"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} {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_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 if (config.lock_on == TYPE_SK) sprintf (items[4].text, "Lock-On: SONIC & KNUCKLES");
else sprintf (items[4].text, "Lock-On: OFF"); else sprintf (items[4].text, "Lock-On: OFF");
sprintf (items[5].text, "Cartridge Swap: %s", config.hot_swap ? "ON":"OFF");
if (svp) if (svp)
{ {
sprintf (items[5].text, "SVP Cycles: %d", SVP_cycles); sprintf (items[6].text, "SVP Cycles: %d", SVP_cycles);
m->max_items = 6; m->max_items = 7;
} }
else else
{ {
m->max_items = 5; m->max_items = 6;
if (m->offset > 1) m->offset =1; if (m->offset > 2) m->offset--;
} }
GUI_InitMenu(m); GUI_InitMenu(m);
@ -973,9 +975,14 @@ static void systemmenu ()
} }
break; 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); 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; break;
case -1: case -1:
@ -1193,10 +1200,7 @@ static void ctrlmenu(void)
gui_item *items = NULL; gui_item *items = NULL;
u8 *special = NULL; u8 *special = NULL;
char msg[16]; char msg[16];
#ifdef HW_RVL
u32 exp; u32 exp;
#endif
/* System devices */ /* System devices */
gui_item items_sys[2][7] = gui_item items_sys[2][7] =
@ -1528,20 +1532,45 @@ static void ctrlmenu(void)
break; break;
case 11: /* input controller selection */ case 11: /* input controller selection */
#ifdef HW_RVL
/* no input device */ /* no input device */
if (config.input[player].device > 0) if (config.input[player].device < 0)
{ {
/* use next port */ /* try gamecube controllers */
config.input[player].port ++; config.input[player].device = 0;
config.input[player].port = 0;
} }
else else
{ {
/* use gamecube pad */ /* try next port */
config.input[player].device ++; config.input[player].port ++;
config.input[player].port = config.input[player].device ? 0 : (player%4);
} }
/* 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) */ /* autodetect connected wiimotes (without nunchuk) */
if (config.input[player].device == 1) if (config.input[player].device == 1)
{ {
@ -1622,8 +1651,8 @@ static void ctrlmenu(void)
if (config.input[player].port >= 4) if (config.input[player].port >= 4)
{ {
/* no classic controller found, use default gamecube pad */ /* no input controller left */
config.input[player].device = 0; config.input[player].device = -1;
config.input[player].port = player%4; config.input[player].port = player%4;
} }
} }
@ -1634,11 +1663,6 @@ static void ctrlmenu(void)
config.input[player].padtype = DEVICE_3BUTTON; config.input[player].padtype = DEVICE_3BUTTON;
memcpy(&m->items[10],&items[*special],sizeof(gui_item)); 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 #endif
/* update menu items */ /* update menu items */
@ -1670,6 +1694,7 @@ static void ctrlmenu(void)
break; break;
} }
} }
else if (update < 0) else if (update < 0)
{ {
if (m->bg_images[7].state & IMAGE_VISIBLE) if (m->bg_images[7].state & IMAGE_VISIBLE)
@ -1702,6 +1727,32 @@ static void ctrlmenu(void)
update = 0; 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 */ /* remove duplicate assigned inputs before leaving */
@ -2224,13 +2275,16 @@ void MainMenu (void)
GUI_InitMenu(m); GUI_InitMenu(m);
break; break;
case 4: /*** Emulator Reset ***/ case 4: /*** System Power Off/On ***/
if (!cart.romsize) break; if (!cart.romsize) break;
GUI_DrawMenuFX(m,10,1); GUI_DrawMenuFX(m,10,1);
GUI_DeleteMenu(m); GUI_DeleteMenu(m);
gxClearScreen((GXColor)BLACK); gxClearScreen((GXColor)BLACK);
gxSetScreen(); gxSetScreen();
system_init();
audio_init(48000);
system_reset(); system_reset();
memfile_autoload(config.sram_auto,-1);
quit = 1; quit = 1;
break; break;

View File

@ -2,6 +2,9 @@
Copyright (c) 2008 Francisco Muñoz 'Hermes' <www.elotrolado.net> Copyright (c) 2008 Francisco Muñoz 'Hermes' <www.elotrolado.net>
All rights reserved. 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 Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met: 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. THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef NO_SOUND
#include "oggplayer.h" #include "oggplayer.h"
#include <gccore.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 */ /* OGG control */
@ -61,15 +266,15 @@ static private_data_ogg private_ogg;
#define STACKSIZE 8192 #define STACKSIZE 8192
static u8 oggplayer_stack[STACKSIZE]; static u8 oggplayer_stack[STACKSIZE];
static lwpq_t oggplayer_queue; static lwpq_t oggplayer_queue = LWP_TQUEUE_NULL;
static lwp_t h_oggplayer; static lwp_t h_oggplayer = LWP_THREAD_NULL;
static int ogg_thread_running = 0; static int ogg_thread_running = 0;
static void ogg_add_callback(int voice) static void ogg_add_callback(int voice)
{ {
if (ogg_thread_running <= 0) if (!ogg_thread_running)
{ {
SND_StopVoice(0); ASND_StopVoice(0);
return; return;
} }
@ -78,7 +283,7 @@ static void ogg_add_callback(int voice)
if (private_ogg.pcm_indx >= READ_SAMPLES) if (private_ogg.pcm_indx >= READ_SAMPLES)
{ {
if (SND_AddVoice(0, if (ASND_AddVoice(0,
(void *) private_ogg.pcmout[private_ogg.pcmout_pos], (void *) private_ogg.pcmout[private_ogg.pcmout_pos],
private_ogg.pcm_indx << 1) == 0) 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) static void * ogg_player_thread(private_data_ogg * priv)
{ {
int first_time = 1; int first_time = 1;
long ret;
ogg_thread_running = 0;
/* init */ /* init */
LWP_InitQueue(&oggplayer_queue); LWP_InitQueue(&oggplayer_queue);
priv[0].vi = ov_info(&priv[0].vf, -1); priv[0].vi = ov_info(&priv[0].vf, -1);
SND_Pause(0); ASND_Pause(0);
priv[0].pcm_indx = 0; priv[0].pcm_indx = 0;
priv[0].pcmout_pos = 0; priv[0].pcmout_pos = 0;
@ -118,22 +323,15 @@ static void * ogg_player_thread(private_data_ogg * priv)
ogg_thread_running = 1; 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) if (priv[0].flag)
LWP_ThreadSleep(oggplayer_queue); /* wait only when i have samples to send */ 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 (priv[0].flag == 0) /* wait to all samples are sended */
{ {
if (SND_TestPointer(0, priv[0].pcmout[priv[0].pcmout_pos]) if (ASND_TestPointer(0, priv[0].pcmout[priv[0].pcmout_pos])
&& SND_StatusVoice(0) != SND_UNUSED) && ASND_StatusVoice(0) != SND_UNUSED)
{ {
priv[0].flag |= 64; priv[0].flag |= 64;
continue; continue;
@ -187,12 +385,12 @@ static void * ogg_player_thread(private_data_ogg * priv)
if (priv[0].flag == 1) if (priv[0].flag == 1)
{ {
if (SND_StatusVoice(0) == SND_UNUSED || first_time) if (ASND_StatusVoice(0) == SND_UNUSED || first_time)
{ {
first_time = 0; first_time = 0;
if (priv[0].vi->channels == 2) 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], (void *) priv[0].pcmout[priv[0].pcmout_pos],
priv[0].pcm_indx << 1, priv[0].volume, priv[0].pcm_indx << 1, priv[0].volume,
priv[0].volume, ogg_add_callback); priv[0].volume, ogg_add_callback);
@ -202,7 +400,7 @@ static void * ogg_player_thread(private_data_ogg * priv)
} }
else 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], (void *) priv[0].pcmout[priv[0].pcmout_pos],
priv[0].pcm_indx << 1, priv[0].volume, priv[0].pcm_indx << 1, priv[0].volume,
priv[0].volume, ogg_add_callback); priv[0].volume, ogg_add_callback);
@ -211,48 +409,47 @@ static void * ogg_player_thread(private_data_ogg * priv)
priv[0].flag = 0; 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); ov_clear(&priv[0].vf);
priv[0].fd = -1; priv[0].fd = -1;
priv[0].pcm_indx = 0; priv[0].pcm_indx = 0;
ogg_thread_running = 0;
/* free */
LWP_CloseQueue(oggplayer_queue);
return 0; return 0;
} }
void StopOgg() void StopOgg()
{ {
SND_StopVoice(0); ASND_StopVoice(0);
if (ogg_thread_running > 0) ogg_thread_running = 0;
if(h_oggplayer != LWP_THREAD_NULL)
{ {
ogg_thread_running = -2; if(oggplayer_queue != LWP_TQUEUE_NULL)
LWP_ThreadSignal(oggplayer_queue); LWP_ThreadSignal(oggplayer_queue);
LWP_JoinThread(h_oggplayer, NULL); LWP_JoinThread(h_oggplayer, NULL);
h_oggplayer = LWP_THREAD_NULL;
while (((volatile int) ogg_thread_running) != 0)
{
;;;
} }
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(); 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.mode = mode;
private_ogg.eof = 0; private_ogg.eof = 0;
private_ogg.volume = 127; private_ogg.volume = 127;
@ -262,32 +459,22 @@ int PlayOgg(int fd, int time_pos, int mode)
if (time_pos > 0) if (time_pos > 0)
private_ogg.seek_time = time_pos; private_ogg.seek_time = time_pos;
if (fd < 0) if (ov_open_callbacks((void *) &private_ogg.fd, &private_ogg.vf, NULL, 0, callbacks) < 0)
{
private_ogg.fd = -1;
return -1;
}
if (ov_open((void *) &private_ogg.fd, &private_ogg.vf, NULL, 0) < 0)
{ {
mem_close(private_ogg.fd); /* mem_close() can too close files from devices */ mem_close(private_ogg.fd); /* mem_close() can too close files from devices */
private_ogg.fd = -1; private_ogg.fd = -1;
ogg_thread_running = -1; ogg_thread_running = 0;
return -1; return -1;
} }
if (LWP_CreateThread(&h_oggplayer, (void *) ogg_player_thread, if (LWP_CreateThread(&h_oggplayer, (void *) ogg_player_thread,
&private_ogg, oggplayer_stack, STACKSIZE, 80) == -1) &private_ogg, oggplayer_stack, STACKSIZE, 80) == -1)
{ {
ogg_thread_running = -1; ogg_thread_running = 0;
ov_clear(&private_ogg.vf); ov_clear(&private_ogg.vf);
private_ogg.fd = -1; private_ogg.fd = -1;
return -1; return -1;
} }
while (((volatile int) ogg_thread_running) == 0)
{
;;;
}
LWP_ThreadSignal(oggplayer_queue);
return 0; return 0;
} }
@ -306,39 +493,33 @@ void PauseOgg(int pause)
if (ogg_thread_running > 0) if (ogg_thread_running > 0)
{ {
LWP_ThreadSignal(oggplayer_queue); LWP_ThreadSignal(oggplayer_queue);
/* while(((volatile int )private_ogg.flag)!=1 && ((volatile int )ogg_thread_running)>0) {;;;} */
} }
} }
} }
} }
int StatusOgg() int StatusOgg()
{ {
if (ogg_thread_running <= 0) if (ogg_thread_running == 0)
return -1; /* Error */ return -1; /* Error */
else if (private_ogg.eof)
if (private_ogg.eof)
return 255; /* EOF */ return 255; /* EOF */
else if (private_ogg.flag & 128)
if (private_ogg.flag & 128)
return 2; /* paused */ return 2; /* paused */
else
return 1; /* running */ return 1; /* running */
} }
void SetVolumeOgg(int volume) void SetVolumeOgg(int volume)
{ {
private_ogg.volume = volume; private_ogg.volume = volume;
ASND_ChangeVolumeVoice(0, volume, volume);
SND_ChangeVolumeVoice(0, volume, volume);
} }
s32 GetTimeOgg() s32 GetTimeOgg()
{ {
int ret; int ret;
if (ogg_thread_running <= 0) if (ogg_thread_running == 0 || private_ogg.fd < 0)
return 0;
if (private_ogg.fd < 0)
return 0; return 0;
ret = ((s32) ov_time_tell(&private_ogg.vf)); ret = ((s32) ov_time_tell(&private_ogg.vf));
if (ret < 0) if (ret < 0)
@ -353,4 +534,3 @@ void SetTimeOgg(s32 time_pos)
private_ogg.seek_time = time_pos; private_ogg.seek_time = time_pos;
} }
#endif

View File

@ -58,7 +58,9 @@ extern "C"
-- Params --- -- 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 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) if (Bg_music_ogg && !Shutdown)
{ {
PauseOgg(0); 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); SetVolumeOgg(((int)config.bgm_volume * 255) / 100);
} }
} }

View File

@ -563,6 +563,26 @@ static void wpad_update(s8 chan, u8 i, u32 exp)
} }
} }
#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 */ /* Invert Y coordinate */
if (!config.invert_mouse) input.analog[2][1] = -input.analog[2][1]; if (!config.invert_mouse) input.analog[2][1] = -input.analog[2][1];
} }
@ -651,7 +671,7 @@ void gx_input_SetDefault(void)
#endif #endif
/* Default player inputs */ /* 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].device = -1;
config.input[i].port = i%4; config.input[i].port = i%4;
@ -697,7 +717,7 @@ void gx_input_SetDefault(void)
/* check if Gamecube Controller is connected */ /* check if Gamecube Controller is connected */
if (exp & (1 << i)) if (exp & (1 << i))
{ {
for (j=0; j<MAX_DEVICES; j++) for (j=0; j<MAX_INPUTS; j++)
{ {
/* look for the first unassigned player */ /* look for the first unassigned player */
if (config.input[j].device == -1) 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_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(0.0, 0.0); GX_TexCoord2f32(0.0, 0.0);
GX_End (); GX_End ();
GX_DrawDone();
/* restore GX rendering */ /* restore GX rendering */
gxResetRendering(0); 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_Position2s16(x,y);
GX_Color4u8(color.r,color.g,color.b,alpha); GX_Color4u8(color.r,color.g,color.b,alpha);
GX_End (); GX_End ();
GX_DrawDone();
/* restore GX rendering */ /* restore GX rendering */
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT); 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_Color4u8(0xff,0xff,0xff,alpha);
GX_TexCoord2f32(0.0, 0.0); GX_TexCoord2f32(0.0, 0.0);
GX_End (); 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_Color4u8(0xff,0xff,0xff,alpha);
GX_TexCoord2f32(0.0, 1.0); GX_TexCoord2f32(0.0, 1.0);
GX_End (); GX_End ();
GX_DrawDone();
/* restore default Modelview */ /* restore default Modelview */
guLookAt(mv, &cam.pos, &cam.up, &cam.view); 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_Color4u8(0xff,0xff,0xff,alpha);
GX_TexCoord2f32(0.0, 0.0); GX_TexCoord2f32(0.0, 0.0);
GX_End (); GX_End ();
GX_DrawDone();
} }
} }
@ -796,7 +791,6 @@ void gxDrawScreenshot(u8 alpha)
GX_Color4u8(0xff,0xff,0xff,alpha); GX_Color4u8(0xff,0xff,0xff,alpha);
GX_TexCoord2f32(0.0, 0.0); GX_TexCoord2f32(0.0, 0.0);
GX_End (); GX_End ();
GX_DrawDone();
} }
void gxCopyScreenshot(gx_texture *texture) void gxCopyScreenshot(gx_texture *texture)
@ -829,7 +823,6 @@ void gxCopyScreenshot(gx_texture *texture)
GX_Color4u8(0xff,0xff,0xff,0xff); GX_Color4u8(0xff,0xff,0xff,0xff);
GX_TexCoord2f32(0.0, 0.0); GX_TexCoord2f32(0.0, 0.0);
GX_End (); GX_End ();
GX_DrawDone();
/* copy EFB to texture */ /* copy EFB to texture */
texture->format = GX_TF_RGBA8; texture->format = GX_TF_RGBA8;
@ -838,6 +831,7 @@ void gxCopyScreenshot(gx_texture *texture)
texture->data = screenshot; texture->data = screenshot;
GX_SetTexCopySrc(0, 0, texture->width * 2, texture->height * 2); GX_SetTexCopySrc(0, 0, texture->width * 2, texture->height * 2);
GX_SetTexCopyDst(texture->width, texture->height, texture->format, GX_TRUE); GX_SetTexCopyDst(texture->width, texture->height, texture->format, GX_TRUE);
GX_DrawDone();
GX_CopyTex(texture->data, GX_TRUE); GX_CopyTex(texture->data, GX_TRUE);
GX_Flush(); GX_Flush();
@ -847,6 +841,7 @@ void gxCopyScreenshot(gx_texture *texture)
GX_PixModeSync(); GX_PixModeSync();
GX_LoadTexObj(&texobj, GX_TEXMAP0); GX_LoadTexObj(&texobj, GX_TEXMAP0);
GX_InvalidateTexAll(); GX_InvalidateTexAll();
GX_Flush();
DCFlushRange(texture->data, texture->width * texture->height * 4); DCFlushRange(texture->data, texture->width * texture->height * 4);
} }
@ -869,6 +864,7 @@ void gxSaveScreenshot(char *filename)
void gxSetScreen(void) void gxSetScreen(void)
{ {
GX_DrawDone();
GX_CopyDisp(xfb[whichfb], GX_FALSE); GX_CopyDisp(xfb[whichfb], GX_FALSE);
GX_Flush(); GX_Flush();
VIDEO_SetNextFramebuffer (xfb[whichfb]); VIDEO_SetNextFramebuffer (xfb[whichfb]);
@ -1396,7 +1392,6 @@ void gx_video_Update(void)
/* render textured quad */ /* render textured quad */
draw_square(); draw_square();
GX_DrawDone();
/* LightGun marks */ /* LightGun marks */
if (crosshair[0]) gxDrawCrosshair(crosshair[0], input.analog[0][0],input.analog[0][1]); 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; whichfb ^= 1;
/* copy EFB to XFB */ /* copy EFB to XFB */
GX_DrawDone();
GX_CopyDisp(xfb[whichfb], GX_TRUE); GX_CopyDisp(xfb[whichfb], GX_TRUE);
GX_Flush(); GX_Flush();
VIDEO_SetNextFramebuffer(xfb[whichfb]); VIDEO_SetNextFramebuffer(xfb[whichfb]);

View File

@ -110,12 +110,26 @@ static void init_machine(void)
***************************************************/ ***************************************************/
void reloadrom (int size, char *name) 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; cart.romsize = size;
load_rom(name); /* Load ROM */ load_rom(name);
if (hotswap)
{
cart_hw_init();
cart_hw_reset();
}
else
{
system_init (); /* Initialize System */ system_init (); /* Initialize System */
audio_init(48000); /* Audio System initialization */ audio_init(48000); /* Audio System initialization */
ClearGGCodes (); /* Clear Game Genie patches */ ClearGGCodes (); /* Clear Game Genie patches */
system_reset (); /* System Power ON */ system_reset (); /* System Power ON */
}
} }
/************************************************** /**************************************************

View File

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

View File

@ -267,7 +267,7 @@ int load_rom(char *filename)
free(ptr); free(ptr);
#endif #endif
/* detect interleaved roms (.smd format) */ /* detect interleaved format (.SMD) */
if (strncmp((char *)(cart.rom + 0x100),"SEGA", 4) && ((size / 512) & 1)) if (strncmp((char *)(cart.rom + 0x100),"SEGA", 4) && ((size / 512) & 1))
{ {
size -= 512; size -= 512;
@ -288,8 +288,8 @@ int load_rom(char *filename)
/* clear unused ROM space */ /* clear unused ROM space */
memset (cart.rom + size, 0xff, MAXROMSIZE - size); memset (cart.rom + size, 0xff, MAXROMSIZE - size);
getrominfo((char *)cart.rom); /* get infos from ROM header */ /* get infos from ROM header */
set_region(); /* set game region (PAL/NTSC, JAP/USA/EUR) */ getrominfo((char *)cart.rom);
#ifdef LSB_FIRST #ifdef LSB_FIRST
/* Byteswap ROM */ /* Byteswap ROM */
@ -380,10 +380,6 @@ void set_region ()
else if (config.region_detect == 2) region_code = REGION_EUROPE; 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 == 3) region_code = REGION_JAPAN_NTSC;
else if (config.region_detect == 4) region_code = REGION_JAPAN_PAL; 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_l = out[0];
sample_t* out_r = out[1]; sample_t* out_r = out[1];
const sample_t* in = buffer; sample_t* in = buffer;
sample_t* end_pos = write_pos; sample_t* end_pos = write_pos;
unsigned long skip = skip_bits >> imp_phase; unsigned long skip = skip_bits >> imp_phase;
sample_t const* imp = impulses [imp_phase]; sample_t const* imp = impulses [imp_phase];

View File

@ -210,9 +210,9 @@ void system_init (void)
{ {
/* Genesis hardware */ /* Genesis hardware */
gen_init(); gen_init();
io_init();
vdp_init(); vdp_init();
render_init(); render_init();
io_init();
/* Cartridge hardware */ /* Cartridge hardware */
cart_hw_init(); cart_hw_init();
@ -229,9 +229,9 @@ void system_reset (void)
/* Genesis hardware */ /* Genesis hardware */
gen_reset(1); gen_reset(1);
SN76489_Reset(); SN76489_Reset();
io_reset();
vdp_reset(); vdp_reset();
render_reset(); render_reset();
io_reset();
/* Clear Sound Buffers */ /* Clear Sound Buffers */
if (snd.psg.buffer) memset (snd.psg.buffer, 0, SND_SIZE); 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) void vdp_init(void)
{ {
/* PAL/NTSC timings */ /* PAL/NTSC timings */
vdp_rate = vdp_pal ? 50 : 60; switch (region_code)
lines_per_frame = vdp_pal ? 313 : 262; {
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) void vdp_reset(void)
@ -443,7 +456,7 @@ unsigned int vdp_ctrl_r(void)
if (!(reg[1] & 0x40)) temp |= 0x8; if (!(reg[1] & 0x40)) temp |= 0x8;
/* HBLANK flag (Sonic 3 and Sonic 2 "VS Modes", Lemmings 2, Mega Turrican) */ /* 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 */ /* clear pending flag */
pending = 0; pending = 0;