Author Topic: Example how to use GLUT/OpenGL in OSX (Intel macho32)  (Read 31070 times)

Offline Stino

  • Jr. Member
  • *
  • Posts: 9
Example how to use GLUT/OpenGL in OSX (Intel macho32)
« on: May 15, 2011, 01:21:11 PM »
Hi All,
yesterday evening I looked around if there in the web some useful examples how to program assembler in OSX. Long long time ago I coded a bit assembler for C64, DOS and Windows, but after my study ends I find not longer enough time assembler coding. Today I have a Mac and for unknown reason just yesterday I get the idea to code a bit assembler that runs under OSX.

Well, any start or restart is hard and so I search in web for some examples. Unfortunately there are only examples out there that shows how to put "Hallo World" to the console and explain something about an strange "16-byte-aglinment"? I start with them and they work, but I want to see some more graphic. Since each Mac is shipped with OpenGL I use this first.

I began with the OpenGL init code but always get those strange "wrong alinement" crashes of my program. I need a few hours until I understand the two problems my code has. Because gdb is really a crap debugger for assembler code! Anyone knows a better debugger for assembler code that runs with OSX?  ???

First problem was that external functions not clean the stack of the used parameter ("push para1", "push para2",...) as I know this from other systems (e.g. Windows-API-calls returns with "ret 12", "ret 8" and "ret ..." to clean the stack). But OSX functions never clean the stack! Always the caller have to this by "pop register" or "add esp,4".

Second problem was the "16-byte-aglinment". If you call an external function your stack should have always a multiple of 16 byte on the stack. If not the external function call will crash! This is really a pain in the a*s! You will start in each function (like _main) with an alinement of zero. Just calling an external function now will crash since the "call" opcode it self pushed the 4-Byte back jump on the stack. But 4 is no multiple of 16 byte. So before doing the call you have to push 12 byte to stack with either 3x useless 4-byte "push" or 1x "sub esp,12" and than the call will be work fine. But after call finishes we have to clean those pushes with either 3x useless 4-byte "pop" or 1x "add esp,12". If your external call function has parameters you joust have to correct the difference of the parameter size to get always in time of call an multiple of 16 bytes. After call come back you have to clean these correction and also the parameters of the call it self (see first problem). Well naturally you can do both corrections with one "add esp,xx".
In my example I make in function "_main" these to corrections step by step to show how it works. In function "_display_func" I do these correction in one step.

Now I understand why there are only a few examples out there, but I hope this example will help others to understand the problems and will leeds to more assembler code for OSX.

Let us all hack and rock those Mac's!  ;D

Here the example code that init GLUT and paint an colored triangle with OpenGL into the window. It is only 32-bit code because I have not learned yet the 64-bit opcodes.
Code: [Select]
;
; Basic OS X calls to GLUT and OpenGL
;
; Example by Stino / former ByTeGeiZ
;
; compile with:
; nasm -g -f macho32 bspGLUT.asm
; gcc -framework GLUT -framework OpenGL -m32 -o bspGLUT.out bspGLUT.o
;

%define GLUT_RGB            0
%define GLUT_SINGLE         0

%define GL_POLYGON          9
%define GL_COLOR_BUFFER_BIT 0x00004000   

; GLUT stuff
extern _glutCreateWindow, _glutInit, _glutInitDisplayMode, _glutDisplayFunc, _glutMainLoop, _glutInitWindowPosition, _glutInitWindowSize, _glutSwapBuffers
; OpenGL stuff
extern _glClearColor, _glClear, _glBegin, _glEnd, _glFlush, _glVertex3f, _glColor3f
 
; static data
segment .data
 
window_name: db "OpenGL on OSX with nasm", 10, 0
fl_one: dd 1.0
fl_neg_one: dd -1.0
fl_zero: dd 0.0
fl_half: dd 0.5
fl_neg_half: dd -0.5
 
; code
segment .text
 
global _main

