• 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.

Getting started with application development for System 6/7

cheesestraws

Well-known member
The pointer-to-pointer is to an entry in that table, yes.  And by doing it this way it stops the application itself having to worry about things like heap fragmentation, because the actual locations of dynamically-allocated things in memory are the memory manager's problem, not the application's.

I tried to throw together a diagram that may (or may not) help (more for anyone stumbling across this thread later than you, as you seem to have worked it out):

memorymanager.png

 

Crutch

Well-known member
That’s right.

In classic Mac parlance, a “Handle” is a pointer to an entry in a table of “Master Pointers” managed by the Memory Manager.  As cheesestraws says, this lets the Memory Manager move around the underlying blocks of memory (so-called “relocatable” blocks) or even nuke them (if they’re “purgeable” resources) entirely.  

(Edit:)  This last point is particularly nifty, so as an app developer if you’re (say) reading a bunch of data from a huge file, you can store it in a relocatable block (accessed via a Handle) and mark it purgeable.  Then, the Memory Manger is allowed to trash it whenever it needs more space.  Before using it each time, just double check that the Master Pointer hasn’t been set to NULL.  If it has, no big deal, just call your file-reading routine again to restore the data to RAM.  (And you only have to do this check at certain times — unless you call routines on a certain magic list, the Memory Manager guarantees it won’t move anything around or purge anything.)

As long as the application plays by the rules (don’t save a copy of the master pointer assuming it won’t change - and check purgeable things to ensure they haven’t been purged before using them!), this is a terrific model.

 
Last edited by a moderator:

techknight

Well-known member
hmm maybe I need to read books on this, but how does the application cope if the memory manager decides if something needs moved? it just moves it halfway in the middle of your loop while your using it? 

I guess this stems from my bad idea of defining a new local pointer with the data from the other pointer. That would be bad, I see.... But then if the pointer address is moving around in a loop inside your application, how does the memory manager know not to reset that pointer back to the beginning again, crashing your app? (if it needs to move data)

Because it would seem to me if your using a pointer to a pointer you would be incrementing the address thats stored in the pointer table. If Memory manager changes this address to a new location, it screws the loop. 

 
Last edited by a moderator:

Mu0n

Well-known member
You use HLock to lock the handle managing your pointer, so you can't lose access to it. You HUnlock it after. 

Your question was spot on, and highlights the cost (small) of using this strategy in memory management. 

If I recall correctly, the most frequent use of those pairs of traps I did back 15 years ago was when I was prepping and blitting my offscreen memory block to the video RAM. 

 
Last edited by a moderator:

ZaneKaminski

Well-known member
how does the application cope if the memory manager decides if something needs moved
The memory manager only moves memory when you make a call to allocate a pointer or handle, or when you call a (toolbox) routine which does the same. Memory never gets moved at interrupt time, so it’s not like you can be going through the code and all of a sudden the memory you were using has moved. And like Mu0n said, if you wanna make a call to allocate memory but don’t want something moved, you lock it with HLock and then the memory manager won’t move it.

 
Last edited by a moderator:

cheesestraws

Well-known member
Addendum to both posts above: the toolbox documentation tells you what functions move memory, and you can't use those in interrupt handlers.  But yes, it's not like it does it at arbitrary times, and if you absolutely need something *not* to move then you can tell the memory manager not to move it.

It sounds kind of clumsy to describe, but it actually works really well; it's one of those tiny abstractions that reaps quite a lot of benefits.

 

techknight

Well-known member
Ahh see this is all good information. I've never written a mac application before in my life in C so its neat knowing these things. I have wrntten mac apps in Abstracted languages such as RealBASIC. 

The only C programming I have done was Bare Metal, and surprisingly enough, was on a 68K. actually, juggling between two 68Ks, with 1 having paged memory access to the RAM of the other. But, thats a cluster**** for another day/time. 

Thanks for the tips. :)

 
Last edited by a moderator:

cheesestraws

Well-known member
The only C programming I have done was Bare Metal, and surprisingly enough, was on a 68K. actually, juggling between two 68Ks, with 1 having paged memory access to the RAM of the other. But, thats a cluster**** for another day/time. 
I'd really like to hear about this sometime in some other thread, if you ever feel like talking about it.  That sounds a bit mad...

 

