1 | ␊ |
2 | /* Copied from 915 resolution created by steve tomljenovic␊ |
3 | *␊ |
4 | * This code is based on the techniques used in :␊ |
5 | *␊ |
6 | * - 855patch. Many thanks to Christian Zietz (czietz gmx net)␊ |
7 | * for demonstrating how to shadow the VBIOS into system RAM␊ |
8 | * and then modify it.␊ |
9 | *␊ |
10 | * - 1280patch by Andrew Tipton (andrewtipton null li).␊ |
11 | *␊ |
12 | * - 855resolution by Alain Poirier␊ |
13 | *␊ |
14 | * This source code is into the public domain.␊ |
15 | */␊ |
16 | ␊ |
17 | #include "libsaio.h"␊ |
18 | #include "915resolution.h"␊ |
19 | ␊ |
20 | char * chipset_type_names[] = {␊ |
21 | ␉"UNKNOWN", "830", "845G", "855GM", "865G", "915G", "915GM", "945G", "945GM", "945GME",␊ |
22 | ␉"946GZ", "G965", "Q965", "965GM", "500"␊ |
23 | };␊ |
24 | ␊ |
25 | char * bios_type_names[] = {"UNKNOWN", "TYPE 1", "TYPE 2", "TYPE 3"};␊ |
26 | ␊ |
27 | int freqs[] = { 60, 75, 85 };␊ |
28 | ␊ |
29 | UInt32 get_chipset_id(void) {␊ |
30 | ␉outl(0xcf8, 0x80000000);␊ |
31 | ␉return inl(0xcfc);␊ |
32 | }␊ |
33 | ␊ |
34 | chipset_type get_chipset(UInt32 id) {␊ |
35 | ␉chipset_type type;␊ |
36 | ␉␊ |
37 | ␉switch (id) {␊ |
38 | ␉␉case 0x35758086:␊ |
39 | ␉␉␉type = CT_830;␊ |
40 | ␉␉␉break;␊ |
41 | ␉␉␊ |
42 | ␉␉case 0x25608086:␊ |
43 | ␉␉␉type = CT_845G;␊ |
44 | ␉␉␉break;␊ |
45 | ␉␉␉␉␊ |
46 | ␉␉case 0x35808086:␊ |
47 | ␉␉␉type = CT_855GM;␊ |
48 | ␉␉␉break;␊ |
49 | ␉␉␉␉␊ |
50 | ␉␉case 0x25708086:␊ |
51 | ␉␉␉type = CT_865G;␊ |
52 | ␉␉␉break;␊ |
53 | ␉␉␊ |
54 | ␉␉case 0x25808086:␊ |
55 | ␉␉␉type = CT_915G;␊ |
56 | ␉␉␉break;␊ |
57 | ␉␉␉␊ |
58 | ␉␉case 0x25908086:␊ |
59 | ␉␉␉type = CT_915GM;␊ |
60 | ␉␉␉break;␊ |
61 | ␉␉␉␊ |
62 | ␉␉case 0x27708086:␊ |
63 | ␉␉␉type = CT_945G;␊ |
64 | ␉␉␉break;␊ |
65 | ␉␉␊ |
66 | ␉␉case 0x27a08086:␊ |
67 | ␉␉␉type = CT_945GM;␊ |
68 | ␉␉␉break;␊ |
69 | ␊ |
70 | ␉␉case 0x27a68086:␊ |
71 | ␉␉␉type = CT_945GM;␊ |
72 | ␉␉␉break;␊ |
73 | ␊ |
74 | ␉␉case 0x27ac8086:␊ |
75 | ␉␉␉type = CT_945GME;␊ |
76 | ␉␉␉break;␊ |
77 | ␊ |
78 | ␉␉case 0x27ae8086:␊ |
79 | ␉␉␉type = CT_945GM;␊ |
80 | ␉␉␉break;␊ |
81 | ␊ |
82 | ␉␉case 0x29708086:␊ |
83 | ␉␉␉type = CT_946GZ;␊ |
84 | ␉␉␉break;␊ |
85 | ␉␉␉␊ |
86 | ␉␉case 0x29a08086:␊ |
87 | ␉␉␉type = CT_G965;␊ |
88 | ␉␉␉break;␊ |
89 | ␉␉␉␊ |
90 | ␉␉case 0x29908086:␊ |
91 | ␉␉␉type = CT_Q965;␊ |
92 | ␉␉␉break;␊ |
93 | ␉␉␉␊ |
94 | ␉␉case 0x81008086:␊ |
95 | ␉␉␉type = CT_500;␊ |
96 | ␉␉␉break;␊ |
97 | ␉␉␉␊ |
98 | ␉␉case 0x2a008086:␊ |
99 | ␉␉␉type = CT_965GM;␊ |
100 | ␉␉␉break;␊ |
101 | ␊ |
102 | ␉␉case 0x2a408086:␊ |
103 | ␉␉␉type = CT_965GM;␊ |
104 | ␉␉␉break;␊ |
105 | ␉␉␉␊ |
106 | ␉␉default:␊ |
107 | ␉␉␉type = CT_UNKWN;␊ |
108 | ␉␉␉break;␊ |
109 | ␉}␊ |
110 | ␉return type;␊ |
111 | }␊ |
112 | ␊ |
113 | vbios_resolution_type1 * map_type1_resolution(vbios_map * map, UInt16 res) {␊ |
114 | ␉vbios_resolution_type1 * ptr = ((vbios_resolution_type1*)(map->bios_ptr + res)); ␊ |
115 | ␉return ptr;␊ |
116 | }␊ |
117 | ␊ |
118 | vbios_resolution_type2 * map_type2_resolution(vbios_map * map, UInt16 res) {␊ |
119 | ␉vbios_resolution_type2 * ptr = ((vbios_resolution_type2*)(map->bios_ptr + res)); ␊ |
120 | ␉return ptr;␊ |
121 | }␊ |
122 | ␊ |
123 | vbios_resolution_type3 * map_type3_resolution(vbios_map * map, UInt16 res) {␊ |
124 | ␉vbios_resolution_type3 * ptr = ((vbios_resolution_type3*)(map->bios_ptr + res)); ␊ |
125 | ␉return ptr;␊ |
126 | }␊ |
127 | ␊ |
128 | char detect_bios_type(vbios_map * map, char modeline, int entry_size) {␊ |
129 | ␉UInt32 i;␊ |
130 | ␉UInt16 r1, r2;␊ |
131 | ␉ ␊ |
132 | ␉r1 = r2 = 32000;␊ |
133 | ␉␊ |
134 | ␉for (i=0; i < map->mode_table_size; i++) {␊ |
135 | ␉␉if (map->mode_table[i].resolution <= r1) {␊ |
136 | ␉␉␉r1 = map->mode_table[i].resolution;␊ |
137 | ␉␉}␊ |
138 | ␉␉else {␊ |
139 | ␉␉␉if (map->mode_table[i].resolution <= r2) {␊ |
140 | ␉␉␉␉r2 = map->mode_table[i].resolution;␊ |
141 | ␉␉␉}␊ |
142 | ␉␉}␊ |
143 | ␉␉␊ |
144 | ␉␉/*printf("r1 = %d r2 = %d\n", r1, r2);*/␊ |
145 | ␉}␊ |
146 | ␊ |
147 | ␉return (r2-r1-6) % entry_size == 0;␊ |
148 | }␊ |
149 | ␊ |
150 | void close_vbios(vbios_map * map);␊ |
151 | ␊ |
152 | vbios_map * open_vbios(chipset_type forced_chipset) {␊ |
153 | ␉UInt32 z;␊ |
154 | ␉vbios_map * map = NEW(vbios_map);␊ |
155 | ␉for(z=0; z<sizeof(vbios_map); z++) ((char*)map)[z]=0;␊ |
156 | ␉/*␊ |
157 | ␉ * Determine chipset␊ |
158 | ␉␉ + */␊ |
159 | ␉␊ |
160 | ␉if (forced_chipset == CT_UNKWN) {␊ |
161 | ␉␉map->chipset_id = get_chipset_id();␊ |
162 | ␉␉map->chipset = get_chipset(map->chipset_id);␊ |
163 | ␉}␊ |
164 | ␉else if (forced_chipset != CT_UNKWN) {␊ |
165 | ␉␉map->chipset = forced_chipset;␊ |
166 | ␉}␊ |
167 | ␉else {␊ |
168 | ␉␉map->chipset = CT_915GM;␊ |
169 | ␉}␊ |
170 | ␉ ␊ |
171 | ␉/*␊ |
172 | ␉ * Map the video bios to memory␊ |
173 | ␉ */␊ |
174 | ␉␊ |
175 | ␉map->bios_ptr=(char*)VBIOS_START;␊ |
176 | ␉␊ |
177 | ␉/*␊ |
178 | ␉ * check if we have ATI Radeon␊ |
179 | ␉ */␊ |
180 | ␉ ␊ |
181 | ␉/*if (memmem(map->bios_ptr, VBIOS_SIZE, ATI_SIGNATURE1, strlen(ATI_SIGNATURE1)) ||␊ |
182 | ␉␉memmem(map->bios_ptr, VBIOS_SIZE, ATI_SIGNATURE2, strlen(ATI_SIGNATURE2)) ) {␊ |
183 | ␉␉printf(stderr, "ATI chipset detected. 915resolution only works with Intel 800/900 series graphic chipsets.\n");␊ |
184 | ␉␉return 0;␊ |
185 | ␉}*/␊ |
186 | ␉␊ |
187 | ␉/*␊ |
188 | ␉ * check if we have NVIDIA␊ |
189 | ␉ */␊ |
190 | ␉ ␊ |
191 | ␉/*if (memmem(map->bios_ptr, VBIOS_SIZE, NVIDIA_SIGNATURE, strlen(NVIDIA_SIGNATURE))) {␊ |
192 | ␉␉printf("NVIDIA chipset detected. 915resolution only works with Intel 800/900 series graphic chipsets.\n");␊ |
193 | ␉␉return 0;␊ |
194 | ␉}*/␊ |
195 | ␉␊ |
196 | ␉/*␊ |
197 | ␉ * check if we have Intel␊ |
198 | ␉ */␊ |
199 | ␉ ␊ |
200 | ␉/*if (map->chipset == CT_UNKWN && memmem(map->bios_ptr, VBIOS_SIZE, INTEL_SIGNATURE, strlen(INTEL_SIGNATURE))) {␊ |
201 | ␉␉printf( "Intel chipset detected. However, 915resolution was unable to determine the chipset type.\n");␊ |
202 | ␉␊ |
203 | ␉␉printf("Chipset Id: %x\n", map->chipset_id);␊ |
204 | ␉␉␊ |
205 | ␉␉printf("Please report this problem to stomljen@yahoo.com\n");␊ |
206 | ␉␉␊ |
207 | ␉␉␉close_vbios(map);␊ |
208 | ␉␉␉return 0;␊ |
209 | ␉␉}*/␊ |
210 | ␉␊ |
211 | ␉␉/*␊ |
212 | ␉␉ * check for others␊ |
213 | ␉␉ */␊ |
214 | ␉␊ |
215 | ␉if (map->chipset == CT_UNKWN) {␊ |
216 | ␉␉printf("Unknown chipset type and unrecognized bios.\n");␊ |
217 | ␉␉ ␊ |
218 | ␉␉printf("915resolution only works with Intel 800/900 series graphic chipsets.\n");␊ |
219 | ␉␊ |
220 | ␉␉printf("Chipset Id: %x\n", map->chipset_id);␊ |
221 | ␉␉close_vbios(map);␊ |
222 | ␉␉return 0;␊ |
223 | ␉}␊ |
224 | ␊ |
225 | ␉/*␊ |
226 | ␉ * Figure out where the mode table is ␊ |
227 | ␉ */␊ |
228 | ␉␊ |
229 | ␉{␊ |
230 | ␉␉char* p = map->bios_ptr + 16;␊ |
231 | ␉␉char* limit = map->bios_ptr + VBIOS_SIZE - (3 * sizeof(vbios_mode));␊ |
232 | ␉␉␉␊ |
233 | ␉␉while (p < limit && map->mode_table == 0) {␊ |
234 | ␉␉␉vbios_mode * mode_ptr = (vbios_mode *) p;␊ |
235 | ␉␉␉ ␊ |
236 | ␉␉␉if (((mode_ptr[0].mode & 0xf0) == 0x30) && ((mode_ptr[1].mode & 0xf0) == 0x30) &&␊ |
237 | ␉␉␉␉((mode_ptr[2].mode & 0xf0) == 0x30) && ((mode_ptr[3].mode & 0xf0) == 0x30)) {␊ |
238 | ␉␉␉␊ |
239 | ␉␉␉␉map->mode_table = mode_ptr;␊ |
240 | ␉␉␉}␊ |
241 | ␉␉␉ ␊ |
242 | ␉␉␉p++;␊ |
243 | ␉␉}␊ |
244 | ␉␉␊ |
245 | ␉␉if (map->mode_table == 0) {␊ |
246 | ␉␉␉printf("Unable to locate the mode table.\n");␊ |
247 | ␉␉␉printf("Please run the program 'dump_bios' as root and\n");␊ |
248 | ␉␉␉printf("email the file 'vbios.dmp' to stomljen@yahoo.com.\n");␊ |
249 | ␉␉␉printf("Chipset: %s\n", chipset_type_names[map->chipset]);␊ |
250 | ␉␉␉close_vbios(map);␊ |
251 | ␉␉␉return 0;␊ |
252 | ␉␉}␊ |
253 | ␉}␊ |
254 | ␉␊ |
255 | ␉/*␊ |
256 | ␉ * Determine size of mode table␊ |
257 | ␉ */␊ |
258 | ␉ ␊ |
259 | ␉{␊ |
260 | ␉␉vbios_mode * mode_ptr = map->mode_table;␊ |
261 | ␉␉␉␊ |
262 | ␉␉while (mode_ptr->mode != 0xff) {␊ |
263 | ␉␉␉map->mode_table_size++;␊ |
264 | ␉␉␉mode_ptr++;␊ |
265 | ␉␉}␊ |
266 | ␉}␊ |
267 | ␉␊ |
268 | ␉/*␊ |
269 | ␉ * Figure out what type of bios we have␊ |
270 | ␉ * order of detection is important␊ |
271 | ␉ */␊ |
272 | ␉␊ |
273 | ␉if (detect_bios_type(map, TRUE, sizeof(vbios_modeline_type3))) {␊ |
274 | ␉␉map->bios = BT_3;␊ |
275 | ␉}␊ |
276 | ␉else if (detect_bios_type(map, TRUE, sizeof(vbios_modeline_type2))) {␊ |
277 | ␉␉map->bios = BT_2;␊ |
278 | ␉}␊ |
279 | ␉else if (detect_bios_type(map, FALSE, sizeof(vbios_resolution_type1))) {␊ |
280 | ␉␉map->bios = BT_1;␊ |
281 | ␉}␊ |
282 | ␉else {␊ |
283 | ␉␉printf("Unable to determine bios type.\n");␊ |
284 | ␉␉printf("Please run the program 'dump_bios' as root and\n");␊ |
285 | ␉␉printf("email the file 'vbios.dmp' to stomljen@yahoo.com.\n");␊ |
286 | ␉␊ |
287 | ␉␉printf("Chipset: %s\n", chipset_type_names[map->chipset]);␊ |
288 | ␉␉printf("Mode Table Offset: $C0000 + $%x\n", ((UInt32)map->mode_table) - ((UInt32)map->bios_ptr));␊ |
289 | ␉␉␊ |
290 | ␉␉printf("Mode Table Entries: %u\n", map->mode_table_size);␊ |
291 | ␉␉return 0;␊ |
292 | ␉}␊ |
293 | ␉␊ |
294 | ␉return map;␊ |
295 | }␊ |
296 | ␊ |
297 | void close_vbios(vbios_map * map) {␊ |
298 | ␉FREE(map);␊ |
299 | }␊ |
300 | ␊ |
301 | void unlock_vbios(vbios_map * map) {␊ |
302 | ␊ |
303 | ␉map->unlocked = TRUE;␊ |
304 | ␉ ␊ |
305 | ␉switch (map->chipset) {␊ |
306 | ␉␉case CT_UNKWN:␊ |
307 | ␉␉␉break;␊ |
308 | ␉␉case CT_830:␊ |
309 | ␉␉case CT_855GM:␊ |
310 | ␉␉␉outl(0xcf8, 0x8000005a);␊ |
311 | ␉␉␉map->b1 = inb(0xcfe);␊ |
312 | ␉␉␉␉␊ |
313 | ␉␉␉outl(0xcf8, 0x8000005a);␊ |
314 | ␉␉␉outb(0xcfe, 0x33);␊ |
315 | ␉␉␉break;␊ |
316 | ␉␉case CT_845G:␊ |
317 | ␉␉case CT_865G:␊ |
318 | ␉␉case CT_915G:␊ |
319 | ␉␉case CT_915GM:␊ |
320 | ␉␉case CT_945G:␊ |
321 | ␉␉case CT_945GM:␊ |
322 | ␉␉case CT_945GME:␊ |
323 | ␉␉case CT_946GZ:␊ |
324 | ␉␉case CT_G965:␊ |
325 | ␉␉case CT_Q965:␊ |
326 | ␉␉case CT_965GM:␊ |
327 | ␉␉case CT_500:␊ |
328 | ␊ |
329 | ␉␉␉outl(0xcf8, 0x80000090);␊ |
330 | ␉␉␉map->b1 = inb(0xcfd);␊ |
331 | ␉␉␉map->b2 = inb(0xcfe);␊ |
332 | ␉␉␉outl(0xcf8, 0x80000090);␊ |
333 | ␉␉␉outb(0xcfd, 0x33);␊ |
334 | ␉␉␉outb(0xcfe, 0x33);␊ |
335 | ␉␉break;␊ |
336 | ␉}␊ |
337 | ␉␊ |
338 | ␉#if DEBUG␊ |
339 | ␉{␊ |
340 | ␉␉UInt32 t = inl(0xcfc);␊ |
341 | ␉␉printf("unlock PAM: (0x%08x)\n", t);␊ |
342 | ␉}␊ |
343 | #endif␊ |
344 | }␊ |
345 | ␊ |
346 | void relock_vbios(vbios_map * map) {␊ |
347 | ␊ |
348 | ␉map->unlocked = FALSE;␊ |
349 | ␉␊ |
350 | ␉switch (map->chipset) {␊ |
351 | ␉␉case CT_UNKWN:␊ |
352 | ␉␉␉break;␊ |
353 | ␉␉case CT_830:␊ |
354 | ␉␉case CT_855GM:␊ |
355 | ␉␉␉outl(0xcf8, 0x8000005a);␊ |
356 | ␉␉␉outb(0xcfe, map->b1);␊ |
357 | ␉␉␉break;␊ |
358 | ␉␉case CT_845G:␊ |
359 | ␉␉␉case CT_865G:␊ |
360 | ␉␉␉case CT_915G:␊ |
361 | ␉␉␉case CT_915GM:␊ |
362 | ␉␉␉case CT_945G:␊ |
363 | ␉␉␉case CT_945GM:␊ |
364 | ␉␉␉case CT_945GME:␊ |
365 | ␉␉␉case CT_946GZ:␊ |
366 | ␉␉␉case CT_G965:␊ |
367 | ␉␉␉case CT_Q965:␊ |
368 | ␉␉␉case CT_965GM:␊ |
369 | ␉␉␉case CT_500:␊ |
370 | ␊ |
371 | ␉␉␉␉outl(0xcf8, 0x80000090);␊ |
372 | ␉␉␉␉outb(0xcfd, map->b1);␊ |
373 | ␉␉␉␉outb(0xcfe, map->b2);␊ |
374 | ␉␉␉break;␊ |
375 | ␉}␊ |
376 | ␉␊ |
377 | ␉#if DEBUG␊ |
378 | ␉{␊ |
379 | UInt32 t = inl(0xcfc);␊ |
380 | ␉␉printf("relock PAM: (0x%08x)\n", t);␊ |
381 | ␉}␊ |
382 | ␉#endif␊ |
383 | }␊ |
384 | ␊ |
385 | ␊ |
386 | static void gtf_timings(UInt32 x, UInt32 y, UInt32 freq,␊ |
387 | ␉␉␉␉␉␉unsigned long *clock,␊ |
388 | ␉␉␉␉␉␉UInt16 *hsyncstart, UInt16 *hsyncend, UInt16 *hblank,␊ |
389 | ␉␉␉␉␉␉UInt16 *vsyncstart, UInt16 *vsyncend, UInt16 *vblank)␊ |
390 | {␊ |
391 | ␉UInt32 hbl, vbl, vfreq;␊ |
392 | ␊ |
393 | ␉vbl = y + (y+1)/(20000.0/(11*freq) - 1) + 1.5;␊ |
394 | ␉vfreq = vbl * freq;␊ |
395 | ␉hbl = 16 * (int)(x * (30.0 - 300000.0 / vfreq) /␊ |
396 | ␉␉␉␉␉␉ + (70.0 + 300000.0 / vfreq) / 16.0 + 0.5);␊ |
397 | ␊ |
398 | ␉*vsyncstart = y;␊ |
399 | ␉*vsyncend = y + 3;␊ |
400 | ␉*vblank = vbl - 1;␊ |
401 | ␉*hsyncstart = x + hbl / 2 - (x + hbl + 50) / 100 * 8 - 1;␊ |
402 | ␉*hsyncend = x + hbl / 2 - 1;␊ |
403 | ␉*hblank = x + hbl - 1;␊ |
404 | ␉*clock = (x + hbl) * vfreq / 1000;␊ |
405 | }␊ |
406 | ␊ |
407 | void set_mode(vbios_map * map, /*UInt32 mode,*/ UInt32 x, UInt32 y, UInt32 bp, UInt32 htotal, UInt32 vtotal) {␊ |
408 | ␉UInt32 xprev, yprev;␊ |
409 | ␉UInt32 i = 0, j;␉// patch first available mode␊ |
410 | ␊ |
411 | //␉for (i=0; i < map->mode_table_size; i++) {␊ |
412 | //␉␉if (map->mode_table[0].mode == mode) {␊ |
413 | ␉␉␉switch(map->bios) {␊ |
414 | ␉␉␉␉case BT_1:␊ |
415 | ␉␉␉␉␉{␊ |
416 | ␉␉␉␉␉␉vbios_resolution_type1 * res = map_type1_resolution(map, map->mode_table[i].resolution);␊ |
417 | ␉␉␉␉␉␉␊ |
418 | ␉␉␉␉␉␉if (bp) {␊ |
419 | ␉␉␉␉␉␉␉map->mode_table[i].bits_per_pixel = bp;␊ |
420 | ␉␉␉␉␉␉}␊ |
421 | ␉␉␉␉␉␉␊ |
422 | ␉␉␉␉␉␉res->x2 = (htotal?(((htotal-x) >> 8) & 0x0f) : (res->x2 & 0x0f)) | ((x >> 4) & 0xf0);␊ |
423 | ␉␉␉␉␉␉res->x1 = (x & 0xff);␊ |
424 | ␉␉␉␉␉␉␊ |
425 | ␉␉␉␉␉␉res->y2 = (vtotal?(((vtotal-y) >> 8) & 0x0f) : (res->y2 & 0x0f)) | ((y >> 4) & 0xf0);␊ |
426 | ␉␉␉␉␉␉res->y1 = (y & 0xff);␊ |
427 | ␉␉␉␉␉␉if (htotal)␊ |
428 | ␉␉␉␉␉␉␉res->x_total = ((htotal-x) & 0xff);␊ |
429 | ␉␉␉␉␉␉␊ |
430 | ␉␉␉␉␉␉if (vtotal)␊ |
431 | ␉␉␉␉␉␉␉res->y_total = ((vtotal-y) & 0xff);␊ |
432 | ␉␉␉␉␉}␊ |
433 | ␉␉␉␉␉break;␊ |
434 | ␉␉␉␉case BT_2:␊ |
435 | ␉␉␉␉␉{␊ |
436 | ␉␉␉␉␉␉vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution);␊ |
437 | ␉␉␉␉␉␉␊ |
438 | ␉␉␉␉␉␉res->xchars = x / 8;␊ |
439 | ␉␉␉␉␉␉res->ychars = y / 16 - 1;␊ |
440 | ␉␉␉␉␉␉xprev = res->modelines[0].x1;␊ |
441 | ␉␉␉␉␉␉yprev = res->modelines[0].y1;␊ |
442 | ␉␉␉␉␉␉␊ |
443 | ␉␉␉␉␉␉for(j=0; j < 3; j++) {␊ |
444 | ␉␉␉␉␉␉␉vbios_modeline_type2 * modeline = &res->modelines[j];␊ |
445 | ␉␉␉␉␉␉␉␊ |
446 | ␉␉␉␉␉␉␉if (modeline->x1 == xprev && modeline->y1 == yprev) {␊ |
447 | ␉␉␉␉␉␉␉␉modeline->x1 = modeline->x2 = x-1;␊ |
448 | ␉␉␉␉␉␉␉␉modeline->y1 = modeline->y2 = y-1;␊ |
449 | ␉␉␉␉␊ |
450 | ␉␉␉␉␉␉␉␉gtf_timings(x, y, freqs[j], &modeline->clock,␊ |
451 | ␉␉␉␉␉␉␉␉␉␉␉&modeline->hsyncstart, &modeline->hsyncend,␊ |
452 | ␉␉␉␉␉␉␉␉␉␉␉&modeline->hblank, &modeline->vsyncstart,␊ |
453 | ␉␉␉␉␉␉␉␉␉␉␉&modeline->vsyncend, &modeline->vblank);␊ |
454 | ␉␉␉␉␉␉␉␉␊ |
455 | ␉␉␉␉␉␉␉␉if (htotal)␊ |
456 | ␉␉␉␉␉␉␉␉␉modeline->htotal = htotal;␊ |
457 | ␉␉␉␉␉␉␉␉else␊ |
458 | ␉␉␉␉␉␉␉␉␉modeline->htotal = modeline->hblank;␊ |
459 | ␉␉␉␉␉␉␉␉␊ |
460 | ␉␉␉␉␉␉␉␉if (vtotal)␊ |
461 | ␉␉␉␉␉␉␉␉␉modeline->vtotal = vtotal;␊ |
462 | ␉␉␉␉␉␉␉␉else␊ |
463 | ␉␉␉␉␉␉␉␉␉modeline->vtotal = modeline->vblank;␊ |
464 | ␉␉␉␉␉␉␉}␊ |
465 | ␉␉␉␉␉␉}␊ |
466 | ␉␉␉␉␉}␊ |
467 | ␉␉␉␉␉break;␊ |
468 | ␉␉␉␉case BT_3:␊ |
469 | ␉␉␉␉␉{␊ |
470 | ␉␉␉␉␉␉vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution);␊ |
471 | ␉␉␉␉␉␉␊ |
472 | ␉␉␉␉␉␉xprev = res->modelines[0].x1;␊ |
473 | ␉␉␉␉␉␉yprev = res->modelines[0].y1;␊ |
474 | ␉␉␉␉␊ |
475 | ␉␉␉␉␉␉for (j=0; j < 3; j++) {␊ |
476 | ␉␉␉␉␉␉␉vbios_modeline_type3 * modeline = &res->modelines[j];␊ |
477 | ␉␉␉␉␉␉␉ ␊ |
478 | ␉␉␉␉␉␉␉if (modeline->x1 == xprev && modeline->y1 == yprev) {␊ |
479 | ␉␉␉␉␉␉␉␉modeline->x1 = modeline->x2 = x-1;␊ |
480 | ␉␉␉␉␉␉␉␉modeline->y1 = modeline->y2 = y-1;␊ |
481 | ␉␉␉␉␉␉␉␉ ␊ |
482 | ␉␉␉␉␉␉␉␉gtf_timings(x, y, freqs[j], &modeline->clock,␊ |
483 | ␉␉␉␉␉␉␉␉␉␉␉&modeline->hsyncstart, &modeline->hsyncend,␊ |
484 | ␉␉␉␉␉␉␉␉␉␉␉&modeline->hblank, &modeline->vsyncstart,␊ |
485 | ␉␉␉␉␉␉␉␉␉␉␉&modeline->vsyncend, &modeline->vblank);␊ |
486 | ␉␉␉␉␉␉␉␉if (htotal)␊ |
487 | ␉␉␉␉␉␉␉␉␉modeline->htotal = htotal;␊ |
488 | ␉␉␉␉␉␉␉␉else␊ |
489 | ␉␉␉␉␉␉␉␉␉modeline->htotal = modeline->hblank;␊ |
490 | ␉␉␉␉␉␉␉␉if (vtotal)␊ |
491 | ␉␉␉␉␉␉␉␉␉modeline->vtotal = vtotal;␊ |
492 | ␉␉␉␉␉␉␉␉else␊ |
493 | ␉␉␉␉␉␉␉␉␉modeline->vtotal = modeline->vblank;␊ |
494 | ␉␉␉␉␉␉␊ |
495 | ␉␉␉␉␉␉␉␉modeline->timing_h = y-1;␊ |
496 | ␉␉␉␉␉␉␉␉modeline->timing_v = x-1;␊ |
497 | ␉␉␉␉␉␉␉}␊ |
498 | ␉␉␉␉␉␉}␊ |
499 | ␉␉␉␉␉}␊ |
500 | ␉␉␉␉␉break;␊ |
501 | ␉␉␉␉case BT_UNKWN:␊ |
502 | ␉␉␉␉␉break;␊ |
503 | ␉␉␉}␊ |
504 | //␉␉}␊ |
505 | //␉}␊ |
506 | } ␊ |
507 | ␊ |
508 | void display_map_info(vbios_map * map) {␊ |
509 | ␉printf("Chipset: %s\n", chipset_type_names[map->chipset]);␊ |
510 | ␉printf("BIOS: %s\n", bios_type_names[map->bios]);␊ |
511 | ␉␊ |
512 | ␉printf("Mode Table Offset: $C0000 + $%x\n", ((UInt32)map->mode_table) - ((UInt32)map->bios_ptr));␊ |
513 | ␉printf("Mode Table Entries: %u\n", map->mode_table_size);␊ |
514 | }␊ |
515 | ␊ |
516 | /*␊ |
517 | int parse_args(int argc, char *argv[], chipset_type *forced_chipset, UInt32 *list, UInt32 *mode, UInt32 *x, UInt32 *y, UInt32 *bp, UInt32 *raw, UInt32 *htotal, UInt32 *vtotal) {␊ |
518 | ␉UInt32 index = 0;␊ |
519 | ␉␊ |
520 | ␉*list = *mode = *x = *y = *raw = *htotal = *vtotal = 0;␊ |
521 | ␊ |
522 | ␉*forced_chipset = CT_UNKWN;␊ |
523 | ␉␊ |
524 | ␉if ((argc > index) && !strcmp(argv[index], "-c")) {␊ |
525 | ␉␉index++;␊ |
526 | ␉␉+␊ |
527 | ␉␉+ if(argc<=index) {␊ |
528 | ␉␉␉+ return 0;␊ |
529 | ␉␉␉+ }␊ |
530 | ␉␉+ ␊ |
531 | ␉␉+ if (!strcmp(argv[index], "845")) {␊ |
532 | ␉␉␉+ *forced_chipset = CT_845G;␊ |
533 | ␉␉␉+ }␊ |
534 | ␉␉+ else if (!strcmp(argv[index], "855")) {␊ |
535 | ␉␉␉+ *forced_chipset = CT_855GM;␊ |
536 | ␉␉␉+ }␊ |
537 | ␉␉+ else if (!strcmp(argv[index], "865")) {␊ |
538 | ␉␉␉+ *forced_chipset = CT_865G;␊ |
539 | ␉␉␉+ }␊ |
540 | ␉␉+ else if (!strcmp(argv[index], "915G")) {␊ |
541 | ␉␉␉+ *forced_chipset = CT_915G;␊ |
542 | ␉␉␉+ }␊ |
543 | ␉␉+ else if (!strcmp(argv[index], "915GM")) {␊ |
544 | ␉␉␉+ *forced_chipset = CT_915GM;␊ |
545 | ␉␉␉+ }␊ |
546 | ␉␉+ else if (!strcmp(argv[index], "945G")) {␊ |
547 | ␉␉␉+ *forced_chipset = CT_945G;␊ |
548 | ␉␉␉+ }␊ |
549 | ␉␉+ else if (!strcmp(argv[index], "945GM")) {␊ |
550 | ␉␉␉+ *forced_chipset = CT_945GM;␊ |
551 | ␉␉␉+ }␊ |
552 | ␉␉+ else if (!strcmp(argv[index], "945GME")) {␊ |
553 | ␉␉␉+ *forced_chipset = CT_945GME;␊ |
554 | ␉␉␉+ }␊ |
555 | ␉␉+ else if (!strcmp(argv[index], "946GZ")) {␊ |
556 | ␉␉␉+ *forced_chipset = CT_946GZ;␊ |
557 | ␉␉␉+ }␊ |
558 | ␉␉+ else if (!strcmp(argv[index], "G965")) {␊ |
559 | ␉␉␉+ *forced_chipset = CT_G965;␊ |
560 | ␉␉␉+ }␊ |
561 | ␉␉+ else if (!strcmp(argv[index], "Q965")) {␊ |
562 | ␉␉␉+ *forced_chipset = CT_Q965;␊ |
563 | ␉␉␉+ }␊ |
564 | ␉␉+ else if (!strcmp(argv[index], "500")) {␊ |
565 | ␉␉␉+ *forced_chipset = CT_500;␊ |
566 | ␉␉␉+ }␊ |
567 | ␉␉␊ |
568 | ␉␉+ else {␊ |
569 | ␉␉␉+␉ printf("No match for forced chipset: %s\n", argv[index]);␊ |
570 | ␉␉␉+ *forced_chipset = CT_UNKWN;␊ |
571 | ␉␉␉+ }␊ |
572 | ␉␉+ ␊ |
573 | ␉␉+ index++;␊ |
574 | ␉␉+ ␊ |
575 | ␉␉+ if (argc<=index) {␊ |
576 | ␉␉␉+ return 0;␊ |
577 | ␉␉␉+ }␊ |
578 | ␉␉+ }␊ |
579 | ␉+␊ |
580 | ␉+ if ((argc > index) && !strcmp(argv[index], "-l")) {␊ |
581 | ␉␉+ *list = 1;␊ |
582 | ␉␉+ index++;␊ |
583 | ␉␉+␊ |
584 | ␉␉+ if(argc<=index) {␊ |
585 | ␉␉␉+ return 0;␊ |
586 | ␉␉␉+ }␊ |
587 | ␉␉+ }␊ |
588 | ␉+ ␊ |
589 | ␉+ if ((argc > index) && !strcmp(argv[index], "-r")) {␊ |
590 | ␉␉+ *raw = 1;␊ |
591 | ␉␉+ index++;␊ |
592 | ␉␉+␊ |
593 | ␉␉+ if(argc<=index) {␊ |
594 | ␉␉␉+ return 0;␊ |
595 | ␉␉␉+ }␊ |
596 | ␉␉+ }␊ |
597 | ␉+ ␊ |
598 | ␉+ if (argc-index < 3 || argc-index > 6) {␊ |
599 | ␉␉+ return -1;␊ |
600 | ␉␉+ }␊ |
601 | ␉+␊ |
602 | ␉+ *mode = (UInt32) strtoul(argv[index], NULL, 16);␊ |
603 | ␉+ *x = (UInt32)strtoul(argv[index+1], NULL, 10);␊ |
604 | ␉+ *y = (UInt32)strtoul(argv[index+2], NULL, 10);␊ |
605 | ␉+␊ |
606 | ␉+␊ |
607 | ␉+ if (argc-index > 3) {␊ |
608 | ␉␉+ *bp = (UInt32)strtoul(argv[index+3], NULL, 10);␊ |
609 | ␉␉+ }␊ |
610 | ␉+ else {␊ |
611 | ␉␉+ *bp = 0;␊ |
612 | ␉␉+ }␊ |
613 | ␉+ ␊ |
614 | ␉+ if (argc-index > 4) {␊ |
615 | ␉␉+ *htotal = (UInt32)strtoul(argv[index+4], NULL, 10);␊ |
616 | ␉␉+ }␊ |
617 | ␉+ else {␊ |
618 | ␉␉+ *htotal = 0;␊ |
619 | ␉␉+ }␊ |
620 | ␉+␊ |
621 | ␉+ if (argc-index > 5) {␊ |
622 | ␉␉+ *vtotal = (UInt32)strtoul(argv[index+5], NULL, 10);␊ |
623 | ␉␉+ }␊ |
624 | ␉+ else {␊ |
625 | ␉␉+ *vtotal = 0;␊ |
626 | ␉␉+ }␊ |
627 | ␉+ ␊ |
628 | ␉+ return 0;␊ |
629 | ␉+}␊ |
630 | +␊ |
631 | ␊ |
632 | ␊ |
633 | */␊ |
634 | ␊ |
635 | ␊ |
636 | void list_modes(vbios_map *map, UInt32 raw) {␊ |
637 | UInt32 i, x, y;␊ |
638 | ␉␊ |
639 | for (i=0; i < map->mode_table_size; i++) {␊ |
640 | switch(map->bios) {␊ |
641 | ␉␉␉case BT_1:␊ |
642 | {␊ |
643 | vbios_resolution_type1 * res = map_type1_resolution(map, map->mode_table[i].resolution);␊ |
644 | ␊ |
645 | x = ((((UInt32) res->x2) & 0xf0) << 4) | res->x1;␊ |
646 | y = ((((UInt32) res->y2) & 0xf0) << 4) | res->y1;␊ |
647 | ␊ |
648 | if (x != 0 && y != 0) {␊ |
649 | printf("Mode %02x : %dx%d, %d bits/pixel\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);␊ |
650 | }␊ |
651 | ␉␉␉␉␊ |
652 | ␉␉␉␉if (raw)␊ |
653 | ␉␉␉␉{␊ |
654 | printf("Mode %02x (raw) :\n\t%02x %02x\n\t%02x\n\t%02x\n\t%02x\n\t%02x\n\t%02x\n\t%02x\n", map->mode_table[i].mode, res->unknow1[0],res->unknow1[1], res->x1,res->x_total,res->x2,res->y1,res->y_total,res->y2);␊ |
655 | ␉␉␉␉}␊ |
656 | ␉␉␉␉␊ |
657 | }␊ |
658 | ␉␉␉␉break;␊ |
659 | ␉␉␉case BT_2:␊ |
660 | {␊ |
661 | vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution);␊ |
662 | ␊ |
663 | x = res->modelines[0].x1+1;␊ |
664 | y = res->modelines[0].y1+1;␊ |
665 | ␉␉␉␉␊ |
666 | if (x != 0 && y != 0) {␊ |
667 | printf("Mode %02x : %dx%d, %d bits/pixel\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);␊ |
668 | }␊ |
669 | }␊ |
670 | ␉␉␉␉break;␊ |
671 | ␉␉␉case BT_3:␊ |
672 | {␊ |
673 | vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution);␊ |
674 | ␊ |
675 | x = res->modelines[0].x1+1;␊ |
676 | y = res->modelines[0].y1+1;␊ |
677 | ␊ |
678 | if (x != 0 && y != 0) {␊ |
679 | printf("Mode %02x : %dx%d, %d bits/pixel\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);␊ |
680 | }␊ |
681 | }␊ |
682 | ␉␉␉␉break;␊ |
683 | ␉␉␉case BT_UNKWN:␊ |
684 | ␉␉␉␉break;␊ |
685 | }␊ |
686 | }␊ |
687 | }␊ |
688 | ␊ |
689 | ␊ |
690 | void usage() {␊ |
691 | ␉printf("Usage: 915resolution [-c chipset] [-l] [mode X Y] [bits/pixel] [htotal] [vtotal]\n");␊ |
692 | ␉printf(" Set the resolution to XxY for a video mode\n");␊ |
693 | ␉printf(" Bits per pixel are optional. htotal/vtotal settings are additionally optional.\n");␊ |
694 | ␉printf(" Options:\n");␊ |
695 | ␉printf(" -c force chipset type (THIS IS USED FOR DEBUG PURPOSES)\n");␊ |
696 | ␉printf(" -l display the modes found in the video BIOS\n");␊ |
697 | ␉printf(" -r display the modes found in the video BIOS in raw mode (THIS IS USED FOR DEBUG PURPOSES)\n");␊ |
698 | }␊ |
699 | ␊ |
700 | /*␊ |
701 | static err_t␊ |
702 | cmd_915resolution (struct arg_list *state ,␊ |
703 | ␉␉␉␉ int argc ,␊ |
704 | ␉␉␉␉ char **argv )␊ |
705 | {␊ |
706 | ␉vbios_map * map;␊ |
707 | ␉UInt32 list, mode, x, y, bp, raw, htotal, vtotal;␊ |
708 | ␉chipset_type forced_chipset;␊ |
709 | ␉␊ |
710 | ␉printf("Intel 500/800/900 Series VBIOS Hack : version %s\n\n", VERSION);␊ |
711 | ␊ |
712 | ␉if (parse_args(argc, argv, &forced_chipset, &list, &mode, &x, &y, &bp, &raw, &htotal, &vtotal) == -1) {␊ |
713 | ␉␉␉usage();␊ |
714 | ␉␉␉return 2;␊ |
715 | ␉␉}␊ |
716 | ␊ |
717 | ␉map = open_vbios(forced_chipset);␊ |
718 | ␉display_map_info(map);␊ |
719 | ␊ |
720 | ␉printf("\n");␊ |
721 | ␊ |
722 | ␉if (list) {␊ |
723 | ␉␉list_modes(map, raw);␊ |
724 | ␉}␊ |
725 | ␊ |
726 | ␉if (mode!=0 && x!=0 && y!=0) {␊ |
727 | ␉␉unlock_vbios(map);␊ |
728 | ␉␉␊ |
729 | ␉␉set_mode(map, mode, x, y, bp, htotal, vtotal);␊ |
730 | ␉␉␊ |
731 | ␉␉relock_vbios(map);␊ |
732 | ␉␉␊ |
733 | ␉␉printf("Patch mode %02x to resolution %dx%d complete\n", mode, x, y);␊ |
734 | ␉␉ ␊ |
735 | ␉␉if (list) {␊ |
736 | ␉␉␉list_modes(map, raw);␊ |
737 | ␉␉}␊ |
738 | ␉}␊ |
739 | ␉␊ |
740 | ␉close_vbios(map);␊ |
741 | ␉ ␊ |
742 | ␉return 0;␊ |
743 | }␊ |
744 | */␊ |
745 | |