BBC BASIC
« Using GDIP with assembler »

Welcome Guest. Please Login or Register.
Mar 31st, 2018, 11:12pm



ATTENTION MEMBERS: Conforums will be closing it doors and discontinuing its service on April 15, 2018.
We apologize Conforums does not have any export functions to migrate data.
Ad-Free has been deactivated. Outstanding Ad-Free credits will be reimbursed to respective payment methods.

Thank you Conforums members.
Cross-platform BBC BASIC (Windows, Linux x86, Mac OS-X, Android, iOS, Raspberry Pi)
BBC BASIC Resources
BBC BASIC Help Documentation
BBC BASIC for Windows Home Page
BBC BASIC Programmers' Reference
BBC BASIC Beginners' Tutorial
BBC BASIC for SDL 2.0 Home Page
BBC BASIC Discussion Group

« Previous Topic | Next Topic »
Pages: 1  Notify Send Topic Print
 thread  Author  Topic: Using GDIP with assembler  (Read 136 times)
svein
New Member
Image


member is offline

Avatar




PM


Posts: 15
xx Using GDIP with assembler
« Thread started on: Oct 25th, 2017, 01:06am »

Hello Richard.
I hope you can help with a little problem.

It's about drawing a line in GDI+ from assembler code.

In the supplied demo, two figures are drawn, one by assembler and one by the regular library call, using the same pen for both.
With a width of one, they look the same, but as the width increases, the assembler drawn figure seems to use a different pen style.
Any idea why ?

The @memhdc% parameter causes a crash if included in the assembler call to 'GdipDrawLine'.
Any idea why ?

In fact, one can remove or replace @memhdc% in SYS 'GdipDrawLine' .... from the library.
And it still works, how come ??

This is for windows 10.
Svein

