Add option for 8-colour mode

Some BIOSs initialize the VGA card by default into a mode where the high
bit of background nybble signals that the cell should blink. The simple
way to avoid this is by restricting the background colours to the range
0…7. However, since our mouse cursor is implemented by swapping the
foreground and the background colours, we also need to restrict the
foreground colours to the range 0…7.
This commit is contained in:
Juhani Krekelä 2023-05-11 21:25:50 +03:00
parent a496c5ce9d
commit d4c15687c8
7 changed files with 138 additions and 64 deletions

View File

@ -2,6 +2,8 @@ NASM = nasm
PYTHON = python3
QEMU = qemu-system-i386
BUILDOPTS =
.SUFFIXES:
.SUFFIXES: .bin .asm .ans .wall
@ -26,10 +28,10 @@ viewer.bin: ponydos.inc
memory.bin: ponydos.inc
.asm.bin:
$(NASM) -fbin -o $@ $<
$(NASM) -fbin $(BUILDOPTS) -o $@ $<
.ans.wall:
$(PYTHON) process_wallpaper.py $@ $< 7 0 0 0
env BUILDOPTS='$(BUILDOPTS)' $(PYTHON) process_wallpaper.py $@ $< 7 0 0 0
run: ponydos.img
$(QEMU) -drive file=$<,index=0,if=floppy,format=raw

View File

