2012年6月25日 星期一

在保護模式下, 不使用 vga bios 呼叫, 將顯示卡設定為繪圖模式 (0) - 失敗篇

花了不少時間完成這篇, 最後才發現這是失敗的版本, 心中的氣餒可想而知, 所有的興奮之情一掃而空。緊急關掉這篇, 怕誤人子弟, dosbox 實在太不可靠, 不能拿來測試, 很多錯誤的程式寫法在 dosbox 上還是可以正常執行。這篇僅留做失敗的教訓, 作為一個紀錄。

請注意本篇的內容是錯誤的。

請改為參考成功的版本:
http://descent-incoming.blogspot.tw/2012/06/vga-biso.html




這次的實驗:
在保護模式下, 不使用 vga biso 呼叫, 將顯示卡設定為繪圖模式。不過在切回真實模式後, 還是呼叫 vga bios 函式呼叫切回文字模式。

參考了一些早期的 VGA/SVGA 書籍, 都是使用 vga bios int 0x10 來切換文字/圖形模式, 但在進入保護模式後, int 0x10 是無法使用的, 我也不願意為了這原因, 在切回真實模式只為了使用 vga bios int 0x10, 在 http://bos.asmhackers.net/docs/vga_without_bios/docs/mode%2013h%20without%20using%20bios.htm 找到一段 code, 稍微改寫一下, 在 gcc 環境下可以編譯, 不過由於沒有 spec, 我無法了解這是對 VGA 做了什麼樣的設定。

這次的程式延續上次, 需要使用 C 語言, 不用辛苦和組合語言奮鬥, 程式一開始進入保護模式, 切換程 320X200X256 色 mode, 在將整個螢幕填成白色, 我有另外一個顏色的版本。切回真實模式後, 還是呼叫 vga bios 函式呼叫切回文字模式。我知道這不完美, 應該使用自己的程式切回文字模式, 不過目前來說這樣就可以讓我繼續下去, 靠著自己切回文字模式就晚點吧!

30 天打造 OS, 這本書上是先使用 int 0x10 切到繪圖模式, 在進入保護模式, 有點受制於 vga bios call, 能用自己的 code 來切換, 真是令人開心。這種解析度好像爛了些, 不過沒辦法, VGA 標準就是這樣, 將就著用。

