From 414a53ca1f038e091c2588168b5a883c79cd9aa6 Mon Sep 17 00:00:00 2001 From: ekeeke31 Date: Tue, 6 Jan 2009 17:15:28 +0000 Subject: [PATCH] modified sn76489 cut-off frequency, modified Video synchronization --- source/ngc/ngc.c | 89 +++++----- source/ngc/ogc_audio.c | 22 +-- source/ngc/ogc_video.c | 339 ++++++++++++++++++++----------------- source/sound/sn76489.c | 316 +++++++++++++++++----------------- source/sound/sn76489.h | 2 +- source/unused/dos/Makefile | 9 +- source/unused/win/Makefile | 2 +- source/vdp.c | 4 +- 8 files changed, 412 insertions(+), 371 deletions(-) diff --git a/source/ngc/ngc.c b/source/ngc/ngc.c index 74f6b42..977fbad 100644 --- a/source/ngc/ngc.c +++ b/source/ngc/ngc.c @@ -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,34 +164,50 @@ 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) { - ogc_audio__start(); - + /* 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) { /* this code is NEVER executed */ @@ -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; } diff --git a/source/ngc/ogc_audio.c b/source/ngc/ogc_audio.c index eb26987..32e5bb2 100644 --- a/source/ngc/ogc_audio.c +++ b/source/ngc/ogc_audio.c @@ -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; - } + 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(); + 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; } diff --git a/source/ngc/ogc_video.c b/source/ngc/ogc_video.c index c39938e..f7f3fb1 100644 --- a/source/ngc/ogc_video.c +++ b/source/ngc/ogc_video.c @@ -53,26 +53,28 @@ 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 - 640, // fbWidth - 286, // efbHeight - 286, // xfbHeight - (VI_MAX_WIDTH_PAL - 720)/2, // viXOrigin - (VI_MAX_HEIGHT_PAL/2 - 572/2)/2,// viYOrigin - 720, // viWidth - 572, // viHeight - VI_XFBMODE_SF, // xFBmode - GX_FALSE, // field_rendering - GX_FALSE, // aa + VI_TVMODE_PAL_DS, // viDisplayMode + 640, // fbWidth + 286, // efbHeight + 286, // xfbHeight + 0, // viXOrigin + (VI_MAX_HEIGHT_PAL - 572)/2, // viYOrigin + VI_MAX_WIDTH_PAL, // viWidth + 572, // viHeight + VI_XFBMODE_SF, // xFBmode + GX_FALSE, // field_rendering + GX_FALSE, // aa - // sample points arranged in increasing Y order + // sample points arranged in increasing Y order { {6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each {6,6},{6,6},{6,6}, // pix 1 @@ -82,102 +84,32 @@ GXRModeObj TV50hz_288p = // vertical filter[7], 1/64 units, 6 bits each { - 0, // line n-1 - 0, // line n-1 - 21, // line n - 22, // line n - 21, // line n - 0, // line n+1 - 0 // line n+1 + 0, // line n-1 + 0, // line n-1 + 21, // line n + 22, // line n + 21, // line n + 0, // line n+1 + 0 // line n+1 } }; /* 288 lines interlaced (PAL 50Hz) */ GXRModeObj TV50hz_288i = { - 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 - 572, // viHeight - VI_XFBMODE_SF, // xFBmode - GX_TRUE, // field_rendering - GX_FALSE, // aa + VI_TVMODE_PAL_INT, // viDisplayMode + 640, // fbWidth + 286, // efbHeight + 286, // xfbHeight + 0, // viXOrigin + (VI_MAX_HEIGHT_PAL - 572)/2, // viYOrigin + VI_MAX_WIDTH_PAL, // viWidth + 572, // viHeight + VI_XFBMODE_SF, // xFBmode + GX_TRUE, // field_rendering + GX_FALSE, // aa - // sample points arranged in increasing Y order - { - {6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each - {6,6},{6,6},{6,6}, // pix 1 - {6,6},{6,6},{6,6}, // pix 2 - {6,6},{6,6},{6,6} // pix 3 - }, - - // vertical filter[7], 1/64 units, 6 bits each - { - 0, // line n-1 - 0, // line n-1 - 21, // line n - 22, // line n - 21, // line n - 0, // line n+1 - 0 // line n+1 - } -}; - -/* 576 lines interlaced (PAL 50Hz, scaled) */ -GXRModeObj TV50hz_576i = -{ - 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_XFBMODE_DF, // xFBmode - GX_FALSE, // field_rendering - GX_FALSE, // aa - - // sample points arranged in increasing Y order - { - {6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each - {6,6},{6,6},{6,6}, // pix 1 - {6,6},{6,6},{6,6}, // pix 2 - {6,6},{6,6},{6,6} // pix 3 - }, - - // vertical filter[7], 1/64 units, 6 bits each - { - 8, // line n-1 - 8, // line n-1 - 10, // line n - 12, // line n - 10, // line n - 8, // line n+1 - 8 // line n+1 - } -}; - -/* 240 lines progressive (NTSC or PAL 60Hz) */ -GXRModeObj TV60hz_240p = -{ - 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_XFBMODE_SF, // xFBmode - GX_FALSE, // field_rendering - GX_FALSE, // aa - - // sample points arranged in increasing Y order + // sample points arranged in increasing Y order { {6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each {6,6},{6,6},{6,6}, // pix 1 @@ -187,32 +119,102 @@ GXRModeObj TV60hz_240p = // vertical filter[7], 1/64 units, 6 bits each { - 0, // line n-1 - 0, // line n-1 - 21, // line n - 22, // line n - 21, // line n - 0, // line n+1 - 0 // line n+1 + 0, // line n-1 + 0, // line n-1 + 21, // line n + 22, // line n + 21, // line n + 0, // line n+1 + 0 // line n+1 + } +}; + +/* 576 lines interlaced (PAL 50Hz, scaled) */ +GXRModeObj TV50hz_576i = +{ + VI_TVMODE_PAL_INT, // viDisplayMode + 640, // fbWidth + 480, // efbHeight + 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 + + // sample points arranged in increasing Y order + { + {6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each + {6,6},{6,6},{6,6}, // pix 1 + {6,6},{6,6},{6,6}, // pix 2 + {6,6},{6,6},{6,6} // pix 3 + }, + + // vertical filter[7], 1/64 units, 6 bits each + { + 8, // line n-1 + 8, // line n-1 + 10, // line n + 12, // line n + 10, // line n + 8, // line n+1 + 8 // line n+1 + } +}; + +/* 240 lines progressive (NTSC or PAL 60Hz) */ +GXRModeObj TV60hz_240p = +{ + VI_TVMODE_EURGB60_DS, // viDisplayMode + 640, // fbWidth + 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 + + // sample points arranged in increasing Y order + { + {6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each + {6,6},{6,6},{6,6}, // pix 1 + {6,6},{6,6},{6,6}, // pix 2 + {6,6},{6,6},{6,6} // pix 3 + }, + + // vertical filter[7], 1/64 units, 6 bits each + { + 0, // line n-1 + 0, // line n-1 + 21, // line n + 22, // line n + 21, // line n + 0, // line n+1 + 0 // line n+1 } }; /* 240 lines interlaced (NTSC or PAL 60Hz) */ GXRModeObj TV60hz_240i = { - 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_XFBMODE_SF, // xFBmode - GX_TRUE, // field_rendering - GX_FALSE, // aa + VI_TVMODE_EURGB60_INT, // viDisplayMode + 640, // fbWidth + 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 - // sample points arranged in increasing Y order + // sample points arranged in increasing Y order { {3,2},{9,6},{3,10}, // pix 0, 3 sample points, 1/12 units, 4 bits each {3,2},{9,6},{3,10}, // pix 1 @@ -220,15 +222,15 @@ GXRModeObj TV60hz_240i = {9,2},{3,6},{9,10} // pix 3 }, - // vertical filter[7], 1/64 units, 6 bits each + // vertical filter[7], 1/64 units, 6 bits each { - 0, // line n-1 - 0, // line n-1 - 21, // line n - 22, // line n - 21, // line n - 0, // line n+1 - 0 // line n+1 + 0, // line n-1 + 0, // line n-1 + 21, // line n + 22, // line n + 21, // line n + 0, // line n+1 + 0 // line n+1 } }; @@ -236,18 +238,18 @@ GXRModeObj TV60hz_240i = 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_XFBMODE_DF, // xFBmode - GX_FALSE, // field_rendering - GX_FALSE, // aa + 640, // fbWidth + 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 - // sample points arranged in increasing Y order + // sample points arranged in increasing Y order { {6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each {6,6},{6,6},{6,6}, // pix 1 @@ -255,15 +257,15 @@ GXRModeObj TV60hz_480i = {6,6},{6,6},{6,6} // pix 3 }, - // vertical filter[7], 1/64 units, 6 bits each + // vertical filter[7], 1/64 units, 6 bits each { - 8, // line n-1 - 8, // line n-1 - 10, // line n - 12, // line n - 10, // line n - 8, // line n+1 - 8 // line n+1 + 8, // line n-1 + 8, // line n-1 + 10, // line n + 12, // line n + 10, // line n + 8, // line n+1 + 8 // line n+1 } }; @@ -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 */ - whichfb ^= 1; - GX_CopyDisp (xfb[whichfb], GX_TRUE); - GX_Flush (); + /* postpound XFB update */ + do_copy = GX_TRUE; +} - /* set next XFB */ - VIDEO_SetNextFramebuffer (xfb[whichfb]); - VIDEO_Flush (); +/* Pre-Retrace handler + synchronize XFB switch with VSYNC + */ +void xfb_switch(u32 cnt) +{ + if (!ConfigRequested) + { + /* switch external framebuffers */ + whichfb ^= 1; + + /* 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); diff --git a/source/sound/sn76489.c b/source/sound/sn76489.c index 55f55ed..2b6f981 100644 --- a/source/sound/sn76489.c +++ b/source/sound/sn76489.c @@ -23,19 +23,22 @@ 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" -#include // for FLT_MIN +#include // for FLT_MIN #include // 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 */ - {892,892,892,760,623,497,404,323,257,198,159,123,96,75,60,0}, /* I can't remember why 892... :P some scaling I did at some point */ + {892,892,892,760,623,497,404,323,257,198,159,123,96,75,60,0}, /* I can't remember why 892... :P some scaling I did at some point */ /* these values are true volumes for 2dB drops at each step (multiply previous by 10^-0.1), normalised at 760 */ {1516,1205,957,760,603,479,381,303,240,191,152,120,96,76,60,0} }; @@ -44,47 +47,46 @@ static SN76489_Context SN76489[MAX_SN76489]; void SN76489_Init(int which, int PSGClockValue, int SamplingRate) { - SN76489_Context *p = &SN76489[which]; - p->dClock=(float)PSGClockValue/16/SamplingRate; - SN76489_Config(which, MUTE_ALLON, VOL_FULL, FB_SEGAVDP, SRW_SEGAVDP, 1); - SN76489_Reset(which); + SN76489_Context *p = &SN76489[which]; + p->dClock=(float)PSGClockValue/16/SamplingRate; + SN76489_Config(which, MUTE_ALLON, VOL_FULL, FB_SEGAVDP, SRW_SEGAVDP, 1); + SN76489_Reset(which); } void SN76489_Reset(int which) { - SN76489_Context *p = &SN76489[which]; - int i; + SN76489_Context *p = &SN76489[which]; + int i; - p->PSGStereo = 0xFF; + p->PSGStereo = 0xFF; - for(i = 0; i <= 3; i++) - { - /* Initialise PSG state */ - p->Registers[2*i] = 1; /* tone freq=1 */ - p->Registers[2*i+1] = 0xf; /* vol=off */ - p->NoiseFreq = 0x10; + for(i = 0; i <= 3; i++) + { + /* Initialise PSG state */ + p->Registers[2*i] = 1; /* tone freq=1 */ + p->Registers[2*i+1] = 0xf; /* vol=off */ + p->NoiseFreq = 0x10; - /* Set counters to 0 */ - p->ToneFreqVals[i] = 0; + /* Set counters to 0 */ + p->ToneFreqVals[i] = 0; - /* Set flip-flops to 1 */ - p->ToneFreqPos[i] = 1; + /* Set flip-flops to 1 */ + p->ToneFreqPos[i] = 1; - /* Set intermediate positions to do-not-use value */ - p->IntermediatePos[i] = FLT_MIN; + /* Set intermediate positions to do-not-use value */ + p->IntermediatePos[i] = FLT_MIN; - /* Set panning to centre */ - p->panning[0]=127; - } + /* Set panning to centre */ + p->panning[0]=127; + } - p->LatchedRegister=0; + p->LatchedRegister=0; - /* Initialise noise generator */ - p->NoiseShiftRegister=NoiseInitialState; - - /* Zero clock */ - p->Clock=0; + /* Initialise noise generator */ + p->NoiseShiftRegister=NoiseInitialState; + /* Zero clock */ + p->Clock=0; } void SN76489_Shutdown(void) @@ -93,164 +95,172 @@ void SN76489_Shutdown(void) void SN76489_Config(int which, int mute, int volume, int feedback, int sr_width, int boost_noise) { - SN76489_Context *p = &SN76489[which]; + SN76489_Context *p = &SN76489[which]; - p->Mute = mute; - p->VolumeArray = volume; - p->WhiteNoiseFeedback = feedback; - p->SRWidth = sr_width; - p->BoostNoise = boost_noise; + p->Mute = mute; + p->VolumeArray = volume; + p->WhiteNoiseFeedback = feedback; + p->SRWidth = sr_width; + p->BoostNoise = boost_noise; } void SN76489_SetContext(int which, uint8 *data) { - memcpy(&SN76489[which], data, sizeof(SN76489_Context)); + memcpy(&SN76489[which], data, sizeof(SN76489_Context)); } void SN76489_GetContext(int which, uint8 *data) { - memcpy(data, &SN76489[which], sizeof(SN76489_Context)); + memcpy(data, &SN76489[which], sizeof(SN76489_Context)); } uint8 *SN76489_GetContextPtr(int which) { - return (uint8 *)&SN76489[which]; + return (uint8 *)&SN76489[which]; } int SN76489_GetContextSize(void) { - return sizeof(SN76489_Context); + return sizeof(SN76489_Context); } void SN76489_Write(int which, int data) { - SN76489_Context *p = &SN76489[which]; + SN76489_Context *p = &SN76489[which]; - 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 { - /* 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 */ + 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 + { + /* 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 */ else - /* Other register */ - p->Registers[p->LatchedRegister]=data&0x0f; /* Replace with data */ - } - switch (p->LatchedRegister) { - case 0: - case 2: + /* Other register */ + p->Registers[p->LatchedRegister]=data&0x0f; /* Replace with data */ + } + + 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 */ - break; + /* 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 */ - break; - } + p->NoiseShiftRegister=NoiseInitialState; /* reset shift register */ + p->NoiseFreq=0x10<<(p->Registers[6]&0x3); /* set noise signal generator frequency */ + break; + } } void SN76489_GGStereoWrite(int which, int data) { - SN76489_Context *p = &SN76489[which]; - p->PSGStereo=data; + SN76489_Context *p = &SN76489[which]; + p->PSGStereo=data; } void SN76489_Update(int which, INT16 *buffer, int length) { - SN76489_Context *p = &SN76489[which]; - int i, j; + SN76489_Context *p = &SN76489[which]; + int i, j; - for(j = 0; j < length; j++) - { - 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]); - else - p->Channels[i]=(p->Mute >> i & 0x1)*PSGVolumeValues[p->VolumeArray][p->Registers[2*i+1]]*p->ToneFreqPos[i]; - - 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]; - - p->Clock+=p->dClock; - p->NumClocksForSample=(int)p->Clock; /* truncates */ - p->Clock-=p->NumClocksForSample; /* remove integer part */ - /* Looks nicer in Delphi... */ - /* Clock:=Clock+p->dClock; */ - /* NumClocksForSample:=Trunc(Clock); */ - /* Clock:=Frac(Clock); */ - - /* Decrement tone channel counters */ - for (i=0;i<=2;++i) - p->ToneFreqVals[i]-=p->NumClocksForSample; - - /* Noise channel: match to tone2 or decrement its counter */ - if (p->NoiseFreq==0x80) p->ToneFreqVals[3]=p->ToneFreqVals[2]; - else p->ToneFreqVals[3]-=p->NumClocksForSample; - - /* Tone channels: */ - for (i=0;i<=2;++i) { - if (p->ToneFreqVals[i]<=0) { /* If it gets below 0... */ - if (p->Registers[i*2]>PSG_CUTOFF) { - /* Calculate how much of the sample is + and how much is - */ - /* Go to floating point and include the clock fraction for extreme accuracy :D */ - /* Store as long int, maybe it's faster? I'm not very good at this */ - p->IntermediatePos[i]=(p->NumClocksForSample-p->Clock+2*p->ToneFreqVals[i])*p->ToneFreqPos[i]/(p->NumClocksForSample+p->Clock); - p->ToneFreqPos[i]=-p->ToneFreqPos[i]; /* Flip the flip-flop */ - } else { - p->ToneFreqPos[i]=1; /* stuck value */ - p->IntermediatePos[i]=FLT_MIN; - } - p->ToneFreqVals[i]+=p->Registers[i*2]*(p->NumClocksForSample/p->Registers[i*2]+1); - } else p->IntermediatePos[i]=FLT_MIN; - } - - /* 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 */ - p->ToneFreqVals[3]+=p->NoiseFreq*(p->NumClocksForSample/p->NoiseFreq+1); - if (p->ToneFreqPos[3]==1) { /* Only once per cycle... */ - int Feedback; - if (p->Registers[6]&0x4) { /* White noise */ - /* Calculate parity of fed-back bits for feedback */ - switch (p->WhiteNoiseFeedback) { - /* Do some optimised calculations for common (known) feedback values */ - case 0x0003: /* SC-3000, BBC %00000011 */ - case 0x0009: /* SMS, GG, MD %00001001 */ - /* If two bits fed back, I can do Feedback=(nsr & fb) && (nsr & fb ^ fb) */ - /* since that's (one or more bits set) && (not all bits set) */ - Feedback=((p->NoiseShiftRegister&p->WhiteNoiseFeedback) && ((p->NoiseShiftRegister&p->WhiteNoiseFeedback)^p->WhiteNoiseFeedback)); - break; - default: /* Default handler for all other feedback values */ - Feedback=p->NoiseShiftRegister&p->WhiteNoiseFeedback; - Feedback^=Feedback>>8; - Feedback^=Feedback>>4; - Feedback^=Feedback>>2; - Feedback^=Feedback>>1; - Feedback&=1; - break; - } - } else /* Periodic noise */ - Feedback=p->NoiseShiftRegister&1; - - p->NoiseShiftRegister=(p->NoiseShiftRegister>>1) | (Feedback << (p->SRWidth-1)); - - /* Original code: */ - /* p->NoiseShiftRegister=(p->NoiseShiftRegister>>1) | ((p->Registers[6]&0x4?((p->NoiseShiftRegister&0x9) && (p->NoiseShiftRegister&0x9^0x9)):p->NoiseShiftRegister&1)<<15); */ - } + 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]); + else + p->Channels[i]=(p->Mute >> i & 0x1)*PSGVolumeValues[p->VolumeArray][p->Registers[2*i+1]]*p->ToneFreqPos[i]; + + 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 */ + /* Looks nicer in Delphi... */ + /* Clock:=Clock+p->dClock; */ + /* NumClocksForSample:=Trunc(Clock); */ + /* Clock:=Frac(Clock); */ + + /* Decrement tone channel counters */ + for (i=0;i<=2;++i) + p->ToneFreqVals[i]-=p->NumClocksForSample; + + /* Noise channel: match to tone2 or decrement its counter */ + if (p->NoiseFreq==0x80) p->ToneFreqVals[3]=p->ToneFreqVals[2]; + else p->ToneFreqVals[3]-=p->NumClocksForSample; + + /* Tone channels: */ + for (i=0;i<=2;++i) { + if (p->ToneFreqVals[i]<=0) { /* If it gets below 0... */ + if (p->Registers[i*2]>PSG_CUTOFF) { + /* Calculate how much of the sample is + and how much is - */ + /* Go to floating point and include the clock fraction for extreme accuracy :D */ + /* Store as long int, maybe it's faster? I'm not very good at this */ + p->IntermediatePos[i]=(p->NumClocksForSample-p->Clock+2*p->ToneFreqVals[i])*p->ToneFreqPos[i]/(p->NumClocksForSample+p->Clock); + p->ToneFreqPos[i]=-p->ToneFreqPos[i]; /* Flip the flip-flop */ + } else { + p->ToneFreqPos[i]=1; /* stuck value */ + p->IntermediatePos[i]=FLT_MIN; } + p->ToneFreqVals[i]+=p->Registers[i*2]*(p->NumClocksForSample/p->Registers[i*2]+1); + } else p->IntermediatePos[i]=FLT_MIN; } + + /* 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, reset counter */ + p->ToneFreqVals[3]+=p->NoiseFreq*(p->NumClocksForSample/p->NoiseFreq+1); + if (p->ToneFreqPos[3]==1) { /* Only once per cycle... */ + int Feedback; + if (p->Registers[6]&0x4) { /* White noise */ + /* Calculate parity of fed-back bits for feedback */ + switch (p->WhiteNoiseFeedback) { + /* Do some optimised calculations for common (known) feedback values */ + case 0x0003: /* SC-3000, BBC %00000011 */ + case 0x0009: /* SMS, GG, MD %00001001 */ + /* If two bits fed back, I can do Feedback=(nsr & fb) && (nsr & fb ^ fb) */ + /* since that's (one or more bits set) && (not all bits set) */ + Feedback=((p->NoiseShiftRegister&p->WhiteNoiseFeedback) && ((p->NoiseShiftRegister&p->WhiteNoiseFeedback)^p->WhiteNoiseFeedback)); + break; + default: /* Default handler for all other feedback values */ + Feedback=p->NoiseShiftRegister&p->WhiteNoiseFeedback; + Feedback^=Feedback>>8; + Feedback^=Feedback>>4; + Feedback^=Feedback>>2; + Feedback^=Feedback>>1; + Feedback&=1; + break; + } + } else /* Periodic noise */ + Feedback=p->NoiseShiftRegister&1; + + p->NoiseShiftRegister=(p->NoiseShiftRegister>>1) | (Feedback << (p->SRWidth-1)); + + /* Original code: */ + /* p->NoiseShiftRegister=(p->NoiseShiftRegister>>1) | ((p->Registers[6]&0x4?((p->NoiseShiftRegister&0x9) && (p->NoiseShiftRegister&0x9^0x9)):p->NoiseShiftRegister&1)<<15); */ + } + } + } } /*void SN76489_UpdateOne(int which, int *l, int *r) diff --git a/source/sound/sn76489.h b/source/sound/sn76489.h index 3bf334c..4062e4d 100644 --- a/source/sound/sn76489.h +++ b/source/sound/sn76489.h @@ -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 diff --git a/source/unused/dos/Makefile b/source/unused/dos/Makefile index 1b0a0b8..8f52d76 100644 --- a/source/unused/dos/Makefile +++ b/source/unused/dos/Makefile @@ -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) diff --git a/source/unused/win/Makefile b/source/unused/win/Makefile index d9c2b75..c66252f 100644 --- a/source/unused/win/Makefile +++ b/source/unused/win/Makefile @@ -58,7 +58,7 @@ OBJECTS += obj/main.o \ obj/loadrom.o OBJECTS += obj/sms_ntsc.o \ - obj/md_ntsc.o + obj/md_ntsc.o OBJECTS += obj/icon.o diff --git a/source/vdp.c b/source/vdp.c index 8e82db2..e2f6d6c 100644 --- a/source/vdp.c +++ b/source/vdp.c @@ -249,8 +249,8 @@ void vdp_restore(uint8 *vdp_regs) bitmap.viewport.changed = 1; /* restore VDP timings */ - fifo_latency = (reg[12] & 1) ? 27 : 30; - if ((code & 0x0F) == 0x01) fifo_latency = fifo_latency * 2; + fifo_latency = (reg[12] & 1) ? 27 : 30; + if ((code & 0x0F) == 0x01) fifo_latency = fifo_latency * 2; /* remake cache */ for (i=0;i<0x800;i++)