flat assembler
Message board for the users of flat assembler.

Index > Tutorials and Examples > VGA 13h mode for16bit MZ exe on DOS

Goto page Previous  1, 2
Author
Thread Post new topic Reply to topic
macomics



Joined: 26 Jan 2021
Posts: 913
Location: Russia
macomics 18 Apr 2023, 16:31
Code:
; push color
; push y1
; push x1
; push y0
; push x0
; call DrawLine
DrawLine:
        push    di
        push    si
        push    bp
        push    bx
        mov     bp,   sp
        mov     cx,   [bp + 18]
        mov     bx,   [bp + 14]
        mov     di,   [bp + 16]
        mov     [_C], cl
        mov     si,   bx
        sub     di,   [bp + 12] ;dy = y1 - y0
        sub     si,   [bp + 10] ;dx = x1 - x0
        mov     cx,   [bp + 10] ;for x from x0 to x1
        mov     dx,   [bp + 12] ;y = y0
        mov     bp,   di
        add     bp,   bp
        add     di,   di
        sub     bp,   si        ; D = 2*dy - dx
        add     si,   si

redraw:
        push    cx
        push    dx
        mov     al,   [_C]
        call    DrawPixel       ;plot(x, y, color)
        pop     dx
        test    bp,   bp
        jg      branch          ;if D > 0
        add     bp,   di        ;D = D + 2*dy
        jmp     continue

branch:
        inc     dx              ;y = y + 1
        sub     bp,   si        ;D = D - 2*dx
continue:
        pop     cx
        inc     cx
        cmp     cx,   320
        jge     quit
        cmp     dx,   200
        jge     quit
        cmp     cx,   bx        ;for x from x0 to x1
        jle     redraw
quit:
        pop     bx
        pop     bp
        pop     si
        pop     di
        ret     10    
I removed the extra shifts from pocket to pocket and corrected the math. Now the arguments are passed through the stack and cleared by the callee


Last edited by macomics on 18 Apr 2023, 16:53; edited 1 time in total
Post 18 Apr 2023, 16:31
View user's profile Send private message Reply with quote
FlierMate2



Joined: 21 Mar 2023
Posts: 39
FlierMate2 18 Apr 2023, 16:52
macomics wrote:
Code:
; push color
; push y1
; push x1
; push y0
; push x0
; call DrawLine    
I removed the extra shifts from pocket to pocket and corrected the math. Now the arguments are passed through the stack and cleared by the callee


Yes, it works (like mine), but shorter. I didn't know add twice is equal to multiply by two, Laughing . And I learned stack handling from you too.

But it still not able to draw vertical line, and does not draw diagonal line from lower left to upper right.

I mean the following still don't work.
Code:
        push 100
        push 20
        push 100
        push 180
        call DrawLine

        push 180
        push 40
        push 30
        push 280
        call DrawLine         
Post 18 Apr 2023, 16:52
View user's profile Send private message Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 1701
Roman 18 Apr 2023, 17:17
Quote:
push 100
push 20
push 100
push 180
call DrawLine

push 180
push 40
push 30
push 280
call DrawLine


Using linesArray and one call for draws many lines !
Code:
dw 2
LinesArr   dw   ;first line
           dw   ;second line


Mov ax,LinesArr
Mov cx,[LinesArr-2] ;how many lines draw
Call drawAllLines
    
Post 18 Apr 2023, 17:17
View user's profile Send private message Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 913
Location: Russia
macomics 18 Apr 2023, 18:09
You just implemented only half of the algorithm. Here's the whole thing.
Code:
use16
org     256
        mov     ax,     19
        int     16
        push    7
        push    100
        push    20
        push    100
        push    180
        call    DrawLine

        push    3
        push    180
        push    -40
        push    30
        push    380
        call    DrawLine

        push    7
        push    20
        push    100
        push    180
        push    100
        call    DrawLine

        push    3
        push    280
        push    280
        push    -40
        push    30
        call    DrawLine

        mov     ax,     0
        int     22
        mov     ax,     3
        int     16
        mov     ax,     0x4C00
        int     33