; the main function that init OpenGL and install the gl draw function (_display_func)
_main:
        ;alignment = 0

        lea  ecx, [esp+4]            ;load adress of argc in stack to ecx
        lea  edx, [esp+8]            ;load adress of argv in stack to edx

        push ebp ; setup the frame   ;alignment => 4
        mov  ebp, esp

        push edx                     ;alignment => 8
        push ecx                     ;alignment => 12
        call _glutInit               ;alignment => 16 -> alignment <= 12 (after backjump with "ret")
        add  esp, 8                  ;alignment <= 4 (caller has to clean call paras (8 byte))


        sub esp, 4                   ;alignment => 8 (correction need to get to 16 at next call !)
        mov eax, GLUT_RGB
        or  eax, GLUT_SINGLE
        push eax                     ;alignment => 12
        call _glutInitDisplayMode    ;alignment => 16 -> alignment <= 12
        add  esp, 4                  ;alignment <= 8 (caller has to clean call paras (4 byte))
        add  esp, 4                  ;alignment <= 4 (clean last the allignment correction)


        push dword 80                ;alignment => 8
        push dword 80                ;alignment => 12
        call _glutInitWindowPosition ;alignment => 16 -> alignment <= 12
        add  esp, 8                  ;alignment <= 4 (caller has to clean call paras (8 byte))


        push dword 300               ;alignment => 8
        push dword 400               ;alignment => 12
        call _glutInitWindowSize     ;alignment => 16 -> alignment <= 12
        add  esp, 8                  ;alignment <= 4 (caller has to clean call paras (8 byte))


        sub esp, 4                   ;alignment => 8 (correction need to get to 16 at next call !)
        mov  eax, dword window_name
        push eax                     ;alignment => 12
        call _glutCreateWindow       ;alignment => 16 -> alignment <= 12
        add  esp, 4                  ;alignment <= 8 (caller has to clean call paras (4 byte))
        add  esp, 4                  ;alignment <= 4 (clean last the allignment correction)


        sub esp, 4                   ;alignment => 8 (correction need to get to 16 at next call !)
        push dword _display_func     ;alignment => 12
        call _glutDisplayFunc        ;alignment => 16 -> alignment <= 12
        add  esp, 4                  ;alignment <= 8 (caller has to clean call paras (4 byte))
        add  esp, 4                  ;alignment <= 4 (clean last the allignment correction)


        sub esp, 8                   ;alignment => 12 (correction need to get to 16 at next call !)
        call _glutMainLoop           ;alignment => 16 -> alignment <= 12
        add  esp, 8                  ;alignment <= 4 (caller has to clean call paras (8 byte))

_pass_exit:
        pop  ebp                     ;alignment <= 0
        ret
         

; the gl draw function (here is the content of OpenGL
_display_func:

        sub     esp,8
        push    dword GL_COLOR_BUFFER_BIT
        call    _glClear
        add     esp,12

        sub     esp,8
        push    dword GL_POLYGON
        call    _glBegin
        add     esp,12

        push    dword 0
        push    dword 0
        push    dword [fl_one]
        call    _glColor3f
        add     esp,12

        push    dword 0
        push    dword [fl_neg_half]
        push    dword [fl_neg_half]
        call    _glVertex3f
        add     esp,12

        push    dword 0
        push    dword [fl_one]
        push    dword 0
        call    _glColor3f
        add     esp,12

        push    dword 0
        push    dword [fl_neg_half]
        push    dword [fl_half]
        call    _glVertex3f
        add     esp,12

        push    dword [fl_one]
        push    dword 0
        push    dword 0
        call    _glColor3f
        add     esp,12

        push    dword 0
        push    dword [fl_half]
        push    dword 0
        call    _glVertex3f
        add     esp,12

        sub     esp,12
        call    _glEnd
        add     esp,12

        sub     esp,12
        call    _glFlush
        add     esp,12

        ret

You need to create an running binary the "Xcode developer tools" (for "gcc", "ld", GLUT- and OpenGL- frameworks) and of curse "NASM" for Mac.  ;)

Compile code with:
nasm -g -f macho32 bspGLUT.asm
gcc -framework GLUT -framework OpenGL -m32 -o bspGLUT.out bspGLUT.o

And run binary:
./bspGLUT.out

Instate of declare all the external functions and constants in one code file as I did in example it will be helpful to have GLUT and OpenGL in some include files (*.inc). Has someone still done the job for all the OpenGL API files?  ???

Happy coding and greetings from Stino
(former ByTeGeiZ)
« Last Edit: May 15, 2011, 01:22:45 PM by Stino »

