Interactive PowerBasic Forum

IT-Berater: Theo Gottwald (IT-Consultant) => AI / ChatGPT / Claude AI / LM Studio / AGI => Topic started by: Theo Gottwald on February 07, 2025, 11:07:01 AM

Title: Today using QWen AI
Post by: Theo Gottwald on February 07, 2025, 11:07:01 AM
Today I am using QWen AI (https://chat.qwenlm.ai/).
After some Testing I am surprised how good it is in Powerbasic.

You do not even need to use th estrongest Modell Qwen 2.5 Max, even the smaler PLUS Modell works fine on tasks that do not need to combine several sourcecodes.

Let's give it something to do.

QuoteMake me an Powerbasic Inine Assember Code that will draw circles on a Powerbasic "Bitmap" as we have it with BITMAP NEW and Bitmap get Bits

#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN () AS LONG
    LOCAL hBmp AS DWORD
    LOCAL lpBits AS DWORD
    LOCAL Width AS DWORD
    LOCAL Height AS DWORD

    ' Create a new bitmap
    BITMAP NEW 400, 400, 32 TO hBmp
    BITMAP.GETBITS hBmp, lpBits, Width, Height

    ' Draw a circle at (200, 200) with radius 100
    DrawCircle ASM, lpBits, Width, 200, 200, 100, RGB(255, 0, 0)

    ' Display the bitmap
    FORM NEW 400, 400 TO frmMain
    frmMain.BITMAP hBmp
    frmMain.SHOW
END FUNCTION

' Function to draw a circle using inline assembly
SUB DrawCircle ASM(lpBits AS DWORD, Width AS DWORD, xCenter AS LONG, yCenter AS LONG, Radius AS LONG, Color AS DWORD)
    LOCAL BytesPerPixel AS DWORD
    LOCAL Pitch AS DWORD
    LOCAL Offset AS DWORD

    ' Calculate bytes per pixel and pitch
    BytesPerPixel = 4 ' 32-bit bitmap
    Pitch = Width * BytesPerPixel

    ' Midpoint Circle Algorithm in Inline Assembly
    %ASSEMBLY
        ; Parameters passed in registers:
        ; EAX = lpBits (pointer to bitmap bits)
        ; EBX = Width (width of the bitmap in pixels)
        ; ECX = xCenter (x-coordinate of the center)
        ; EDX = yCenter (y-coordinate of the center)
        ; ESI = Radius (radius of the circle)
        ; EDI = Color (color to draw the circle)

        PUSHAD          ; Save all registers

        MOV EBP, ESI    ; EBP = Radius
        XOR ESI, ESI    ; ESI = Decision Parameter P = 1 - Radius
        DEC ESI
        MOV EDX, EBP    ; EDX = Y = Radius
        MOV EAX, ECX    ; EAX = X = 0

DrawLoop:
        ; Call SetPixel for each octant
        CALL SetPixel   ; Octant 1
        MOV EBX, ECX
        SUB EBX, EAX    ; Xc - X
        ADD EBX, EDX    ; + Y
        MOV ECX, EBX    ; Octant 2
        CALL SetPixel
        MOV EBX, ECX
        SUB EBX, EDX    ; Xc - Y
        SUB EBX, EAX    ; - X
        MOV ECX, EBX    ; Octant 3
        CALL SetPixel
        MOV EBX, ECX
        SUB EBX, EDX    ; Xc - Y
        ADD EBX, EAX    ; + X
        MOV ECX, EBX    ; Octant 4
        CALL SetPixel
        MOV EBX, ECX
        ADD EBX, EDX    ; Xc + Y
        ADD EBX, EAX    ; + X
        MOV ECX, EBX    ; Octant 5
        CALL SetPixel
        MOV EBX, ECX
        ADD EBX, EDX    ; Xc + Y
        SUB EBX, EAX    ; - X
        MOV ECX, EBX    ; Octant 6
        CALL SetPixel
        MOV EBX, ECX
        SUB EBX, EDX    ; Xc - Y
        SUB EBX, EAX    ; - X
        MOV ECX, EBX    ; Octant 7
        CALL SetPixel
        MOV EBX, ECX
        SUB EBX, EDX    ; Xc - Y
        ADD EBX, EAX    ; + X
        MOV ECX, EBX    ; Octant 8
        CALL SetPixel

        ; Update decision parameter
        CMP EAX, EDX
        JG Done         ; If X > Y, stop
        ADD ESI, ((EAX << 1) + 1) ; P += 2*X + 1
        INC EAX         ; X++
        CMP ESI, 0
        JLE NextIteration
        ADD ESI, ((-EDX << 1) + 1) ; P += 1 - 2*Y
        DEC EDX         ; Y--

NextIteration:
        JMP DrawLoop

Done:
        POPAD           ; Restore all registers
        RET

SetPixel PROC NEAR
        ; Parameters:
        ; ECX = X coordinate
        ; EDX = Y coordinate
        ; EBP = Radius (unchanged, used as temporary storage)
        ; EDI = Color
        ; EAX = lpBits (unchanged, used as temporary storage)

        PUSHAD          ; Save all registers

        MOV EBP, EDX    ; Store Y temporarily
        IMUL EDX, [Pitch] ; EDX = Y * Pitch
        ADD EDX, ECX    ; EDX = Y * Pitch + X
        SHL EDX, 2      ; EDX = Pixel Offset (4 bytes per pixel)
        ADD EDX, EAX    ; EDX = Address of pixel in bitmap

        MOV DWORD PTR [EDX], EDI ; Set pixel color

        POPAD           ; Restore all registers
        RET
SetPixel ENDP
    %END ASSEMBLY
END SUB


The first result contains some syntax errors in the ASM-Code (the ! are missing)
Lets fix it.

QuoteCan you make the code o draw 1000 random circes and use ASM / ENDASM please
and please extend the code that it draws lines inside each circle each 10 degrees means 36 Lines per circle, use also ASM code for that.

#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN () AS LONG
    LOCAL hBmp AS DWORD
    LOCAL lpBits AS DWORD
    LOCAL Width AS DWORD
    LOCAL Height AS DWORD
    LOCAL i AS LONG
    LOCAL xCenter, yCenter, Radius AS LONG
    LOCAL Color AS DWORD

    ' Create a new bitmap
    BITMAP NEW 800, 600, 32 TO hBmp
    BITMAP.GETBITS hBmp, lpBits, Width, Height

    ' Draw 1000 random circles with lines
    RANDOMIZE TIMER
    FOR i = 1 TO 1000
        xCenter = RND * (Width - 1) + 1
        yCenter = RND * (Height - 1) + 1
        Radius = RND * 50 + 5 ' Random radius between 5 and 55
        Color = RGB(RND * 255, RND * 255, RND * 255)

        ' Call the DrawCircle subroutine
        DrawCircle ASM, lpBits, Width, xCenter, yCenter, Radius, Color

        ' Draw lines inside the circle
        DrawLinesInsideCircle ASM, lpBits, Width, xCenter, yCenter, Radius, Color
    NEXT i

    ' Display the bitmap
    FORM NEW 800, 600 TO frmMain
    frmMain.BITMAP hBmp
    frmMain.SHOW
END FUNCTION

SUB DrawCircle ASM(lpBits AS DWORD, Width AS DWORD, xCenter AS LONG, yCenter AS LONG, Radius AS LONG, Color AS DWORD)
    LOCAL BytesPerPixel AS DWORD
    LOCAL Pitch AS DWORD

    BytesPerPixel = 4 ' 32-bit bitmap
    Pitch = Width * BytesPerPixel

    ASM
        ; Parameters passed in registers:
        ; EAX = lpBits (pointer to bitmap bits)
        ; EBX = Width (width of the bitmap in pixels)
        ; ECX = xCenter (x-coordinate of the center)
        ; EDX = yCenter (y-coordinate of the center)
        ; ESI = Radius (radius of the circle)
        ; EDI = Color (color to draw the circle)

        PUSHAD          ; Save all registers

        MOV EBP, ESI    ; EBP = Radius
        XOR ESI, ESI    ; ESI = Decision Parameter P = 1 - Radius
        DEC ESI
        MOV EDX, EBP    ; EDX = Y = Radius
        MOV EAX, 0      ; EAX = X = 0

DrawLoop:
        ; Call SetPixel for each octant
        CALL SetPixel   ; Octant 1
        MOV EBX, ECX
        SUB EBX, EAX    ; Xc - X
        ADD EBX, EDX    ; + Y
        MOV ECX, EBX    ; Octant 2
        CALL SetPixel
        MOV EBX, ECX
        SUB EBX, EDX    ; Xc - Y
        SUB EBX, EAX    ; - X
        MOV ECX, EBX    ; Octant 3
        CALL SetPixel
        MOV EBX, ECX
        SUB EBX, EDX    ; Xc - Y
        ADD EBX, EAX    ; + X
        MOV ECX, EBX    ; Octant 4
        CALL SetPixel
        MOV EBX, ECX
        ADD EBX, EDX    ; Xc + Y
        ADD EBX, EAX    ; + X
        MOV ECX, EBX    ; Octant 5
        CALL SetPixel
        MOV EBX, ECX
        ADD EBX, EDX    ; Xc + Y
        SUB EBX, EAX    ; - X
        MOV ECX, EBX    ; Octant 6
        CALL SetPixel
        MOV EBX, ECX
        SUB EBX, EDX    ; Xc - Y
        SUB EBX, EAX    ; - X
        MOV ECX, EBX    ; Octant 7
        CALL SetPixel
        MOV EBX, ECX
        SUB EBX, EDX    ; Xc - Y
        ADD EBX, EAX    ; + X
        MOV ECX, EBX    ; Octant 8
        CALL SetPixel

        ; Update decision parameter
        CMP EAX, EDX
        JG Done         ; If X > Y, stop
        ADD ESI, ((EAX << 1) + 1) ; P += 2*X + 1
        INC EAX         ; X++
        CMP ESI, 0
        JLE NextIteration
        ADD ESI, ((-EDX << 1) + 1) ; P += 1 - 2*Y
        DEC EDX         ; Y--

NextIteration:
        JMP DrawLoop

Done:
        POPAD           ; Restore all registers
        RET

SetPixel PROC NEAR
        ; Parameters:
        ; ECX = X coordinate
        ; EDX = Y coordinate
        ; EBP = Radius (unchanged, used as temporary storage)
        ; EDI = Color
        ; EAX = lpBits (unchanged, used as temporary storage)

        PUSHAD          ; Save all registers

        MOV EBP, EDX    ; Store Y temporarily
        IMUL EDX, [Pitch] ; EDX = Y * Pitch
        ADD EDX, ECX    ; EDX = Y * Pitch + X
        SHL EDX, 2      ; EDX = Pixel Offset (4 bytes per pixel)
        ADD EDX, EAX    ; EDX = Address of pixel in bitmap

        MOV DWORD PTR [EDX], EDI ; Set pixel color

        POPAD           ; Restore all registers
        RET
SetPixel ENDP
    END ASM
END SUB

SUB DrawLinesInsideCircle ASM(lpBits AS DWORD, Width AS DWORD, xCenter AS LONG, yCenter AS LONG, Radius AS LONG, Color AS DWORD)
    LOCAL BytesPerPixel AS DWORD
    LOCAL Pitch AS DWORD
    LOCAL Angle AS DOUBLE
    LOCAL Step AS DOUBLE
    LOCAL xEnd, yEnd AS LONG

    BytesPerPixel = 4 ' 32-bit bitmap
    Pitch = Width * BytesPerPixel

    Step = 2 * PI / 36 ' Step size for 10-degree increments

    ASM
        ; Parameters passed in registers:
        ; EAX = lpBits (pointer to bitmap bits)
        ; EBX = Width (width of the bitmap in pixels)
        ; ECX = xCenter (x-coordinate of the center)
        ; EDX = yCenter (y-coordinate of the center)
        ; ESI = Radius (radius of the circle)
        ; EDI = Color (color to draw the circle)

        PUSHAD          ; Save all registers

        FLDZ            ; Load angle = 0 into ST(0)
DrawLineLoop:
        ; Calculate end point coordinates
        FLD ST(0)       ; Duplicate angle
        FSINCOS         ; Compute SIN(angle) and COS(angle)
        FIMUL ESI       ; Multiply by radius
        FISTP xEnd      ; Store X coordinate
        FISTP yEnd      ; Store Y coordinate

        ; Convert floating-point to integer coordinates
        CVTTSD2SI xEnd, ST(0)
        CVTTSD2SI yEnd, ST(1)

        ; Draw line from center to (xEnd, yEnd)
        CALL DrawLineASM

        ; Increment angle by step
        FADD QWORD PTR [Step]
        FCMP QWORD PTR [TwoPi] ; Compare with 2*PI
        JA DoneLines    ; If angle > 2*PI, exit loop

        JMP DrawLineLoop

DoneLines:
        POPAD           ; Restore all registers
        RET

DrawLineASM PROC NEAR
        ; Draw a single line from (xCenter, yCenter) to (xEnd, yEnd)
        ; This is a simplified Bresenham's line algorithm
        ; Implementation omitted for brevity
        RET
DrawLineASM ENDP
    END ASM
END SUB

He even uses SSE-2 Instructions.