.code16 # the currently viewed sector gets put at 0x7c00 # we move to 0x7000 to make space .global _start # the linker needs to find it _start: jmp move_self .ascii "the bootsector" # CAN AFFECT MANUALLY SET POINTER, LEAVE AT THIS LEN _Xterm_grad: .byte 0x00, 0x5f / 4, 0x87 / 4, 0xaf / 4, 0xd7 / 4, 0xff / 4 # saves some work later on when i'll want to execute sectors move_self: mov $512, %si move_self_loop: movb 0x7c00(%si), %ah movb %ah, 0x7000(%si) dec %si jnz move_self_loop jmp (vga_init-0xc00) # correct IP vga_init: # enter mode 13h mov $0x13, %ax int $0x10 # prepare the xterm palette 0-15 # 7 and 8 aren't right, TODO # bl - counter rgb xor %bh, %bh palette1_loop: mov %bh, %al mov %al, %ah mov $0x3c8, %dx out %al, %dx inc %dx mov $3, %bl palette1_color: xor %al, %al # 0 al shr $1, %ah # sets carry to the lost bit adc $0, %al # add carry to %al, setting it to the carry flag _palette1_sal: sal $5, %al sub $1, %al # this gets changed to 6 in the second half # it will increase the lightness adc $0, %al out %al, %dx dec %bl jnz palette1_color cmp $8, %bh jne palette1_not7 inc _palette1_sal+2 palette1_not7: inc %bh jnz palette1_loop # prepare the xterm palette 16-231 # ch - color id # dx - used up for the port number mov $16, %ch mov $0x701, %ax # pointer to _Xterm_grad mov %ax, %ds palette_loop: mov %ch, %al dec %dx # we can reuse the %dx from the previous loop out %al, %dx inc %dx sub $16, %al # the colors start at 16, real_id = id - 16 mov $6, %bl xor %ah, %ah div %bl # al = real_id / 6 # ah = remainder mov %ah, %cl # cl = real_id % 6 xor %ah, %ah div %bl # al = real_id / 6 / 6 # ah = remainder # at this point # al - R # ah - G # cl - B # here i'm assuming that %bh is 0, because the loop above clears it mov %al, %bl # output R mov (%bx), %al out %al, %dx mov %ah, %bl # G mov (%bx), %al out %al, %dx mov %cl, %bl # B mov (%bx), %al out %al, %dx inc %ch jnz palette_loop # loop until 0 # %ah stores the current shade # %ch iterator mov $2, %ah mov $232, %ch # the pattern i'm aiming for is # [2, 5, 7, 10, 12, 15, 17, 20, 22, 25, 27, 30, 32, 35, 37, 40, 42, 45, 47, 50, 52, 55, 57, 60] # +3 +2 +3 +2 +3 +2 +3 +2 +3 +2 +3 +2 +3 +2 +3 +2 +3 +2 ... palette_greys: mov %ch, %al dec %dx out %al, %dx inc %dx mov %ah, %al out %al, %dx out %al, %dx out %al, %dx add $2, %ah # TODO this is obviously wrong inc %ch jnz palette_greys mov $0xA000, %ax # DS = vga memory mov %ax, %ds mov $0x7c0, %ax # ES = the bootsector mov %ax, %es update_screen_vgay: mov $0, %dh # "arguments": # %es - has the sector at 0-512 # %dh - vga Y, should be either 0 or more than 25 update_screen: .set SCALE, 6 .set TEXT_X, 0 .set TEXT_CLR, 102 .set IMG_X, 128 .set IMG_Y, 0 # %bl/h - scale iterators # %al - current byte # %si - position in sector # %di - position in vga mem # %dl - text X mov $0, %si mov $320*IMG_Y+IMG_X, %di mov $TEXT_X, %dl render_loop: movb %es:(%si), %al mov $SCALE, %bh y_loop: mov $SCALE, %bl x_loop: movb %al, %ds:(%di) inc %di dec %bl # loop ctr jnz x_loop add $320-SCALE, %di dec %bh jnz y_loop sub $(320-1)*SCALE, %di # text preview cmp $25, %dh # the screen only has 25 lines, we can't render more jnb text_overflow mov $TEXT_CLR, %bl # update %bl with the text color mov $0x2, %ah # move cursor (the position is already loaded) int $0x10 mov $0xe, %ah # and print the charactr (again, already in the correct register) int $0x10 text_overflow: inc %dl # text forward inc %si # sector forward mov $15, %cl # check if %si is a multiple of 16 and %si, %cx jnz not_eol # if it is, then we've finished the current row add $(320-16)*SCALE, %di # go down in visualization mov $TEXT_X, %dl # text back to left inc %dh # and text down not_eol: cmp $512, %si jl render_loop # print sector number int $0x10 # wild assumption - %ah == 0xe int $0x10 # printing some garbage to make this line up int $0x10 mov %cs:_sector_num+1, %cx mov $4, %dl # loop counter mov $231, %bl # TODO can be removed if i change the loop condition higher up digit_loop: mov %cx, %ax mov $10, %dh # base 10 div %dh # %al = quotient ; %ah = remainder ror $8, %ax # swap those around add $'0', %al mov %ah, %cl # save remainder xor %ch, %ch mov $0xe, %ah int $0x10 mov $'\b', %al # backspace two times int $0x10 int $0x10 dec %dl jnz digit_loop mov $0, %ah # read character int $0x16 # scancode in %ah cmp $0x4d, %ah # right arrow? jne 1f incw %cs:_sector_num+1 read_sector: _sector_num: movw $0, %ax # sector num (0indexed) movb $18, %ch # divide by 18 (sectors / track) div %ch # %ah - sector # %al - track * 2, 1st bit - head mov $0x100, %dx # head / drive number and %al, %dh sar $1, %al mov %al, %ch # track mov %ah, %cl # sector inc %cl # sectors are 1indexed mov $1, %al # read only one sector xor %bx, %bx # write to es:bx # mov $0, %ah # reset disk system # int $0x13 mov $2, %ah # actual read int $0x13 # TODO error checking jmp update_screen_vgay 1: # not the right arrow # left arrow? cmp $0x4b, %ah jne 1f decw %cs:_sector_num+1 # it is, decrease sector and read jmp read_sector 1: # default: scroll text xorb $-7, %cs:update_screen_vgay+1 jmp update_screen_vgay .fill 510-(.-_start), 1, 0x90 # fill with 0x90 (NOPs) .word 0xaa55 # boot sector magic