mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-11-05 02:15:07 +01:00
finally fixed interlaced mode, reimplemented frame counters
This commit is contained in:
parent
e822832b99
commit
c8d27f6740
@ -1,6 +1,9 @@
|
||||
Genesis Plus for Gamecube
|
||||
------------------------------
|
||||
|
||||
[NGC/Wii]
|
||||
- fixed video issues in original interlaced modes
|
||||
- fixed some statibilty issues
|
||||
|
||||
1.3.1 (20/12/2008):
|
||||
-------------------
|
||||
|
@ -1109,7 +1109,7 @@ void showrominfo ()
|
||||
* Main Menu
|
||||
*
|
||||
****************************************************************************/
|
||||
void MainMenu ()
|
||||
void MainMenu (u32 fps)
|
||||
{
|
||||
menu = 0;
|
||||
int ret;
|
||||
@ -1139,6 +1139,7 @@ void MainMenu ()
|
||||
{
|
||||
crccheck = crc32 (0, &sram.sram[0], 0x10000);
|
||||
if (genromsize && (crccheck != sram.crc)) strcpy (menutitle, "*** SRAM has been modified ***");
|
||||
else if (genromsize) sprintf (menutitle, "%d FPS",fps);
|
||||
|
||||
ret = domenu (&items[0], count, 0);
|
||||
switch (ret)
|
||||
|
@ -130,6 +130,10 @@ int main (int argc, char *argv[])
|
||||
DI_Init();
|
||||
#endif
|
||||
|
||||
uint32 RenderedFrames;
|
||||
uint32 TotalFrames;
|
||||
uint32 FramesPerSecond;
|
||||
|
||||
/* initialize OGC subsystems */
|
||||
ogc_video__init();
|
||||
ogc_input__init();
|
||||
@ -192,11 +196,14 @@ int main (int argc, char *argv[])
|
||||
ogc_video__stop();
|
||||
|
||||
/* go to menu */
|
||||
MainMenu ();
|
||||
MainMenu (FramesPerSecond);
|
||||
ConfigRequested = 0;
|
||||
|
||||
/* reset frame sync */
|
||||
frameticker = 0;
|
||||
frameticker = 0;
|
||||
RenderedFrames = 0;
|
||||
TotalFrames = 0;
|
||||
FramesPerSecond = vdp_rate;
|
||||
|
||||
/* start Audio & Video */
|
||||
ogc_audio__start();
|
||||
@ -223,9 +230,18 @@ int main (int argc, char *argv[])
|
||||
/* update video & audio */
|
||||
ogc_audio__update();
|
||||
ogc_video__update();
|
||||
RenderedFrames++;
|
||||
}
|
||||
|
||||
frameticker--;
|
||||
|
||||
TotalFrames++;
|
||||
if (TotalFrames == vdp_rate)
|
||||
{
|
||||
FramesPerSecond = RenderedFrames;
|
||||
RenderedFrames = 0;
|
||||
TotalFrames = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -534,11 +534,14 @@ static void gxReset(void)
|
||||
if (rmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||
else while (VIDEO_GetNextField() != odd_frame) VIDEO_WaitVSync();
|
||||
|
||||
/* resynchronize field & restore VSYNC handler */
|
||||
whichfb = odd_frame;
|
||||
VIDEO_SetPreRetraceCallback(xfb_swap);
|
||||
VIDEO_Flush();
|
||||
VIDEO_WaitVSync();
|
||||
/* resynchronize interlaced field */
|
||||
if (interlaced && !config.render)
|
||||
{
|
||||
whichfb = odd_frame;
|
||||
VIDEO_SetPreRetraceCallback(xfb_swap);
|
||||
VIDEO_Flush();
|
||||
VIDEO_WaitVSync();
|
||||
}
|
||||
}
|
||||
|
||||
/* Set Menu Video mode */
|
||||
@ -560,8 +563,8 @@ void ogc_video__stop(void)
|
||||
void ogc_video__start()
|
||||
{
|
||||
/* clear screen */
|
||||
VIDEO_ClearFrameBuffer(vmode, xfb[whichfb], COLOR_BLACK);
|
||||
VIDEO_ClearFrameBuffer(vmode, xfb[whichfb], COLOR_BLACK);
|
||||
VIDEO_ClearFrameBuffer(vmode, xfb[0], COLOR_BLACK);
|
||||
VIDEO_ClearFrameBuffer(vmode, xfb[1], COLOR_BLACK);
|
||||
VIDEO_Flush();
|
||||
VIDEO_WaitVSync();
|
||||
|
||||
@ -654,14 +657,29 @@ void ogc_video__update()
|
||||
draw_square ();
|
||||
GX_DrawDone ();
|
||||
|
||||
/* special case: interlaced display */
|
||||
if (interlaced && !config.render && (odd_frame == whichfb))
|
||||
/* single-field interlaced display requires proper sync*/
|
||||
if (interlaced && !config.render)
|
||||
{
|
||||
/* resynchronize frame emulation */
|
||||
odd_frame = whichfb ^1;
|
||||
/* desync */
|
||||
if (odd_frame == whichfb)
|
||||
{
|
||||
/* force field resync */
|
||||
odd_frame = whichfb ^ 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* copy EFB to proper XFB */
|
||||
GX_CopyDisp (xfb[whichfb], GX_TRUE);
|
||||
GX_Flush ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* swap XFB */
|
||||
whichfb ^= 1;
|
||||
VIDEO_SetNextFramebuffer (xfb[whichfb]);
|
||||
VIDEO_Flush ();
|
||||
|
||||
/* copy EFB to current XFB */
|
||||
GX_CopyDisp (xfb[whichfb], GX_TRUE);
|
||||
GX_Flush ();
|
||||
|
@ -30,7 +30,7 @@ extern void reloadrom();
|
||||
extern void ClearGGCodes();
|
||||
extern void GetGGEntries();
|
||||
extern void legal();
|
||||
extern void MainMenu();
|
||||
extern void MainMenu(u32 fps);
|
||||
extern void set_region();
|
||||
extern int ManageSRAM(u8 direction, u8 device);
|
||||
extern int ManageState(u8 direction, u8 device);
|
||||
|
@ -115,8 +115,8 @@
|
||||
#include "shared.h"
|
||||
|
||||
/* globals */
|
||||
#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */
|
||||
#define EG_SH 16 /* 16.16 fixed point (envelope generator timing) */
|
||||
#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */
|
||||
#define EG_SH 16 /* 16.16 fixed point (envelope generator timing) */
|
||||
#define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */
|
||||
#define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */
|
||||
|
||||
@ -586,8 +586,8 @@ typedef struct
|
||||
/***********************************************************/
|
||||
typedef struct
|
||||
{
|
||||
FM_CH CH[6]; /* channel state */
|
||||
UINT8 dacen; /* DAC mode */
|
||||
FM_CH CH[6]; /* channel state */
|
||||
UINT8 dacen; /* DAC mode */
|
||||
INT32 dacout; /* DAC output */
|
||||
FM_OPN OPN; /* OPN state */
|
||||
} YM2612;
|
||||
@ -599,7 +599,7 @@ static YM2612 ym2612;
|
||||
static INT32 m2,c1,c2; /* Phase Modulation input for operators 2,3,4 */
|
||||
static INT32 mem; /* one sample delay memory */
|
||||
static INT32 out_fm[8]; /* outputs of working channels */
|
||||
static UINT32 LFO_AM; /* runtime LFO calculations helper */
|
||||
static UINT32 LFO_AM; /* runtime LFO calculations helper */
|
||||
static INT32 LFO_PM; /* runtime LFO calculations helper */
|
||||
|
||||
|
||||
@ -922,20 +922,20 @@ INLINE void advance_eg_channel(FM_SLOT *SLOT)
|
||||
break;
|
||||
|
||||
case EG_DEC: /* decay phase */
|
||||
if ( !(ym2612.OPN.eg_cnt & ((1<<SLOT->eg_sh_d1r)-1) ) )
|
||||
{
|
||||
if ( !(ym2612.OPN.eg_cnt & ((1<<SLOT->eg_sh_d1r)-1) ) )
|
||||
{
|
||||
if (SLOT->ssg&0x08) /* SSG EG type envelope selected */
|
||||
SLOT->volume += 6 * eg_inc[SLOT->eg_sel_d1r + ((ym2612.OPN.eg_cnt>>SLOT->eg_sh_d1r)&7)];
|
||||
else
|
||||
else
|
||||
SLOT->volume += eg_inc[SLOT->eg_sel_d1r + ((ym2612.OPN.eg_cnt>>SLOT->eg_sh_d1r)&7)];
|
||||
}
|
||||
|
||||
/* check transition even if no volume update: this fixes the case when SL = MIN_ATT_INDEX */
|
||||
if ( SLOT->volume >= (INT32)(SLOT->sl) )
|
||||
{
|
||||
SLOT->volume = (INT32)(SLOT->sl);
|
||||
SLOT->state = EG_SUS;
|
||||
}
|
||||
if ( SLOT->volume >= (INT32)(SLOT->sl) )
|
||||
{
|
||||
SLOT->volume = (INT32)(SLOT->sl);
|
||||
SLOT->state = EG_SUS;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@ -991,8 +991,8 @@ INLINE void advance_eg_channel(FM_SLOT *SLOT)
|
||||
if ( SLOT->volume >= MAX_ATT_INDEX )
|
||||
SLOT->volume = MAX_ATT_INDEX;
|
||||
/* do not change SLOT->state (verified on real chip) */
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EG_REL: /* release phase */
|
||||
@ -1011,7 +1011,6 @@ INLINE void advance_eg_channel(FM_SLOT *SLOT)
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
unsigned int out = (UINT32)SLOT->volume;
|
||||
@ -1229,7 +1228,8 @@ INLINE void refresh_fc_eg_slot(FM_SLOT *SLOT , int fc , int kc )
|
||||
/* update phase increment counters */
|
||||
INLINE void refresh_fc_eg_chan(FM_CH *CH )
|
||||
{
|
||||
if( CH->SLOT[SLOT1].Incr==-1){
|
||||
if( CH->SLOT[SLOT1].Incr==-1)
|
||||
{
|
||||
int fc = CH->fc;
|
||||
int kc = CH->kcode;
|
||||
refresh_fc_eg_slot(&CH->SLOT[SLOT1] , fc , kc );
|
||||
@ -1380,20 +1380,20 @@ INLINE void CSMKeyControll(FM_CH *CH)
|
||||
|
||||
if (!CH->SLOT[SLOT2].key)
|
||||
{
|
||||
FM_KEYON(CH,SLOT2);
|
||||
FM_KEYON(CH,SLOT2);
|
||||
FM_KEYOFF(CH,SLOT2);
|
||||
}
|
||||
|
||||
if (!CH->SLOT[SLOT3].key)
|
||||
{
|
||||
FM_KEYON(CH,SLOT3);
|
||||
FM_KEYON(CH,SLOT3);
|
||||
FM_KEYOFF(CH,SLOT3);
|
||||
}
|
||||
|
||||
if (!CH->SLOT[SLOT4].key)
|
||||
{
|
||||
FM_KEYON(CH,SLOT4);
|
||||
FM_KEYOFF(CH,SLOT4);
|
||||
FM_KEYON(CH,SLOT4);
|
||||
FM_KEYOFF(CH,SLOT4);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1662,8 +1662,8 @@ static void OPNWriteReg(int r, int v)
|
||||
CH->block_fnum = (blk<<11) | fn;
|
||||
|
||||
CH->SLOT[SLOT1].Incr=-1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: /* 0xa4-0xa6 : FNUM2,BLK */
|
||||
ym2612.OPN.ST.fn_h = v&0x3f;
|
||||
break;
|
||||
@ -1695,8 +1695,8 @@ static void OPNWriteReg(int r, int v)
|
||||
CH->ALGO = v&7;
|
||||
CH->FB = feedback ? feedback+6 : 0;
|
||||
setup_connection( CH, c );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (ym2612/YM2610B/YM2610/YM2608) */
|
||||
/* b0-2 PMS */
|
||||
CH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */
|
||||
@ -1707,7 +1707,6 @@ static void OPNWriteReg(int r, int v)
|
||||
/* PAN : b7 = L, b6 = R */
|
||||
ym2612.OPN.pan[ c*2 ] = (v & 0x80) ? ~0 : 0;
|
||||
ym2612.OPN.pan[ c*2+1 ] = (v & 0x40) ? ~0 : 0;
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -130,7 +130,7 @@ int system_frame (int do_skip)
|
||||
/* parse sprites for line 0 (done on last line) */
|
||||
parse_satb (0x80);
|
||||
|
||||
/* process frame */
|
||||
/* process scanlines */
|
||||
for (line = 0; line < lines_per_frame; line ++)
|
||||
{
|
||||
/* update VCounter */
|
||||
|
12
source/vdp.c
12
source/vdp.c
@ -1,4 +1,4 @@
|
||||
/***************************************************************************************
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* Video Display Processor (memory handlers)
|
||||
*
|
||||
@ -338,7 +338,7 @@ static inline void dma_copy(void)
|
||||
int source = (reg[22] << 8 | reg[21]) & 0xFFFF;
|
||||
if (!length) length = 0x10000;
|
||||
|
||||
dma_type = 3;
|
||||
dma_type = 3;
|
||||
dma_length = length;
|
||||
dma_update();
|
||||
|
||||
@ -623,7 +623,7 @@ static inline void vdp_reg_w(unsigned int r, unsigned int d)
|
||||
/* Check if Mode 4 (SMS mode) has been activated
|
||||
According to official doc, VDP registers #11 to #23 can not be written unless bit2 in register #1 is set
|
||||
Fix Captain Planet & Avengers (Alt version), Bass Master Classic Pro Edition (they incidentally activate Mode 4)
|
||||
*/
|
||||
*/
|
||||
if (!(reg[1] & 4) && (r > 10)) return;
|
||||
|
||||
switch(r)
|
||||
@ -887,7 +887,7 @@ unsigned int vdp_data_r(void)
|
||||
}
|
||||
|
||||
/* Increment address register */
|
||||
addr += reg[15];
|
||||
addr += reg[15];
|
||||
|
||||
/* return data */
|
||||
return (temp);
|
||||
@ -898,7 +898,7 @@ unsigned int vdp_hvc_r(void)
|
||||
uint8 hc = (hc_latch & 0x100) ? (hc_latch & 0xFF) : hctab[count_m68k % m68cycles_per_line];
|
||||
uint8 vc = vctab[v_counter];
|
||||
|
||||
/* interlace mode 2 */
|
||||
/* interlace mode 2 */
|
||||
if (im2_flag) vc = (vc << 1) | ((vc >> 7) & 1);
|
||||
|
||||
return ((vc << 8) | hc);
|
||||
@ -908,7 +908,7 @@ unsigned int vdp_hvc_r(void)
|
||||
void vdp_test_w(unsigned int value)
|
||||
{
|
||||
#ifdef LOGERROR
|
||||
error("Unused VDP Write 0x%x (%08x)", value, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
error("Unused VDP Write 0x%x (%08x)\n", value, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user