DrawPixel:
        cmp     cx, 0
        jl      .out_of_bounds
        cmp     cx, 320
        jge     .out_of_bounds
        cmp     dx, 0
        jl      .out_of_bounds
        cmp     dx, 200
        jge     .out_of_bounds
        push    ax
        mov     ah,     12
        int     16
        pop     ax

  .out_of_bounds:
        retn

DrawPixelRev:
        xchg    cx,     dx
        call    DrawPixel
        xchg    cx,     dx
        retn

; push color
; push y1
; push x1
; push y0
; push x0
; call DrawLine
DrawLine:
  label .x0     word at bp + 10
  label .y0     word at bp + 12
  label .x1     word at bp + 14
  label .y1     word at bp + 16
  label .color  byte at bp + 18
  label .plt    word at bp - 2
  label .D      word at bp - 4
  label .dv     word at bp - 6
  label .cx     word at bp - 8
        push    di
        push    si
        push    bx
        push    bp
        mov     bp,     sp
        sub     sp,     8
        mov     di,     [.y1]
        mov     bx,     [.x1]
        mov     dx,     [.y0]
        mov     cx,     [.x0]
        mov     [.cx],  320
        sub     dx, di          ; dx = y0 - y1
        jns     @f
        neg     dx              ; if y0 - y1 < 0 then dx = y1 - y0

  @@:
        sub     cx,     bx      ; cx = x0 - x1
        jns     @f
        neg     cx              ; if x0 - x1 < 0 then cx = x1 - x0

  @@:
        mov     si,     DrawPixel
        cmp     cx,     dx      ; if abs(x0 - x1) > abs(y0 - y1)
        mov     cx,     [.x0]
        mov     dx,     [.y0]
        jg      @f
        mov     si,     DrawPixelRev
        xchg    cx,     dx
        xchg    bx,     di
        mov     [.cx],  200

  @@:
        mov     [.plt], si
        cmp     cx,     bx
        jle     @f
        xchg    cx,     bx
        xchg    dx,     di

  @@:
        mov     al,     [.color]
        mov     si,     bx      ; si = u1
        mov     [.dv],  1       ; v` = 1
        sub     si,     cx      ; si = u1 - u0
        sub     di,     dx      ; di = v1 - v0
        jge     @f              ; if v1 - v0 < 0:
        neg     di              ;       di = v0 - v1
        neg     [.dv]           ;       v` = -1

  @@:
        add     di,     di      ; di = 2*dv
        mov     [.D],   di      ; D  = 2*dv
        sub     [.D],   si      ; D  = 2*dv - du
        add     si,     si      ; si = 2*du
        sub     si,     di      ; si = 2*(du - dv)
        cmp     cx,     0
        jge     @f
        xor     cx,     cx
        cmp     cx,     bx
        jg      .break

  @@:
        call    [.plt]          ; plot(cx, dx, al)
        cmp     [.D],   0
        jle     .else           ; if D > 0
        sub     [.D],   si      ; D = D + 2*(du - dv)
        add     dx,     [.dv]   ; v = v + v`
        jmp     .endif

  .else:
        add     [.D],   di      ; D = D + 2*dy

  .endif:
        inc     cx
        cmp     cx,     [.cx]
        jge     .break
        cmp     cx,     bx      ; for x from x0 to x1
        jle     @b

  .break:
        leave
        pop     bx
        pop     si
        pop     di
        retn    10    


ADD: Updated yesterday's version. Corrected the error and removed two identical routines. Now everything is completed in one.


Description:
Filesize: 16 KB
Viewed: 3076 Time(s)

Screenshot_20230419_154624.png


Post 18 Apr 2023, 18:09
View user's profile Send private message Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 913
Location: Russia
macomics 19 Apr 2023, 13:06
Latest
Code:
use16
org     256
        mov     ax,     19
        int     16
        push    7
        push    100
        push    20
        push    100
        push    180
        call    DrawLine

        push    3
        push    180
        push    -40
        push    30
        push    380
        call    DrawLine

        push    5
        push    20
        push    100
        push    180
        push    100
        call    DrawLine

        push    8
        push    280
        push    280
        push    -40
        push    30
        call    DrawLine

        mov     ax,     0
        int     22
        mov     ax,     3
        int     16
        mov     ax,     0x4C00
        int     33

DrawPixel:
        cmp     cx, 0
        jl      .out_of_bounds
        cmp     cx, 320
        jge     .out_of_bounds
        cmp     dx, 0
        jl      .out_of_bounds
        cmp     dx, 200
        jge     .out_of_bounds
        push    ax
        mov     ah,     12
        int     16
        pop     ax

  .out_of_bounds:
        retn

DrawPixelRev:
        xchg    cx,     dx
        call    DrawPixel
        xchg    cx,     dx
        retn

; push color
; push y1
; push x1
; push y0
; push x0
; call DrawLine
DrawLine:
  label .x0     word at bp + 10
  label .y0     word at bp + 12
  label .x1     word at bp + 14
  label .y1     word at bp + 16
  label .color  byte at bp + 18
  label .p      word at bp - 2
  label .D      word at bp - 4
  label .v      word at bp - 6
        push    di
        push    si
        push    bx
        push    bp
        mov     bp,     sp
        lea     sp,     [.v]
        mov     di,     [.y1]
        mov     bx,     [.x1]
        mov     dx,     [.y0]
        mov     cx,     [.x0]
        mov     ax,     320
        sub     dx,     di      ; dx = y0 - y1
        jns     @f
        neg     dx              ; if y0 - y1 < 0 then dx = y1 - y0

  @@:
        sub     cx,     bx      ; cx = x0 - x1
        jns     @f
        neg     cx              ; if x0 - x1 < 0 then cx = x1 - x0

  @@:
        mov     si,     DrawPixel
        cmp     cx,     dx      ; if abs(x0 - x1) > abs(y0 - y1)
        mov     cx,     [.x0]
        mov     dx,     [.y0]
        jg      @f
        add     si,     DrawPixelRev - DrawPixel
        xchg    cx,     dx
        xchg    bx,     di
        add     ax,     200 - 320

  @@:
        mov     [.p],   si
        cmp     cx,     bx
        jle     @f
        xchg    cx,     bx
        xchg    dx,     di

  @@:
        cmp     bx,     ax
        jl      @f
        mov     bx,     ax
        dec     bx

  @@:
        mov     si,     bx      ; si = u1
        mov     [.v],   1       ; v` = 1
        sub     si,     cx      ; si = u1 - u0
        sub     di,     dx      ; di = v1 - v0
        jge     @f              ; if v1 - v0 < 0:
        neg     di              ;       di = v0 - v1
        neg     [.v]            ;       v` = -1

  @@:
        mov     al,     [.color]
        add     di,     di      ; di = 2*dv
        mov     [.D],   di      ; D  = 2*dv
        sub     [.D],   si      ; D  = 2*dv - du
        add     si,     si      ; si = 2*du
        sub     si,     di      ; si = 2*(du - dv)
        cmp     cx,     0
        jge     @f
        xor     cx,     cx
        cmp     cx,     bx
        jg      .break

  @@:
        call    [.p]            ; plot(cx, dx, al)
        cmp     [.D],   0
        jle     .else           ; if D > 0
        sub     [.D],   si      ; D = D + 2*(du - dv)
        add     dx,     [.v]    ; v = v + v`
        jmp     .endif

  .else:
        add     [.D],   di      ; D = D + 2*dv

  .endif:
        inc     cx
        cmp     cx,     bx      ; for x from x0 to x1
        jle     @b

  .break:
        leave
        pop     bx
        pop     si
        pop     di
        retn    10    


