Merge branch 'refactor' into 'master'
Refactor See merge request ZeusWPI/ass_messages!1
This commit is contained in:
commit
ab6cede5b7
1 changed files with 202 additions and 139 deletions
341
messages.asm
341
messages.asm
|
@ -1,9 +1,12 @@
|
||||||
org 0x7C00
|
org 0x7C00 ; The boot code on a drive always gets loaded at address 0x7C00
|
||||||
bits 16
|
bits 16 ; .bin defaults to 16 bits
|
||||||
|
|
||||||
WIDTH equ 0x50
|
WIDTH equ 0x4F ; 79
|
||||||
HEIGHT equ 0x18
|
HEIGHT equ 0x18 ; 24
|
||||||
VIDEO_MODE equ 0x3
|
VIDEO_MODE equ 0x3 ; 80x25 screen, text mode
|
||||||
|
|
||||||
|
PIT_MODECOMMAND_PORT equ 0x43 ; programmable interval timer mode/command port (used for speaker)
|
||||||
|
PIT_CH2_DATA_PORT equ 0x42 ; PIT channel 2 data port
|
||||||
|
|
||||||
;; see http://www.ctyme.com/intr/int-10.htm for interrupts
|
;; see http://www.ctyme.com/intr/int-10.htm for interrupts
|
||||||
|
|
||||||
|
@ -13,173 +16,233 @@ mov ax, VIDEO_MODE
|
||||||
int 10h
|
int 10h
|
||||||
|
|
||||||
;; Clear screen
|
;; Clear screen
|
||||||
mov ah, 0x06
|
mov ah, 0x06 ; scroll screen up
|
||||||
mov al, 0x00
|
mov al, 0x00 ; lines to scroll (0 = clear)
|
||||||
mov bh, 0x0F
|
mov bh, 0x0F ; bg/fg colour
|
||||||
mov cx, 0x0000
|
mov cx, 0x0000 ; upper row number, left col number (both 0)
|
||||||
mov dh, HEIGHT
|
mov dh, HEIGHT ; lower row number (24)
|
||||||
mov dl, WIDTH
|
mov dl, WIDTH ; right col number (80)
|
||||||
int 0x10
|
int 0x10
|
||||||
|
|
||||||
;; Set cursor to bottom of screen
|
;; Set cursor to bottom of screen
|
||||||
mov dh, HEIGHT
|
mov ah, 0x02 ; set cursor position
|
||||||
mov dl, 0x00
|
mov bh, 0x00 ; page number
|
||||||
mov bh, 0x00
|
mov dh, HEIGHT ; row (bottommost row)
|
||||||
mov ah, 0x02
|
mov dl, 0x00 ; col (leftmost col)
|
||||||
int 0x10
|
int 0x10
|
||||||
mov sp, 0x2000
|
|
||||||
|
mov sp, 0x2000 ; initialise stack pointer
|
||||||
|
|
||||||
.loop:
|
.loop:
|
||||||
;; Read character
|
mov ah, 0x00 ; Read a character
|
||||||
mov ah, 0x00
|
int 0x16
|
||||||
int 0x16
|
|
||||||
|
|
||||||
cmp al, 0x0d ; newline
|
cmp al, 0x08 ; backspace
|
||||||
je .newline
|
je change_color_mode
|
||||||
cmp al, 0x08 ; delete character
|
|
||||||
je .change_color_mode
|
|
||||||
cmp al, 0x1b ; escape character
|
|
||||||
je .beep
|
|
||||||
jmp .nonewline
|
|
||||||
|
|
||||||
.change_color_mode:
|
cmp al, 0x1b ; esc
|
||||||
call .readbyte
|
je beep
|
||||||
mov [color_mode], al
|
|
||||||
jmp .loop
|
|
||||||
|
|
||||||
.newline:
|
cmp al, 0x0d ; enter
|
||||||
;; Scroll up window
|
je .nl
|
||||||
mov ah, 0x06
|
|
||||||
mov al, 0x01
|
|
||||||
mov bh, 0x0F
|
|
||||||
mov cx, 0x0000
|
|
||||||
mov dh, HEIGHT
|
|
||||||
mov dl, WIDTH
|
|
||||||
int 0x10
|
|
||||||
|
|
||||||
;; Get current cursor position
|
jmp nonewline ; all other characters
|
||||||
mov bh, 0x00
|
|
||||||
mov ah, 0x03
|
|
||||||
int 0x10
|
|
||||||
|
|
||||||
;; Move cursor to beginning of screen
|
.nl:
|
||||||
mov dl, 0x00
|
call newline
|
||||||
mov ah, 0x02
|
jmp .loop
|
||||||
int 0x10
|
|
||||||
|
|
||||||
jmp .loop
|
;; Update the color_mode variable with a byte from the keyboard
|
||||||
|
;;
|
||||||
|
;; CLOBBERS
|
||||||
|
;; - ax
|
||||||
|
;; - bl
|
||||||
|
change_color_mode:
|
||||||
|
call readbyte ; get byte from keyboard (in al)
|
||||||
|
mov [color_mode], al ; store byte in color_mode variable
|
||||||
|
|
||||||
.beep:
|
jmp start.loop
|
||||||
call .readduration
|
|
||||||
mov ah, 0
|
|
||||||
push ax
|
|
||||||
mov al, 182 ; Prepare the speaker for the
|
|
||||||
out 43h, al ; note.
|
|
||||||
call .readbyte
|
|
||||||
mov ah, 0
|
|
||||||
sal ax, 5 ; multiply by 32
|
|
||||||
add ax, 1140
|
|
||||||
out 42h, al ; Output low byte.
|
|
||||||
mov al, ah ; Output high byte.
|
|
||||||
out 42h, al
|
|
||||||
in al, 61h ; Turn on note (get value from
|
|
||||||
; port 61h).
|
|
||||||
or al, 00000011b ; Set bits 1 and 0.
|
|
||||||
out 61h, al ; Send new value.
|
|
||||||
;; mov bx, 50000 ; Pause for duration of note.
|
|
||||||
pop bx
|
|
||||||
push ax
|
|
||||||
mov ax, 3125
|
|
||||||
mul bx
|
|
||||||
mov bx, ax
|
|
||||||
pop ax
|
|
||||||
|
|
||||||
|
;; Simulates going to a new line
|
||||||
|
;;
|
||||||
|
;; CLOBBERS
|
||||||
|
;; - ax
|
||||||
|
;; - bh
|
||||||
|
;; - cx
|
||||||
|
;; - dx
|
||||||
|
newline:
|
||||||
|
;; Scroll up window
|
||||||
|
mov ah, 0x06 ; scroll screen up
|
||||||
|
mov al, 0x01 ; lines to scroll (1)
|
||||||
|
mov bh, 0x0F ; bg/fg colour
|
||||||
|
mov cx, 0x0000 ; upper row num/left col num (both 0)
|
||||||
|
mov dh, HEIGHT ; lower row num (24)
|
||||||
|
mov dl, WIDTH ; right col num (80)
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
;; Move cursor to beginning of screen
|
||||||
|
mov ah, 0x02 ; set cursors position
|
||||||
|
mov bh, 0x0 ; page number
|
||||||
|
mov dh, HEIGHT ; row
|
||||||
|
mov dl, 0x00 ; col
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
;; Plays a note on the speaker for a given duration
|
||||||
|
;;
|
||||||
|
;; CLOBBERS
|
||||||
|
;; - ax
|
||||||
|
;; - bx
|
||||||
|
;; - cx
|
||||||
|
beep:
|
||||||
|
call read_duration ; get duration from keyboard (in al)
|
||||||
|
mov ah, 0
|
||||||
|
push ax ; store on stack
|
||||||
|
|
||||||
|
;; move 182 (0b10 11 011 0) into al
|
||||||
|
;; bit 7-6 = channel select (2, PC speaker)
|
||||||
|
;; bit 5-4 = access mode (lobyte/hibyte)
|
||||||
|
;; bit 3-1 = operating mode (square wave generator)
|
||||||
|
;; bit 0 = BCD/binary mode (16-bit binary)
|
||||||
|
mov al, 0b10110110
|
||||||
|
out PIT_MODECOMMAND_PORT, al ; write to PIT control port
|
||||||
|
|
||||||
|
;; Read byte and convert to a usable frequency
|
||||||
|
call readbyte ; read byte from keyboard (in al)
|
||||||
|
mov ah, 0 ; readbyte clobbers ax
|
||||||
|
sal ax, 5 ; multiply by 32
|
||||||
|
add ax, 1140
|
||||||
|
|
||||||
|
out PIT_CH2_DATA_PORT, al ; Output low byte.
|
||||||
|
mov al, ah
|
||||||
|
out PIT_CH2_DATA_PORT, al ; Output high byte
|
||||||
|
|
||||||
|
;; Port 0x61 does a whole lot but only the bottom 2 bits are relevant here
|
||||||
|
;; (speaker enable and speaker input select)
|
||||||
|
in al, 61h ; Preserve previous value
|
||||||
|
or al, 00000011b ; Set bits 1 and 0 (enable speaker, input = channel 2)
|
||||||
|
out 61h, al ; Send new value
|
||||||
|
|
||||||
|
;; mov bx, 50000 ; Pause for duration of note.
|
||||||
|
|
||||||
|
;; multiply duration by 3125
|
||||||
|
pop bx ; pull duration value from stack into bx
|
||||||
|
push ax ; save ax (contains garbage?)
|
||||||
|
mov ax, 3125
|
||||||
|
mul bx
|
||||||
|
mov bx, ax ; move dur * 3125 into bx
|
||||||
|
pop ax ; restore ax
|
||||||
|
|
||||||
|
;; play note for a certain duration
|
||||||
.pause1:
|
.pause1:
|
||||||
mov cx, 65535
|
mov ecx, 65535
|
||||||
.pause2:
|
.pause2:
|
||||||
dec cx
|
dec cx ; count down
|
||||||
jne .pause2
|
jne .pause2 ; if not zero keep counting down
|
||||||
dec bx
|
|
||||||
jne .pause1
|
|
||||||
in al, 61h ; Turn off note (get value from
|
|
||||||
; port 61h).
|
|
||||||
and al, 11111100b ; Reset bits 1 and 0.
|
|
||||||
out 61h, al ; Send new value.
|
|
||||||
jmp .loop
|
|
||||||
|
|
||||||
|
dec bx ; decrement duration counter
|
||||||
|
jne .pause1 ; keep doing that until it is 0
|
||||||
|
|
||||||
.nonewline:
|
in al, 61h ; Preserve previous value
|
||||||
|
and al, 11111100b ; Clear bits 1 and 0 (disable speaker, clear channel select)
|
||||||
|
out 61h, al ; Send new value
|
||||||
|
|
||||||
;; Write character
|
jmp start.loop
|
||||||
mov ah, 0x09
|
|
||||||
mov bh, 0x00
|
|
||||||
mov bl, [color_mode]
|
|
||||||
mov cx, 0x01
|
|
||||||
int 0x10
|
|
||||||
|
|
||||||
;; Get current cursor position
|
;; Handles all other characters by writing them to the screen
|
||||||
mov ah, 0x03
|
;;
|
||||||
int 0x10
|
;; CLOBBERS
|
||||||
|
;; - ah
|
||||||
|
;; - bx
|
||||||
|
;; - cx
|
||||||
|
;; - dx
|
||||||
|
nonewline:
|
||||||
|
;; Write character
|
||||||
|
mov ah, 0x09 ; write character with attribute
|
||||||
|
mov bh, 0x00 ; page number
|
||||||
|
mov bl, [color_mode] ; BIOS colour code
|
||||||
|
mov cx, 0x01 ; amount of times to print character
|
||||||
|
int 0x10
|
||||||
|
|
||||||
cmp dl, WIDTH
|
;; Get current cursor position
|
||||||
jge .eol
|
;; dh = row, dl = col
|
||||||
jmp .noeol
|
mov ah, 0x03 ; get cursor position and shape
|
||||||
|
int 0x10
|
||||||
|
|
||||||
|
;; if the cursor is at the edge of the screen go to the next line
|
||||||
|
;; else move it forward once
|
||||||
|
cmp dl, WIDTH
|
||||||
|
jge .eol
|
||||||
|
jmp .noeol
|
||||||
|
|
||||||
.eol:
|
.eol:
|
||||||
;; Scroll up window
|
call newline
|
||||||
mov ah, 0x06
|
|
||||||
mov al, 0x01
|
|
||||||
mov bh, 0x0F
|
|
||||||
mov cx, 0x0000
|
|
||||||
mov dh, HEIGHT
|
|
||||||
mov dl, WIDTH
|
|
||||||
int 0x10
|
|
||||||
|
|
||||||
;; Move cursor to beginning of screen
|
jmp start.loop
|
||||||
mov bh, 0
|
|
||||||
mov dh, HEIGHT
|
|
||||||
mov dl, 0x00
|
|
||||||
mov ah, 0x02
|
|
||||||
int 0x10
|
|
||||||
jmp .loop
|
|
||||||
|
|
||||||
.noeol:
|
.noeol:
|
||||||
|
;; Move cursor forward
|
||||||
|
inc dl
|
||||||
|
mov ah, 0x02 ; set cursor position, dh (row) already set, dl (col) updated on prev line
|
||||||
|
int 0x10
|
||||||
|
|
||||||
;; Move cursor forward
|
jmp start.loop
|
||||||
inc dl
|
|
||||||
mov ah, 0x02
|
|
||||||
int 0x10
|
|
||||||
jmp .loop
|
|
||||||
|
|
||||||
|
;; Reads two characters from the keyboard buffer and converts them into a single byte
|
||||||
|
;;
|
||||||
|
;; The conversion happens as follows:
|
||||||
|
;; ASCII 'a' is subtracted from each character (so 'a' = 0, 'b' = 1, ...)
|
||||||
|
;; the first character is shifted left by 4
|
||||||
|
;; the shifted and non-shifted values are then or'ed together to form a byte
|
||||||
|
;;
|
||||||
|
;; RETURNS
|
||||||
|
;; A byte in al
|
||||||
|
;;
|
||||||
|
;; CLOBBERS
|
||||||
|
;; - ax
|
||||||
|
;; - bl
|
||||||
|
readbyte:
|
||||||
|
mov ah, 0x00 ; Read character
|
||||||
|
int 0x16
|
||||||
|
|
||||||
.readbyte:
|
;; Read character is in al
|
||||||
;; Read character
|
sub al, 'a' ; Normalise
|
||||||
mov ah, 0x00
|
mov bl, al
|
||||||
int 0x16
|
shl bl, 0x4 ; First character is upper 4 bits
|
||||||
;; Read character is in al
|
|
||||||
sub al, 'a'
|
|
||||||
mov bl, al
|
|
||||||
shl bl, 0x4
|
|
||||||
|
|
||||||
;; Read character
|
mov ah, 0x00 ; Read character
|
||||||
mov ah, 0x00
|
int 0x16
|
||||||
int 0x16
|
|
||||||
;; Read character is in al
|
|
||||||
sub al, 'a'
|
|
||||||
or al, bl
|
|
||||||
ret
|
|
||||||
|
|
||||||
.readduration:
|
;; Read character is in al
|
||||||
;; Read duration (0-16 supported)
|
sub al, 'a' ; Normalise
|
||||||
mov ah, 0x00
|
|
||||||
int 0x16
|
|
||||||
;; Read character is in al
|
|
||||||
sub al, 'a'
|
|
||||||
ret
|
|
||||||
|
|
||||||
halt: hlt
|
or al, bl ; Combine both characters
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
;; Reads a duration from the keyboard
|
||||||
|
;;
|
||||||
|
;; RETURNS
|
||||||
|
;; A duration in al
|
||||||
|
;;
|
||||||
|
;; CLOBBERS
|
||||||
|
;; - ax
|
||||||
|
read_duration:
|
||||||
|
;; Read duration (0-16 supported)
|
||||||
|
mov ah, 0x00 ; read keypress
|
||||||
|
int 0x16
|
||||||
|
|
||||||
|
;; Read character is in al
|
||||||
|
sub al, 'a' ; normalise
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
;; Variable to store color mode information for writing to the screen
|
||||||
color_mode: db 0x02
|
color_mode: db 0x02
|
||||||
|
|
||||||
|
;; Magic number must be in the last 2 bytes of the sector so
|
||||||
|
;; fill the binary with zeroes until it is 510 bytes in size
|
||||||
|
;; (magic number will use up the remaining 2)
|
||||||
times 510 - ($ - $$) db 0
|
times 510 - ($ - $$) db 0
|
||||||
dw 0xAA55
|
dw 0xAA55 ;; Magic number to mark sector as bootable
|
||||||
|
|
Loading…
Reference in a new issue