From d4c15687c8d8445cd3c4ed96132187efbcfbd81c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juhani=20Krekel=C3=A4?= Date: Thu, 11 May 2023 21:25:50 +0300 Subject: [PATCH] Add option for 8-colour mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- Makefile | 6 ++-- README.md | 14 +++++++++ hello.asm | 12 +++++-- memory.asm | 20 ++++++++---- process_wallpaper.py | 21 ++++++++++++- shell.asm | 54 ++++++++++++++++++------------- viewer.asm | 75 +++++++++++++++++++++++++------------------- 7 files changed, 138 insertions(+), 64 deletions(-) diff --git a/Makefile b/Makefile index c962b64..385fafb 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/README.md b/README.md index afa1537..af5e297 100644 --- a/README.md +++ b/README.md @@ -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= 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`. diff --git a/hello.asm b/hello.asm index b7965b0..9f60c86 100644 --- a/hello.asm +++ b/hello.asm @@ -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 diff --git a/memory.asm b/memory.asm index 3d03605..54c6de8 100644 --- a/memory.asm +++ b/memory.asm @@ -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 diff --git a/process_wallpaper.py b/process_wallpaper.py index f92ab47..dfc346c 100644 --- a/process_wallpaper.py +++ b/process_wallpaper.py @@ -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])) diff --git a/shell.asm b/shell.asm index dcacbb5..5ef1c6e 100644 --- a/shell.asm +++ b/shell.asm @@ -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 diff --git a/viewer.asm b/viewer.asm index acfa540..bb8041c 100644 --- a/viewer.asm +++ b/viewer.asm @@ -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