Skip to content

Commit 3959e64

Browse files
committed
Highscan modes (B5, B6) fix
1 parent d812c63 commit 3959e64

File tree

2 files changed

+51
-33
lines changed

2 files changed

+51
-33
lines changed

src/main/msx/video/V9990.js

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -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
20752092
wmsx.V9990.SIGNAL_MAX_WIDTH = 1024 + 8 * 4 * 2; // B7 mode + borders, pixel width = 0.5 (* 4)
20762093
wmsx.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

src/main/msx/video/VDP.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -687,9 +687,12 @@ wmsx.VDP = function(machine, cpu, vSyncConnection) {
687687
// End of line
688688

689689
++currentScanline;
690-
if (currentScanline >= finishingScanline) finishFrame();
691-
692690
if (slave) slave.lineEventEnd();
691+
692+
if (currentScanline >= finishingScanline) {
693+
finishFrame();
694+
if (slave) slave.frameEventFinishFrame();
695+
}
693696
}
694697

695698
function triggerVerticalInterrupt() {
@@ -2208,6 +2211,8 @@ wmsx.VDP = function(machine, cpu, vSyncConnection) {
22082211
}
22092212

22102213
function beginFrame() {
2214+
// wmsx.Util.error("Begin Frame. CurrentScanline: " + currentScanline);
2215+
22112216
vSyncConnection.vSyncPulse();
22122217

22132218
// Adjust for pending VideoStandard/Pulldown changes
@@ -2242,11 +2247,7 @@ wmsx.VDP = function(machine, cpu, vSyncConnection) {
22422247
}
22432248

22442249
function finishFrame() {
2245-
// console.error("Finish Frame");
2246-
2247-
//var cpuCycles = cpu.getCycles();
2248-
//wmsx.Util.log("Frame FINISHED. CurrentScanline: " + currentScanline + ", CPU cycles: " + (cpuCycles - debugFrameStartCPUCycle));
2249-
//debugFrameStartCPUCycle = cpuCycles;
2250+
// wmsx.Util.error("Frame FINISHED. CurrentScanline: " + currentScanline);
22502251

22512252
// Update frame image from backbuffer
22522253
if (videoDisplayed) {

0 commit comments

Comments
 (0)