Load wallpaper from disk

This commit is contained in:
Juhani Krekelä 2023-03-11 17:49:55 +02:00
parent 465f6ebf22
commit ff1b91f3dd
5 changed files with 247 additions and 11 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
*.bin
*.img

View File

@ -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

View File

@ -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
View 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
View File

@ -0,0 +1,25 @@
ANSI art is my
passion
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