Oxygen Basic
Programming => Problems & Solutions => Topic started by: helloworld on June 19, 2017, 03:47:46 AM
-
This is the function I am writing about:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd183494(v=vs.85).aspx
I can set up the DIB and use GDI functions with it. But I cannot write to the bitmap bits directly - then the app crashes.
It works in C++ and the problem seems to be the transliteration of the pointer to the pointer to the bits. In C++ it works this way:
HBITMAP dibm;
int* bits;
dibm = CreateDIBSection(dc, (const BITMAPINFO*)&bitmapinfoheader, DIB_RGB_COLORS, (void**) &bits, NULL, 0);
// then I can write at x,y:
bits[y*SCANLINELEN+x]=RGB(r,g,b);
Now the Oxygen Basic code. When I write to x,y, app crashes. When I use GDI on the DIB, it works:
sys dibm;
int* bits;
dibm = CreateDIBSection(dc, @bitmapinfoheader, DIB_RGB_COLORS, @@bits, NULL, 0);
' when I write to x,y, app crashes:
bits[y*SCANLINELEN+x]=RGB(r,g,b);
Q: How to put the right value into the pointer variable?
Also:
When I import the BOOL GDIflush(void) function like so:
extern lib "gdi32.dll"
! gdiflush() as sys
end extern
and when I use it, OB just prints out "gdiflush" and exits :D
also $/examples/Asm64/HelloWorld64.o2bas does not build: linker finds "unidentified names", namely messagebox. [version=A43 12:29 22/05/2017]
.
-
helloworld,
! GdiFlush() as sys 'requires precise capitalisation
What prototype, if any, are you using for CreateDIBSection?
You could try byval @@bits
I see the HelloWorld64 problem and will try to rectify soonest.
-
What prototype, if any, are you using for CreateDIBSection?
You could try byval @@bits
None. Anyway the compiler requires #long#long#long#long#long#long. Byval (in the call I assume) does not work.
And thanks, GdiFlush works now.
-
helloworld
do you can post whole example that we can see what is what
also bitmap DIB require that you must know what kind of bitmap is
4,8,16,32 ..right? ..or not ?
-
You can check whether the function has returned a valid bits pointer:
print @bits
-
Are you using indexbase 0 ?
The default is indexbase 1, which would corrupt the preceding variable space when attempting to write to bits[0].
-
Are you using indexbase 0 ?
The default is indexbase 1, which would corrupt the preceding variable space when attempting to write to bits[0].
That has been it! Thank you.
@Aurel
Here the (working) code for reference:
includepath "$/inc/"
indexbase 0
#include "MinWin.inc"
#define SRCCOPY 0xCC0020
#define BLACKNESS 0x42
#define WHITENESS 0xFF0062
#define SCANLEN 1280
type BITMAPINFOHEADER
DWORD biSize
LONG biWidth
LONG biHeight
WORD biPlanes
WORD biBitCount
DWORD biCompression
DWORD biSizeImage
LONG biXPelsPerMeter
LONG biYPelsPerMeter
DWORD biClrUsed
DWORD biClrImportant
end type
dim bmih as BITMAPINFOHEADER, dc0 as sys, dc1 as sys, bits as integer ptr
extern lib "Gdi32.dll"
! CreateDIBSection
! GdiFlush
end extern
#lookahead ' for procedures
s=error() : if s then: print s : end : end if
dim cmdline as asciiz ptr, inst as sys
&cmdline=GetCommandLine
inst=GetModuleHandle 0
WinMain inst,0,cmdline,SW_NORMAL
end
Function WinMain(sys inst, prevInst, asciiz*cmdline, sys show) as sys
WndClass wc
MSG wm
sys hwnd, wwd, wht, wtx, wty, tax
wc.style = CS_HREDRAW or CS_VREDRAW
wc.lpfnWndProc = @WndProc
wc.cbClsExtra =0
wc.cbWndExtra =0
wc.hInstance =inst
wc.hIcon=LoadIcon 0, IDI_APPLICATION
wc.hCursor=LoadCursor 0,IDC_ARROW
wc.hbrBackground = GetStockObject WHITE_BRUSH
wc.lpszMenuName = null
wc.lpszClassName = strptr "dib"
RegisterClass (@wc)
Wwd = 640 : Wht = 400
Tax = GetSystemMetrics SM_CXSCREEN
Wtx = (Tax - Wwd) /2
Tax = GetSystemMetrics SM_CYSCREEN
Wty = (Tax - Wht) /2
hwnd = CreateWindowEx 0,wc.lpszClassName,"dib",WS_OVERLAPPEDWINDOW,Wtx,Wty,Wwd,Wht,0,0,inst,0
ShowWindow hwnd,SW_SHOW
UpdateWindow hwnd
sys ret
do while ret := GetMessage &wm, 0, 0, 0
if ret = -1 then
'show an error message
else
TranslateMessage &wm
DispatchMessage &wm
end if
wend
End Function
function WndProc (hWnd, wMsg, wParam, lparam) as sys callback
select wmsg
case WM_CREATE
dc0=GetDC(NULL)
dc1=CreateCompatibleDC(dc0)
bmih = {sizeof(BITMAPINFOHEADER), 1280, -1024, 1, 32, 0, 0, 0, 0, 0, 0}
dibm=CreateDIBSection(dc1, @bmih, 0, @@bits, NULL, 0)
if dc0==NULL or dc1==NULL or dibm==NULL then DestroyWindow(hwnd)
SelectObject(dc1,dibm)
ReleaseDC(hwnd,dc0)
case WM_DESTROY
deleteobject(dibm)
deleteobject(dc1)
PostQuitMessage 0
case WM_PAINT
paint hwnd,dc1
case WM_KEYDOWN
keydown hwnd,wparam,lparam
case else
function=DefWindowProc hWnd,wMsg,wParam,lParam
end select
end function
function paint(hwnd,dc1)
rect rc
paintstruct ps
getclientrect hwnd,&rc
dc=beginpaint hwnd,&ps
BitBlt dc1, 0,0, 640,400, NULL, 0, 0, WHITENESS
gdiflush
fillr(bits, 10,10,100,100,0xFF0000)
/*
for i=0 to 1280*10-1
bits[i]=0xFF
next
*/
BitBlt(dc, 0,0, rc.right-rc.left,rc.bottom-rc.top, dc1, 0, 0, SRCCOPY)
endpaint hwnd,&ps
end function
function keydown(hwnd,wparam,lparam)
if wparam==0x1B 'escape
sendmessage hwnd,WM_CLOSE,0,0
end if
end function
function fillr(bm as integer ptr, x as dword,y as dword,w as dword,h as dword,col as dword)
int* bits=@bm
pitch=(SCANLEN-w)*4
@bits+=(y*SCANLEN+x)*4
for i=0 to <h
for j=0 to <w
bits=col : @bits+=4
next
@bits+=pitch
next
end function
-
OB does not do even minimal optimisation. So I wonder how to use the assembler? Fragment below does not work.
Btw, Oxide has severe issues:
It may "eat" characters: it may do stuff like open the "save" dialogue, start code etc, when coding and typing i.e. "s" or "e".
Do you really use it for coding?
function fillr(bm as integer ptr, x as dword,y as dword,w as dword,h as dword,col as dword)
int* bits
int pitch
/*
@bits=@bm
pitch=(SCANLEN-w)*4
@bits+=(y*SCANLEN+x)*4
for i=0 to <h
for j=0 to <w
bits=col
@bits+=4
next
@bits+=pitch
next
*/
mov eax,bm ; @bits=@bm
mov bits,eax
mov ecx,1280 ; pitch=(SCANLEN-w)*4
sub ecx,w
shl ecx,2
mov pitch,ecx
mov eax,1280 ; @bits+=(y*SCANLEN+x)*4
mul y
add eax,x
shl eax,2
add bits,eax
mov eax,col
mov edx,bits
._for1 ; for i=0 to <h
dec h
jz _exitfor1
mov ecx,w
._for2 ; for j=0 to <w
dec ecx
jz _exitfor2
mov [edx],eax ; bits=col
add edx,4 ; @bits+=4
jmp _for2
._exitfor2
add edx,pitch ; @bits+=pitch
jmp _for1
._exitfor1
._leave
xor eax,eax
end function
-
I use Oxide for most of my code testing without the 's' and 'e' problems you describe.
But when the control key is held down, a second 's' or 'e' keypress will insert ascii 19 or ascii 5 into the text. Which is an occasional nuisance that needs to be fixed.
re: assembler
You can display the assembly code generated by any line of basic by inserting #show at the beginning of the line.
Optimisation is a work in progress, but the gains from hand-written asm are usually small, and maintaining 32-bit and 64-bit compatibility can be tricky.
To resolve the address of any variable, including pointered variables, use the pseudo-instruction addr
addr eax,bm
-
HelloWorld64 fix:
https://github.com/Charles-Pegge/OxygenBasic/blob/master/Oxygen.zip
And the attached Oxide should be free of any ctrl-s and Ctrl-e problems:
.
-
I use Oxide for most of my code testing without the 's' and 'e' problems you describe.
The problem may have been due to keyboard layout..
I.e., it arised when I type the open bracket "[" (to do so, on my keyboard I have to prefix "Alr Gr"-key a.k.a. the right-side "Alt"-key) followed by i.e. "e" (->execute) or "s" (->save).
And now is fixed. :)
Other issues:
-The -a option to co2.exe is quite useless, because the listing is normally longer than the display height. Output shoud happen to file instead.
-It seems that it is not possible to transfer pointers via asm (!): there is no equivalent to @pointer1=@pointer2 witout knowing the stack position of the pointers?
-
Glad it worked for you :)
re co2:
You can output asm to text file:
co2 -a -m prog.o2bas > t.txt
re: transferring pointers in asm:
One crude solution is to embed the basic line into your asm.
push edi
@pointer1 = @pointer2
pop edi
but what I need to do is support @: addr eax,@pointer1
then this will be possible:
addr edx,@pointer1
addr eax,pointer2
mov [ecx],eax
Another solution is to go C :o
I have not tested this in depth yet, but it certainly works for simple expressions.
#cpointer on
'pointer1=pointer2
mov eax,pointer2
mov pointer1,eax
#cpointer off
-
You can output asm to text file:
co2 -a -m prog.o2bas > t.txt
My bad. I tried the pipe, but missed out the -m option :D
re: transferring pointers in asm:
I found this works:
dim p1 as integer ptr
dim p2 as integer ptr
dim a as integer
a=99
@p1=@a
(
mov eax,@p1
mov @p2,eax
)
print p2
But this does not:
dim as integer ptr p1
dim as integer ptr p2
dim a as integer
a=99
@p1=@a
(
mov eax,@p1
mov @p2,eax
)
print p2
This also works:
int* p1
int* p2
int a
a=99
@p1=@a
(
mov eax,@p1
mov @p2,eax
)
print p2