//called from sh4 context , should update pvr/ta state and everything else int spg_line_sched(int tag, int cycl, int jit) { clc_pvr_scanline += cycl; while (clc_pvr_scanline >= Line_Cycles)//60 ~hertz = 200 mhz / 60=3333333.333 cycles per screen refresh { //ok .. here , after much effort , we did one line //now , we must check for raster beam interrupts and vblank prv_cur_scanline=(prv_cur_scanline+1)%pvr_numscanlines; clc_pvr_scanline -= Line_Cycles; //Check for scanline interrupts -- really need to test the scanline values if (SPG_VBLANK_INT.vblank_in_interrupt_line_number == prv_cur_scanline) asic_RaiseInterrupt(holly_SCANINT1); if (SPG_VBLANK_INT.vblank_out_interrupt_line_number == prv_cur_scanline) asic_RaiseInterrupt(holly_SCANINT2); if (SPG_VBLANK.vstart == prv_cur_scanline) in_vblank=1; if (SPG_VBLANK.vbend == prv_cur_scanline) in_vblank=0; SPG_STATUS.vsync=in_vblank; SPG_STATUS.scanline=prv_cur_scanline; //Vblank start -- really need to test the scanline values if (prv_cur_scanline==0) { if (SPG_CONTROL.interlace) SPG_STATUS.fieldnum=~SPG_STATUS.fieldnum; else SPG_STATUS.fieldnum=0; //Vblank counter vblk_cnt++; asic_RaiseInterrupt(holly_HBLank);// -> This turned out to be HBlank btw , needs to be emulated ;( //TODO : rend_if_VBlank(); rend_vblank();//notify for vblank :) if ((os_GetSeconds()-last_fps)>2) { static int Last_FC; double ts=os_GetSeconds()-last_fps; double spd_fps=(FrameCount-Last_FC)/ts; double spd_vbs=vblk_cnt/ts; double spd_cpu=spd_vbs*Frame_Cycles; spd_cpu/=1000000; //mrhz kthx double fullvbs=(spd_vbs/spd_cpu)*200; double mv=VertexCount/ts/(spd_cpu/200); char mv_c=' '; Last_FC=FrameCount; if (mv>750) { mv/=1000; //KV mv_c='K'; } if (mv>750) { mv/=1000; // mv_c='M'; } VertexCount=0; vblk_cnt=0; char fpsStr[256]; const char* mode=0; const char* res=0; res=SPG_CONTROL.interlace?"480i":"240p"; if (SPG_CONTROL.NTSC==0 && SPG_CONTROL.PAL==1) mode="PAL"; else if (SPG_CONTROL.NTSC==1 && SPG_CONTROL.PAL==0) mode="NTSC"; else { res=SPG_CONTROL.interlace?"480i":"480p"; mode="VGA"; } double frames_done=spd_cpu/2; double mspdf=1/frames_done*1000; full_rps=(spd_fps+fskip/ts); #ifdef TARGET_PANDORA sprintf(fpsStr,"CPU: %4.2f V: %4.2f (%s%s%4.2f) R: %4.2f+%4.2f", spd_cpu*100/200,spd_vbs, mode,res,fullvbs, spd_fps,fskip/ts); #else sprintf(fpsStr,"%s/%c - %4.2f (%4.2f) - %4.2f - V: %4.2f (%.2f, %s%s%4.2f) R: %4.2f+%4.2f VTX: %4.2f%c", VER_SHORTNAME,'n',mspdf,speed_load_mspdf,spd_cpu*100/200,spd_vbs, spd_vbs/full_rps,mode,res,fullvbs, spd_fps,fskip/ts ,mv,mv_c); #endif fskip=0; os_SetWindowText(fpsStr); last_fps=os_GetSeconds(); } } } //interrupts //0 //vblank_in_interrupt_line_number //vblank_out_interrupt_line_number //vstart //vbend //pvr_numscanlines u32 min_scanline=prv_cur_scanline+1; u32 min_active=pvr_numscanlines; if (min_scanline<SPG_VBLANK_INT.vblank_in_interrupt_line_number) min_active=min(min_active,SPG_VBLANK_INT.vblank_in_interrupt_line_number); if (min_scanline<SPG_VBLANK_INT.vblank_out_interrupt_line_number) min_active=min(min_active,SPG_VBLANK_INT.vblank_out_interrupt_line_number); if (min_scanline<SPG_VBLANK.vstart) min_active=min(min_active,SPG_VBLANK.vstart); if (min_scanline<SPG_VBLANK.vbend) min_active=min(min_active,SPG_VBLANK.vbend); if (min_scanline<pvr_numscanlines) min_active=min(min_active,pvr_numscanlines); min_active=max(min_active,min_scanline); return (min_active-prv_cur_scanline)*Line_Cycles; }
//called from sh4 context , should update pvr/ta state and everything else void FASTCALL spgUpdatePvr(u32 cycles) { if (Line_Cycles==0) return; clc_pvr_scanline += cycles; if (clc_pvr_scanline > Line_Cycles)//60 ~herz = 200 mhz / 60=3333333.333 cycles per screen refresh { //ok .. here , after much effort , we did one line //now , we must check for raster beam interrupts and vblank prv_cur_scanline=(prv_cur_scanline+1)%pvr_numscanlines; clc_pvr_scanline -= Line_Cycles; //Check for scanline interrupts -- really need to test the scanline values if (SPG_VBLANK_INT.vblank_in_interrupt_line_number == prv_cur_scanline) params.RaiseInterrupt(holly_SCANINT1); if (SPG_VBLANK_INT.vblank_out_interrupt_line_number == prv_cur_scanline) params.RaiseInterrupt(holly_SCANINT2); if (SPG_VBLANK.vstart == prv_cur_scanline) in_vblank=1; if (SPG_VBLANK.vbend == prv_cur_scanline) in_vblank=0; if (SPG_CONTROL.interlace) SPG_STATUS.fieldnum=~SPG_STATUS.fieldnum; else SPG_STATUS.fieldnum=0; SPG_STATUS.vsync=in_vblank; SPG_STATUS.scanline=prv_cur_scanline; //Vblank start -- really need to test the scanline values if (prv_cur_scanline==0) { //Vblank counter vblk_cnt++; params.RaiseInterrupt(holly_HBLank);// -> This turned out to be HBlank btw , needs to be emulated ;( //TODO : rend_if_VBlank(); rend_vblank();//notify for vblank :) UpdateRRect(); if ((timeGetTime()-last_fps)>1000) { double spd_fps=(double)(FrameCount)/(double)((double)(timeGetTime()-(double)last_fps)/1000); double spd_vbs=(double)(vblk_cnt)/(double)((double)(timeGetTime()-(double)last_fps)/1000); double spd_cpu=spd_vbs*Frame_Cycles; spd_cpu/=1000000; //mrhz kthx double fullvbs=(spd_vbs/spd_cpu)*200; double mv=VertexCount; char mv_c=' '; if (mv>750) { mv/=1000; //KV mv_c='K'; } if (mv>750) { mv/=1000; // mv_c='M'; } VertexCount=0; last_fps=timeGetTime(); FrameCount=0; vblk_cnt=0; wchar fpsStr[256]; wchar* mode=0; wchar* res=0; res=SPG_CONTROL.interlace?L"480i":L"240p"; if (SPG_CONTROL.NTSC==0 && SPG_CONTROL.PAL==1) mode=L"PAL"; else if (SPG_CONTROL.NTSC==1 && SPG_CONTROL.PAL==0) mode=L"NTSC"; else { res=SPG_CONTROL.interlace?L"480i":L"480p"; mode=L"VGA"; } swprintf(fpsStr,256,L"%s/%c - %4.2f%% - VPS: %4.2f(%s%s%4.2f) RPS: %4.2f Vert: %4.2f%c Sh4: %4.2f mhz", emu_name,'n',spd_cpu*100/200,spd_vbs, mode,res,fullvbs, spd_fps,mv,mv_c, spd_cpu); if (GetWindowLong((HWND)emu.GetRenderTarget(),GWL_STYLE)&WS_BORDER) { SetWindowText((HWND)emu.GetRenderTarget(), fpsStr); } } } } if (render_end_pending) { if (render_end_pending_cycles<cycles) { render_end_pending=false; params.RaiseInterrupt(holly_RENDER_DONE); params.RaiseInterrupt(holly_RENDER_DONE_isp); params.RaiseInterrupt(holly_RENDER_DONE_vd); rend_end_render(); } render_end_pending_cycles-=cycles; } }
//called from sh4 context , should update pvr/ta state and everything else int spg_line_sched(int tag, int cycl, int jit) { clc_pvr_scanline += cycl; while (clc_pvr_scanline >= Line_Cycles)//60 ~hertz = 200 mhz / 60=3333333.333 cycles per screen refresh { //ok .. here , after much effort , we did one line //now , we must check for raster beam interrupts and vblank prv_cur_scanline = (prv_cur_scanline+1) % pvr_numscanlines; clc_pvr_scanline -= Line_Cycles; //Check for scanline interrupts -- really need to test the scanline values /* Vblank in */ if (SPG_VBLANK_INT.vblank_in_interrupt_line_number == prv_cur_scanline) asic_RaiseInterrupt(holly_SCANINT1); /* Vblank Out */ if (SPG_VBLANK_INT.vblank_out_interrupt_line_number == prv_cur_scanline) asic_RaiseInterrupt(holly_SCANINT2); if (SPG_VBLANK.vstart == prv_cur_scanline) in_vblank = 1; if (SPG_VBLANK.vbend == prv_cur_scanline) in_vblank = 0; SPG_STATUS.vsync = in_vblank; SPG_STATUS.scanline = prv_cur_scanline; //Vblank start -- really need to test the scanline values if (prv_cur_scanline==0) { if (SPG_CONTROL.interlace) SPG_STATUS.fieldnum = ~SPG_STATUS.fieldnum; else SPG_STATUS.fieldnum=0; /* Vblank counter */ vblk_cnt++; asic_RaiseInterrupt(holly_HBLank); /* HBlank in */ rend_vblank(); // notify for vblank } if (lightgun_line != 0xffff && lightgun_line == prv_cur_scanline) { SPG_TRIGGER_POS = ((lightgun_line & 0x3FF) << 16) | (lightgun_hpos & 0x3FF); asic_RaiseInterrupt(holly_MAPLE_DMA); lightgun_line = 0xffff; } } //interrupts //0 //vblank_in_interrupt_line_number //vblank_out_interrupt_line_number //vstart //vbend //pvr_numscanlines u32 min_scanline=prv_cur_scanline+1; u32 min_active=pvr_numscanlines; if (min_scanline < SPG_VBLANK_INT.vblank_in_interrupt_line_number) min_active=min(min_active,SPG_VBLANK_INT.vblank_in_interrupt_line_number); if (min_scanline < SPG_VBLANK_INT.vblank_out_interrupt_line_number) min_active=min(min_active,SPG_VBLANK_INT.vblank_out_interrupt_line_number); if (min_scanline < SPG_VBLANK.vstart) min_active=min(min_active,SPG_VBLANK.vstart); if (min_scanline < SPG_VBLANK.vbend) min_active=min(min_active,SPG_VBLANK.vbend); if (min_scanline < pvr_numscanlines) min_active=min(min_active,pvr_numscanlines); min_active=max(min_active,min_scanline); return (min_active-prv_cur_scanline)*Line_Cycles; }
//called from sh4 context , should update pvr/ta state and everything else static int spg_line_sched(int tag, int cycl, int jit) { clc_pvr_scanline += cycl; while (clc_pvr_scanline >= Line_Cycles)//60 ~hertz = 200 mhz / 60=3333333.333 cycles per screen refresh { //ok .. here , after much effort , we did one line //now , we must check for raster beam interrupts and vblank prv_cur_scanline = (prv_cur_scanline+1) % pvr_numscanlines; clc_pvr_scanline -= Line_Cycles; //Check for scanline interrupts -- really need to test the scanline values if (SPG_VBLANK_INT.vblank_in_interrupt_line_number == prv_cur_scanline) asic_RaiseInterrupt(holly_SCANINT1); if (SPG_VBLANK_INT.vblank_out_interrupt_line_number == prv_cur_scanline) asic_RaiseInterrupt(holly_SCANINT2); if (SPG_VBLANK.vstart == prv_cur_scanline) in_vblank = 1; if (SPG_VBLANK.vbend == prv_cur_scanline) in_vblank = 0; SPG_STATUS.vsync = in_vblank; SPG_STATUS.scanline = prv_cur_scanline; //Vblank start -- really need to test the scanline values if (prv_cur_scanline==0) { SPG_STATUS.fieldnum = 0; if (SPG_CONTROL.interlace) SPG_STATUS.fieldnum = ~SPG_STATUS.fieldnum; /* Vblank counter */ vblk_cnt++; asic_RaiseInterrupt(holly_HBLank);// -> This turned out to be HBlank btw , needs to be emulated ;( //TODO : rend_if_VBlank(); rend_vblank();//notify for vblank :) } } //interrupts //0 //vblank_in_interrupt_line_number //vblank_out_interrupt_line_number //vstart //vbend //pvr_numscanlines u32 min_scanline=prv_cur_scanline+1; u32 min_active=pvr_numscanlines; if (min_scanline<SPG_VBLANK_INT.vblank_in_interrupt_line_number) min_active=min(min_active,SPG_VBLANK_INT.vblank_in_interrupt_line_number); if (min_scanline<SPG_VBLANK_INT.vblank_out_interrupt_line_number) min_active=min(min_active,SPG_VBLANK_INT.vblank_out_interrupt_line_number); if (min_scanline<SPG_VBLANK.vstart) min_active=min(min_active,SPG_VBLANK.vstart); if (min_scanline<SPG_VBLANK.vbend) min_active=min(min_active,SPG_VBLANK.vbend); if (min_scanline<pvr_numscanlines) min_active=min(min_active,pvr_numscanlines); min_active=max(min_active,min_scanline); return (min_active-prv_cur_scanline)*Line_Cycles; }