; _______________________________________________________________________________________
;|                                                                                       |
;| ..::FreshLib::..  Free, open source. Licensed under "BSD 2-clause" license.           |
;|_______________________________________________________________________________________|
;
;  Description: SimpleDebug library.
;
;  Target OS: KolibriOS
;
;  Dependencies: Not dependent on other libraries.
;
;  Notes:
;_________________________________________________________________________________________

DBG_CHAR_NEWLINE equ $0d, $0a

CONSOLE_X_SIZE = 128
CONSOLE_X_SHIFT = 7

CONSOLE_Y_SIZE = 256
CONSOLE_Y_SHIFT = 8

FONT_HEIGHT = 9
FONT_WIDTH  = 6

CONSOLE_TEXT_COLOR = $00000000
CONSOLE_BG_COLOR = $fffff0


if used CharOut | used STDIN | used STDOUT | used STDERR
initialize InitConsole
begin
        mov     eax, sys_threads
        mov     ebx, 1
        mov     ecx, ConsoleThread
        mov     edx, ConsoleSP
        int     $40

        mov     [hConsoleThread], eax

        return
endp

end if


uglobal
  if used ConsoleSP
                rd 16383
    ConsoleSP   dd ?
  end if

  if used DebugBuffer
    xDebugBuffer dd ?           ; current X position
    yDebugBuffer dd ?           ; current Y position
    rDebugBuffer dd ?           ; the top row of the console
    sDebugBuffer dd ?           ; start of the debug buffer.
    fDebugRefresh dd ?          ; flag that the console needs refresh.

    hConsoleThread dd ?

    DebugBuffer rb CONSOLE_X_SIZE * CONSOLE_Y_SIZE

    KeyboardHead   dd 0
    KeyboardTail   dd 0
    KeyboardBuffer rb 1024
  end if
endg



proc Output, .ptrString
begin
        push    eax esi

        mov     esi, [.ptrString]

.loop:
        lodsb

        test    al, al
        jz      .end_output

        stdcall CharOut, eax
        jmp     .loop

.end_output:
        pop     esi eax
        return
endp


; this one writes to the KolibriOS debug message board.

;proc Output, .ptrStr
;begin
;        pushad
;
;        mov     esi, [.ptrStr]
;        mov     eax, sys_msg_board
;        mov     ebx, 1
;
;.loop:
;        mov     cl, [esi]
;        test    cl,cl
;        jz      .finish
;        lea     esi, [esi+1]
;        int     $40
;        jmp     .loop
;
;.finish:
;        popad
;        return
;endp



proc GetTimestamp
begin
        pushad

        mov     eax, sys_getsetup
        mov     ebx, 9
        int     $40

        imul    eax, 10                 ; in [ms]
        mov     [esp+4*regEAX], eax
        popad
        return
endp




proc ConsoleThread
.info __TThreadInfo
begin
        mov     eax, sys_process_def
        mov     ebx, 1
        mov     ecx, 0
        int     $40

        stdcall DrawConsole, 1

        mov     eax, sys_set_app_param
        mov     ebx, emaskRedraw or emaskGUIButton or emaskKeyboard or emaskMouse or emaskNetwork
        int     $40

.event_loop:
        cmp     [fDebugRefresh], 0
        jne     .redraw

        mov     eax, sys_wait_event_timeout
        mov     ebx, 1
        int     $40

        test    eax, eax
        jz      .event_loop

        cmp     eax, eventRedraw
        je      .redraw

        cmp     eax, eventKeyboard
        je      .keyboard

        cmp     eax, eventGUIButton
        je      .button

        cmp     eax, eventMouse
        je      .mouse

        cmp     eax, eventNetwork
        je      .network

        jmp     .event_loop

.network:
        jmp     .event_loop


.redraw:
        stdcall DrawConsole, [fDebugRefresh]
        mov     [fDebugRefresh], 0
        jmp     .event_loop

.keyboard:
        mov     eax, sys_getkey
        int     $40

;        jmp     .ascii
;
;        cmp     eax, 1
;        je      .event_loop
;
;        test    al, al
;        jz      .ascii
;
;        cmp     ah, keyUp
;        je      .up1
;        cmp     ah, keyDown
;        je      .dn1
;        cmp     ah, keyPgUp
;        je      .up2
;        cmp     ah, keyPgDown
;        je      .dn2
;
;        jmp     .event_loop
;
;.ascii:

        mov     ebx, [KeyboardHead]
        mov     ecx, ebx

        inc     ebx
        and     ebx, $fff
        cmp     ebx, [KeyboardTail]     ; overflow? Don't store then.
        je      .event_loop

        mov     [KeyboardBuffer+ecx], ah
        mov     [KeyboardHead], ebx

        movzx   eax, ah
        stdcall CharOut, eax

        jmp     .event_loop

.up1:
        mov     eax, -1
        jmp     .scroll

.dn1:
        mov     eax, 1
        jmp     .scroll

.up2:
        call    .get_info
        neg     eax
        jmp     .scroll

