font_table: #include_bin "data/font_table.dat" font_data: #include_bin "data/font_data.dat" ; defines FONT_SIZE and FONT_LINE_HEIGHT #include "data/font_data.inc" ; input: ; r0: pointer to frame buffer ; r1: frame buffer width ; r2: pointer to string to draw ; r3: x coordinate to draw at ; r4: y coordinate to draw at ; r5: text box left ; r6: text box right ; r7: text box bottom ; r30: text delay (ms, blocking) ; r31: text color ; returns: ; r0, r1, r5, r6, r7, r30, r31 kept ; r2: pointer to last char drawn ; r3: x coordinate to next char to draw ; r4: y coordinate to next char to draw draw_str_at: ; store char pointer in r8 mov r8, r2 draw_str_at_loop: cmp r30, 0 ifnz call font_sleep ; r2: current char movz.8 r2, [r8] cmp r2, 0 ; check for null terminator ifz jmp draw_str_at_loop_end ; check for newline cmp r2, 10 ifz jmp draw_str_at_newline ; r9: char entry mov r9, r2 mul r9, 7 add r9, font_table ; r10: width, r11: end x movz.8 r10, [r9] mov r11, r3 add r11, r10 ; are we after the edge? cmp r11, r6 iflt jmp draw_str_at_loop_draw ; if we have a space, don't reset cmp r2, 32 ifz jmp draw_str_at_loop_draw draw_str_at_linebreak: mov r3, r5 ; reset x ; update end x mov r11, r5 add r11, r10 ; step to next line, check if we've overrun the box add r4, FONT_LINE_HEIGHT cmp r4, r7 ifgteq jmp draw_str_at_loop_end draw_str_at_loop_draw: push r0 push r1 push r2 push r3 push r4 call draw_char_at pop r4 pop r3 pop r2 pop r1 pop r0 draw_str_at_spaceskip: inc r8 ; update string index mov r3, r11 ; update x coordinate add r3, FONT_SIZE ; padding jmp draw_str_at_loop draw_str_at_newline: inc r8 ; update string index mov r3, r5 ; reset x ; step to next line, check if we've overrur the box add r4, FONT_LINE_HEIGHT cmp r4, r7 ifgteq jmp draw_str_at_loop_end jmp draw_str_at_loop draw_str_at_loop_end: ; restore char pointer into r2 mov r2, r8 ret ; input: ; r0: pointer to frame buffer ; r1: frame buffer width ; r2: char to draw ; r3: x coordinate to draw at ; r4: y coordinate to draw at ; r31: color ; returns: ; nothing draw_char_at: push r5 push r6 push r7 push r8 push r9 ; r5: width ; r7: baseline ; r8: char data pointer ; r9: number of pixels to draw mul r2, 7 ; size of char add r2, font_table movz.8 r5, [r2] inc r2 movz.8 r9, [r2] mul r9, r5 inc r2 movz.8 r7, [r2] inc r2 mov r8, [r2] add r8, font_data ; adjust y for baseline sub r4, r7 ; calculate init framebuffer address into r4 mul r4, r1 add r4, r3 mul r4, 4 add r4, r0 ; r6: x counter in glyph ; r9: countdown mov r6, 0 draw_char_at_loop: cmp r9, 0 ; zero terminator ifz jmp draw_char_at_loop_done cmp.8 [r8], 0 ifnz mov [r4], r31 inc r8 ; advance glyph data pointer dec r9 ; lower count add r4, 4 ; advance screen pointer inc r6 ; advance x counter cmp r6, r5 ; are we at the end of the glyph line? ifnz jmp draw_char_at_loop ; move screen pointer down one (x4 for 4 bytes per pixel) add r4, r1 add r4, r1 add r4, r1 add r4, r1 sub r4, r5 sub r4, r5 sub r4, r5 sub r4, r5 mov r6, 0 jmp draw_char_at_loop draw_char_at_loop_done: pop r9 pop r8 pop r7 pop r6 pop r5 ret ; input ; r30: time to sleep (ms) font_sleep: push r0 push r1 ; r0: end time ; r1: current time in r0, 0x8000_0706 ; RTC uptime (ms) add r0, 30 font_sleep_busyloop: in r1, 0x8000_0706 cmp r1, r0 iflt jmp font_sleep_busyloop pop r1 pop r0 ret