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

Help getting started with retro software development

Mu0n

Well-known member
I suggest just going with Symantec THINK C 6 (or even THINK C 5). Just use 'Mac Traps' and your app will run very well on a Plus, I do it all the time and if you hit a snag, I can help you.
 

Crutch

Well-known member
I think he’s looking for a class library recommendation though. Here are some options:
  1. MacApp - runs pre-system 6 for sure if you get an earlier version, but requires (I think) MPW
  2. Think Class Library (TCL), definitely supported in THINK C++ 7 and THINK C 6 and probably 5, any of which will compile code that runs under System 6 just fine.
  3. Use a UI toolkit like Prototyper, which I have not personally used but is intended to support all the common UI bits of a Mac application and dates back to 1986-ish so will definitely run under older system software.
  4. Bite the bullet and learn the Toolbox … liberally stealing code from a classic source code demo for a Mac application like MiniWriter.
I would go with option 2 or perhaps 4 personally, since I find learning a class library like TCL is itself a bit of work.

Good luck!
 

BacioiuC

Well-known member
Code Warrior 4 builds and runs apps on System 6. As far as the toolbox, you technically need to setup a wrapper for it once for a few things. In my own game I only touched the toolbox once in the beginning and did the following:
  • An init class that initialises everything I need.
  • A gui library that handles three thing:
    • Creating a window
    • Creating a button
    • Displaying a pict from the res file
  • The update function. It's basically a big case switch statement that handles on mouse down, updateEvt, activateEvt. inThumbPressed (for scroll bars) and controlPressed. That's all.
I straight up, without any remorse, copied the start template from Macintosh C Primer book from 1989 (I think) and then just wrapped the things in my own functions, allowing me to make a button like: CreateButton(x,y, width, height, label) and CreateImage(pictID, x, y, width, height) and UpdateImage(imageID, pictID) to allow me to do quick animation for standard picts.

Now, I saw your gifs and they look lovely. However, I have a feeling the gifs have been recorded from an emulator and the speed of drawing the picts you have there will be really slow on actual hardware. I'm saying this because drawing 20 picts directly using standard toolbox calls is pretty slow. Your next step is to learn about GrafPtr and offscreen rendering and probably the most useful routine for making games - CopyBits. I might be mistaken and you are already doing that but it was worth mentioning. You have no idea how surprised I was testing my first level editor on actual hardware and crying at my scroll routine.

In the end, even if you go for a class library for handling the toolbox, you will need to dive deep into how to use offscreen worlds and copybits if you want any chance to get the game to run okay on a plus.

If I had the time to start all over again, I would honestly just drop support for the toolbox outside of Initialising a window and handling the finder menus and just do my own gui controls.
 

nightingale

Well-known member
Thanks for the tips everyone! @Crutch and @Mu0n, I will definitely look into the tools you suggested tonight.


Now, I saw your gifs and they look lovely. However, I have a feeling the gifs have been recorded from an emulator and the speed of drawing the picts you have there will be really slow on actual hardware. I'm saying this because drawing 20 picts directly using standard toolbox calls is pretty slow. Your next step is to learn about GrafPtr and offscreen rendering and probably the most useful routine for making games - CopyBits. I might be mistaken and you are already doing that but it was worth mentioning. You have no idea how surprised I was testing my first level editor on actual hardware and crying at my scroll routine.

Don’t worry, I already had my crying moment the first time I ran it on actual hardware, then I learned how to draw to an offscreen buffer first and performance is quite good on my SE/30 right now. I draw all of my tiles to the buffer when the level loads then copy it to the visible window and scroll it. It takes a few seconds to load the level, but then it scrolls very smoothly. Right now for my bad guys, I am redrawing them in their new location and drawing a blank tile over their old location, so it’s quite slow with more than just a few bad guys on the map, so my next big task will be figuring out how to use sprites to relocate them instead of redrawing them every 200ms.
 

bdurbrow