Last edited by macomics on 19 Apr 2023, 13:13; edited 1 time in total
Post 19 Apr 2023, 13:06
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20130
Location: In your JS exploiting you and your system
revolution 19 Apr 2023, 13:11
If I wanted to draw a line from 10,10 to -10,-10 I would hope to see a line on the output going from 10,10 to 0,0 and the remaining out-of-bounds portion discarded.


Last edited by revolution on 19 Apr 2023, 14:20; edited 1 time in total
Post 19 Apr 2023, 13:11
View user's profile Send private message Visit poster's website Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 913
Location: Russia
macomics 19 Apr 2023, 13:20
I wanted to reduce the number of iterations of the line drawing cycle, but I did not consider that there are two coordinates there and it is necessary to recalculate cx and dx. For now, it can simply be removed. Then I will recalculate dx, so that the loop does not iterate with negative cx
Code:
use16
org     256
        mov     ax,     19
        int     16
        push    7
        push    100
        push    20
        push    100
        push    180
        call    DrawLine

        push    3
        push    180
        push    -40
        push    30
        push    380
        call    DrawLine

        push    5
        push    20
        push    100
        push    180
        push    100
        call    DrawLine

        push    8
        push    280
        push    280
        push    -40
        push    30
        call    DrawLine

        push    14
        push    -10
        push    -10
        push    10
        push    10
        call    DrawLine

        mov     ax,     0
        int     22
        mov     ax,     3
        int     16
        mov     ax,     0x4C00
        int     33

