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.