Merge git://github.com/ekeeke/Genesis-Plus-GX

Conflicts:
	source/system.c
This commit is contained in:
Twinaphex 2012-07-26 13:12:06 +02:00
commit d28fe8ee29
28 changed files with 686 additions and 503 deletions

View File

@ -6,124 +6,142 @@
# #
# Defines : # Defines :
# -DLSB_FIRST : for little endian systems. # -DLSB_FIRST : for little endian systems.
# -DBUILD_TABLES: do not use const tables for 68k instructions (obsolete)
# -DLOGERROR : enable message logging # -DLOGERROR : enable message logging
# -DLOGVDP : enable VDP debug messages # -DLOGVDP : enable VDP debug messages
# -DLOG_SCD : enable SCD debug messages
# -DLOG_CDD : enable CDD debug messages
# -DLOG_CDC : enable CDC debug messages
# -DLOG_PCM : enable PCM debug messages
# -DLOGSOUND : enable AUDIO debug messages # -DLOGSOUND : enable AUDIO debug messages
# -D8BPP_RENDERING - configure for 8-bit pixels (RGB332) # -D8BPP_RENDERING - configure for 8-bit pixels (RGB332)
# -D15BPP_RENDERING - configure for 15-bit pixels (RGB555) # -D15BPP_RENDERING - configure for 15-bit pixels (RGB555)
# -D16BPP_RENDERING - configure for 16-bit pixels (RGB565) # -D16BPP_RENDERING - configure for 16-bit pixels (RGB565)
# -D32BPP_RENDERING - configure for 32-bit pixels (RGB888) # -D32BPP_RENDERING - configure for 32-bit pixels (RGB888)
NAME = gen_sdl.exe NAME = gen_sdl.exe
CC = gcc CC = gcc
CFLAGS = `sdl-config --cflags` -march=i686 -O6 -fomit-frame-pointer -Wall -Wno-strict-aliasing CFLAGS = `sdl-config --cflags` -march=i686 -O6 -fomit-frame-pointer -Wall -Wno-strict-aliasing -ansi -std=c89 -pedantic-errors
#-ansi -pedantic-errors
#-g -ggdb -pg #-g -ggdb -pg
#-fomit-frame-pointer #-fomit-frame-pointer
#LDFLAGS = -pg LDFLAGS =
DEFINES = -DLSB_FIRST -DUSE_16BPP_RENDERING DEFINES = -DLSB_FIRST -DUSE_16BPP_RENDERING -DLOGERROR -DLOG_CDC -DLOG_CDD -DLOG_SCD -DLOGVDP -DLOG_PCM
INCLUDES = -Isource -Isource/z80 -Isource/m68k -Isource/sound -Isource/input_hw -Isource/cart_hw -Isource/cart_hw/svp -Isource/ntsc -Isource/win INCLUDES = -I. -I.. -I../z80 -I../m68k -I../sound -I../input_hw -I../cart_hw -I../cd_hw -I../cart_hw/svp -I../ntsc
LIBS = `sdl-config --libs` -lz -lm LIBS = `sdl-config --libs` -lz -lm
OBJDIR = ./build_sdl OBJECTS = obj/z80.o
OBJECTS = $(OBJDIR)/z80.o OBJECTS += obj/m68kcpu.o \
obj/s68kcpu.o \
OBJECTS += $(OBJDIR)/m68kcpu.o OBJECTS += obj/genesis.o \
obj/vdp_ctrl.o \
obj/vdp_render.o \
obj/system.o \
obj/io_ctrl.o \
obj/mem68k.o \
obj/memz80.o \
obj/membnk.o \
obj/state.o
OBJECTS += $(OBJDIR)/genesis.o \ OBJECTS += obj/input.o \
$(OBJDIR)/vdp_ctrl.o \ obj/gamepad.o \
$(OBJDIR)/vdp_render.o \ obj/lightgun.o \
$(OBJDIR)/system.o \ obj/mouse.o \
$(OBJDIR)/io_ctrl.o \ obj/activator.o \
$(OBJDIR)/mem68k.o \ obj/xe_a1p.o \
$(OBJDIR)/memz80.o \ obj/teamplayer.o \
$(OBJDIR)/membnk.o \ obj/paddle.o \
$(OBJDIR)/state.o \ obj/sportspad.o \
$(OBJDIR)/loadrom.o obj/terebi_oekaki.o
OBJECTS += $(OBJDIR)/input.o \
$(OBJDIR)/gamepad.o \
$(OBJDIR)/lightgun.o \
$(OBJDIR)/mouse.o \
$(OBJDIR)/activator.o \
$(OBJDIR)/xe_a1p.o \
$(OBJDIR)/teamplayer.o \
$(OBJDIR)/paddle.o \
$(OBJDIR)/sportspad.o \
$(OBJDIR)/terebi_oekaki.o
OBJECTS += $(OBJDIR)/sound.o \ OBJECTS += obj/sound.o \
$(OBJDIR)/sn76489.o \ obj/sn76489.o \
$(OBJDIR)/ym2413.o \ obj/ym2413.o \
$(OBJDIR)/ym2612.o obj/ym2612.o
OBJECTS += $(OBJDIR)/Fir_Resampler.o OBJECTS += obj/Fir_Resampler.o
OBJECTS += $(OBJDIR)/blip.o OBJECTS += obj/blip.o
OBJECTS += $(OBJDIR)/eq.o
OBJECTS += $(OBJDIR)/sram.o \ OBJECTS += obj/eq.o \
$(OBJDIR)/svp.o \
$(OBJDIR)/ssp16.o \
$(OBJDIR)/ggenie.o \
$(OBJDIR)/areplay.o \
$(OBJDIR)/gg_eeprom.o \
$(OBJDIR)/md_eeprom.o \
$(OBJDIR)/md_cart.o \
$(OBJDIR)/sms_cart.o
OBJECTS += $(OBJDIR)/sms_ntsc.o \ OBJECTS += obj/sram.o \
$(OBJDIR)/md_ntsc.o obj/svp.o \
obj/ssp16.o \
obj/ggenie.o \
obj/areplay.o \
obj/gg_eeprom.o \
obj/md_eeprom.o \
obj/md_cart.o \
obj/sms_cart.o
OBJECTS += $(OBJDIR)/main.o \ OBJECTS += obj/scd.o \
$(OBJDIR)/config.o \ obj/cdd.o \
$(OBJDIR)/error.o \ obj/cdc.o \
$(OBJDIR)/unzip.o \ obj/gfx.o \
$(OBJDIR)/fileio.o obj/pcm.o \
obj/cd_cart.o
OBJECTS += $(OBJDIR)/icon.o OBJECTS += obj/main.o \
obj/config.o \
obj/error.o \
obj/unzip.o \
obj/fileio.o \
obj/loadrom.o
OBJECTS += obj/sms_ntsc.o \
obj/md_ntsc.o
OBJECTS += obj/icon.o
all: $(NAME) all: $(NAME)
$(NAME): $(OBJDIR) $(OBJECTS) $(NAME): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $@ $(CC) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $@ -Wl,-Map,genplus.map
$(OBJDIR) : obj/%.o : ../%.c ../%.h
@[ -d $@ ] || mkdir -p $@
$(OBJDIR)/%.o : source/%.c source/%.h
$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@ $(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@
$(OBJDIR)/%.o : source/sound/%.c source/sound/%.h obj/%.o : ../asm/%.s
$(AS) $< -o $@
obj/%.o : ../sound/%.c ../sound/%.h
$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@
obj/%.o : ../sound/%.c
$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@ $(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@
$(OBJDIR)/%.o : source/input_hw/%.c source/input_hw/%.h obj/%.o : ../input_hw/%.c ../input_hw/%.h
$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@ $(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@
$(OBJDIR)/%.o : source/cart_hw/%.c source/cart_hw/%.h obj/%.o : ../cart_hw/%.c ../cart_hw/%.h
$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@ $(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@
$(OBJDIR)/%.o : source/cart_hw/svp/%.c obj/%.o : ../cart_hw/svp/%.c
$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@
obj/%.o : ../cart_hw/svp/%.c ../cart_hw/svp/%.h
$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@ $(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@
$(OBJDIR)/%.o : source/cart_hw/svp/%.c source/cart_hw/svp/%.h obj/%.o : ../cd_hw/%.c
$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@ $(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@
$(OBJDIR)/%.o : source/z80/%.c source/z80/%.h obj/%.o : ../z80/%.c ../z80/%.h
$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@ $(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@
$(OBJDIR)/%.o : source/m68k/%.c source/m68k/%.h obj/%.o : ../m68k/%.c
$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@ $(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@
$(OBJDIR)/%.o : source/ntsc/%.c source/ntsc/%.h obj/%.o : ./%.c ./%.h
$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@ $(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@
$(OBJDIR)/%.o : source/win/%.c source/win/%.h obj/%.o : ../ntsc/%.c ../ntsc/%.h
$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@ $(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@
$(OBJDIR)/icon.o : obj/icon.o :
windres source/win/icon.rc $@ windres icon.rc $@
pack : pack :
strip $(NAME) strip $(NAME)

View File

@ -249,10 +249,10 @@ void cd_cart_init(void)
m68k.memory_map[i].base = scd.cartridge.area + ((i & 0x3f) << 16); m68k.memory_map[i].base = scd.cartridge.area + ((i & 0x3f) << 16);
m68k.memory_map[i].read8 = NULL; m68k.memory_map[i].read8 = NULL;
m68k.memory_map[i].read16 = NULL; m68k.memory_map[i].read16 = NULL;
m68k.memory_map[i].write8 = NULL; m68k.memory_map[i].write8 = m68k_unused_8_w;
m68k.memory_map[i].write16 = NULL; m68k.memory_map[i].write16 = m68k_unused_16_w;
zbank_memory_map[i].read = NULL; zbank_memory_map[i].read = NULL;
zbank_memory_map[i].write = NULL; zbank_memory_map[i].write = zbank_unused_w;
} }
} }
} }

View File

@ -471,9 +471,6 @@ void cdc_reg_w(unsigned char data)
unsigned char cdc_reg_r(void) unsigned char cdc_reg_r(void)
{ {
#ifdef LOG_CDC
error("CDC register %X read (%X) ", scd.regs[0x04>>1].byte.l & 0x0F, s68k.pc);
#endif
switch (scd.regs[0x04>>1].byte.l & 0x0F) switch (scd.regs[0x04>>1].byte.l & 0x0F)
{ {
case 0x01: /* IFSTAT */ case 0x01: /* IFSTAT */

View File

@ -74,6 +74,15 @@ static const uint16 lut_BCD_16[100] =
0x0900, 0x0901, 0x0902, 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, 0x0909, 0x0900, 0x0901, 0x0902, 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, 0x0909,
}; };
static const uint16 toc_snatcher[21] =
{
56164, 495, 10120, 20555, 1580, 5417, 12502, 16090, 6553, 9681,
8148, 20228, 8622, 6142, 5858, 1287, 7424, 3535, 31697, 2485,
31380
};
void cdd_init(void) void cdd_init(void)
{ {
} }
@ -126,33 +135,65 @@ void cdd_load(char *filename, int type_bin)
fseek(cdd.toc.tracks[0].fd, 0, SEEK_SET); fseek(cdd.toc.tracks[0].fd, 0, SEEK_SET);
/* initialize TOC */ /* initialize TOC */
/* TODO: add 2 seconds pause after data track ? */
cdd.toc.end = cdd.toc.tracks[0].end; cdd.toc.end = cdd.toc.tracks[0].end;
cdd.toc.last = 1; cdd.toc.last = 1;
/* TODO: add audio track support from BIN/CUE, ISO/WAV, MP3, OGG ? */ /* TODO: add audio track support from BIN/CUE, ISO/WAV, MP3, OGG ? */
/* Fake audio tracks if none found */ /* Simulated audio tracks if none found */
if (cdd.toc.last == 1) if (cdd.toc.last == 1)
{ {
/* default track duration (fix Snatcher intro) */ /* Some games require specific TOC infos */
int length = 4 * 60 * 75; if (strstr(rominfo.product,"T-95035") != NULL)
/* A-Rank Thunder Tanjouen requires shorter track duration to pass intro */
if (strstr(rominfo.product,"T-49064") != NULL)
{ {
length = 2 * 75; /* Snatcher */
cdd.toc.last = cdd.toc.end = 0;
do
{
cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_snatcher[cdd.toc.last];
cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
cdd.toc.last++;
}
while (cdd.toc.last < 21);
} }
else if (strstr(rominfo.product,"T-45074") != NULL)
/* max length = 60:02:00 */
do
{ {
cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; /* Lunar - Eternal Blue (J) */
cdd.toc.tracks[cdd.toc.last].end = cdd.toc.end + length; cdd.toc.tracks[1].start = cdd.toc.end + 2*75;
cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; cdd.toc.tracks[1].end = cdd.toc.tracks[1].start + 21654;
cdd.toc.last++; cdd.toc.end = cdd.toc.tracks[1].end;
cdd.toc.tracks[2].start = cdd.toc.end + 2*75;
cdd.toc.tracks[2].end = cdd.toc.tracks[2].start + 5004;
cdd.toc.end = cdd.toc.tracks[2].end;
cdd.toc.tracks[3].start = cdd.toc.end + 2*75;
cdd.toc.tracks[3].end = cdd.toc.tracks[3].start + 684;
cdd.toc.end = cdd.toc.tracks[3].end;
cdd.toc.last = 4;
}
else if (strstr(rominfo.product,"T-127045") != NULL)
{
/* Lunar - Eternal Blue (U) */
cdd.toc.tracks[1].start = cdd.toc.end + 2*75;
cdd.toc.tracks[1].end = cdd.toc.tracks[1].start + 21735;
cdd.toc.end = cdd.toc.tracks[1].end;
cdd.toc.tracks[2].start = cdd.toc.end + 2*75;
cdd.toc.tracks[2].end = cdd.toc.tracks[2].start + 27131;
cdd.toc.end = cdd.toc.tracks[2].end;
cdd.toc.last = 3;
}
else
{
/* default TOC (99 x 2s) */
do
{
cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end + 2*75;
cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + 2*75;
cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
cdd.toc.last++;
}
while ((cdd.toc.last < 99) && (cdd.toc.end < 56*60*75));
} }
while (cdd.toc.last <= 54);
} }
/* CD loaded */ /* CD loaded */
@ -175,15 +216,15 @@ void cdd_unload(void)
} }
} }
/* reset TOC */
memset(&cdd.toc, 0x00, sizeof(cdd.toc));
/* CD unloaded */ /* CD unloaded */
cdd.loaded = 0; cdd.loaded = 0;
/* unknown CD image file format */
cdd.sectorSize = 0;
} }
/* reset TOC */
memset(&cdd.toc, 0x00, sizeof(cdd.toc));
/* unknown CD image file format */
cdd.sectorSize = 0;
} }
void cdd_read(uint8 *dst) void cdd_read(uint8 *dst)
@ -219,19 +260,22 @@ void cdd_update(void)
} }
/* track type */ /* track type */
if (cdd.index) if (cdd.index > 0)
{ {
/* audio track sector is sent to CD Fader/DAC but also CDD */ if (cdd.index < cdd.toc.last)
cdc_decoder_update(0);
/* next audio track sector is automatically read */
cdd.lba++;
/* check end of current track */
if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
{ {
/* next track */ /* audio track sector sent to CD Fader/DAC should also be sent to CDD */
cdd.index++; cdc_decoder_update(0);
/* next sector is automatically read */
cdd.lba++;
/* check end of current track */
if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
{
/* next track */
cdd.index++;
}
} }
} }
else else
@ -249,7 +293,36 @@ void cdd_update(void)
} }
} }
/* TODO: handle FAST_FW & FAST_RW commands */ /* fast scanning disc */
else if (cdd.status == CD_SCAN)
{
/* skip track */
cdd.lba += cdd.scanOffset;
/* check current track limits */
if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
{
/* next track */
cdd.index++;
}
else if (cdd.lba < cdd.toc.tracks[cdd.index].start)
{
/* previous track */
cdd.index--;
}
/* check disc limits */
if (cdd.index < 0)
{
cdd.index = 0;
cdd.lba = 0;
}
else if (cdd.index >= cdd.toc.last)
{
cdd.index = cdd.toc.last;
cdd.lba = cdd.toc.end;
}
}
} }
void cdd_process(void) void cdd_process(void)
@ -303,7 +376,7 @@ void cdd_process(void)
case 0x02: /* Current track */ case 0x02: /* Current track */
{ {
scd.regs[0x38>>1].w = (cdd.status << 8) | 0x02; scd.regs[0x38>>1].w = (cdd.status << 8) | 0x02;
scd.regs[0x3a>>1].w = lut_BCD_16[cdd.index + 1]; scd.regs[0x3a>>1].w = (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A;
scd.regs[0x3c>>1].w = 0x0000; scd.regs[0x3c>>1].w = 0x0000;
scd.regs[0x3e>>1].w = 0x0000; scd.regs[0x3e>>1].w = 0x0000;
scd.regs[0x40>>1].byte.h = 0x00; scd.regs[0x40>>1].byte.h = 0x00;
@ -383,7 +456,7 @@ void cdd_process(void)
cdd.lba = lba; cdd.lba = lba;
/* update current track index */ /* update current track index */
while (cdd.toc.tracks[index].end <= lba) index++; while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
cdd.index = index; cdd.index = index;
/* track type */ /* track type */
@ -405,7 +478,7 @@ void cdd_process(void)
/* update status */ /* update status */
cdd.status = CD_PLAY; cdd.status = CD_PLAY;
scd.regs[0x38>>1].w = (CD_PLAY << 8) | 0x02; scd.regs[0x38>>1].w = (CD_PLAY << 8) | 0x02;
scd.regs[0x3a>>1].w = lut_BCD_16[index + 1]; scd.regs[0x3a>>1].w = (cdd.index < cdd.toc.last) ? lut_BCD_16[index + 1] : 0x0A0A;
scd.regs[0x3c>>1].w = 0x0000; scd.regs[0x3c>>1].w = 0x0000;
scd.regs[0x3e>>1].w = 0x0000; scd.regs[0x3e>>1].w = 0x0000;
scd.regs[0x40>>1].byte.h = 0x00; scd.regs[0x40>>1].byte.h = 0x00;
@ -426,7 +499,7 @@ void cdd_process(void)
cdd.lba = lba; cdd.lba = lba;
/* update current track index */ /* update current track index */
while (cdd.toc.tracks[index].end <= lba) index++; while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
cdd.index = index; cdd.index = index;
/* DATA track */ /* DATA track */
@ -482,7 +555,7 @@ void cdd_process(void)
/* update status */ /* update status */
cdd.status = CD_PLAY; cdd.status = CD_PLAY;
scd.regs[0x38>>1].w = (CD_PLAY << 8) | 0x02; scd.regs[0x38>>1].w = (CD_PLAY << 8) | 0x02;
scd.regs[0x3a>>1].w = lut_BCD_16[cdd.index+1]; scd.regs[0x3a>>1].w = (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A;
scd.regs[0x3c>>1].w = 0x0000; scd.regs[0x3c>>1].w = 0x0000;
scd.regs[0x3e>>1].w = 0x0000; scd.regs[0x3e>>1].w = 0x0000;
scd.regs[0x40>>1].byte.h = 0x00; scd.regs[0x40>>1].byte.h = 0x00;
@ -491,6 +564,7 @@ void cdd_process(void)
case 0x08: /* Forward Scan */ case 0x08: /* Forward Scan */
{ {
cdd.scanOffset = 10;
cdd.status = CD_SCAN; cdd.status = CD_SCAN;
scd.regs[0x38>>1].w = (CD_SCAN << 8) | 0x02; scd.regs[0x38>>1].w = (CD_SCAN << 8) | 0x02;
scd.regs[0x3a>>1].w = lut_BCD_16[cdd.index+1]; scd.regs[0x3a>>1].w = lut_BCD_16[cdd.index+1];
@ -502,6 +576,7 @@ void cdd_process(void)
case 0x09: /* Rewind Scan */ case 0x09: /* Rewind Scan */
{ {
cdd.scanOffset = -10;
cdd.status = CD_SCAN; cdd.status = CD_SCAN;
scd.regs[0x38>>1].w = (CD_SCAN << 8) | 0x02; scd.regs[0x38>>1].w = (CD_SCAN << 8) | 0x02;
scd.regs[0x3a>>1].w = lut_BCD_16[cdd.index+1]; scd.regs[0x3a>>1].w = lut_BCD_16[cdd.index+1];

View File

@ -67,6 +67,7 @@ typedef struct
int loaded; int loaded;
int index; int index;
int lba; int lba;
int scanOffset;
uint8 status; uint8 status;
uint16 sectorSize; uint16 sectorSize;
toc_t toc; toc_t toc;

View File

@ -93,38 +93,41 @@ void pcm_update(short *buffer, int length)
/* run eight PCM channels */ /* run eight PCM channels */
for (j=0; j<8; j++) for (j=0; j<8; j++)
{ {
/* check if channel is enabled (bit cleared) */ /* check if channel is enabled */
if (!(pcm.status & (1 << j))) if (pcm.status & (1 << j))
{ {
/* read current WAVE RAM address */ /* read from current WAVE RAM address */
short data = pcm.ram[(pcm.chan[j].addr >> 11) & 0xffff]; short data = pcm.ram[(pcm.chan[j].addr >> 11) & 0xffff];
/* STOP data ? */ /* loop data ? */
if (data == 0xff) if (data == 0xff)
{ {
/* reset WAVE RAM address with loop address */ /* reset WAVE RAM address */
pcm.chan[j].addr = pcm.chan[j].ls.w << 11; pcm.chan[j].addr = pcm.chan[j].ls.w << 11;
/* read WAVE RAM address again */ /* read again from WAVE RAM address */
data = pcm.ram[pcm.chan[j].ls.w]; data = pcm.ram[pcm.chan[j].ls.w];
/* no output on infinite loop */
if (data == 0xff) break;
} }
else
/* output L & R subchannels */
if (data & 0x80)
{ {
/* PCM data is negative */ /* increment WAVE RAM address */
data = -(data & 0x7f); pcm.chan[j].addr += pcm.chan[j].fd.w;
} }
/* multiply PCM data with ENV & stereo PAN data then add to outputs (13.6 fixed point) */ /* infinite loop should not output any data */
l += ((data * pcm.chan[j].env * (pcm.chan[j].pan & 0x0F)) >> 6); if (data != 0xff)
r += ((data * pcm.chan[j].env * (pcm.chan[j].pan >> 4)) >> 6); {
/* output L & R subchannels */
if (data & 0x80)
{
/* PCM data is negative */
data = -(data & 0x7f);
}
/* increment WAVE RAM address */ /* multiply PCM data with ENV & stereo PAN data then add to outputs (13.6 fixed point) */
pcm.chan[j].addr += pcm.chan[j].fd.w; l += ((data * pcm.chan[j].env * (pcm.chan[j].pan & 0x0F)) >> 6);
r += ((data * pcm.chan[j].env * (pcm.chan[j].pan >> 4)) >> 6);
}
} }
} }
@ -175,6 +178,10 @@ void pcm_update(short *buffer, int length)
void pcm_write(unsigned int address, unsigned char data) void pcm_write(unsigned int address, unsigned char data)
{ {
#ifdef LOG_PCM
error("[%d][%d]PCM %x write -> 0x%02x (%X)\n", v_counter, s68k.cycles, address, data, s68k.pc);
#endif
/* external RAM is mapped to $1000-$1FFF */ /* external RAM is mapped to $1000-$1FFF */
if (address >= 0x1000) if (address >= 0x1000)
{ {
@ -232,6 +239,12 @@ void pcm_write(unsigned int address, unsigned char data)
{ {
/* update channel WAVE RAM start address (16.11 fixed point) */ /* update channel WAVE RAM start address (16.11 fixed point) */
pcm.chan[pcm.index].st = data << (8 + 11); pcm.chan[pcm.index].st = data << (8 + 11);
/* reload WAVE RAM address if channel is OFF */
if (!(pcm.status & (1 << pcm.index)))
{
pcm.chan[pcm.index].addr = pcm.chan[pcm.index].st;
}
return; return;
} }
@ -255,18 +268,18 @@ void pcm_write(unsigned int address, unsigned char data)
case 0x08: /* ON/OFF register */ case 0x08: /* ON/OFF register */
{ {
/* reload WAVE RAM address pointers when channels are switched ON (bit cleared) */
if ((pcm.status & 0x01) && !(data & 0x01)) pcm.chan[0].addr = pcm.chan[0].st;
if ((pcm.status & 0x02) && !(data & 0x02)) pcm.chan[1].addr = pcm.chan[1].st;
if ((pcm.status & 0x04) && !(data & 0x04)) pcm.chan[2].addr = pcm.chan[2].st;
if ((pcm.status & 0x08) && !(data & 0x08)) pcm.chan[3].addr = pcm.chan[3].st;
if ((pcm.status & 0x10) && !(data & 0x10)) pcm.chan[4].addr = pcm.chan[4].st;
if ((pcm.status & 0x20) && !(data & 0x20)) pcm.chan[5].addr = pcm.chan[5].st;
if ((pcm.status & 0x40) && !(data & 0x40)) pcm.chan[6].addr = pcm.chan[6].st;
if ((pcm.status & 0x80) && !(data & 0x80)) pcm.chan[7].addr = pcm.chan[7].st;
/* update PCM channels status */ /* update PCM channels status */
pcm.status = data; pcm.status = ~data;
/* reload WAVE RAM address pointers when channels are OFF */
if (data & 0x01) pcm.chan[0].addr = pcm.chan[0].st;
if (data & 0x02) pcm.chan[1].addr = pcm.chan[1].st;
if (data & 0x04) pcm.chan[2].addr = pcm.chan[2].st;
if (data & 0x08) pcm.chan[3].addr = pcm.chan[3].st;
if (data & 0x10) pcm.chan[4].addr = pcm.chan[4].st;
if (data & 0x20) pcm.chan[5].addr = pcm.chan[5].st;
if (data & 0x40) pcm.chan[6].addr = pcm.chan[6].st;
if (data & 0x80) pcm.chan[7].addr = pcm.chan[7].st;
return; return;
} }
@ -280,6 +293,10 @@ void pcm_write(unsigned int address, unsigned char data)
unsigned char pcm_read(unsigned int address) unsigned char pcm_read(unsigned int address)
{ {
#ifdef LOG_PCM
error("[%d][%d]PCM %x read (%X)\n", v_counter, s68k.cycles, address, s68k.pc);
#endif
/* external RAM (TODO: verify if possible to read, some docs claim it's not !) */ /* external RAM (TODO: verify if possible to read, some docs claim it's not !) */
if (address >= 0x1000) if (address >= 0x1000)
{ {
@ -294,7 +311,7 @@ unsigned char pcm_read(unsigned int address)
if (address & 1) if (address & 1)
{ {
return pcm.chan[index].addr >> (11 + 8); return (pcm.chan[index].addr >> (11 + 8)) & 0xff;
} }
else else
{ {

View File

@ -190,6 +190,9 @@ INLINE void s68k_poll_detect(reg)
if (s68k.pc == s68k.poll.pc) if (s68k.pc == s68k.poll.pc)
{ {
/* stop SUB-CPU until register is modified by MAIN-CPU */ /* stop SUB-CPU until register is modified by MAIN-CPU */
#ifdef LOG_SCD
error("s68k stopped from %d cycles\n", s68k.cycles);
#endif
s68k.cycles = s68k.cycle_end; s68k.cycles = s68k.cycle_end;
s68k.stopped = 1 << reg; s68k.stopped = 1 << reg;
} }
@ -226,6 +229,9 @@ INLINE void s68k_poll_sync(reg)
/* restart MAIN-CPU */ /* restart MAIN-CPU */
m68k.stopped = 0; m68k.stopped = 0;
#ifdef LOG_SCD
error("m68k started from %d cycles\n", cycles);
#endif
} }
/* clear CPU register(s) access flags */ /* clear CPU register(s) access flags */
@ -269,6 +275,9 @@ static unsigned int scd_read_byte(unsigned int address)
if (address == 0xff8007) if (address == 0xff8007)
{ {
unsigned int data = cdc_reg_r(); unsigned int data = cdc_reg_r();
#ifdef LOG_CDC
error("CDC register %X read 0x%02X (%X) ", scd.regs[0x04>>1].byte.l & 0x0F, data, s68k.pc);
#endif
return data; return data;
} }
@ -412,6 +421,7 @@ INLINE void word_ram_switch(uint8 mode)
if (mode & 0x04) if (mode & 0x04)
{ {
/* 2M -> 1M mode */
for (i=0; i<0x10000; i++) for (i=0; i<0x10000; i++)
{ {
*ptr2++=*ptr1++; *ptr2++=*ptr1++;
@ -420,11 +430,43 @@ INLINE void word_ram_switch(uint8 mode)
} }
else else
{ {
/* 1M -> 2M mode */
for (i=0; i<0x10000; i++) for (i=0; i<0x10000; i++)
{ {
*ptr1++=*ptr2++; *ptr1++=*ptr2++;
*ptr1++=*ptr3++; *ptr1++=*ptr3++;
} }
/* allow Word-RAM access from both CPU in 2M mode (fixes sync issues in Mortal Kombat) */
for (i=scd.cartridge.boot+0x20; i<scd.cartridge.boot+0x24; i++)
{
/* MAIN-CPU: $200000-$23FFFF is mapped to 256K Word-RAM */
m68k.memory_map[i].base = scd.word_ram_2M + ((i & 0x03) << 16);
m68k.memory_map[i].read8 = NULL;
m68k.memory_map[i].read16 = NULL;
m68k.memory_map[i].write8 = NULL;
m68k.memory_map[i].write16 = NULL;
zbank_memory_map[i].read = NULL;
zbank_memory_map[i].write = NULL;
}
for (i=0x08; i<0x0c; i++)
{
/* SUB-CPU: $080000-$0BFFFF is mapped to 256K Word-RAM */
s68k.memory_map[i].read8 = NULL;
s68k.memory_map[i].read16 = NULL;
s68k.memory_map[i].write8 = NULL;
s68k.memory_map[i].write16 = NULL;
}
for (i=0x0c; i<0x0e; i++)
{
/* SUB-CPU: $0C0000-$0DFFFF is unmapped */
s68k.memory_map[i].read8 = s68k_read_bus_8;
s68k.memory_map[i].read16 = s68k_read_bus_16;
s68k.memory_map[i].write8 = s68k_unused_8_w;
s68k.memory_map[i].write16 = s68k_unused_16_w;
}
} }
} }
@ -471,12 +513,12 @@ static void scd_write_byte(unsigned int address, unsigned int data)
case 0x03: /* Memory Mode */ case 0x03: /* Memory Mode */
{ {
s68k_poll_sync(0x02);
/* detect MODE & RET bits modifications */ /* detect MODE & RET bits modifications */
if ((data ^ scd.regs[0x03 >> 1].byte.l) & 0x05) if ((data ^ scd.regs[0x03 >> 1].byte.l) & 0x05)
{ {
int i; int i;
s68k_poll_sync(0x02);
/* MODE bit */ /* MODE bit */
if (data & 0x04) if (data & 0x04)
@ -485,7 +527,7 @@ static void scd_write_byte(unsigned int address, unsigned int data)
if (!(scd.regs[0x03 >> 1].byte.l & 0x04)) if (!(scd.regs[0x03 >> 1].byte.l & 0x04))
{ {
/* re-arrange Word-RAM banks */ /* re-arrange Word-RAM banks */
word_ram_switch(data); word_ram_switch(0x04);
} }
/* RET bit in 1M Mode */ /* RET bit in 1M Mode */
@ -501,7 +543,6 @@ static void scd_write_byte(unsigned int address, unsigned int data)
for (i=scd.cartridge.boot+0x22; i<scd.cartridge.boot+0x24; i++) for (i=scd.cartridge.boot+0x22; i<scd.cartridge.boot+0x24; i++)
{ {
/* VRAM cell image mapped at $220000-$23FFFF */ /* VRAM cell image mapped at $220000-$23FFFF */
m68k.memory_map[i].base = NULL;
m68k.memory_map[i].read8 = cell_ram_1_read8; m68k.memory_map[i].read8 = cell_ram_1_read8;
m68k.memory_map[i].read16 = cell_ram_1_read16; m68k.memory_map[i].read16 = cell_ram_1_read16;
m68k.memory_map[i].write8 = cell_ram_1_write8; m68k.memory_map[i].write8 = cell_ram_1_write8;
@ -545,7 +586,6 @@ static void scd_write_byte(unsigned int address, unsigned int data)
for (i=scd.cartridge.boot+0x22; i<scd.cartridge.boot+0x24; i++) for (i=scd.cartridge.boot+0x22; i<scd.cartridge.boot+0x24; i++)
{ {
/* VRAM cell image mapped at $220000-$23FFFF */ /* VRAM cell image mapped at $220000-$23FFFF */
m68k.memory_map[i].base = NULL;
m68k.memory_map[i].read8 = cell_ram_0_read8; m68k.memory_map[i].read8 = cell_ram_0_read8;
m68k.memory_map[i].read16 = cell_ram_0_read16; m68k.memory_map[i].read16 = cell_ram_0_read16;
m68k.memory_map[i].write8 = cell_ram_0_write8; m68k.memory_map[i].write8 = cell_ram_0_write8;
@ -585,38 +625,7 @@ static void scd_write_byte(unsigned int address, unsigned int data)
if (scd.regs[0x02 >> 1].byte.l & 0x04) if (scd.regs[0x02 >> 1].byte.l & 0x04)
{ {
/* re-arrange Word-RAM banks */ /* re-arrange Word-RAM banks */
word_ram_switch(data); word_ram_switch(0x00);
/* allow Word-RAM access from both CPU in 2M mode (fixes sync issues in Mortal Kombat) */
for (i=scd.cartridge.boot+0x20; i<scd.cartridge.boot+0x24; i++)
{
/* MAIN-CPU: $200000-$23FFFF is mapped to 256K Word-RAM */
m68k.memory_map[i].base = scd.word_ram_2M + ((i & 0x03) << 16);
m68k.memory_map[i].read8 = NULL;
m68k.memory_map[i].read16 = NULL;
m68k.memory_map[i].write8 = NULL;
m68k.memory_map[i].write16 = NULL;
zbank_memory_map[i].read = NULL;
zbank_memory_map[i].write = NULL;
}
for (i=0x08; i<0x0c; i++)
{
/* SUB-CPU: $080000-$0BFFFF is mapped to 256K Word-RAM */
s68k.memory_map[i].read8 = NULL;
s68k.memory_map[i].read16 = NULL;
s68k.memory_map[i].write8 = NULL;
s68k.memory_map[i].write16 = NULL;
}
for (i=0x0c; i<0x0e; i++)
{
/* SUB-CPU: $0C0000-$0DFFFF is unmapped */
s68k.memory_map[i].read8 = s68k_read_bus_8;
s68k.memory_map[i].read16 = s68k_read_bus_16;
s68k.memory_map[i].write8 = s68k_unused_8_w;
s68k.memory_map[i].write16 = s68k_unused_16_w;
}
/* RET bit set during 1M mode ? */ /* RET bit set during 1M mode ? */
data |= ~scd.dmna & 0x01; data |= ~scd.dmna & 0x01;
@ -777,12 +786,12 @@ static void scd_write_word(unsigned int address, unsigned int data)
case 0x02: /* Memory Mode */ case 0x02: /* Memory Mode */
{ {
s68k_poll_sync(0x02);
/* detect MODE & RET bits modifications */ /* detect MODE & RET bits modifications */
if ((data ^ scd.regs[0x03>>1].byte.l) & 0x05) if ((data ^ scd.regs[0x03>>1].byte.l) & 0x05)
{ {
int i; int i;
s68k_poll_sync(0x02);
/* MODE bit */ /* MODE bit */
if (data & 0x04) if (data & 0x04)
@ -791,7 +800,7 @@ static void scd_write_word(unsigned int address, unsigned int data)
if (!(scd.regs[0x03 >> 1].byte.l & 0x04)) if (!(scd.regs[0x03 >> 1].byte.l & 0x04))
{ {
/* re-arrange Word-RAM banks */ /* re-arrange Word-RAM banks */
word_ram_switch(data); word_ram_switch(0x04);
} }
/* RET bit in 1M Mode */ /* RET bit in 1M Mode */
@ -807,7 +816,6 @@ static void scd_write_word(unsigned int address, unsigned int data)
for (i=scd.cartridge.boot+0x22; i<scd.cartridge.boot+0x24; i++) for (i=scd.cartridge.boot+0x22; i<scd.cartridge.boot+0x24; i++)
{ {
/* VRAM cell image mapped at $220000-$23FFFF */ /* VRAM cell image mapped at $220000-$23FFFF */
m68k.memory_map[i].base = NULL;
m68k.memory_map[i].read8 = cell_ram_1_read8; m68k.memory_map[i].read8 = cell_ram_1_read8;
m68k.memory_map[i].read16 = cell_ram_1_read16; m68k.memory_map[i].read16 = cell_ram_1_read16;
m68k.memory_map[i].write8 = cell_ram_1_write8; m68k.memory_map[i].write8 = cell_ram_1_write8;
@ -851,7 +859,6 @@ static void scd_write_word(unsigned int address, unsigned int data)
for (i=scd.cartridge.boot+0x22; i<scd.cartridge.boot+0x24; i++) for (i=scd.cartridge.boot+0x22; i<scd.cartridge.boot+0x24; i++)
{ {
/* VRAM cell image mapped at $220000-$23FFFF */ /* VRAM cell image mapped at $220000-$23FFFF */
m68k.memory_map[i].base = NULL;
m68k.memory_map[i].read8 = cell_ram_0_read8; m68k.memory_map[i].read8 = cell_ram_0_read8;
m68k.memory_map[i].read16 = cell_ram_0_read16; m68k.memory_map[i].read16 = cell_ram_0_read16;
m68k.memory_map[i].write8 = cell_ram_0_write8; m68k.memory_map[i].write8 = cell_ram_0_write8;
@ -891,38 +898,7 @@ static void scd_write_word(unsigned int address, unsigned int data)
if (scd.regs[0x03>>1].byte.l & 0x04) if (scd.regs[0x03>>1].byte.l & 0x04)
{ {
/* re-arrange Word-RAM banks */ /* re-arrange Word-RAM banks */
word_ram_switch(data); word_ram_switch(0x00);
/* allow Word-RAM access from both CPU in 2M mode (fixes sync issues in Mortal Kombat) */
for (i=scd.cartridge.boot+0x20; i<scd.cartridge.boot+0x24; i++)
{
/* MAIN-CPU: $200000-$23FFFF is mapped to 256K Word-RAM */
m68k.memory_map[i].base = scd.word_ram_2M + ((i & 0x03) << 16);
m68k.memory_map[i].read8 = NULL;
m68k.memory_map[i].read16 = NULL;
m68k.memory_map[i].write8 = NULL;
m68k.memory_map[i].write16 = NULL;
zbank_memory_map[i].read = NULL;
zbank_memory_map[i].write = NULL;
}
for (i=0x08; i<0x0c; i++)
{
/* SUB-CPU: $080000-$0BFFFF is mapped to 256K Word-RAM */
s68k.memory_map[i].read8 = NULL;
s68k.memory_map[i].read16 = NULL;
s68k.memory_map[i].write8 = NULL;
s68k.memory_map[i].write16 = NULL;
}
for (i=0x0c; i<0x0e; i++)
{
/* SUB-CPU: $0C0000-$0DFFFF is unmapped */
s68k.memory_map[i].read8 = s68k_read_bus_8;
s68k.memory_map[i].read16 = s68k_read_bus_16;
s68k.memory_map[i].write8 = s68k_unused_8_w;
s68k.memory_map[i].write16 = s68k_unused_16_w;
}
/* RET bit set during 1M mode ? */ /* RET bit set during 1M mode ? */
data |= ~scd.dmna & 0x01; data |= ~scd.dmna & 0x01;
@ -1104,7 +1080,7 @@ void scd_init(void)
/* $240000-$3FFFFF (resp. $400000-$7FFFFF): unused area (Word-RAM mirrored ?) */ /* $240000-$3FFFFF (resp. $400000-$7FFFFF): unused area (Word-RAM mirrored ?) */
for (i=base+0x24; i<base+0x40; i++) for (i=base+0x24; i<base+0x40; i++)
{ {
m68k.memory_map[i].base = NULL; m68k.memory_map[i].base = scd.word_ram_2M + ((i & 3) << 16);
m68k.memory_map[i].read8 = m68k_read_bus_8; m68k.memory_map[i].read8 = m68k_read_bus_8;
m68k.memory_map[i].read16 = m68k_read_bus_16; m68k.memory_map[i].read16 = m68k_read_bus_16;
m68k.memory_map[i].write8 = m68k_unused_8_w; m68k.memory_map[i].write8 = m68k_unused_8_w;
@ -1143,10 +1119,10 @@ void scd_init(void)
s68k.memory_map[i].write16 = NULL; s68k.memory_map[i].write16 = NULL;
} }
/* $0C0000-$FD0000: Unused area */ /* $0C0000-$FD0000: Unused area (Word-RAM mirrored ?) */
for (i=0x0c; i<0xfd; i++) for (i=0x0c; i<0xfd; i++)
{ {
s68k.memory_map[i].base = NULL; s68k.memory_map[i].base = scd.word_ram_2M + ((i & 3) << 16);
s68k.memory_map[i].read8 = s68k_read_bus_8; s68k.memory_map[i].read8 = s68k_read_bus_8;
s68k.memory_map[i].read16 = s68k_read_bus_16; s68k.memory_map[i].read16 = s68k_read_bus_16;
s68k.memory_map[i].write8 = s68k_unused_8_w; s68k.memory_map[i].write8 = s68k_unused_8_w;
@ -1205,6 +1181,9 @@ void scd_reset(int hard)
/* Power ON initial values (MAIN-CPU side) */ /* Power ON initial values (MAIN-CPU side) */
scd.regs[0x00>>1].w = 0x0002; scd.regs[0x00>>1].w = 0x0002;
scd.regs[0x02>>1].w = 0x0001; scd.regs[0x02>>1].w = 0x0001;
/* 2M mode */
word_ram_switch(0);
} }
else else
{ {
@ -1697,9 +1676,6 @@ int scd_context_load(uint8 *state)
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_USP,tmp32); load_param(&tmp32, 4); s68k_set_reg(M68K_REG_USP,tmp32);
load_param(&tmp32, 4); s68k_set_reg(M68K_REG_ISP,tmp32); load_param(&tmp32, 4); s68k_set_reg(M68K_REG_ISP,tmp32);
/* update IRQ level */
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
return bufferptr; return bufferptr;
} }

View File

@ -258,8 +258,21 @@ void gen_reset(int hard_reset)
/* 8-bit / 16-bit modes */ /* 8-bit / 16-bit modes */
if ((system_hw & SYSTEM_PBC) == SYSTEM_MD) if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
{ {
/* reset cartridge hardware & mapping */ if (system_hw == SYSTEM_MCD)
md_cart_reset(hard_reset); {
/* reset CD hardware */
scd_reset(1);
/* reset & halt SUB-CPU */
s68k.cycles = 0;
s68k_pulse_reset();
s68k_pulse_halt();
}
else
{
/* reset MD cartridge hardware */
md_cart_reset(hard_reset);
}
/* Z80 bus is released & Z80 is reseted */ /* Z80 bus is released & Z80 is reseted */
m68k.memory_map[0xa0].read8 = m68k_read_bus_8; m68k.memory_map[0xa0].read8 = m68k_read_bus_8;
@ -301,17 +314,6 @@ void gen_reset(int hard_reset)
} }
} }
if (system_hw == SYSTEM_MCD)
{
/* reset CD hardware */
scd_reset(1);
/* reset & halt SUB-CPU */
s68k.cycles = 0;
s68k_pulse_reset();
s68k_pulse_halt();
}
/* reset MAIN-CPU */ /* reset MAIN-CPU */
m68k_pulse_reset(); m68k_pulse_reset();
} }
@ -348,7 +350,7 @@ void gen_tmss_w(unsigned int offset, unsigned int data)
WRITE_WORD(tmss, offset, data); WRITE_WORD(tmss, offset, data);
/* VDP requires "SEGA" value to be written in TMSS register */ /* VDP requires "SEGA" value to be written in TMSS register */
if (strncmp((char *)tmss, "SEGA", 4) == 0) if (memcmp((char *)tmss, "SEGA", 4) == 0)
{ {
for (i=0xc0; i<0xe0; i+=8) for (i=0xc0; i<0xe0; i+=8)
{ {
@ -376,21 +378,29 @@ void gen_tmss_w(unsigned int offset, unsigned int data)
void gen_bankswitch_w(unsigned int data) void gen_bankswitch_w(unsigned int data)
{ {
if (data & 1) if (system_hw == SYSTEM_MD)
{ {
/* enable cartridge ROM */ if (data & 1)
m68k.memory_map[0].base = cart.base; {
} /* enable cartridge ROM */
else m68k.memory_map[0].base = cart.base;
{ }
/* enable internal BOOT ROM */ else
m68k.memory_map[0].base = boot_rom; {
/* enable internal BOOT ROM */
m68k.memory_map[0].base = boot_rom;
}
} }
} }
unsigned int gen_bankswitch_r(void) unsigned int gen_bankswitch_r(void)
{ {
return (m68k.memory_map[0].base == cart.base); if (system_hw == SYSTEM_MD)
{
return (m68k.memory_map[0].base == cart.base);
}
return 0xff;
} }

View File

@ -61,7 +61,7 @@ static int config_load(void)
char version[16]; char version[16];
fseek(fp, 0, SEEK_SET); fseek(fp, 0, SEEK_SET);
fread(version, 16, 1, fp); fread(version, 16, 1, fp);
if (strncmp(version,CONFIG_VERSION,16)) if (memcmp(version,CONFIG_VERSION,16))
{ {
fclose(fp); fclose(fp);
return 0; return 0;

View File

@ -108,12 +108,17 @@ void slot_autoload(int slot, int device)
/* update CRC */ /* update CRC */
brm_crc[0] = crc32(0, scd.bram, 0x2000); brm_crc[0] = crc32(0, scd.bram, 0x2000);
} }
else
{
/* force internal backup RAM format (does not use previous region backup RAM) */
scd.bram[0x1fff] = 0;
}
/* check if internal backup RAM is correctly formatted */ /* check if internal backup RAM is correctly formatted */
if (memcmp(scd.bram + 0x2000 - 0x20, brm_format + 0x20, 0x20)) if (memcmp(scd.bram + 0x2000 - 0x20, brm_format + 0x20, 0x20))
{ {
/* clear internal backup RAM */ /* clear internal backup RAM */
memset(scd.bram, 0x00, 0x200); memset(scd.bram, 0x00, 0x2000 - 0x40);
/* internal Backup RAM size fields */ /* internal Backup RAM size fields */
brm_format[0x10] = brm_format[0x12] = brm_format[0x14] = brm_format[0x16] = 0x00; brm_format[0x10] = brm_format[0x12] = brm_format[0x14] = brm_format[0x16] = 0x00;
@ -121,6 +126,9 @@ void slot_autoload(int slot, int device)
/* format internal backup RAM */ /* format internal backup RAM */
memcpy(scd.bram + 0x2000 - 0x40, brm_format, 0x40); memcpy(scd.bram + 0x2000 - 0x40, brm_format, 0x40);
/* clear CRC to force file saving (in case previous region backup RAM was also formatted) */
brm_crc[0] = 0;
} }
/* automatically load cartridge backup RAM (if enabled) */ /* automatically load cartridge backup RAM (if enabled) */
@ -129,7 +137,24 @@ void slot_autoload(int slot, int device)
fp = fopen(CART_BRAM, "rb"); fp = fopen(CART_BRAM, "rb");
if (fp != NULL) if (fp != NULL)
{ {
fread(scd.cartridge.area, scd.cartridge.mask + 1, 1, fp); int filesize = scd.cartridge.mask + 1;
int done = 0;
/* Read into buffer (2k blocks) */
while (filesize > CHUNKSIZE)
{
fread(scd.cartridge.area + done, CHUNKSIZE, 1, fp);
done += CHUNKSIZE;
filesize -= CHUNKSIZE;
}
/* Read remaining bytes */
if (filesize)
{
fread(scd.cartridge.area + done, filesize, 1, fp);
}
/* close file */
fclose(fp); fclose(fp);
/* update CRC */ /* update CRC */
@ -194,7 +219,24 @@ void slot_autosave(int slot, int device)
FILE *fp = fopen(CART_BRAM, "wb"); FILE *fp = fopen(CART_BRAM, "wb");
if (fp != NULL) if (fp != NULL)
{ {
fwrite(scd.cartridge.area, scd.cartridge.mask + 1, 1, fp); int filesize = scd.cartridge.mask + 1;
int done = 0;
/* Write to file (2k blocks) */
while (filesize > CHUNKSIZE)
{
fwrite(scd.cartridge.area + done, CHUNKSIZE, 1, fp);
done += CHUNKSIZE;
filesize -= CHUNKSIZE;
}
/* Write remaining bytes */
if (filesize)
{
fwrite(scd.cartridge.area + done, filesize, 1, fp);
}
/* Close file */
fclose(fp); fclose(fp);
/* update CRC */ /* update CRC */
@ -622,6 +664,9 @@ int slot_save(int slot, int device)
fclose(fp); fclose(fp);
free(buffer); free(buffer);
/* Close message box */
GUI_MsgBoxClose();
/* Save state screenshot */ /* Save state screenshot */
if (slot > 0) if (slot > 0)
{ {
@ -768,8 +813,10 @@ int slot_save(int slot, int device)
CARD_Unmount(device); CARD_Unmount(device);
free(out); free(out);
free(buffer); free(buffer);
}
GUI_MsgBoxClose(); /* Close message box */
GUI_MsgBoxClose();
}
return 1; return 1;
} }

View File

@ -83,37 +83,7 @@ static inline u16 FLIP16 (u16 b)
return c; return c;
} }
void get_zipfilename(char *filename) int load_archive(char *filename, unsigned char *buffer, int maxsize, char *extension)
{
char in[CHUNKSIZE];
/* Open file */
FILE *fd = fopen(filename, "rb");
if (!fd) return;
/* Read first 2 bytes */
fread(in, 2, 1, fd);
/* Detect Zip file */
if (memcmp(in, "PK", 2) == 0)
{
/* Read remaining header data */
fread(in + 2, sizeof(PKZIPHEADER) - 2, 1, fd);
/* Zip header pointer */
PKZIPHEADER *pkzip = (PKZIPHEADER *) in;
/* Return compressed file name */
int len = FLIP16(pkzip->filenameLength);
if (len >= MAXPATHLEN) len = MAXPATHLEN - 1;
fread(filename, len, 1, fd);
filename[len] = 0;
}
fclose(fd);
}
int load_archive(char *filename, unsigned char *buffer, int maxsize)
{ {
int size = 0; int size = 0;
char in[CHUNKSIZE]; char in[CHUNKSIZE];
@ -132,7 +102,7 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize)
/* Mega CD BIOS are required files */ /* Mega CD BIOS are required files */
if (!strcmp(filename,CD_BIOS_US) || !strcmp(filename,CD_BIOS_EU) || !strcmp(filename,CD_BIOS_JP)) if (!strcmp(filename,CD_BIOS_US) || !strcmp(filename,CD_BIOS_EU) || !strcmp(filename,CD_BIOS_JP))
{ {
sprintf(msg,"Unable to open CD BIOS"); sprintf(msg,"Unable to open %s", filename + 14);
} }
if (!fd) if (!fd)
@ -187,19 +157,23 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize)
return 0; return 0;
} }
/* Compressed filename offset */
int offset = sizeof (PKZIPHEADER) + FLIP16(pkzip->filenameLength);
if (extension)
{
memcpy(extension, &in[offset - 3], 3);
extension[3] = 0;
}
/* Initial Zip buffer offset */ /* Initial Zip buffer offset */
int offset = sizeof (PKZIPHEADER) + FLIP16(pkzip->filenameLength) + FLIP16(pkzip->extraDataLength); offset += FLIP16(pkzip->extraDataLength);
zs.next_in = (Bytef *)&in[offset]; zs.next_in = (Bytef *)&in[offset];
/* Initial Zip remaining chunk size */ /* Initial Zip remaining chunk size */
zs.avail_in = CHUNKSIZE - offset; zs.avail_in = CHUNKSIZE - offset;
/* Overwrite input filename with compressed filename */
offset = FLIP16(pkzip->filenameLength);
if (offset >= MAXPATHLEN) offset = MAXPATHLEN - 1;
strncpy(filename, &in[sizeof(PKZIPHEADER)], offset);
filename[offset] = 0;
/* Start unzipping file */ /* Start unzipping file */
do do
{ {
@ -255,6 +229,13 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize)
sprintf((char *)msg,"Loading %d bytes ...", size); sprintf((char *)msg,"Loading %d bytes ...", size);
GUI_MsgBoxOpen("Information", (char *)msg, 1); GUI_MsgBoxOpen("Information", (char *)msg, 1);
/* filename extension */
if (extension)
{
memcpy(extension, &filename[strlen(filename) - 3], 3);
extension[3] = 0;
}
/* Read into buffer */ /* Read into buffer */
int left = size; int left = size;
while (left > CHUNKSIZE) while (left > CHUNKSIZE)

View File

@ -42,6 +42,6 @@
#define _FILEIO_H_ #define _FILEIO_H_
/* Function prototypes */ /* Function prototypes */
int load_archive(char *filename, unsigned char *buffer, int maxsize); int load_archive(char *filename, unsigned char *buffer, int maxsize, char *extension);
#endif /* _FILEIO_H_ */ #endif /* _FILEIO_H_ */

View File

@ -52,8 +52,8 @@
extern const u8 Key_Minus_wii_png[]; extern const u8 Key_Minus_wii_png[];
extern const u8 Key_Plus_wii_png[]; extern const u8 Key_Plus_wii_png[];
#else #else
extern const u8 Key_L_gcn_png[];
extern const u8 Key_R_gcn_png[]; extern const u8 Key_R_gcn_png[];
extern const u8 Key_L_gcn_png[];
#endif #endif
extern const u8 Key_DPAD_png[]; extern const u8 Key_DPAD_png[];
@ -784,19 +784,19 @@ static void cheatmenu_cb(void)
gui_image key_enable; gui_image key_enable;
gui_image key_delete; gui_image key_delete;
#ifdef HW_RVL #ifdef HW_RVL
key_delete.texture = gxTextureOpenPNG(Key_Minus_wii_png,0);
key_enable.texture = gxTextureOpenPNG(Key_Plus_wii_png,0); key_enable.texture = gxTextureOpenPNG(Key_Plus_wii_png,0);
gxDrawTexture(key_delete.texture,152,424,24,24,255); key_delete.texture = gxTextureOpenPNG(Key_Minus_wii_png,0);
gxDrawTexture(key_enable.texture,372,424,24,24,255); gxDrawTexture(key_enable.texture,152,424,24,24,255);
FONT_write("Delete\nCheat",16,184,436,640,(GXColor)WHITE); gxDrawTexture(key_delete.texture,372,424,24,24,255);
FONT_write(cheatlist[offset + selection].enable ? "Disable\nCheat":"Enable\nCheat",16,404,436,640,(GXColor)WHITE); FONT_write(cheatlist[offset + selection].enable ? "Disable\nCheat":"Enable\nCheat",16,184,436,640,(GXColor)WHITE);
FONT_write("Delete\nCheat",16,404,436,640,(GXColor)WHITE);
#else #else
key_delete.texture = gxTextureOpenPNG(Key_L_gcn_png,0); key_enable.texture = gxTextureOpenPNG(Key_L_gcn_png,0);
key_enable.texture = gxTextureOpenPNG(Key_R_gcn_png,0); key_delete.texture = gxTextureOpenPNG(Key_R_gcn_png,0);
gxDrawTexture(key_delete.texture,136,426,44,20,255); gxDrawTexture(key_enable.texture,136,426,44,20,255);
gxDrawTexture(key_enable.texture,368,426,44,20,255); gxDrawTexture(key_delete.texture,368,426,44,20,255);
FONT_write("Delete\nCheat",16,188,436,640,(GXColor)WHITE); FONT_write(cheatlist[offset + selection].enable ? "Disable\nCheat":"Enable\nCheat",16,188,436,640,(GXColor)WHITE);
FONT_write(cheatlist[offset + selection].enable ? "Disable\nCheat":"Enable\nCheat",16,420,436,640,(GXColor)WHITE); FONT_write("Delete\nCheat",16,420,436,640,(GXColor)WHITE);
#endif #endif
gxTextureClose(&key_enable.texture); gxTextureClose(&key_enable.texture);
gxTextureClose(&key_delete.texture); gxTextureClose(&key_delete.texture);
@ -1191,7 +1191,7 @@ void CheatMenu(void)
if ((offset + selection) < maxcheats) if ((offset + selection) < maxcheats)
{ {
/* Special inputs */ /* Special inputs */
if (m_input.keys & PAD_TRIGGER_L) if (m_input.keys & PAD_TRIGGER_R)
{ {
/* sort cheat list */ /* sort cheat list */
for (i = offset + selection + 1; i < maxcheats; i++) for (i = offset + selection + 1; i < maxcheats; i++)
@ -1223,7 +1223,7 @@ void CheatMenu(void)
/* reset scrolling */ /* reset scrolling */
string_offset = 0; string_offset = 0;
} }
else if (m_input.keys & PAD_TRIGGER_R) else if (m_input.keys & PAD_TRIGGER_L)
{ {
/* cheat ON/OFF */ /* cheat ON/OFF */
cheatlist[offset + selection].enable ^= 1; cheatlist[offset + selection].enable ^= 1;

View File

@ -1145,7 +1145,7 @@ static void systemmenu ()
else else
sprintf (items[7].text, "Lock-On: OFF"); sprintf (items[7].text, "Lock-On: OFF");
sprintf (items[8].text, "Cartridge Swap: %s", config.hot_swap ? "ON":"OFF"); sprintf (items[8].text, "Cartridge Swap: %s", (config.hot_swap & 1) ? "ON":"OFF");
if (svp) if (svp)
{ {
@ -1233,6 +1233,9 @@ static void systemmenu ()
} }
} }
/* reinitialize audio streams */
audio_init(snd.sample_rate, snd.frame_rate);
/* force hard reset */ /* force hard reset */
system_init(); system_init();
system_reset(); system_reset();
@ -1389,7 +1392,7 @@ static void systemmenu ()
case 8: /*** Cartridge Hot Swap ***/ case 8: /*** Cartridge Hot Swap ***/
{ {
config.hot_swap ^= 1; config.hot_swap ^= 1;
sprintf (items[8].text, "Cartridge Swap: %s", config.hot_swap ? "ON":"OFF"); sprintf (items[8].text, "Cartridge Swap: %s", (config.hot_swap & 1) ? "ON":"OFF");
break; break;
} }
@ -1421,6 +1424,12 @@ static void systemmenu ()
{ {
system_init(); system_init();
system_reset(); system_reset();
/* restore SRAM */
if (config.s_auto & 1)
{
slot_autoload(0,config.s_device);
}
} }
else else
{ {

View File

@ -182,6 +182,7 @@ void gx_audio_Start(void)
ASND_End(); ASND_End();
AUDIO_StopDMA(); AUDIO_StopDMA();
AUDIO_RegisterDMACallback(NULL); AUDIO_RegisterDMACallback(NULL);
DSP_Halt();
/* when VSYNC is forced OFF or AUTO with TV mode not matching emulated video mode, emulation is synchronized with Audio Hardware */ /* when VSYNC is forced OFF or AUTO with TV mode not matching emulated video mode, emulation is synchronized with Audio Hardware */
if (!config.vsync || (config.tv_mode == !vdp_pal)) if (!config.vsync || (config.tv_mode == !vdp_pal))
@ -206,6 +207,7 @@ void gx_audio_Start(void)
void gx_audio_Stop(void) void gx_audio_Stop(void)
{ {
/* restart menu audio processing */ /* restart menu audio processing */
DSP_Unhalt();
ASND_Init(); ASND_Init();
ASND_Pause(0); ASND_Pause(0);

View File

@ -1218,8 +1218,8 @@ void gx_input_SetDefault(void)
{ {
/* Wiimote */ /* Wiimote */
config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_BUTTONA] = WPAD_BUTTON_A; config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_BUTTONA] = WPAD_BUTTON_A;
config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_BUTTONB] = WPAD_BUTTON_2; config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_BUTTONB] = WPAD_BUTTON_1;
config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_BUTTONC] = WPAD_BUTTON_1; config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_BUTTONC] = WPAD_BUTTON_2;
config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_START] = WPAD_BUTTON_PLUS; config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_START] = WPAD_BUTTON_PLUS;
config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_BUTTONX] = 0; config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_BUTTONX] = 0;
config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_BUTTONY] = 0; config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_BUTTONY] = 0;
@ -1228,8 +1228,8 @@ void gx_input_SetDefault(void)
/* Wiimote + Nunchuk */ /* Wiimote + Nunchuk */
config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_BUTTONA] = WPAD_NUNCHUK_BUTTON_Z; config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_BUTTONA] = WPAD_NUNCHUK_BUTTON_Z;
config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_BUTTONB] = WPAD_BUTTON_A; config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_BUTTONB] = WPAD_BUTTON_B;
config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_BUTTONC] = WPAD_BUTTON_B; config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_BUTTONC] = WPAD_BUTTON_A;
config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_START] = WPAD_BUTTON_PLUS; config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_START] = WPAD_BUTTON_PLUS;
config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_BUTTONX] = WPAD_NUNCHUK_BUTTON_C; config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_BUTTONX] = WPAD_NUNCHUK_BUTTON_C;
config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_BUTTONY] = WPAD_BUTTON_1; config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_BUTTONY] = WPAD_BUTTON_1;
@ -1242,8 +1242,8 @@ void gx_input_SetDefault(void)
config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_BUTTONC] = WPAD_CLASSIC_BUTTON_A; config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_BUTTONC] = WPAD_CLASSIC_BUTTON_A;
config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_START] = WPAD_CLASSIC_BUTTON_PLUS; config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_START] = WPAD_CLASSIC_BUTTON_PLUS;
config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_BUTTONX] = WPAD_CLASSIC_BUTTON_ZL; config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_BUTTONX] = WPAD_CLASSIC_BUTTON_ZL;
config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_BUTTONY] = WPAD_CLASSIC_BUTTON_X; config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_BUTTONY] = WPAD_CLASSIC_BUTTON_ZR;
config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_BUTTONZ] = WPAD_CLASSIC_BUTTON_ZR; config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_BUTTONZ] = WPAD_CLASSIC_BUTTON_X;
config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_MODE] = WPAD_CLASSIC_BUTTON_MINUS; config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_MODE] = WPAD_CLASSIC_BUTTON_MINUS;
} }
#endif #endif

View File

@ -118,7 +118,7 @@ static void init_machine(void)
fclose(fp); fclose(fp);
/* check BOOT ROM */ /* check BOOT ROM */
if (!strncmp((char *)(boot_rom + 0x120),"GENESIS OS", 10)) if (!memcmp((char *)(boot_rom + 0x120),"GENESIS OS", 10))
{ {
/* mark Genesis BIOS as loaded */ /* mark Genesis BIOS as loaded */
system_bios = SYSTEM_MD; system_bios = SYSTEM_MD;

View File

@ -54,6 +54,8 @@
#define CD_BRAM_JP "/genplus/saves/cd/scd_J.brm" #define CD_BRAM_JP "/genplus/saves/cd/scd_J.brm"
#define CART_BRAM "/genplus/saves/cd/cart.brm" #define CART_BRAM "/genplus/saves/cd/cart.brm"
#define ALIGN_SND 0xfffffff8 /* 32 bytes aligned sound buffers (8 samples alignment) */
/*************************************************/ /*************************************************/
#ifdef HW_RVL #ifdef HW_RVL

View File

@ -403,13 +403,13 @@ int load_bios(void)
switch (region_code) switch (region_code)
{ {
case REGION_USA: case REGION_USA:
size = load_archive(CD_BIOS_US, scd.bootrom, sizeof(scd.bootrom)); size = load_archive(CD_BIOS_US, scd.bootrom, sizeof(scd.bootrom), 0);
break; break;
case REGION_EUROPE: case REGION_EUROPE:
size = load_archive(CD_BIOS_EU, scd.bootrom, sizeof(scd.bootrom)); size = load_archive(CD_BIOS_EU, scd.bootrom, sizeof(scd.bootrom), 0);
break; break;
default: default:
size = load_archive(CD_BIOS_JP, scd.bootrom, sizeof(scd.bootrom)); size = load_archive(CD_BIOS_JP, scd.bootrom, sizeof(scd.bootrom), 0);
break; break;
} }
@ -431,12 +431,6 @@ int load_bios(void)
/* loaded BIOS region */ /* loaded BIOS region */
system_bios = (system_bios & 0xf0) | (region_code >> 4); system_bios = (system_bios & 0xf0) | (region_code >> 4);
}
else
{
/* CD BOOT ROM disabled (SYSTEM ERROR) */
memset(scd.bootrom, 0xff, sizeof(scd.bootrom));
} }
return size; return size;
@ -458,7 +452,7 @@ int load_bios(void)
if (cart.romsize <= 0x400000) if (cart.romsize <= 0x400000)
{ {
/* load Game Gear "BIOS" file */ /* load Game Gear "BIOS" file */
size = load_archive(GG_BIOS, cart.rom + 0x400000, 0x100000); size = load_archive(GG_BIOS, cart.rom + 0x400000, 0x100000, 0);
if (size > 0) if (size > 0)
{ {
@ -489,13 +483,13 @@ int load_bios(void)
switch (region_code) switch (region_code)
{ {
case REGION_USA: case REGION_USA:
size = load_archive(MS_BIOS_US, cart.rom + 0x400000, 0x100000); size = load_archive(MS_BIOS_US, cart.rom + 0x400000, 0x100000, 0);
break; break;
case REGION_EUROPE: case REGION_EUROPE:
size = load_archive(MS_BIOS_EU, cart.rom + 0x400000, 0x100000); size = load_archive(MS_BIOS_EU, cart.rom + 0x400000, 0x100000, 0);
break; break;
default: default:
size = load_archive(MS_BIOS_JP, cart.rom + 0x400000, 0x100000); size = load_archive(MS_BIOS_JP, cart.rom + 0x400000, 0x100000, 0);
break; break;
} }
@ -543,14 +537,19 @@ int load_rom(char *filename)
ggenie_shutdown(); ggenie_shutdown();
areplay_shutdown(); areplay_shutdown();
/* unload any existing disc */
if (romtype == SYSTEM_MCD) if (romtype == SYSTEM_MCD)
{ {
/* unload CD image */
cdd_unload(); cdd_unload();
} }
else
{
/* no CD image loaded */
cdd.loaded = 0;
}
/* .cue file support */ /* .cue file support */
if (!strncmp(".cue", &filename[strlen(filename) - 4], 4)) if (!memcmp(".cue", &filename[strlen(filename) - 4], 4))
{ {
/* open associated .bin file */ /* open associated .bin file */
strncpy(&filename[strlen(filename) - 4], ".bin", 4); strncpy(&filename[strlen(filename) - 4], ".bin", 4);
@ -565,7 +564,7 @@ int load_rom(char *filename)
} }
/* auto-detect CD image file */ /* auto-detect CD image file */
if (!strncmp("SEGADISCSYSTEM", buf + 0x10, 14)) if (!memcmp("SEGADISCSYSTEM", buf + 0x10, 14))
{ {
/* file header pointer (BIN format) */ /* file header pointer (BIN format) */
header = buf + 0x10; header = buf + 0x10;
@ -573,7 +572,7 @@ int load_rom(char *filename)
/* enable CD hardware */ /* enable CD hardware */
system_hw = SYSTEM_MCD; system_hw = SYSTEM_MCD;
} }
else if (!strncmp("SEGADISCSYSTEM", buf, 14)) else if (!memcmp("SEGADISCSYSTEM", buf, 14))
{ {
/* file header pointer (ISO format) */ /* file header pointer (ISO format) */
header = buf; header = buf;
@ -583,25 +582,30 @@ int load_rom(char *filename)
} }
else else
{ {
/* load file into ROM buffer (input filename is overwritten by uncompressed filename) */ /* load file into ROM buffer */
int size = load_archive(filename, cart.rom, sizeof(cart.rom)); char extension[4];
if (!size) return(0); int size = load_archive(filename, cart.rom, sizeof(cart.rom), extension);
/* mark CD BIOS as unloaded */ /* mark CD BIOS as unloaded */
system_bios &= ~0x10; system_bios &= ~0x10;
if (!size) return(0);
/* convert lower case to upper case */
*(uint32 *)(extension) &= 0xdfdfdfdf;
/* Auto-detect system hardware from ROM file extension */ /* Auto-detect system hardware from ROM file extension */
if (!strncmp(".sms", &filename[strlen(filename) - 4], 4)) if (!memcmp("SMS", &extension[0], 3))
{ {
/* Master System II hardware */ /* Master System II hardware */
system_hw = SYSTEM_SMS2; system_hw = SYSTEM_SMS2;
} }
else if (!strncmp(".gg", &filename[strlen(filename) - 3], 3)) else if (!memcmp("GG", &extension[1], 2))
{ {
/* Game Gear hardware (GG mode) */ /* Game Gear hardware (GG mode) */
system_hw = SYSTEM_GG; system_hw = SYSTEM_GG;
} }
else if (!strncmp(".sg", &filename[strlen(filename) - 3], 3)) else if (!memcmp("SG", &extension[1], 2))
{ {
/* SG-1000 hardware */ /* SG-1000 hardware */
system_hw = SYSTEM_SG; system_hw = SYSTEM_SG;
@ -612,7 +616,7 @@ int load_rom(char *filename)
system_hw = SYSTEM_MD; system_hw = SYSTEM_MD;
/* Decode .MDX format */ /* Decode .MDX format */
if (!strncmp(".mdx", &filename[strlen(filename) - 4], 4)) if (!memcmp("MDX", &extension[0], 3))
{ {
for (i = 4; i < size - 1; i++) for (i = 4; i < size - 1; i++)
{ {
@ -623,7 +627,7 @@ int load_rom(char *filename)
} }
/* auto-detect 512 byte extra header */ /* auto-detect 512 byte extra header */
if (strncmp((char *)(cart.rom + 0x100),"SEGA", 4) && ((size / 512) & 1)) if (memcmp((char *)(cart.rom + 0x100), "SEGA", 4) && ((size / 512) & 1))
{ {
/* remove header */ /* remove header */
size -= 512; size -= 512;
@ -713,8 +717,11 @@ int load_rom(char *filename)
/* boot from CD */ /* boot from CD */
scd.cartridge.boot = 0x00; scd.cartridge.boot = 0x00;
/* CD unloaded */ /* no CD image loaded */
cdd.loaded = 0; cdd.loaded = 0;
/* clear CD TOC */
cdd_unload();
} }
/* special ROM cartridges that use CD hardware */ /* special ROM cartridges that use CD hardware */
@ -729,9 +736,12 @@ int load_rom(char *filename)
/* load CD BOOT ROM */ /* load CD BOOT ROM */
if (load_bios()) if (load_bios())
{ {
/* CD unloaded */ /* no CD image loaded */
cdd.loaded = 0; cdd.loaded = 0;
/* clear CD TOC */
cdd_unload();
/* boot from cartridge */ /* boot from cartridge */
scd.cartridge.boot = 0x40; scd.cartridge.boot = 0x40;
} }
@ -739,6 +749,9 @@ int load_rom(char *filename)
{ {
/* assume Mega Drive hardware */ /* assume Mega Drive hardware */
system_hw = SYSTEM_MD; system_hw = SYSTEM_MD;
/* copy back to cartridge ROM area */
memcpy(cart.rom, scd.cartridge.area, sizeof(scd.cartridge.area));
} }
} }
@ -817,12 +830,12 @@ void get_region(char *romheader)
int country = 0; int country = 0;
/* from Gens */ /* from Gens */
if (!strncmp(rominfo.country, "eur", 3)) country |= 8; if (!memcmp(rominfo.country, "eur", 3)) country |= 8;
else if (!strncmp(rominfo.country, "EUR", 3)) country |= 8; else if (!memcmp(rominfo.country, "EUR", 3)) country |= 8;
else if (!strncmp(rominfo.country, "jap", 3)) country |= 1; else if (!memcmp(rominfo.country, "jap", 3)) country |= 1;
else if (!strncmp(rominfo.country, "JAP", 3)) country |= 1; else if (!memcmp(rominfo.country, "JAP", 3)) country |= 1;
else if (!strncmp(rominfo.country, "usa", 3)) country |= 4; else if (!memcmp(rominfo.country, "usa", 3)) country |= 4;
else if (!strncmp(rominfo.country, "USA", 3)) country |= 4; else if (!memcmp(rominfo.country, "USA", 3)) country |= 4;
else else
{ {
int i; int i;

View File

@ -273,7 +273,11 @@ void m68k_run(unsigned int cycles)
/* Save end cycles count for when CPU is stopped */ /* Save end cycles count for when CPU is stopped */
m68k.cycle_end = cycles; m68k.cycle_end = cycles;
#ifdef LOGVDP
error("[%d][%d] m68k run to %d cycles (%x)\n", v_counter, m68k.cycles, cycles, m68k.pc);
#endif
while (m68k.cycles < cycles) while (m68k.cycles < cycles)
{ {
/* Set tracing accodring to T1. */ /* Set tracing accodring to T1. */

View File

@ -211,13 +211,13 @@ void s68k_update_irq(unsigned int mask)
/* Set IRQ level */ /* Set IRQ level */
CPU_INT_LEVEL = mask << 8; CPU_INT_LEVEL = mask << 8;
/* Check interrupt mask to process IRQ */
m68ki_check_interrupts();
#ifdef LOG_SCD #ifdef LOG_SCD
error("[%d][%d] IRQ Level = %d(0x%02x) (%x)\n", v_counter, s68k.cycles, CPU_INT_LEVEL>>8,FLAG_INT_MASK,s68k.pc); error("[%d][%d] IRQ Level = %d(0x%02x) (%x)\n", v_counter, s68k.cycles, CPU_INT_LEVEL>>8,FLAG_INT_MASK,s68k.pc);
#endif #endif
/* Check interrupt mask to process IRQ */
m68ki_check_interrupts();
} }
void s68k_run(unsigned int cycles) void s68k_run(unsigned int cycles)
@ -234,7 +234,10 @@ void s68k_run(unsigned int cycles)
/* Save end cycles count for when CPU is stopped */ /* Save end cycles count for when CPU is stopped */
s68k.cycle_end = cycles; s68k.cycle_end = cycles;
#ifdef LOG_SCD
error("[%d][%d] s68k run to %d cycles (%x), irq mask = %x (%x)\n", v_counter, s68k.cycles, cycles, s68k.pc,FLAG_INT_MASK, CPU_INT_LEVEL);
#endif
while (s68k.cycles < cycles) while (s68k.cycles < cycles)
{ {
/* Set tracing accodring to T1. */ /* Set tracing accodring to T1. */

View File

@ -233,6 +233,9 @@ INLINE void m68k_poll_detect(reg)
if (m68k.pc == m68k.poll.pc) if (m68k.pc == m68k.poll.pc)
{ {
/* stop MAIN-CPU until register is modified by SUB-CPU */ /* stop MAIN-CPU until register is modified by SUB-CPU */
#ifdef LOG_SCD
error("m68k stopped from %d cycles\n", m68k.cycles);
#endif
m68k.cycles = m68k.cycle_end; m68k.cycles = m68k.cycle_end;
m68k.stopped = 1 << reg; m68k.stopped = 1 << reg;
} }
@ -269,6 +272,9 @@ INLINE void m68k_poll_sync(reg)
/* restart SUB-CPU */ /* restart SUB-CPU */
s68k.stopped = 0; s68k.stopped = 0;
#ifdef LOG_SCD
error("s68k started from %d cycles\n", cycles);
#endif
} }
/* clear CPU register(s) access flags */ /* clear CPU register(s) access flags */

View File

@ -46,7 +46,7 @@ int state_load(unsigned char *state)
char version[17]; char version[17];
load_param(version,16); load_param(version,16);
version[16] = 0; version[16] = 0;
if (strncmp(version,STATE_VERSION,11)) if (memcmp(version,STATE_VERSION,11))
{ {
return -1; return -1;
} }

View File

@ -178,9 +178,9 @@ int audio_update(int16 *buffer)
/* get number of available samples */ /* get number of available samples */
int size = sound_update(mcycles_vdp); int size = sound_update(mcycles_vdp);
#ifndef __LIBRETRO__ #ifdef ALIGN_SND
/* return an aligned number of samples */ /* return an aligned number of samples if necessary*/
size &= ~7; size &= ALIGN_SND;
#endif #endif
if (config.hq_fm) if (config.hq_fm)

View File

@ -96,6 +96,27 @@ void (*vdp_z80_data_w)(unsigned int data);
unsigned int (*vdp_68k_data_r)(void); unsigned int (*vdp_68k_data_r)(void);
unsigned int (*vdp_z80_data_r)(void); unsigned int (*vdp_z80_data_r)(void);
/* Function prototypes */
static void vdp_68k_data_w_m4(unsigned int data);
static void vdp_68k_data_w_m5(unsigned int data);
static unsigned int vdp_68k_data_r_m4(void);
static unsigned int vdp_68k_data_r_m5(void);
static void vdp_z80_data_w_m4(unsigned int data);
static void vdp_z80_data_w_m5(unsigned int data);
static unsigned int vdp_z80_data_r_m4(void);
static unsigned int vdp_z80_data_r_m5(void);
static void vdp_z80_data_w_ms(unsigned int data);
static void vdp_z80_data_w_gg(unsigned int data);
static void vdp_z80_data_w_sg(unsigned int data);
static void vdp_bus_w(unsigned int data);
static void vdp_fifo_update(unsigned int cycles);
static void vdp_reg_w(unsigned int r, unsigned int d, unsigned int cycles);
static void vdp_dma_68k_ext(unsigned int length);
static void vdp_dma_68k_ram(unsigned int length);
static void vdp_dma_68k_io(unsigned int length);
static void vdp_dma_copy(unsigned int length);
static void vdp_dma_fill(unsigned int length);
/* Tables that define the playfield layout */ /* Tables that define the playfield layout */
static const uint8 hscroll_mask_table[] = { 0x00, 0x07, 0xF8, 0xFF }; static const uint8 hscroll_mask_table[] = { 0x00, 0x07, 0xF8, 0xFF };
static const uint8 shift_table[] = { 6, 7, 0, 8 }; static const uint8 shift_table[] = { 6, 7, 0, 8 };
@ -121,14 +142,6 @@ static uint16 fifo[4]; /* FIFO buffer */
static void (*set_irq_line)(unsigned int level); static void (*set_irq_line)(unsigned int level);
static void (*set_irq_line_delay)(unsigned int level); static void (*set_irq_line_delay)(unsigned int level);
/* DMA Timings */
static const uint8 dma_timing[2][2] =
{
/* H32, H40 */
{16 , 18}, /* active display */
{167, 205} /* blank display */
};
/* Vertical counter overflow values (see hvc.h) */ /* Vertical counter overflow values (see hvc.h) */
static const uint16 vc_table[4][2] = static const uint16 vc_table[4][2] =
{ {
@ -139,27 +152,30 @@ static const uint16 vc_table[4][2] =
{0x106, 0x10A} /* Mode 5 (240 lines) */ {0x106, 0x10A} /* Mode 5 (240 lines) */
}; };
/*--------------------------------------------------------------------------*/ /* DMA Timings (number of access slots per line) */
/* Function prototypes */ static const uint8 dma_timing[2][2] =
/*--------------------------------------------------------------------------*/ {
/* H32, H40 */
{16 , 18}, /* active display */
{167, 205} /* blank display */
};
/* DMA processing functions (set by VDP register 23 high nibble) */
static void (*const dma_func[16])(unsigned int length) =
{
/* 0x0-0x3 : DMA from 68k bus $000000-$7FFFFF (external area) */
vdp_dma_68k_ext,vdp_dma_68k_ext,vdp_dma_68k_ext,vdp_dma_68k_ext,
/* 0x4-0x7 : DMA from 68k bus $800000-$FFFFFF (internal RAM & I/O) */
vdp_dma_68k_ram, vdp_dma_68k_io,vdp_dma_68k_ram,vdp_dma_68k_ram,
/* 0x8-0xB : DMA Fill */
vdp_dma_fill,vdp_dma_fill,vdp_dma_fill,vdp_dma_fill,
/* 0xC-0xF : DMA Copy */
vdp_dma_copy,vdp_dma_copy,vdp_dma_copy,vdp_dma_copy
};
static void vdp_68k_data_w_m4(unsigned int data);
static void vdp_68k_data_w_m5(unsigned int data);
static unsigned int vdp_68k_data_r_m4(void);
static unsigned int vdp_68k_data_r_m5(void);
static void vdp_z80_data_w_m4(unsigned int data);
static void vdp_z80_data_w_m5(unsigned int data);
static unsigned int vdp_z80_data_r_m4(void);
static unsigned int vdp_z80_data_r_m5(void);
static void vdp_z80_data_w_ms(unsigned int data);
static void vdp_z80_data_w_gg(unsigned int data);
static void vdp_z80_data_w_sg(unsigned int data);
static void vdp_bus_w(unsigned int data);
static void vdp_fifo_update(unsigned int cycles);
static void vdp_reg_w(unsigned int r, unsigned int d, unsigned int cycles);
static void vdp_dma_copy(unsigned int length);
static void vdp_dma_vbus(unsigned int length);
static void vdp_dma_fill(unsigned char data, unsigned int length);
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/* Init, reset, context functions */ /* Init, reset, context functions */
@ -608,30 +624,8 @@ void vdp_dma_update(unsigned int cycles)
/* Update DMA length */ /* Update DMA length */
dma_length -= dma_bytes; dma_length -= dma_bytes;
/* Select DMA operation */ /* Process DMA operation */
switch (dma_type) dma_func[reg[23] >> 4](dma_bytes);
{
case 2:
{
/* VRAM Fill */
vdp_dma_fill(dmafill, dma_bytes);
break;
}
case 3:
{
/* VRAM Copy */
vdp_dma_copy(dma_bytes);
break;
}
default:
{
/* 68K bus to VRAM, CRAM or VSRAM */
vdp_dma_vbus(dma_bytes);
break;
}
}
/* Check if DMA is finished */ /* Check if DMA is finished */
if (!dma_length) if (!dma_length)
@ -2868,78 +2862,112 @@ static void vdp_z80_data_w_sg(unsigned int data)
/* DMA operations */ /* DMA operations */
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/* 68K bus to VRAM, VSRAM or CRAM */ /* DMA from 68K bus: $000000-$7FFFFF (external area) */
static void vdp_dma_vbus(unsigned int length) static void vdp_dma_68k_ext(unsigned int length)
{ {
uint16 data; uint16 data;
/* 68k bus source address */ /* 68k bus source address */
uint32 source = (reg[23] << 17) | (dma_src << 1); uint32 source = (reg[23] << 17) | (dma_src << 1);
/* Z80 & I/O area ($A00000-$A1FFFF) specific */ do
if (reg[23] == 0x50)
{ {
do /* Read data word from 68k bus */
if (m68k.memory_map[source>>16].read16)
{ {
/* Z80 area */ data = m68k.memory_map[source>>16].read16(source);
if (source <= 0xA0FFFF)
{
/* Return $FFFF only when the Z80 isn't hogging the Z-bus.
(e.g. Z80 isn't reset and 68000 has the bus) */
data = ((zstate ^ 3) ? *(uint16 *)(work_ram + (source & 0xFFFF)) : 0xFFFF);
}
/* The I/O chip and work RAM try to drive the data bus which results
in both values being combined in random ways when read.
We return the I/O chip values which seem to have precedence, */
else if (source <= 0xA1001F)
{
data = io_68k_read((source >> 1) & 0x0F);
data = (data << 8 | data);
}
/* All remaining locations access work RAM */
else
{
data = *(uint16 *)(work_ram + (source & 0xFFFF));
}
/* Increment source address */
source += 2;
/* 128k DMA window */
source = (reg[23] << 17) | (source & 0x1FFFF);
/* Write data to VRAM, CRAM or VSRAM */
vdp_bus_w(data);
} }
while (--length); else
}
else
{
do
{ {
/* Read data word from 68k bus */ data = *(uint16 *)(m68k.memory_map[source>>16].base + (source & 0xFFFF));
if (m68k.memory_map[source>>16].base) }
{
data = *(uint16 *)(m68k.memory_map[source>>16].base + (source & 0xFFFF));
}
else
{
data = m68k.memory_map[source>>16].read16(source);
}
/* Increment source address */ /* Increment source address */
source += 2; source += 2;
/* 128k DMA window */ /* 128k DMA window */
source = (reg[23] << 17) | (source & 0x1FFFF); source = (reg[23] << 17) | (source & 0x1FFFF);
/* Write data word to VRAM, CRAM or VSRAM */ /* Write data word to VRAM, CRAM or VSRAM */
vdp_bus_w(data); vdp_bus_w(data);
}
while (--length);
} }
while (--length);
/* Update DMA source address */
dma_src = (source >> 1) & 0xffff;
}
/* DMA from 68K bus: $800000-$FFFFFF (internal area) except I/O area */
static void vdp_dma_68k_ram(unsigned int length)
{
uint16 data;
/* 68k bus source address */
uint32 source = (reg[23] << 17) | (dma_src << 1);
do
{
/* access Work-RAM by default */
data = *(uint16 *)(work_ram + (source & 0xFFFF));
/* Increment source address */
source += 2;
/* 128k DMA window */
source = (reg[23] << 17) | (source & 0x1FFFF);
/* Write data word to VRAM, CRAM or VSRAM */
vdp_bus_w(data);
}
while (--length);
/* Update DMA source address */
dma_src = (source >> 1) & 0xffff;
}
/* DMA from 68K bus: $A00000-$A1FFFF (I/O area) specific */
static void vdp_dma_68k_io(unsigned int length)
{
uint16 data;
/* 68k bus source address */
uint32 source = (reg[23] << 17) | (dma_src << 1);
do
{
/* Z80 area */
if (source <= 0xA0FFFF)
{
/* Return $FFFF only when the Z80 isn't hogging the Z-bus.
(e.g. Z80 isn't reset and 68000 has the bus) */
data = ((zstate ^ 3) ? *(uint16 *)(work_ram + (source & 0xFFFF)) : 0xFFFF);
}
/* The I/O chip and work RAM try to drive the data bus which results
in both values being combined in random ways when read.
We return the I/O chip values which seem to have precedence, */
else if (source <= 0xA1001F)
{
data = io_68k_read((source >> 1) & 0x0F);
data = (data << 8 | data);
}
/* All remaining locations access work RAM */
else
{
data = *(uint16 *)(work_ram + (source & 0xFFFF));
}
/* Increment source address */
source += 2;
/* 128k DMA window */
source = (reg[23] << 17) | (source & 0x1FFFF);
/* Write data to VRAM, CRAM or VSRAM */
vdp_bus_w(data);
}
while (--length);
/* Update DMA source address */ /* Update DMA source address */
dma_src = (source >> 1) & 0xffff; dma_src = (source >> 1) & 0xffff;
@ -2989,12 +3017,14 @@ static void vdp_dma_copy(unsigned int length)
} }
/* VRAM Fill (TODO: check if CRAM or VSRAM fill is possible) */ /* VRAM Fill (TODO: check if CRAM or VSRAM fill is possible) */
static void vdp_dma_fill(unsigned char data, unsigned int length) static void vdp_dma_fill(unsigned int length)
{ {
/* VRAM write operation only (Williams Greatest Hits after soft reset) */ /* VRAM write operation only (Williams Greatest Hits after soft reset) */
if ((code & 0x1F) == 0x01) if ((code & 0x1F) == 0x01)
{ {
int name; int name;
uint8 data = dmafill;
do do
{ {
/* Intercept writes to Sprite Attribute Table */ /* Intercept writes to Sprite Attribute Table */

View File

@ -45,9 +45,8 @@
#include <zlib.h> #include <zlib.h>
static int check_zip(char *filename); static int check_zip(char *filename);
static int gzsize(gzFile *gd);
int load_archive(char *filename, unsigned char *buffer, int maxsize) int load_archive(char *filename, unsigned char *buffer, int maxsize, char *extension)
{ {
int size = 0; int size = 0;
@ -55,6 +54,7 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize)
{ {
unz_file_info info; unz_file_info info;
int ret = 0; int ret = 0;
char fname[256];
/* Attempt to open the archive */ /* Attempt to open the archive */
unzFile *fd = unzOpen(filename); unzFile *fd = unzOpen(filename);
@ -69,13 +69,20 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize)
} }
/* Get file informations and update filename */ /* Get file informations and update filename */
ret = unzGetCurrentFileInfo(fd, &info, filename, 128, NULL, 0, NULL, 0); ret = unzGetCurrentFileInfo(fd, &info, fname, 256, NULL, 0, NULL, 0);
if(ret != UNZ_OK) if(ret != UNZ_OK)
{ {
unzClose(fd); unzClose(fd);
return 0; return 0;
} }
/* Compressed filename extension */
if (extension)
{
strncpy(extension, &fname[strlen(fname) - 3], 3);
extension[3] = 0;
}
/* Open the file for reading */ /* Open the file for reading */
ret = unzOpenCurrentFile(fd); ret = unzOpenCurrentFile(fd);
if(ret != UNZ_OK) if(ret != UNZ_OK)
@ -121,6 +128,13 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize)
/* Read file data */ /* Read file data */
size = gzread(gd, buffer, maxsize); size = gzread(gd, buffer, maxsize);
/* filename extension */
if (extension)
{
strncpy(extension, &filename[strlen(filename) - 3], 3);
extension[3] = 0;
}
/* Close file */ /* Close file */
gzclose(gd); gzclose(gd);
} }
@ -143,25 +157,3 @@ static int check_zip(char *filename)
if(memcmp(buf, "PK", 2) == 0) return (1); if(memcmp(buf, "PK", 2) == 0) return (1);
return (0); return (0);
} }
/*
Returns the size of a GZ compressed file.
*/
static int gzsize(gzFile *gd)
{
#define CHUNKSIZE (0x10000)
int size = 0, length = 0;
unsigned char buffer[CHUNKSIZE];
gzrewind(gd);
do
{
size = gzread(gd, buffer, CHUNKSIZE);
if(size <= 0) break;
length += size;
}
while (!gzeof(gd));
gzrewind(gd);
return (length);
#undef CHUNKSIZE
}

View File

@ -43,6 +43,6 @@
#define _FILEIO_H_ #define _FILEIO_H_
/* Function prototypes */ /* Function prototypes */
extern int load_archive(char *filename, unsigned char *buffer, int maxsize); extern int load_archive(char *filename, unsigned char *buffer, int maxsize, char *extension);
#endif /* _FILEIO_H_ */ #endif /* _FILEIO_H_ */

View File

@ -701,7 +701,7 @@ int main (int argc, char **argv)
fclose(fp); fclose(fp);
/* check BOOT ROM */ /* check BOOT ROM */
if (!strncmp((char *)(boot_rom + 0x120),"GENESIS OS", 10)) if (!memcmp((char *)(boot_rom + 0x120),"GENESIS OS", 10))
{ {
/* mark Genesis BIOS as loaded */ /* mark Genesis BIOS as loaded */
system_bios = SYSTEM_MD; system_bios = SYSTEM_MD;