.dn2:
        call    .get_info
        jmp     .scroll

.mouse:
        mov     eax, sys_readmousepos
        mov     ebx, 7
        int     $40
        cwde
        shl     eax, 1

.scroll:
        mov     edx, [rDebugBuffer]

        test    eax, eax
        jz      .event_loop
        js      .minusloop

.plusloop:
        inc     edx
        and     edx, CONSOLE_Y_SIZE - 1
        cmp     edx, [sDebugBuffer]
        je      .redraw
        mov     [rDebugBuffer], edx
        dec     eax
        jnz     .plusloop
        jmp     .redraw

.minusloop:
        dec     edx
        and     edx, CONSOLE_Y_SIZE - 1
        mov     ecx, [sDebugBuffer]
        dec     ecx
        and     ecx, CONSOLE_Y_SIZE - 1
        cmp     edx, ecx
        je      .redraw
        mov     [rDebugBuffer], edx
        inc     eax
        jnz     .minusloop
        jmp     .redraw

.button:
        mov     eax, sys_getbutton
        int     $40

        cmp     ah, 1
        jne     .event_loop

.finish:
        mov     eax, sys_end
        int     $40


.get_info:
        mov     eax, sys_cpuusage
        lea     ebx, [.info]
        mov     ecx, -1
        int     $40

        mov     eax, [.info.ClientHeight]
        cdq
        mov     ecx, FONT_HEIGHT
        sub     eax, ecx
        div     ecx
        retn


endp






cDebugWindowHeader text 'FreshLib console'


proc DrawConsole, .fScroll
.info __TThreadInfo
begin
; start draw
        mov     eax, 12
        mov     ebx, 1
        int     $40

; draw standard elements.
        mov     eax, sys_drawwindow
        mov     ebx, 480+8
        mov     ecx, 320+32
        mov     edx, $33000000 or CONSOLE_BG_COLOR
        mov     edi, cDebugWindowHeader
        int     $40

; draw the text from the buffer

; get the window size:
        mov     eax, sys_cpuusage
        lea     ebx, [.info]
        mov     ecx, -1
        int     $40

        sub     [.info.ClientHeight], FONT_HEIGHT

; check for scroll
        cmp     [.fScroll], 0
        je      .scrollok

        mov     eax, [.info.ClientHeight]
        cdq
        mov     ecx, FONT_HEIGHT
        div     ecx

        mov     edx, [yDebugBuffer]
        sub     edx, [rDebugBuffer]
        and     edx, CONSOLE_Y_SIZE - 1

        cmp     edx, eax
        jbe     .scrollok

        sub     edx, eax
        add     [rDebugBuffer], edx

.scrollok:
        mov     eax, sys_writetext
        xor     ebx, ebx
        mov     ecx, CONSOLE_TEXT_COLOR     ; text color and options.
        mov     edi, [rDebugBuffer]
        mov     esi, CONSOLE_X_SIZE

.text_loop:
        mov     edx, edi
        shl     edx, CONSOLE_X_SHIFT
        add     edx, DebugBuffer

        int     $40

        inc     edi
        and     edi, CONSOLE_Y_SIZE - 1
        cmp     edi, [sDebugBuffer]
        je      .text_ok

        add     ebx, FONT_HEIGHT
        cmp     ebx, [.info.ClientHeight]
        jbe     .text_loop

.text_ok:
        mov     eax, 12
        mov     ebx, 2
        int     $40
        return
endp





proc CharOut, .char
begin
        pushad

        mov     ecx, [xDebugBuffer]
        mov     edx, [yDebugBuffer]

        mov     eax, [.char]

        cmp     al, $20
        jb      .control

.charout:
        mov     edi, edx
        shl     edi, CONSOLE_X_SHIFT
        add     edi, ecx
        mov     [edi+DebugBuffer], al

        inc     ecx
        cmp     ecx, CONSOLE_X_SIZE
        jb      .end_output

        xor     ecx, ecx
.LF:
        inc     edx
        and     edx, CONSOLE_Y_SIZE - 1

        cmp     edx, [sDebugBuffer]
        jne     @f
        inc     [sDebugBuffer]
        and     [sDebugBuffer], CONSOLE_Y_SIZE - 1
@@:
        call    .clearEOL

.end_output:
        mov     [xDebugBuffer], ecx
        mov     [yDebugBuffer], edx
        mov     [fDebugRefresh], 1

        popad
        return

.control:
        cmp     al, $0d
        je      .CR
        cmp     al, $0a
        je      .LF

        mov     al, '.'        ; replace ctrl code with "."
        jmp     .charout

.CR:
        xor     ecx, ecx
        jmp     .end_output

; clear the row.
.clearEOL:
        xor     eax, eax
        mov     edi, edx
        shl     edi, CONSOLE_X_SHIFT
        add     edi, ecx
        add     edi, DebugBuffer
        push    ecx
        mov     ecx, CONSOLE_X_SIZE / 4
        rep stosd
        pop     ecx
        retn
endp



