Compare commits
5 Commits
44e4447d21
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 0222a7adb9 | |||
| 7906c48a2e | |||
| 015d4d1fce | |||
| d83871e161 | |||
| 0b9014d846 |
BIN
.Makefile.swo
Normal file
BIN
.Makefile.swo
Normal file
Binary file not shown.
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
*.swp
|
*.swp
|
||||||
disk-images/*
|
disk_images/*
|
||||||
|
tmp-loop/*
|
||||||
|
|||||||
8
Makefile
8
Makefile
@@ -7,12 +7,16 @@ DATA_DIR=data
|
|||||||
# CD image
|
# CD image
|
||||||
cdrom: $(BUILD_DIR)/crawos.iso
|
cdrom: $(BUILD_DIR)/crawos.iso
|
||||||
$(BUILD_DIR)/crawos.iso: floppy_image
|
$(BUILD_DIR)/crawos.iso: floppy_image
|
||||||
|
mkdir -p disk_images
|
||||||
mkisofs -quiet -V 'CRAWOS' -input-charset iso8859-1 -o disk_images/crawos.iso -b crawos.img disk_images/
|
mkisofs -quiet -V 'CRAWOS' -input-charset iso8859-1 -o disk_images/crawos.iso -b crawos.img disk_images/
|
||||||
|
chmod 755 disk_images/*
|
||||||
|
chgrp users disk_images/*
|
||||||
|
|
||||||
# Floppy image
|
# Floppy image
|
||||||
# Fat12
|
# Fat12
|
||||||
floppy_image: $(BUILD_DIR)/crawos.img
|
floppy_image: $(BUILD_DIR)/crawos.img
|
||||||
$(BUILD_DIR)/crawos.img: bootloader kernel
|
$(BUILD_DIR)/crawos.img: bootloader kernel
|
||||||
|
mkdir -p disk_images
|
||||||
dd if=/dev/zero of=$(BUILD_DIR)/crawos.img bs=512 count=2880 # Use dd to make a disk image
|
dd if=/dev/zero of=$(BUILD_DIR)/crawos.img bs=512 count=2880 # Use dd to make a disk image
|
||||||
mkfs.fat -F 12 -n "CRAWOS" $(BUILD_DIR)/crawos.img # Format the disk image with fat12
|
mkfs.fat -F 12 -n "CRAWOS" $(BUILD_DIR)/crawos.img # Format the disk image with fat12
|
||||||
dd if=$(BUILD_DIR)/boot.bin of=$(BUILD_DIR)/crawos.img conv=notrunc # Put boot.bin inside the disk image
|
dd if=$(BUILD_DIR)/boot.bin of=$(BUILD_DIR)/crawos.img conv=notrunc # Put boot.bin inside the disk image
|
||||||
@@ -23,13 +27,15 @@ $(BUILD_DIR)/crawos.img: bootloader kernel
|
|||||||
# Bootloader
|
# Bootloader
|
||||||
bootloader: $(BUILD_DIR)/boot.bin
|
bootloader: $(BUILD_DIR)/boot.bin
|
||||||
$(BUILD_DIR)/boot.bin:
|
$(BUILD_DIR)/boot.bin:
|
||||||
|
mkdir -p disk_images
|
||||||
$(ASM) $(SRC_DIR)/bootload/boot.asm -f bin -o $ $(BUILD_DIR)/boot.bin
|
$(ASM) $(SRC_DIR)/bootload/boot.asm -f bin -o $ $(BUILD_DIR)/boot.bin
|
||||||
|
|
||||||
# Kernel
|
# Kernel
|
||||||
kernel: $(BUILD_DIR)/kernel.bin
|
kernel: $(BUILD_DIR)/kernel.bin
|
||||||
$(BUILD_DIR)/kernel.bin:
|
$(BUILD_DIR)/kernel.bin:
|
||||||
|
mkdir -p disk_images
|
||||||
$(ASM) $(SRC_DIR)/kernel/kernel.asm -f bin -o $ $(BUILD_DIR)/kernel.bin
|
$(ASM) $(SRC_DIR)/kernel/kernel.asm -f bin -o $ $(BUILD_DIR)/kernel.bin
|
||||||
|
|
||||||
# Clean
|
# Clean
|
||||||
clean:
|
clean:
|
||||||
rm -f disk-images/*
|
rm -f disk_images/*
|
||||||
|
|||||||
@@ -5,27 +5,27 @@ jmp short main
|
|||||||
nop
|
nop
|
||||||
|
|
||||||
; Define Fat12 header
|
; Define Fat12 header
|
||||||
bdb_oem: db 'MSWIN4.1'
|
bdb_oem: db 'MSWIN4.1' ; ignore
|
||||||
bdb_bytes_per_sector: dw 512
|
bdb_bytes_per_sector: dw 200h ; = 512d
|
||||||
bdb_sectors_per_cluster: db 1
|
bdb_sectors_per_cluster: db 01h ; sector = cluster
|
||||||
bdb_reserved_sectors: dw 1
|
bdb_reserved_sectors: dw 01h
|
||||||
bdb_fat_count: db 2
|
bdb_fat_count: db 02h ; We've got a fat1 and fat2
|
||||||
bdb_dir_entries_count: dw 0E0h
|
bdb_dir_entries_count: dw 0E0h ; Maximum number of root directory entries
|
||||||
bdb_total_sectors: dw 2880
|
bdb_total_sectors: dw 0B40h ; = 2880d
|
||||||
bdb_media_descriptor_type: db 0F0h
|
bdb_media_descriptor_type: db 0F0h ; ignore
|
||||||
bdb_sectors_per_fat: dw 9
|
bdb_sectors_per_fat: dw 09h
|
||||||
bdb_sectors_per_track: dw 18
|
bdb_sectors_per_track: dw 12h ; = 18d
|
||||||
bdb_heads: dw 2
|
bdb_number_of_heads: dw 02h ; top and bottom of the floppy disk
|
||||||
bdb_hidden_sectors: dd 0
|
bdb_hidden_sectors: dd 0 ; ignore
|
||||||
bdb_large_sector_count: dd 0
|
bdb_large_sector_count: dd 0 ; total sector count for fat32 (0 for fat12 or fat16)
|
||||||
|
|
||||||
; extended boot record
|
; extended boot record
|
||||||
ebr_drive_number: db 0
|
ebr_drive_number: db 0 ; ignore
|
||||||
db 0
|
db 0 ; ignore
|
||||||
ebr_signature: db 29h
|
ebr_signature: db 29h ; boot signature, indicates that the next three fields are present (0x29)
|
||||||
ebr_volume_id: db 12h, 34h, 56h, 78h
|
ebr_volume_id: db 12h, 34h, 56h, 78h ; unique id for volume tracking
|
||||||
ebr_volume_label: db 'CrawShaw OS'
|
ebr_volume_label: db 'CrawShaw OS' ; must be 11 bytes
|
||||||
ebr_system_id: db 'FAT12 '
|
ebr_system_id: db 'FAT12 ' ; must be 8 bytes
|
||||||
|
|
||||||
main:
|
main:
|
||||||
; Setup registers
|
; Setup registers
|
||||||
@@ -54,46 +54,54 @@ main:
|
|||||||
; root dir: gives location of data
|
; root dir: gives location of data
|
||||||
; data: stores the actual data
|
; data: stores the actual data
|
||||||
|
|
||||||
; Get LBA of root dir
|
; Get LBA of root dir (sectors per fat * fat count) + number of reserved sectors
|
||||||
mov ax, [bdb_sectors_per_fat]
|
mov ax, [bdb_sectors_per_fat] ; ax = 09h
|
||||||
mov bl, [bdb_fat_count]
|
mov bl, [bdb_fat_count] ; bl = 02h
|
||||||
xor bh,bh ; clear bh
|
xor bh,bh ; clear bh
|
||||||
mul bx ; 9 * 2 = 18
|
mul bx ; ax*bx = sectors per fat * fat count = 09h * 02h = 18
|
||||||
add ax, [bdb_reserved_sectors] ; The LBA of root dir
|
add ax, [bdb_reserved_sectors] ; then add on the reserved sector (1) = The LBA of root dir = 19d = 13h
|
||||||
push ax ; Push to stack
|
push ax ; Push to stack
|
||||||
|
; the top of the ax stack now stores the LBA of the root directory
|
||||||
|
|
||||||
mov ax, [bdb_dir_entries_count]
|
; determine the size of the root directory
|
||||||
|
mov ax, [bdb_dir_entries_count] ; move the number of root directory entries into ax (E0h)
|
||||||
shl ax,5 ; ax *= 32 (shifting 5 times)
|
shl ax,5 ; ax *= 32 (shifting 5 times)
|
||||||
xor dx,dx ; Clear dx
|
xor dx,dx ; Clear dx (remainder)
|
||||||
div word [bdb_bytes_per_sector] ;32*num of entries)/bytes per sector
|
div word [bdb_bytes_per_sector] ;(32*num of entries)/bytes per sector = total number of sectors we need to read
|
||||||
test dx,dx ; See if there's a remainder
|
test dx,dx ; See if there's a remainder
|
||||||
jz root_dir_after
|
jz root_dir_after
|
||||||
inc ax ; Add one if there's a remainder
|
inc ax ; Add one if there's a remainder (this is like rounding up)
|
||||||
|
|
||||||
|
; read the root directory tree into memory
|
||||||
root_dir_after:
|
root_dir_after:
|
||||||
|
; read the data from the root directory from disk
|
||||||
mov cl, al
|
mov cl, al
|
||||||
pop ax ; LBA of root dir
|
pop ax ; LBA of root dir
|
||||||
mov dl, [ebr_drive_number]
|
mov dl, [ebr_drive_number]
|
||||||
mov bx, buffer
|
mov bx, buffer
|
||||||
call disk_read
|
call disk_read ; convert the LBA of the root directory to a CHS
|
||||||
|
|
||||||
xor bx,bx ; clear bx
|
xor bx,bx ; clear bx
|
||||||
mov di, buffer ; Loaded root dir into memory
|
mov di, buffer ; Loaded root dir into memory, now we need to find the kernel
|
||||||
|
; di points to the start of this memory
|
||||||
|
|
||||||
|
; Search for 'KERNEL BIN' in a loop until all root files entries have been checked
|
||||||
search_for_kernel:
|
search_for_kernel:
|
||||||
mov si, file_kernel_bin ; Move the name of the kernel into si
|
mov si, file_kernel_bin ; Move the name of the kernel into si (string pointer)
|
||||||
mov cx, 11
|
mov cx, 11 ; length of 'KERNEL BIN'
|
||||||
push di ; Preserve di
|
push di ; Preserve di
|
||||||
repe cmpsb ; Repeat a comparison of bytes between kernel name and current bytes until it finds a match
|
repe cmpsb ; Repeat a comparison of bytes between kernel name and current bytes until it finds a match
|
||||||
pop di ; Retrieve di
|
pop di ; Retrieve di
|
||||||
je found_kernel
|
je found_kernel
|
||||||
|
|
||||||
add di, 32 ; Next directory entry
|
add di, 32 ; increment di to the next directory entry
|
||||||
inc bx
|
inc bx
|
||||||
cmp bx, [bdb_dir_entries_count] ; Have we reached the number of directories that exist
|
cmp bx, [bdb_dir_entries_count] ; Have we reached the number of directories that exist
|
||||||
jl search_for_kernel ; Repeat search
|
jl search_for_kernel ; Repeat search
|
||||||
|
|
||||||
jmp kernel_not_found ; If the last dir has been searched, then there is no kernel
|
jmp kernel_not_found ; If the last dir has been searched, then there is no kernel
|
||||||
|
|
||||||
|
; The kernel has not been found so output an error and halt
|
||||||
kernel_not_found:
|
kernel_not_found:
|
||||||
mov si, kernel_load_error
|
mov si, kernel_load_error
|
||||||
call print_string
|
call print_string
|
||||||
@@ -101,13 +109,15 @@ kernel_not_found:
|
|||||||
hlt
|
hlt
|
||||||
jmp halt
|
jmp halt
|
||||||
|
|
||||||
|
; The kernel has been found
|
||||||
found_kernel:
|
found_kernel:
|
||||||
mov si, kernel_found_text
|
mov si, kernel_found_text
|
||||||
call print_string
|
call print_string
|
||||||
; Find kernel cluster
|
; Find kernel cluster
|
||||||
mov ax, [di+26]
|
mov ax, [di+26] ; di is the address of the kernel, 26 is the offset
|
||||||
mov [kernel_cluster], ax
|
mov [kernel_cluster], ax
|
||||||
|
|
||||||
|
; Setup registers for disk read
|
||||||
mov ax, [bdb_reserved_sectors]
|
mov ax, [bdb_reserved_sectors]
|
||||||
mov bx, buffer
|
mov bx, buffer
|
||||||
mov cl, [bdb_sectors_per_fat]
|
mov cl, [bdb_sectors_per_fat]
|
||||||
@@ -160,6 +170,8 @@ next_cluster_after:
|
|||||||
jmp load_kernel_loop
|
jmp load_kernel_loop
|
||||||
|
|
||||||
read_finish: ; Load kernel
|
read_finish: ; Load kernel
|
||||||
|
mov si, kernel_loading
|
||||||
|
call print_string
|
||||||
mov dl, [ebr_drive_number]
|
mov dl, [ebr_drive_number]
|
||||||
mov ax, kernel_load_segment
|
mov ax, kernel_load_segment
|
||||||
mov ds, ax
|
mov ds, ax
|
||||||
@@ -174,10 +186,35 @@ halt:
|
|||||||
|
|
||||||
; LBA = index of data segment on disk
|
; LBA = index of data segment on disk
|
||||||
; CHS = cylinder, header, sector
|
; CHS = cylinder, header, sector
|
||||||
|
; T = LBA/sectors per track
|
||||||
|
; S = (LBA%sectors per track) + 1
|
||||||
|
; H = T % heads
|
||||||
|
; C = T / headers
|
||||||
; input, LBA index: ax
|
; input, LBA index: ax
|
||||||
; sector number: cx [0-5]
|
; sector number: cl
|
||||||
; cylinder: cx [6-15]
|
; cylinder: ch
|
||||||
; head: dh
|
; head: dh
|
||||||
|
; Example where LBA = 50h (CHS = 2,0,9)
|
||||||
|
; ax = 0050h, push this to the stack
|
||||||
|
; dx = 0000h
|
||||||
|
; dx = 50h % 12h = 0008h
|
||||||
|
; ax = 50h / 12h = 0004h
|
||||||
|
; dx = 0009h
|
||||||
|
; cx = 0009h
|
||||||
|
; dx = 0000h
|
||||||
|
; dx = 04h % 02h = 0000h
|
||||||
|
; ax = 04h / 02h = 0002h
|
||||||
|
; dh = 00h (dx = 0000h)
|
||||||
|
; ch = 02h (cx = 0209h)
|
||||||
|
; ah = 00h (ax = 0002h)
|
||||||
|
; cl = 09h OR 00h = 09h (cx = 0209h)
|
||||||
|
; ax = 0050h
|
||||||
|
; dl = 50h (dx = 0050h)
|
||||||
|
; ax = 0050h
|
||||||
|
; thus:
|
||||||
|
; cylinder (ch) = 02h
|
||||||
|
; head (cl) = 00h
|
||||||
|
; sector (dh) = 09h
|
||||||
lba_to_chs:
|
lba_to_chs:
|
||||||
push ax
|
push ax
|
||||||
push dx
|
push dx
|
||||||
@@ -188,19 +225,26 @@ lba_to_chs:
|
|||||||
mov cx,dx
|
mov cx,dx
|
||||||
|
|
||||||
xor dx,dx ; clear dx
|
xor dx,dx ; clear dx
|
||||||
div word [bdb_heads]
|
div word [bdb_number_of_heads]
|
||||||
|
mov dh,dl ; head, dx stores remainder so we move that up 8 bits to dh
|
||||||
|
|
||||||
mov dh,dl ; head
|
|
||||||
mov ch,al
|
mov ch,al
|
||||||
shl ah, 6
|
shl ah, 6 ; * 32
|
||||||
or CL, AH ; cylinder
|
or cl, ah ; cylinder
|
||||||
|
|
||||||
pop ax
|
pop ax
|
||||||
mov dl,al
|
mov dl,al
|
||||||
pop ax
|
pop ax
|
||||||
|
|
||||||
RET
|
ret
|
||||||
|
|
||||||
|
; int 13h/ah = 02h read disk sectors into memory
|
||||||
|
; al = number of sectors to read
|
||||||
|
; ch = cylinder number
|
||||||
|
; cl = sector number
|
||||||
|
; dh = head number
|
||||||
|
; dl = drive number
|
||||||
|
; es:bx = points to data buffer
|
||||||
disk_read:
|
disk_read:
|
||||||
push ax
|
push ax
|
||||||
push bx
|
push bx
|
||||||
@@ -209,22 +253,32 @@ disk_read:
|
|||||||
push di
|
push di
|
||||||
|
|
||||||
|
|
||||||
call lba_to_chs
|
; cl = sector
|
||||||
|
; ch = cylinder
|
||||||
|
; dh = head
|
||||||
|
; dl = drive
|
||||||
|
call lba_to_chs ; Get the chs address
|
||||||
|
|
||||||
mov ah, 02h
|
mov ah, 02h ; BIOS ah code for read disk sectors to memory
|
||||||
|
|
||||||
; repeat drive read 3 times (incase of random error)
|
; repeat drive read 3 times (incase of random error)
|
||||||
mov di, 3 ; counter
|
mov di, 3 ; counter
|
||||||
|
|
||||||
|
; This is basically
|
||||||
|
; for di in range(3,1,1):
|
||||||
|
; We test to see if we can read the disk 3 times
|
||||||
retry:
|
retry:
|
||||||
stc
|
; When the disk is tried to be read, the CF flag will be
|
||||||
|
; set if there's an error, so we just clear it to return it to
|
||||||
|
; the default state
|
||||||
|
stc ; sets the cf flag
|
||||||
int 13h
|
int 13h
|
||||||
jnc done_read
|
jnc done_read ; jump if cf = 0
|
||||||
|
|
||||||
call disk_reset ; Reset drivers of disk
|
call disk_reset ; Reset drivers of disk
|
||||||
|
|
||||||
dec di
|
dec di ; di -= 1
|
||||||
test di, di
|
test di, di ; if di = 0
|
||||||
jnz retry
|
jnz retry
|
||||||
|
|
||||||
fail_disk_read:
|
fail_disk_read:
|
||||||
@@ -233,6 +287,7 @@ fail_disk_read:
|
|||||||
hlt
|
hlt
|
||||||
jmp halt
|
jmp halt
|
||||||
|
|
||||||
|
; int 13h / ah = 00h reset disk system
|
||||||
disk_reset:
|
disk_reset:
|
||||||
pusha
|
pusha
|
||||||
mov ah, 0 ; Reset drive
|
mov ah, 0 ; Reset drive
|
||||||
@@ -280,14 +335,15 @@ print_string:
|
|||||||
pop si
|
pop si
|
||||||
ret
|
ret
|
||||||
|
|
||||||
boot_text: db '[OK] Boot sequence begun...', 0
|
boot_text: db 'OK] Boot begun', 0
|
||||||
kernel_found_text: db '[OK] Kernel located...', 0
|
kernel_found_text: db 'OK] Kernel located', 0
|
||||||
disk_read_fail: db '[ERR] Failed to read disk!', 0
|
kernel_loading: db 'OK] Loading kernel', 0
|
||||||
|
disk_read_fail: db 'ERR] Disk read fail', 0
|
||||||
file_kernel_bin: db 'KERNEL BIN' ; Must have a double space between KERNEL and BIN
|
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_load_error: db 'ERR] Kernel not found', 0
|
||||||
|
|
||||||
kernel_cluster: dw 0
|
kernel_cluster: dw 0
|
||||||
kernel_load_segment: equ 2000h
|
kernel_load_segment: equ 2000h ; an area in memory we know should be available
|
||||||
kernel_load_offset: equ 0
|
kernel_load_offset: equ 0
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,42 +17,48 @@ os_start_cli:
|
|||||||
|
|
||||||
os_read_cli:
|
os_read_cli:
|
||||||
pusha
|
pusha
|
||||||
|
mov si, user_input
|
||||||
|
call os_upper_case ; Make the input uppercase so it's case insensitive
|
||||||
|
|
||||||
.output_the_user_input:
|
.output_the_user_input:
|
||||||
call os_print_newline
|
call os_print_newline
|
||||||
|
|
||||||
.check_matches: ; Check if the user input matches any internal commands
|
.check_matches: ; Check if the user input matches any internal commands
|
||||||
|
; Help
|
||||||
mov si, user_input
|
mov si, user_input
|
||||||
mov di, help_string
|
mov di, help_string
|
||||||
call os_compare_strings
|
call os_compare_strings
|
||||||
cmp cl, 1
|
cmp cl, 1
|
||||||
je help
|
je help
|
||||||
|
|
||||||
|
; Clear screen
|
||||||
mov si, user_input
|
mov si, user_input
|
||||||
mov di, clear_string
|
mov di, clear_string
|
||||||
call os_compare_strings
|
call os_compare_strings
|
||||||
cmp cl, 1
|
cmp cl, 1
|
||||||
je clear
|
je clear
|
||||||
|
|
||||||
|
; Reboot
|
||||||
|
mov si, user_input
|
||||||
|
mov di, reboot_string
|
||||||
|
call os_compare_strings
|
||||||
|
cmp cl, 1
|
||||||
|
je power_reboot
|
||||||
|
|
||||||
|
; Pong
|
||||||
mov si, user_input
|
mov si, user_input
|
||||||
mov di, pong_string
|
mov di, pong_string
|
||||||
call os_compare_strings
|
call os_compare_strings
|
||||||
cmp cl, 1
|
cmp cl, 1
|
||||||
je pong
|
je pong
|
||||||
|
|
||||||
mov si, user_input
|
|
||||||
mov di, snake_string
|
|
||||||
call os_compare_strings
|
|
||||||
cmp cl, 1
|
|
||||||
je snake
|
|
||||||
|
|
||||||
jmp .unkown
|
jmp .unkown
|
||||||
|
|
||||||
.unkown:
|
.unkown:
|
||||||
mov si, unknown_command
|
mov si, unknown_command
|
||||||
call os_print_string
|
call os_print_string
|
||||||
mov si, user_input
|
mov si, user_input
|
||||||
call os_print_string_nl
|
call os_print_string
|
||||||
jmp .finish
|
jmp .finish
|
||||||
|
|
||||||
.finish:
|
.finish:
|
||||||
@@ -65,26 +71,23 @@ clear:
|
|||||||
|
|
||||||
help:
|
help:
|
||||||
mov si, help_text
|
mov si, help_text
|
||||||
call os_print_string_nl
|
call os_print_string
|
||||||
call os_read_cli.finish
|
call os_read_cli.finish
|
||||||
|
|
||||||
pong:
|
pong:
|
||||||
call game_pong
|
call game_pong
|
||||||
call os_read_cli.finish
|
call os_read_cli.finish
|
||||||
|
|
||||||
snake:
|
|
||||||
call game_snake
|
|
||||||
call os_read_cli.finish
|
|
||||||
|
|
||||||
section .data
|
section .data
|
||||||
welcome_text db 'Welcome to CrawOS, the Cool, Real and AWsome Operating System', 0
|
welcome_text db 'Welcome to CrawOS, the Cwick, Real and AWsome Operating System\n', 0
|
||||||
user_input times 20 db 0
|
user_input times 20 db 0
|
||||||
prompt_length db 20
|
prompt_length db 20
|
||||||
prompt db 'CrawOS sh> ', 0
|
prompt db 'CrawOS sh> ', 0
|
||||||
help_string db 'HELP', 0
|
help_string db 'HELP', 0
|
||||||
clear_string db 'CLEAR', 0
|
clear_string db 'CLEAR', 0
|
||||||
|
reboot_string db 'REBOOT', 0
|
||||||
|
cat_string db 'CAT', 0
|
||||||
pong_string db 'PONG', 0
|
pong_string db 'PONG', 0
|
||||||
snake_string db 'SNAKE', 0
|
help_text db 'This is for Cowards:\n"HELP" for this helpful text,\n"CLEAR" to clear the screen,\n"REBOOT" or esc to reboot\n', 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
|
command_result_text db 'You typed: ', 0
|
||||||
unknown_command db 'Error: Unkown Command.. ', 0
|
unknown_command db 'Error: Unkown Command.. \n', 0
|
||||||
|
|||||||
@@ -0,0 +1,175 @@
|
|||||||
|
; Reset the disk system using int 13h / AH = 00h
|
||||||
|
disk_reset:
|
||||||
|
pusha
|
||||||
|
stc
|
||||||
|
mov ah, 00h
|
||||||
|
int 13h
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
; ------------------------------------
|
||||||
|
|
||||||
|
; Load the root directory into memory (into disk_buffer which is 24000h)
|
||||||
|
disk_load_root:
|
||||||
|
pusha
|
||||||
|
mov ax, 19 ; First sector of root entry
|
||||||
|
call math_lba_to_chs ; Assigns ch, cl and dh the correct values
|
||||||
|
xor ax,ax
|
||||||
|
mov dl, [ebr_drive_number] ; Drive number
|
||||||
|
mov ah, 02h ; BIOS ah code for read disk sectors to memory
|
||||||
|
mov al, 0Ch ; Root directory has 12 sectors
|
||||||
|
|
||||||
|
mov si, root_buffer ; ES:BX should point to our buffer
|
||||||
|
mov bx, si
|
||||||
|
|
||||||
|
; repeat drive read 3 times (incase of random error)
|
||||||
|
mov di, 3 ; counter
|
||||||
|
; This is basically
|
||||||
|
; for di in range(3,1,1):
|
||||||
|
; We test to see if we can read the disk 3 times
|
||||||
|
.try_read_disk: ; Try read the floppy three times
|
||||||
|
; When the disk is tried to be read, the CF flag will be
|
||||||
|
; set if there's an error, so we just clear it to return it to
|
||||||
|
; the default state
|
||||||
|
stc ; sets the cf flag
|
||||||
|
int 13h
|
||||||
|
jnc .done_read ; jump if cf = 0
|
||||||
|
|
||||||
|
call disk_reset ; Reset drivers of disk
|
||||||
|
|
||||||
|
dec di ; di -= 1
|
||||||
|
test di, di ; if di = 0
|
||||||
|
jnz .try_read_disk
|
||||||
|
jmp .disk_error
|
||||||
|
.disk_error:
|
||||||
|
mov si, disk_read_fail
|
||||||
|
call os_print_string
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
.done_read:
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
; ---------------------------------------------
|
||||||
|
|
||||||
|
; Reads a certain number of sectors into memory
|
||||||
|
; int 13h/ah = 02h read disk sectors into memory
|
||||||
|
; al = number of sectors to read
|
||||||
|
; ch = cylinder number
|
||||||
|
; cl = sector number
|
||||||
|
; dh = head number
|
||||||
|
; dl = drive number
|
||||||
|
; es:bx = points to data buffer
|
||||||
|
disk_read:
|
||||||
|
push ax
|
||||||
|
push bx
|
||||||
|
push cx
|
||||||
|
push dx
|
||||||
|
push di
|
||||||
|
|
||||||
|
|
||||||
|
; cl = sector
|
||||||
|
; ch = cylinder
|
||||||
|
; dh = head
|
||||||
|
; dl = drive
|
||||||
|
call math_lba_to_chs ; Get the chs address
|
||||||
|
|
||||||
|
mov ah, 02h ; BIOS ah code for read disk sectors to memory
|
||||||
|
|
||||||
|
; repeat drive read 3 times (incase of random error)
|
||||||
|
mov di, 3 ; counter
|
||||||
|
|
||||||
|
; This is basically
|
||||||
|
; for di in range(3,1,1):
|
||||||
|
; We test to see if we can read the disk 3 times
|
||||||
|
.retry:
|
||||||
|
; When the disk is tried to be read, the CF flag will be
|
||||||
|
; set if there's an error, so we just clear it to return it to
|
||||||
|
; the default state
|
||||||
|
stc ; sets the cf flag
|
||||||
|
int 13h
|
||||||
|
jnc .done_read ; jump if cf = 0
|
||||||
|
|
||||||
|
call .disk_reset ; Reset drivers of disk
|
||||||
|
|
||||||
|
dec di ; di -= 1
|
||||||
|
test di, di ; if di = 0
|
||||||
|
jnz .retry
|
||||||
|
|
||||||
|
.fail_disk_read:
|
||||||
|
pop di
|
||||||
|
pop dx
|
||||||
|
pop cx
|
||||||
|
pop bx
|
||||||
|
pop ax
|
||||||
|
ret
|
||||||
|
|
||||||
|
; int 13h / ah = 00h reset disk system
|
||||||
|
.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
|
||||||
|
|
||||||
|
; -------------------------------------
|
||||||
|
|
||||||
|
disk_load_file:
|
||||||
|
pusha
|
||||||
|
mov di, fat12_file_name
|
||||||
|
call os_format_fat_filename
|
||||||
|
|
||||||
|
; Prepare values
|
||||||
|
mov si, root_buffer
|
||||||
|
xor bx,bx
|
||||||
|
.search_root:
|
||||||
|
mov di, fat12_file_name ; Move the name of the kernel into di
|
||||||
|
mov cx, 11 ; length of 'KERNEL BIN'
|
||||||
|
push si ; Preserve si
|
||||||
|
repe cmpsb ; Repeat a comparison of bytes between file name and current bytes until it finds a match
|
||||||
|
pop si ; Retrieve si
|
||||||
|
je .found_file
|
||||||
|
|
||||||
|
add si, 32 ; increment di to the next directory entry
|
||||||
|
inc bx
|
||||||
|
cmp bx, [bdb_dir_entries_count] ; Have we reached the number of directories that exist
|
||||||
|
jl .search_root ; Repeat search
|
||||||
|
|
||||||
|
jmp .file_not_found ; If the last dir has been searched, then there is no kernel
|
||||||
|
.found_file:
|
||||||
|
mov ax, [si+26] ; ax is now a pointer to the pointer to the file relative to the data segments :D
|
||||||
|
add ax, 20h
|
||||||
|
mov [file_cluster], ax
|
||||||
|
; Setup registers for disk read
|
||||||
|
mov bx, data_buffer
|
||||||
|
mov dl, [ebr_drive_number]
|
||||||
|
|
||||||
|
call disk_read ; Load file from disk into memory
|
||||||
|
jmp .done
|
||||||
|
.file_not_found:
|
||||||
|
mov si, file_not_found
|
||||||
|
call os_print_string
|
||||||
|
jmp .done
|
||||||
|
.done:
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
section .data:
|
||||||
|
disk_read_fail: db 'Error: Could not read disk\n', 0
|
||||||
|
file_not_found: db 'File not found\n', 0
|
||||||
|
file_found: db 'File found\n', 0
|
||||||
|
loading_root: db 'Loading root diretory\n', 0
|
||||||
|
file_cluster: dw 0
|
||||||
|
fat12_file_name: db ' '
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ os_display_input:
|
|||||||
jmp .check_key_pressed
|
jmp .check_key_pressed
|
||||||
|
|
||||||
.esc_key:
|
.esc_key:
|
||||||
call os_reboot
|
call power_reboot
|
||||||
|
|
||||||
.enter_key:
|
.enter_key:
|
||||||
mov al, 0
|
mov al, 0
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
; LBA = index of data segment on disk
|
||||||
|
; CHS = cylinder, header, sector
|
||||||
|
; T = LBA/sectors per track
|
||||||
|
; S = (LBA%sectors per track) + 1
|
||||||
|
; H = T % heads
|
||||||
|
; C = T / headers
|
||||||
|
; input, LBA index: ax
|
||||||
|
; ouput:
|
||||||
|
; sector number: cl
|
||||||
|
; cylinder: ch
|
||||||
|
; head: dh
|
||||||
|
; Example where LBA = 50h (CHS = 2,0,9)
|
||||||
|
; ax = 0050h, push this to the stack
|
||||||
|
; dx = 0000h
|
||||||
|
; dx = 50h % 12h = 0008h
|
||||||
|
; ax = 50h / 12h = 0004h
|
||||||
|
; dx = 0009h
|
||||||
|
; cx = 0009h
|
||||||
|
; dx = 0000h
|
||||||
|
; dx = 04h % 02h = 0000h
|
||||||
|
; ax = 04h / 02h = 0002h
|
||||||
|
; dh = 00h (dx = 0000h)
|
||||||
|
; ch = 02h (cx = 0209h)
|
||||||
|
; ah = 00h (ax = 0002h)
|
||||||
|
; cl = 09h OR 00h = 09h (cx = 0209h)
|
||||||
|
; ax = 0050h
|
||||||
|
; dl = 50h (dx = 0050h)
|
||||||
|
; ax = 0050h
|
||||||
|
; thus:
|
||||||
|
; cylinder (ch) = 02h
|
||||||
|
; head (cl) = 00h
|
||||||
|
; sector (dh) = 09h
|
||||||
|
math_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_number_of_heads]
|
||||||
|
mov dh,dl ; head, dx stores remainder so we move that up 8 bits to dh
|
||||||
|
|
||||||
|
mov ch,al
|
||||||
|
shl ah, 6 ; * 32
|
||||||
|
or cl, ah ; cylinder
|
||||||
|
|
||||||
|
pop ax
|
||||||
|
mov dl,al
|
||||||
|
pop ax
|
||||||
|
|
||||||
|
ret
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
os_reboot:
|
power_reboot:
|
||||||
mov ax, 0x5307
|
mov ax, 0x5307
|
||||||
mov bx, 0x0001
|
mov bx, 0x0001
|
||||||
mov cx, 0x0003
|
mov cx, 0x0003
|
||||||
int 0x19
|
int 0x19
|
||||||
|
|
||||||
|
; Not done
|
||||||
|
power_shutdown:
|
||||||
|
ret
|
||||||
|
|||||||
@@ -6,21 +6,125 @@
|
|||||||
; memory address 2: |s|n|a|k|e|0|
|
; memory address 2: |s|n|a|k|e|0|
|
||||||
; ^
|
; ^
|
||||||
; SI => lodsb loads value stored at SI to AX and then increments SI if DF is 0
|
; SI => lodsb loads value stored at SI to AX and then increments SI if DF is 0
|
||||||
|
; Additionaly, if the di string ends and the relevant character in si contains a space, it will still return
|
||||||
|
; the strings as being equal, this is to allow for command line arquments
|
||||||
os_compare_strings:
|
os_compare_strings:
|
||||||
cld
|
cld
|
||||||
|
|
||||||
.compare:
|
.compare:
|
||||||
|
mov al, 0
|
||||||
|
scasb
|
||||||
|
je .di_ended
|
||||||
|
dec di
|
||||||
lodsb
|
lodsb
|
||||||
scasb ; Compare di to si
|
scasb ; Compare di to si
|
||||||
jne .unequal ; If they are no equal, jump to .unequal
|
jne .unequal ; If they are not equal, jump to .unequal
|
||||||
cmp al, 0 ; Check if string is finished
|
|
||||||
je .equal ; If it has, return true
|
|
||||||
jmp .compare ; Finally, repeat
|
jmp .compare ; Finally, repeat
|
||||||
|
|
||||||
.unequal:
|
.unequal:
|
||||||
mov cl, 0 ; Change to 0 if unquality is proven
|
mov cl, 0 ; Change to 0 if unquality is proven
|
||||||
ret
|
ret
|
||||||
|
.di_ended:
|
||||||
|
lodsb
|
||||||
|
cmp al, 20h ; 20h = space
|
||||||
|
je .equal
|
||||||
|
cmp al, 0
|
||||||
|
je .equal
|
||||||
|
jmp .unequal
|
||||||
.equal:
|
.equal:
|
||||||
mov cl, 1
|
mov cl, 1
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
; Get the length of a string
|
||||||
|
; 'hello world', 0 is 11 characters long (excluding the terminator)
|
||||||
|
; input: si points to the string to be counted
|
||||||
|
; output: cl holds the length
|
||||||
|
os_string_length:
|
||||||
|
push si
|
||||||
|
xor cl,cl ; Clear the al register
|
||||||
|
.loop:
|
||||||
|
lodsb
|
||||||
|
cmp al, 0
|
||||||
|
je .finish
|
||||||
|
inc cl
|
||||||
|
jmp .loop
|
||||||
|
.finish:
|
||||||
|
pop si
|
||||||
|
ret
|
||||||
|
|
||||||
|
; convert a string to fat's filename format
|
||||||
|
; It will be capitalised and 11 characters long,
|
||||||
|
; 8 for the filename, 3 for the extension
|
||||||
|
; eg: 'file.txt' -> 'FILE TXT'
|
||||||
|
; input: si points to filename, di points to a free 11 bytes in memory
|
||||||
|
; output: di points to the fat formatted filename
|
||||||
|
os_format_fat_filename:
|
||||||
|
pusha
|
||||||
|
call os_upper_case
|
||||||
|
call os_string_length ; Stores the length of the string in cl
|
||||||
|
mov bl, 11
|
||||||
|
sub bl, cl ; 11 - string_length
|
||||||
|
.character_loop:
|
||||||
|
lodsb
|
||||||
|
cmp al, 0
|
||||||
|
je .finish
|
||||||
|
cmp al, 2Eh ; 2Eh
|
||||||
|
je .add_spaces ; This will end up back at .character_loop
|
||||||
|
stosb
|
||||||
|
jmp .character_loop
|
||||||
|
|
||||||
|
.add_spaces: ; Add the number of spaces as bl holds
|
||||||
|
mov al, ' ' ; 20h = space
|
||||||
|
.spaces_loop:
|
||||||
|
stosb
|
||||||
|
cmp bl, 0
|
||||||
|
je .character_loop
|
||||||
|
dec bl
|
||||||
|
jmp .spaces_loop
|
||||||
|
.finish:
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
; Convert a string to all upper/lower case
|
||||||
|
; INPUT: si pointing to a string
|
||||||
|
; OUPUT: the same string in memory will now be capitalised/decapitalised
|
||||||
|
os_upper_case: ; to upper case
|
||||||
|
pusha
|
||||||
|
mov di, si
|
||||||
|
.loop:
|
||||||
|
lodsb ; Load the character into al
|
||||||
|
inc di
|
||||||
|
cmp al, 0
|
||||||
|
je .finish ; If it's null then the string is finished
|
||||||
|
cmp al, 7Ah ; 7Ah = 'z'
|
||||||
|
jns .loop ; Ignore if it's more than 'z'
|
||||||
|
cmp al, 61h ; 61h = 'a'
|
||||||
|
js .loop ; Ignore if it's less than 'a'
|
||||||
|
sub al, 20h ; Otherwise subtract 20h to capitalise it
|
||||||
|
dec di
|
||||||
|
stosb ; Store the new value
|
||||||
|
jmp .loop ; Next character
|
||||||
|
.finish:
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
os_lower_case: ; to lower case
|
||||||
|
pusha
|
||||||
|
mov di, si
|
||||||
|
.loop:
|
||||||
|
lodsb ; Load the character into al
|
||||||
|
inc di
|
||||||
|
cmp al, 0
|
||||||
|
je .finish ; If it's null then the string is finished
|
||||||
|
cmp al, 5Ah ; 5Ah = 'Z'
|
||||||
|
jns .loop ; Ignore if it's more than 'Z'
|
||||||
|
cmp al, 41h ; 41h = 'A'
|
||||||
|
js .loop ; Ignore if it's less than 'A'
|
||||||
|
add al, 20h ; Otherwise subtract 20h to capitalise it
|
||||||
|
dec di
|
||||||
|
stosb ; Store the new value
|
||||||
|
jmp .loop ; Next character
|
||||||
|
.finish:
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
; SI = pointer to start of string to be printed
|
; SI = pointer to start of string to be printed
|
||||||
|
; \n for newline
|
||||||
|
; \t for tab
|
||||||
|
; \\ for a single backslash
|
||||||
os_print_string:
|
os_print_string:
|
||||||
pusha
|
pusha
|
||||||
|
|
||||||
@@ -8,34 +11,68 @@ os_print_string:
|
|||||||
lodsb ; Get char from si into al
|
lodsb ; Get char from si into al
|
||||||
cmp al, 0 ; Compare al to 0
|
cmp al, 0 ; Compare al to 0
|
||||||
je .done ; If char is zero, end of string
|
je .done ; If char is zero, end of string
|
||||||
|
cmp al, 5Ch ; backslash
|
||||||
|
je .backslash
|
||||||
|
|
||||||
int 10h ; Otherwise, print it
|
int 10h ; Otherwise, print it
|
||||||
jmp .repeat ; And move on to next char
|
jmp .repeat ; And move on to next char
|
||||||
|
|
||||||
|
.backslash: ; If there is a '\', do what it says, \n for newline, \t for tab etc
|
||||||
|
lodsb
|
||||||
|
dec si
|
||||||
|
cmp al, 6Eh ; 'n'
|
||||||
|
je .newline
|
||||||
|
cmp al, 74h ; \t
|
||||||
|
je .tab
|
||||||
|
cmp al, 5Ch ; '\'
|
||||||
|
je .another_backslash
|
||||||
|
jmp .repeat
|
||||||
|
.newline:
|
||||||
|
mov al, 0Ah ; new line
|
||||||
|
int 10h
|
||||||
|
mov al, 0Dh ; carriage return
|
||||||
|
int 10h
|
||||||
|
jmp .finish_backslash
|
||||||
|
.tab:
|
||||||
|
mov al, 09h ; tab
|
||||||
|
int 10h
|
||||||
|
jmp .finish_backslash
|
||||||
|
.another_backslash: ; This just prints 1 backslash
|
||||||
|
mov al, 5Ch
|
||||||
|
int 10h
|
||||||
|
jmp .finish_backslash
|
||||||
|
.finish_backslash:
|
||||||
|
inc si
|
||||||
|
jmp .repeat
|
||||||
.done:
|
.done:
|
||||||
popa
|
popa
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Exact same as the above procedure, but this adds a newline
|
; This is similar to the previous, however it prints
|
||||||
; after priting, similar to the difference between Rust's print! and println!
|
; raw output (including null) and prints the number
|
||||||
os_print_string_nl:
|
; of character defined by ax
|
||||||
|
; IN:
|
||||||
|
; SI = pointer to start of string to be printed
|
||||||
|
; AX = Length of string to print
|
||||||
|
text_raw_output:
|
||||||
pusha
|
pusha
|
||||||
|
|
||||||
|
mov di, ax
|
||||||
|
|
||||||
mov ah, 0Eh ; int 10h teletype function, we're telling the BIOS we will print something
|
mov ah, 0Eh ; int 10h teletype function, we're telling the BIOS we will print something
|
||||||
|
|
||||||
.repeat:
|
.repeat:
|
||||||
lodsb ; Get char from si into al
|
lodsb ; Get char from si into al
|
||||||
cmp al, 0 ; Compare al to 0
|
|
||||||
je .done ; If char is zero, end of string
|
|
||||||
|
|
||||||
int 10h ; Otherwise, print it
|
int 10h ; Otherwise, print it
|
||||||
jmp .repeat ; And move on to next char
|
dec di
|
||||||
|
cmp di, 00h
|
||||||
|
je .done
|
||||||
|
jne .repeat
|
||||||
.done:
|
.done:
|
||||||
call os_print_newline
|
|
||||||
popa
|
popa
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
; --------------------------------------------
|
; --------------------------------------------
|
||||||
|
|
||||||
os_print_newline:
|
os_print_newline:
|
||||||
|
|||||||
@@ -48,24 +48,24 @@ game_pong:
|
|||||||
mov dx, [p1_y]
|
mov dx, [p1_y]
|
||||||
sub dx, 5
|
sub dx, 5
|
||||||
mov [p1_y], dx
|
mov [p1_y], dx
|
||||||
jmp .detect_input
|
ret
|
||||||
.p1_down:
|
.p1_down:
|
||||||
mov dx, [p1_y]
|
mov dx, [p1_y]
|
||||||
add dx, 5
|
add dx, 5
|
||||||
mov [p1_y], dx
|
mov [p1_y], dx
|
||||||
jmp .detect_input
|
ret
|
||||||
|
|
||||||
; Player 2 movements
|
; Player 2 movements
|
||||||
.p2_up:
|
.p2_up:
|
||||||
mov dx, [p2_y]
|
mov dx, [p2_y]
|
||||||
sub dx, 5
|
sub dx, 5
|
||||||
mov [p2_y], dx
|
mov [p2_y], dx
|
||||||
jmp .detect_input
|
ret
|
||||||
.p2_down:
|
.p2_down:
|
||||||
mov dx, [p2_y]
|
mov dx, [p2_y]
|
||||||
add dx, 5
|
add dx, 5
|
||||||
mov [p2_y], dx
|
mov [p2_y], dx
|
||||||
jmp .detect_input
|
ret
|
||||||
|
|
||||||
; Ball bouncing
|
; Ball bouncing
|
||||||
; This should move the ball along one frame
|
; This should move the ball along one frame
|
||||||
@@ -97,17 +97,17 @@ game_pong:
|
|||||||
|
|
||||||
; Player 1
|
; Player 1
|
||||||
cmp al, 77h ; Pressed 'w' (player 1 up)
|
cmp al, 77h ; Pressed 'w' (player 1 up)
|
||||||
je .p1_up
|
call .p1_up
|
||||||
cmp al, 73h ; Pressed 's' (player 1 down)
|
cmp al, 73h ; Pressed 's' (player 1 down)
|
||||||
je .p1_down
|
call .p1_down
|
||||||
|
|
||||||
; Player 2
|
; Player 2
|
||||||
cmp al, 5bh ; Pressed '[' (player 2 up)
|
cmp al, 5bh ; Pressed '[' (player 2 up)
|
||||||
je .p2_up
|
call .p2_up
|
||||||
cmp al, 27h ; Pressed ''' (player 2 down)
|
cmp al, 27h ; Pressed ''' (player 2 down)
|
||||||
je .p2_down
|
call .p2_down
|
||||||
|
|
||||||
call .bounce_ball
|
;call .bounce_ball
|
||||||
call .draw_screen
|
call .draw_screen
|
||||||
|
|
||||||
jmp .detect_input
|
jmp .detect_input
|
||||||
|
|||||||
@@ -1,94 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,12 +1,17 @@
|
|||||||
ORG 0h
|
ORG 00h
|
||||||
BITS 16
|
BITS 16
|
||||||
|
root_buffer equ 24000h
|
||||||
|
data_buffer equ 26000h
|
||||||
|
|
||||||
start:
|
start:
|
||||||
mov si, boot_message
|
mov si, boot_message
|
||||||
call os_print_string_nl
|
call os_print_string
|
||||||
|
|
||||||
mov si, help_text
|
call disk_load_root ; Loads the root directory into disk_buffer
|
||||||
call os_print_string_nl
|
|
||||||
|
; Physical address = (segment * 16) + offset
|
||||||
|
mov si, file_name
|
||||||
|
call disk_load_file
|
||||||
|
|
||||||
call os_start_cli
|
call os_start_cli
|
||||||
hlt
|
hlt
|
||||||
@@ -14,7 +19,31 @@ start:
|
|||||||
halt:
|
halt:
|
||||||
jmp halt
|
jmp halt
|
||||||
|
|
||||||
boot_message: db 0Dh, 'Welcome to CrawOS!', 0Dh, 0
|
boot_message: db 'OK] Kernel successfully loaded!\n\n', 0
|
||||||
|
file_name: db 'hello.cws', 0
|
||||||
|
|
||||||
|
; Define Fat12 header
|
||||||
|
bdb_oem: db 'MSWIN4.1' ; ignore
|
||||||
|
bdb_bytes_per_sector: dw 200h ; = 512d
|
||||||
|
bdb_sectors_per_cluster: db 01h ; sector = cluster
|
||||||
|
bdb_reserved_sectors: dw 01h
|
||||||
|
bdb_fat_count: db 02h ; We've got a fat1 and fat2
|
||||||
|
bdb_dir_entries_count: dw 0E0h ; Maximum number of root directory entries
|
||||||
|
bdb_total_sectors: dw 0B40h ; = 2880d
|
||||||
|
bdb_media_descriptor_type: db 0F0h ; ignore
|
||||||
|
bdb_sectors_per_fat: dw 09h
|
||||||
|
bdb_sectors_per_track: dw 12h ; = 18d
|
||||||
|
bdb_number_of_heads: dw 02h ; top and bottom of the floppy disk
|
||||||
|
bdb_hidden_sectors: dd 0 ; ignore
|
||||||
|
bdb_large_sector_count: dd 0 ; total sector count for fat32 (0 for fat12 or fat16)
|
||||||
|
|
||||||
|
; extended boot record
|
||||||
|
ebr_drive_number: db 0 ; ignore
|
||||||
|
db 0 ; ignore
|
||||||
|
ebr_signature: db 29h ; boot signature, indicates that the next three fields are present (0x29)
|
||||||
|
ebr_volume_id: db 12h, 34h, 56h, 78h ; unique id for volume tracking
|
||||||
|
ebr_volume_label: db 'CrawShaw OS' ; must be 11 bytes
|
||||||
|
ebr_system_id: db 'FAT12 ' ; must be 8 bytes
|
||||||
|
|
||||||
; ------------------------------------------------------------------
|
; ------------------------------------------------------------------
|
||||||
; FEATURES -- Code to pull into the kernel
|
; FEATURES -- Code to pull into the kernel
|
||||||
@@ -24,9 +53,9 @@ boot_message: db 0Dh, 'Welcome to CrawOS!', 0Dh, 0
|
|||||||
%INCLUDE "source/kernel/features/power.asm"
|
%INCLUDE "source/kernel/features/power.asm"
|
||||||
%INCLUDE "source/kernel/features/strings.asm"
|
%INCLUDE "source/kernel/features/strings.asm"
|
||||||
%INCLUDE "source/kernel/features/graphics.asm"
|
%INCLUDE "source/kernel/features/graphics.asm"
|
||||||
%INCLUDE "source/kernel/features/sound.asm"
|
%INCLUDE "source/kernel/features/disk.asm"
|
||||||
%INCLUDE "source/kernel/features/basic.asm"
|
|
||||||
%INCLUDE "source/kernel/features/math.asm"
|
%INCLUDE "source/kernel/features/math.asm"
|
||||||
; GAMES -- Games that I wrote for it
|
; GAMES -- Games that I wrote for it
|
||||||
%INCLUDE "source/kernel/games/pong.asm"
|
%INCLUDE "source/kernel/games/pong.asm"
|
||||||
%INCLUDE "source/kernel/games/snake.asm"
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
make clean
|
||||||
# This script starts the QEMU PC emulator, booting from the
|
sudo make
|
||||||
# MikeOS floppy disk image
|
sudo chown $(whoami) disk_images/*
|
||||||
|
qemu-system-i386\
|
||||||
qemu-system-i386 -soundhw pcspk -drive format=raw,file=disk_images/mikeos.flp,index=0,if=floppy
|
-drive file=disk_images/crawos.img,if=floppy,format=raw\
|
||||||
|
-m 512m\
|
||||||
|
-object memory-backend-file,id=pc.ram,size=512m,mem-path=/dev/shm/qemu-ram,share=on -machine memory-backend=pc.ram\
|
||||||
|
$1 $2
|
||||||
|
|||||||
Reference in New Issue
Block a user