Offline Keith Kanios

  • Full Member
  • **
  • Posts: 383
  • Country: us
    • Personal Homepage
Re: Example how to use GLUT/OpenGL in OSX (Intel macho32)
« Reply #1 on: May 15, 2011, 03:52:35 PM »
Yep, good work.

Most of the ABI specifics can be found HERE (developer.apple.com). For 64-bit, Mac follows the System V AMD64 ABI.

I have a 32-bit/64-bit Quartz (Core Graphics) based Hello, World! example HERE that may help you transition to 64-bit. It is fairly verbose (i.e. not optimized) for the sake of clarity.

You'll also see some syscalls... they are simply based on FreeBSD.

As for the GLUT/OpenGL inc files, while those can be fairly easily (but tediously) transcribed from equivalent C header files, I am not aware of anyone who has developed a complete equivalent for NASM. This is something that would be great fit for the NASMX Project.

Offline Stino

  • Jr. Member
  • *
  • Posts: 9
Re: Example how to use GLUT/OpenGL in OSX (Intel macho32)
« Reply #2 on: May 15, 2011, 08:36:18 PM »
You'll also see some syscalls... they are simply based on FreeBSD.

I was wondering why there exists examples that uses software interrupts like in DOS times (with "int" opcode) to call a system function while others examples often use the same functionality with normal "call" opcode inside libraries.

Thanks to you I know now that there are part of OSX FreeBSD base layer.  :) Exists there an documentation for all these FreeBSD syscalls?  ???

Quote
As for the GLUT/OpenGL inc files, while those can be fairly easily (but tediously) transcribed from equivalent C header files, I am not aware of anyone who has developed a complete equivalent for NASM. This is something that would be great fit for the NASMX Project.

That sounds to me like an hint to start the job.  ::)
Well since I'm maybe the only person that is interested in this I did the job. It was really no hard job if you know how to use macros in VIM and whats this "search&replace" all about.  ;)

The "typedef" are not longer useful with NASM, but I let them in the files as comments to give the programmer the possibility of a quick overview about the byte lengths of the data types.

gl.inc
glut.inc

Simply add them as includes to your code:
%include "gl.inc"
%include "glut.inc"

Offline Stino

  • Jr. Member
  • *
  • Posts: 9
Re: Example how to use GLUT/OpenGL in OSX (Intel macho32)
« Reply #3 on: May 15, 2011, 09:02:59 PM »
For 64-bit, Mac follows the System V AMD64 ABI.

Hey! Really cool demo how to use Quartz graphics!  8)

I read over this before since I was thinking this was just the link to the text based 64-bit hello-world-demo that I saw somewhere in web (that one uses "int 0x80" syscalls).

But I will need a while to understand the code. For me it was just possible to create a 32-bit binary. If I create a 64-bit binary it crashes at run time with an SIGSEGV. I have an 64-bit machine with SL. So I guess that apple has changed the ABI a bit... or I link it wrong...?

Addition:
I get the 64-bit running now! My problem was that I tried to link through the "gcc" instead of using "ld" directly as it was suggested in the comments of the file.  ::)
« Last Edit: May 15, 2011, 09:11:39 PM by Stino »

Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 429
  • Country: us
Re: Example how to use GLUT/OpenGL in OSX (Intel macho32)
« Reply #4 on: May 15, 2011, 09:52:31 PM »