techknight

Well-known member
I'd really like to hear about this sometime in some other thread, if you ever feel like talking about it.  That sounds a bit mad...
I should. it's just a bit off-topic for this forum so I dont know where I would put it. 

I need to have someone more seasoned in C code take a look at my program at some point. It works fine, but im sure there room for improvement to make things faster. When it comes to the 68010 running at 8Mhz, you need to squeeze every ounce of performance you can get out of it. 

 
Last edited by a moderator:

Crutch

Well-known member
as well as Popfunc, so you can add a leftmost corner pop-up menu to your window editing a source file, allowing you to go directly to any function from a pull-down menu, if you're a barbarian like me and write too many functions in an individual source file sometimes (I'm trying to break the habit) 
Do you have a link for Popfunc?  I can’t find it anywhere.  Indeed Googling “popfunc” “think c” brings up only this one forum post on the whole wide web!  @Mu0n

 

Mu0n

Well-known member
Do you have a link for Popfunc?  I can’t find it anywhere.  Indeed Googling “popfunc” “think c” brings up only this one forum post on the whole wide web!  @Mu0n
image.png

PopupFuncs is the correct name.

I have no recollection where I got it, but I have a vivid memory of having installed it a few weeks/months after I started using THINK C for my millions of little projects back in 2004-5.

Perhaps I got it from the hotline server that was up back then, Retromac68k (what a treasure trove, long gone, before I could manually back up it all - I got a good chunk of it though).

 

petteri

Well-known member
Back to basics. I wrote a simple application to load PICT from resources and to display it using simple DrawPicture. Works fine as a stand alone compiled application but if I try the "Run" command on Think Pascal 4.5a1 and OS 9.2.2 I get an empty window. Is that some known issue?

Edit: Ah, the PICT was in 24bit image. I converted it to 1bit in GraphicsConverter and works fine now.

 
Last edited by a moderator:

Crutch

Well-known member
Are you creating your own window, or relying on a THINK Pascal-produced standard drawing window from including InterfaceLib (or whatever it’s called ... been a long time)?  If the latter, my understanding is there are incompatibilities with later versions of MacOS, such as OS 9.  Ingemar’s website explains some of this http://www.think-pascal.org

I haven’t tried using THINK Pascal with anything after 7.5.5 personally so this is conjecture.  But try creating your own window with NewWindow instead of relying on the standard drawing window.  Or:  use THINK C.

 

petteri

Well-known member
Hehe, this went pretty fast from a fun little hello world window to the dark misery. Things I suffered lately:


But with "Try Harder" mentality it is progressing. Deadline in February so I should be able to finish this by then...

 

petteri

Well-known member
One more question. I want to have buttons straight on the window next to the picture without any dialog. These buttons would have direct effect on the picture without need of hitting any ok button.

Is it possible to use the standard buttons without dialog? Or should I go more low level and draw button looking image and figure out if mousedown happens on it? 

 

cheesestraws

Well-known member
Is it possible to use the standard buttons without dialog
I was actually looking at some demo source code to do precisely this a few days ago and I cannot for the life of me remember where it was.  It might perhaps have been on @Mu0n's github page, which I can't find the URL for.

(This morning is going really well so far, as you can probably tell...)

 

Crutch

Well-known member
Yes, of course. 
 

The routines you need are NewControl (or GetNewControl if you want to put your control’s details in a CNTL resource - but that’s probably overkill), FindControl, and TrackControl. You will also need to call DrawControls when you get an update event if your window is modeless. These are covered in the Control Manager chapter of Inside Macintosh Volume I. 
 

In short:

- call NewControl to create your buttons 
- then, if you get a mouse down in your window from WaitNextEvent, call FindControl to see if it’s in a button

- if so, call TrackControl to deal with the button highlighting and see if the user does the mouseUp inside your button

- if so, your button has been pushed!
 

 

Crutch

Well-known member
Yeah that’s good. Just notice there that the first button (beepButton) takes action immediately upon a mouseDown before calling TrackControl, which is nonstandard behavior for a push button. Assuming you want a standard push button, wait until TrackControl returns before doing anything as with “beepButton2” here. 

 
Top