5M_mem_rw_mix_c_vga.S 1 /*
2 ref: Orange'S:一个操作系统的实现
3 do the 5M memory r/w
4 link with C code, but not yet ok.
5 */
6 /* chapter3/1/loader.S
7
8 Author: Wenbo Yang <solrex@gmail.com> <http://solrex.cn>
9
10 This file is part of the source code of book "Write Your Own OS with Free
11 and Open Source Software". Homepage @ <http://share.solrex.cn/WriteOS/>.
12
13 This file is licensed under the GNU General Public License; either
14 version 3 of the License, or (at your option) any later version. */
15
16 #include "pm.h"
17
18 .code16
19 .text
20 jmp LABEL_BEGIN /* jump over the .data section. */
21
22 /* NOTE! Wenbo-20080512: Actually here we put the normal .data section into
23 the .code section. For application SW, it is not allowed. However, we are
24 writing an OS. That is OK. Because there is no OS to complain about
25 that behavior. :) */
26
27 /* Global Descriptor Table */
28 LABEL_GDT: Descriptor 0, 0, 0
29 LABEL_DESC_NORMAL: Descriptor 0, 0xffff, DA_DRW # Normal descriptor is for back to real mode.
30 LABEL_DESC_CODE32: Descriptor 0, (SegCode32Len - 1), (DA_C + DA_32)
31 LABEL_DESC_CODE16: Descriptor 0, 0xffff, DA_C # 非一致程式碼段, 16
32 LABEL_DESC_DATA: Descriptor 0, DataLen-1, DA_DRW # Data
33 LABEL_DESC_STACK: Descriptor 0, TopOfStack, DA_DRWA+DA_32 # Stack, 32 位
34 LABEL_DESC_TEST: Descriptor 0x500000, 0xffff, DA_DRW
35 LABEL_DESC_VIDEO: Descriptor 0xB8000, 0xffff, DA_DRW
36 LABEL_DESC_TEST_DATA: Descriptor 0, 0xffff, DA_DRW # Data
37
38 .set GdtLen, (. - LABEL_GDT) /* GDT Length */
39
40 GdtPtr: .2byte (GdtLen - 1) /* GDT Limit */
41 .4byte 0 /* GDT Base */
42
43 /* GDT Selector */
44 .set SelectorNormal, (LABEL_DESC_NORMAL - LABEL_GDT)
45 .set SelectorCode32, (LABEL_DESC_CODE32 - LABEL_GDT)
46 .set SelectorCode16, (LABEL_DESC_CODE16 - LABEL_GDT)
47 .set SelectorData, (LABEL_DESC_DATA - LABEL_GDT)
48 .set SelectorStack, (LABEL_DESC_STACK - LABEL_GDT)
49 .set SelectorTest, (LABEL_DESC_TEST - LABEL_GDT)
50 .set SelectorVideo, (LABEL_DESC_VIDEO - LABEL_GDT)
51 .set SELECT_TEST_DATA, (LABEL_DESC_TEST_DATA - LABEL_GDT)
52
53
54 /* Program starts here. */
55 LABEL_BEGIN:
56 mov %cs, %ax /* Move code segment address(CS) to data segment */
57 mov %ax, %ds /* register(DS), ES and SS. Because we have */
58 mov %ax, %es /* embedded .data section into .code section in */
59 mov %ax, %ss /* the start(mentioned in the NOTE above). */
60
61 movw $0x100, %sp
62 nop
63 movw %ax, (LABEL_GO_BACK_TO_REAL+3) # modify segment value, indexed memory mode, ref professional aeesmbly language p 102.
64
65 /* Initialize 16-bits code segment descriptor. */
66 xor %eax, %eax
67 mov %cs, %ax
68 shl $4, %eax
69 addl $(LABEL_SEG_CODE16), %eax
70 movw %ax, (LABEL_DESC_CODE16 + 2)
71 shr $16, %eax
72 movb %al, (LABEL_DESC_CODE16 + 4)
73 movb %ah, (LABEL_DESC_CODE16 + 7)
74
75 /* Initialize 32-bits code segment descriptor. */
76 xor %eax, %eax
77 mov %cs, %ax
78 shl $4, %eax
79 addl $(LABEL_SEG_CODE32), %eax
80 movw %ax, (LABEL_DESC_CODE32 + 2)
81 shr $16, %eax
82 movb %al, (LABEL_DESC_CODE32 + 4)
83 movb %ah, (LABEL_DESC_CODE32 + 7)
84
85 # initialize data segment descriptor
86 xor %eax, %eax
87 mov %ds, %ax
88 shl $4, %eax
89 addl $(LABEL_DATA), %eax
90 movw %ax, (LABEL_DESC_DATA + 2)
91 shr $16, %eax
92 movb %al, (LABEL_DESC_DATA + 4)
93 movb %ah, (LABEL_DESC_DATA + 7)
94
95 # initialize stack segment descriptor
96 xor %eax, %eax
97 mov %ds, %ax
98 shl $4, %eax
99 addl $(LABEL_STACK), %eax
100 movw %ax, (LABEL_DESC_STACK + 2)
101 shr $16, %eax
102 movb %al, (LABEL_DESC_STACK + 4)
103 movb %ah, (LABEL_DESC_STACK + 7)
104
105 /* Prepared for loading GDTR */
106 xor %eax, %eax
107 mov %ds, %ax
108 shl $4, %eax
109 add $(LABEL_GDT), %eax /* eax <- gdt base*/
110 movl %eax, (GdtPtr + 2)
111
112 /* Load GDTR(Global Descriptor Table Register) */
113 lgdtw GdtPtr
114
115 /* Clear Interrupt Flags */
116 cli
117
118 /* Open A20 line. */
119 inb $0x92, %al
120 orb $0b00000010, %al
121 outb %al, $0x92
122
123 /* Enable protect mode, PE bit of CR0. */
124 movl %cr0, %eax
125 orl $1, %eax
126 movl %eax, %cr0
127
128 /* Mixed-Size Jump. */
129 ljmp $SelectorCode32, $0 /* Thanks to earthengine@gmail, I got */
130 /* this mixed-size jump insn of gas. */
131 /* this calls far jump (ptr 16:32) in intel manual) */
132
133 LABEL_REAL_ENTRY: # 從保護模式跳回到實模式就到了這裡
134 mov %cx, %ax
135 mov %ax, %ds
136 mov %ax, %es
137 mov %ax, %ss
138
139 # mov sp, [SPValueInRealMode]
140
141 in $0x92, %al
142 and $0b11111101, %al # close A20 line
143 out %al, $0x92
144
145 sti # 開中斷
146
147
148
149 # read a key from keyboard, bios call
150 movb $0x0, %ah
151 int $0x16
152
153 #if 1
154 # switch to text mode
155 movb $0x3, %al
156 movb $0x0, %ah
157 int $0x10
158 #endif
159
160 mov $0x4c00, %ax
161 int $0x21 # 回到 DOS
162 # END of .code16
163
164 LABEL_SEG_CODE32:
165 .code32
166
167 mov $(SelectorData), %ax
168 mov %ax, %ds # 資料段選擇子
169 mov $(SelectorTest), %ax
170 mov %ax, %es # 測試段選擇子
171
172
173
174
175 mov $(SelectorVideo), %ax
176 mov %ax, %gs /* Video segment selector(dest) */
177
178 mov $(SELECT_TEST_DATA), %ax
179 mov %ax, %es /* Video segment selector(dest) */
180
181 mov $(SelectorStack), %ax
182 mov %ax, %ss # 堆疊段選擇子
183
184 mov $(TopOfStack), %esp
185
186 /*
187 movl $((80 * 10 + 0) * 2), %edi
188 movb $0xC, %ah # 0000: Black Back 1100: Red Front
189 movb $'P', %al
190
191 mov %ax, %gs:(%edi)
192 */
193
194 # print string "In Protect Mode now. ^-^"
195 movb $0x0c, %ah # 0000: 黑底 1100: 紅字
196 xor %esi, %esi
197 xor %edi, %edi
198 mov $(OffsetPMMessage), %esi # data string offset
199 movl $((80 * 10 + 0) * 2), %edi # 目的資料偏移。螢幕第 10 行, 第 0 列。
200 cld # Clear Direction Flag, ref: http://www.fermi.mn.it/linux/quarta/x86/cld.htm
201 # After CLD is executed, string operations will increment the index
202 # (SI and/or DI) that they use.
203 .1:
204 lodsb # For legacy mode, Load byte at address DS:(E)SI into AL.
205 # For 64-bit mode load byte at address (R)SI into AL.
206 # ref: http://siyobik.info/main/reference/instruction/LODS%2FLODSB%2FLODSW%2FLODSD%2FLODSQ
207 test %al, %al # result is 0, zf sets to 1.
208 jz .2 # zf = 1 jump
209 # mov [gs:edi], ax
210 mov %ax, %gs:(%edi)
211 add $2, %edi
212 jmp .1
213 .2: # 顯示完畢
214
215 #push %eax # Multiboot magic number
216 # push %ebx # Multiboot data structure
217
218 # movb $0xef, %al
219 # call kmain
220 # call init_graph_vga
221 call vga_test
222 movb $0xa9, %al
223 call DispAL
224 /*
225 call DispReturn
226 #movb $0xa9, %al
227 #call DispAL
228
229 call TestRead
230 call TestWrite
231 call TestRead
232 */
233
234 ljmpl $SelectorCode16,$0
235 # jmpl $SelectorCode16,$0 # it works
236
237 # ------------------------------------------------------------------------
238 TestRead:
239 xor %esi, %esi
240 mov $8, %ecx
241 .loop:
242 mov %es:(%esi), %al
243 call DispAL
244 inc %esi
245 loop .loop
246 call DispReturn
247
248 ret
249 # TestRead 結束-----------------------------------------------------------
250
251
252 # ------------------------------------------------------------------------
253 TestWrite:
254 pushl %esi
255 pushl %edi
256 xor %esi, %esi
257 xor %edi, %edi
258 mov $(OffsetStrTest), %esi # data offset
259 cld # Clear Direction Flag, ref: http://www.fermi.mn.it/linux/quarta/x86/cld.htm
260 # After CLD is executed, string operations will increment the index
261 # (SI and/or DI) that they use.
262 .6:
263 lodsb # For legacy mode, Load byte at address DS:(E)SI into AL.
264 # For 64-bit mode load byte at address (R)SI into AL.
265 # ref: http://siyobik.info/main/reference/instruction/LODS%2FLODSB%2FLODSW%2FLODSD%2FLODSQ
266
267 test %al, %al
268 jz .5 # zf = 1 jump
269 # mov [es:edi], al
270 mov %al, %es:(%edi)
271 inc %edi
272 jmp .6
273 .5:
274
275 popl %edi
276 popl %esi
277 ret
278 # TestWrite 結束----------------------------------------------------------
279
280 # ref 30 天打造OS, page 80
281 .globl write_mem8
282 write_mem8:
283 mov 4(%esp), %ecx;
284 movb 8(%esp), %al;
285 mov %al, %es:(%ecx)
286 ret
287
288 # ------------------------------------------------------------------------
289 # 顯示 AL 中的數字
290 # 默認地:
291 # 數字已經存在 AL 中
292 # edi 始終指向要顯示的下一個字元的位置
293 # 被改變的暫存器:
294 # ax, edi
295 # ------------------------------------------------------------------------
296 .globl DispAL
297 DispAL:
298 pushl %ecx
299 pushl %edx
300
301 movb $0x0c, %ah # 0000: 黑底 1100: 紅字
302 movb %al, %dl
303 shr $4, %al
304 movl $2, %ecx
305 .begin:
306 andb $0x0f, %al
307 cmp $9, %al
308 ja .3 # cf=0, zf=0, above 9 (>9)
309 #addb $'0', %al
310 addb $0x30, %al
311 jmp .4
312 .3:
313 sub $0x0A, %al
314 #add $'A', %al
315 add $0x41, %al
316 .4:
317 #mov [gs:edi], ax
318 mov %ax, %gs:(%edi)
319 add $2, %edi
320
321 mov %dl, %al
322 loop .begin
323 add $2, %edi
324
325 popl %edx
326 popl %ecx
327
328 ret
329 # DispAL 結束-------------------------------------------------------------
330
331
332 # ------------------------------------------------------------------------
333 DispReturn:
334 pushl %eax
335 pushl %ebx
336 mov %edi, %eax
337 movb $160, %bl
338 divb %bl # %eax/160, 商 al, 餘數 ah.
339 and $0x0FF, %eax
340 inc %eax # ++ %eax
341 mov $160, %bl
342 mul %bl
343 mov %eax, %edi
344 popl %ebx
345 popl %eax
346 ret
347 # DispReturn 結束---------------------------------------------------------
348
349 /*
350 kmain:
351 pushl %ebp
352 movl %esp, %ebp
353 popl %ebp
354 ret
355 .size kmain, .-kmain
356 .ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2"
357 */
358 # .section .note.GNU-stack,"",@progbits
359
360
361 /* Get the length of 32-bit segment code. */
362 .set SegCode32Len, . - LABEL_SEG_CODE32
363
364 #[SECTION .data1] ; 資料段
365 #ALIGN 32
366 #[BITS 32]
367 LABEL_DATA:
368 SPValueInRealMode: .2byte 0x0
369 # string
370 PMMessage: .ascii "In Protect Mode now. ^-^\0" # 在保護模式中顯示
371 .set OffsetPMMessage, (PMMessage - LABEL_DATA)
372 #StrTest: .ascii "B\0"
373 StrTest: .ascii "ABCDEFGHIJKLMNOPQRSTUVWXYZ\0"
374 #OffsetStrTest equ StrTest - $$
375 .set OffsetStrTest , (StrTest - LABEL_DATA)
376 #DataLen equ $ - LABEL_DATA
377 .set DataLen, . - LABEL_DATA
378 /* 32-bit global stack segment. */
379 LABEL_STACK:
380 .space 512, 0
381 .set TopOfStack, (. - LABEL_STACK - 1)
382
383 # END of [SECTION .data1]
384
385
386 LABEL_SEG_CODE16:
387 .code16
388 #jmp .
389 # back to real mode
390 mov $SelectorNormal, %ax
391 mov %ax, %ds
392 mov %ax, %es
393 mov %ax, %fs
394 mov %ax, %gs
395 mov %ax, %ss
396
397 mov %cr0, %eax
398 and $0b11111110, %al
399 mov %eax, %cr0
400
401
402 LABEL_GO_BACK_TO_REAL:
403 #.2byte 0xea66
404 #.4byte 0x00000000
405 #.2byte LABEL_REAL_ENTRY
406 jmp $0, $LABEL_REAL_ENTRY # 段位址會在程序開始處被設置成正確的值
407
408
409 .set Code16Len, . - LABEL_SEG_CODE16


