1 | /*␊ |
2 | * nvidia_resolution.c␊ |
3 | * ␊ |
4 | *␊ |
5 | * Created by Le Bidou on 19/03/10.␊ |
6 | * Copyright 2010 ---. All rights reserved.␊ |
7 | *␊ |
8 | */␊ |
9 | ␊ |
10 | #include "nvidia_resolution.h"␊ |
11 | ␊ |
12 | vBiosMap * openNvidiaVbios(vBiosMap *map)␊ |
13 | {␊ |
14 | ␉unsigned short nvDataTableOffset = 0;␊ |
15 | ␉unsigned short nvModeline_2_Offset = 0;␊ |
16 | ␉unsigned short * nvDataTable = NULL;␊ |
17 | ␉nvVesaTable * stdVesa;␊ |
18 | ␉␊ |
19 | ␉// initialize the table chain with two elements␊ |
20 | ␉sModeTable * table = intializeTables(map, 2);␊ |
21 | ␉/*␊ |
22 | ␉ * Locate the VESA Tables␊ |
23 | ␉ */␊ |
24 | ␉␊ |
25 | ␉int i = 0;␊ |
26 | ␉//First VESA Table␊ |
27 | ␉while (i < 0x300) //We don't need to look for the table in the whole bios, the 768 first bytes only␊ |
28 | ␉{ ␊ |
29 | ␉␉if ((map->biosPtr[i] == 0x44) ␊ |
30 | ␉␉␉&& (map->biosPtr[i+1] == 0x01) ␊ |
31 | ␉␉␉&& (map->biosPtr[i+2] == 0x04) ␊ |
32 | ␉␉␉&& (map->biosPtr[i+3] == 0x00)) {␊ |
33 | ␉␉␉nvDataTableOffset = (unsigned short) (map->biosPtr[i+4] | (map->biosPtr[i+5] << 8));␊ |
34 | ␉␉␉break;␊ |
35 | ␉␉}␊ |
36 | ␉␉i++;␊ |
37 | ␉}␊ |
38 | ␉␊ |
39 | ␉nvDataTable = (unsigned short *) (map->biosPtr + (nvDataTableOffset + OFFSET_TO_VESA_TABLE_INDEX));␊ |
40 | ␉stdVesa = (nvVesaTable *) (map->biosPtr + *nvDataTable);␊ |
41 | ␉table->pointer = (uint8_t *) stdVesa + sizeof(nvCommonTableHeader);␊ |
42 | ␉verbose("First Standard VESA Table at offset 0x%x\n",(unsigned int) (table->pointer - map->biosPtr));␊ |
43 | ␉␊ |
44 | ␉//Second VESA Table␊ |
45 | ␉while (i < VBIOS_SIZE) //We don't know how to locate it other way␊ |
46 | ␉{␊ |
47 | ␉␉if ((map->biosPtr[i] == 0x40) && (map->biosPtr[i+1] == 0x01) //this is the first 320x200 modeline.␊ |
48 | ␉␉␉&& (map->biosPtr[i+2] == 0xC8) && (map->biosPtr[i+3] == 0x00)␊ |
49 | ␉␉␉&& (map->biosPtr[i+4] == 0x28)␊ |
50 | ␉␉␉&& (map->biosPtr[i+5] == 0x18)␊ |
51 | ␉␉␉&& (map->biosPtr[i+6] == 0x08)␊ |
52 | ␉␉␉&& (map->biosPtr[i+7] == 0x08))␊ |
53 | ␉␉{␊ |
54 | ␉␉␉nvModeline_2_Offset = (unsigned short) i;␊ |
55 | ␉␉␉break;␊ |
56 | ␉␉}␊ |
57 | ␉␉i++;␊ |
58 | ␉}␊ |
59 | ␉␊ |
60 | ␉␊ |
61 | ␉␊ |
62 | ␉if (nvModeline_2_Offset == (VBIOS_SIZE-1) || nvModeline_2_Offset == 0)␊ |
63 | ␉{␊ |
64 | ␉␉//If no second vesa table is available, free the corresponding table in chain␊ |
65 | ␉␉free(table->next);␊ |
66 | ␉␉table->next = NULL;␊ |
67 | ␉␉PRINT("There is no Second Standard VESA Table to patch\n");␊ |
68 | ␉} ␊ |
69 | ␉else␊ |
70 | ␉{␊ |
71 | ␉␉table = table->next;␊ |
72 | ␉␉table->pointer = map->biosPtr + nvModeline_2_Offset;␊ |
73 | ␉␉PRINT("Second Standard VESA Table at offset 0x%x\n", (unsigned int)(table->pointer - map->biosPtr));␊ |
74 | ␉}␊ |
75 | ␉␊ |
76 | ␉if (table->prev->pointer == NULL)␊ |
77 | ␉{␊ |
78 | ␉␉PRINT("Unable to locate the mode table.\n");␊ |
79 | ␉␉PRINT("Please run the program 'dumpBios' as root and\n");␊ |
80 | ␉␉PRINT("email the file 'vbios.dmp' to gaeloulacuisse@yahoo.fr.\n");␊ |
81 | ␉␉␊ |
82 | ␉␉closeVbios(map);␊ |
83 | ␉␉return 0;␊ |
84 | ␉}␊ |
85 | ␉␊ |
86 | ␉// reset the table pointer to the first in chain␊ |
87 | ␉table = map->modeTables;␊ |
88 | ␉␊ |
89 | ␉/*␊ |
90 | ␉ * for each table in chain, figure out how many modes are available␊ |
91 | ␉ * and what is the size of the table␊ |
92 | ␉ */␊ |
93 | ␉while (table != NULL)␊ |
94 | ␉{␊ |
95 | ␉␉table->modeCount = 0;␊ |
96 | ␉␉PRINT("Table #%d has ", table->id);␊ |
97 | ␉␉␊ |
98 | ␉␉if (table->id == MAIN_VESA_TABLE)␊ |
99 | ␉␉{␊ |
100 | ␉␉␉table->modeCount = stdVesa->header.tableSize & 0xff;␊ |
101 | ␉␉␉if (table->modeCount == 0) table->modeCount = 16;␊ |
102 | ␉␉␉table->size = table->modeCount * sizeof(nvModeline);␊ |
103 | ␉␉}␊ |
104 | ␉␉␊ |
105 | ␉␉if (table->id == SECOND_VESA_TABLE)␊ |
106 | ␉␉{␊ |
107 | ␉␉␉nvModeline_2 * modePtr = (nvModeline_2 *)table->pointer;␊ |
108 | ␉␉␉while (1)␊ |
109 | ␉␉␉{␊ |
110 | ␉␉␉␉if (modePtr[table->modeCount].hActive > 2048) break;␊ |
111 | ␉␉␉␉table->modeCount++;␉␉␊ |
112 | ␉␉␉}␊ |
113 | ␉␉␉if (table->modeCount == 0) table->modeCount = 31;␊ |
114 | ␉␉␉table->size = table->modeCount * sizeof(nvModeline_2);␊ |
115 | ␉␉}␊ |
116 | ␉␉␊ |
117 | ␉␉PRINT("%d modes\n", table->modeCount);␊ |
118 | ␉␉table = table->next;␊ |
119 | ␉}␊ |
120 | ␉␊ |
121 | ␉map->setMode = nvidiaSetMode;␊ |
122 | ␉␊ |
123 | ␉saveTables(map->modeTables);␊ |
124 | ␉␊ |
125 | #if AUTORES_DEBUG␊ |
126 | ␉PRINT("Press Any Key...\n");␊ |
127 | ␉getc();␊ |
128 | #endif␊ |
129 | ␉␊ |
130 | ␉return map;␊ |
131 | }␊ |
132 | ␊ |
133 | bool nvidiaSetMode(sModeTable * table, uint8_t idx, uint32_t* x, uint32_t* y)␊ |
134 | {␊ |
135 | ␉//In First VESA table, only first mode in table is patched␊ |
136 | ␉if (table->id == MAIN_VESA_TABLE)␊ |
137 | ␉{␊ |
138 | ␉␉nvModeline * modeTiming = (nvModeline *)table->pointer;␊ |
139 | ␉␉␊ |
140 | ␉␉// patch only if mode differs and if the mode to patch isn't a console mode␊ |
141 | ␉␉if (((*x != modeTiming[idx].hActive) || (*y != modeTiming[idx].vActive))␊ |
142 | ␉␉␉&& (modeTiming[idx].hActive > 100))␊ |
143 | ␉␉{␊ |
144 | ␉␉␉␊ |
145 | ␉␉␉PRINT("Mode %dx%d -> ", modeTiming[idx].hActive, modeTiming[idx].vActive);␊ |
146 | ␉␉␉␊ |
147 | ␉␉␉if (modeTiming[idx].hActive != *x)␊ |
148 | ␉␉␉{␊ |
149 | ␉␉␉␉modeTiming[idx].hActive = *x;␊ |
150 | ␉␉␉␉modeTiming[idx].hActiveMinusOne = *x - 1;␊ |
151 | ␉␉␉␉modeTiming[idx].hActiveMinusOne_ = *x - 1;␊ |
152 | ␉␉␉}␊ |
153 | ␉␉␉␊ |
154 | ␉␉␉modeTiming[idx].vActive = *y;␊ |
155 | ␉␉␉modeTiming[idx].vActiveMinusOne = *y - 1;␊ |
156 | ␉␉␉modeTiming[idx].vActiveMinusOne_ = *y - 1;␊ |
157 | ␉␉␉␊ |
158 | ␉␉␉PRINT("%dx%d (%d %d %d %d %d %d)\n",␊ |
159 | ␉␉␉␉ modeTiming[idx].hActive,␊ |
160 | ␉␉␉␉ modeTiming[idx].vActive,␊ |
161 | ␉␉␉␉ modeTiming[idx].hSyncStart,␊ |
162 | ␉␉␉␉ modeTiming[idx].hSyncEnd,␊ |
163 | ␉␉␉␉ modeTiming[idx].hTotal,␊ |
164 | ␉␉␉␉ modeTiming[idx].vSyncStart,␊ |
165 | ␉␉␉␉ modeTiming[idx].vSyncEnd,␊ |
166 | ␉␉␉␉ modeTiming[idx].vTotal);␊ |
167 | ␉␉}␊ |
168 | ␉␉␊ |
169 | ␉␉//Since we are only patching the first mode, this deprecated␊ |
170 | ␉␉*x = modeTiming[idx + 1].hActive;␊ |
171 | ␉␉*y = modeTiming[idx + 1].vActive;␊ |
172 | ␉}␊ |
173 | ␉␊ |
174 | ␉if (table->id == SECOND_VESA_TABLE)␊ |
175 | ␉{␊ |
176 | ␉␉nvModeline_2 * modeTiming = (nvModeline_2 *) table->pointer;␊ |
177 | ␉␉int h = *y;␊ |
178 | ␉␉int w = *x;␊ |
179 | ␉␉␊ |
180 | ␉␉while (idx < table->modeCount)␊ |
181 | ␉␉{␊ |
182 | ␉␉␉*y = *x * h / w;␊ |
183 | ␉␉␉//patch only different mode in table except console modes and 320 wide modes␊ |
184 | ␉␉␉if (((*x != modeTiming[idx].hActive) || (*y != modeTiming[idx].vActive))␊ |
185 | ␉␉␉␉&& (modeTiming[idx].hActive > 400))␊ |
186 | ␉␉␉{␊ |
187 | ␉␉␉␊ |
188 | ␉␉␉␉PRINT("Mode %dx%d -> ", modeTiming[idx].hActive, modeTiming[idx].vActive);␊ |
189 | ␉␉␉␊ |
190 | ␉␉␉␉if (modeTiming[idx].hActive != *x)␊ |
191 | ␉␉␉␉␉modeTiming[idx].hActive = *x;␊ |
192 | ␉␉␉␊ |
193 | ␉␉␉␉modeTiming[idx].vActive = *y;␊ |
194 | ␉␉␉␊ |
195 | ␉␉␉␉PRINT("%dx%d (%d %d %d %d ",␊ |
196 | ␉␉␉␉␉ modeTiming[idx].hActive,␊ |
197 | ␉␉␉␉␉ modeTiming[idx].vActive,␊ |
198 | ␉␉␉␉␉ modeTiming[idx].hActive + modeTiming[idx].hSyncOffset,␊ |
199 | ␉␉␉␉␉ modeTiming[idx].hActive + modeTiming[idx].hSyncOffset + modeTiming[idx].hSyncWidth,␊ |
200 | ␉␉␉␉␉ modeTiming[idx].hActive + modeTiming[idx].hBlank,␊ |
201 | ␉␉␉␉␉ modeTiming[idx].vActive + modeTiming[idx].vBlank);␊ |
202 | ␉␉␉␊ |
203 | ␉␉␉␉if ((modeTiming[idx].flags & HSyncPolarityMask) == HSyncPolarityMask)␊ |
204 | ␉␉␉␉{␉PRINT("H- ");␉}␊ |
205 | ␉␉␉␉else␊ |
206 | ␉␉␉␉{␉PRINT("H+ ");␉}␊ |
207 | ␊ |
208 | ␉␉␉␉if ((modeTiming[idx].flags & VSyncPolarityMask) == VSyncPolarityMask)␊ |
209 | ␉␉␉␉{␉PRINT("V-)\n");␉}␊ |
210 | ␉␉␉␉else␊ |
211 | ␉␉␉␉{␉PRINT("V+)\n");␉}␊ |
212 | ␉␉␉}␊ |
213 | ␉␉␉//returns the next mode in table␊ |
214 | ␉␉␉*x = modeTiming[idx + 1].hActive;␊ |
215 | ␉␉␉*y = modeTiming[idx + 1].vActive;␊ |
216 | ␉␉␉␊ |
217 | ␉␉␉idx++;␊ |
218 | ␉␉}␊ |
219 | ␉␉␊ |
220 | ␉␉␊ |
221 | ␉␉␊ |
222 | ␉}␊ |
223 | ␉return TRUE;␊ |
224 | } |