[NTVDM]: Code "formatting" + fix types.
[reactos.git] / subsystems / ntvdm / vga.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: vga.c
5 * PURPOSE: VGA hardware emulation
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #define NDEBUG
12
13 #include "emulator.h"
14 #include "vga.h"
15
16 #include "io.h"
17 #include "bios.h"
18
19 /* PRIVATE VARIABLES **********************************************************/
20
21 static CONST DWORD MemoryBase[] = { 0xA0000, 0xA0000, 0xB0000, 0xB8000 };
22 static CONST DWORD MemoryLimit[] = { 0xAFFFF, 0xAFFFF, 0xB7FFF, 0xBFFFF };
23
24 #define USE_REACTOS_COLORS
25 // #define USE_DOSBOX_COLORS
26
27 #if defined(USE_REACTOS_COLORS)
28
29 // ReactOS colors
30 static CONST COLORREF VgaDefaultPalette[VGA_MAX_COLORS] =
31 {
32 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
33 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
34 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
35 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
36 RGB(0x00, 0x00, 0x00), RGB(0x10, 0x10, 0x10), RGB(0x20, 0x20, 0x20), RGB(0x35, 0x35, 0x35),
37 RGB(0x45, 0x45, 0x45), RGB(0x55, 0x55, 0x55), RGB(0x65, 0x65, 0x65), RGB(0x75, 0x75, 0x75),
38 RGB(0x8A, 0x8A, 0x8A), RGB(0x9A, 0x9A, 0x9A), RGB(0xAA, 0xAA, 0xAA), RGB(0xBA, 0xBA, 0xBA),
39 RGB(0xCA, 0xCA, 0xCA), RGB(0xDF, 0xDF, 0xDF), RGB(0xEF, 0xEF, 0xEF), RGB(0xFF, 0xFF, 0xFF),
40 RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x82, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF),
41 RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x82), RGB(0xFF, 0x00, 0x41),
42 RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x82, 0x00), RGB(0xFF, 0xBE, 0x00),
43 RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x82, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00),
44 RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x82), RGB(0x00, 0xFF, 0xBE),
45 RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x82, 0xFF), RGB(0x00, 0x41, 0xFF),
46 RGB(0x82, 0x82, 0xFF), RGB(0x9E, 0x82, 0xFF), RGB(0xBE, 0x82, 0xFF), RGB(0xDF, 0x82, 0xFF),
47 RGB(0xFF, 0x82, 0xFF), RGB(0xFF, 0x82, 0xDF), RGB(0xFF, 0x82, 0xBE), RGB(0xFF, 0x82, 0x9E),
48 RGB(0xFF, 0x82, 0x82), RGB(0xFF, 0x9E, 0x82), RGB(0xFF, 0xBE, 0x82), RGB(0xFF, 0xDF, 0x82),
49 RGB(0xFF, 0xFF, 0x82), RGB(0xDF, 0xFF, 0x82), RGB(0xBE, 0xFF, 0x82), RGB(0x9E, 0xFF, 0x82),
50 RGB(0x82, 0xFF, 0x82), RGB(0x82, 0xFF, 0x9E), RGB(0x82, 0xFF, 0xBE), RGB(0x82, 0xFF, 0xDF),
51 RGB(0x82, 0xFF, 0xFF), RGB(0x82, 0xDF, 0xFF), RGB(0x82, 0xBE, 0xFF), RGB(0x82, 0x9E, 0xFF),
52 RGB(0xBA, 0xBA, 0xFF), RGB(0xCA, 0xBA, 0xFF), RGB(0xDF, 0xBA, 0xFF), RGB(0xEF, 0xBA, 0xFF),
53 RGB(0xFF, 0xBA, 0xFF), RGB(0xFF, 0xBA, 0xEF), RGB(0xFF, 0xBA, 0xDF), RGB(0xFF, 0xBA, 0xCA),
54 RGB(0xFF, 0xBA, 0xBA), RGB(0xFF, 0xCA, 0xBA), RGB(0xFF, 0xDF, 0xBA), RGB(0xFF, 0xEF, 0xBA),
55 RGB(0xFF, 0xFF, 0xBA), RGB(0xEF, 0xFF, 0xBA), RGB(0xDF, 0xFF, 0xBA), RGB(0xCA, 0xFF, 0xBA),
56 RGB(0xBA, 0xFF, 0xBA), RGB(0xBA, 0xFF, 0xCA), RGB(0xBA, 0xFF, 0xDF), RGB(0xBA, 0xFF, 0xEF),
57 RGB(0xBA, 0xFF, 0xFF), RGB(0xBA, 0xEF, 0xFF), RGB(0xBA, 0xDF, 0xFF), RGB(0xBA, 0xCA, 0xFF),
58 RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x39, 0x00, 0x71), RGB(0x55, 0x00, 0x71),
59 RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x39), RGB(0x71, 0x00, 0x1C),
60 RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x39, 0x00), RGB(0x71, 0x55, 0x00),
61 RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x39, 0x71, 0x00), RGB(0x1C, 0x71, 0x00),
62 RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x39), RGB(0x00, 0x71, 0x55),
63 RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x39, 0x71), RGB(0x00, 0x1C, 0x71),
64 RGB(0x39, 0x39, 0x71), RGB(0x45, 0x39, 0x71), RGB(0x55, 0x39, 0x71), RGB(0x61, 0x39, 0x71),
65 RGB(0x71, 0x39, 0x71), RGB(0x71, 0x39, 0x61), RGB(0x71, 0x39, 0x55), RGB(0x71, 0x39, 0x45),
66 RGB(0x71, 0x39, 0x39), RGB(0x71, 0x45, 0x39), RGB(0x71, 0x55, 0x39), RGB(0x71, 0x61, 0x39),
67 RGB(0x71, 0x71, 0x39), RGB(0x61, 0x71, 0x39), RGB(0x55, 0x71, 0x39), RGB(0x45, 0x71, 0x39),
68 RGB(0x39, 0x71, 0x39), RGB(0x39, 0x71, 0x45), RGB(0x39, 0x71, 0x55), RGB(0x39, 0x71, 0x61),
69 RGB(0x39, 0x71, 0x71), RGB(0x39, 0x61, 0x71), RGB(0x39, 0x55, 0x71), RGB(0x39, 0x45, 0x71),
70 RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71),
71 RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59),
72 RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51),
73 RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51),
74 RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69),
75 RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71),
76 RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x31, 0x00, 0x41),
77 RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x31), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10),
78 RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x31, 0x00),
79 RGB(0x41, 0x41, 0x00), RGB(0x31, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00),
80 RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x31),
81 RGB(0x00, 0x41, 0x41), RGB(0x00, 0x31, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41),
82 RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x31, 0x20, 0x41), RGB(0x39, 0x20, 0x41),
83 RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x39), RGB(0x41, 0x20, 0x31), RGB(0x41, 0x20, 0x28),
84 RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x31, 0x20), RGB(0x41, 0x39, 0x20),
85 RGB(0x41, 0x41, 0x20), RGB(0x39, 0x41, 0x20), RGB(0x31, 0x41, 0x20), RGB(0x28, 0x41, 0x20),
86 RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x31), RGB(0x20, 0x41, 0x39),
87 RGB(0x20, 0x41, 0x41), RGB(0x20, 0x39, 0x41), RGB(0x20, 0x31, 0x41), RGB(0x20, 0x28, 0x41),
88 RGB(0x2D, 0x2D, 0x41), RGB(0x31, 0x2D, 0x41), RGB(0x35, 0x2D, 0x41), RGB(0x3D, 0x2D, 0x41),
89 RGB(0x41, 0x2D, 0x41), RGB(0x41, 0x2D, 0x3D), RGB(0x41, 0x2D, 0x35), RGB(0x41, 0x2D, 0x31),
90 RGB(0x41, 0x2D, 0x2D), RGB(0x41, 0x31, 0x2D), RGB(0x41, 0x35, 0x2D), RGB(0x41, 0x3D, 0x2D),
91 RGB(0x41, 0x41, 0x2D), RGB(0x3D, 0x41, 0x2D), RGB(0x35, 0x41, 0x2D), RGB(0x31, 0x41, 0x2D),
92 RGB(0x2D, 0x41, 0x2D), RGB(0x2D, 0x41, 0x31), RGB(0x2D, 0x41, 0x35), RGB(0x2D, 0x41, 0x3D),
93 RGB(0x2D, 0x41, 0x41), RGB(0x2D, 0x3D, 0x41), RGB(0x2D, 0x35, 0x41), RGB(0x2D, 0x31, 0x41),
94 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
95 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00)
96 };
97
98 #elif defined(USE_DOSBOX_COLORS)
99
100 // DOSBox colors
101 static CONST COLORREF VgaDefaultPalette[VGA_MAX_COLORS] =
102 {
103 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
104 RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
105 RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
106 RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
107 RGB(0x00, 0x00, 0x00), RGB(0x14, 0x14, 0x14), RGB(0x20, 0x20, 0x20), RGB(0x2C, 0x2C, 0x2C),
108 RGB(0x38, 0x38, 0x38), RGB(0x45, 0x45, 0x45), RGB(0x51, 0x51, 0x51), RGB(0x61, 0x61, 0x61),
109 RGB(0x71, 0x71, 0x71), RGB(0x82, 0x82, 0x82), RGB(0x92, 0x92, 0x92), RGB(0xA2, 0xA2, 0xA2),
110 RGB(0xB6, 0xB6, 0xB6), RGB(0xCB, 0xCB, 0xCB), RGB(0xE3, 0xE3, 0xE3), RGB(0xFF, 0xFF, 0xFF),
111 RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x7D, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF),
112 RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x7D), RGB(0xFF, 0x00, 0x41),
113 RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x7D, 0x00), RGB(0xFF, 0xBE, 0x00),
114 RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x7D, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00),
115 RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x7D), RGB(0x00, 0xFF, 0xBE),
116 RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x7D, 0xFF), RGB(0x00, 0x41, 0xFF),
117 RGB(0x7D, 0x7D, 0xFF), RGB(0x9E, 0x7D, 0xFF), RGB(0xBE, 0x7D, 0xFF), RGB(0xDF, 0x7D, 0xFF),
118 RGB(0xFF, 0x7D, 0xFF), RGB(0xFF, 0x7D, 0xDF), RGB(0xFF, 0x7D, 0xBE), RGB(0xFF, 0x7D, 0x9E),
119
120 RGB(0xFF, 0x7D, 0x7D), RGB(0xFF, 0x9E, 0x7D), RGB(0xFF, 0xBE, 0x7D), RGB(0xFF, 0xDF, 0x7D),
121 RGB(0xFF, 0xFF, 0x7D), RGB(0xDF, 0xFF, 0x7D), RGB(0xBE, 0xFF, 0x7D), RGB(0x9E, 0xFF, 0x7D),
122 RGB(0x7D, 0xFF, 0x7D), RGB(0x7D, 0xFF, 0x9E), RGB(0x7D, 0xFF, 0xBE), RGB(0x7D, 0xFF, 0xDF),
123 RGB(0x7D, 0xFF, 0xFF), RGB(0x7D, 0xDF, 0xFF), RGB(0x7D, 0xBE, 0xFF), RGB(0x7D, 0x9E, 0xFF),
124 RGB(0xB6, 0xB6, 0xFF), RGB(0xC7, 0xB6, 0xFF), RGB(0xDB, 0xB6, 0xFF), RGB(0xEB, 0xB6, 0xFF),
125 RGB(0xFF, 0xB6, 0xFF), RGB(0xFF, 0xB6, 0xEB), RGB(0xFF, 0xB6, 0xDB), RGB(0xFF, 0xB6, 0xC7),
126 RGB(0xFF, 0xB6, 0xB6), RGB(0xFF, 0xC7, 0xB6), RGB(0xFF, 0xDB, 0xB6), RGB(0xFF, 0xEB, 0xB6),
127 RGB(0xFF, 0xFF, 0xB6), RGB(0xEB, 0xFF, 0xB6), RGB(0xDB, 0xFF, 0xB6), RGB(0xC7, 0xFF, 0xB6),
128 RGB(0xB6, 0xFF, 0xB6), RGB(0xB6, 0xFF, 0xC7), RGB(0xB6, 0xFF, 0xDB), RGB(0xB6, 0xFF, 0xEB),
129 RGB(0xB6, 0xFF, 0xFF), RGB(0xB6, 0xEB, 0xFF), RGB(0xB6, 0xDB, 0xFF), RGB(0xB6, 0xC7, 0xFF),
130 RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x38, 0x00, 0x71), RGB(0x55, 0x00, 0x71),
131 RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x38), RGB(0x71, 0x00, 0x1C),
132 RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x38, 0x00), RGB(0x71, 0x55, 0x00),
133 RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x38, 0x71, 0x00), RGB(0x1C, 0x71, 0x00),
134 RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x38), RGB(0x00, 0x71, 0x55),
135 RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x38, 0x71), RGB(0x00, 0x1C, 0x71),
136
137 RGB(0x38, 0x38, 0x71), RGB(0x45, 0x38, 0x71), RGB(0x55, 0x38, 0x71), RGB(0x61, 0x38, 0x71),
138 RGB(0x71, 0x38, 0x71), RGB(0x71, 0x38, 0x61), RGB(0x71, 0x38, 0x55), RGB(0x71, 0x38, 0x45),
139 RGB(0x71, 0x38, 0x38), RGB(0x71, 0x45, 0x38), RGB(0x71, 0x55, 0x38), RGB(0x71, 0x61, 0x38),
140 RGB(0x71, 0x71, 0x38), RGB(0x61, 0x71, 0x38), RGB(0x55, 0x71, 0x38), RGB(0x45, 0x71, 0x38),
141 RGB(0x38, 0x71, 0x38), RGB(0x38, 0x71, 0x45), RGB(0x38, 0x71, 0x55), RGB(0x38, 0x71, 0x61),
142 RGB(0x38, 0x71, 0x71), RGB(0x38, 0x61, 0x71), RGB(0x38, 0x55, 0x71), RGB(0x38, 0x45, 0x71),
143 RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71),
144 RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59),
145 RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51),
146 RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51),
147 RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69),
148 RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71),
149 RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x30, 0x00, 0x41),
150 RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x30), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10),
151 RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x30, 0x00),
152 RGB(0x41, 0x41, 0x00), RGB(0x30, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00),
153
154 RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x30),
155 RGB(0x00, 0x41, 0x41), RGB(0x00, 0x30, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41),
156 RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x30, 0x20, 0x41), RGB(0x38, 0x20, 0x41),
157 RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x38), RGB(0x41, 0x20, 0x30), RGB(0x41, 0x20, 0x28),
158 RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x30, 0x20), RGB(0x41, 0x38, 0x20),
159 RGB(0x41, 0x41, 0x20), RGB(0x38, 0x41, 0x20), RGB(0x30, 0x41, 0x20), RGB(0x28, 0x41, 0x20),
160 RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x30), RGB(0x20, 0x41, 0x38),
161 RGB(0x20, 0x41, 0x41), RGB(0x20, 0x38, 0x41), RGB(0x20, 0x30, 0x41), RGB(0x20, 0x28, 0x41),
162 RGB(0x2C, 0x2C, 0x41), RGB(0x30, 0x2C, 0x41), RGB(0x34, 0x2C, 0x41), RGB(0x3C, 0x2C, 0x41),
163 RGB(0x41, 0x2C, 0x41), RGB(0x41, 0x2C, 0x3C), RGB(0x41, 0x2C, 0x34), RGB(0x41, 0x2C, 0x30),
164 RGB(0x41, 0x2C, 0x2C), RGB(0x41, 0x30, 0x2C), RGB(0x41, 0x34, 0x2C), RGB(0x41, 0x3C, 0x2C),
165 RGB(0x41, 0x41, 0x2C), RGB(0x3C, 0x41, 0x2C), RGB(0x34, 0x41, 0x2C), RGB(0x30, 0x41, 0x2C),
166 RGB(0x2C, 0x41, 0x2C), RGB(0x2C, 0x41, 0x30), RGB(0x2C, 0x41, 0x34), RGB(0x2C, 0x41, 0x3C),
167 RGB(0x2C, 0x41, 0x41), RGB(0x2C, 0x3C, 0x41), RGB(0x2C, 0x34, 0x41), RGB(0x2C, 0x30, 0x41),
168 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
169 RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00)
170 };
171
172 #endif
173
174 static BYTE VgaMemory[VGA_NUM_BANKS * VGA_BANK_SIZE];
175 static LPVOID ConsoleFramebuffer = NULL;
176 static HANDLE TextConsoleBuffer = NULL;
177 static HANDLE GraphicsConsoleBuffer = NULL;
178 static HANDLE ConsoleMutex = NULL;
179 static HPALETTE PaletteHandle = NULL;
180 static BOOLEAN DoubleVision = FALSE;
181
182 static BYTE VgaLatchRegisters[VGA_NUM_BANKS] = {0, 0, 0, 0};
183
184 static BYTE VgaMiscRegister;
185 static BYTE VgaFeatureRegister;
186
187 static BYTE VgaSeqIndex = VGA_SEQ_RESET_REG;
188 static BYTE VgaSeqRegisters[VGA_SEQ_MAX_REG];
189
190 static BYTE VgaCrtcIndex = VGA_CRTC_HORZ_TOTAL_REG;
191 static BYTE VgaCrtcRegisters[VGA_CRTC_MAX_REG];
192
193 static BYTE VgaGcIndex = VGA_GC_RESET_REG;
194 static BYTE VgaGcRegisters[VGA_GC_MAX_REG];
195
196 static BOOLEAN VgaAcLatch = FALSE;
197 static BOOLEAN VgaAcPalDisable = TRUE;
198 static BYTE VgaAcIndex = VGA_AC_PAL_0_REG;
199 static BYTE VgaAcRegisters[VGA_AC_MAX_REG];
200
201 // static VGA_REGISTERS VgaRegisters;
202
203 static BYTE VgaDacMask = 0xFF;
204 static WORD VgaDacIndex = 0;
205 static BOOLEAN VgaDacReadWrite = FALSE;
206 static BYTE VgaDacRegisters[VGA_PALETTE_SIZE];
207
208 static BOOLEAN InVerticalRetrace = FALSE;
209 static BOOLEAN InHorizontalRetrace = FALSE;
210
211 static BOOLEAN NeedsUpdate = FALSE;
212 static BOOLEAN ModeChanged = TRUE;
213 static BOOLEAN CursorMoved = FALSE;
214 static BOOLEAN PaletteChanged = FALSE;
215
216 static
217 enum SCREEN_MODE
218 {
219 TEXT_MODE,
220 GRAPHICS_MODE
221 } ScreenMode = TEXT_MODE;
222
223 static SMALL_RECT UpdateRectangle = { 0, 0, 0, 0 };
224
225 /* PRIVATE FUNCTIONS **********************************************************/
226
227 static inline DWORD VgaGetAddressSize(VOID)
228 {
229 if (VgaCrtcRegisters[VGA_CRTC_UNDERLINE_REG] & VGA_CRTC_UNDERLINE_DWORD)
230 {
231 /* Double-word addressing */
232 return 4; // sizeof(DWORD)
233 }
234
235 if (VgaCrtcRegisters[VGA_CRTC_MODE_CONTROL_REG] & VGA_CRTC_MODE_CONTROL_BYTE)
236 {
237 /* Byte addressing */
238 return 1; // sizeof(BYTE)
239 }
240
241 /* Word addressing */
242 return 2; // sizeof(WORD)
243 }
244
245 static inline DWORD VgaTranslateReadAddress(DWORD Address)
246 {
247 DWORD Offset = Address - VgaGetVideoBaseAddress();
248 BYTE Plane;
249
250 /* Check for chain-4 and odd-even mode */
251 if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4)
252 {
253 /* The lowest two bits are the plane number */
254 Plane = Offset & 3;
255 Offset >>= 2;
256 }
257 else if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE)
258 {
259 /* The LSB is the plane number */
260 Plane = Offset & 1;
261 Offset >>= 1;
262 }
263 else
264 {
265 /* Use the read mode */
266 Plane = VgaGcRegisters[VGA_GC_READ_MAP_SEL_REG] & 0x03;
267 }
268
269 /* Multiply the offset by the address size */
270 Offset *= VgaGetAddressSize();
271
272 return Offset + Plane * VGA_BANK_SIZE;
273 }
274
275 static inline DWORD VgaTranslateWriteAddress(DWORD Address)
276 {
277 DWORD Offset = Address - VgaGetVideoBaseAddress();
278
279 /* Check for chain-4 and odd-even mode */
280 if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4)
281 {
282 /* Shift the offset to the right by 2 */
283 Offset >>= 2;
284 }
285 else if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE)
286 {
287 /* Shift the offset to the right by 1 */
288 Offset >>= 1;
289 }
290
291 /* Multiply the offset by the address size */
292 Offset *= VgaGetAddressSize();
293
294 /* Return the offset on plane 0 */
295 return Offset;
296 }
297
298 static inline BYTE VgaTranslateByteForWriting(BYTE Data, BYTE Plane)
299 {
300 BYTE WriteMode = VgaGcRegisters[VGA_GC_MODE_REG] & 3;
301 BYTE BitMask = VgaGcRegisters[VGA_GC_BITMASK_REG];
302
303 if (WriteMode == 1)
304 {
305 /* In write mode 1 just return the latch register */
306 return VgaLatchRegisters[Plane];
307 }
308
309 if (WriteMode != 2)
310 {
311 /* Write modes 0 and 3 rotate the data to the right first */
312 BYTE RotateCount = VgaGcRegisters[VGA_GC_ROTATE_REG] & 7;
313 Data = LOBYTE(((DWORD)Data >> RotateCount) | ((DWORD)Data << (8 - RotateCount)));
314 }
315 else
316 {
317 /* Write mode 2 expands the appropriate bit to all 8 bits */
318 Data = (Data & (1 << Plane)) ? 0xFF : 0x00;
319 }
320
321 if (WriteMode == 0)
322 {
323 /*
324 * In write mode 0, the enable set/reset register decides if the
325 * set/reset bit should be expanded to all 8 bits.
326 */
327 if (VgaGcRegisters[VGA_GC_ENABLE_RESET_REG] & (1 << Plane))
328 {
329 /* Copy the bit from the set/reset register to all 8 bits */
330 Data = (VgaGcRegisters[VGA_GC_RESET_REG] & (1 << Plane)) ? 0xFF : 0x00;
331 }
332 }
333
334 if (WriteMode != 3)
335 {
336 /* Write modes 0 and 2 then perform a logical operation on the data and latch */
337 BYTE LogicalOperation = (VgaGcRegisters[VGA_GC_ROTATE_REG] >> 3) & 3;
338
339 if (LogicalOperation == 1) Data &= VgaLatchRegisters[Plane];
340 else if (LogicalOperation == 2) Data |= VgaLatchRegisters[Plane];
341 else if (LogicalOperation == 3) Data ^= VgaLatchRegisters[Plane];
342 }
343 else
344 {
345 /* For write mode 3, we AND the bitmask with the data, which is used as the new bitmask */
346 BitMask &= Data;
347
348 /* Then we expand the bit in the set/reset field */
349 Data = (VgaGcRegisters[VGA_GC_RESET_REG] & (1 << Plane)) ? 0xFF : 0x00;
350 }
351
352 /* Bits cleared in the bitmask are replaced with latch register bits */
353 Data = (Data & BitMask) | (VgaLatchRegisters[Plane] & (~BitMask));
354
355 /* Return the byte */
356 return Data;
357 }
358
359 static inline VOID VgaMarkForUpdate(SHORT Row, SHORT Column)
360 {
361 /* Check if this is the first time the rectangle is updated */
362 if (!NeedsUpdate)
363 {
364 UpdateRectangle.Left = UpdateRectangle.Top = MAXSHORT;
365 UpdateRectangle.Right = UpdateRectangle.Bottom = MINSHORT;
366 }
367
368 /* Expand the rectangle to include the point */
369 UpdateRectangle.Left = min(UpdateRectangle.Left, Column);
370 UpdateRectangle.Right = max(UpdateRectangle.Right, Column);
371 UpdateRectangle.Top = min(UpdateRectangle.Top, Row);
372 UpdateRectangle.Bottom = max(UpdateRectangle.Bottom, Row);
373
374 /* Set the update request flag */
375 NeedsUpdate = TRUE;
376 }
377
378 static VOID VgaWriteSequencer(BYTE Data)
379 {
380 ASSERT(VgaSeqIndex < VGA_SEQ_MAX_REG);
381
382 /* Save the value */
383 VgaSeqRegisters[VgaSeqIndex] = Data;
384 }
385
386 static VOID VgaWriteGc(BYTE Data)
387 {
388 ASSERT(VgaGcIndex < VGA_GC_MAX_REG);
389
390 /* Save the value */
391 VgaGcRegisters[VgaGcIndex] = Data;
392
393 /* Check the index */
394 switch (VgaGcIndex)
395 {
396 case VGA_GC_MISC_REG:
397 {
398 /* The GC misc register decides if it's text or graphics mode */
399 ModeChanged = TRUE;
400 break;
401 }
402 }
403 }
404
405 static VOID VgaWriteCrtc(BYTE Data)
406 {
407 ASSERT(VgaGcIndex < VGA_CRTC_MAX_REG);
408
409 /* Save the value */
410 VgaCrtcRegisters[VgaCrtcIndex] = Data;
411
412 /* Check the index */
413 switch (VgaCrtcIndex)
414 {
415 case VGA_CRTC_END_HORZ_DISP_REG:
416 case VGA_CRTC_VERT_DISP_END_REG:
417 case VGA_CRTC_OVERFLOW_REG:
418 {
419 /* The video mode has changed */
420 ModeChanged = TRUE;
421 break;
422 }
423
424 case VGA_CRTC_CURSOR_LOC_LOW_REG:
425 case VGA_CRTC_CURSOR_LOC_HIGH_REG:
426 case VGA_CRTC_CURSOR_START_REG:
427 case VGA_CRTC_CURSOR_END_REG:
428 {
429 /* Set the cursor moved flag */
430 CursorMoved = TRUE;
431 break;
432 }
433 }
434 }
435
436 static VOID VgaWriteDac(BYTE Data)
437 {
438 INT PaletteIndex;
439 PALETTEENTRY Entry;
440
441 /* Set the value */
442 VgaDacRegisters[VgaDacIndex] = Data;
443
444 /* Find the palette index */
445 PaletteIndex = VgaDacIndex / 3;
446
447 /* Fill the entry structure */
448 Entry.peRed = VGA_DAC_TO_COLOR(VgaDacRegisters[PaletteIndex * 3]);
449 Entry.peGreen = VGA_DAC_TO_COLOR(VgaDacRegisters[PaletteIndex * 3 + 1]);
450 Entry.peBlue = VGA_DAC_TO_COLOR(VgaDacRegisters[PaletteIndex * 3 + 2]);
451 Entry.peFlags = 0;
452
453 /* Update the palette entry and set the palette change flag */
454 SetPaletteEntries(PaletteHandle, PaletteIndex, 1, &Entry);
455 PaletteChanged = TRUE;
456
457 /* Update the index */
458 VgaDacIndex++;
459 VgaDacIndex %= VGA_PALETTE_SIZE;
460 }
461
462 static VOID VgaWriteAc(BYTE Data)
463 {
464 ASSERT(VgaAcIndex < VGA_AC_MAX_REG);
465
466 /* Save the value */
467 if (VgaAcIndex <= VGA_AC_PAL_F_REG)
468 {
469 if (VgaAcPalDisable) return;
470
471 // DbgPrint(" AC Palette Writing %d to index %d\n", Data, VgaAcIndex);
472 if (VgaAcRegisters[VgaAcIndex] != Data)
473 {
474 /* Update the AC register and set the palette change flag */
475 VgaAcRegisters[VgaAcIndex] = Data;
476 PaletteChanged = TRUE;
477 }
478 }
479 else
480 {
481 VgaAcRegisters[VgaAcIndex] = Data;
482 }
483 }
484
485 static VOID VgaRestoreDefaultPalette(PPALETTEENTRY Entries, USHORT NumOfEntries)
486 {
487 USHORT i;
488
489 /* Copy the colors of the default palette to the DAC and console palette */
490 for (i = 0; i < NumOfEntries; i++)
491 {
492 /* Set the palette entries */
493 Entries[i].peRed = GetRValue(VgaDefaultPalette[i]);
494 Entries[i].peGreen = GetGValue(VgaDefaultPalette[i]);
495 Entries[i].peBlue = GetBValue(VgaDefaultPalette[i]);
496 Entries[i].peFlags = 0;
497
498 /* Set the DAC registers */
499 VgaDacRegisters[i * 3] = VGA_COLOR_TO_DAC(GetRValue(VgaDefaultPalette[i]));
500 VgaDacRegisters[i * 3 + 1] = VGA_COLOR_TO_DAC(GetGValue(VgaDefaultPalette[i]));
501 VgaDacRegisters[i * 3 + 2] = VGA_COLOR_TO_DAC(GetBValue(VgaDefaultPalette[i]));
502 }
503 }
504
505 static BOOLEAN VgaInitializePalette(VOID)
506 {
507 LPLOGPALETTE Palette;
508
509 /* Allocate storage space for the palette */
510 Palette = (LPLOGPALETTE)HeapAlloc(GetProcessHeap(),
511 HEAP_ZERO_MEMORY,
512 sizeof(LOGPALETTE) +
513 VGA_MAX_COLORS * sizeof(PALETTEENTRY));
514 if (Palette == NULL) return FALSE;
515
516 /* Initialize the palette */
517 Palette->palVersion = 0x0300;
518 Palette->palNumEntries = VGA_MAX_COLORS;
519
520 /* Restore the default palette */
521 VgaRestoreDefaultPalette(Palette->palPalEntry, Palette->palNumEntries);
522
523 /* Create the palette */
524 PaletteHandle = CreatePalette(Palette);
525
526 /* Free the palette */
527 HeapFree(GetProcessHeap(), 0, Palette);
528
529 /* Fail if the palette wasn't successfully created... */
530 if (PaletteHandle == NULL) return FALSE;
531
532 /* ... otherwise return success */
533 return TRUE;
534 }
535
536 static BOOL VgaEnterGraphicsMode(PCOORD Resolution)
537 {
538 DWORD i;
539 CONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo;
540 BYTE BitmapInfoBuffer[VGA_BITMAP_INFO_SIZE];
541 LPBITMAPINFO BitmapInfo = (LPBITMAPINFO)BitmapInfoBuffer;
542 LPWORD PaletteIndex = (LPWORD)(BitmapInfo->bmiColors);
543
544 LONG Width = Resolution->X;
545 LONG Height = Resolution->Y;
546
547 /* Use DoubleVision mode if the resolution is too small */
548 if (Width < VGA_MINIMUM_WIDTH && Height < VGA_MINIMUM_HEIGHT)
549 {
550 DoubleVision = TRUE;
551 Width *= 2;
552 Height *= 2;
553 }
554 else
555 {
556 DoubleVision = FALSE;
557 }
558
559 /* Fill the bitmap info header */
560 ZeroMemory(&BitmapInfo->bmiHeader, sizeof(BITMAPINFOHEADER));
561 BitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
562 BitmapInfo->bmiHeader.biWidth = Width;
563 BitmapInfo->bmiHeader.biHeight = Height;
564 BitmapInfo->bmiHeader.biBitCount = 8;
565 BitmapInfo->bmiHeader.biPlanes = 1;
566 BitmapInfo->bmiHeader.biCompression = BI_RGB;
567 BitmapInfo->bmiHeader.biSizeImage = Width * Height /* * 1 == biBitCount / 8 */;
568
569 /* Fill the palette data */
570 for (i = 0; i < (VGA_PALETTE_SIZE / 3); i++) PaletteIndex[i] = (WORD)i;
571
572 /* Fill the console graphics buffer info */
573 GraphicsBufferInfo.dwBitMapInfoLength = VGA_BITMAP_INFO_SIZE;
574 GraphicsBufferInfo.lpBitMapInfo = BitmapInfo;
575 GraphicsBufferInfo.dwUsage = DIB_PAL_COLORS;
576
577 /* Create the buffer */
578 GraphicsConsoleBuffer = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
579 FILE_SHARE_READ | FILE_SHARE_WRITE,
580 NULL,
581 CONSOLE_GRAPHICS_BUFFER,
582 &GraphicsBufferInfo);
583 if (GraphicsConsoleBuffer == INVALID_HANDLE_VALUE) return FALSE;
584
585 /* Save the framebuffer address and mutex */
586 ConsoleFramebuffer = GraphicsBufferInfo.lpBitMap;
587 ConsoleMutex = GraphicsBufferInfo.hMutex;
588
589 /* Clear the framebuffer */
590 ZeroMemory(ConsoleFramebuffer, BitmapInfo->bmiHeader.biSizeImage);
591
592 /* Set the active buffer */
593 SetConsoleActiveScreenBuffer(GraphicsConsoleBuffer);
594
595 /* Set the graphics mode palette */
596 SetConsolePalette(GraphicsConsoleBuffer,
597 PaletteHandle,
598 SYSPAL_NOSTATIC256);
599
600 /* Set the screen mode flag */
601 ScreenMode = GRAPHICS_MODE;
602
603 return TRUE;
604 }
605
606 static VOID VgaLeaveGraphicsMode(VOID)
607 {
608 /* Release the console framebuffer mutex if needed */
609 ReleaseMutex(ConsoleMutex);
610
611 /* Switch back to the text buffer */
612 SetConsoleActiveScreenBuffer(TextConsoleBuffer);
613
614 /* Cleanup the video data */
615 CloseHandle(ConsoleMutex);
616 ConsoleMutex = NULL;
617 CloseHandle(GraphicsConsoleBuffer);
618 GraphicsConsoleBuffer = NULL;
619 DoubleVision = FALSE;
620 }
621
622 static BOOL VgaEnterTextMode(PCOORD Resolution)
623 {
624 /* Resize the console */
625 SetConsoleScreenBufferSize(TextConsoleBuffer, *Resolution);
626
627 /* Allocate a framebuffer */
628 ConsoleFramebuffer = HeapAlloc(GetProcessHeap(),
629 HEAP_ZERO_MEMORY,
630 Resolution->X * Resolution->Y
631 * sizeof(CHAR_INFO));
632 if (ConsoleFramebuffer == NULL)
633 {
634 DisplayMessage(L"An unexpected error occurred!\n");
635 VdmRunning = FALSE;
636 return FALSE;
637 }
638
639 /*
640 * Set the text mode palette.
641 *
642 * WARNING: This call should fail on Windows (and therefore
643 * we get the default palette and our external behaviour is
644 * just like Windows' one), but it should success on ReactOS
645 * (so that we get console palette changes even for text-mode
646 * screen-buffers, which is a new feature on ReactOS).
647 */
648 SetConsolePalette(TextConsoleBuffer,
649 PaletteHandle,
650 SYSPAL_NOSTATIC256);
651
652 /* Set the screen mode flag */
653 ScreenMode = TEXT_MODE;
654
655 return TRUE;
656 }
657
658 static VOID VgaLeaveTextMode(VOID)
659 {
660 /* Free the old framebuffer */
661 HeapFree(GetProcessHeap(), 0, ConsoleFramebuffer);
662 ConsoleFramebuffer = NULL;
663 }
664
665 static VOID VgaChangeMode(VOID)
666 {
667 COORD Resolution = VgaGetDisplayResolution();
668
669 /* Reset the mode change flag */
670 // ModeChanged = FALSE;
671
672 if (ScreenMode == GRAPHICS_MODE)
673 {
674 /* Leave the current graphics mode */
675 VgaLeaveGraphicsMode();
676 }
677 else
678 {
679 /* Leave the current text mode */
680 VgaLeaveTextMode();
681 }
682
683 /* Check if the new mode is alphanumeric */
684 if (!(VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA))
685 {
686 /* Enter new text mode */
687 if (!VgaEnterTextMode(&Resolution))
688 {
689 DisplayMessage(L"An unexpected VGA error occurred while switching into text mode.");
690 VdmRunning = FALSE;
691 return;
692 }
693 }
694 else
695 {
696 /* Enter 8-bit graphics mode */
697 if (!VgaEnterGraphicsMode(&Resolution))
698 {
699 DisplayMessage(L"An unexpected VGA error occurred while switching into graphics mode.");
700 VdmRunning = FALSE;
701 return;
702 }
703 }
704
705 /* Trigger a full update of the screen */
706 NeedsUpdate = TRUE;
707 UpdateRectangle.Left = 0;
708 UpdateRectangle.Top = 0;
709 UpdateRectangle.Right = Resolution.X;
710 UpdateRectangle.Bottom = Resolution.Y;
711
712 /* Reset the mode change flag */
713 ModeChanged = FALSE;
714 }
715
716 static VOID VgaUpdateFramebuffer(VOID)
717 {
718 INT i, j, k;
719 COORD Resolution = VgaGetDisplayResolution();
720 DWORD AddressSize = VgaGetAddressSize();
721 DWORD Address = MAKEWORD(VgaCrtcRegisters[VGA_CRTC_START_ADDR_LOW_REG],
722 VgaCrtcRegisters[VGA_CRTC_START_ADDR_HIGH_REG]);
723 DWORD ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2;
724
725 /*
726 * If console framebuffer is NULL, that means something went wrong
727 * earlier and this is the final display refresh.
728 */
729 if (ConsoleFramebuffer == NULL) return;
730
731 /* Check if this is text mode or graphics mode */
732 if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA)
733 {
734 /* Graphics mode */
735 PBYTE GraphicsBuffer = (PBYTE)ConsoleFramebuffer;
736
737 /*
738 * Synchronize access to the graphics framebuffer
739 * with the console framebuffer mutex.
740 */
741 WaitForSingleObject(ConsoleMutex, INFINITE);
742
743 /* Loop through the scanlines */
744 for (i = 0; i < Resolution.Y; i++)
745 {
746 /* Loop through the pixels */
747 for (j = 0; j < Resolution.X; j++)
748 {
749 BYTE PixelData = 0;
750
751 /* Check the shifting mode */
752 if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_SHIFT256)
753 {
754 /* 4 bits shifted from each plane */
755
756 /* Check if this is 16 or 256 color mode */
757 if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT)
758 {
759 /* One byte per pixel */
760 PixelData = VgaMemory[(j % VGA_NUM_BANKS) * VGA_BANK_SIZE
761 + (Address + (j / VGA_NUM_BANKS))
762 * AddressSize];
763 }
764 else
765 {
766 /* 4-bits per pixel */
767
768 PixelData = VgaMemory[(j % VGA_NUM_BANKS) * VGA_BANK_SIZE
769 + (Address + (j / (VGA_NUM_BANKS * 2)))
770 * AddressSize];
771
772 /* Check if we should use the highest 4 bits or lowest 4 */
773 if (((j / VGA_NUM_BANKS) % 2) == 0)
774 {
775 /* Highest 4 */
776 PixelData >>= 4;
777 }
778 else
779 {
780 /* Lowest 4 */
781 PixelData &= 0x0F;
782 }
783 }
784 }
785 else if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_SHIFTREG)
786 {
787 /* Check if this is 16 or 256 color mode */
788 if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT)
789 {
790 // TODO: NOT IMPLEMENTED
791 DPRINT1("8-bit interleaved mode is not implemented!\n");
792 }
793 else
794 {
795 /*
796 * 2 bits shifted from plane 0 and 2 for the first 4 pixels,
797 * then 2 bits shifted from plane 1 and 3 for the next 4
798 */
799 BYTE LowPlaneData = VgaMemory[((j / 4) % 2) * VGA_BANK_SIZE
800 + (Address + (j / 4)) * AddressSize];
801 BYTE HighPlaneData = VgaMemory[(((j / 4) % 2) + 2) * VGA_BANK_SIZE
802 + (Address + (j / 4)) * AddressSize];
803
804 /* Extract the two bits from each plane */
805 LowPlaneData = (LowPlaneData >> (6 - ((j % 4) * 2))) & 3;
806 HighPlaneData = (HighPlaneData >> (6 - ((j % 4) * 2))) & 3;
807
808 /* Combine them into the pixel */
809 PixelData = LowPlaneData | (HighPlaneData << 2);
810 }
811 }
812 else
813 {
814 /* 1 bit shifted from each plane */
815
816 /* Check if this is 16 or 256 color mode */
817 if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT)
818 {
819 /* 8 bits per pixel, 2 on each plane */
820
821 for (k = 0; k < VGA_NUM_BANKS; k++)
822 {
823 /* The data is on plane k, 4 pixels per byte */
824 BYTE PlaneData = VgaMemory[k * VGA_BANK_SIZE
825 + (Address + (j / VGA_NUM_BANKS))
826 * AddressSize];
827
828 /* The mask of the first bit in the pair */
829 BYTE BitMask = 1 << (((3 - (j % VGA_NUM_BANKS)) * 2) + 1);
830
831 /* Bits 0, 1, 2 and 3 come from the first bit of the pair */
832 if (PlaneData & BitMask) PixelData |= 1 << k;
833
834 /* Bits 4, 5, 6 and 7 come from the second bit of the pair */
835 if (PlaneData & (BitMask >> 1)) PixelData |= 1 << (k + 4);
836 }
837 }
838 else
839 {
840 /* 4 bits per pixel, 1 on each plane */
841
842 for (k = 0; k < VGA_NUM_BANKS; k++)
843 {
844 BYTE PlaneData = VgaMemory[k * VGA_BANK_SIZE
845 + (Address + (j / (VGA_NUM_BANKS * 2)))
846 * AddressSize];
847
848 /* If the bit on that plane is set, set it */
849 if (PlaneData & (1 << (7 - (j % 8)))) PixelData |= 1 << k;
850 }
851 }
852 }
853
854 if (!(VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT))
855 {
856 /*
857 * In 16 color mode, the value is an index to the AC registers
858 * if external palette access is disabled, otherwise (in case
859 * of palette loading) it is a blank pixel.
860 */
861 PixelData = (VgaAcPalDisable ? VgaAcRegisters[PixelData & 0x0F]
862 : 0);
863 }
864
865 /* Take into account DoubleVision mode when checking for pixel updates */
866 if (DoubleVision)
867 {
868 /* Now check if the resulting pixel data has changed */
869 if (GraphicsBuffer[(i * Resolution.X * 4) + (j * 2)] != PixelData)
870 {
871 /* Yes, write the new value */
872 GraphicsBuffer[(i * Resolution.X * 4) + (j * 2)] = PixelData;
873 GraphicsBuffer[(i * Resolution.X * 4) + (j * 2 + 1)] = PixelData;
874 GraphicsBuffer[((i * 2 + 1) * Resolution.X * 2) + (j * 2)] = PixelData;
875 GraphicsBuffer[((i * 2 + 1) * Resolution.X * 2) + (j * 2 + 1)] = PixelData;
876
877 /* Mark the specified pixel as changed */
878 VgaMarkForUpdate(i, j);
879 }
880 }
881 else
882 {
883 /* Now check if the resulting pixel data has changed */
884 if (GraphicsBuffer[i * Resolution.X + j] != PixelData)
885 {
886 /* Yes, write the new value */
887 GraphicsBuffer[i * Resolution.X + j] = PixelData;
888
889 /* Mark the specified pixel as changed */
890 VgaMarkForUpdate(i, j);
891 }
892 }
893 }
894
895 /* Move to the next scanline */
896 Address += ScanlineSize;
897 }
898
899 /*
900 * Release the console framebuffer mutex
901 * so that we allow for repainting.
902 */
903 ReleaseMutex(ConsoleMutex);
904 }
905 else
906 {
907 /* Text mode */
908 PCHAR_INFO CharBuffer = (PCHAR_INFO)ConsoleFramebuffer;
909
910 /* Loop through the scanlines */
911 for (i = 0; i < Resolution.Y; i++)
912 {
913 /* Loop through the characters */
914 for (j = 0; j < Resolution.X; j++)
915 {
916 DWORD CurrentAddr = LOWORD((Address + j) * AddressSize);
917 CHAR_INFO CharInfo;
918
919 /* Plane 0 holds the character itself */
920 CharInfo.Char.AsciiChar = VgaMemory[CurrentAddr];
921
922 /* Plane 1 holds the attribute */
923 CharInfo.Attributes = VgaMemory[CurrentAddr + VGA_BANK_SIZE];
924
925 /* Now check if the resulting character data has changed */
926 if ((CharBuffer[i * Resolution.X + j].Char.AsciiChar != CharInfo.Char.AsciiChar)
927 || (CharBuffer[i * Resolution.X + j].Attributes != CharInfo.Attributes))
928 {
929 /* Yes, write the new value */
930 CharBuffer[i * Resolution.X + j] = CharInfo;
931
932 /* Mark the specified cell as changed */
933 VgaMarkForUpdate(i, j);
934 }
935 }
936
937 /* Move to the next scanline */
938 Address += ScanlineSize;
939 }
940 }
941 }
942
943 static VOID VgaUpdateTextCursor(VOID)
944 {
945 COORD Position;
946 CONSOLE_CURSOR_INFO CursorInfo;
947 BYTE CursorStart = VgaCrtcRegisters[VGA_CRTC_CURSOR_START_REG] & 0x3F;
948 BYTE CursorEnd = VgaCrtcRegisters[VGA_CRTC_CURSOR_END_REG] & 0x1F;
949 DWORD ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2;
950 BYTE TextSize = 1 + (VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & 0x1F);
951 WORD Location = MAKEWORD(VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_LOW_REG],
952 VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_HIGH_REG]);
953
954 /* Just return if we are not in text mode */
955 if ((VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA) != 0) return;
956
957 if (CursorStart < CursorEnd)
958 {
959 /* Visible cursor */
960 CursorInfo.bVisible = TRUE;
961 CursorInfo.dwSize = (100 * (CursorEnd - CursorStart)) / TextSize;
962 }
963 else
964 {
965 /* No cursor */
966 CursorInfo.bVisible = FALSE;
967 CursorInfo.dwSize = 0;
968 }
969
970 /* Add the cursor skew to the location */
971 Location += (VgaCrtcRegisters[VGA_CRTC_CURSOR_END_REG] >> 5) & 3;
972
973 /* Find the coordinates of the new position */
974 Position.X = (WORD)(Location % ScanlineSize);
975 Position.Y = (WORD)(Location / ScanlineSize);
976
977 /* Update the physical cursor */
978 SetConsoleCursorInfo(TextConsoleBuffer, &CursorInfo);
979 SetConsoleCursorPosition(TextConsoleBuffer, Position);
980
981 /* Reset the cursor move flag */
982 CursorMoved = FALSE;
983 }
984
985 /* PUBLIC FUNCTIONS ***********************************************************/
986
987 DWORD VgaGetVideoBaseAddress(VOID)
988 {
989 return MemoryBase[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03];
990 }
991
992 DWORD VgaGetVideoLimitAddress(VOID)
993 {
994 return MemoryLimit[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03];
995 }
996
997 COORD VgaGetDisplayResolution(VOID)
998 {
999 COORD Resolution;
1000 BYTE MaximumScanLine = 1 + (VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & 0x1F);
1001
1002 /* The low 8 bits are in the display registers */
1003 Resolution.X = VgaCrtcRegisters[VGA_CRTC_END_HORZ_DISP_REG];
1004 Resolution.Y = VgaCrtcRegisters[VGA_CRTC_VERT_DISP_END_REG];
1005
1006 /* Set the top bits from the overflow register */
1007 if (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VDE8)
1008 {
1009 Resolution.Y |= 1 << 8;
1010 }
1011 if (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VDE9)
1012 {
1013 Resolution.Y |= 1 << 9;
1014 }
1015
1016 /* Increase the values by 1 */
1017 Resolution.X++;
1018 Resolution.Y++;
1019
1020 if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA)
1021 {
1022 /* Multiply the horizontal resolution by the 9/8 dot mode */
1023 Resolution.X *= (VgaSeqRegisters[VGA_SEQ_CLOCK_REG] & VGA_SEQ_CLOCK_98DM)
1024 ? 8 : 9;
1025
1026 /* The horizontal resolution is halved in 8-bit mode */
1027 if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT) Resolution.X /= 2;
1028 }
1029
1030 if (VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & VGA_CRTC_MAXSCANLINE_DOUBLE)
1031 {
1032 /* Halve the vertical resolution */
1033 Resolution.Y >>= 1;
1034 }
1035
1036 /* Divide the vertical resolution by the maximum scan line (== font size in text mode) */
1037 Resolution.Y /= MaximumScanLine;
1038
1039 /* Return the resolution */
1040 return Resolution;
1041 }
1042
1043 VOID VgaRefreshDisplay(VOID)
1044 {
1045 HANDLE ConsoleBufferHandle = NULL;
1046 COORD Resolution;
1047
1048 /* Set the vertical retrace flag */
1049 InVerticalRetrace = TRUE;
1050
1051 /* If nothing has changed, just return */
1052 if (!ModeChanged && !CursorMoved && !PaletteChanged && !NeedsUpdate)
1053 return;
1054
1055 /* Retrieve the current resolution */
1056 Resolution = VgaGetDisplayResolution();
1057
1058 /* Change the display mode */
1059 if (ModeChanged) VgaChangeMode();
1060
1061 /* Change the text cursor location */
1062 if (CursorMoved) VgaUpdateTextCursor();
1063
1064 if (PaletteChanged)
1065 {
1066 /* Trigger a full update of the screen */
1067 NeedsUpdate = TRUE;
1068 UpdateRectangle.Left = 0;
1069 UpdateRectangle.Top = 0;
1070 UpdateRectangle.Right = Resolution.X;
1071 UpdateRectangle.Bottom = Resolution.Y;
1072
1073 PaletteChanged = FALSE;
1074 }
1075
1076 /* Update the contents of the framebuffer */
1077 VgaUpdateFramebuffer();
1078
1079 /* Ignore if there's nothing to update */
1080 if (!NeedsUpdate) return;
1081
1082 DPRINT("Updating screen rectangle (%d, %d, %d, %d)\n",
1083 UpdateRectangle.Left,
1084 UpdateRectangle.Top,
1085 UpdateRectangle.Right,
1086 UpdateRectangle.Bottom);
1087
1088 /* Check if this is text mode or graphics mode */
1089 if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA)
1090 {
1091 /* Graphics mode */
1092 ConsoleBufferHandle = GraphicsConsoleBuffer;
1093 }
1094 else
1095 {
1096 /* Text mode */
1097 COORD Origin = { UpdateRectangle.Left, UpdateRectangle.Top };
1098 ConsoleBufferHandle = TextConsoleBuffer;
1099
1100 /* Write the data to the console */
1101 WriteConsoleOutputA(TextConsoleBuffer,
1102 (PCHAR_INFO)ConsoleFramebuffer,
1103 Resolution,
1104 Origin,
1105 &UpdateRectangle);
1106 }
1107
1108 /* In DoubleVision mode, scale the update rectangle */
1109 if (DoubleVision)
1110 {
1111 UpdateRectangle.Left *= 2;
1112 UpdateRectangle.Top *= 2;
1113 UpdateRectangle.Right = UpdateRectangle.Right * 2 + 1;
1114 UpdateRectangle.Bottom = UpdateRectangle.Bottom * 2 + 1;
1115 }
1116
1117 /* Redraw the screen */
1118 InvalidateConsoleDIBits(ConsoleBufferHandle, &UpdateRectangle);
1119
1120 /* Clear the update flag */
1121 NeedsUpdate = FALSE;
1122 }
1123
1124 VOID VgaHorizontalRetrace(VOID)
1125 {
1126 /* Set the flag */
1127 InHorizontalRetrace = TRUE;
1128 }
1129
1130 VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size)
1131 {
1132 DWORD i;
1133 DWORD VideoAddress;
1134
1135 DPRINT("VgaReadMemory: Address 0x%08X, Size %lu\n", Address, Size);
1136
1137 /* Ignore if video RAM access is disabled */
1138 if ((VgaMiscRegister & VGA_MISC_RAM_ENABLED) == 0) return;
1139
1140 /* Loop through each byte */
1141 for (i = 0; i < Size; i++)
1142 {
1143 VideoAddress = VgaTranslateReadAddress(Address + i);
1144
1145 /* Load the latch registers */
1146 VgaLatchRegisters[0] = VgaMemory[LOWORD(VideoAddress)];
1147 VgaLatchRegisters[1] = VgaMemory[VGA_BANK_SIZE + LOWORD(VideoAddress)];
1148 VgaLatchRegisters[2] = VgaMemory[(2 * VGA_BANK_SIZE) + LOWORD(VideoAddress)];
1149 VgaLatchRegisters[3] = VgaMemory[(3 * VGA_BANK_SIZE) + LOWORD(VideoAddress)];
1150
1151 /* Copy the value to the buffer */
1152 Buffer[i] = VgaMemory[VideoAddress];
1153 }
1154 }
1155
1156 VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size)
1157 {
1158 DWORD i, j;
1159 DWORD VideoAddress;
1160
1161 DPRINT("VgaWriteMemory: Address 0x%08X, Size %lu\n", Address, Size);
1162
1163 /* Ignore if video RAM access is disabled */
1164 if ((VgaMiscRegister & VGA_MISC_RAM_ENABLED) == 0) return;
1165
1166 /* Also ignore if write access to all planes is disabled */
1167 if ((VgaSeqRegisters[VGA_SEQ_MASK_REG] & 0x0F) == 0x00) return;
1168
1169 /* Loop through each byte */
1170 for (i = 0; i < Size; i++)
1171 {
1172 VideoAddress = VgaTranslateWriteAddress(Address + i);
1173
1174 for (j = 0; j < VGA_NUM_BANKS; j++)
1175 {
1176 /* Make sure the page is writeable */
1177 if (!(VgaSeqRegisters[VGA_SEQ_MASK_REG] & (1 << j))) continue;
1178
1179 /* Check if this is chain-4 mode */
1180 if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4)
1181 {
1182 if (((Address + i) & 3) != j)
1183 {
1184 /* This plane will not be accessed */
1185 continue;
1186 }
1187 }
1188
1189 /* Check if this is odd-even mode */
1190 if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE)
1191 {
1192 if (((Address + i) & 1) != (j & 1))
1193 {
1194 /* This plane will not be accessed */
1195 continue;
1196 }
1197 }
1198
1199 /* Copy the value to the VGA memory */
1200 VgaMemory[VideoAddress + j * VGA_BANK_SIZE] = VgaTranslateByteForWriting(Buffer[i], j);
1201 }
1202 }
1203 }
1204
1205 BYTE WINAPI VgaReadPort(ULONG Port)
1206 {
1207 DPRINT("VgaReadPort: Port 0x%X\n", Port);
1208
1209 switch (Port)
1210 {
1211 case VGA_MISC_READ:
1212 return VgaMiscRegister;
1213
1214 case VGA_INSTAT0_READ:
1215 return 0; // Not implemented
1216
1217 case VGA_INSTAT1_READ_MONO:
1218 case VGA_INSTAT1_READ_COLOR:
1219 {
1220 BYTE Result = 0;
1221
1222 /* Reset the AC latch */
1223 VgaAcLatch = FALSE;
1224
1225 /* Set a flag if there is a vertical or horizontal retrace */
1226 if (InVerticalRetrace || InHorizontalRetrace) Result |= VGA_STAT_DD;
1227
1228 /* Set an additional flag if there was a vertical retrace */
1229 if (InVerticalRetrace) Result |= VGA_STAT_VRETRACE;
1230
1231 /* Clear the flags */
1232 InHorizontalRetrace = InVerticalRetrace = FALSE;
1233
1234 return Result;
1235 }
1236
1237 case VGA_FEATURE_READ:
1238 return VgaFeatureRegister;
1239
1240 case VGA_AC_INDEX:
1241 return VgaAcIndex;
1242
1243 case VGA_AC_READ:
1244 return VgaAcRegisters[VgaAcIndex];
1245
1246 case VGA_SEQ_INDEX:
1247 return VgaSeqIndex;
1248
1249 case VGA_SEQ_DATA:
1250 return VgaSeqRegisters[VgaSeqIndex];
1251
1252 case VGA_DAC_MASK:
1253 return VgaDacMask;
1254
1255 case VGA_DAC_READ_INDEX:
1256 /* This returns the read/write state */
1257 return (VgaDacReadWrite ? 0 : 3);
1258
1259 case VGA_DAC_WRITE_INDEX:
1260 return (VgaDacIndex / 3);
1261
1262 case VGA_DAC_DATA:
1263 {
1264 /* Ignore reads in write mode */
1265 if (!VgaDacReadWrite)
1266 {
1267 BYTE Data = VgaDacRegisters[VgaDacIndex++];
1268 VgaDacIndex %= VGA_PALETTE_SIZE;
1269 return Data;
1270 }
1271
1272 break;
1273 }
1274
1275 case VGA_CRTC_INDEX_MONO:
1276 case VGA_CRTC_INDEX_COLOR:
1277 return VgaCrtcIndex;
1278
1279 case VGA_CRTC_DATA_MONO:
1280 case VGA_CRTC_DATA_COLOR:
1281 return VgaCrtcRegisters[VgaCrtcIndex];
1282
1283 case VGA_GC_INDEX:
1284 return VgaGcIndex;
1285
1286 case VGA_GC_DATA:
1287 return VgaGcRegisters[VgaGcIndex];
1288
1289 default:
1290 DPRINT1("VgaReadPort: Unknown port 0x%X\n", Port);
1291 break;
1292 }
1293
1294 return 0;
1295 }
1296
1297 VOID WINAPI VgaWritePort(ULONG Port, BYTE Data)
1298 {
1299 DPRINT("VgaWritePort: Port 0x%X, Data 0x%02X\n", Port, Data);
1300
1301 switch (Port)
1302 {
1303 case VGA_MISC_WRITE:
1304 {
1305 VgaMiscRegister = Data;
1306
1307 if (VgaMiscRegister & 0x01)
1308 {
1309 /* Color emulation */
1310 DPRINT1("Color emulation\n");
1311
1312 /* Register the new I/O Ports */
1313 RegisterIoPort(0x3D4, VgaReadPort, VgaWritePort); // VGA_CRTC_INDEX_COLOR
1314 RegisterIoPort(0x3D5, VgaReadPort, VgaWritePort); // VGA_CRTC_DATA_COLOR
1315 RegisterIoPort(0x3DA, VgaReadPort, VgaWritePort); // VGA_INSTAT1_READ_COLOR, VGA_FEATURE_WRITE_COLOR
1316
1317 /* Unregister the old ones */
1318 UnregisterIoPort(0x3B4); // VGA_CRTC_INDEX_MONO
1319 UnregisterIoPort(0x3B5); // VGA_CRTC_DATA_MONO
1320 UnregisterIoPort(0x3BA); // VGA_INSTAT1_READ_MONO, VGA_FEATURE_WRITE_MONO
1321 }
1322 else
1323 {
1324 /* Monochrome emulation */
1325 DPRINT1("Monochrome emulation\n");
1326
1327 /* Register the new I/O Ports */
1328 RegisterIoPort(0x3B4, VgaReadPort, VgaWritePort); // VGA_CRTC_INDEX_MONO
1329 RegisterIoPort(0x3B5, VgaReadPort, VgaWritePort); // VGA_CRTC_DATA_MONO
1330 RegisterIoPort(0x3BA, VgaReadPort, VgaWritePort); // VGA_INSTAT1_READ_MONO, VGA_FEATURE_WRITE_MONO
1331
1332 /* Unregister the old ones */
1333 UnregisterIoPort(0x3D4); // VGA_CRTC_INDEX_COLOR
1334 UnregisterIoPort(0x3D5); // VGA_CRTC_DATA_COLOR
1335 UnregisterIoPort(0x3DA); // VGA_INSTAT1_READ_COLOR, VGA_FEATURE_WRITE_COLOR
1336 }
1337
1338 // if (VgaMiscRegister & 0x02) { /* Enable RAM access */ } else { /* Disable RAM access */ }
1339 break;
1340 }
1341
1342 case VGA_FEATURE_WRITE_MONO:
1343 case VGA_FEATURE_WRITE_COLOR:
1344 {
1345 VgaFeatureRegister = Data;
1346 break;
1347 }
1348
1349 case VGA_AC_INDEX:
1350 // case VGA_AC_WRITE:
1351 {
1352 if (!VgaAcLatch)
1353 {
1354 /* Change the index */
1355 BYTE Index = Data & 0x1F;
1356 if (Index < VGA_AC_MAX_REG) VgaAcIndex = Index;
1357
1358 /*
1359 * Change palette protection by checking for
1360 * the Palette Address Source bit.
1361 */
1362 VgaAcPalDisable = (Data & 0x20) ? TRUE : FALSE;
1363 }
1364 else
1365 {
1366 /* Write the data */
1367 VgaWriteAc(Data);
1368 }
1369
1370 /* Toggle the latch */
1371 VgaAcLatch = !VgaAcLatch;
1372 break;
1373 }
1374
1375 case VGA_SEQ_INDEX:
1376 {
1377 /* Set the sequencer index register */
1378 if (Data < VGA_SEQ_MAX_REG) VgaSeqIndex = Data;
1379 break;
1380 }
1381
1382 case VGA_SEQ_DATA:
1383 {
1384 /* Call the sequencer function */
1385 VgaWriteSequencer(Data);
1386 break;
1387 }
1388
1389 case VGA_DAC_MASK:
1390 {
1391 VgaDacMask = Data;
1392 break;
1393 }
1394
1395 case VGA_DAC_READ_INDEX:
1396 {
1397 VgaDacReadWrite = FALSE;
1398 VgaDacIndex = Data * 3;
1399 break;
1400 }
1401
1402 case VGA_DAC_WRITE_INDEX:
1403 {
1404 VgaDacReadWrite = TRUE;
1405 VgaDacIndex = Data * 3;
1406 break;
1407 }
1408
1409 case VGA_DAC_DATA:
1410 {
1411 /* Ignore writes in read mode */
1412 if (VgaDacReadWrite) VgaWriteDac(Data & 0x3F);
1413 break;
1414 }
1415
1416 case VGA_CRTC_INDEX_MONO:
1417 case VGA_CRTC_INDEX_COLOR:
1418 {
1419 /* Set the CRTC index register */
1420 if (Data < VGA_CRTC_MAX_REG) VgaCrtcIndex = Data;
1421 break;
1422 }
1423
1424 case VGA_CRTC_DATA_MONO:
1425 case VGA_CRTC_DATA_COLOR:
1426 {
1427 /* Call the CRTC function */
1428 VgaWriteCrtc(Data);
1429 break;
1430 }
1431
1432 case VGA_GC_INDEX:
1433 {
1434 /* Set the GC index register */
1435 if (Data < VGA_GC_MAX_REG) VgaGcIndex = Data;
1436 break;
1437 }
1438
1439 case VGA_GC_DATA:
1440 {
1441 /* Call the GC function */
1442 VgaWriteGc(Data);
1443 break;
1444 }
1445
1446 default:
1447 DPRINT1("VgaWritePort: Unknown port 0x%X\n", Port);
1448 break;
1449 }
1450 }
1451
1452 VOID VgaClearMemory(VOID)
1453 {
1454 ZeroMemory(VgaMemory, sizeof(VgaMemory));
1455 }
1456
1457 VOID VgaResetPalette(VOID)
1458 {
1459 PALETTEENTRY Entries[VGA_MAX_COLORS];
1460
1461 /* Restore the default palette */
1462 VgaRestoreDefaultPalette(Entries, VGA_MAX_COLORS);
1463 SetPaletteEntries(PaletteHandle, 0, VGA_MAX_COLORS, Entries);
1464 PaletteChanged = TRUE;
1465 }
1466
1467 BOOLEAN VgaInitialize(HANDLE TextHandle)
1468 {
1469 INT i, j;
1470 COORD Resolution;
1471 DWORD AddressSize;
1472 DWORD ScanlineSize;
1473 COORD Origin = { 0, 0 };
1474 SMALL_RECT ScreenRect;
1475 PCHAR_INFO CharBuffer;
1476 DWORD Address = 0;
1477 DWORD CurrentAddr;
1478
1479 /* Initialize the VGA palette and fail if it isn't successfully created */
1480 if (!VgaInitializePalette()) return FALSE;
1481 /***/ VgaResetPalette(); /***/
1482
1483 /* Set the global handle */
1484 TextConsoleBuffer = TextHandle;
1485
1486 /* Register the I/O Ports */
1487 RegisterIoPort(0x3CC, VgaReadPort, NULL); // VGA_MISC_READ
1488 RegisterIoPort(0x3C2, VgaReadPort, VgaWritePort); // VGA_MISC_WRITE, VGA_INSTAT0_READ
1489 RegisterIoPort(0x3CA, VgaReadPort, NULL); // VGA_FEATURE_READ
1490 RegisterIoPort(0x3C0, VgaReadPort, VgaWritePort); // VGA_AC_INDEX, VGA_AC_WRITE
1491 RegisterIoPort(0x3C1, VgaReadPort, NULL); // VGA_AC_READ
1492 RegisterIoPort(0x3C4, VgaReadPort, VgaWritePort); // VGA_SEQ_INDEX
1493 RegisterIoPort(0x3C5, VgaReadPort, VgaWritePort); // VGA_SEQ_DATA
1494 RegisterIoPort(0x3C6, VgaReadPort, VgaWritePort); // VGA_DAC_MASK
1495 RegisterIoPort(0x3C7, VgaReadPort, VgaWritePort); // VGA_DAC_READ_INDEX
1496 RegisterIoPort(0x3C8, VgaReadPort, VgaWritePort); // VGA_DAC_WRITE_INDEX
1497 RegisterIoPort(0x3C9, VgaReadPort, VgaWritePort); // VGA_DAC_DATA
1498 RegisterIoPort(0x3CE, VgaReadPort, VgaWritePort); // VGA_GC_INDEX
1499 RegisterIoPort(0x3CF, VgaReadPort, VgaWritePort); // VGA_GC_DATA
1500
1501 /* Clear the VGA memory */
1502 VgaClearMemory();
1503
1504 /* Set the default video mode */
1505 BiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
1506 VgaChangeMode();
1507
1508 /* Get the data */
1509 Resolution = VgaGetDisplayResolution();
1510 CharBuffer = (PCHAR_INFO)ConsoleFramebuffer;
1511 AddressSize = VgaGetAddressSize();
1512 ScreenRect.Left = ScreenRect.Top = 0;
1513 ScreenRect.Right = Resolution.X;
1514 ScreenRect.Bottom = Resolution.Y;
1515 ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2;
1516
1517 /* Read the data from the console into the framebuffer */
1518 ReadConsoleOutputA(TextConsoleBuffer,
1519 CharBuffer,
1520 Resolution,
1521 Origin,
1522 &ScreenRect);
1523
1524 /* Loop through the scanlines */
1525 for (i = 0; i < Resolution.Y; i++)
1526 {
1527 /* Loop through the characters */
1528 for (j = 0; j < Resolution.X; j++)
1529 {
1530 CurrentAddr = LOWORD((Address + j) * AddressSize);
1531
1532 /* Store the character in plane 0 */
1533 VgaMemory[CurrentAddr] = CharBuffer[i * Resolution.X + j].Char.AsciiChar;
1534
1535 /* Store the attribute in plane 1 */
1536 VgaMemory[CurrentAddr + VGA_BANK_SIZE] = (BYTE)CharBuffer[i * Resolution.X + j].Attributes;
1537 }
1538
1539 /* Move to the next scanline */
1540 Address += ScanlineSize;
1541 }
1542
1543 /* Return success */
1544 return TRUE;
1545 }
1546
1547 /* EOF */