switch_vga_mode.c 1 // ref: http://bos.asmhackers.net/docs/vga_without_bios/docs/mode%2013h%20without%20using%20bios.htm
2
3 //
4 // vga mode switcher by Jonas Berlin -98 <jberlin@cc.hut.fi>
5 //
6
7
8 typedef char byte;
9 typedef unsigned char u8;
10 typedef unsigned short int u16;
11 typedef unsigned short word;
12 typedef unsigned long dword;
13
14 u8 io_in8(u16 port)
15 {
16 #if 0
17 u8 data;
18
19 // in $0x92, %al
20 asm("inb $0x92, %0"
21 : "=a"(data)
22 : );
23 #endif
24
25
26 // ref: http://wiki.osdev.org/Inline_Assembly/Examples
27 u8 ret;
28 asm volatile( "inb %1, %0"
29 : "=a"(ret) : "Nd"(port) );
30 return ret;
31 }
32
33 #if 0
34 // ref: http://wiki.osdev.org/Inline_Assembly/Examples
35 static inline
36 void outb( unsigned short port, unsigned char val )
37 {
38 asm volatile( "outb %0, %1"
39 : : "a"(val), "Nd"(port) );
40 }
41 #endif
42
43 void io_out8(u16 port, u8 data)
44 {
45 // outb %al, $0x92
46 // N: "N" : Constant in range 0 to 255 (for out instruction).
47 // ref: http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#s6
48 asm volatile("outb %0, %1"
49 : : "a"(data), "Nd"(port) );
50 }
51
52 void io_out16(u16 port, u16 data)
53 {
54 asm volatile("outw %0, %1"
55 : : "a"(data), "Nd"(port) );
56 }
57
58 #define SZ(x) (sizeof(x)/sizeof(x[0]))
59
60
61 // misc out (3c2h) value for various modes
62
63 #define R_COM 0x63 // "common" bits
64
65 #define R_W256 0x00
66 #define R_W320 0x00
67 #define R_W360 0x04
68 #define R_W376 0x04
69 #define R_W400 0x04
70
71 #define R_H200 0x00
72 #define R_H224 0x80
73 #define R_H240 0x80
74 #define R_H256 0x80
75 #define R_H270 0x80
76 #define R_H300 0x80
77 #define R_H360 0x00
78 #define R_H400 0x00
79 #define R_H480 0x80
80 #define R_H564 0x80
81 #define R_H600 0x80
82
83
84 static const byte hor_regs [] = { 0x0, 0x1, 0x2, 0x3, 0x4,
85 0x5, 0x13 };
86
87 static const byte width_256[] = { 0x5f, 0x3f, 0x40, 0x82, 0x4a,
88 0x9a, 0x20 };
89 static const byte width_320[] = { 0x5f, 0x4f, 0x50, 0x82, 0x54,
90 0x80, 0x28 };
91 static const byte width_360[] = { 0x6b, 0x59, 0x5a, 0x8e, 0x5e,
92 0x8a, 0x2d };
93 static const byte width_376[] = { 0x6e, 0x5d, 0x5e, 0x91, 0x62,
94 0x8f, 0x2f };
95 static const byte width_400[] = { 0x70, 0x63, 0x64, 0x92, 0x65,
96 0x82, 0x32 };
97
98 static const byte ver_regs [] = { 0x6, 0x7, 0x9, 0x10, 0x11,
99 0x12, 0x15, 0x16 };
100
101 static const byte height_200[] = { 0xbf, 0x1f, 0x41, 0x9c, 0x8e,
102 0x8f, 0x96, 0xb9 };
103 static const byte height_224[] = { 0x0b, 0x3e, 0x41, 0xda, 0x9c,
104 0xbf, 0xc7, 0x04 };
105 static const byte height_240[] = { 0x0d, 0x3e, 0x41, 0xea, 0xac,
106 0xdf, 0xe7, 0x06 };
107 static const byte height_256[] = { 0x23, 0xb2, 0x61, 0x0a, 0xac,
108 0xff, 0x07, 0x1a };
109 static const byte height_270[] = { 0x30, 0xf0, 0x61, 0x20, 0xa9,
110 0x1b, 0x1f, 0x2f };
111 static const byte height_300[] = { 0x70, 0xf0, 0x61, 0x5b, 0x8c,
112 0x57, 0x58, 0x70 };
113 static const byte height_360[] = { 0xbf, 0x1f, 0x40, 0x88, 0x85,
114 0x67, 0x6d, 0xba };
115 static const byte height_400[] = { 0xbf, 0x1f, 0x40, 0x9c, 0x8e,
116 0x8f, 0x96, 0xb9 };
117 static const byte height_480[] = { 0x0d, 0x3e, 0x40, 0xea, 0xac,
118 0xdf, 0xe7, 0x06 };
119 static const byte height_564[] = { 0x62, 0xf0, 0x60, 0x37, 0x89,
120 0x33, 0x3c, 0x5c };
121 static const byte height_600[] = { 0x70, 0xf0, 0x60, 0x5b, 0x8c,
122 0x57, 0x58, 0x70 };
123
124 // the chain4 parameter should be 1 for normal 13h-type mode, but
125 // only allows 320x200 256x200, 256x240 and 256x256 because you
126 // can only access the first 64kb
127
128 // if chain4 is 0, then plane mode is used (tweaked modes), and
129 // you'll need to switch planes to access the whole screen but
130 // that allows you using any resolution, up to 400x600
131
132 int init_graph_vga(int width, int height,int chain4)
133 // returns 1=ok, 0=fail
134 {
135 const byte *w,*h;
136 byte val;
137 int a;
138
139 #if 1
140 width=320;
141 height=200;
142 chain4=1;
143 #endif
144
145 switch(width) {
146 case 256: w=width_256; val=R_COM+R_W256; break;
147 case 320: w=width_320; val=R_COM+R_W320; break;
148 case 360: w=width_360; val=R_COM+R_W360; break;
149 case 376: w=width_376; val=R_COM+R_W376; break;
150 case 400: w=width_400; val=R_COM+R_W400; break;
151 default: return 0; // fail
152 }
153 switch(height) {
154 case 200: h=height_200; val|=R_H200; break;
155 case 224: h=height_224; val|=R_H224; break;
156 case 240: h=height_240; val|=R_H240; break;
157 case 256: h=height_256; val|=R_H256; break;
158 case 270: h=height_270; val|=R_H270; break;
159 case 300: h=height_300; val|=R_H300; break;
160 case 360: h=height_360; val|=R_H360; break;
161 case 400: h=height_400; val|=R_H400; break;
162 case 480: h=height_480; val|=R_H480; break;
163 case 564: h=height_564; val|=R_H564; break;
164 case 600: h=height_600; val|=R_H600; break;
165 default: return 0; // fail
166 }
167
168 // chain4 not available if mode takes over 64k
169
170 if(chain4 && (long)width*(long)height>65536L) return 0;
171
172 // here goes the actual modeswitch
173
174 io_out8(0x3c2,val);
175 io_out16(0x3d4,0x0e11); // enable regs 0-7
176
177 for(a=0;a<SZ(hor_regs);++a)
178 io_out16(0x3d4,(word)((w[a]<<8)+hor_regs[a]));
179 for(a=0;a<SZ(ver_regs);++a)
180 io_out16(0x3d4,(word)((h[a]<<8)+ver_regs[a]));
181
182 io_out16(0x3d4,0x0008); // vert.panning = 0
183
184 if(chain4) {
185 io_out16(0x3d4,0x4014);
186 io_out16(0x3d4,0xa317);
187 io_out16(0x3c4,0x0e04);
188 } else {
189 io_out16(0x3d4,0x0014);
190 io_out16(0x3d4,0xe317);
191 io_out16(0x3c4,0x0604);
192 }
193
194 io_out16(0x3c4,0x0101);
195 io_out16(0x3c4,0x0f02); // enable writing to all planes
196 io_out16(0x3ce,0x4005); // 256color mode
197 io_out16(0x3ce,0x0506); // graph mode & A000-AFFF
198
199 io_in8(0x3da);
200 io_out8(0x3c0,0x30); io_out8(0x3c0,0x41);
201 io_out8(0x3c0,0x33); io_out8(0x3c0,0x00);
202
203 for(a=0;a<16;a++) { // ega pal
204 io_out8(0x3c0,(byte)a);
205 io_out8(0x3c0,(byte)a);
206 }
207
208 io_out8(0x3c0, 0x20); // enable video
209
210 return 1;
211 }
212
213
214 // ref: 30 天打造 OS, projects/04_day sample code
215 void init_palette(void)
216 {
217 void set_palette(int start, int end, unsigned char *rgb);
218
219 static unsigned char table_rgb[16 * 3] = {
220 0x00, 0x00, 0x00, /* 0:• */
221 0xff, 0x00, 0x00, /* 1:–¾‚é‚¢Ô */
222 0x00, 0xff, 0x00, /* 2:–¾‚é‚¢—Î */
223 0xff, 0xff, 0x00, /* 3:–¾‚é‚¢‰©F */
224 0x00, 0x00, 0xff, /* 4:–¾‚é‚¢Â */
225 0xff, 0x00, 0xff, /* 5:–¾‚é‚¢Ž‡ */
226 0x00, 0xff, 0xff, /* 6:–¾‚é‚¢…F */
227 0xff, 0xff, 0xff, /* 7:”’ */
228 0xc6, 0xc6, 0xc6, /* 8:–¾‚é‚¢ŠDF */
229 0x84, 0x00, 0x00, /* 9:ˆÃ‚¢Ô */
230 0x00, 0x84, 0x00, /* 10:ˆÃ‚¢—Î */
231 0x84, 0x84, 0x00, /* 11:ˆÃ‚¢‰©F */
232 0x00, 0x00, 0x84, /* 12:ˆÃ‚¢Â */
233 0x84, 0x00, 0x84, /* 13:ˆÃ‚¢Ž‡ */
234 0x00, 0x84, 0x84, /* 14:ˆÃ‚¢…F */
235 0x84, 0x84, 0x84 /* 15:ˆÃ‚¢ŠDF */
236 };
237 set_palette(0, 15, table_rgb);
238 return;
239
240 /* static char –½—߂́Aƒf[ƒ^‚É‚µ‚©Žg‚¦‚È‚¢‚¯‚ÇDB–½—ß‘Š“– */
241 }
242
243 void set_palette(int start, int end, unsigned char *rgb)
244 {
245 int i, eflags;
246 //eflags = io_load_eflags(); /* Š„‚荞‚Ý‹–‰Âƒtƒ‰ƒO‚Ì’l‚ð‹L˜^‚·‚é */
247 //io_cli(); /* ‹–‰Âƒtƒ‰ƒO‚ð0‚É‚µ‚ÄŠ„‚荞‚Ý‹ÖŽ~‚É‚·‚é */
248 io_out8(0x03c8, start);
249 for (i = start; i <= end; i++) {
250 io_out8(0x03c9, rgb[0] / 4);
251 io_out8(0x03c9, rgb[1] / 4);
252 io_out8(0x03c9, rgb[2] / 4);
253 rgb += 3;
254 }
255 //io_store_eflags(eflags); /* Š„‚荞‚Ý‹–‰Âƒtƒ‰ƒO‚ðŒ³‚É–ß‚· */
256 return;
257 }
258
259
260 /*
261 * Hope you get what you want. To put on normal mode 13h, use
262 * init_graph_vga(320,200,1);
263 */

264 #if 0
265 int main(int argc, char **argv)
266 {
267 init_graph_vga(320,200,1);
268 }
269 #endif
270 int vga_test()
271 {
272 int i=0;
273 void write_mem8(int addr, u8 data);
274
275 init_graph_vga(300, 200, 1);
276 for (i=0xa0000; i <= 0xaffff; ++i)
277 {
278 write_mem8(i, 15);
279 }
280
281
282 }

 ↓ 程式執行前


↓ 320X200X256 色, write_mem8(i, 15); 白色畫面



↓ 320X200X256 色, write_mem8(i, 5); 紫色畫面
From write_os

↓ 回到文字模式


ref:

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。