A possible optimization that can be made when calling multiple cdecl-style functions (those that don't clean up the stack) is, at the beginning of your own function, simply subtract from esp the largest amount of bytes required by one of the subfunctions then not worry about popping or add exp, XX until the end of the function.
Of course, you have to use mov rather than push instructions.

For example:

Code: [Select]
;prologue
   push ebp
   mov  ebp, esp
   sub  esp, 32    ; <-- make sure this is multiple of 16
   .
   .
   mov [esp+4], edx
   mov [esp], ecx
   call SomeFunction
   .
   .
   mov [esp+12], eax
   mov [esp+8], ebx
   mov [esp+4], ecx
   mov [esp], edx
   call SomeOtherFunction

;epilogue
   add esp, 32
   mov esp, ebp
   pop ebp
   ret

Please note that this same technique can work in both 32/64 bit environments ONLY IF your function does not call a pascal/fastcall/stdcall type function that executes a [/b]ret XX[/b].

This is something that I've implemented in NASMX but it is only useful in very specific situations.

And as Keith mentioned, having GLUT/GL headers available in NASMX would indeed be a great fit!
As Mach-O is one of the targets to be supported with NASMX perhaps you can help out with this as well?   Feeling ambitious?  ;D

Offline Stino

  • Jr. Member
  • *
  • Posts: 9
Re: Example how to use GLUT/OpenGL in OSX (Intel macho32)
« Reply #5 on: May 16, 2011, 07:39:40 PM »

A possible optimization that can be made when calling multiple cdecl-style functions (those that don't clean up the stack) is, at the beginning of your own function, simply subtract from esp the largest amount of bytes required by one of the subfunctions then not worry about popping or add exp, XX until the end of the function.
Of course, you have to use mov rather than push instructions.

Very interesting approach to get rid of all those problematic 16-bit-alinement stuff inside an sub function. So I was give it a try in one of my functions to see how it works.

One thing I saw was that it will not work if you make an stack frame with "sub esp,16/32/.." and "add esp,16/32/..". But this is just because each "call" opcode make his own 4-byte-push to stack (cleaned later automatic with "ret") and after this push we have to reach the multiple of 16. We have to correct the frame by subtract of 4 byte and your idea works like hell.  8) Stack frame start than with "sub esp,12/28/.." and ends with "add esp,12/28/..".

What I did with my OpenGL timer function:
Code: [Select]
_timer_func:
        sub     esp,28

        mov     eax, [window_handle]
        mov     [esp],eax
        call    _glutSetWindow

        call    _glutPostRedisplay

        mov     [esp+8], dword 0
        mov     [esp+4], dword  _timer_func
        mov     [esp], dword 40
        call    _glutTimerFunc

        add     esp,28
        ret

Thanks for the good idea!

Offline Stino

  • Jr. Member
  • *
  • Posts: 9
Re: Example how to use GLUT/OpenGL in OSX (Intel macho32)
« Reply #6 on: May 16, 2011, 08:02:50 PM »
I have another question. Does someone know how I can sync my OpenGL graphic draw code with vertical retrace? I was googling for this an it seems that OpenGL only support for Windows this functionality, but this is no generic function of OpenGL. Very strange cause this should be a basic of all graphic libraries to make clean drawings (without raster fragments) to a screen.

Or is there maybe an Quartz function of OSX I can use to sync my code with VBLANK?  ???
« Last Edit: May 16, 2011, 08:05:10 PM by Stino »

Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 429
  • Country: us
Re: Example how to use GLUT/OpenGL in OSX (Intel macho32)
« Reply #7 on: May 16, 2011, 09:15:46 PM »
One thing I saw was that it will not work if you make an stack frame with "sub esp,16/32/.." and "add esp,16/32/..". But this is just because each "call" opcode make his own 4-byte-push to stack (cleaned later automatic with "ret") and after this push we have to reach the multiple of 16. We have to correct the frame by subtract of 4 byte and your idea works like hell.  8) Stack frame start than with "sub esp,12/28/.." and ends with "add esp,12/28/..".

Thanks for the good idea!

Usually when a function makes multiple calls it will have a local stack area to maintain data.  Thus, in my code above you will see the push ebp which makes the stack aligned to 8.  Then once you've factored in all your local variables the final alignment is implemented with something like this:

Code: [Select]
        ; %$__nx_locnt context var contains total stack used calculated thus far
%assign %%__off (((%$__nx_locnt + 16) / 16) * 16)
%assign %%__tmp (%$__nx_locnt + 16)
%if (%%__off != %%__tmp)
%assign %$__nx_locnt %%__off
%endif
sub esp, %$__nx_locnt

Your code reminds me that I need to revisit the callstack optimization code to account for functions with no locals.  So thank you for that. ;)


Offline Stino

  • Jr. Member
  • *
  • Posts: 9
Re: Example how to use GLUT/OpenGL in OSX (Intel macho32)
« Reply #8 on: May 17, 2011, 07:06:01 PM »
I solve missing VSYNC problem at least in OpenGL on OSX.  :)

