Load wallpaper from disk
This commit is contained in:
parent
465f6ebf22
commit
ff1b91f3dd
5 changed files with 247 additions and 11 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
*.bin
|
||||
*.img
|
||||
|
|
20
Makefile
20
Makefile
|
@ -1,20 +1,28 @@
|
|||
NASM = nasm
|
||||
PYTHON = python3
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .bin .asm
|
||||
.SUFFIXES: .bin .asm .ansi
|
||||
|
||||
all: ponydos.bin
|
||||
all: ponydos.img
|
||||
|
||||
run: ponydos.bin
|
||||
qemu-system-i386 -fda ponydos.bin
|
||||
ponydos.img: ponydos.bin wallpaper.bin
|
||||
rw -i /dev/zero -o $@ -c 1440K
|
||||
rw -i ponydos.bin -o $@
|
||||
rw -i wallpaper.bin -o $@ -O 512
|
||||
|
||||
.asm.bin:
|
||||
$(NASM) -fbin -o $@ $<
|
||||
|
||||
.ansi.bin:
|
||||
$(PYTHON) process_wallpaper.py $< $@ 7 0 0 0
|
||||
|
||||
run: ponydos.img
|
||||
qemu-system-i386 -fda $<
|
||||
|
||||
clean:
|
||||
rm -f *.bin
|
||||
rm -f *.bin *.img
|
||||
|
||||
distclean: clean
|
||||
qemu-system
|
||||
|
||||
.PHONY: all run clean distclean
|
||||
|
|
130
ponydos.asm
130
ponydos.asm
|
@ -6,6 +6,8 @@ org 0x7c00
|
|||
COLUMNS equ 80
|
||||
ROWS equ 25
|
||||
|
||||
WALLPAPER equ 0x500
|
||||
|
||||
jmp 0:start
|
||||
start:
|
||||
cld
|
||||
|
@ -27,6 +29,8 @@ start:
|
|||
xor al, al
|
||||
rep stosb
|
||||
|
||||
mov [boot_disk], dl
|
||||
|
||||
initialize_mouse:
|
||||
; Initialize mouse
|
||||
; https://www.ctyme.com/intr/rb-1601.htm
|
||||
|
@ -60,21 +64,26 @@ initialize_mouse:
|
|||
|
||||
.done:
|
||||
|
||||
initialize_screen:
|
||||
mov ax, 0xb800 ; VGA text video memory
|
||||
mov es, ax
|
||||
|
||||
load_wallpaper:
|
||||
; Clear screen with asterisks and 15-0 background-foreground
|
||||
mov ax, 0xf000 + '*'
|
||||
mov cx, 25*80
|
||||
xor di, di
|
||||
mov di, WALLPAPER
|
||||
rep stosw
|
||||
|
||||
mov ax, 1
|
||||
mov bl, [boot_disk]
|
||||
mov cx, 8
|
||||
mov di, WALLPAPER
|
||||
call read_sectors
|
||||
|
||||
initialize_screen:
|
||||
; Disable text cursor
|
||||
mov ah, 0x01
|
||||
mov ch, 0x20
|
||||
int 0x10
|
||||
|
||||
call draw_wallpaper
|
||||
call flip_mouse_cursor
|
||||
|
||||
mainloop:
|
||||
|
@ -98,6 +107,30 @@ mainloop:
|
|||
call flip_mouse_cursor
|
||||
jmp mainloop
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; Drawing subroutines
|
||||
; ------------------------------------------------------------------
|
||||
|
||||
draw_wallpaper:
|
||||
push ax
|
||||
push bx
|
||||
push cx
|
||||
push es
|
||||
|
||||
mov bx, 0xb800
|
||||
mov es, bx
|
||||
|
||||
mov si, WALLPAPER
|
||||
xor di, di
|
||||
mov cx, 80*25
|
||||
rep movsw
|
||||
|
||||
pop es
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
ret
|
||||
|
||||
flip_mouse_cursor:
|
||||
push ax
|
||||
push bx
|
||||
|
@ -131,6 +164,75 @@ flip_mouse_cursor:
|
|||
pop ax
|
||||
ret
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; Disk subroutines
|
||||
; ------------------------------------------------------------------
|
||||
|
||||
; in:
|
||||
; ax = LBA of first sector
|
||||
; bl = drive number
|
||||
; cx = number of sectors to read (must be at least 1)
|
||||
; es:di = output buffer
|
||||
read_sectors:
|
||||
push ax
|
||||
push cx
|
||||
push di
|
||||
|
||||
.loop:
|
||||
call read_sector
|
||||
inc ax
|
||||
add di, 512
|
||||
loop .loop
|
||||
|
||||
pop di
|
||||
pop cx
|
||||
pop ax
|
||||
ret
|
||||
|
||||
; in:
|
||||
; ax = LBA of first sector
|
||||
; bl = drive number
|
||||
; es:di = output buffer
|
||||
read_sector:
|
||||
push ax
|
||||
push bx
|
||||
push cx
|
||||
push dx
|
||||
|
||||
mov cx, 18
|
||||
div cx
|
||||
|
||||
; cl = sector (1…18)
|
||||
mov cl, dl
|
||||
inc cl
|
||||
|
||||
; dh = head (0…1)
|
||||
mov dh, 1
|
||||
and dh, al
|
||||
|
||||
; ch = cylinder
|
||||
shr ax, 1
|
||||
mov ch, al
|
||||
|
||||
; dl = drive number
|
||||
mov dl, bl
|
||||
|
||||
; es:bx = output buffer
|
||||
mov bx, di
|
||||
|
||||
mov ax, 0x0201 ; read one sector
|
||||
int 0x13
|
||||
|
||||
pop dx
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
ret
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; Mouse callback
|
||||
; ------------------------------------------------------------------
|
||||
|
||||
Y_OVERFLOW equ 0x80
|
||||
X_OVERFLOW equ 0x40
|
||||
Y_NEGATIVE equ 0x20
|
||||
|
@ -205,6 +307,10 @@ mouse_handler:
|
|||
pop ax
|
||||
retf
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; Debug routines
|
||||
; ------------------------------------------------------------------
|
||||
|
||||
hexprint16:
|
||||
xchg ah, al
|
||||
call hexprint8
|
||||
|
@ -234,10 +340,22 @@ hexprint4:
|
|||
pop ax
|
||||
ret
|
||||
|
||||
hang:
|
||||
hlt
|
||||
jmp hang
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; Padding and boot sector signature
|
||||
; ------------------------------------------------------------------
|
||||
|
||||
times 510-($-$$) db 0
|
||||
db 0x55
|
||||
db 0xaa
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; Zero-initialized variables
|
||||
; ------------------------------------------------------------------
|
||||
|
||||
section .bss
|
||||
_bss_start:
|
||||
|
||||
|
@ -248,4 +366,6 @@ mouse_buttons resb 1
|
|||
mouse_column resb 1
|
||||
mouse_row resw 1
|
||||
|
||||
boot_disk resb 1
|
||||
|
||||
_bss_end:
|
||||
|
|
82
process_wallpaper.py
Normal file
82
process_wallpaper.py
Normal file
|
@ -0,0 +1,82 @@
|
|||
import sys
|
||||
|
||||
WIDTH = 80
|
||||
HEIGHT = 25
|
||||
# ANSI orders the colours black, red, green, yellow, blue, magenta, cyan, white
|
||||
# VGA orders them black, blue, green, cyan, red, magenta, yellow, white
|
||||
color_map = [0, 4, 2, 6, 1, 5, 3, 7]
|
||||
|
||||
if len(sys.argv) != 7:
|
||||
print("Usage: {sys.argv[0]} infile outfile default_fgcolor default_bgcolor origin_x origin_y", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
infile = sys.argv[1]
|
||||
outfile = sys.argv[2]
|
||||
|
||||
default_fgcolor = int(sys.argv[3])
|
||||
assert 0 <= default_fgcolor <= 15
|
||||
default_bgcolor = int(sys.argv[4])
|
||||
assert 0 <= default_bgcolor <= 15
|
||||
|
||||
origin_x = int(sys.argv[5])
|
||||
assert 0 <= origin_x < WIDTH
|
||||
origin_y = int(sys.argv[6])
|
||||
assert 0 <= origin_y < HEIGHT
|
||||
|
||||
chars = [bytearray([0]*HEIGHT) for _ in range(WIDTH)]
|
||||
attributes = [[(default_fgcolor, default_bgcolor)]*HEIGHT for _ in range(WIDTH)]
|
||||
|
||||
with open(infile, 'rb') as f:
|
||||
ansitext = f.read()
|
||||
|
||||
x = origin_x
|
||||
y = origin_y
|
||||
fgcolor = default_fgcolor
|
||||
bgcolor = default_bgcolor
|
||||
|
||||
line = 1
|
||||
line_start = 0
|
||||
index = 0
|
||||
while index < len(ansitext):
|
||||
if ansitext[index:].startswith(b'\x1b['):
|
||||
index += len(b'\x1b[')
|
||||
escape_length = ansitext[index:].index(b'm')
|
||||
escape = ansitext[index:index+escape_length]
|
||||
for color_parameter in escape.split(b';'):
|
||||
color_parameter = int(color_parameter)
|
||||
if color_parameter == 39:
|
||||
fgcolor = default_fgcolor
|
||||
elif color_parameter == 49:
|
||||
bgcolor = default_bgcolor
|
||||
elif 30 <= color_parameter <= 37:
|
||||
fgcolor = color_map[color_parameter - 30]
|
||||
elif 40 <= color_parameter <= 47:
|
||||
bgcolor = color_map[color_parameter - 40]
|
||||
elif 90 <= color_parameter <= 97:
|
||||
fgcolor = color_map[color_parameter - 90] + 8
|
||||
elif 100 <= color_parameter <= 107:
|
||||
bgcolor = color_map[color_parameter - 100] + 8
|
||||
else:
|
||||
print(f'{line},{index-line_start+1}: Unknown colour escape {color_parameter}')
|
||||
index += escape_length + len(b'm')
|
||||
elif ansitext[index] == 13:
|
||||
x = origin_x
|
||||
index += 1
|
||||
elif ansitext[index] == 10:
|
||||
x = origin_x
|
||||
y += 1
|
||||
index += 1
|
||||
line += 1
|
||||
line_start = index
|
||||
else:
|
||||
chars[x][y] = ansitext[index]
|
||||
attributes[x][y] = (fgcolor, bgcolor)
|
||||
index += 1
|
||||
x += 1
|
||||
|
||||
with open(outfile, 'wb') as f:
|
||||
for y in range(HEIGHT):
|
||||
for x in range(WIDTH):
|
||||
fgcolor, bgcolor = attributes[x][y]
|
||||
char = chars[x][y]
|
||||
f.write(bytes([char, (bgcolor<<4) | fgcolor]))
|
25
wallpaper.ansi
Normal file
25
wallpaper.ansi
Normal file
|
@ -0,0 +1,25 @@
|
|||
ANSI art is my
|
||||
[91mp[92ma[93ms[94ms[95mi[96mo[97mn
|
||||
line 3
|
||||
line 4
|
||||
line 5
|
||||
line 6
|
||||
line 7
|
||||
line 8
|
||||
line 9
|
||||
line 10
|
||||
line 11
|
||||
line 12
|
||||
line 13
|
||||
line 14
|
||||
line 15
|
||||
line 16
|
||||
line 17
|
||||
line 18
|
||||
line 19
|
||||
line 20
|
||||
line 21
|
||||
line 22
|
||||
line 23
|
||||
line 24
|
||||
line 25
|
Loading…
Reference in a new issue