Mirai's Miscellaneous Misadventures
M29 / x86 / main.s
# copyright 2022 zamfofex
# license: AGPLv3 or later
.intel_syntax noprefix
.code16
.section boot2
.global mimimi_x86_boot
mimimi_x86_boot:
# query disc geometry
mov ah, 8
mov dl, 0x80
int 0x13
jc mimimi_x86_exit
cmp ah, 0
jne mimimi_x86_exit
and cl, 0x3F
mov [sectors_per_track], cl
inc dh
mov [heads_per_cylinder], dh
# load parts after the bootloader
mov esp, 0x7C00
mov ebp, esp
mov ax, 0x3D
mov bx, 0x8000
call load_data
mov ax, 0x1000
mov es, ax
mov ax, 0x7D
mov bx, 0
call load_data
mov ax, 0xBD
mov bx, 0x8000
call load_data
mov ax, 0x2000
mov es, ax
mov ax, 0xFD
mov bx, 0
call load_data
mov ax, 0xFD
mov bx, 0x8000
call load_data
# set up VBE
xor eax, eax
mov es, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
call 0:mimimi_vbe_set_mode
jc mimimi_x86_exit
# establish keyboard IRQ handler
cli
mov word ptr [9*4], offset handle_key
mov word ptr [9*4+2], 0
sti
# set up game state
cld
mov eax, 0
mov ebx, 0
mov ecx, 0
mov edx, 0
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, 0x7C00
mov ebp, esp
call 0:mimimi_x86_start
measure_time:
mov ah, 0x86
mov al, 0
mov cx, 2
mov dx, 0
int 0x15
jc measure_time
lfence ; rdtsc ; lfence
mov [time], eax
mov [time + 4], edx
mov ah, 0x86
mov al, 0
mov cx, 0x08
mov dx, 0x2355
int 0x15
jc measure_time
lfence ; rdtsc ; lfence
sub eax, [time]
sbb edx, [time + 4]
mov ecx, edx
and ecx, 0x0F
shl ecx, 28
shr eax, 4
shr edx, 4
or eax, ecx
mov [delta], eax
mov [delta + 4], edx
loop:
pause
lfence ; rdtsc ; lfence
cmp [time + 4], edx
ja loop
jb step
cmp [time], eax
ja loop
step:
mov [time], eax
mov [time + 4], edx
mov eax, [delta]
mov edx, [delta + 4]
add [time], eax
adc [time + 4], edx
# switch video modes
cmp byte ptr [return], 0
jz main
mov byte ptr [return], 0
call mimimi_vbe_next_mode
main:
cld
mov eax, 0
mov ebx, 0
mov ecx, 0
mov edx, 0
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, 0x7C00
mov ebp, esp
call 0:mimimi_x86_step
jmp loop
lba_to_chs:
push es
push bx
mov cx, ax
mov bl, [sectors_per_track]
div bl
inc ah
mov [sector_number], ah
mov ax, cx
mov bl, [sectors_per_track]
div bl
cbw
mov bl, [heads_per_cylinder]
div bl
mov [cylinder_number], al
mov [head_number], ah
mov ah, 2
mov al, 0x40
pop bx
mov ch, [cylinder_number]
mov cl, [sector_number]
mov dl, 0x80
mov dh, [head_number]
pop es
int 0x13
ret
load_data:
mov ecx, 6
load_loop:
dec ecx
jz load_end
push ecx
call lba_to_chs
pop ecx
cmp ah, 0
jne load_loop
load_end:
ret
handle_key:
pusha
in al, 0x60
cmp al, 0x4B
jne break_left
mov byte ptr [mimimi_x86_left], 1
break_left:
cmp al, 0xCB
jne make_right
mov byte ptr [mimimi_x86_left], 0
make_right:
cmp al, 0x4D
jne break_right
mov byte ptr [mimimi_x86_right], 1
break_right:
cmp al, 0xCD
jne break_return
mov byte ptr [mimimi_x86_right], 0
break_return:
cmp al, 0x9C
jne handle_key_done
mov byte ptr [return], 1
handle_key_done:
in al, 0x61
mov ah, al
or al, 0x80
out 0x61, al
mov al, ah
out 0x61, al
mov al, 0x20
out 0x20, al
popa
iret
.global mimimi_x86_exit
mimimi_x86_exit:
cli
hlt
jmp mimimi_x86_exit
.global mimimi_x86_left, mimimi_x86_right
mimimi_x86_left: .zero 1
mimimi_x86_right: .zero 1
return: .zero 1
sectors_per_track: .zero 1
heads_per_cylinder: .zero 1
sector_number: .zero 1
cylinder_number: .zero 1
head_number: .zero 1
delta: .zero 8
time: .zero 8