Skip to content

Commit 7dcf8d2

Browse files
committed
Add example of switching to 256 color VGA mode
1 parent b923391 commit 7dcf8d2

6 files changed

Lines changed: 456 additions & 1 deletion

File tree

examples/256_color_vga/Makefile

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#################################################
2+
# IncludeOS SERVICE makefile #
3+
#################################################
4+
5+
# The name of your service
6+
SERVICE = 256_Color_VGA
7+
SERVICE_NAME = 256 Color VGA
8+
9+
# Your service parts
10+
FILES = service.cpp
11+
ASM_FILES = int32.asm
12+
13+
# Your disk image
14+
DISK=
15+
16+
DRIVERS=
17+
18+
# Your own include-path
19+
LOCAL_INCLUDES=
20+
21+
# IncludeOS location
22+
ifndef INCLUDEOS_INSTALL
23+
INCLUDEOS_INSTALL=$(HOME)/IncludeOS_install
24+
endif
25+
26+
# Include the installed seed makefile
27+
include $(INCLUDEOS_INSTALL)/Makeseed

examples/256_color_vga/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
### Snake game
2+
3+
Using VGA text-mode in qemu (or possibly VirtualBox) we can play snake!
4+
5+
```
6+
make
7+
./run.sh
8+
```
9+
10+
Use arrow keys to change the snakes direction. Press spacebar to restart the game.

