Implement generalized vga pipeline
Big Picture: https://gist.github.com/ErnWong/7db67164224aaa3be5f6fcc2a6f5dd21 Fixes #26, and fixes #179. Implements: - mode 4/5, x, and everything in between - page flipping, panning, split screen - transitions and animations that depend on changing dac_map and vga256_palette. - a linked list to keep track of what pixels have what color, so in theory it doesn't need to redraw the entire buffer every time the palettes are modified. Currently slow and incorrect. - improved display-disable signal timing (port 3DA) Changes: - Add layering concept to ScreenAdapter. The idea is that using the built-in drawImageData to handle the split screens, panning, and page flipping would be more efficient than writing a loop to recopy pixels one by one. - All video modes are now handled by the same generalized pipeline, so non-standard video modes and configurations such as Mode X will work. - Video size and buffer size are now determined from register values. - The code for converting the plane write data into pixel colors (also known as the "shifting" or the "serializing" step) is deferred until the next fill-buffer event. This appears to make programs (esp. games) run smoother. See vga_replot - Separate VGA redraw from SVGA 8 bpp redraw
This commit is contained in:
parent
c5d178a4d5
commit
2a74c9d5af
|
@ -64,6 +64,8 @@ function ScreenAdapter(screen_container, bus)
|
|||
// number of rows
|
||||
text_mode_height;
|
||||
|
||||
var layers = [];
|
||||
|
||||
var screen = this;
|
||||
|
||||
// 0x12345 -> "#012345"
|
||||
|
@ -167,13 +169,27 @@ function ScreenAdapter(screen_container, bus)
|
|||
this.update_cursor_scanline(data[0], data[1]);
|
||||
}, this);
|
||||
|
||||
bus.register("screen-update-layers", function(data)
|
||||
{
|
||||
this.layers = data;
|
||||
}, this);
|
||||
|
||||
bus.register("screen-set-size-text", function(data)
|
||||
{
|
||||
this.set_size_text(data[0], data[1]);
|
||||
}, this);
|
||||
bus.register("screen-set-size-graphical", function(data)
|
||||
{
|
||||
this.set_size_graphical(data[0], data[1]);
|
||||
if(DEBUG_SCREEN_LAYERS)
|
||||
{
|
||||
data[0] = data[3];
|
||||
data[1] = data[4];
|
||||
}
|
||||
if(!data[0]) data[0] = 1;
|
||||
if(!data[1]) data[1] = 1;
|
||||
if(!data[3]) data[3] = data[0];
|
||||
if(!data[4]) data[4] = data[1];
|
||||
this.set_size_graphical(data[0], data[1], data[3], data[4]);
|
||||
}, this);
|
||||
|
||||
|
||||
|
@ -294,7 +310,7 @@ function ScreenAdapter(screen_container, bus)
|
|||
update_scale_text();
|
||||
};
|
||||
|
||||
this.set_size_graphical = function(width, height)
|
||||
this.set_size_graphical = function(width, height, buffer_width, buffer_height)
|
||||
{
|
||||
graphic_screen.style.display = "block";
|
||||
|
||||
|
@ -307,13 +323,20 @@ function ScreenAdapter(screen_container, bus)
|
|||
// Make sure to call this here, because pixels are transparent otherwise
|
||||
//screen.clear_screen();
|
||||
|
||||
graphic_image_data = graphic_context.createImageData(width, height);
|
||||
graphic_image_data = graphic_context.createImageData(buffer_width, buffer_height);
|
||||
graphic_buffer = new Uint8Array(graphic_image_data.data.buffer);
|
||||
graphic_buffer32 = new Int32Array(graphic_image_data.data.buffer);
|
||||
|
||||
graphical_mode_width = width;
|
||||
graphical_mode_height = height;
|
||||
|
||||
this.layers =
|
||||
[{
|
||||
screen_x: 0, screen_y: 0,
|
||||
buffer_x: 0, buffer_y: 0,
|
||||
buffer_width: width, buffer_height: height
|
||||
}];
|
||||
|
||||
this.bus.send("screen-tell-buffer", [graphic_buffer32], [graphic_buffer32.buffer]);
|
||||
update_scale_graphic();
|
||||
};
|
||||
|
@ -487,7 +510,7 @@ function ScreenAdapter(screen_container, bus)
|
|||
|
||||
this.update_buffer = function(min, max)
|
||||
{
|
||||
if(max < min)
|
||||
/*if(max < min)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -501,6 +524,40 @@ function ScreenAdapter(screen_container, bus)
|
|||
0, min_y,
|
||||
graphical_mode_width, max_y - min_y + 1
|
||||
);
|
||||
*/
|
||||
this.clear_screen();
|
||||
if(DEBUG_SCREEN_LAYERS)
|
||||
{
|
||||
graphic_context.putImageData(
|
||||
graphic_image_data,
|
||||
0, 0
|
||||
);
|
||||
graphic_context.strokeStyle = "#0F0";
|
||||
graphic_context.lineWidth = 4;
|
||||
this.layers.forEach((layer) =>
|
||||
{
|
||||
graphic_context.strokeRect(
|
||||
layer.buffer_x,
|
||||
layer.buffer_y,
|
||||
layer.buffer_width,
|
||||
layer.buffer_height
|
||||
);
|
||||
});
|
||||
graphic_context.lineWidth = 1;
|
||||
return;
|
||||
}
|
||||
this.layers.forEach((layer) =>
|
||||
{
|
||||
graphic_context.putImageData(
|
||||
graphic_image_data,
|
||||
layer.screen_x - layer.buffer_x,
|
||||
layer.screen_y - layer.buffer_y,
|
||||
layer.buffer_x,
|
||||
layer.buffer_y,
|
||||
layer.buffer_width,
|
||||
layer.buffer_height
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
this.init();
|
||||
|
|
|
@ -28,6 +28,12 @@ var LOG_PAGE_FAULTS = false;
|
|||
var LOG_LEVEL = LOG_ALL & ~LOG_PS2 & ~LOG_PIT & ~LOG_VIRTIO & ~LOG_9P & ~LOG_PIC &
|
||||
~LOG_DMA & ~LOG_SERIAL & ~LOG_NET & ~LOG_FLOPPY & ~LOG_DISK;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* Draws entire buffer and visualizes the layers that would be drawn
|
||||
*/
|
||||
var DEBUG_SCREEN_LAYERS = DEBUG && false;
|
||||
|
||||
|
||||
/** @const */
|
||||
var ENABLE_HPET = DEBUG && false;
|
||||
|
|
1709
src/vga.js
1709
src/vga.js
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue