@@ -340,6 +340,7 @@ wmsx.V9990 = function() {
340340 kanjiPort2Address = 0x20000 ;
341341
342342 softReset ( ) ;
343+ updateSignalMetrics ( true ) ;
343344
344345 frame = cycles = lastBUSCyclesComputed = 0 ;
345346 frameVideoStandard = videoStandard ; framePulldown = pulldown ;
@@ -349,6 +350,8 @@ wmsx.V9990 = function() {
349350 } ;
350351
351352 function softReset ( ) {
353+ // wmsx.Util.error("V9990 Soft Reset. CurrentScanline: " + currentScanline);
354+
352355 interruptFlags = 0 ;
353356 vramPointerRead = 0 ; vramPointerWrite = 0 ; vramPointerReadInc = true ; vramPointerWriteInc = true ; vramReadData = 0 ;
354357 palettePointer = 0 ; palettePointerReadInc = true ;
@@ -366,7 +369,6 @@ wmsx.V9990 = function() {
366369 commandProcessor . reset ( ) ;
367370
368371 initRegisters ( ) ;
369- updateSignalMetrics ( true ) ;
370372 updateIRQ ( ) ;
371373 updateMode ( true ) ;
372374 updateBackdropColor ( ) ;
@@ -629,7 +631,7 @@ wmsx.V9990 = function() {
629631 } ;
630632
631633 // Total line clocks: V9990: 1368, CPU: 228
632- // Timing for HR/VR should be different for Normal and Oversan modes. Ignoring for now
634+ // Timing for HR/VR should be different for Normal and Overscan/Highscan modes. Ignoring for now
633635
634636 this . lineEventStartActiveDisplay = function ( ) {
635637 status &= ~ 0x20 ; // HR = 0
@@ -647,6 +649,12 @@ wmsx.V9990 = function() {
647649 } ;
648650
649651 this . lineEventEndActiveDisplay = function ( ) {
652+ // Render extra line for Double-scan modes (High-scan modes B5, B6)
653+ if ( frameDoubleScan ) {
654+ ++ currentScanline ;
655+ this . lineEventRenderLine ( ) ;
656+ }
657+
650658 status |= 0x20 ; // HR = 1
651659
652660 if ( currentScanline - frameStartingActiveScanline === signalActiveHeight - 1 )
@@ -655,7 +663,7 @@ wmsx.V9990 = function() {
655663
656664 this . lineEventEnd = function ( ) {
657665 ++ currentScanline ;
658- if ( currentScanline >= finishingScanline ) finishFrame ( ) ;
666+ // Frame finishing controlled by VDP Genlock
659667 } ;
660668
661669 // TODO Command Completion INT is not triggered at the correct time for internal commands, only by checking status or finishing with the last CPU write/read
@@ -871,11 +879,14 @@ wmsx.V9990 = function() {
871879 startingActiveScanline = startingVisibleTopBorderScanline + border + vertAdjust ;
872880 var startingVisibleBottomBorderScanline = startingActiveScanline + signalActiveHeight ;
873881 startingInvisibleScanline = startingVisibleBottomBorderScanline + border - vertAdjust ; // Remaining left invisible: Bottom border, Bottom Erase, Sync and Top Erase
874- finishingScanline = frameVideoStandard . totalHeight ;
882+ // finishingScanline = frameVideoStandard.totalHeight; // Controlled by VDP Genlock
875883
876- if ( force ) frameStartingActiveScanline = startingActiveScanline ;
884+ if ( force ) {
885+ frameStartingActiveScanline = startingActiveScanline ;
886+ frameDoubleScan = modeData . doublesScan ;
887+ }
877888
878- // logInfo("Update Signal Metrics: " + force + ", activeHeight: " + signalActiveHeight);
889+ // logInfo("Update Signal Metrics: " + force + ", activeHeight: " + signalActiveHeight);
879890 }
880891
881892 function updateRenderMetrics ( force ) {
@@ -890,7 +901,7 @@ wmsx.V9990 = function() {
890901
891902 if ( newRenderWidth === renderWidth && newRenderHeight === renderHeight ) return ;
892903
893- // console.error("V9990 Update Render Metrics. currentScanline: " + currentScanline + ", force: " + force + " Asked: " + newRenderWidth + "x" + newRenderHeight + ", set : " + renderWidth + "x" + renderHeight);
904+ // console.error("V9990 Update Render Metrics. currentScanline: " + currentScanline + ", force: " + force + " Asked: " + newRenderWidth + "x" + newRenderHeight + ", current : " + renderWidth + "x" + renderHeight);
894905
895906 // Only change width if forced (loadState and beginFrame)
896907 if ( newRenderWidth !== renderWidth ) {
@@ -912,6 +923,8 @@ wmsx.V9990 = function() {
912923 renderMetricsUpdatePending = true ;
913924 }
914925
926+ // console.error("V9990 Update Render Metrics Set: " + renderWidth + "x" + renderHeight);
927+
915928 if ( clean ) cleanFrameBuffer ( ) ;
916929 if ( changed ) self . refreshDisplayMetrics ( ) ;
917930 }
@@ -1595,6 +1608,9 @@ wmsx.V9990 = function() {
15951608 }
15961609
15971610 function beginFrame ( ) {
1611+ // wmsx.Util.error("V9990 Begin Frame. CurrentScanline: " + currentScanline
1612+ // + ", VDP CurrentScanline: " + vdp.eval("currentScanline"));
1613+
15981614 // Adjust for pending VideoStandard/Pulldown changes
15991615 if ( framePulldown !== pulldown ) {
16001616 frameVideoStandard = videoStandard ;
@@ -1628,14 +1644,13 @@ wmsx.V9990 = function() {
16281644
16291645 currentScanline = 0 ;
16301646 frameStartingActiveScanline = startingActiveScanline ;
1647+ frameDoubleScan = modeData . doublesScan ;
16311648
16321649 if ( currentScanline >= frameStartingActiveScanline ) enterActiveDisplay ( ) ; // Overscan modes with vertical adjust can make frameStartingActiveScanline < 0
16331650 }
16341651
1635- function finishFrame ( ) {
1636- //var cpuCycles = cpu.getCycles();
1637- //wmsx.Util.log("Frame FINISHED. CurrentScanline: " + currentScanline + ", CPU cycles: " + (cpuCycles - debugFrameStartCPUCycle));
1638- //debugFrameStartCPUCycle = cpuCycles;
1652+ this . frameEventFinishFrame = function ( ) {
1653+ // wmsx.Util.error("V9990 Frame FINISHED. CurrentScanline: " + currentScanline);
16391654
16401655 // Update frame image from backbuffer
16411656 if ( videoDisplayed ) {
@@ -1649,7 +1664,7 @@ wmsx.V9990 = function() {
16491664 //logInfo("Finish Frame");
16501665
16511666 beginFrame ( ) ;
1652- }
1667+ } ;
16531668
16541669 // TODO P2 mode uses a strange RAM interleaving not completely implemented
16551670 function updateVRAMInterleaving ( ) {
@@ -1854,10 +1869,11 @@ wmsx.V9990 = function() {
18541869 var cycles = 0 , lastBUSCyclesComputed = 0 ;
18551870
18561871 var signalActiveHeight = 0 ;
1857- var finishingScanline = 0 ;
1872+ // var finishingScanline = 0;
18581873 var startingActiveScanline = 0 , frameStartingActiveScanline = 0 ;
18591874 var startingVisibleTopBorderScanline = 0 ;
18601875 var startingInvisibleScanline = 0 ;
1876+ var frameDoubleScan = false ;
18611877
18621878 var frameVideoStandard = videoStandard , framePulldown ; // Delays VideoStandard change until next frame
18631879
@@ -1901,17 +1917,17 @@ wmsx.V9990 = function() {
19011917 var vramEOLineShift = 0 , vramEOLineAdd = 0 ;
19021918
19031919 var modes = {
1904- SBY : { name : "SBY" , width : 256 , height : 212 , pixelWidthDiv : 1 , hasBorders : 1 , allowIL : false , cmdTiming : 0 , renderLine : renderLineModeSBY } ,
1905- P1 : { name : "P1" , width : 256 , height : 212 , pixelWidthDiv : 1 , hasBorders : 1 , allowIL : false , cmdTiming : 2 , renderLine : renderLineModeP1 } ,
1906- P2 : { name : "P2" , width : 512 , height : 212 , pixelWidthDiv : 2 , hasBorders : 1 , allowIL : false , cmdTiming : 3 , renderLine : renderLineModeP2 } ,
1907- B0 : { name : "B0" , width : 192 , height : 240 , pixelWidthDiv : 1 , hasBorders : 0 , allowIL : true , cmdTiming : 1 , renderLine : renderLineModeB0 } , // B1 Overscan? Undocumented
1908- B1 : { name : "B1" , width : 256 , height : 212 , pixelWidthDiv : 1 , hasBorders : 1 , allowIL : true , cmdTiming : 0 , renderLine : renderLineModeB1 } ,
1909- B2 : { name : "B2" , width : 384 , height : 240 , pixelWidthDiv : 1 , hasBorders : 0 , allowIL : true , cmdTiming : 1 , renderLine : renderLineModeB2 } , // B1 Overscan
1910- B3 : { name : "B3" , width : 512 , height : 212 , pixelWidthDiv : 2 , hasBorders : 1 , allowIL : true , cmdTiming : 0 , renderLine : renderLineModeB3 } ,
1911- B4 : { name : "B4" , width : 768 , height : 240 , pixelWidthDiv : 2 , hasBorders : 0 , allowIL : true , cmdTiming : 1 , renderLine : renderLineModeB4 } , // B3 Overscan
1912- B5 : { name : "B5" , width : 640 , height : 400 , pixelWidthDiv : 2 , hasBorders : 0 , allowIL : false , cmdTiming : 0 , renderLine : renderLineModeB5 } ,
1913- B6 : { name : "B6" , width : 640 , height : 480 , pixelWidthDiv : 2 , hasBorders : 0 , allowIL : false , cmdTiming : 0 , renderLine : renderLineModeB6 } ,
1914- B7 : { name : "B7" , width : 1024 , height : 212 , pixelWidthDiv : 4 , hasBorders : 1 , allowIL : true , cmdTiming : 0 , renderLine : renderLineModeB7 } // Weird! Undocumented
1920+ SBY : { name : "SBY" , width : 256 , height : 212 , pixelWidthDiv : 1 , hasBorders : 1 , allowIL : false , cmdTiming : 0 , doublesScan : false , renderLine : renderLineModeSBY } ,
1921+ P1 : { name : "P1" , width : 256 , height : 212 , pixelWidthDiv : 1 , hasBorders : 1 , allowIL : false , cmdTiming : 2 , doublesScan : false , renderLine : renderLineModeP1 } ,
1922+ P2 : { name : "P2" , width : 512 , height : 212 , pixelWidthDiv : 2 , hasBorders : 1 , allowIL : false , cmdTiming : 3 , doublesScan : false , renderLine : renderLineModeP2 } ,
1923+ B0 : { name : "B0" , width : 192 , height : 240 , pixelWidthDiv : 1 , hasBorders : 0 , allowIL : true , cmdTiming : 1 , doublesScan : false , renderLine : renderLineModeB0 } , // B1 Overscan? Undocumented
1924+ B1 : { name : "B1" , width : 256 , height : 212 , pixelWidthDiv : 1 , hasBorders : 1 , allowIL : true , cmdTiming : 0 , doublesScan : false , renderLine : renderLineModeB1 } ,
1925+ B2 : { name : "B2" , width : 384 , height : 240 , pixelWidthDiv : 1 , hasBorders : 0 , allowIL : true , cmdTiming : 1 , doublesScan : false , renderLine : renderLineModeB2 } , // B1 Overscan
1926+ B3 : { name : "B3" , width : 512 , height : 212 , pixelWidthDiv : 2 , hasBorders : 1 , allowIL : true , cmdTiming : 0 , doublesScan : false , renderLine : renderLineModeB3 } ,
1927+ B4 : { name : "B4" , width : 768 , height : 240 , pixelWidthDiv : 2 , hasBorders : 0 , allowIL : true , cmdTiming : 1 , doublesScan : false , renderLine : renderLineModeB4 } , // B3 Overscan
1928+ B5 : { name : "B5" , width : 640 , height : 400 , pixelWidthDiv : 2 , hasBorders : 0 , allowIL : false , cmdTiming : 0 , doublesScan : true , renderLine : renderLineModeB5 } ,
1929+ B6 : { name : "B6" , width : 640 , height : 480 , pixelWidthDiv : 2 , hasBorders : 0 , allowIL : false , cmdTiming : 0 , doublesScan : true , renderLine : renderLineModeB6 } ,
1930+ B7 : { name : "B7" , width : 1024 , height : 212 , pixelWidthDiv : 4 , hasBorders : 1 , allowIL : true , cmdTiming : 0 , doublesScan : false , renderLine : renderLineModeB7 } // Weird! Undocumented
19151931 } ;
19161932
19171933 var types = {
@@ -1980,7 +1996,7 @@ wmsx.V9990 = function() {
19801996 pp : palettePointer , pri : palettePointerReadInc ,
19811997 poa : paletteOffsetA , pob : paletteOffsetB , po : paletteOffset , poc : paletteOffsetCursor ,
19821998 l : currentScanline , b : bufferPosition , ba : bufferLineAdvance , ad : renderLine === renderLineActive ,
1983- fs : frameStartingActiveScanline ,
1999+ fs : frameStartingActiveScanline , fd : frameDoubleScan ,
19842000 f : frame , c : cycles , cc : lastBUSCyclesComputed ,
19852001 sx : scrollXOffset , sy : scrollYOffset , syf : scrollYOffsetFrame , sxb : scrollXBOffset , syb : scrollYBOffset , sybf : scrollYBOffsetFrame , sym : scrollYMax ,
19862002 syu : scrollYHiUpdatePending , sybu : scrollYBHiUpdatePending ,
@@ -2028,6 +2044,7 @@ wmsx.V9990 = function() {
20282044 frameVideoStandard = videoStandard ; framePulldown = pulldown ;
20292045 updateSignalMetrics ( true ) ;
20302046 if ( s . fs !== undefined ) frameStartingActiveScanline = s . fs ; // backward compatibility
2047+ if ( s . fd !== undefined ) frameDoubleScan = s . fd ; // backward compatibility
20312048 if ( cpu ) updateIRQ ( ) ;
20322049 updateMode ( true ) ;
20332050 updateYSEnabled ( true ) ;
@@ -2075,4 +2092,4 @@ wmsx.V9990.SIGNAL_START_HEIGHT = 212 + 8 * 2; // P1 mode + borders, pixel
20752092wmsx . V9990 . SIGNAL_MAX_WIDTH = 1024 + 8 * 4 * 2 ; // B7 mode + borders, pixel width = 0.5 (* 4)
20762093wmsx . V9990 . SIGNAL_MAX_HEIGHT = 480 ; // B6 mode no border, pixel height = 1
20772094
2078- wmsx . V9990 . BASE_CLOCK = wmsx . VDP . BASE_CLOCK ; // 21504960 Hz
2095+ wmsx . V9990 . BASE_CLOCK = wmsx . VDP . BASE_CLOCK ; // 21504960 Hz
0 commit comments