diff --git a/blog/2015/06/01/README.md b/blog/2015/06/01/README.md
index e0908c355..f1f42fb57 100644
--- a/blog/2015/06/01/README.md
+++ b/blog/2015/06/01/README.md
@@ -75,68 +75,68 @@ Another problem: during IBM VGA ROM initialization, a "missing readByte handler"
Before debugging this though, I decided to first make a table of all the register values for most of the modes that
the IBM VGA supports:
- INT 0x10 Mode Requested: 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x0D 0x0E 0x10 0x12
-
- BIOSMODE: 0x01 0x01 0x03 0x03 0x04 0x04 0x06 0x12 0x12 0x12 0x12
- CRTC[0x00]: HORZ_TOTAL 0x2D 0x2D 0x5F 0x5F 0x2D 0x2D 0x5F 0x2D 0x5F 0x5F 0x5F
- CRTC[0x01]: HORZ_DISP_END 0x27 0x27 0x4F 0x4F 0x27 0x27 0x4F 0x27 0x4F 0x4F 0x4F
- CRTC[0x02]: HORZ_BLANK_START 0x28 0x28 0x50 0x50 0x28 0x28 0x50 0x28 0x50 0x50 0x50
- CRTC[0x03]: HORZ_BLANK_END 0x90 0x90 0x82 0x82 0x90 0x90 0x82 0x90 0x82 0x82 0x82
- CRTC[0x04]: HORZ_RETRACE_START 0x2B 0x2B 0x55 0x55 0x2B 0x2B 0x54 0x2B 0x54 0x54 0x54
- CRTC[0x05]: HORZ_RETRACE_END 0xA0 0xA0 0x81 0x81 0x80 0x80 0x80 0x80 0x80 0x80 0x80
- CRTC[0x06]: VERT_TOTAL 0xBF 0xBF 0xBF 0xBF 0xBF 0xBF 0xBF 0xBF 0xBF 0xBF 0x0B
- CRTC[0x07]: OVERFLOW 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x3E
- CRTC[0x08]: PRESET_ROW_SCAN 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
- CRTC[0x09]: MAX_SCAN_LINE 0x4F 0x4F 0x4F 0x4F 0xC1 0xC1 0xC1 0xC0 0xC0 0x40 0x40
- CRTC[0x0A]: CURSOR_START 0x0D 0x0D 0x0D 0x0D 0x00 0x00 0x00 0x00 0x00 0x00 0x00
- CRTC[0x0B]: CURSOR_END 0x0E 0x0E 0x0E 0x0E 0x00 0x00 0x00 0x00 0x00 0x00 0x00
- CRTC[0x0C]: START_ADDR_HI 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
- CRTC[0x0D]: START_ADDR_LO 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
- CRTC[0x0E]: CURSOR_ADDR_HI 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01
- CRTC[0x0F]: CURSOR_ADDR_LO 0x19 0x19 0x41 0x41 0x19 0x19 0x41 0x19 0x41 0x41 0xE1
- CRTC[0x10]: VERT_RETRACE_START 0x9C 0x9C 0x9C 0x9C 0x9C 0x9C 0x9C 0x9C 0x9C 0x83 0xEA
- CRTC[0x11]: VERT_RETRACE_END 0x8E 0x8E 0x8E 0x8E 0x8E 0x8E 0x8E 0x8E 0x8E 0x85 0x8C
- CRTC[0x12]: VERT_DISP_END 0x8F 0x8F 0x8F 0x8F 0x8F 0x8F 0x8F 0x8F 0x8F 0x5D 0xDF
- CRTC[0x13]: OFFSET 0x14 0x14 0x28 0x28 0x14 0x14 0x28 0x14 0x28 0x28 0x28
- CRTC[0x14]: UNDERLINE 0x1F 0x1F 0x1F 0x1F 0x00 0x00 0x00 0x00 0x00 0x0F 0x00
- CRTC[0x15]: VERT_BLANK_START 0x96 0x96 0x96 0x96 0x96 0x96 0x96 0x96 0x96 0x63 0xE7
- CRTC[0x16]: VERT_BLANK_END 0xB9 0xB9 0xB9 0xB9 0xB9 0xB9 0xB9 0xB9 0xB9 0xBA 0x04
- CRTC[0x17]: MODE_CTRL 0xA3 0xA3 0xA3 0xA3 0xA2 0xA2 0xC2 0xE3 0xE3 0xE3 0xE3
- CRTC[0x18]: LINE_COMPARE 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
- GRC[0x00]: SRESET 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
- GRC[0x01]: ESRESET 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
- GRC[0x02]: COLORCMP 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
- GRC[0x03]: DATAROT 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
- GRC[0x04]: READMAP 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
- GRC[0x05]: MODE 0x10 0x10 0x10 0x10 0x30 0x30 0x00 0x00 0x00 0x00 0x00
- GRC[0x06]: MISC 0x0E 0x0E 0x0E 0x0E 0x0F 0x0F 0x0D 0x05 0x05 0x05 0x05
- GRC[0x07]: COLORDC 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0F 0x0F 0x0F 0x0F
- GRC[0x08]: BITMASK 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
- SEQ[0x00]: RESET 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03
- SEQ[0x01]: CLOCKING 0x08 0x08 0x00 0x00 0x09 0x09 0x01 0x09 0x01 0x01 0x01
- SEQ[0x02]: MAPMASK 0x03 0x03 0x03 0x03 0x03 0x03 0x01 0x0F 0x0F 0x0F 0x0F
- SEQ[0x03]: CHARMAP 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
- SEQ[0x04]: MEMMODE 0x03 0x03 0x03 0x03 0x02 0x02 0x06 0x06 0x06 0x06 0x06
- ATC[0x00]: PAL00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
- ATC[0x01]: PAL01 0x01 0x01 0x01 0x01 0x13 0x13 0x17 0x01 0x01 0x01 0x01
- ATC[0x02]: PAL02 0x02 0x02 0x02 0x02 0x15 0x15 0x17 0x02 0x02 0x02 0x02
- ATC[0x03]: PAL03 0x03 0x03 0x03 0x03 0x17 0x17 0x17 0x03 0x03 0x03 0x03
- ATC[0x04]: PAL04 0x04 0x04 0x04 0x04 0x02 0x02 0x17 0x04 0x04 0x04 0x04
- ATC[0x05]: PAL05 0x05 0x05 0x05 0x05 0x04 0x04 0x17 0x05 0x05 0x05 0x05
- ATC[0x06]: PAL06 0x14 0x14 0x14 0x14 0x06 0x06 0x17 0x06 0x06 0x14 0x14
- ATC[0x07]: PAL07 0x07 0x07 0x07 0x07 0x07 0x07 0x17 0x07 0x07 0x07 0x07
- ATC[0x08]: PAL08 0x38 0x38 0x38 0x38 0x10 0x10 0x17 0x10 0x10 0x38 0x38
- ATC[0x09]: PAL09 0x39 0x39 0x39 0x39 0x11 0x11 0x17 0x11 0x11 0x39 0x39
- ATC[0x0A]: PAL0A 0x3A 0x3A 0x3A 0x3A 0x12 0x12 0x17 0x12 0x12 0x3A 0x3A
- ATC[0x0B]: PAL0B 0x3B 0x3B 0x3B 0x3B 0x13 0x13 0x17 0x13 0x13 0x3B 0x3B
- ATC[0x0C]: PAL0C 0x3C 0x3C 0x3C 0x3C 0x14 0x14 0x17 0x14 0x14 0x3C 0x3C
- ATC[0x0D]: PAL0D 0x3D 0x3D 0x3D 0x3D 0x15 0x15 0x17 0x15 0x15 0x3D 0x3D
- ATC[0x0E]: PAL0E 0x3E 0x3E 0x3E 0x3E 0x16 0x16 0x17 0x16 0x16 0x3E 0x3E
- ATC[0x0F]: PAL0F 0x3F 0x3F 0x3F 0x3F 0x17 0x17 0x17 0x17 0x17 0x3F 0x3F
- ATC[0x10]: MODE 0x0C 0x0C 0x0C 0x0C 0x01 0x01 0x01 0x01 0x01 0x01 0x01
- ATC[0x11]: OVERSCAN 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
- ATC[0x12]: PLANES 0x0F 0x0F 0x0F 0x0F 0x03 0x03 0x01 0x0F 0x0F 0x0F 0x0F
- ATC[0x13]: HORZPAN 0x08 0x08 0x08 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ INT 0x10 Mode Requested: 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x0D 0x0E 0x10 0x12 0x13
+
+ BIOSMODE: 0x01 0x01 0x03 0x03 0x04 0x04 0x06 0x12 0x12 0x12 0x12 0x13
+ CRTC[0x00]: HORZ_TOTAL 0x2D 0x2D 0x5F 0x5F 0x2D 0x2D 0x5F 0x2D 0x5F 0x5F 0x5F 0x5F
+ CRTC[0x01]: HORZ_DISP_END 0x27 0x27 0x4F 0x4F 0x27 0x27 0x4F 0x27 0x4F 0x4F 0x4F 0x4F
+ CRTC[0x02]: HORZ_BLANK_START 0x28 0x28 0x50 0x50 0x28 0x28 0x50 0x28 0x50 0x50 0x50 0x50
+ CRTC[0x03]: HORZ_BLANK_END 0x90 0x90 0x82 0x82 0x90 0x90 0x82 0x90 0x82 0x82 0x82 0x82
+ CRTC[0x04]: HORZ_RETRACE_START 0x2B 0x2B 0x55 0x55 0x2B 0x2B 0x54 0x2B 0x54 0x54 0x54 0x54
+ CRTC[0x05]: HORZ_RETRACE_END 0xA0 0xA0 0x81 0x81 0x80 0x80 0x80 0x80 0x80 0x80 0x80 0x80
+ CRTC[0x06]: VERT_TOTAL 0xBF 0xBF 0xBF 0xBF 0xBF 0xBF 0xBF 0xBF 0xBF 0xBF 0x0B 0xBF
+ CRTC[0x07]: OVERFLOW 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x1F 0x3E 0x1F
+ CRTC[0x08]: PRESET_ROW_SCAN 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ CRTC[0x09]: MAX_SCAN_LINE 0x4F 0x4F 0x4F 0x4F 0xC1 0xC1 0xC1 0xC0 0xC0 0x40 0x40 0x41
+ CRTC[0x0A]: CURSOR_START 0x0D 0x0D 0x0D 0x0D 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ CRTC[0x0B]: CURSOR_END 0x0E 0x0E 0x0E 0x0E 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ CRTC[0x0C]: START_ADDR_HI 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ CRTC[0x0D]: START_ADDR_LO 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ CRTC[0x0E]: CURSOR_ADDR_HI 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x00
+ CRTC[0x0F]: CURSOR_ADDR_LO 0x19 0x19 0x41 0x41 0x19 0x19 0x41 0x19 0x41 0x41 0xE1 0xA2
+ CRTC[0x10]: VERT_RETRACE_START 0x9C 0x9C 0x9C 0x9C 0x9C 0x9C 0x9C 0x9C 0x9C 0x83 0xEA 0x9C
+ CRTC[0x11]: VERT_RETRACE_END 0x8E 0x8E 0x8E 0x8E 0x8E 0x8E 0x8E 0x8E 0x8E 0x85 0x8C 0x8E
+ CRTC[0x12]: VERT_DISP_END 0x8F 0x8F 0x8F 0x8F 0x8F 0x8F 0x8F 0x8F 0x8F 0x5D 0xDF 0x8F
+ CRTC[0x13]: OFFSET 0x14 0x14 0x28 0x28 0x14 0x14 0x28 0x14 0x28 0x28 0x28 0x28
+ CRTC[0x14]: UNDERLINE 0x1F 0x1F 0x1F 0x1F 0x00 0x00 0x00 0x00 0x00 0x0F 0x00 0x40 (bit 6 selects double-word mode)
+ CRTC[0x15]: VERT_BLANK_START 0x96 0x96 0x96 0x96 0x96 0x96 0x96 0x96 0x96 0x63 0xE7 0x96
+ CRTC[0x16]: VERT_BLANK_END 0xB9 0xB9 0xB9 0xB9 0xB9 0xB9 0xB9 0xB9 0xB9 0xBA 0x04 0xB9
+ CRTC[0x17]: MODE_CTRL 0xA3 0xA3 0xA3 0xA3 0xA2 0xA2 0xC2 0xE3 0xE3 0xE3 0xE3 0xA3 (bit 6 selects byte mode)
+ CRTC[0x18]: LINE_COMPARE 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
+ GRC[0x00]: SRESET 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ GRC[0x01]: ESRESET 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ GRC[0x02]: COLORCMP 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ GRC[0x03]: DATAROT 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ GRC[0x04]: READMAP 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ GRC[0x05]: MODE 0x10 0x10 0x10 0x10 0x30 0x30 0x00 0x00 0x00 0x00 0x00 0x40
+ GRC[0x06]: MISC 0x0E 0x0E 0x0E 0x0E 0x0F 0x0F 0x0D 0x05 0x05 0x05 0x05 0x05
+ GRC[0x07]: COLORDC 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0F 0x0F 0x0F 0x0F 0x0F
+ GRC[0x08]: BITMASK 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
+ SEQ[0x00]: RESET 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03 0x03
+ SEQ[0x01]: CLOCKING 0x08 0x08 0x00 0x00 0x09 0x09 0x01 0x09 0x01 0x01 0x01 0x01
+ SEQ[0x02]: MAPMASK 0x03 0x03 0x03 0x03 0x03 0x03 0x01 0x0F 0x0F 0x0F 0x0F 0x0F
+ SEQ[0x03]: CHARMAP 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ SEQ[0x04]: MEMMODE 0x03 0x03 0x03 0x03 0x02 0x02 0x06 0x06 0x06 0x06 0x06 0x0E
+ ATC[0x00]: PAL00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ ATC[0x01]: PAL01 0x01 0x01 0x01 0x01 0x13 0x13 0x17 0x01 0x01 0x01 0x01 0x01
+ ATC[0x02]: PAL02 0x02 0x02 0x02 0x02 0x15 0x15 0x17 0x02 0x02 0x02 0x02 0x02
+ ATC[0x03]: PAL03 0x03 0x03 0x03 0x03 0x17 0x17 0x17 0x03 0x03 0x03 0x03 0x03
+ ATC[0x04]: PAL04 0x04 0x04 0x04 0x04 0x02 0x02 0x17 0x04 0x04 0x04 0x04 0x04
+ ATC[0x05]: PAL05 0x05 0x05 0x05 0x05 0x04 0x04 0x17 0x05 0x05 0x05 0x05 0x05
+ ATC[0x06]: PAL06 0x14 0x14 0x14 0x14 0x06 0x06 0x17 0x06 0x06 0x14 0x14 0x06
+ ATC[0x07]: PAL07 0x07 0x07 0x07 0x07 0x07 0x07 0x17 0x07 0x07 0x07 0x07 0x07
+ ATC[0x08]: PAL08 0x38 0x38 0x38 0x38 0x10 0x10 0x17 0x10 0x10 0x38 0x38 0x08
+ ATC[0x09]: PAL09 0x39 0x39 0x39 0x39 0x11 0x11 0x17 0x11 0x11 0x39 0x39 0x09
+ ATC[0x0A]: PAL0A 0x3A 0x3A 0x3A 0x3A 0x12 0x12 0x17 0x12 0x12 0x3A 0x3A 0x0A
+ ATC[0x0B]: PAL0B 0x3B 0x3B 0x3B 0x3B 0x13 0x13 0x17 0x13 0x13 0x3B 0x3B 0x0B
+ ATC[0x0C]: PAL0C 0x3C 0x3C 0x3C 0x3C 0x14 0x14 0x17 0x14 0x14 0x3C 0x3C 0x0C
+ ATC[0x0D]: PAL0D 0x3D 0x3D 0x3D 0x3D 0x15 0x15 0x17 0x15 0x15 0x3D 0x3D 0x0D
+ ATC[0x0E]: PAL0E 0x3E 0x3E 0x3E 0x3E 0x16 0x16 0x17 0x16 0x16 0x3E 0x3E 0x0E
+ ATC[0x0F]: PAL0F 0x3F 0x3F 0x3F 0x3F 0x17 0x17 0x17 0x17 0x17 0x3F 0x3F 0x0F
+ ATC[0x10]: MODE 0x0C 0x0C 0x0C 0x0C 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x41
+ ATC[0x11]: OVERSCAN 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ ATC[0x12]: PLANES 0x0F 0x0F 0x0F 0x0F 0x03 0x03 0x01 0x0F 0x0F 0x0F 0x0F 0x0F
+ ATC[0x13]: HORZPAN 0x08 0x08 0x08 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
In the process of building this table, I also discovered that INT 0x10 mode 0x0D display is garbled, and that all
graphics modes >= 0x0D are misdetected as BIOSMODE 0x12.
@@ -147,4 +147,4 @@ In addition, I've created a [VGA Tests](/tests/pc/vga/) directory to hold VGA te
to run successfully. See that directory for more details.
*[@jeffpar](http://twitter.com/jeffpar)*
-*June 1, 2015 (Updated June 10, 2015)*
+*June 1, 2015 (Updated July 3, 2015)*
diff --git a/devices/pc/machine/compaq/deskpro386/vga/2048kb/machine.xml b/devices/pc/machine/compaq/deskpro386/vga/2048kb/machine.xml
index ef813ef02..b23ff9108 100644
--- a/devices/pc/machine/compaq/deskpro386/vga/2048kb/machine.xml
+++ b/devices/pc/machine/compaq/deskpro386/vga/2048kb/machine.xml
@@ -10,7 +10,7 @@
-
+
diff --git a/modules/pcjs/lib/video.js b/modules/pcjs/lib/video.js
index 805d46a89..502496447 100644
--- a/modules/pcjs/lib/video.js
+++ b/modules/pcjs/lib/video.js
@@ -180,9 +180,12 @@ function Video(parmsVideo, canvas, context, textarea, container)
/*
* Instead of (re)allocating a new color array every time getCardColors() is called, we preallocate
- * an array now and simply update the entries as needed.
+ * an array now and simply update the entries as needed. Note that for an EGA (or a VGA operating
+ * in an EGA-compatible mode), only the first 16 entries get used (derived from the ATC); only when
+ * a VGA is operating in an 8bpp mode are 256 entries used (derived from the DAC rather than the ATC).
*/
- this.aRGB = new Array(16);
+ this.aRGB = new Array(this.nCard == Video.CARD.VGA? 256 : 16);
+ this.fRGBValid = false; // whenever this is false, it signals getCardColors() to rebuild aRGB
/*
* Since I've not found clear documentation on a reliable way to check whether a particular DOM element
@@ -1150,7 +1153,12 @@ Card.CRTC = {
* this word address is [effectively] either a word or double-word address. #IBMVGATechRef
*/
OFFSET: 0x13,
- UNDERLINE: 0x14,
+ UNDERLINE: {
+ INDX: 0x14,
+ ROWSCAN: 0x1f,
+ COUNTBY4: 0x20,
+ DWORD: 0x40
+ },
VERT_BLANK_START: 0x15,
VERT_BLANK_END: 0x16,
MODE_CTRL: {
@@ -3502,14 +3510,48 @@ Video.prototype.getCardColors = function(nBitsPerPixel)
this.assert(this.cardColor === this.cardEGA);
- var aRegs = (this.cardEGA.regATCData[15] != null? this.cardEGA.regATCData : Video.aEGAPalDef);
- for (var i = 0; i < this.aRGB.length; i++) {
- var b = aRegs[i] || 0;
- var bRed = (((b & 0x04)? 0xaa : 0) | ((b & 0x20)? 0x55 : 0));
- var bGreen = (((b & 0x02)? 0xaa : 0) | ((b & 0x10)? 0x55 : 0));
- var bBlue = (((b & 0x01)? 0xaa : 0) | ((b & 0x08)? 0x55 : 0));
- this.aRGB[i] = [bRed, bGreen, bBlue, 0xff];
+ if (this.fRGBValid && nBitsPerPixel && !this.aRGB[16]) {
+ this.assert(false);
+ this.fRGBValid = false;
}
+
+ if (!this.fRGBValid) {
+ var aRegs, i, bRed, bGreen, bBlue;
+ if (nBitsPerPixel == 8) {
+ /*
+ * The card must be a VGA, and it's using a (8bpp) mode that bypasses the ATC, so we need
+ * to pull RGB data exclusively from the 256-entry DAC; each entry contains 6-bit red, green,
+ * and blue values packed into bits 0-5, 6-11, and 12-17, respectively, each of which we
+ * effectively shift left 2 bits, for a crude 6-to-8-bit conversion.
+ */
+ aRegs = this.cardEGA.regDACData;
+ for (i = 0; i < 256; i++) {
+ var dw = aRegs[i] || 0;
+ bRed = (dw << 2) & 0xfc;
+ bGreen = (dw >> 4) & 0xfc;
+ bBlue = (dw >> 10) & 0xfc;
+ this.aRGB[i] = [bRed, bGreen, bBlue, 0xff];
+ }
+ this.fRGBValid = true;
+ } else {
+ /*
+ * We need to pull RGB data from the ATC; moreover, if the ATC hasn't been initialized yet,
+ * we go with a default EGA-compatible 16-color palette.
+ *
+ * TODO: If the card is really a VGA, the DAC plays a role as well; need to update this code.
+ */
+ aRegs = (this.cardEGA.regATCData[15] != null? this.cardEGA.regATCData : Video.aEGAPalDef);
+ for (i = 0; i < 16; i++) {
+ var b = aRegs[i] || 0;
+ bRed = (((b & 0x04)? 0xaa : 0) | ((b & 0x20)? 0x55 : 0));
+ bGreen = (((b & 0x02)? 0xaa : 0) | ((b & 0x10)? 0x55 : 0));
+ bBlue = (((b & 0x01)? 0xaa : 0) | ((b & 0x08)? 0x55 : 0));
+ this.aRGB[i] = [bRed, bGreen, bBlue, 0xff];
+ }
+ this.fRGBValid = true;
+ }
+ }
+
return this.aRGB;
};
@@ -3576,15 +3618,17 @@ Video.prototype.buildFonts = function()
*/
if (window && this.abFontData) {
- var aRGBColors = this.getCardColors();
var offSplit = 0x0000;
var cxChar = this.cxFontChar? this.cxFontChar : 8;
+ var aRGBColors = this.getCardColors();
+
if (this.buildFont(Video.FONT.CGA, this.aFontOffsets[0], offSplit, cxChar, 8, this.abFontData, aRGBColors)) {
fChanges = true;
}
offSplit = this.cxFontChar? 0 : 0x0800;
cxChar = this.cxFontChar? this.cxFontChar : 9;
+
if (this.buildFont(Video.FONT.MDA, this.aFontOffsets[1], offSplit, cxChar, 14, this.abFontData, Video.aMDAColors, Video.aMDAColorMap)) {
fChanges = true;
}
@@ -3666,17 +3710,18 @@ Video.prototype.createFont = function(nFont, offData, offSplit, cxChar, cyChar,
var fChanges = false;
var nDouble = (nFont & 0x1)? 0 : 1;
var font = this.aFonts[nFont];
+ var nColors = (aRGBColors.length < 16? aRGBColors.length : 16);
if (!font) {
font = {
cxCell: cxChar << nDouble,
cyCell: cyChar << nDouble,
- aCSSColors: new Array(aRGBColors.length),
- aRGBColors: aRGBColors.slice(), // using the Array slice() method to simply make a copy
+ aCSSColors: new Array(nColors),
+ aRGBColors: aRGBColors.slice(0, nColors), // using the Array slice() method to simply make a copy
aColorMap: aColorMap,
- aCanvas: new Array(aRGBColors.length)
+ aCanvas: new Array(nColors)
};
}
- for (var iColor = 0; iColor < aRGBColors.length; iColor++) {
+ for (var iColor = 0; iColor < nColors; iColor++) {
var rgbColor = aRGBColors[iColor];
var rgbColorOrig = font.aCSSColors[iColor]? font.aRGBColors[iColor] : [];
if (rgbColor[0] !== rgbColorOrig[0] || rgbColor[1] !== rgbColorOrig[1] || rgbColor[2] !== rgbColorOrig[2]) {
@@ -4179,7 +4224,6 @@ Video.prototype.setDimensions = function()
this.nCellCache = (this.nCells / this.nCellsPerWord)|0;
this.cbScreen = ((this.nCellCache << 1) + this.cbPadding)|0;
this.cbSplit = (this.cbPadding? ((this.cbScreen + this.cbPadding) >> 1) : 0);
- this.fLinear = false; // set for 8bpp "linear" VGA modes only
if (this.nMode >= Video.MODE.EGA_320X200) this.nCellCache <<= 1; // double nCellCache (every cell is a byte)
/*
@@ -4469,6 +4513,7 @@ Video.prototype.setMode = function(nMode, fForce)
this.cUpdates = 0; // count updateScreen() calls as a means of driving blink updates
this.nMode = nMode;
+ this.fRGBValid = false;
/*
* On an EGA, it's CRITICAL that a reset() invalidate cardActive, to ensure that the code below
@@ -4827,7 +4872,7 @@ Video.prototype.updateScreen = function(fForce)
* We now calculate the logical width, and the compute a new cbScreen in much the same way the original
* cbScreen was computed (but without any CGA-related padding considerations).
*/
- this.nColsLogical = card.regCRTData[Card.CRTC.EGA.OFFSET] << (this.nFont? 1 : 4);
+ this.nColsLogical = card.regCRTData[Card.CRTC.EGA.OFFSET] << (this.nFont? 1 : (card.regCRTData[Card.CRTC.EGA.UNDERLINE.INDX] & Card.CRTC.EGA.UNDERLINE.DWORD)? 3 : 4);
cbScreen = ((((this.nColsLogical * (this.nRows-1) + this.nCols) / this.nCellsPerWord) << 1) + this.cbPadding)|0;
}
@@ -5170,12 +5215,13 @@ Video.prototype.updateScreenGraphicsVGA = function(addrScreen, addrScreenLimit)
this.cBlinkVisible = 0;
var iCell = 0;
- var aPixelColors = this.getCardColors();
+ var aPixelColors = this.getCardColors(8);
var adwMemory = this.cardActive.adwMemory;
var x = 0, y = 0;
var xDirty = this.nCols, xMaxDirty = 0, yDirty = this.nRows, yMaxDirty = 0;
+ var cbInc = (this.cardActive.regSEQData[Card.SEQ.MEMMODE.INDX] & Card.SEQ.MEMMODE.CHAIN4)? 4 : 1;
var iPixelFirst = this.cardActive.regATCData[Card.ATC.HORZPAN.INDX] & Card.ATC.HORZPAN.SHIFT_LEFT;
/*
* TODO: What should happen if the card is programmed such that nColsLogical is LESS THAN nCols?
@@ -5183,7 +5229,7 @@ Video.prototype.updateScreenGraphicsVGA = function(addrScreen, addrScreenLimit)
var nRowAdjust = (this.nColsLogical > this.nCols? ((this.nColsLogical - this.nCols - iPixelFirst) >> 3) : 0);
while (addr < addrScreenLimit) {
- var idw = addr++ - this.addrBuffer;
+ var idw = addr - this.addrBuffer;
this.assert(idw >= 0 && idw < adwMemory.length);
data = adwMemory[idw];
@@ -5235,6 +5281,8 @@ Video.prototype.updateScreenGraphicsVGA = function(addrScreen, addrScreenLimit)
this.assert(x <= this.nCols);
+ addr += cbInc;
+
if (x >= this.nCols) {
x = 0;
if (++y > this.nRows) break;
@@ -5450,6 +5498,7 @@ Video.prototype.outATC = function(port, bOut, addrFrom)
if (DEBUG && (!addrFrom || this.messageEnabled())) {
this.printMessage("outATC(" + str.toHexByte(bOut) + "): redraw screen for font changes");
}
+ this.fRGBValid = false;
this.updateScreen(true);
}
}
@@ -5466,6 +5515,7 @@ Video.prototype.outATC = function(port, bOut, addrFrom)
this.printMessageIO(port, bOut, addrFrom, "ATC." + this.cardEGA.asATCRegs[iReg]);
}
this.cardEGA.regATCData[iReg] = bOut;
+ this.fRGBValid = false;
}
}
this.cardEGA.fATCData = false;
@@ -5780,6 +5830,7 @@ Video.prototype.outDACData = function(port, bOut, addrFrom)
this.cardEGA.regDACShift = 0;
this.cardEGA.regDACAddr = (this.cardEGA.regDACAddr + 1) & (Card.DAC.TOTAL_REGS-1);
}
+ this.fRGBValid = false;
};
/**