Code:
      INSTALL @lib$+"GDIPLIB" : PROC_gdipinit      ON CLOSE PROCexit : QUIT      Pen%=FN_gdipcreatepen(&FF000000,0,1)      PROC_asm : OFF      ON TIME PROCnewpen : RETURN      *REFRESH OFF      REPEAT : CLS        Posx=500 : Posy=500        A%+=1 : Angle=A%        FOR I%=1 TO 12          Angle+=30          FOR J%=1 TO 6            Posx+=100*SINRAD(Angle)            Posy+=100*COSRAD(Angle)            CALL antiline            PROC_gdipline(Pen%,oldx+400,oldy,Posx+400,Posy)            oldx=Posx : oldy=Posy            Angle-=60          NEXT        NEXT        *REFRESH        WAIT 0      UNTIL 0      DEF PROCnewpen      PRIVATE width,adj      IF width=0 THEN width=2 : adj=0.25      width+=adj      IF width>5 OR width<1 THEN adj=-adj      PROC_gdipdeletepen(Pen%)      Pen%=FN_gdipcreatepen(&FF204080,0,width)      ENDPROC      DEF PROC_gdipline(P%, x1, y1, x2, y2)      LOCAL rc{}      DIM rc{l%,t%,r%,b%}      PROC_bbc2api(x1,y1)      PROC_bbc2api(x2,y2)      SYS "SetBoundsRect", @memhdc%, 0, 5      SYS `GdipDrawLine`, FN_gdipg, P%, FN_f4(x1), FN_f4(y1), FN_f4(x2), FN_f4(y2), @memhdc%      SYS "GetBoundsRect", @memhdc%, rc{}, 0      SYS "OffsetRect", rc{}, -@ox%, -@oy%      SYS "InvalidateRect", @hwnd%, rc{}, 0      ENDPROC      DEF PROC_asm      LOCAL var%,code%,pass%,P%,L%,size%      size%=2048      DIM var% NOTEND AND 3, var% 1023      DIM code% NOTEND AND 2047, code% size%-1      FOR pass%=8 TO 10 STEP 2        P%=var% : L%=code%-1        [OPT pass%        .temprc        dd 0 : dd 0 : dd 0 : dd 0        .tempx        dd 0        .tempy        dd 0        .grhdc        dd 0        .two        dd 2        ]          P%=code% : L%=code%+size%-1        [OPT pass%        .antiline        cld        finit        ;SYS "SetBoundsRect", @memhdc%, 0, 5        push 5 ; DCB_ENABLE OR DCB_RESET        push 0        push @memhdc%        call "SetBoundsRect"        ;        ;SYS `GdipDrawLine`, FN_gdipg, P%, FN_f4(x1), FN_f4(y1), FN_f4(x2), FN_f4(y2), @memhdc%        ; push @memhdc%        fld tbyte [^Posy] : call y2api : fstp dword [tempy] : push [tempy]  ;real80 to real32 for gdi+        fld tbyte [^Posx] : call x2api : fstp dword [tempx] : push [tempx]        fld tbyte [^oldy] : call y2api : fstp dword [tempy] : push [tempy]        fld tbyte [^oldx] : call x2api : fstp dword [tempx] : push [tempx]        push Pen%        push [grhdc]        call `GdipDrawLine`        ;        ;SYS "GetBoundsRect", @memhdc%, rc{}, 0        push 0        push temprc        push @memhdc%        call "GetBoundsRect"        ;        ;SYS "OffsetRect", rc{}, -@ox%, -@oy%        push -@oy%        push -@ox%        push temprc        call "OffsetRect"        ;        ;SYS "InvalidateRect", @hwnd%, rc{}, 0        push 0        push temprc        push @hwnd%        call "InvalidateRect"        ret        ;        .y2api        ;y=@vdu%!212-(y+@vdu%!4)/2        fiadd dword [@vdu%+4]        fidiv dword [two]        fild dword [@vdu%+212]        fsub st0,st1        ret        ;        .x2api        ;x=(x+@vdu%!0)/2        fiadd dword [@vdu%]        fidiv dword [two]        ret        ]      NEXT pass%      !grhdc=FN_gdipg      ENDPROC      DEF PROCexit      ON TIME OFF : WAIT 30      PROC_gdipdeletepen(Pen%)      PROC_gdipexit      ENDPROC 
User IP Logged

Richard Russell
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM


Posts: 803
xx Re: Using GDIP with assembler
« Reply #1 on: Oct 25th, 2017, 10:20am »

on Oct 25th, 2017, 01:06am, svein wrote:
Any idea why ?

As far as I can see, there are two principal faults in your code:
  1. Pen% is a variable (it's modified in PROCnewpen) but your assembler code treats it as a constant. To fix this:

    Change this Code:
            push Pen% 

    To this Code:
            push [^Pen%] 

  2. Your y2api subroutine corrupts the floating-point stack (there are more 'pushes' than 'pops'). To fix this:

    Change this Code:
            fsub st0,st1 

    To this Code:
            fsubr 
Quote:
In fact, one can remove or replace @memhdc% in SYS 'GdipDrawLine' .... from the library. And it still works, how come ??

It doesn't still work, or at least not reliably. The @memhdc% activates the Critical Section that protects against concurrent access to the DC from two different threads (Windows DCs are not thread-safe and must be accessed from only one thread at a time). If you omit the @memhdc% you are trusting to luck that the interpreter thread and the GUI thread will not try to access the DC at the same time, which would fail.

Richard.
« Last Edit: Oct 25th, 2017, 10:25am by Richard Russell » User IP Logged

svein
New Member
Image


member is offline

Avatar




PM


Posts: 15
xx Re: Using GDIP with assembler
« Reply #2 on: Oct 26th, 2017, 06:59am »

Thank you !
Went over the code a million times without spotting the errors.
Svein
User IP Logged

Pages: 1  Notify Send Topic Print
« Previous Topic | Next Topic »

| |

This forum powered for FREE by Conforums ©
Terms of Service | Privacy Policy | Conforums Support | Parental Controls