DrawPixel:
        cmp     cx, 320
        jae     .out_of_bounds
        cmp     dx, 200
        jae     .out_of_bounds
        push    ax
        mov     ah,     12
        int     16
        pop     ax

  .out_of_bounds:
        retn

DrawPixelRev:
        xchg    cx,     dx
        call    DrawPixel
        xchg    cx,     dx
        retn

; push color
; push y1
; push x1
; push y0
; push x0
; call DrawLine
DrawLine:
  label .x0     word at bp + 10
  label .y0     word at bp + 12
  label .x1     word at bp + 14
  label .y1     word at bp + 16
  label .color  byte at bp + 18
  label .p      word at bp - 2
  label .D      word at bp - 4
  label .v      word at bp - 6
        push    di
        push    si
        push    bx
        push    bp
        mov     bp,     sp
        lea     sp,     [.v]
        mov     di,     [.y1]
        mov     bx,     [.x1]
        mov     dx,     [.y0]
        mov     cx,     [.x0]
        mov     ax,     320
        sub     dx,     di      ; dx = y0 - y1
        jns     @f
        neg     dx              ; if y0 - y1 < 0 then dx = y1 - y0

  @@:
        sub     cx,     bx      ; cx = x0 - x1
        jns     @f
        neg     cx              ; if x0 - x1 < 0 then cx = x1 - x0

  @@:
        mov     si,     DrawPixel
        cmp     cx,     dx      ; if abs(x0 - x1) > abs(y0 - y1)
        mov     cx,     [.x0]
        mov     dx,     [.y0]
        jg      @f
        add     si,     DrawPixelRev - DrawPixel
        xchg    cx,     dx
        xchg    bx,     di
        add     ax,     200 - 320

  @@:
        mov     [.p],   si
        cmp     cx,     bx
        jle     @f
        xchg    cx,     bx
        xchg    dx,     di

  @@:
        cmp     bx,     ax
        jl      @f
        mov     bx,     ax
        dec     bx

  @@:
        mov     si,     bx      ; si = u1
        mov     [.v],   1       ; v` = 1
        sub     si,     cx      ; si = u1 - u0
        sub     di,     dx      ; di = v1 - v0
        jge     @f              ; if v1 - v0 < 0:
        neg     di              ;       di = v0 - v1
        neg     [.v]            ;       v` = -1

  @@:
        mov     al,     [.color]
        add     di,     di      ; di = 2*dv
        mov     [.D],   di      ; D  = 2*dv
        sub     [.D],   si      ; D  = 2*dv - du
        add     si,     si      ; si = 2*du
        sub     si,     di      ; si = 2*(du - dv)