@ -20,6 +20,16 @@ run `make`. `make run` runs the floppy disk image `ponydos.img` with QEMU.
By default, `qemu-system-i386` is invoked. If you want to use a different
backend, use `make QEMU=<backend> run`.
### Build options
You can configure the build using build options passed to the build system using
the `BUILDOPTS` variable, e.g. `make BUILDOPTS='-DBLINKY'`. It is advised to run
`make clean` before changing the value of `BUILDOPTS`.
* `-DBLINKY` builds an image which restricts the number of colours to 8. This is
for compatibility with BIOSs which use the highest bit of background colour to
signal that a cell should blink.
### How do I contribute?
There is a model `hello.asm` file to demonstrate how best to use the
@ -70,3 +80,7 @@ You don't.
At the moment, PonyDOS is only offered as a live floppy disk image with no
installation option, for your safety.
#### How do I stop my entire desktop from blinking?
Build with the [build option](#build-options) `-DBLINKY`.

View File

@ -2,6 +2,14 @@
cpu 8086
bits 16
%ifdef BLINKY
TITLEBAR_ATTRIBUTE equ 0x07
WINDOW_ATTRIBUTE equ 0x70
%else
TITLEBAR_ATTRIBUTE equ 0x0f
WINDOW_ATTRIBUTE equ 0xf0
%endif
WINDOW_STATUS_NORMAL equ 0
WINDOW_STATUS_MOVE equ 1
WINDOW_STATUS_RESIZE equ 2
@ -498,12 +506,12 @@ render_window:
mov cx, [window_height]
mul cx
mov cx, ax
mov ax, 0xf000 ; Attribute is in the high byte
mov ax, WINDOW_ATTRIBUTE<<8 ; Attribute is in the high byte
rep stosw
; Set title bar to be white-on-black
mov di, window_data
mov ax, 0x0f00
mov ax, TITLEBAR_ATTRIBUTE<<8
mov cx, [window_width]
rep stosw

View File

@ -2,6 +2,14 @@
cpu 8086
bits 16
%ifdef BLINKY
TITLEBAR_ATTRIBUTE equ 0x07
WINDOW_ATTRIBUTE equ 0x70
%else
TITLEBAR_ATTRIBUTE equ 0x0f
WINDOW_ATTRIBUTE equ 0xf0
%endif
WINDOW_STATUS_NORMAL equ 0
WINDOW_STATUS_MOVE equ 1
@ -572,9 +580,9 @@ window_status db WINDOW_STATUS_NORMAL
window_move_x_offset dw 0
window_data:
db 'U', 0x0f, 's', 0x0f, 'a', 0x0f, 'g', 0x0f, 'e', 0x0f
times 10-5-1 db 0x00, 0x0f
db 'x', 0x0f
db '0', 0xf0, '1', 0xf0, '2', 0xf0, '3', 0xf0, '4', 0xf0, '5'
db 0xf0, '6', 0xf0, '7', 0xf0, '8', 0xf0, '9', 0xf0
.indicators: times 10 db 0x00, 0xf0
db 'U', TITLEBAR_ATTRIBUTE, 's', TITLEBAR_ATTRIBUTE, 'a', TITLEBAR_ATTRIBUTE, 'g', TITLEBAR_ATTRIBUTE, 'e', TITLEBAR_ATTRIBUTE
times 10-5-1 db 0x00, TITLEBAR_ATTRIBUTE
db 'x', TITLEBAR_ATTRIBUTE
db '0', WINDOW_ATTRIBUTE, '1', WINDOW_ATTRIBUTE, '2', WINDOW_ATTRIBUTE, '3', WINDOW_ATTRIBUTE, '4', WINDOW_ATTRIBUTE, '5'
db WINDOW_ATTRIBUTE, '6', WINDOW_ATTRIBUTE, '7', WINDOW_ATTRIBUTE, '8', WINDOW_ATTRIBUTE, '9', WINDOW_ATTRIBUTE
.indicators: times 10 db 0x00, WINDOW_ATTRIBUTE

View File

@ -1,3 +1,4 @@
import os
import sys
from collections import namedtuple
@ -14,6 +15,15 @@ if len(sys.argv) != 7:
print("Usage: {sys.argv[0]} outfile infile default_fgcolor default_bgcolor origin_x origin_y", file=sys.stderr)
sys.exit(1)
blinky_vgamode = False
if 'BUILDOPTS' in os.environ:
for opt in os.environ['BUILDOPTS'].split():
if opt == '-DBLINKY':
blinky_vgamode = True
else:
print(f"Error: Unrecognized build option {opt}", file=sys.stderr)
sys.exit(1)
outfile = sys.argv[1]
infile = sys.argv[2]
@ -118,5 +128,14 @@ with open(outfile, 'wb') as f:
for y in range(HEIGHT):
for x in range(WIDTH):
fgcolor, bgcolor, bold = attributes[x][y]
fgcolor = fgcolor | (8 if bold else 0)
if blinky_vgamode:
# VGA mode can be set up so that the highest
# bit of the bg colour marks that the cell
# should blink instead of intensity
# Restrict the colours (including foreground
# to account for swapping of the two) to 0…7
fgcolor = fgcolor & 0x7
bgcolor = bgcolor & 0x7
char = chars[x][y]
f.write(bytes([char, (bgcolor<<4) | fgcolor | (8 if bold else 0)]))
f.write(bytes([char, (bgcolor<<4) | fgcolor]))

View File

@ -1,4 +1,16 @@
%include "ponydos.inc"
cpu 8086
bits 16
%ifdef BLINKY
TITLEBAR_ATTRIBUTE equ 0x07
WINDOW_ATTRIBUTE equ 0x70
DISK_ATTRIBUTE equ 0x07
%else
TITLEBAR_ATTRIBUTE equ 0x0f
WINDOW_ATTRIBUTE equ 0xf0
DISK_ATTRIBUTE equ 0x0f
%endif
struc window
.next resw 1
@ -637,7 +649,7 @@ launch:
show_launch_error:
mov di, launch_error_dialog.filename
mov cx, FS_DIRENT_NAME_SIZE-1
mov ah, 0xf0
mov ah, WINDOW_ATTRIBUTE
.copy:
lodsb
test al, al
@ -937,11 +949,11 @@ render_file_window:
mov es, ax
mov di, [si + window.data]
mov cx, [si + window.width]
mov ax, 0x0f00
mov ax, TITLEBAR_ATTRIBUTE<<8
rep stosw
mov cx, (ROWS-1)*COLUMNS
mov ax, 0xf000
mov ax, WINDOW_ATTRIBUTE<<8
rep stosw
mov di, [si + window.data]
@ -1225,28 +1237,28 @@ viewer_file_name db 'viewer.bin', 0
; ------------------------------------------------------------------
disk_icon:
db 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f
db 0x00, 0x0f, 0x00, 0x0f, 0x09, 0x0f, 0x00, 0x0f, 0x00, 0x0f
db 0x00, 0x0f, 0x00, 0x0f, '|', 0x0f, 0x00, 0x0f, 0x00, 0x0f
db 0x00, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE
db 0x00, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE, 0x09, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE
db 0x00, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE, '|', DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE, 0x00, DISK_ATTRIBUTE
oom_error_dialog:
db 'E', 0x0f, 'r', 0x0f, 'r', 0x0f, 'o', 0x0f, 'r', 0x0f
times 13-5-1 db 0x00, 0x0f
db 'x', 0x0f
db 'O', 0xf0, 'u', 0xf0, 't', 0xf0, ' ', 0xf0, 'o', 0xf0, 'f', 0xf0
db ' ', 0xf0, 'm', 0xf0, 'e', 0xf0, 'm', 0xf0, 'o', 0xf0, 'r', 0xf0
db 'y', 0xf0
db 'E', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE, 'o', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE
times 13-5-1 db 0x00, TITLEBAR_ATTRIBUTE
db 'x', TITLEBAR_ATTRIBUTE
db 'O', WINDOW_ATTRIBUTE, 'u', WINDOW_ATTRIBUTE, 't', WINDOW_ATTRIBUTE, ' ', WINDOW_ATTRIBUTE, 'o', WINDOW_ATTRIBUTE, 'f', WINDOW_ATTRIBUTE
db ' ', WINDOW_ATTRIBUTE, 'm', WINDOW_ATTRIBUTE, 'e', WINDOW_ATTRIBUTE, 'm', WINDOW_ATTRIBUTE, 'o', WINDOW_ATTRIBUTE, 'r', WINDOW_ATTRIBUTE
db 'y', WINDOW_ATTRIBUTE
launch_error_dialog:
db 'E', 0x0f, 'r', 0x0f, 'r', 0x0f, 'o', 0x0f, 'r', 0x0f
times FS_DIRENT_NAME_SIZE-1-5-1 db 0x00, 0x0f
db 'x', 0x0f
db 'C', 0xf0, 'a', 0xf0, 'n', 0xf0, 'n', 0xf0, 'o', 0xf0, 't', 0xf0
db ' ', 0xf0, 'l', 0xf0, 'a', 0xf0, 'u', 0xf0, 'n', 0xf0, 'c', 0xf0
db 'h', 0xf0, ' ', 0xf0, 'f', 0xf0, 'i', 0xf0, 'l', 0xf0, 'e', 0xf0
db ':', 0xf0
times FS_DIRENT_NAME_SIZE-1-19 db 0x00, 0xf0
.filename times FS_DIRENT_NAME_SIZE-1 db 0x00, 0xf0
db 'E', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE, 'o', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE
times FS_DIRENT_NAME_SIZE-1-5-1 db 0x00, TITLEBAR_ATTRIBUTE
db 'x', TITLEBAR_ATTRIBUTE
db 'C', WINDOW_ATTRIBUTE, 'a', WINDOW_ATTRIBUTE, 'n', WINDOW_ATTRIBUTE, 'n', WINDOW_ATTRIBUTE, 'o', WINDOW_ATTRIBUTE, 't', WINDOW_ATTRIBUTE
db ' ', WINDOW_ATTRIBUTE, 'l', WINDOW_ATTRIBUTE, 'a', WINDOW_ATTRIBUTE, 'u', WINDOW_ATTRIBUTE, 'n', WINDOW_ATTRIBUTE, 'c', WINDOW_ATTRIBUTE
db 'h', WINDOW_ATTRIBUTE, ' ', WINDOW_ATTRIBUTE, 'f', WINDOW_ATTRIBUTE, 'i', WINDOW_ATTRIBUTE, 'l', WINDOW_ATTRIBUTE, 'e', WINDOW_ATTRIBUTE
db ':', WINDOW_ATTRIBUTE
times FS_DIRENT_NAME_SIZE-1-19 db 0x00, WINDOW_ATTRIBUTE
.filename times FS_DIRENT_NAME_SIZE-1 db 0x00, WINDOW_ATTRIBUTE
windows:
times window.size db 0

View File

@ -2,6 +2,19 @@
cpu 8086
bits 16
%ifdef BLINKY
TITLEBAR_ATTRIBUTE equ 0x07
WINDOW_ATTRIBUTE equ 0x70
CANCEL_ATTRIBUTE equ 0x07
%else
TITLEBAR_ATTRIBUTE equ 0x0f
WINDOW_ATTRIBUTE equ 0xf0
CANCEL_ATTRIBUTE equ 0x8f
%endif
OK_ATTRIBUTE equ 0x20
OPEN_DIALOG_ATTRIBUTE equ 0x70
FILENAME_ATTRIBUTE equ WINDOW_ATTRIBUTE
WINDOW_STATUS_NORMAL equ 0
WINDOW_STATUS_MOVE equ 1
WINDOW_STATUS_RESIZE equ 2
@ -591,14 +604,14 @@ event_click:
mov bx, ax
inc bx
cmp byte [bx], CANCEL_COLOR
cmp byte [bx], CANCEL_ATTRIBUTE
jne .not_cancel
.cancel:
call unhook_self_from_window_chain
mov byte [exiting], 1
jmp .end
.not_cancel:
cmp byte [bx], OK_COLOR
cmp byte [bx], OK_ATTRIBUTE
jne .not_ok
.ok:
call filename_ok
@ -921,12 +934,12 @@ render_window:
mov cx, [window.height]
mul cx
mov cx, ax
mov ax, 0xf000 ; Attribute is in the high byte
mov ax, WINDOW_ATTRIBUTE<<8 ; Attribute is in the high byte
rep stosw
; Set title bar to be white-on-black
mov di, text_window_data
mov ax, 0x0f00
mov ax, TITLEBAR_ATTRIBUTE<<8
mov cx, [window.width]
rep stosw
@ -1233,46 +1246,44 @@ cur_filename_address dw filename_window_data.filename
file_opened db 0
; pre-built windows
CANCEL_COLOR equ 0x8f
OK_COLOR equ 0x20
filename_window_data:
; header
db 'V', 0x0f, 'i', 0x0f, 'e', 0x0f, 'w', 0x0f, 'e', 0x0f, 'r', 0x0f
times FS_DIRENT_NAME_SIZE + 2 - 7 db 0, 0x0f
db 'x', 0x0f
db 'V', TITLEBAR_ATTRIBUTE, 'i', TITLEBAR_ATTRIBUTE, 'e', TITLEBAR_ATTRIBUTE, 'w', TITLEBAR_ATTRIBUTE, 'e', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE
times FS_DIRENT_NAME_SIZE + 2 - 7 db 0, TITLEBAR_ATTRIBUTE
db 'x', TITLEBAR_ATTRIBUTE
; blank line
times FS_DIRENT_NAME_SIZE + 2 db 0, 0x70
times FS_DIRENT_NAME_SIZE + 2 db 0, OPEN_DIALOG_ATTRIBUTE
; filename
db 0, 0x70
db 0, OPEN_DIALOG_ATTRIBUTE
.filename:
times FS_DIRENT_NAME_SIZE db 0, 0xf0
db 0, 0x70
times FS_DIRENT_NAME_SIZE db 0, FILENAME_ATTRIBUTE
db 0, OPEN_DIALOG_ATTRIBUTE
; blank line
times FS_DIRENT_NAME_SIZE + 2 db 0, 0x70
times FS_DIRENT_NAME_SIZE + 2 db 0, OPEN_DIALOG_ATTRIBUTE
; buttons line
times 7 db 0, 0x70
db 0, 0x8f, 'C', 0x8f, 'a', 0x8f, 'n', 0x8f, 'c', 0x8f, 'e', 0x8f, 'l', 0x8f, 0, 0x8f
times 5 db 0, 0x70
db 0, 0x20, 'O', 0x20, 'K', 0x20, 0x, 0x20
times 8 db 0, 0x70
times 7 db 0, OPEN_DIALOG_ATTRIBUTE
db 0, CANCEL_ATTRIBUTE, 'C', CANCEL_ATTRIBUTE, 'a', CANCEL_ATTRIBUTE, 'n', CANCEL_ATTRIBUTE, 'c', CANCEL_ATTRIBUTE, 'e', CANCEL_ATTRIBUTE, 'l', CANCEL_ATTRIBUTE, 0, CANCEL_ATTRIBUTE
times 5 db 0, OPEN_DIALOG_ATTRIBUTE
db 0, OK_ATTRIBUTE, 'O', OK_ATTRIBUTE, 'K', OK_ATTRIBUTE, 0x, OK_ATTRIBUTE
times 8 db 0, OPEN_DIALOG_ATTRIBUTE
; blank line
times FS_DIRENT_NAME_SIZE + 2 db 0, 0x70
times FS_DIRENT_NAME_SIZE + 2 db 0, OPEN_DIALOG_ATTRIBUTE
oom_window_data:
db 'E', 0x0f, 'r', 0x0f, 'r', 0x0f, 'o', 0x0f, 'r', 0x0f
times 13-5-1 db 0x00, 0x0f
db 'x', 0x0f
db 'O', 0xf0, 'u', 0xf0, 't', 0xf0, ' ', 0xf0, 'o', 0xf0, 'f', 0xf0
db ' ', 0xf0, 'm', 0xf0, 'e', 0xf0, 'm', 0xf0, 'o', 0xf0, 'r', 0xf0
db 'y', 0xf0
db 'E', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE, 'o', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE
times 13-5-1 db 0x00, TITLEBAR_ATTRIBUTE
db 'x', TITLEBAR_ATTRIBUTE
db 'O', WINDOW_ATTRIBUTE, 'u', WINDOW_ATTRIBUTE, 't', WINDOW_ATTRIBUTE, ' ', WINDOW_ATTRIBUTE, 'o', WINDOW_ATTRIBUTE, 'f', WINDOW_ATTRIBUTE
db ' ', WINDOW_ATTRIBUTE, 'm', WINDOW_ATTRIBUTE, 'e', WINDOW_ATTRIBUTE, 'm', WINDOW_ATTRIBUTE, 'o', WINDOW_ATTRIBUTE, 'r', WINDOW_ATTRIBUTE
db 'y', WINDOW_ATTRIBUTE
ood_window_data:
db 'E', 0x0f, 'r', 0x0f, 'r', 0x0f, 'o', 0x0f, 'r', 0x0f
times 17-5-1 db 0x00, 0x0f
db 'x', 0x0f
db 'O', 0xf0, 'u', 0xf0, 't', 0xf0, ' ', 0xf0, 'o', 0xf0, 'f', 0xf0
db ' ', 0xf0, 'd', 0xf0, 'i', 0xf0, 's', 0xf0, 'k', 0xf0, ' ', 0xf0
db 's', 0xf0, 'p', 0xf0, 'a', 0xf0, 'c', 0xf0, 'e', 0xf0
db 'E', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE, 'o', TITLEBAR_ATTRIBUTE, 'r', TITLEBAR_ATTRIBUTE
times 17-5-1 db 0x00, TITLEBAR_ATTRIBUTE
db 'x', TITLEBAR_ATTRIBUTE
db 'O', WINDOW_ATTRIBUTE, 'u', WINDOW_ATTRIBUTE, 't', WINDOW_ATTRIBUTE, ' ', WINDOW_ATTRIBUTE, 'o', WINDOW_ATTRIBUTE, 'f', WINDOW_ATTRIBUTE
db ' ', WINDOW_ATTRIBUTE, 'd', WINDOW_ATTRIBUTE, 'i', WINDOW_ATTRIBUTE, 's', WINDOW_ATTRIBUTE, 'k', WINDOW_ATTRIBUTE, ' ', WINDOW_ATTRIBUTE
db 's', WINDOW_ATTRIBUTE, 'p', WINDOW_ATTRIBUTE, 'a', WINDOW_ATTRIBUTE, 'c', WINDOW_ATTRIBUTE, 'e', WINDOW_ATTRIBUTE
section .bss
text_window_data resw ROWS*COLUMNS