After I start my OpenGL demo I saw that the created GLUT window offers a menu to enable/disable vertical blank in GLUT.
I can be found under: "program name" -> "Preferences..." -> "Default Syncronize to Vertical Blank"
If you enable this value you will have VSYNC after close and restart of your program (it seems that GLUT read this value just at init time.

I trace my program with fseventer to see in which files it save its data and see it was in /Users/[your_homedir]/Library/Preferences/com.apple.glut.plist. A look into the config file shows quick that the interesting value is called GLUTSyncToVBLKey.

So now you can check or set this value on terminal.
Read it out with: 
defaults read com.apple.glut GLUTSyncToVBLKey
Enable it with:
defaults write com.apple.glut GLUTSyncToVBLKey 1
Disable it with:
defaults write com.apple.glut GLUTSyncToVBLKey 0

Or enable it direct in your assembler program before initialize GLUT stuff:

Code: [Select]
extern _system
...
segment .data
enable_glut_vsync_command: db "defaults write com.apple.glut GLUTSyncToVBLKey 1", 10, 0
...
segment .text
mov     [esp],dword enable_glut_vsync_command
call    _system
...
[init OpenGL]
...

Anyway I'm still interest to know how VSYNC works with Quartz...

Offline Stino

  • Jr. Member
  • *
  • Posts: 9
Next example
« Reply #9 on: May 17, 2011, 07:44:04 PM »
Time for OpenGL example number two.

It needs the two include files I offer for download in a former post her in thread:
gl.inc
glut.inc

This is more an HowTo demo with some comments to explain it. My finally goal was to initialize an good vsynced OpenGL window and gives an asm coder the possibility to write some own grafic code to screen. I allocate therefore an linear frame buffer that has 4 bytes per pixel. This buffer is drawn in each vertical retrace to screen.

Well the content I draw into this frame buffer is just filling it with an random color (random generator was coded by me years ago since random generator of DOS was not optimal). But at this just an placeholder and can be filled with any content you want.  :)
Code: [Select]
;
; Basic OS X calls to GLUT and OpenGL
;
; Example by Stino / ByTeGeiZ
;
; compile with:
; nasm -g -f macho32 bspGLframBuff.asm
; gcc -framework GLUT -framework OpenGL -m32 -o bspGLframBuff.out bspGLframBuff.o
;

;inclut GLUT/OpenGL stuff
%include "gl.inc"
%include "glut.inc"

;glibc stuff
extern _clock, _malloc, _free, _usleep, _system

;different ways to use OpenGL (all should work)
;%define USE_TIMER_UPDATE 1
;%define USE_DEPTH_BUFFER 1
%define USE_DOUBLE_BUFFER 1
%define USE_VSYNC 1


; inside com.apple.glut.plist
; set GLUTSyncToVBLKey to true for vsync active in GLUT/OpenGL
;
; at terminal:
; defaults read com.apple.glut GLUTSyncToVBLKey
; defaults write com.apple.glut GLUTSyncToVBLKey 1

; frame buffer data
%define width         800
%define high          600
%define colordeep       4


; static data
segment .data

; enable/disable vertical retrace sync inside com.apple.glut.plist
; set GLUTSyncToVBLKey to true for vsync active in GLUT/OpenGL
;
; at terminal:
; defaults read com.apple.glut GLUTSyncToVBLKey
; defaults write com.apple.glut GLUTSyncToVBLKey 1
enable_glut_vsync_command: db "defaults write com.apple.glut GLUTSyncToVBLKey 1", 10, 0
disable_glut_vsync_command: db "defaults write com.apple.glut GLUTSyncToVBLKey 0", 10, 0

window_name: db "OpenGL frame buffer example", 10, 0
window_handle: dd 0
fl_one: dd 1.0
fl_neg_one: dd -1.0
fl_zero: dd 0.0
fl_half: dd 0.5
fl_neg_half: dd -0.5

; variables for random
seed1:   dd  0
seed2:   dd  0

; for pointer to frame buffer
fbuff:   dd  0

; code
segment .text
 
global _main

; the main function that init OpenGL and install the gl draw function (_display_func)
_main:
        lea     ecx, [esp+4]            ;load adress of argc in stack to ecx
        lea     edx, [esp+8]            ;load adress of argv in stack to edx

        push    ebp ; setup the frame
        mov     ebp, esp

        sub     esp,24      ;add to get rid of 16-bit-alignment-problem (not 28 as normal since we allready push ebp)