examples/256_color_vga/int32.asm

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
;
2+
; Protected Mode BIOS Call Functionailty v2.0 - by Napalm
3+
; -------------------------------------------------------
4+
;
5+
; This is code shows how its POSSIBLE to execute BIOS interrupts
6+
; by switch out to real-mode and then back into protected mode.
7+
;
8+
; If you wish to use all or part of this code you must agree
9+
; to the license at the following URL.
10+
;
11+
; License: http://creativecommons.org/licenses/by-sa/2.0/uk/
12+
;
13+
; Notes: This file is in NASM syntax.
14+
; Turn off paging before calling these functions.
15+
; int32() resets all selectors.
16+
;
17+
; C Prototype:
18+
; void _cdelc int32(unsigned char intnum, regs16_t *regs);
19+
;
20+
; Example of usage:
21+
; regs.ax = 0x0013;
22+
; int32(0x10, &regs);
23+
; memset((char *)0xA0000, 1, (320*200));
24+
; memset((char *)0xA0000 + (100*320+80), 14, 80);
25+
; regs.ax = 0x0000;
26+
; int32(0x16, &regs);
27+
; regs.ax = 0x0003;
28+
; int32(0x10, &regs);
29+
;
30+
;
31+
[bits 32]
32+
33+
global int32, _int32
34+
35+
struc regs16_t
36+
.di resw 1
37+
.si resw 1
38+
.bp resw 1
39+
.sp resw 1
40+
.bx resw 1
41+
.dx resw 1
42+
.cx resw 1
43+
.ax resw 1
44+
.gs resw 1
45+
.fs resw 1
46+
.es resw 1
47+
.ds resw 1
48+
.ef resw 1
49+
endstruc
50+
51+
%define INT32_BASE 0x7C00
52+
%define REBASE(x) (((x) - reloc) + INT32_BASE)
53+
%define GDTENTRY(x) ((x) << 3)
54+
%define CODE32 GDTENTRY(1) ; 0x08
55+
%define DATA32 GDTENTRY(2) ; 0x10
56+
%define CODE16 GDTENTRY(3) ; 0x18
57+
%define DATA16 GDTENTRY(4) ; 0x20
58+
%define STACK16 (INT32_BASE - regs16_t_size)
59+
60+
61+
section .text
62+
int32: use32 ; by Napalm
63+
_int32:
64+
cli ; disable interrupts
65+
pusha ; save register state to 32bit stack
66+
mov esi, reloc ; set source to code below
67+
mov edi, INT32_BASE ; set destination to new base address
68+
mov ecx, (int32_end - reloc) ; set copy size to our codes size
69+
cld ; clear direction flag (so we copy forward)
70+
rep movsb ; do the actual copy (relocate code to low 16bit space)
71+
jmp INT32_BASE ; jump to new code location
72+
reloc: use32 ; by Napalm
73+
mov [REBASE(stack32_ptr)], esp ; save 32bit stack pointer
74+
sidt [REBASE(idt32_ptr)] ; save 32bit idt pointer
75+
sgdt [REBASE(gdt32_ptr)] ; save 32bit gdt pointer
76+
lgdt [REBASE(gdt16_ptr)] ; load 16bit gdt pointer
77+
lea esi, [esp+0x24] ; set position of intnum on 32bit stack
78+
lodsd ; read intnum into eax
79+
mov [REBASE(ib)], al ; set intrrupt immediate byte from our arguments
80+
mov esi, [esi] ; read regs pointer in esi as source
81+
mov edi, STACK16 ; set destination to 16bit stack
82+
mov ecx, regs16_t_size ; set copy size to our struct size
83+
mov esp, edi ; save destination to as 16bit stack offset
84+
rep movsb ; do the actual copy (32bit stack to 16bit stack)
85+
jmp word CODE16:REBASE(p_mode16) ; switch to 16bit selector (16bit protected mode)
86+
p_mode16: use16
87+
mov ax, DATA16 ; get our 16bit data selector
88+
mov ds, ax ; set ds to 16bit selector
89+
mov es, ax ; set es to 16bit selector
90+
mov fs, ax ; set fs to 16bit selector
91+
mov gs, ax ; set gs to 16bit selector
92+
mov ss, ax ; set ss to 16bit selector
93+
mov eax, cr0 ; get cr0 so we can modify it
94+
and al, ~0x01 ; mask off PE bit to turn off protected mode
95+
mov cr0, eax ; set cr0 to result
96+
jmp word 0x0000:REBASE(r_mode16) ; finally set cs:ip to enter real-mode
97+
r_mode16: use16
98+
xor ax, ax ; set ax to zero
99+
mov ds, ax ; set ds so we can access idt16
100+
mov ss, ax ; set ss so they the stack is valid
101+
lidt [REBASE(idt16_ptr)] ; load 16bit idt
102+
mov bx, 0x0870 ; master 8 and slave 112
103+
call resetpic ; set pic's the to real-mode settings
104+
popa ; load general purpose registers from 16bit stack
105+
pop gs ; load gs from 16bit stack
106+
pop fs ; load fs from 16bit stack
107+
pop es ; load es from 16bit stack
108+
pop ds ; load ds from 16bit stack
109+
sti ; enable interrupts
110+
db 0xCD ; opcode of INT instruction with immediate byte
111+
ib: db 0x00
112+
cli ; disable interrupts
113+
xor sp, sp ; zero sp so we can reuse it
114+
mov ss, sp ; set ss so the stack is valid
115+
mov sp, INT32_BASE ; set correct stack position so we can copy back
116+
pushf ; save eflags to 16bit stack
117+
push ds ; save ds to 16bit stack
118+
push es ; save es to 16bit stack
119+
push fs ; save fs to 16bit stack
120+
push gs ; save gs to 16bit stack
121+
pusha ; save general purpose registers to 16bit stack
122+
mov bx, 0x2028 ; master 32 and slave 40
123+
call resetpic ; restore the pic's to protected mode settings
124+
mov eax, cr0 ; get cr0 so we can modify it
125+
inc eax ; set PE bit to turn on protected mode
126+
mov cr0, eax ; set cr0 to result
127+
jmp dword CODE32:REBASE(p_mode32) ; switch to 32bit selector (32bit protected mode)
128+
p_mode32: use32
129+
mov ax, DATA32 ; get our 32bit data selector
130+
mov ds, ax ; reset ds selector
131+
mov es, ax ; reset es selector
132+
mov fs, ax ; reset fs selector
133+
mov gs, ax ; reset gs selector
134+
mov ss, ax ; reset ss selector
135+
lgdt [REBASE(gdt32_ptr)] ; restore 32bit gdt pointer
136+
lidt [REBASE(idt32_ptr)] ; restore 32bit idt pointer
137+
mov esp, [REBASE(stack32_ptr)] ; restore 32bit stack pointer
138+
mov esi, STACK16 ; set copy source to 16bit stack
139+
lea edi, [esp+0x28] ; set position of regs pointer on 32bit stack
140+
mov edi, [edi] ; use regs pointer in edi as copy destination
141+
mov ecx, regs16_t_size ; set copy size to our struct size
142+
cld ; clear direction flag (so we copy forward)
143+
rep movsb ; do the actual copy (16bit stack to 32bit stack)
144+
popa ; restore registers
145+
sti ; enable interrupts
146+
ret ; return to caller
147+
148+
resetpic: ; reset's 8259 master and slave pic vectors
149+
push ax ; expects bh = master vector, bl = slave vector
150+
mov al, 0x11 ; 0x11 = ICW1_INIT | ICW1_ICW4
151+
out 0x20, al ; send ICW1 to master pic
152+
out 0xA0, al ; send ICW1 to slave pic
153+
mov al, bh ; get master pic vector param
154+
out 0x21, al ; send ICW2 aka vector to master pic
155+
mov al, bl ; get slave pic vector param
156+
out 0xA1, al ; send ICW2 aka vector to slave pic
157+
mov al, 0x04 ; 0x04 = set slave to IRQ2
158+
out 0x21, al ; send ICW3 to master pic
159+
shr al, 1 ; 0x02 = tell slave its on IRQ2 of master
160+
out 0xA1, al ; send ICW3 to slave pic
161+
shr al, 1 ; 0x01 = ICW4_8086
162+
out 0x21, al ; send ICW4 to master pic
163+
out 0xA1, al ; send ICW4 to slave pic
164+
pop ax ; restore ax from stack
165+
ret ; return to caller
166+
167+
stack32_ptr: ; address in 32bit stack after we
168+
dd 0x00000000 ; save all general purpose registers
169+
170+
idt32_ptr: ; IDT table pointer for 32bit access
171+
dw 0x0000 ; table limit (size)
172+
dd 0x00000000 ; table base address
173+
174+
gdt32_ptr: ; GDT table pointer for 32bit access
175+
dw 0x0000 ; table limit (size)
176+
dd 0x00000000 ; table base address
177+
178+
idt16_ptr: ; IDT table pointer for 16bit access
179+
dw 0x03FF ; table limit (size)
180+
dd 0x00000000 ; table base address
181+
182+
gdt16_base: ; GDT descriptor table
183+
.null: ; 0x00 - null segment descriptor
184+
dd 0x00000000 ; must be left zero'd
185+
dd 0x00000000 ; must be left zero'd
186+
187+
.code32: ; 0x01 - 32bit code segment descriptor 0xFFFFFFFF
188+
dw 0xFFFF ; limit 0:15
189+
dw 0x0000 ; base 0:15
190+
db 0x00 ; base 16:23
191+
db 0x9A ; present, iopl/0, code, execute/read
192+
db 0xCF ; 4Kbyte granularity, 32bit selector; limit 16:19
193+
db 0x00 ; base 24:31
194+
195+
.data32: ; 0x02 - 32bit data segment descriptor 0xFFFFFFFF
196+
dw 0xFFFF ; limit 0:15
197+
dw 0x0000 ; base 0:15
198+
db 0x00 ; base 16:23
199+
db 0x92 ; present, iopl/0, data, read/write
200+
db 0xCF ; 4Kbyte granularity, 32bit selector; limit 16:19
201+
db 0x00 ; base 24:31
202+
203+
.code16: ; 0x03 - 16bit code segment descriptor 0x000FFFFF
204+
dw 0xFFFF ; limit 0:15
205+
dw 0x0000 ; base 0:15
206+
db 0x00 ; base 16:23
207+
db 0x9A ; present, iopl/0, code, execute/read
208+
db 0x0F ; 1Byte granularity, 16bit selector; limit 16:19
209+
db 0x00 ; base 24:31
210+
211+
.data16: ; 0x04 - 16bit data segment descriptor 0x000FFFFF
212+
dw 0xFFFF ; limit 0:15
213+
dw 0x0000 ; base 0:15
214+
db 0x00 ; base 16:23
215+
db 0x92 ; present, iopl/0, data, read/write
216+
db 0x0F ; 1Byte granularity, 16bit selector; limit 16:19
217+
db 0x00 ; base 24:31
218+
219+
gdt16_ptr: ; GDT table pointer for 16bit access
220+
dw gdt16_ptr - gdt16_base - 1 ; table limit (size)
221+
dd gdt16_base ; table base address
222+
223+
int32_end: ; end marker (so we can copy the code)
224+
225+

examples/256_color_vga/run.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#! /bin/bash
2+
export GRAPHICS="-vga std"
3+
source ${INCLUDEOS_HOME-$HOME/IncludeOS_install}/etc/run.sh `make servicefile`

0 commit comments

Comments
 (0)