• Updated 2023-07-12: Hello, Guest! Welcome back, and be sure to check out this follow-up post about our outage a week or so ago.

Learning 68k assembly - issues with _NewWindow

ry755

Active member
Hi!! So I've been playing around with learning Macintosh Programmer's Workshop and 68k assembly, and I'm currently trying to just make a simple hello world application. Yet I can't even get a window to render properly for whatever reason. The application starts but it doesn't display anything. The `TryButton` loop works as expected though, clicking the mouse button causes the application to exit.
This code is based on multiple Macintosh programming books from the 80s (here on page 35 and here on page 65), so I'm pretty confused at to why this doesn't work. Does anyone here know what I'm doing wrong?

Here is the code:
Code:
    include 'Quickdraw.a'
    include 'Windows.a'

qd ds QDGlobals
WindowSize dc.w 80,60,290,450
WindowName dc.b 'test'
WindowPtr dc.l 0

    main

    pea qd.thePort
    _InitGraf
    _InitFonts
    _InitWindows
    _InitMenus
    _InitCursor

    ; create a new window
    subq #4,sp               ; space for the WindowPtr result
    clr.l -(sp)              ; allocate window record on the heap
    pea WindowSize           ; coords of window
    pea WindowName           ; window title
    st -(sp)                 ; make window visible
    move #documentProc,-(sp) ; document window
    move.l #-1,-(sp)         ; put window on top
    st -(sp)                 ; make window have a GoAway box
    clr.l -(sp)              ; reference value
    _NewWindow

    ; store the window pointer in WindowPtr
    lea WindowPtr,a0
    move.l (sp)+,(a0)

TryButton
    ; loop until the mouse button is pressed
    _SystemTask
    subq #2,sp
    _Button
    tst.b (sp)+
    beq.s TryButton

    _ExitToShell

    end
 

Crutch

Well-known member
Your setup for the _NewWindow trap looks good.

Why are you passing that address to _InitGraf that way? Is that MPW standard? (I don’t use MPW). The examples you cite both do what I would expect, which is pass _InitGraf an address offset from A5. But I see that you are doing something different.
 

ry755

Active member
Why are you passing that address to _InitGraf that way? Is that MPW standard? (I don’t use MPW). The examples you cite both do what I would expect, which is pass _InitGraf an address offset from A5. But I see that you are doing something different.
I was originally passing an offset from A5 like the books say, but that was causing it to jump to 0x4000 and crash with an invalid instruction error. After doing some googling I came across this thread which explains that MPW positions things a little bit differently. It's weird since the first book I cited is based around MPW, although I'm using a newer version so I guess it must've been changed at some point.
 

cheesestraws

Well-known member
Just as a general note, unless you're specifically doing it to relive a particular point in history, or to explore the history of the UI of development tools, basically anything else more recent is better than MPW from a minimising developer pain standpoint...

That's not telling you not to, just to make sure that you know that more modern developer tools are available if you want them :)
 

ry755

Active member
Just as a general note, unless you're specifically doing it to relive a particular point in history, or to explore the history of the UI of development tools, basically anything else more recent is better than MPW from a minimising developer pain standpoint...

That's not telling you not to, just to make sure that you know that more modern developer tools are available if you want them :)
Yeahhh I was thinking that MPW would give me the "original Macintosh programming experience" but you're right, I'm probably better off with something like CodeWarrior. I do quite like the console-oriented workflow of MPW though since I'm used to software development on Linux.
 

cheesestraws

Well-known member
Well, if you are finding MPW congenial, use it :). You may be in a minority in finding it so, but one of the great things about developing for a dead platform is that you can use whatever development tools you like because none of it is getting updates anyway... So use what you like.

Personally it's just familiar/unfamiliar enough to my UNIX side so I get nothing done, though I find it very interesting. But people do turn up sometimes thinking that MPW is the One True Way to learn Mac development and I do feel the moral requirement to gently tell people that they don't have to throw themselves against that wall if they would prefer not to. :)
 

Crutch

Well-known member
Yeah looks like you did it right. http://preserve.mactech.com/articles/mactech/Vol.05/05.06/MDStoMPW/index.html

In my experience things not getting drawn at all is often a symptom of QuickDraw not looking in the right place for thePort (and maybe for example thinking the pen is invisible). But that’s unlikely here anyway since your window frame should get drawn using the Window Manager Port?

Anyway I’m stumped but would love to know how you figure it out. Which I’m sure you will.
 

ry755

Active member
Thank you for double checking, I'll keep you updated if I figure out what's going on :)
 

ry755

Active member
Using MacsBug's `windlist` command I figured out that the pointers to the window's rect and title don't seem to be getting set properly:

windlist.jpg

As a test, I ran the following code:
Code:
lea WindowSize,a0
lea WindowName,a1

; break into macsbug
divu #0,d0

For some reason, A0 and A1 don't seem to point to WindowSize and WindowName?? Examining the memory at address A1 should show me the "test" string from WindowName, but instead it's just garbage data. The values are always consistent, A0 is always 0x0796F1D2 and A1 is always 0x0796F1CC. I feel like I'm doing something obviously wrong here that I'm just not seeing.
 

Crutch

Well-known member
Oh wait, shot in the dark here (did I mention I don’t use MPW?) but …. You are DC’ing those constants before the start of your MAIN segment, right? Is MPW putting that data in a different segment? What happens if you move your first four lines to the bottom of the program (so, after MAIN) instead of the top?
 

ry755

Active member
Putting them after MAIN just causes it to complain that `qd` is undefined, I'm not sure why :(

I'd like to give CodeWarrior a try and see if this is just some weird issue with MPW, does it allow writing code in plain assembly? I tried creating a blank project and adding my existing .a file to it but it wouldn't let me. Otherwise, what IDE/assembler would you recommend?
 

Juror22

Well-known member
I think that you need to include a _SetPort after you create the _NewWindow to make the view port active, so that you can draw to it.
 

ry755

Active member
I think that you need to include a _SetPort after you create the _NewWindow to make the view port active, so that you can draw to it.
I've already tried that, the problem is that the window doesn't even show up in the first place.
 

Crutch

Well-known member
Right. SetPort isn’t necessary to make a window visible.

By the way you don’t need to force a zero divide to break into Macsbug. There is a trap for that: _Debugger (a9ff).
 

ry755

Active member
After taking a break from this for a while I decided to give this another try, and guess what!! It was the simplest fix, ti works perfectly now.

PXL_20221001_002511222.jpg

Oh wait, shot in the dark here (did I mention I don’t use MPW?) but …. You are DC’ing those constants before the start of your MAIN segment, right? Is MPW putting that data in a different segment? What happens if you move your first four lines to the bottom of the program (so, after MAIN) instead of the top?
This was the fix, however I had to keep the `QDGlobals` definition outside of MAIN for some reason. The final code looks like this:

Code:
    include 'Quickdraw.a'
    include 'Windows.a'

qd ds QDGlobals

    main

    pea qd.thePort
    _InitGraf
    _InitFonts
    _InitWindows
    _InitMenus
    _InitCursor

    ; create a new window
    subq #4,sp               ; space for the WindowPtr result
    clr.l -(sp)              ; allocate window record on the heap
    pea WindowSize           ; coords of window
    pea WindowName           ; window title
    st -(sp)                 ; make window visible
    move #documentProc,-(sp) ; document window
    move.l #-1,-(sp)         ; put window on top
    st -(sp)                 ; make window have a GoAway box
    clr.l -(sp)              ; reference value
    _NewWindow

    ; store the window pointer in WindowPtr
    lea WindowPtr,a0
    move.l (sp)+,(a0)

TryButton
    ; loop until the mouse button is pressed
    _SystemTask
    subq #2,sp
    _Button
    tst.b (sp)+
    beq.s TryButton

    _ExitToShell

WindowSize dc.w 80,60,290,450
WindowName dc.b 'test'
WindowPtr dc.l 0

    end
 

Romko23

Well-known member
Speaking of assembly, what app can I use in OS 9 to write assembly language programs ? I am trying to work on writing a USB 2 driver and need to know what app to use for this ? Does Codewarrior support assembly programming under OS 9 ?
 

ry755

Active member
Speaking of assembly, what app can I use in OS 9 to write assembly language programs ? I am trying to work on writing a USB 2 driver and need to know what app to use for this ? Does Codewarrior support assembly programming under OS 9 ?
CodeWarrior doesn't seem to support assembling bare assembly programs, at least not that I've found. (If it is actually possible, someone please let me know how!)
I've been using Macintosh Programmer's Workshop, which gets the job done but it has a bit of a learning curve.
 

Phipli

Well-known member
Speaking of assembly, what app can I use in OS 9 to write assembly language programs ? I am trying to work on writing a USB 2 driver and need to know what app to use for this ? Does Codewarrior support assembly programming under OS 9 ?
@ry755 I think CodeWarrior lets you do inline assembly at the very least?


Odd context example but it was the first evidence I found and has some guidance.
 

cheesestraws

Well-known member
CodeWarrior will allow you to embed chunks of assembler in projects in other languages. If you're undertaking a project as big and as complex as a USB driver, I would strongly suggest not attempting to write the whole thing in assembler, because that way madness lies.
 
Top