modified sn76489 cut-off frequency, modified Video synchronization

This commit is contained in:
ekeeke31 2009-01-06 17:15:28 +00:00
parent 0e86a15c09
commit 414a53ca1f
8 changed files with 412 additions and 371 deletions

View File

@ -125,33 +125,33 @@ bool fat_enabled = 0;
int main (int argc, char *argv[])
{
long long now, prev;
int RenderedFrameCount = 0;
int FrameCount = 0;
#ifdef HW_RVL
/* initialize Wii DVD interface first */
DI_Close();
DI_Init();
#endif
long long now, prev;
int RenderedFrameCount = 0;
int FrameCount = 0;
/* Initialize OGC subsystems */
/* initialize OGC subsystems */
ogc_video__init();
ogc_input__init();
ogc_audio__init();
#ifdef HW_DOL
/* Initialize GC DVD interface */
/* initialize GC DVD interface */
DVD_Init ();
dvd_drive_detect();
#endif
#ifdef HW_RVL
/* Power Button callback */
/* Power button callback */
SYS_SetPowerCallback(Power_Off);
#endif
/* Initialize FAT Interface */
/* initialize FAT Interface */
if (fatInitDefault() == true)
{
fat_enabled = 1;
@ -164,33 +164,49 @@ int main (int argc, char *argv[])
#endif
}
/* Default Config */
/* default Config */
legal();
set_config_defaults();
config_load();
/* Restore Recent Files list */
/* restore recent Files list */
set_history_defaults();
history_load();
/* Initialize Virtual Machine */
/* initialize VM */
init_machine ();
/* Load any injected rom */
/* load any injected rom */
if (genromsize)
{
ARAMFetch((char *)cart_rom, (void *)0x8000, genromsize);
reloadrom ();
}
/* Show Menu */
MainMenu();
ConfigRequested = 0;
/* show Menu first */
ConfigRequested = 1;
/* Emulation Loop */
/* main emulation loop */
while (1)
{
/* Check for Menu request */
if (ConfigRequested)
{
/* stop Audio */
ogc_audio__stop();
/* go to Menu */
MainMenu ();
ConfigRequested = 0;
/* reset frame sync */
frameticker = 0;
FrameCount = 0;
RenderedFrameCount = 0;
/* restart sound loop */
ogc_audio__start();
}
if (gc_pal < 0)
{
@ -204,28 +220,31 @@ int main (int argc, char *argv[])
{
if (frameticker > 1)
{
/* frameskipping */
/* skip one frame */
frameticker--;
system_frame (1);
/* update audio only */
ogc_audio__update();
}
else
{
/* frame sync */
while (!frameticker) usleep(1);
while (frameticker < 1) usleep(1);
/* frame rendering */
/* render one frame */
system_frame (0);
RenderedFrameCount++;
/* update audio & video */
ogc_audio__update();
ogc_video__update();
}
frameticker--;
}
/* update video & audio */
ogc_audio__update();
ogc_video__update();
/* check rendered frames (FPS) */
/* check rendered frame count (FPS) */
FrameCount++;
if (FrameCount == vdp_rate)
{
@ -233,23 +252,7 @@ int main (int argc, char *argv[])
RenderedFrameCount = 0;
FrameCount = 0;
}
/* Check for Menu request */
if (ConfigRequested)
{
/* stop Audio */
ogc_audio__stop();
/* go to menu */
MainMenu ();
ConfigRequested = 0;
/* reset frame sync */
frameticker = 0;
FrameCount = 0;
RenderedFrameCount = 0;
}
}
return 0;
}

View File

@ -35,9 +35,6 @@ u8 soundbuffer[2][3840] ATTRIBUTE_ALIGN(32);
/* Current work soundbuffer */
int mixbuffer;
/* Current DMA status (1: DMA in progress, 0: DMA stopped) */
static int IsPlaying = 0;
/* Current DMA length (required to be a factor of 32-bytes)
length is calculated regarding current emulation timings:
PAL timings : 50 frames/sec, 48000 samples/sec = 960 samples per frame = 3840 bytes (16 bits stereo samples)
@ -99,27 +96,22 @@ void ogc_audio__update(void)
***/
void ogc_audio__start(void)
{
if (!IsPlaying)
{
dma_len = vdp_pal ? 3840 : 3200;
memset(soundbuffer[0], 0, dma_len);
AUDIO_InitDMA((u32) soundbuffer[0], dma_len);
DCFlushRange(soundbuffer[0], dma_len);
AUDIO_StartDMA();
IsPlaying = 1;
mixbuffer = 1;
}
}
/***
ogc_audio__stop
This function reset current Audio DMA process and clear soundbuffers
This function reset current Audio DMA process
This is called when going back to Main Menu
DMA need to be restarted when going back to the game (see above)
***/
void ogc_audio__stop(void)
{
AUDIO_StopDMA ();
IsPlaying = 0;
}

View File

@ -53,20 +53,22 @@ u8 *texturemem; /*** Texture Data ***/
static u8 gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN (32);
static GXTexObj texobj;
static u8 do_copy = GX_FALSE;
static Mtx view;
static u32 vwidth, vheight;
/*** custom Video modes (used to emulate original console video modes) ***/
/*** custom Video modes ***/
/* 288 lines progressive (PAL 50Hz) */
GXRModeObj TV50hz_288p =
{
VI_TVMODE_PAL_DS,// viDisplayMode
VI_TVMODE_PAL_DS, // viDisplayMode
640, // fbWidth
286, // efbHeight
286, // xfbHeight
(VI_MAX_WIDTH_PAL - 720)/2, // viXOrigin
(VI_MAX_HEIGHT_PAL/2 - 572/2)/2,// viYOrigin
720, // viWidth
0, // viXOrigin
(VI_MAX_HEIGHT_PAL - 572)/2, // viYOrigin
VI_MAX_WIDTH_PAL, // viWidth
572, // viHeight
VI_XFBMODE_SF, // xFBmode
GX_FALSE, // field_rendering
@ -95,13 +97,13 @@ GXRModeObj TV50hz_288p =
/* 288 lines interlaced (PAL 50Hz) */
GXRModeObj TV50hz_288i =
{
VI_TVMODE_PAL_INT,// viDisplayMode
VI_TVMODE_PAL_INT, // viDisplayMode
640, // fbWidth
286, // efbHeight
286, // xfbHeight
(VI_MAX_WIDTH_PAL - 720)/2, // viXOrigin
(VI_MAX_HEIGHT_PAL/2 - 572/2)/2,// viYOrigin
720, // viWidth
0, // viXOrigin
(VI_MAX_HEIGHT_PAL - 572)/2, // viYOrigin
VI_MAX_WIDTH_PAL, // viWidth
572, // viHeight
VI_XFBMODE_SF, // xFBmode
GX_TRUE, // field_rendering
@ -130,14 +132,14 @@ GXRModeObj TV50hz_288i =
/* 576 lines interlaced (PAL 50Hz, scaled) */
GXRModeObj TV50hz_576i =
{
VI_TVMODE_PAL_INT,// viDisplayMode
VI_TVMODE_PAL_INT, // viDisplayMode
640, // fbWidth
480, // efbHeight
574, // xfbHeight
(VI_MAX_WIDTH_PAL - 720)/2, // viXOrigin
(VI_MAX_HEIGHT_PAL - 574)/2,// viYOrigin
720, // viWidth
574, // viHeight
VI_MAX_HEIGHT_PAL, // xfbHeight
0, // viXOrigin
0, // viYOrigin
VI_MAX_WIDTH_PAL, // viWidth
VI_MAX_HEIGHT_PAL, // viHeight
VI_XFBMODE_DF, // xFBmode
GX_FALSE, // field_rendering
GX_FALSE, // aa
@ -165,14 +167,14 @@ GXRModeObj TV50hz_576i =
/* 240 lines progressive (NTSC or PAL 60Hz) */
GXRModeObj TV60hz_240p =
{
VI_TVMODE_EURGB60_DS,// viDisplayMode
VI_TVMODE_EURGB60_DS, // viDisplayMode
640, // fbWidth
240, // efbHeight
240, // xfbHeight
(VI_MAX_WIDTH_NTSC - 720)/2, // viXOrigin
(VI_MAX_HEIGHT_NTSC/2 - 480/2)/2, // viYOrigin
720, // viWidth
480, // viHeight
VI_MAX_HEIGHT_NTSC/2, // efbHeight
VI_MAX_HEIGHT_NTSC/2, // xfbHeight
0, // viXOrigin
0, // viYOrigin
VI_MAX_WIDTH_NTSC, // viWidth
VI_MAX_HEIGHT_NTSC, // viHeight
VI_XFBMODE_SF, // xFBmode
GX_FALSE, // field_rendering
GX_FALSE, // aa
@ -200,14 +202,14 @@ GXRModeObj TV60hz_240p =
/* 240 lines interlaced (NTSC or PAL 60Hz) */
GXRModeObj TV60hz_240i =
{
VI_TVMODE_EURGB60_INT,// viDisplayMode
VI_TVMODE_EURGB60_INT, // viDisplayMode
640, // fbWidth
240, // efbHeight
240, // xfbHeight
(VI_MAX_WIDTH_NTSC - 720)/2, // viXOrigin
(VI_MAX_HEIGHT_NTSC/2 - 480/2)/2, // viYOrigin
720, // viWidth
480, // viHeight
VI_MAX_HEIGHT_NTSC/2, // efbHeight
VI_MAX_HEIGHT_NTSC/2, // xfbHeight
0, // viXOrigin
0, // viYOrigin
VI_MAX_WIDTH_NTSC, // viWidth
VI_MAX_HEIGHT_NTSC, // viHeight
VI_XFBMODE_SF, // xFBmode
GX_TRUE, // field_rendering
GX_FALSE, // aa
@ -237,12 +239,12 @@ GXRModeObj TV60hz_480i =
{
VI_TVMODE_EURGB60_INT,// viDisplayMode
640, // fbWidth
480, // efbHeight
480, // xfbHeight
(VI_MAX_WIDTH_NTSC - 720)/2, // viXOrigin
(VI_MAX_HEIGHT_NTSC - 480)/2, // viYOrigin
720, // viWidth
480, // viHeight
VI_MAX_HEIGHT_NTSC, // efbHeight
VI_MAX_HEIGHT_NTSC, // xfbHeight
0, // viXOrigin
0, // viYOrigin
VI_MAX_WIDTH_NTSC, // viWidth
VI_MAX_HEIGHT_NTSC, // viHeight
VI_XFBMODE_DF, // xFBmode
GX_FALSE, // field_rendering
GX_FALSE, // aa
@ -489,6 +491,7 @@ static void gxScale(GXRModeObj *rmode)
square[4] = square[1] = yscale + yshift;
square[7] = square[10] = -yscale + yshift;
/* flush data from cache */
DCFlushRange (square, 32);
GX_InvVtxCache ();
}
@ -618,14 +621,37 @@ void ogc_video__update()
draw_square ();
GX_DrawDone ();
/* switch external framebuffers then copy EFB to XFB */
/* postpound XFB update */
do_copy = GX_TRUE;
}
/* Pre-Retrace handler
synchronize XFB switch with VSYNC
*/
void xfb_switch(u32 cnt)
{
if (!ConfigRequested)
{
/* switch external framebuffers */
whichfb ^= 1;
GX_CopyDisp (xfb[whichfb], GX_TRUE);
GX_Flush ();
/* set next XFB */
VIDEO_SetNextFramebuffer (xfb[whichfb]);
VIDEO_Flush ();
}
}
/* Post-Retrace handler
synchronize XFB copy with VSYNC */
void xfb_copy(u32 cnt)
{
if (do_copy)
{
/* copy EFB to XFB */
GX_CopyDisp (xfb[whichfb], GX_TRUE);
GX_Flush ();
do_copy = GX_FALSE;
}
}
/* Initialize VIDEO subsystem */
@ -720,6 +746,9 @@ void ogc_video__init(void)
/* Set the framebuffer to be displayed at next VBlank */
VIDEO_SetNextFramebuffer (xfb[0]);
VIDEO_SetPreRetraceCallback(xfb_switch);
VIDEO_SetPostRetraceCallback(xfb_copy);
/* Enable Video Interface */
VIDEO_SetBlack (FALSE);

View File

@ -23,6 +23,9 @@
Modified for use with GenesisPlus Gamecube's port:
- made SN76489_Update outputs 16bits mono samples
- replaced volume table with VGM plugin's one
05/01/2009 Eke-Eke
Modified Cut-Off frequency (according to Steve Snake: http://www.smspower.org/forums/viewtopic.php?t=1746)
*/
#include "shared.h"
@ -31,7 +34,7 @@
#include <string.h> // for memcpy
#define NoiseInitialState 0x8000 /* Initial state of shift register */
#define PSG_CUTOFF 0x6 /* Value below which PSG does not output */
#define PSG_CUTOFF 0x1 /* Value below which PSG does not output */
static const int PSGVolumeValues[2][16] = {
/* These values are taken from a real SMS2's output */
@ -84,7 +87,6 @@ void SN76489_Reset(int which)
/* Zero clock */
p->Clock=0;
}
void SN76489_Shutdown(void)
@ -126,29 +128,36 @@ void SN76489_Write(int which, int data)
{
SN76489_Context *p = &SN76489[which];
if (data&0x80) {
if (data&0x80)
{
/* Latch/data byte %1 cc t dddd */
p->LatchedRegister=((data>>4)&0x07);
p->Registers[p->LatchedRegister]=
(p->Registers[p->LatchedRegister] & 0x3f0) /* zero low 4 bits */
| (data&0xf); /* and replace with data */
} else {
p->Registers[p->LatchedRegister] =
(p->Registers[p->LatchedRegister] & 0x3f0) | /* zero low 4 bits */
(data&0xf); /* and replace with data */
}
else
{
/* Data byte %0 - dddddd */
if (!(p->LatchedRegister%2)&&(p->LatchedRegister<5))
/* Tone register */
p->Registers[p->LatchedRegister]=
(p->Registers[p->LatchedRegister] & 0x00f) /* zero high 6 bits */
| ((data&0x3f)<<4); /* and replace with data */
(p->Registers[p->LatchedRegister] & 0x00f) | /* zero high 6 bits */
((data&0x3f)<<4); /* and replace with data */
else
/* Other register */
p->Registers[p->LatchedRegister]=data&0x0f; /* Replace with data */
}
switch (p->LatchedRegister) {
switch (p->LatchedRegister)
{
case 0:
case 2:
case 4: /* Tone channels */
if (p->Registers[p->LatchedRegister]==0) p->Registers[p->LatchedRegister]=1; /* Zero frequency changed to 1 to avoid div/0 */
/* Zero frequency changed to 1 to avoid div/0 */
if (p->Registers[p->LatchedRegister]==0) p->Registers[p->LatchedRegister]=1;
break;
case 6: /* Noise */
p->NoiseShiftRegister=NoiseInitialState; /* reset shift register */
p->NoiseFreq=0x10<<(p->Registers[6]&0x3); /* set noise signal generator frequency */
@ -169,6 +178,7 @@ void SN76489_Update(int which, INT16 *buffer, int length)
for(j = 0; j < length; j++)
{
/* update output */
for (i=0;i<=2;++i)
if (p->IntermediatePos[i]!=FLT_MIN)
p->Channels[i]=(short)((p->Mute >> i & 0x1)*PSGVolumeValues[p->VolumeArray][p->Registers[2*i+1]]*p->IntermediatePos[i]);
@ -178,10 +188,10 @@ void SN76489_Update(int which, INT16 *buffer, int length)
p->Channels[3]=(short)((p->Mute >> 3 & 0x1)*PSGVolumeValues[p->VolumeArray][p->Registers[7]]*(p->NoiseShiftRegister & 0x1));
if (p->BoostNoise) p->Channels[3]<<=1; /* double noise volume */
buffer[j] =0;
for (i=0;i<=3;++i) buffer[j] += p->Channels[i];
/* update tone */
p->Clock+=p->dClock;
p->NumClocksForSample=(int)p->Clock; /* truncates */
p->Clock-=p->NumClocksForSample; /* remove integer part */
@ -218,7 +228,7 @@ void SN76489_Update(int which, INT16 *buffer, int length)
/* Noise channel */
if (p->ToneFreqVals[3]<=0) { /* If it gets below 0... */
p->ToneFreqPos[3]=-p->ToneFreqPos[3]; /* Flip the flip-flop */
if (p->NoiseFreq!=0x80) /* If not matching tone2, decrement counter */
if (p->NoiseFreq!=0x80) /* If not matching tone2, reset counter */
p->ToneFreqVals[3]+=p->NoiseFreq*(p->NumClocksForSample/p->NoiseFreq+1);
if (p->ToneFreqPos[3]==1) { /* Only once per cycle... */
int Feedback;

View File

@ -28,7 +28,7 @@
#ifndef _SN76489_H_
#define _SN76489_H_
#define MAX_SN76489 4
#define MAX_SN76489 1
/*
More testing is needed to find and confirm feedback patterns for

View File

@ -12,7 +12,7 @@
CC = gcc
AS = nasm -f coff
LDFLAGS =
FLAGS = -I. -I.. -I../z80 -I../m68k -I../dos -I../sound -I../sound/SRC -I../cart_hw -I../cart_hw/svp \
FLAGS = -I. -I.. -I../z80 -I../m68k -I../dos -I../sound -I../sound/SRC -I../cart_hw -I../cart_hw/svp -I../ntsc \
-Wall -g \
-O6 -march=i686 -fomit-frame-pointer \
-DLSB_FIRST -DX86_ASM -DDOS
@ -61,6 +61,9 @@ OBJ += obj/dos.o \
obj/fileio.o \
obj/loadrom.o
OBJ += obj/sms_ntsc.o \
obj/md_ntsc.o
EXE = ../gen.exe
all : $(EXE)
@ -102,6 +105,10 @@ obj/%.o : ../m68k/%.c ../m68k/%.h
obj/%.o : ./%.c ./%.h
$(CC) -c $< -o $@ $(FLAGS)
obj/%.o : ../ntsc/%.c ../ntsc/%.h
$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@
pack :
strip $(EXE)
upx -1 $(EXE)