in cores/pce/mednafen/pce_fast/vdc.cpp [730:1034]
void VDC_RunFrame(EmulateSpecStruct *espec, bool IsHES)
{
int max_dc = 0;
MDFN_Surface *surface = espec->surface;
MDFN_Rect *DisplayRect = &espec->DisplayRect;
int32 *LineWidths = espec->LineWidths;
bool skip = espec->skip || IsHES;
if(!skip){
DisplayRect->y = MDFN_GetSettingUI("pce_fast.slstart");
DisplayRect->h = MDFN_GetSettingUI("pce_fast.slend") - DisplayRect->y + 1;
}
//Change 352 mode width without restart
if (defined_width[1] != MDFN_GetSettingUI("pce_fast.hoverscan"))
defined_width[1] = MDFN_GetSettingUI("pce_fast.hoverscan");
do
{
const bool SHOULD_DRAW = (!skip && (int)frame_counter >= (DisplayRect->y + 14) && (int)frame_counter < (DisplayRect->y + DisplayRect->h + 14));
if(frame_counter == 0)
{
VDS = M_vdc_VDS;
VSW = M_vdc_VSW;
VDW = M_vdc_VDW;
VCR = M_vdc_VCR;
VBlankFL = VDS + VSW + VDW + 1;
if(VBlankFL > 261)
VBlankFL = 261;
}
need_vbi[0] = need_vbi[1] = 0;
#if 1
line_leadin1 = 0;
magical = M_vdc_HDS + (M_vdc_HDW + 1) + M_vdc_HDE;
magical = (magical + 2) & ~1;
magical -= M_vdc_HDW + 1;
cyc_tot = magical * 8; //ClockPixelWidths[vce.dot_clock] - magical * 8;
cyc_tot-=2;
switch(vce.dot_clock)
{
case 0: cyc_tot = 4 * cyc_tot / 3; break;
case 1: break;
case 2: cyc_tot = 2 * cyc_tot / 3; break;
}
if(cyc_tot < 0) cyc_tot = 0;
line_leadin1 = cyc_tot;
#endif
#if 0
{
int vdc_to_master = 4;
line_leadin1 = 1365 - ((M_vdc_HDW + 1) * 8 - 4 + 6) * vdc_to_master;
if(line_leadin1 < 0)
{
line_leadin1 = 0;
puts("Eep");
}
if(M_vdc_HDS > 2)
line_leadin1 += 2;
line_leadin1 = line_leadin1 / 3;
}
if(line_leadin1 < 0)
line_leadin1 = 0;
else if(line_leadin1 > 400)
line_leadin1 = 400;
#endif
//printf("%d\n", line_leadin1);
if(max_dc < vce.dot_clock)
max_dc = vce.dot_clock;
if(!skip)
{
DisplayRect->x = 0;
DisplayRect->w = defined_width[vce.dot_clock];
}
int chip = 0;
{
if(frame_counter == 0)
{
vdc->display_counter = 0;
vdc->burst_mode = !(vdc->CR & 0xC0);
}
if(vdc->display_counter == (VDS + VSW))
{
vdc->burst_mode = !(vdc->CR & 0xC0);
vdc->RCRCount = 0;
}
int have_free_time = 1;
if(!vdc->burst_mode && vdc->display_counter >= (VDS + VSW) && vdc->display_counter < (VDS + VSW + VDW + 1))
have_free_time = 0;
if(have_free_time) // We're outside of the active display area. Weehee
{
if(vdc->DMARunning)
DoDMA(vdc);
}
if(vdc->display_counter == VBlankFL)
{
need_vbi[0] = 1;
if(vdc->SATBPending || (vdc->DCR & 0x10))
{
vdc->SATBPending = 0;
vdc->sat_dma_slcounter = 2;
DoSATDMA(vdc);
}
}
if((int)vdc->RCRCount == ((int)vdc->RCR - 0x40) && (vdc->CR & 0x04))
{
VDC_DEBUG("RCR IRQ");
vdc->status |= VDCS_RR;
HuC6280_IRQBegin(MDFN_IQIRQ1);
}
}
HuC6280_Run(line_leadin1);
const bool fc_vrm = (frame_counter >= 14 && frame_counter < (14 + 242 + 1));
chip = 0;
{
MDFN_ALIGN(8) uint8 bg_linebuf[8 + 1024];
MDFN_ALIGN(8) uint16 spr_linebuf[16 + 1024];
uint16 *target_ptr16 = surface->pixels + (frame_counter - 14) * surface->pitch;
if(fc_vrm && !skip)
LineWidths[frame_counter - 14] = DisplayRect->w;
if(vdc->burst_mode)
{
if(fc_vrm && SHOULD_DRAW)
{
DrawOverscan(vdc, target_ptr16, DisplayRect);
}
}
else if(vdc->display_counter >= (VDS + VSW) && vdc->display_counter < (VDS + VSW + VDW + 1))
{
if(vdc->display_counter == (VDS + VSW))
vdc->BG_YOffset = vdc->BYR;
else
vdc->BG_YOffset++;
vdc->BG_XOffset = vdc->BXR;
if(fc_vrm)
{
uint32 start = (M_vdc_HDS + 1) * 8;
uint32 end = start + (M_vdc_HDW + 1) * 8;
if((vdc->CR & 0x80) && SHOULD_DRAW)
{
if(userle & (ULE_BG0))
DrawBG(vdc, end - start + (vdc->BG_XOffset & 7), bg_linebuf);
else
memset(bg_linebuf, 0, end - start + (vdc->BG_XOffset & 7));
}
if((vdc->CR & 0x40) && (SHOULD_DRAW || (vdc->CR & 0x03))) // Don't skip sprite drawing if we can generate sprite #0 or sprite overflow IRQs.
{
if((userle & (ULE_SPR0)) || (vdc->CR & 0x03))
DrawSprites(vdc, end - start, spr_linebuf + 0x20);
if(!(userle & (ULE_SPR0)))
memset(spr_linebuf + 0x20, 0, sizeof(uint16) * (end - start));
}
if(SHOULD_DRAW){
int32 width = end - start;
int32 source_offset = 0;
int32 target_offset = 0;
//Centre any picture thinner than its display mode width
if(width > 0 && width < defined_width[vce.dot_clock]){
target_offset = (defined_width[vce.dot_clock] - width)/2;
}
//Centre overscan cropping
if(vce.dot_clock == 1 && defined_width[1] < width){
target_offset += (defined_width[1] - width) / 2;
}
// Align TV Sport Basketball
if(vce.dot_clock ==2 && width > 512){
target_offset = - 16;
}
// Semi-hack for Asuka 120%
if(vce.dot_clock == 1 && M_vdc_HDS == 5 && M_vdc_HDE == 6 && M_vdc_HDW == 43 && M_vdc_HSW == 2)
target_offset += 8;
else if(vce.dot_clock == 0 && M_vdc_HDS == 2 && M_vdc_HDE == 3 && M_vdc_HDW == 33 && M_vdc_HSW == 2)
target_offset = 0;
// and for Addams Family
else if(vce.dot_clock == 1 && M_vdc_HDS == 4 && M_vdc_HDE == 4 && M_vdc_HDW == 43 && M_vdc_HSW == 9)
target_offset += 4;
if(target_offset < 0)
{
width += target_offset;
source_offset += 0 - target_offset;
target_offset = 0;
}
if((target_offset + width) > DisplayRect->w)
width = (int32)DisplayRect->w - target_offset;
if(width > 0)
{
//else if(target_ptr16)
{
switch(vdc->CR & 0xC0)
{
case 0xC0:
MixBGSPR(width, bg_linebuf + (vdc->BG_XOffset & 7) + source_offset, spr_linebuf + 0x20 + source_offset, target_ptr16 + target_offset);
break;
case 0x80:
MixBGOnly(width, bg_linebuf + (vdc->BG_XOffset & 7) + source_offset, target_ptr16 + target_offset);
break;
case 0x40:
MixSPROnly(width, spr_linebuf + 0x20 + source_offset, target_ptr16 + target_offset);
break;
case 0x00:
MixNone(width, target_ptr16 + target_offset);
break;
}
}
}
//else if(target_ptr16)
DrawOverscan(vdc, target_ptr16, DisplayRect, false, target_offset, target_offset + width);
} // end if(SHOULD_DRAW)
}
}
else if(SHOULD_DRAW && fc_vrm) // Hmm, overscan...
{
//else if(target_ptr16)
DrawOverscan(vdc, target_ptr16, DisplayRect);
}
}
if((vdc->CR & 0x08) && need_vbi[0])
vdc->status |= VDCS_VD;
HuC6280_Run(2);
if(vdc->status & VDCS_VD)
{
VDC_DEBUG("VBlank IRQ");
HuC6280_IRQBegin(MDFN_IQIRQ1);
}
HuC6280_Run(455 - line_leadin1 - 2);
if(PCE_IsCD)
{
PCECD_Run(HuCPU.timestamp * 3);
}
{
vdc->RCRCount++;
//vdc->BG_YOffset = (vdc->BG_YOffset + 1);
vdc->display_counter++;
if(vdc->sat_dma_slcounter)
{
vdc->sat_dma_slcounter--;
if(!vdc->sat_dma_slcounter)
{
if(vdc->DCR & 0x01)
{
VDC_DEBUG("Sprite DMA IRQ");
vdc->status |= VDCS_DS;
HuC6280_IRQBegin(MDFN_IQIRQ1);
}
}
}
if(vdc->display_counter == (VDS + VSW + VDW + VCR + 3))
{
vdc->display_counter = 0;
}
}
frame_counter = (frame_counter + 1) % (vce.lc263 ? 263 : 262);
//printf("%d\n", vce.lc263);
} while(frame_counter != VBlankFL); // big frame loop!
DisplayRect->w = defined_width[vce.dot_clock];
}