From 3b655815db2f6a0c4ffa700338e699e7e258f986 Mon Sep 17 00:00:00 2001 From: oscar Date: Fri, 21 Aug 2026 11:33:11 +0200 Subject: [PATCH 1/2] Update vga.js fix: prevent image freezes caused by svga_offset --- src/vga.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/vga.js b/src/vga.js index 91d076784a..f14ad90628 100644 --- a/src/vga.js +++ b/src/vga.js @@ -2536,10 +2536,14 @@ VGAScreen.prototype.screen_fill_buffer = function() // XXX: Doesn't take svga_offset into account const buffer = new Int32Array(this.cpu.wasm_memory.buffer, this.dest_buffet_offset, this.screen_width * this.screen_height); const svga_memory = new Uint8Array(this.cpu.wasm_memory.buffer, this.svga_memory.byteOffset, this.vga_memory_size); + // svga_offset selects which region of svga_memory is actually being shown, which programs use for double buffering / page flipping + // This has to be applied here too to avoid the displayed image freezing on whatever was last written at offset 0 when a program flips away + // from it. (Master of Orion 2 640x480x256 VESA mode). + const base = this.svga_offset % this.vga_memory_size; for(var i = 0; i < buffer.length; i++) { - var color = this.vga256_palette[svga_memory[i]]; + var color = this.vga256_palette[svga_memory[(base + i) % this.vga_memory_size]]; buffer[i] = color & 0xFF00 | color << 16 | color >> 16 | 0xFF000000; } } From 1c1e676910cc2f89bfd8bc662f7816fb166823df Mon Sep 17 00:00:00 2001 From: Fabian Date: Wed, 26 Aug 2026 18:33:28 -0600 Subject: [PATCH 2/2] simplify fix --- src/vga.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/vga.js b/src/vga.js index f14ad90628..9b90f6454b 100644 --- a/src/vga.js +++ b/src/vga.js @@ -2533,17 +2533,15 @@ VGAScreen.prototype.screen_fill_buffer = function() if(this.svga_bpp === 8) { // XXX: Slow, should be ported to rust, but it doesn't have access to vga256_palette - // XXX: Doesn't take svga_offset into account const buffer = new Int32Array(this.cpu.wasm_memory.buffer, this.dest_buffet_offset, this.screen_width * this.screen_height); const svga_memory = new Uint8Array(this.cpu.wasm_memory.buffer, this.svga_memory.byteOffset, this.vga_memory_size); - // svga_offset selects which region of svga_memory is actually being shown, which programs use for double buffering / page flipping - // This has to be applied here too to avoid the displayed image freezing on whatever was last written at offset 0 when a program flips away - // from it. (Master of Orion 2 640x480x256 VESA mode). - const base = this.svga_offset % this.vga_memory_size; + // svga_offset selects the visible part of svga_memory, used for page flipping (e.g. Master of Orion 2) + const base = this.svga_offset; + const end = Math.min(buffer.length, this.vga_memory_size - base); - for(var i = 0; i < buffer.length; i++) + for(var i = 0; i < end; i++) { - var color = this.vga256_palette[svga_memory[(base + i) % this.vga_memory_size]]; + var color = this.vga256_palette[svga_memory[base + i]]; buffer[i] = color & 0xFF00 | color << 16 | color >> 16 | 0xFF000000; } }