;       cmp     cx,     0
;       jge     @f
;       xor     cx,     cx
;       cmp     cx,     bx
;       jg      .break

  @@:
        call    [.p]            ; plot(cx, dx, al)
        cmp     [.D],   0
        jle     .else           ; if D > 0
        sub     [.D],   si      ; D = D + 2*(du - dv)
        add     dx,     [.v]    ; v = v + v`
        jmp     .endif

  .else:
        add     [.D],   di      ; D = D + 2*dv

  .endif:
        inc     cx
        cmp     cx,     bx      ; for x from x0 to x1
        jle     @b

  .break:
        leave
        pop     bx
        pop     si
        pop     di
        retn    10    


Description:
Filesize: 15.79 KB
Viewed: 3057 Time(s)

Screenshot_20230419_154624.png


Post 19 Apr 2023, 13:20
View user's profile Send private message Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4325
Location: Now
edfed 19 Apr 2023, 20:58
Kitsune, are you still there?
Post 19 Apr 2023, 20:58
View user's profile Send private message Visit poster's website Reply with quote
DimonSoft



Joined: 03 Mar 2010
Posts: 1228
Location: Belarus
DimonSoft 19 Apr 2023, 22:09
I’m surprised noone has yet mentioned that pixel-drawing BIOS functions are very ineffective. Preparing arguments in specific registers, invoking the whole interrupt handling mechanism with at least 3 stack writes and, later, reads (even if we believe no additional stack/memory accesses are performed internally), then a multiplication+addition, changing a segment register value to access specific video memory segment, then restoring the value (invokes the segment register related stuff, which is not that simple, at least twice) — and all that for actually doing a single write to memory.

The only positive property is that it is somewhat video mode agnostic (and we do hope there’s a table lookup instead of a sequence of branches inside the function). But then again, for AL with highest bit set it performs XOR with what’s already on the screen which basically reduces the Mode 13h default 256 color palette to 128 colors, i.e. twice less. Or at least makes it way harder to achieve exactly the image expected.

Don’t you, guys, want the topic starter to write a cool DOS demo some day?
Post 19 Apr 2023, 22:09
View user's profile Send private message Visit poster's website Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4325
Location: Now
edfed 20 Apr 2023, 12:18
BIOS put pixel is ineffective if you use it intensivelly. but if the put pixel is just used to set a single pixel for any reason, it is convenient. because it don't need extra code to work. just give arguements and call interrupt.

it can be interresting to make a demo yes... but what to do? what rules?
Post 20 Apr 2023, 12:18
View user's profile Send private message Visit poster's website Reply with quote
FlierMate2



Joined: 21 Mar 2023
Posts: 39
FlierMate2 20 Apr 2023, 12:47
edfed wrote:

it can be interresting to make a demo yes... but what to do? what rules?


According to a definition:
Quote:
Demos are special computer programs. They are beautiful presentations made by talented people - programmers, graphics, musicians - just for fun. This is real electronic art. Size-limited demos are called intros, and there are some categories of them - we have intros in 64 kilobytes, 4 kilobytes, even in 256 bytes and less. It's wonderful that some people make very impressive effects in so tiny space.


http://hardcode.untergrund.net/
https://github.com/netspooky/hardcode

One of my demo was also included.
Post 20 Apr 2023, 12:47
View user's profile Send private message Reply with quote
DimonSoft



Joined: 03 Mar 2010
Posts: 1228
Location: Belarus
DimonSoft 27 Apr 2023, 15:11
edfed wrote:
BIOS put pixel is ineffective if you use it intensivelly. but if the put pixel is just used to set a single pixel for any reason, it is convenient. because it don't need extra code to work. just give arguements and call interrupt.

Freeing and overwriting 4 GPRs (AX, CX, DX and, partially, BX) to put a single point? For direct video memory access one only has to have a segment register set up (let’s count it as 1) and, probably, a GPR register that would store the variable part defining the point coordinates (it’s now 2). Hmmm, let me think about what “convenient” means Smile

The only reason I can see to use the int 10h/0Ch function is that it is somewhat screen-mode-independent. Although one still has to deal with screen size and future image size. And the number of colors available. And palette, if some particular color is expected. Maybe the function was really introduced there “just because we can”? Smile
Post 27 Apr 2023, 15:11
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page Previous  1, 2

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.