%ifdef USE_VSYNC
        ;force enable vsync support of GLUT in OSX
        mov     [esp],dword enable_glut_vsync_command
        call    _system
%endif       

        ;init OpenGL with GLUT
        mov     [esp+4],edx             ;**argv       
        mov     [esp],ecx               ;&argc     
        call    _glutInit               

        ;Init Random numbers
        call    _randomize

        ;get memory for the gl-frame-buffer
        mov     eax,width*high*colordeep
        mov     [esp], eax
        call    _malloc
        ; check if the malloc failed
        test    eax, eax
        jz      _fail_exit
        mov     [fbuff],eax
         
        ;init display mode for OpenGL window
        mov     eax, GLUT_RGB
%ifdef USE_DOUBLE_BUFFER       
        or      eax, GLUT_DOUBLE
%else
        or      eax, GLUT_SINGLE
%endif
%ifdef USE_DEPTH_BUFFER
        or      eax, GLUT_DEPTH
%endif       
        mov     [esp], eax
        call    _glutInitDisplayMode   

        ;define posion of OpenGL window
        mov     [esp+4],dword 80               
        mov     [esp],dword 80               
        call    _glutInitWindowPosition

        ;define OpenGL window size
        mov     [esp+4], dword high           
        mov     [esp], dword width           
        call    _glutInitWindowSize   

        ;create OpenGL window
        mov     eax, dword window_name
        mov     [esp], eax
        call    _glutCreateWindow 
        mov     dword [window_handle],eax

%ifdef USE_DEPTH_BUFFER
        ;enable depth buffer
        mov     [esp],dword GL_DEPTH_TEST
        call    _glEnable
%endif       

        ;add own draw function as call back
        mov     [esp], dword _display_func
        call    _glutDisplayFunc 

%ifdef USE_TIMER_UPDATE
        ;add call back that triggers draw update(timer based)
        mov     [esp+8], dword 0
        mov     [esp+4], dword _timer_func
        mov     [esp], dword 1
        call    _glutTimerFunc

%else
        ;add call back that triggers draw update(idle based)
        mov     [esp], dword _idle_func
        call    _glutIdleFunc
%endif

%ifdef USE_VSYNC
        ; disable glut vsync before main loop, since this loop will never terminate normaly
        ; it works if it was enabled while init of glut/OpenGL ;-)
        mov     [esp],dword disable_glut_vsync_command
        call    _system
%endif

        ;start OpenGL main loop
        call    _glutMainLoop

        ; free the malloc'd memory
        mov     eax, dword [fbuff]
        mov     [esp], eax
        call    _free

_pass_exit:
        add     esp,24
        pop     ebp         
        ret
         
_fail_exit:
%ifdef USE_VSYNC
        ;disable glut vsync in case we had an error
        mov     [esp],dword disable_glut_vsync_command
        call    _system
%endif

        mov     eax, 1
        add     esp,24
        pop     ebp
        ret

;##############################################################################

; GL timer function to give GL draw function the command for redraw and also restart the timer
_timer_func:
        sub     esp,28

        ;select OpenGL window
        mov     eax, [window_handle]
        mov     [esp],eax
        call    _glutSetWindow

        ;start redraw of OpenGL
        call    _glutPostRedisplay

        ;restart timer
        mov     [esp+8], dword 0
        mov     [esp+4], dword  _timer_func
        mov     [esp], dword 40 ;the timer
        call    _glutTimerFunc

        add     esp,28
        ret

;##############################################################################

; GL idle function to give GL draw function the command for redraw
_idle_func:
        sub     esp,28

        ;just wait a few micro secs
        mov     [esp], dword 10
        call    _usleep

        ;select OpenGL window
        mov     eax,[window_handle]
        mov     [esp],eax
        call    _glutSetWindow

        ;start redraw of OpenGL
        call    _glutPostRedisplay

        add     esp,28
        ret

;##############################################################################

