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 | ␉if (nvModeline_2_Offset == (VBIOS_SIZE-1) || nvModeline_2_Offset == 0)␊ |
61 | ␉{␊ |
62 | ␉␉//If no second vesa table is available, free the corresponding table in chain␊ |
63 | ␉␉free(table->next);␊ |
64 | ␉␉table->next = NULL;␊ |
65 | ␉␉PRINT("There is no Second Standard VESA Table to patch\n");␊ |
66 | ␉} ␊ |
67 | ␉else␊ |
68 | ␉{␊ |
69 | ␉␉table = table->next;␊ |
70 | ␉␉table->pointer = map->biosPtr + nvModeline_2_Offset;␊ |
71 | ␉␉PRINT("Second Standard VESA Table at offset 0x%x\n", (unsigned int)(table->pointer - map->biosPtr));␊ |
72 | ␉}␊ |
73 | ␉␊ |
74 | ␉if (table->prev->pointer == NULL)␊ |
75 | ␉{␊ |
76 | ␉␉PRINT("Unable to locate the mode table.\n");␊ |
77 | ␉␉PRINT("Please run the program 'dumpBios' as root and\n");␊ |
78 | ␉␉PRINT("email the file 'vbios.dmp' to gaeloulacuisse@yahoo.fr.\n");␊ |
79 | ␉␉␊ |
80 | ␉␉closeVbios(map);␊ |
81 | ␉␉return 0;␊ |
82 | ␉}␊ |
83 | ␉␊ |
84 | ␉// reset the table pointer to the first in chain␊ |
85 | ␉table = map->modeTables;␊ |
86 | ␉␊ |
87 | ␉/*␊ |
88 | ␉ * for each table in chain, figure out how many modes are available␊ |
89 | ␉ * and what is the size of the table␊ |
90 | ␉ */␊ |
91 | ␉while (table != NULL)␊ |
92 | ␉{␊ |
93 | ␉␉table->modeCount = 0;␊ |
94 | ␉␉PRINT("Table #%d has ", table->id);␊ |
95 | ␉␉␊ |
96 | ␉␉if (table->id == MAIN_VESA_TABLE)␊ |
97 | ␉␉{␊ |
98 | ␉␉␉table->modeCount = stdVesa->header.tableSize & 0xff;␊ |
99 | ␉␉␉if (table->modeCount == 0) table->modeCount = 16;␊ |
100 | ␉␉␉table->size = table->modeCount * sizeof(nvModeline);␊ |
101 | ␉␉}␊ |
102 | ␉␉␊ |
103 | ␉␉if (table->id == SECOND_VESA_TABLE)␊ |
104 | ␉␉{␊ |
105 | ␉␉␉nvModeline_2 * modePtr = (nvModeline_2 *)table->pointer;␊ |
106 | ␉␉␉while (1)␊ |
107 | ␉␉␉{␊ |
108 | ␉␉␉␉if (modePtr[table->modeCount].hActive > 2048) break;␊ |
109 | ␉␉␉␉table->modeCount++;␉␉␊ |
110 | ␉␉␉}␊ |
111 | ␉␉␉if (table->modeCount == 0) table->modeCount = 31;␊ |
112 | ␉␉␉table->size = table->modeCount * sizeof(nvModeline_2);␊ |
113 | ␉␉}␊ |
114 | ␉␉␊ |
115 | ␉␉PRINT("%d modes\n", table->modeCount);␊ |
116 | ␉␉table = table->next;␊ |
117 | ␉}␊ |
118 | ␉␊ |
119 | ␉map->setMode = nvidiaSetMode;␊ |
120 | ␉␊ |
121 | ␉saveTables(map->modeTables);␊ |
122 | ␉␊ |
123 | #ifdef AUTORES_DEBUG␊ |
124 | ␉pause();␊ |
125 | #endif␊ |
126 | ␉␊ |
127 | ␉return map;␊ |
128 | }␊ |
129 | ␊ |
130 | bool nvidiaSetMode(sModeTable * table, uint8_t idx, uint32_t* x, uint32_t* y)␊ |
131 | {␊ |
132 | ␉//In First VESA table, only first mode in table is patched␊ |
133 | ␉if (table->id == MAIN_VESA_TABLE)␊ |
134 | ␉{␊ |
135 | ␉␉nvModeline * modeTiming = (nvModeline *)table->pointer;␊ |
136 | ␉␉␊ |
137 | ␉␉// patch only if mode differs and if the mode to patch isn't a console mode␊ |
138 | ␉␉if (((*x != modeTiming[idx].hActive) || (*y != modeTiming[idx].vActive))␊ |
139 | ␉␉␉&& (modeTiming[idx].hActive > 100))␊ |
140 | ␉␉{␊ |
141 | ␉␉␉␊ |
142 | ␉␉␉PRINT("Mode %dx%d -> ", modeTiming[idx].hActive, modeTiming[idx].vActive);␊ |
143 | ␉␉␉␊ |
144 | ␉␉␉if (modeTiming[idx].hActive != *x)␊ |
145 | ␉␉␉{␊ |
146 | ␉␉␉␉modeTiming[idx].hActive = *x;␊ |
147 | ␉␉␉␉modeTiming[idx].hActiveMinusOne = *x - 1;␊ |
148 | ␉␉␉␉modeTiming[idx].hActiveMinusOne_ = *x - 1;␊ |
149 | ␉␉␉}␊ |
150 | ␉␉␉␊ |
151 | ␉␉␉modeTiming[idx].vActive = *y;␊ |
152 | ␉␉␉modeTiming[idx].vActiveMinusOne = *y - 1;␊ |
153 | ␉␉␉modeTiming[idx].vActiveMinusOne_ = *y - 1;␊ |
154 | ␉␉␉␊ |
155 | ␉␉␉PRINT("%dx%d (%d %d %d %d %d %d)\n",␊ |
156 | ␉␉␉␉ modeTiming[idx].hActive,␊ |
157 | ␉␉␉␉ modeTiming[idx].vActive,␊ |
158 | ␉␉␉␉ modeTiming[idx].hSyncStart,␊ |
159 | ␉␉␉␉ modeTiming[idx].hSyncEnd,␊ |
160 | ␉␉␉␉ modeTiming[idx].hTotal,␊ |
161 | ␉␉␉␉ modeTiming[idx].vSyncStart,␊ |
162 | ␉␉␉␉ modeTiming[idx].vSyncEnd,␊ |
163 | ␉␉␉␉ modeTiming[idx].vTotal);␊ |
164 | ␉␉}␊ |
165 | ␉␉␊ |
166 | ␉␉//Since we are only patching the first mode, this deprecated␊ |
167 | ␉␉*x = modeTiming[idx + 1].hActive;␊ |
168 | ␉␉*y = modeTiming[idx + 1].vActive;␊ |
169 | ␉}␊ |
170 | ␉␊ |
171 | ␉if (table->id == SECOND_VESA_TABLE)␊ |
172 | ␉{␊ |
173 | ␉␉nvModeline_2 * modeTiming = (nvModeline_2 *) table->pointer;␊ |
174 | ␉␉int h = *y;␊ |
175 | ␉␉int w = *x;␊ |
176 | ␉␉␊ |
177 | ␉␉while (idx < table->modeCount)␊ |
178 | ␉␉{␊ |
179 | ␉␉␉*y = *x * h / w;␊ |
180 | ␉␉␉//patch only different mode in table except console modes and 320 wide modes␊ |
181 | ␉␉␉if (((*x != modeTiming[idx].hActive) || (*y != modeTiming[idx].vActive))␊ |
182 | ␉␉␉␉&& (modeTiming[idx].hActive > 400))␊ |
183 | ␉␉␉{␊ |
184 | ␉␉␉␊ |
185 | ␉␉␉␉PRINT("Mode %dx%d -> ", modeTiming[idx].hActive, modeTiming[idx].vActive);␊ |
186 | ␉␉␉␊ |
187 | ␉␉␉␉if (modeTiming[idx].hActive != *x)␊ |
188 | ␉␉␉␉␉modeTiming[idx].hActive = *x;␊ |
189 | ␉␉␉␊ |
190 | ␉␉␉␉modeTiming[idx].vActive = *y;␊ |
191 | ␉␉␉␊ |
192 | ␉␉␉␉PRINT("%dx%d (%d %d %d %d ",␊ |
193 | ␉␉␉␉␉ modeTiming[idx].hActive,␊ |
194 | ␉␉␉␉␉ modeTiming[idx].vActive,␊ |
195 | ␉␉␉␉␉ modeTiming[idx].hActive + modeTiming[idx].hSyncOffset,␊ |
196 | ␉␉␉␉␉ modeTiming[idx].hActive + modeTiming[idx].hSyncOffset + modeTiming[idx].hSyncWidth,␊ |
197 | ␉␉␉␉␉ modeTiming[idx].hActive + modeTiming[idx].hBlank,␊ |
198 | ␉␉␉␉␉ modeTiming[idx].vActive + modeTiming[idx].vBlank);␊ |
199 | ␉␉␉␊ |
200 | ␉␉␉␉if ((modeTiming[idx].flags & HSyncPolarityMask) == HSyncPolarityMask)␊ |
201 | ␉␉␉␉{␉PRINT("H- ");␉}␊ |
202 | ␉␉␉␉else␊ |
203 | ␉␉␉␉{␉PRINT("H+ ");␉}␊ |
204 | ␊ |
205 | ␉␉␉␉if ((modeTiming[idx].flags & VSyncPolarityMask) == VSyncPolarityMask)␊ |
206 | ␉␉␉␉{␉PRINT("V-)\n");␉}␊ |
207 | ␉␉␉␉else␊ |
208 | ␉␉␉␉{␉PRINT("V+)\n");␉}␊ |
209 | ␉␉␉}␊ |
210 | ␉␉␉//returns the next mode in table␊ |
211 | ␉␉␉*x = modeTiming[idx + 1].hActive;␊ |
212 | ␉␉␉*y = modeTiming[idx + 1].vActive;␊ |
213 | ␉␉␉␊ |
214 | ␉␉␉idx++;␊ |
215 | ␉␉}␊ |
216 | ␉}␊ |
217 | ␉return true;␊ |
218 | }␊ |
219 | |