Moved stuff around and added a makefile also got a custom bootloader
based on the JazzOS bootloader (modified a bit)
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
297
source/bootload/boot.asm
Normal file
297
source/bootload/boot.asm
Normal file
@@ -0,0 +1,297 @@
|
||||
ORG 7C00h
|
||||
BITS 16
|
||||
|
||||
jmp short main
|
||||
nop
|
||||
|
||||
; Define Fat12 header
|
||||
bdb_oem: db 'MSWIN4.1'
|
||||
bdb_bytes_per_sector: dw 512
|
||||
bdb_sectors_per_cluster: db 1
|
||||
bdb_reserved_sectors: dw 1
|
||||
bdb_fat_count: db 2
|
||||
bdb_dir_entries_count: dw 0E0h
|
||||
bdb_total_sectors: dw 2880
|
||||
bdb_media_descriptor_type: db 0F0h
|
||||
bdb_sectors_per_fat: dw 9
|
||||
bdb_sectors_per_track: dw 18
|
||||
bdb_heads: dw 2
|
||||
bdb_hidden_sectors: dd 0
|
||||
bdb_large_sector_count: dd 0
|
||||
|
||||
; extended boot record
|
||||
ebr_drive_number: db 0
|
||||
db 0
|
||||
ebr_signature: db 29h
|
||||
ebr_volume_id: db 12h, 34h, 56h, 78h
|
||||
ebr_volume_label: db 'CrawShaw OS'
|
||||
ebr_system_id: db 'FAT12 '
|
||||
|
||||
main:
|
||||
; Setup registers
|
||||
mov ax, 0
|
||||
mov ds, ax ; ds = data segment pointer
|
||||
mov es, ax ; es = extra segment pointer
|
||||
mov ss, ax ; ss = stack pointer
|
||||
|
||||
mov sp, 7C00h
|
||||
|
||||
; Read from disk
|
||||
;mov [ebr_drive_number], dl
|
||||
;mov ax, 1
|
||||
;mov cl, 1
|
||||
;mov bx, 7E00h
|
||||
;call disk_read
|
||||
|
||||
; Output boot text
|
||||
mov si, boot_text
|
||||
call print_string
|
||||
|
||||
; Load kernel
|
||||
; 4 segments:
|
||||
; reserved segment (bdb_reserved_segments, 1)
|
||||
; FAT: (sectors_per_fat * fat_count) 9*2=18
|
||||
; root dir: gives location of data
|
||||
; data: stores the actual data
|
||||
|
||||
; Get LBA of root dir
|
||||
mov ax, [bdb_sectors_per_fat]
|
||||
mov bl, [bdb_fat_count]
|
||||
xor bh,bh ; clear bh
|
||||
mul bx ; 9 * 2 = 18
|
||||
add ax, [bdb_reserved_sectors] ; The LBA of root dir
|
||||
push ax ; Push to stack
|
||||
|
||||
mov ax, [bdb_dir_entries_count]
|
||||
shl ax,5 ; ax *= 32 (shifting 5 times)
|
||||
xor dx,dx ; Clear dx
|
||||
div word [bdb_bytes_per_sector] ;32*num of entries)/bytes per sector
|
||||
test dx,dx ; See if there's a remainder
|
||||
jz root_dir_after
|
||||
inc ax ; Add one if there's a remainder
|
||||
|
||||
root_dir_after:
|
||||
mov cl, al
|
||||
pop ax ; LBA of root dir
|
||||
mov dl, [ebr_drive_number]
|
||||
mov bx, buffer
|
||||
call disk_read
|
||||
|
||||
xor bx,bx ; clear bx
|
||||
mov di, buffer ; Loaded root dir into memory
|
||||
|
||||
search_for_kernel:
|
||||
mov si, file_kernel_bin ; Move the name of the kernel into si
|
||||
mov cx, 11
|
||||
push di ; Preserve di
|
||||
repe cmpsb ; Repeat a comparison of bytes between kernel name and current bytes until it finds a match
|
||||
pop di ; Retrieve di
|
||||
je found_kernel
|
||||
|
||||
add di, 32 ; Next directory entry
|
||||
inc bx
|
||||
cmp bx, [bdb_dir_entries_count] ; Have we reached the number of directories that exist
|
||||
jl search_for_kernel ; Repeat search
|
||||
|
||||
jmp kernel_not_found ; If the last dir has been searched, then there is no kernel
|
||||
kernel_not_found:
|
||||
mov si, kernel_load_error
|
||||
call print_string
|
||||
|
||||
hlt
|
||||
jmp halt
|
||||
|
||||
found_kernel:
|
||||
mov si, kernel_found_text
|
||||
call print_string
|
||||
; Find kernel cluster
|
||||
mov ax, [di+26]
|
||||
mov [kernel_cluster], ax
|
||||
|
||||
mov ax, [bdb_reserved_sectors]
|
||||
mov bx, buffer
|
||||
mov cl, [bdb_sectors_per_fat]
|
||||
mov dl, [ebr_drive_number]
|
||||
|
||||
call disk_read ; Load FAT from disk into memory
|
||||
|
||||
; Load kernel into memory
|
||||
mov bx, kernel_load_segment
|
||||
mov es, bx
|
||||
mov bx, kernel_load_offset ; Setup memory that kernel will be loaded into
|
||||
|
||||
load_kernel_loop:
|
||||
mov ax, [kernel_cluster]
|
||||
add ax, 31 ; Setup offset so we can read the particular cluster
|
||||
mov cl, 1 ;sectors to read
|
||||
mov dl, [ebr_drive_number]
|
||||
|
||||
call disk_read
|
||||
|
||||
add bx, [bdb_bytes_per_sector]
|
||||
|
||||
; (kernel_cluster * 3) / 2
|
||||
mov ax, [kernel_cluster]
|
||||
mov cx, 3
|
||||
mul cx
|
||||
mov cx, 2
|
||||
div cx
|
||||
|
||||
; setup buffers
|
||||
mov si, buffer
|
||||
add si, ax
|
||||
mov ax, [ds:si]
|
||||
|
||||
or dx,dx
|
||||
jz even
|
||||
|
||||
odd:
|
||||
shr ax, 4 ;shift ax 4
|
||||
jmp next_cluster_after
|
||||
|
||||
even:
|
||||
and ax, 0fffh ; Gives the other 12 bits
|
||||
|
||||
next_cluster_after:
|
||||
cmp ax, 0ff8h ; If the value is ff8h or bigger then we've reached the end of FAT
|
||||
jae read_finish
|
||||
|
||||
mov [kernel_cluster], ax
|
||||
jmp load_kernel_loop
|
||||
|
||||
read_finish: ; Load kernel
|
||||
mov dl, [ebr_drive_number]
|
||||
mov ax, kernel_load_segment
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
|
||||
jmp kernel_load_segment:kernel_load_offset ; Jump to the kernel code
|
||||
hlt
|
||||
|
||||
|
||||
halt:
|
||||
jmp halt
|
||||
|
||||
; LBA = index of data segment on disk
|
||||
; CHS = cylinder, header, sector
|
||||
; input, LBA index: ax
|
||||
; sector number: cx [0-5]
|
||||
; cylinder: cx [6-15]
|
||||
; head: dh
|
||||
lba_to_chs:
|
||||
push ax
|
||||
push dx
|
||||
|
||||
xor dx,dx ; clear dx
|
||||
div word [bdb_sectors_per_track] ;(LBA % sectors per track) + 1 = sector
|
||||
inc dx ; sector, dx stores the remainder so we increment that.
|
||||
mov cx,dx
|
||||
|
||||
xor dx,dx ; clear dx
|
||||
div word [bdb_heads]
|
||||
|
||||
mov dh,dl ; head
|
||||
mov ch,al
|
||||
shl ah, 6
|
||||
or CL, AH ; cylinder
|
||||
|
||||
pop ax
|
||||
mov dl,al
|
||||
pop ax
|
||||
|
||||
RET
|
||||
|
||||
disk_read:
|
||||
push ax
|
||||
push bx
|
||||
push cx
|
||||
push dx
|
||||
push di
|
||||
|
||||
|
||||
call lba_to_chs
|
||||
|
||||
mov ah, 02h
|
||||
|
||||
; repeat drive read 3 times (incase of random error)
|
||||
mov di, 3 ; counter
|
||||
|
||||
retry:
|
||||
stc
|
||||
int 13h
|
||||
jnc done_read
|
||||
|
||||
call disk_reset ; Reset drivers of disk
|
||||
|
||||
dec di
|
||||
test di, di
|
||||
jnz retry
|
||||
|
||||
fail_disk_read:
|
||||
mov si, disk_read_fail
|
||||
call print_string
|
||||
hlt
|
||||
jmp halt
|
||||
|
||||
disk_reset:
|
||||
pusha
|
||||
mov ah, 0 ; Reset drive
|
||||
stc
|
||||
int 13h
|
||||
jc fail_disk_read
|
||||
popa
|
||||
ret
|
||||
|
||||
done_read:
|
||||
pop di
|
||||
pop dx
|
||||
pop cx
|
||||
pop bx
|
||||
pop ax
|
||||
ret
|
||||
|
||||
; SI = pointer to start of string to be printed
|
||||
print_string:
|
||||
push si
|
||||
push ax
|
||||
push bx
|
||||
|
||||
mov ah, 0Eh ; int 10h teletype function, we're telling the BIOS we will print something
|
||||
|
||||
.repeat:
|
||||
lodsb ; Get char from si into al
|
||||
cmp al, 0 ; Compare al to 0
|
||||
je .done ; If char is zero, end of string
|
||||
|
||||
mov bh, 0
|
||||
int 10h ; Otherwise, print it
|
||||
jmp .repeat ; And move on to next char
|
||||
|
||||
.done:
|
||||
; Print newline
|
||||
mov ah, 0Eh
|
||||
mov al, 13
|
||||
int 10h
|
||||
mov al, 10
|
||||
int 10h
|
||||
; Exit function
|
||||
pop bx
|
||||
pop ax
|
||||
pop si
|
||||
ret
|
||||
|
||||
boot_text: db '[OK] Boot sequence begun...', 0
|
||||
kernel_found_text: db '[OK] Kernel located...', 0
|
||||
disk_read_fail: db '[ERR] Failed to read disk!', 0
|
||||
file_kernel_bin: db 'KERNEL BIN' ; Must have a double space between KERNEL and BIN
|
||||
kernel_load_error: db '[ERR] Kernel not found!', 0
|
||||
|
||||
kernel_cluster: dw 0
|
||||
kernel_load_segment: equ 2000h
|
||||
kernel_load_offset: equ 0
|
||||
|
||||
|
||||
times 510-($-$$) db 0 ; Fill up the next 510 bits with 0's
|
||||
dw 0AA55h ; D
|
||||
|
||||
buffer:
|
||||
@@ -1,357 +0,0 @@
|
||||
; ==================================================================
|
||||
; The Mike Operating System bootloader
|
||||
; Copyright (C) 2006 - 2022 MikeOS Developers -- see doc/LICENSE.TXT
|
||||
;
|
||||
; Based on a free boot loader by E Dehling. It scans the FAT12
|
||||
; floppy for KERNEL.BIN (the MikeOS kernel), loads it and executes it.
|
||||
; This must grow no larger than 512 bytes (one sector), with the final
|
||||
; two bytes being the boot signature (AA55h). Note that in FAT12,
|
||||
; a cluster is the same as a sector: 512 bytes.
|
||||
; ==================================================================
|
||||
|
||||
|
||||
BITS 16
|
||||
|
||||
jmp short bootloader_start ; Jump past disk description section
|
||||
nop ; Pad out before disk description
|
||||
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; Disk description table, to make it a valid floppy
|
||||
; Note: some of these values are hard-coded in the source!
|
||||
; Values are those used by IBM for 1.44 MB, 3.5" diskette
|
||||
|
||||
OEMLabel db "MIKEBOOT" ; Disk label
|
||||
BytesPerSector dw 512 ; Bytes per sector
|
||||
SectorsPerCluster db 1 ; Sectors per cluster
|
||||
ReservedForBoot dw 1 ; Reserved sectors for boot record
|
||||
NumberOfFats db 2 ; Number of copies of the FAT
|
||||
RootDirEntries dw 224 ; Number of entries in root dir
|
||||
; (224 * 32 = 7168 = 14 sectors to read)
|
||||
LogicalSectors dw 2880 ; Number of logical sectors
|
||||
MediumByte db 0F0h ; Medium descriptor byte
|
||||
SectorsPerFat dw 9 ; Sectors per FAT
|
||||
SectorsPerTrack dw 18 ; Sectors per track (36/cylinder)
|
||||
Sides dw 2 ; Number of sides/heads
|
||||
HiddenSectors dd 0 ; Number of hidden sectors
|
||||
LargeSectors dd 0 ; Number of LBA sectors
|
||||
DriveNo dw 0 ; Drive No: 0
|
||||
Signature db 41 ; Drive signature: 41 for floppy
|
||||
VolumeID dd 00000000h ; Volume ID: any number
|
||||
VolumeLabel db "MIKEOS "; Volume Label: any 11 chars
|
||||
FileSystem db "FAT12 " ; File system type: don't change!
|
||||
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; Main bootloader code
|
||||
|
||||
bootloader_start:
|
||||
mov ax, 07C0h ; Set up 4K of stack space above buffer
|
||||
add ax, 544 ; 8k buffer = 512 paragraphs + 32 paragraphs (loader)
|
||||
cli ; Disable interrupts while changing stack
|
||||
mov ss, ax
|
||||
mov sp, 4096
|
||||
sti ; Restore interrupts
|
||||
|
||||
mov ax, 07C0h ; Set data segment to where we're loaded
|
||||
mov ds, ax
|
||||
|
||||
; NOTE: A few early BIOSes are reported to improperly set DL
|
||||
|
||||
cmp dl, 0
|
||||
je no_change
|
||||
mov [bootdev], dl ; Save boot device number
|
||||
mov ah, 8 ; Get drive parameters
|
||||
int 13h
|
||||
jc fatal_disk_error
|
||||
and cx, 3Fh ; Maximum sector number
|
||||
mov [SectorsPerTrack], cx ; Sector numbers start at 1
|
||||
movzx dx, dh ; Maximum head number
|
||||
add dx, 1 ; Head numbers start at 0 - add 1 for total
|
||||
mov [Sides], dx
|
||||
|
||||
no_change:
|
||||
mov eax, 0 ; Needed for some older BIOSes
|
||||
|
||||
|
||||
; First, we need to load the root directory from the disk. Technical details:
|
||||
; Start of root = ReservedForBoot + NumberOfFats * SectorsPerFat = logical 19
|
||||
; Number of root = RootDirEntries * 32 bytes/entry / 512 bytes/sector = 14
|
||||
; Start of user data = (start of root) + (number of root) = logical 33
|
||||
|
||||
floppy_ok: ; Ready to read first block of data
|
||||
mov ax, 19 ; Root dir starts at logical sector 19
|
||||
call l2hts
|
||||
|
||||
mov si, buffer ; Set ES:BX to point to our buffer (see end of code)
|
||||
mov bx, ds
|
||||
mov es, bx
|
||||
mov bx, si
|
||||
|
||||
mov ah, 2 ; Params for int 13h: read floppy sectors
|
||||
mov al, 14 ; And read 14 of them
|
||||
|
||||
pusha ; Prepare to enter loop
|
||||
|
||||
|
||||
read_root_dir:
|
||||
popa ; In case registers are altered by int 13h
|
||||
pusha
|
||||
|
||||
stc ; A few BIOSes do not set properly on error
|
||||
int 13h ; Read sectors using BIOS
|
||||
|
||||
jnc search_dir ; If read went OK, skip ahead
|
||||
call reset_floppy ; Otherwise, reset floppy controller and try again
|
||||
jnc read_root_dir ; Floppy reset OK?
|
||||
|
||||
jmp reboot ; If not, fatal double error
|
||||
|
||||
|
||||
search_dir:
|
||||
popa
|
||||
|
||||
mov ax, ds ; Root dir is now in [buffer]
|
||||
mov es, ax ; Set DI to this info
|
||||
mov di, buffer
|
||||
|
||||
mov cx, word [RootDirEntries] ; Search all (224) entries
|
||||
mov ax, 0 ; Searching at offset 0
|
||||
|
||||
|
||||
next_root_entry:
|
||||
xchg cx, dx ; We use CX in the inner loop...
|
||||
|
||||
mov si, kern_filename ; Start searching for kernel filename
|
||||
mov cx, 11
|
||||
rep cmpsb
|
||||
je found_file_to_load ; Pointer DI will be at offset 11
|
||||
|
||||
add ax, 32 ; Bump searched entries by 1 (32 bytes per entry)
|
||||
|
||||
mov di, buffer ; Point to next entry
|
||||
add di, ax
|
||||
|
||||
xchg dx, cx ; Get the original CX back
|
||||
loop next_root_entry
|
||||
|
||||
mov si, file_not_found ; If kernel is not found, bail out
|
||||
call print_string
|
||||
jmp reboot
|
||||
|
||||
|
||||
found_file_to_load: ; Fetch cluster and load FAT into RAM
|
||||
mov ax, word [es:di+0Fh] ; Offset 11 + 15 = 26, contains 1st cluster
|
||||
mov word [cluster], ax
|
||||
|
||||
mov ax, 1 ; Sector 1 = first sector of first FAT
|
||||
call l2hts
|
||||
|
||||
mov di, buffer ; ES:BX points to our buffer
|
||||
mov bx, di
|
||||
|
||||
mov ah, 2 ; int 13h params: read (FAT) sectors
|
||||
mov al, 9 ; All 9 sectors of 1st FAT
|
||||
|
||||
pusha ; Prepare to enter loop
|
||||
|
||||
|
||||
read_fat:
|
||||
popa ; In case registers are altered by int 13h
|
||||
pusha
|
||||
|
||||
stc
|
||||
int 13h ; Read sectors using the BIOS
|
||||
|
||||
jnc read_fat_ok ; If read went OK, skip ahead
|
||||
call reset_floppy ; Otherwise, reset floppy controller and try again
|
||||
jnc read_fat ; Floppy reset OK?
|
||||
|
||||
; ******************************************************************
|
||||
fatal_disk_error:
|
||||
; ******************************************************************
|
||||
mov si, disk_error ; If not, print error message and reboot
|
||||
call print_string
|
||||
jmp reboot ; Fatal double error
|
||||
|
||||
|
||||
read_fat_ok:
|
||||
popa
|
||||
|
||||
mov ax, 2000h ; Segment where we'll load the kernel
|
||||
mov es, ax
|
||||
mov bx, 0
|
||||
|
||||
mov ah, 2 ; int 13h floppy read params
|
||||
mov al, 1
|
||||
|
||||
push ax ; Save in case we (or int calls) lose it
|
||||
|
||||
|
||||
; Now we must load the FAT from the disk. Here's how we find out where it starts:
|
||||
; FAT cluster 0 = media descriptor = 0F0h
|
||||
; FAT cluster 1 = filler cluster = 0FFh
|
||||
; Cluster start = ((cluster number) - 2) * SectorsPerCluster + (start of user)
|
||||
; = (cluster number) + 31
|
||||
|
||||
load_file_sector:
|
||||
mov ax, word [cluster] ; Convert sector to logical
|
||||
add ax, 31
|
||||
|
||||
call l2hts ; Make appropriate params for int 13h
|
||||
|
||||
mov ax, 2000h ; Set buffer past what we've already read
|
||||
mov es, ax
|
||||
mov bx, word [pointer]
|
||||
|
||||
pop ax ; Save in case we (or int calls) lose it
|
||||
push ax
|
||||
|
||||
stc
|
||||
int 13h
|
||||
|
||||
jnc calculate_next_cluster ; If there's no error...
|
||||
|
||||
call reset_floppy ; Otherwise, reset floppy and retry
|
||||
jmp load_file_sector
|
||||
|
||||
|
||||
; In the FAT, cluster values are stored in 12 bits, so we have to
|
||||
; do a bit of maths to work out whether we're dealing with a byte
|
||||
; and 4 bits of the next byte -- or the last 4 bits of one byte
|
||||
; and then the subsequent byte!
|
||||
|
||||
calculate_next_cluster:
|
||||
mov ax, [cluster]
|
||||
mov dx, 0
|
||||
mov bx, 3
|
||||
mul bx
|
||||
mov bx, 2
|
||||
div bx ; DX = [cluster] mod 2
|
||||
mov si, buffer
|
||||
add si, ax ; AX = word in FAT for the 12 bit entry
|
||||
mov ax, word [ds:si]
|
||||
|
||||
or dx, dx ; If DX = 0 [cluster] is even; if DX = 1 then it's odd
|
||||
|
||||
jz even ; If [cluster] is even, drop last 4 bits of word
|
||||
; with next cluster; if odd, drop first 4 bits
|
||||
|
||||
odd:
|
||||
shr ax, 4 ; Shift out first 4 bits (they belong to another entry)
|
||||
jmp short next_cluster_cont
|
||||
|
||||
|
||||
even:
|
||||
and ax, 0FFFh ; Mask out final 4 bits
|
||||
|
||||
|
||||
next_cluster_cont:
|
||||
mov word [cluster], ax ; Store cluster
|
||||
|
||||
cmp ax, 0FF8h ; FF8h = end of file marker in FAT12
|
||||
jae end
|
||||
|
||||
add word [pointer], 512 ; Increase buffer pointer 1 sector length
|
||||
jmp load_file_sector
|
||||
|
||||
|
||||
end: ; We've got the file to load!
|
||||
pop ax ; Clean up the stack (AX was pushed earlier)
|
||||
mov dl, byte [bootdev] ; Provide kernel with boot device info
|
||||
|
||||
jmp 2000h:0000h ; Jump to entry point of loaded kernel!
|
||||
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; BOOTLOADER SUBROUTINES
|
||||
|
||||
reboot:
|
||||
mov ax, 0
|
||||
int 16h ; Wait for keystroke
|
||||
mov ax, 0
|
||||
int 19h ; Reboot the system
|
||||
|
||||
|
||||
print_string: ; Output string in SI to screen
|
||||
pusha
|
||||
|
||||
mov ah, 0Eh ; int 10h teletype function
|
||||
|
||||
.repeat:
|
||||
lodsb ; Get char from string
|
||||
cmp al, 0
|
||||
je .done ; If char is zero, end of string
|
||||
int 10h ; Otherwise, print it
|
||||
jmp short .repeat
|
||||
|
||||
.done:
|
||||
popa
|
||||
ret
|
||||
|
||||
|
||||
reset_floppy: ; IN: [bootdev] = boot device; OUT: carry set on error
|
||||
push ax
|
||||
push dx
|
||||
mov ax, 0
|
||||
mov dl, byte [bootdev]
|
||||
stc
|
||||
int 13h
|
||||
pop dx
|
||||
pop ax
|
||||
ret
|
||||
|
||||
|
||||
l2hts: ; Calculate head, track and sector settings for int 13h
|
||||
; IN: logical sector in AX, OUT: correct registers for int 13h
|
||||
push bx
|
||||
push ax
|
||||
|
||||
mov bx, ax ; Save logical sector
|
||||
|
||||
mov dx, 0 ; First the sector
|
||||
div word [SectorsPerTrack]
|
||||
add dl, 01h ; Physical sectors start at 1
|
||||
mov cl, dl ; Sectors belong in CL for int 13h
|
||||
mov ax, bx
|
||||
|
||||
mov dx, 0 ; Now calculate the head
|
||||
div word [SectorsPerTrack]
|
||||
mov dx, 0
|
||||
div word [Sides]
|
||||
mov dh, dl ; Head/side
|
||||
mov ch, al ; Track
|
||||
|
||||
pop ax
|
||||
pop bx
|
||||
|
||||
mov dl, byte [bootdev] ; Set correct device
|
||||
|
||||
ret
|
||||
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; STRINGS AND VARIABLES
|
||||
|
||||
kern_filename db "KERNEL BIN" ; MikeOS kernel filename
|
||||
|
||||
disk_error db "Floppy error! Press any key...", 0
|
||||
file_not_found db "KERNEL.BIN not found!", 0
|
||||
|
||||
bootdev db 0 ; Boot device number
|
||||
cluster dw 0 ; Cluster of the file we want to load
|
||||
pointer dw 0 ; Pointer into Buffer, for loading kernel
|
||||
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; END OF BOOT SECTOR AND BUFFER START
|
||||
|
||||
times 510-($-$$) db 0 ; Pad remainder of boot sector with zeros
|
||||
dw 0AA55h ; Boot signature (DO NOT CHANGE!)
|
||||
|
||||
|
||||
buffer: ; Disk buffer begins (8k after this, stack starts)
|
||||
|
||||
|
||||
; ==================================================================
|
||||
|
||||
Binary file not shown.
@@ -1,86 +0,0 @@
|
||||
game_pong:
|
||||
pusha
|
||||
call os_set_graphics_mode
|
||||
jmp .draw_player_1
|
||||
jmp .draw_player_2
|
||||
jmp .detect_inputi
|
||||
.draw_player_1:
|
||||
; X coords
|
||||
mov ax, [p1_x]
|
||||
mov [x_start], ax
|
||||
mov [x_end], ax
|
||||
|
||||
; Y coords
|
||||
mov bx, [p1_y]
|
||||
mov [y_start], bx
|
||||
add bx, [bat_height] ; Add the bat height to the y coord
|
||||
mov [y_end], b
|
||||
call os_draw_graphical_rectangle
|
||||
ret
|
||||
.draw_player_2:
|
||||
; X coords
|
||||
mov ax, [p2_x]
|
||||
mov [x_start], ax
|
||||
mov [x_end], ax
|
||||
|
||||
; Y coords
|
||||
mov bx, [p2_y]
|
||||
mov [y_start], bx
|
||||
add bx, [bat_height] ; Add the bat height to the y coord
|
||||
mov [y_end], bx
|
||||
|
||||
call os_draw_graphical_rectangle
|
||||
ret
|
||||
.detect_input:
|
||||
call os_read_input
|
||||
; Exit if backspace is pressed
|
||||
cmp al, 08h
|
||||
je .finish
|
||||
; Go up when you press 'w'
|
||||
cmp al, 77h
|
||||
je .p1_up
|
||||
; Go up when you press 's'
|
||||
cmp al, 73h
|
||||
je .p1_down
|
||||
|
||||
; Loop back
|
||||
jmp .detect_input
|
||||
.p1_down:
|
||||
; X coords
|
||||
mov ax, [p1_x]
|
||||
mov [x_start], ax
|
||||
mov [x_end], ax
|
||||
|
||||
; Y coords
|
||||
mov bx, [p1_y]
|
||||
add bx, 5 ; Move the bat down 5
|
||||
mov [y_start], bx
|
||||
add bx, [bat_height] ; Add the bat height to the y coord
|
||||
mov [y_end], bx
|
||||
|
||||
call os_draw_graphical_rectangle
|
||||
ret
|
||||
.p1_up:
|
||||
mov ax, [move_distance]
|
||||
sub ax, [p1_y]
|
||||
call os_draw_graphical_rectangle
|
||||
ret
|
||||
.finish:
|
||||
call os_set_text_mode
|
||||
popa
|
||||
ret
|
||||
|
||||
section .data
|
||||
x_start dw 0
|
||||
y_start dw 0
|
||||
x_end dw 0
|
||||
y_end dw 0
|
||||
|
||||
p1_y dw 5
|
||||
p2_y dw 0
|
||||
p1_x dw 5
|
||||
p2_x dw 30
|
||||
|
||||
bat_height dw 20
|
||||
move_distance dw 5
|
||||
colour db 1111b
|
||||
@@ -1,79 +0,0 @@
|
||||
BITS 16
|
||||
CPU 386 ; pusha offsets depends on a 386 or better
|
||||
; FS and GS require a 386 or better
|
||||
|
||||
%DEFINE CRAWOS_VER '0.0.2' ; OS version number
|
||||
%DEFINE CRAWOS_API_VER 1 ; API version for programs to check
|
||||
|
||||
|
||||
; This is the location in RAM for kernel disk operations, 24K
|
||||
; after the point where the kernel has loaded; it's 8K in size,
|
||||
; because external programs load after it at the 32K point:
|
||||
|
||||
disk_buffer equ 24576
|
||||
|
||||
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; START OF MAIN KERNEL CODE
|
||||
|
||||
os_main:
|
||||
cli ; Clear interrupts
|
||||
mov ax, 0
|
||||
mov ss, ax ; Set stack segment and pointer
|
||||
mov sp, 0FFFFh
|
||||
sti ; Restore interrupts
|
||||
|
||||
cld ; The default direction for string operations
|
||||
; will be 'up' - incrementing address in RAM
|
||||
|
||||
mov ax, 2000h ; Set all segments to match where kernel is loaded
|
||||
mov ds, ax ; After this, we don't need to bother with
|
||||
mov es, ax ; segments ever again, as MikeOS and its programs
|
||||
mov fs, ax ; live entirely in 64K
|
||||
mov gs, ax
|
||||
|
||||
cmp dl, 0
|
||||
je no_change
|
||||
|
||||
no_change:
|
||||
mov si, help_text
|
||||
call os_print_string_nl
|
||||
call os_start_cli
|
||||
|
||||
bootdev db 0
|
||||
SecsPerTrack dw 18
|
||||
Sides dw 2
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; SYSTEM VARIABLES -- Settings for programs and system calls
|
||||
|
||||
|
||||
; Time and date formatting
|
||||
|
||||
fmt_12_24 db 0 ; Non-zero = 24-hr format
|
||||
|
||||
fmt_date db 0, '/' ; 0, 1, 2 = M/D/Y, D/M/Y or Y/M/D
|
||||
; Bit 7 = use name for months
|
||||
; If bit 7 = 0, second byte = separator character
|
||||
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; FEATURES -- Code to pull into the kernel
|
||||
%INCLUDE "features/screen.asm"
|
||||
%INCLUDE "features/cli.asm"
|
||||
%INCLUDE "features/power.asm"
|
||||
%INCLUDE "features/strings.asm"
|
||||
%INCLUDE "features/graphics.asm"
|
||||
%INCLUDE "features/sound.asm"
|
||||
|
||||
; FUNCTIONS -- Other stuff that is useful
|
||||
%INCLUDE "functios/math.asm"
|
||||
|
||||
; GAMES -- Games that I wrote for it
|
||||
%INCLUDE "games/pong.asm"
|
||||
|
||||
; ==================================================================
|
||||
; END OF KERNEL
|
||||
; ==================================================================
|
||||
|
||||
Binary file not shown.
@@ -40,6 +40,12 @@ os_read_cli:
|
||||
cmp cl, 1
|
||||
je pong
|
||||
|
||||
mov si, user_input
|
||||
mov di, snake_string
|
||||
call os_compare_strings
|
||||
cmp cl, 1
|
||||
je snake
|
||||
|
||||
jmp .unkown
|
||||
|
||||
.unkown:
|
||||
@@ -66,13 +72,19 @@ pong:
|
||||
call game_pong
|
||||
call os_read_cli.finish
|
||||
|
||||
snake:
|
||||
call game_snake
|
||||
call os_read_cli.finish
|
||||
|
||||
section .data
|
||||
welcome_text db 'Welcome to CrawOS, the Cool, Real and AWsome Operating System', 0
|
||||
user_input times 20 db 0
|
||||
prompt_length db 20
|
||||
prompt db 'CrawOS: ', 0
|
||||
prompt db 'CrawOS sh> ', 0
|
||||
help_string db 'HELP', 0
|
||||
clear_string db 'CLEAR', 0
|
||||
pong_string db 'PONG', 0
|
||||
help_text db 'This is CrawOS, type "HELP" for help, "CLEAR" to clear the screen', 0
|
||||
snake_string db 'SNAKE', 0
|
||||
help_text db 'This is for Cowards: "HELP" for this help text, "CLEAR" to clear the screen, esc to reboot', 0
|
||||
command_result_text db 'You typed: ', 0
|
||||
unknown_command db 'Error: Unkown Command.. ', 0
|
||||
77
source/kernel/features/keyboard.asm
Normal file
77
source/kernel/features/keyboard.asm
Normal file
@@ -0,0 +1,77 @@
|
||||
; AX = key pressed
|
||||
os_read_input:
|
||||
mov ah, 11h ; BIOS call to check for key
|
||||
int 16h ; Interrupt
|
||||
jnz .key_pressed ; Jump if input isn't 0
|
||||
|
||||
hlt
|
||||
jmp os_read_input
|
||||
|
||||
.key_pressed:
|
||||
mov ah, 10h
|
||||
int 16h
|
||||
ret
|
||||
|
||||
; -------------------------------------------
|
||||
|
||||
os_display_input:
|
||||
pusha
|
||||
mov cx, [prompt_length]
|
||||
|
||||
.loop:
|
||||
call .check_key_pressed
|
||||
|
||||
jmp .loop
|
||||
|
||||
.check_key_pressed:
|
||||
call os_read_input
|
||||
|
||||
cmp al, 08h
|
||||
je .backspace
|
||||
|
||||
cmp al, 0Dh
|
||||
je .enter_key
|
||||
|
||||
cmp al, 1Bh
|
||||
je .esc_key
|
||||
|
||||
cmp cx, 0
|
||||
jb .check_key_pressed
|
||||
|
||||
call .print_current_input
|
||||
dec cx
|
||||
jmp .check_key_pressed
|
||||
|
||||
.esc_key:
|
||||
call os_reboot
|
||||
|
||||
.enter_key:
|
||||
mov al, 0
|
||||
stosb
|
||||
popa
|
||||
call os_read_cli
|
||||
|
||||
.backspace:
|
||||
call .move_cursor_back ; then .move_cursor_back
|
||||
call .loop ; Else .loop
|
||||
|
||||
.move_cursor_back:
|
||||
mov ah, 0Eh
|
||||
|
||||
mov al, 08h
|
||||
int 10h
|
||||
mov al, 20h
|
||||
int 10h
|
||||
mov al, 08h
|
||||
int 10h
|
||||
|
||||
dec di
|
||||
jmp os_display_input
|
||||
|
||||
.print_current_input:
|
||||
stosb
|
||||
|
||||
mov ah, 0Eh
|
||||
int 10h
|
||||
|
||||
ret
|
||||
0
source/kernel/features/math.asm
Normal file
0
source/kernel/features/math.asm
Normal file
0
source/kernel/features/sound.asm
Normal file
0
source/kernel/features/sound.asm
Normal file
@@ -68,82 +68,3 @@ os_set_text_mode:
|
||||
popa
|
||||
ret
|
||||
|
||||
; -------------------------------------------
|
||||
|
||||
; AX = key pressed
|
||||
os_read_input:
|
||||
mov ah, 11h ; BIOS call to check for key
|
||||
int 16h ; Interrupt
|
||||
jnz .key_pressed ; Jump if input isn't 0
|
||||
|
||||
hlt
|
||||
jmp os_read_input
|
||||
|
||||
.key_pressed:
|
||||
mov ah, 10h
|
||||
int 16h
|
||||
ret
|
||||
|
||||
; -------------------------------------------
|
||||
|
||||
os_display_input:
|
||||
pusha
|
||||
mov cx, [prompt_length]
|
||||
|
||||
.loop:
|
||||
call .check_key_pressed
|
||||
|
||||
jmp .loop
|
||||
|
||||
.check_key_pressed:
|
||||
call os_read_input
|
||||
|
||||
cmp al, 08h
|
||||
je .backspace
|
||||
|
||||
cmp al, 0Dh
|
||||
je .enter_key
|
||||
|
||||
cmp al, 1Bh
|
||||
je .esc_key
|
||||
|
||||
cmp cx, 0
|
||||
jb .check_key_pressed
|
||||
|
||||
call .print_current_input
|
||||
dec cx
|
||||
jmp .check_key_pressed
|
||||
|
||||
.esc_key:
|
||||
call os_reboot
|
||||
|
||||
.enter_key:
|
||||
mov al, 0
|
||||
stosb
|
||||
popa
|
||||
call os_read_cli
|
||||
|
||||
.backspace:
|
||||
call .move_cursor_back ; then .move_cursor_back
|
||||
call .loop ; Else .loop
|
||||
|
||||
.move_cursor_back:
|
||||
mov ah, 0Eh
|
||||
|
||||
mov al, 08h
|
||||
int 10h
|
||||
mov al, 20h
|
||||
int 10h
|
||||
mov al, 08h
|
||||
int 10h
|
||||
|
||||
dec di
|
||||
jmp os_display_input
|
||||
|
||||
.print_current_input:
|
||||
stosb
|
||||
|
||||
mov ah, 0Eh
|
||||
int 10h
|
||||
|
||||
ret
|
||||
@@ -1,5 +1,5 @@
|
||||
game_pong:
|
||||
call .draw_players
|
||||
call .draw_screen
|
||||
call .detect_input
|
||||
|
||||
; Clears screen and draws both players and ball
|
||||
@@ -29,6 +29,18 @@ game_pong:
|
||||
mov [y_end], bx
|
||||
|
||||
call os_draw_graphical_rectangle ; Draw player 1
|
||||
.draw_ball:
|
||||
; The ball
|
||||
mov ax, [ball_x]
|
||||
mov [x_start], ax
|
||||
mov [x_end], ax
|
||||
|
||||
mov bx, [ball_y]
|
||||
mov [y_start], bx
|
||||
mov [y_end], bx
|
||||
|
||||
call os_draw_graphical_rectangle ; Draw the ball
|
||||
|
||||
ret
|
||||
|
||||
; Player 1 movements
|
||||
@@ -36,13 +48,11 @@ game_pong:
|
||||
mov dx, [p1_y]
|
||||
sub dx, 5
|
||||
mov [p1_y], dx
|
||||
call .draw_players
|
||||
jmp .detect_input
|
||||
.p1_down:
|
||||
mov dx, [p1_y]
|
||||
add dx, 5
|
||||
mov [p1_y], dx
|
||||
call .draw_players
|
||||
jmp .detect_input
|
||||
|
||||
; Player 2 movements
|
||||
@@ -50,18 +60,35 @@ game_pong:
|
||||
mov dx, [p2_y]
|
||||
sub dx, 5
|
||||
mov [p2_y], dx
|
||||
call .draw_players
|
||||
jmp .detect_input
|
||||
.p2_down:
|
||||
mov dx, [p2_y]
|
||||
add dx, 5
|
||||
mov [p2_y], dx
|
||||
call .draw_players
|
||||
jmp .detect_input
|
||||
|
||||
; Ball bouncing
|
||||
; This should move the ball along one frame
|
||||
; The ball moves 1 pixel per frame, however this is usually
|
||||
; at an angle, so we need sin and cos
|
||||
.bounce_ball:
|
||||
; Change the x coords
|
||||
fld dword [ball_angle]
|
||||
fcos
|
||||
fld dword [precise_ball_x]
|
||||
faddp
|
||||
frndint
|
||||
fstp dword [ball_x]
|
||||
|
||||
; Change the y coords
|
||||
fld dword [ball_angle]
|
||||
fsin
|
||||
fld dword [precise_ball_y]
|
||||
faddp
|
||||
frndint
|
||||
fstp dword [ball_y]
|
||||
|
||||
ret
|
||||
|
||||
.detect_input:
|
||||
call os_read_input
|
||||
@@ -80,6 +107,9 @@ game_pong:
|
||||
cmp al, 27h ; Pressed ''' (player 2 down)
|
||||
je .p2_down
|
||||
|
||||
call .bounce_ball
|
||||
call .draw_screen
|
||||
|
||||
jmp .detect_input
|
||||
|
||||
.finish:
|
||||
@@ -87,8 +117,13 @@ game_pong:
|
||||
call os_start_cli
|
||||
|
||||
section .data
|
||||
ball_x dw 5
|
||||
ball_y dw 5
|
||||
ball_x dw 100
|
||||
ball_y dw 100
|
||||
precise_ball_x dw 100
|
||||
precise_ball_y dw 100
|
||||
ball_angle dw 1 ; In radians
|
||||
cos_ball_angle dw 0
|
||||
sin_ball_angle dw 0
|
||||
|
||||
p1_x dw 5
|
||||
p1_y dw 5
|
||||
94
source/kernel/games/snake.asm
Normal file
94
source/kernel/games/snake.asm
Normal file
@@ -0,0 +1,94 @@
|
||||
game_snake:
|
||||
call .draw_screen
|
||||
call .detect_input
|
||||
|
||||
.draw_screen:
|
||||
call os_set_graphics_mode ; Clear screen
|
||||
.draw_snake_loop:
|
||||
mov ax, [snake_x]
|
||||
mov [x_start], ax
|
||||
mov [x_end], ax
|
||||
|
||||
mov bx, [snake_y]
|
||||
mov [y_start], bx
|
||||
mov [y_end], bx
|
||||
|
||||
call os_draw_graphical_rectangle
|
||||
ret
|
||||
|
||||
; Player 1 movements
|
||||
.up:
|
||||
mov dword [snake_direction], 0
|
||||
jmp .end_detect_input
|
||||
.down:
|
||||
mov dword [snake_direction], 2
|
||||
jmp .end_detect_input
|
||||
.left:
|
||||
mov dword [snake_direction], 3
|
||||
jmp .end_detect_input
|
||||
.right:
|
||||
mov dword [snake_direction], 1
|
||||
jmp .end_detect_input
|
||||
|
||||
.move_up:
|
||||
mov dx, [snake_y]
|
||||
sub dx, 1
|
||||
mov [snake_y], dx
|
||||
ret
|
||||
.move_down:
|
||||
mov dx, [snake_y]
|
||||
add dx, 1
|
||||
mov [snake_y], dx
|
||||
ret
|
||||
.move_left:
|
||||
mov dx, [snake_x]
|
||||
sub dx, 1
|
||||
mov [snake_x], dx
|
||||
ret
|
||||
.move_right:
|
||||
mov dx, [snake_x]
|
||||
add dx, 1
|
||||
mov [snake_x], dx
|
||||
ret
|
||||
|
||||
.move_snake:
|
||||
cmp dword [snake_direction], 0
|
||||
je .move_up
|
||||
cmp dword [snake_direction], 1
|
||||
je .move_right
|
||||
cmp dword [snake_direction], 2
|
||||
je .move_down
|
||||
; Else it must be left
|
||||
jmp .move_left
|
||||
|
||||
|
||||
.detect_input:
|
||||
call os_read_input
|
||||
cmp al, 08h
|
||||
je .finish
|
||||
|
||||
; Player 1
|
||||
cmp al, 77h ; Pressed 'w' up
|
||||
je .up
|
||||
cmp al, 61h ; Pressed 'a' left
|
||||
je .left
|
||||
cmp al, 73h ; Pressed 's' down
|
||||
je .down
|
||||
cmp al, 64h ; Pressed 'd' right
|
||||
je .right
|
||||
.end_detect_input:
|
||||
call .move_snake
|
||||
call .draw_screen
|
||||
|
||||
jmp .detect_input
|
||||
|
||||
.finish:
|
||||
call os_set_text_mode
|
||||
call os_start_cli
|
||||
|
||||
|
||||
section .data:
|
||||
snake_x: dw 5
|
||||
snake_y: dw 5
|
||||
snake_direction: dw 1 ; 0=up, 1=right, 2=down, 3=left
|
||||
snake_length: dw 1
|
||||
32
source/kernel/kernel.asm
Normal file
32
source/kernel/kernel.asm
Normal file
@@ -0,0 +1,32 @@
|
||||
ORG 0h
|
||||
BITS 16
|
||||
|
||||
start:
|
||||
mov si, boot_message
|
||||
call os_print_string_nl
|
||||
|
||||
mov si, help_text
|
||||
call os_print_string_nl
|
||||
|
||||
call os_start_cli
|
||||
hlt
|
||||
|
||||
halt:
|
||||
jmp halt
|
||||
|
||||
boot_message: db 0Dh, 'Welcome to CrawOS!', 0Dh, 0
|
||||
|
||||
; ------------------------------------------------------------------
|
||||
; FEATURES -- Code to pull into the kernel
|
||||
%INCLUDE "source/kernel/features/text.asm"
|
||||
%INCLUDE "source/kernel/features/keyboard.asm"
|
||||
%INCLUDE "source/kernel/features/cli.asm"
|
||||
%INCLUDE "source/kernel/features/power.asm"
|
||||
%INCLUDE "source/kernel/features/strings.asm"
|
||||
%INCLUDE "source/kernel/features/graphics.asm"
|
||||
%INCLUDE "source/kernel/features/sound.asm"
|
||||
%INCLUDE "source/kernel/features/basic.asm"
|
||||
%INCLUDE "source/kernel/features/math.asm"
|
||||
; GAMES -- Games that I wrote for it
|
||||
%INCLUDE "source/kernel/games/pong.asm"
|
||||
%INCLUDE "source/kernel/games/snake.asm"
|
||||
Reference in New Issue
Block a user