Well-known member
If you mean sprites in the sense that Amigas have them... there's no hardware for that on the Mac Plus. The best you can do is CopyBits; or if you know that the pixels always align on byte boundaries, an assembler fragment that copies them as whole bytes as fast as possible.
 

Mu0n

Well-known member
iirc, copybits is fastest if you use a width that's an integer multiple of 32 bits (4 bytes) in srcCopy mode to prevent it from doing any per pixel checkup.

check out an earlier relevant discussion on the topic:
 

nightingale

Well-known member
All right, so a bit of an update after a long hiatus here. I've been busy with life, but finally buckled down and starting reading through some books about C programming on the Macintosh. I'm now using Think C 5 and the libraries that come with it. I'm struggling because there is so much work to be done setting up the bones of the Macintosh application before I can even get to programming my game, which is the part I'm actually not too worried about. I just finished reading through Macintosh C Programming By Example, which has a disk with some great example code and a "generic app" to get you started. Basically, the "generic app" has already done all the Macintosh stuff for you to set up your application, which is a huge head start, and gets me to the point where I can actually work on the code for my game. But what I've found about this, and all other "templates" I've found for Think C projects, is that they are all designed to allow for an application with the ability to have multiple instances of your document window. For my game, there will be one main application window, and when that closes, it quits the application. Now I've just set it up for now that closing the document window quits the application, and I have removed the ability to create new document windows in the user interface, so it behaves the way I want, but there is a lot of extra unused code in here, and I'm worried this is going to make it more complicated for me to chase bugs. Since I'm not using that functionality, I haven't really put the time into understanding how it works, so I'm worried there is a whole segment of my code that is a mystery to me. I'm also trying to keep the size of my application to a minimum so I can fit it on an 800k disk with a system Folder for System 6. Every KB counts. Now I can go through and manually remove all of this stuff, but I'm wondering if anyone knows of any starter templates for Think C that are design for a single-window application like this? I want to try not to reinvent the wheel here, and start myself off with a solid template that will work for me. Or am I overthinking it? Should I just carry on and treat my window as a document window and not worry about it?
 

bdurbrow

Well-known member
It is a hard-learned truth that the fewer lines of code you have, the better off you are: that's code that you don't have to maintain... and that applies to everything from tiny microcontrollers to classic computers to large systems running on modern hardware. So, yeah - prune it down to the essentials; and that's technical debt that you won't have hanging over your head.

IIRC, the SillyBalls demo project that came with CodeWarrior was as simple an app example as you could get; and it should run on a Plus. You'd have to re-build the project file to port it to Think C, but I think the source should compile with only minor changes, if any at all.
 

Crutch

Well-known member
Most versions of THINK C, I believe including THINK C 5, include a demo app called “Bullseye” that sounds like just what you’re looking for. Single window with working menubar.
 

nightingale

Well-known member
Honestly, I think I'm suffering from a bit of analysis paralysis. I'm worrying about making a mistake early on that will haunt me later. The reality is there are several basic options, as several of you have pointed out, and when I look at them, they are not much different from what I coded myself from scratch. So I think that confirms that I need to just dive in and get coding, and accept that there are always going to be things I could have done differently at the beginning that would have made my life easier, but that's part of the learning process. Thank you for all of the helpful suggestions! It's time to get going.
 

cheesestraws

Well-known member
So I think that confirms that I need to just dive in and get coding, and accept that there are always going to be things I could have done differently at the beginning that would have made my life easier, but that's part of the learning process