; the gl draw function (here is the content of OpenGL
_display_func:
        sub     esp,28 ;add to get rid of 16-bit-alignment-problem

        ;fill frame buffer with some content
        call    _draw_to_frame_buff

        ;defiene color for clear screen
        mov     eax, dword [fl_one]
        mov     [esp+12],eax
        mov     eax, dword [fl_zero]
        mov     [esp+8],eax
        mov     [esp+4],eax
        mov     [esp],eax
        call    _glClearColor

        ;clear screen
        mov     eax, dword GL_COLOR_BUFFER_BIT
%ifdef USE_DEPTH_BUFFER
        or      eax, dword GL_DEPTH_BUFFER_BIT
%endif       
        mov     [esp],eax
        call    _glClear

        ;set position were _glDrawPixels will start
        mov     eax,dword [fl_neg_one]
        mov     [esp+4],eax
        mov     [esp],eax
        call    _glRasterPos2f
 
        ;draw frame buffer to screen
        mov     eax, dword [fbuff]
        mov     [esp+16],eax
        mov     [esp+12],dword GL_UNSIGNED_BYTE
        mov     [esp+8],dword GL_RGBA
        mov     [esp+4],dword high
        mov     [esp],dword width
        call    _glDrawPixels

%ifdef USE_DOUBLE_BUFFER       
        ;do all actions and than change the buffer
        call    _glutSwapBuffers
%else
        ;so all actions in single buffer mode
        call    _glFlush
%endif

        add     esp,28
        ret

;##############################################################################

;here draw own content to frame buffer
_draw_to_frame_buff:
        sub     esp,28 ;add to get rid of 16-bit-alignment-problem

        ;get a random number
        mov     [esp],dword 0xFFFFFFFF
        call    _random ;eax has radom number

        ;fill complete frame buffer with a random color
        mov     edi,[fbuff]
        mov     ecx,width*high
        rep     stosd

        add     esp,28
        ret


;##############################################################################

;Init the random number seeds with system time
_randomize:
        ;parameter:
        ;none

        ;return value:
        ;none

        push eax
        push    edx
        xor     eax,eax
        sub     esp,4
        call    _clock  ;nach eax
        add     esp,4
        mov     [seed1],eax
        mov     edx,eax
        sub     esp,4
        call    _clock  ;nach eax
        add     esp,4
        xor     eax,edx
        mul     edx ;eax * edx nach edx:eax
        mov     [seed2],eax
        pop     edx
        pop     eax
        ret

;##############################################################################

;create a new random number
_random:
        ;parameter:
        ;EAX = w, range of random number: 0 - (w-1)

        ;return value:
        ;EAX = new random number

        push    ebx
        push    edx
        mov     ebx,eax
        mov     eax,[seed1]
        mov     edx,[seed2]
        mov     [seed2],eax
        add     eax,edx
        shld    eax,edx,9
        mov     [seed1],eax       
        xor     edx,edx
        div     ebx
        mov     eax,edx
        pop     edx
        pop     ebx
        ret


Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 429
  • Country: us
Re: Example how to use GLUT/OpenGL in OSX (Intel macho32)
« Reply #10 on: May 17, 2011, 10:59:16 PM »
Very nice, Stino.  With your permission may I add that as a demo for NASMX?

Keith / Bryant - Before I add the GL headers referenced above can you take a quick look at the licenses to confirm redistribution?
Their short and appear amicable but a second pair of eyes never hurts.

Offline Keith Kanios

  • Full Member
  • **
  • Posts: 383
  • Country: us
    • Personal Homepage
Re: Example how to use GLUT/OpenGL in OSX (Intel macho32)
« Reply #11 on: May 18, 2011, 01:22:55 AM »
Very nice, Stino.  With your permission may I add that as a demo for NASMX?

Keith / Bryant - Before I add the GL headers referenced above can you take a quick look at the licenses to confirm redistribution?
Their short and appear amicable but a second pair of eyes never hurts.

The license looks OK to use, but IANAL and I'd rather avoid setting this precedent of including lengthy/cumbersome licenses in a project that still has my name attached to it. I have an inherent distrust of anything longer than a paragraph that resembles legalese.

I'd opt for the "clean room" approach of piecing together include files from official documentation, and contributing it to NASMX under our chosen license. This should be pretty much OK as interfaces/constants/standards and whatnot fall under fact and not implementation... and are thus not subject to copyright. So strict function, data and constant (i.e. interface) declarations should be OK to implement and license ourselves.

Mind you that my recommendation is merely in the best interests of our user base, in that they shouldn't have to think hard about the limitations of using any given part of NASMX... it is supposed to be gift, unencumbered and no strings attached.

Food for thought.

Offline Stino

  • Jr. Member
  • *
  • Posts: 9
Re: Example how to use GLUT/OpenGL in OSX (Intel macho32)
« Reply #12 on: May 18, 2011, 09:22:27 PM »
I can just speak for the demos I post here. The code was written by me and I allow everybody to copy, to modify and to uses them in any other software. In other words it is free.

Other thing are the OpenGL headers that I adopt to use them with NASM. "gl.h" is part of OpenGL and should be under License of OpenGL that can be found here: http://www.opengl.org/about/licensing/ The main message I understand is that application developers have not to license it. A bit more difficult seems "glut.h" to me since this is part of GLUT from Mark Kilgard. According to this Wikipedia article it is not so free as it seems. http://en.wikipedia.org/wiki/OpenGL_Utility_Toolkit

The arguments of Keith that headers not include any code and that they are free because they offer just the knowledge about an interface (function names and constants) sounds plausible for me. But actually I'm no jurist and have absolutely no idea how the juridical argumentation is?  ???

Anyway If you decide not to include the headers to NASMX I will post here an patch for my second demo to make it running without the headers.

Remove:
Code: [Select]
;inclut GLUT/OpenGL stuff
%include "gl.inc"
%include "glut.inc"
And replace it by:
Code: [Select]
extern _glutInit, _glutInitDisplayMode, _glutInitWindowPosition, _glutInitWindowSize, _glutCreateWindow, _glEnable, _glutDisplayFunc, _glutTimerFunc, _glutIdleFunc, _glutMainLoop, _glutSetWindow, _glutPostRedisplay, _glClearColor, _glClear, _glRasterPos2f, _glDrawPixels, _glutSwapBuffers, _glFlush

%define GLUT_RGB            0
%define GLUT_DOUBLE         2
%define GLUT_SINGLE         0
%define GLUT_DEPTH          16
%define GL_DEPTH_TEST       0x0B71
%define GL_COLOR_BUFFER_BIT 0x00004000
%define GL_DEPTH_BUFFER_BIT 0x00000100
%define GL_UNSIGNED_BYTE    0x1401
%define GL_RGBA             0x1908

Offline Bryant Keller

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 360
  • Country: us
    • About Bryant Keller
Re: Example how to use GLUT/OpenGL in OSX (Intel macho32)
« Reply #13 on: May 23, 2011, 05:56:41 AM »
Mind you that my recommendation is merely in the best interests of our user base, in that they shouldn't have to think hard about the limitations of using any given part of NASMX... it is supposed to be gift, unencumbered and no strings attached.

I couldn't say it better myself. In fact, right off hand I can't tell yah what license NASMX is using much less if it conflicts with another license. I originally released NASM32 to the public domain, NASMX is more or less Keith's port of the project, his code and the code I contributed at that time is under whatever licenses it's under now.

As for the NASMX user base, I'm not sure including OGL/GLUT is really in their best interest. I always thought of NASMX as a more generic utility (which is why we attempted to support as many systems as we did). This kinda makes me think of a conversation I had on this board some time back. Apparently most of the user base wasn't even aware of the cross platform nature of the library because so much emphasis (and work) was done on the Win32/64 editions. I think if the NASMX project starts adding support for things like OGL/GLUT then it will just open the floodgates for users to misinterpret the projects capabilities again and might fuel rumors that "You can't do [insert graphics engine library] in NASMX 'cause it only supports OGL". I know, sounds silly but it happens. What's worse is, it makes NASMX look like it's taking sides on the whole OGL vs DX vs whatever (personally I'm an allegro fan but my graphics needs tend to be minimal at best) arguments that could easily be avoided by simply linking to Stino's page. As for NASMX revision of Stino's code, sounds like a good idea, however I would go as far as to say that game/graphics dev is popular enough that you might want to release it as a separate package. [NX4G - NASMX 4 Gamers]... Sounds interesting none the less. Maybe could get homer to help out with it after he finishes formalizing his skillset, he was picking up quite a lot of NASM before he went off to school. :)

About Bryant Keller
bkeller@about.me

Offline kevin

  • Jr. Member
  • *
  • Posts: 4
Re: Example how to use GLUT/OpenGL in OSX (Intel macho32)
« Reply #14 on: December 22, 2012, 04:48:39 PM »
Thank you