Your whole post is good sense, and this bit especially. I'm a pretty experienced software engineer at this point and nearly every project I do that isn't tiny, I can find something I could have done to make my (or my colleagues', at work) life easier. This is a good thing. It sounds like your head is in the right place, so yes, get going, see what you come up with :).
 

Crutch

Well-known member
Just one final note to reduce worry - code is pretty small. If your app gets too big to fit on an 800K disk, it’s really unlikely that unused bits of demo code are the main culprit. Also your linker will probably omit any code that never gets called from your compiled binary in any case (THINK does this I believe with the “Smart Link” box checked). So that is one issue I wouldn’t worry about too much.
 

nightingale

Well-known member
So little status update... After I got over my paralysis of getting started, and over thinking everything, I just dove in and started coding. And once I got started, I just flew through it, and within a week had re-created my progress in Think C! I'm now making great strides each day. Most of the times when I've been stuck and can't figure out what is wrong, it ends up being something stupid, like forgetting that an array with properties 0-4 needs to be declared with an array size of 5! That gets you some strange results when you write beyond the end of the array, and it just overwrites a different variable in memory!

But now I'm stuck on something that I truly can't figure out. When I run my app from within Think C, it works perfectly. However, when I compile it into an application and run it on any of my systems running System 7.5, the main portion of my window doesn't draw or update -- I can still move my character around and interact with the map, so it is just a drawing issue. What is strange is that if I take that same compiled application and run it on my Plus in 6.0.8, it works exactly as intended.

Here's what it looks like when running from within Think C:
Screen Shot 2022-04-21 at 9.10.13 PM.png

And when compiled on a Mac Plus in 6.0.8:
Screen Shot 2022-04-21 at 9.09.06 PM.png

On the same Mac Plus running 7.1:
Screen Shot 2022-04-21 at 9.08.35 PM.png

And finally, on any of my Macs running 7.5.5:
Screen Shot 2022-04-21 at 9.09.46 PM.png

These screenshots are all taken from emulators, but the behaviour on real hardware is identical.

I've been stuck on this for a week -- I've tried commenting out huge chunks of my code, but I can't seem to isolate what could be causing this. My best guess is that something is causing an issue with the section of memory which stores the array that holds my map tiles. The tiles are just an icon resource, and I have an array that stores the resource id for each x/y coordinate. I first started to notice this issue when my code started to grow in size. The weird first row that I see in System 7.1 is what used to happen in 7.5.5, but as my code grew, it just stopped drawing in 7.5.5. But for the life of me, I cannot figure out what the culprit is.

If anyone has thoughts on what might be causing this, I would be so grateful! I'm pulling my hair out!

My code is a bit of a mess, because I've been learning as I go, but if anyone wants to see it, let me know!
 

mdeverhart

Well-known member
I’m sure some folks here would be happy to look at your code if you could post it somewhere, or attach the whole project here as a StuffIt file (SIT)
 

mdeverhart

Well-known member
Thanks for sharing! There’s nothing to be embarrassed about - you were/are learning, and I’d venture that most of us here (myself included) have done no (or very little) Classic Mac programming. That said, there are some experienced folks here that I’m sure would be happy to take a look.
 

Crutch

Well-known member
On a really quick look at your code my guess is some junk is getting into your mapTile array somehow.

One telltale sign: those stop sign icons you are seeing on your Plus under 7.1 are resource ID #0 in the System resource file, suggesting you have zeros in mapTile[][]. Is that supposed to be true?

I would suggest checking what’s in mapTile[ix+scrollX][iy+scrollY] before you call GetIcon() with whatever’s in there, so you can ensure it’s in the valid range. I would suggesting adding a check that GetIcon() isn’t returning NULL before passing whatever it returns to PlotIcon().
 

mdeverhart

Well-known member
A couple of times on my Duo running 7.1 I was able to reproduce the blank map bug that you saw under 7.5.5, but I didn’t see the “stop sign” bug that you saw under 7.1. Most of the time it ran fine, both the compiled binary you provided and when I rebuilt it with THINK C 5. I’m not sure that’s helpful though.

Crutch makes a good point about checking the tile contents before you draw the icon. I also saw there are only a few places where the mapTile array is updated, mostly having to do with entity updates. It’s probably worth checking any places where you do mapTile array updates. I (think) I also noticed that mapTile is a 50x50 array, but you only initialize a 16x16 region at launch. Is it possible that uninitialized memory is being read later as a mapTile icon number?
 

mdeverhart

Well-known member
Also - the mapTile array is updated in a few places based on the content of the entity array, so if the entity array is uninitialized or corrupted, it could corrupt the mapTile array.
 
Top