• 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

nightingale

Well-known member
Thanks for the advice everyone! I'll try some things out tonight and see if I can isolate the problem.

I think you're right about junk ending up in the mapTile array, because I had the problem before with the stop icon when I accidentally wrote beyond the limits of another array and it overwrote that part of memory. I guess I was confused that it only happens on some computers with some operating systems. Is it possible that something outside my program is writing to that part of memory that my program is expecting to be used for that variable?

The reason I've defined my arrays as much larger than needed for this 16x16 map is that the various levels will have various map sizes, and I want to make sure my array is large enough regardless of which level I load. Is it important that I fill the entire array with some value, even if it's not currently used, so that it takes up the expected area of memory? I've read a few books now that talk about how the Macintosh handles memory for applications, but I'll admit that this is one area I still don't fully understand.

Another thing that I am aware of is that I haven't implemented any error handling yet, so when something goes wrong, the program either crashes or I get junk in my variables, so doing a check to see if the variable has an expected value is also a good tip I will try.

Most of the problems I've encountered to date are the result of human error. For example, in the code I posted, you can see I'm manually setting the values for each mapTile value. This is just because I haven't implemented the routines to open one of my map files and read the values from there yet, so doing it manually has often lead to strange results if I get one value wrong. Taking that human factor out of the equation also might help me eliminate some of the gremlins, so perhaps that another thing to prioritize.

Thanks again everyone, and I'll post an update tonight when I have a chance to try some things out!
 

mdeverhart

Well-known member
You shouldn’t need to initialize the array in order to “reserve” it - it should be allocated for your application when your application loads (since it’s defined as a fixed array in your source - dynamic memory allocation is another subject). I’m suggesting initializing the arrays with a known value to prevent accidental corruption (or to make it more evident if corruption occurs). In particular I’m wondering about the entity array, since you have a few places where you update the mapTile based on the entity array contents. If the entity array has bad data at a location you’re reading from, you could write bad contents into the mapTile array.

I’m torn on the map loader aspect. On one hand, eliminating manual errors is worthwhile, but in the other hand, debugging multiple pieces of code simultaneously is almost always a bad idea. I’d lean toward figuring out the mapTile issues first. Otherwise you won’t know if the issues are due to latent bugs in the mapTile code, or if they’re new bugs in the map loading code.
 

nightingale

Well-known member
Success!!

So after running a few tests, I determined that the value that my UpdateGameBoard routine was using to load the map tiles was junk -- the value of mapTiles was correct, but the formula I was using to calculate where to draw it was the issue. I run through a loop to read and draw each icon, and used the variables ix and iy to keep track of where I was in the array. But when I declared the variables, I did not define them. So on some systems, it defaulted to zero, and some it was -1, so it was trying to draw the tile at a strange location, or using a resource value of 25956 instead of 128 which was expected.

So I set the variables to zero when I declared them, and voila! It works!!

So thank you to everyone for the troubleshooting steps you suggested, it helped me narrow down the problem in no time!
 

cheesestraws

Well-known member
Well troubleshooted! (troubleshot?)

Uninitialised variables are a bane and a curse and should never have been a thing in the first place </soapbox>
 

Crutch

Well-known member
That’s funny. I read that function semi carefully and never noticed you don’t initialize ix and iy! Easy mistake to make and hard to find once you make it.

One small suggestion: you say you don’t do any error handling “yet”. I would generally advocate almost the opposite approach: start out with a ridiculous amount of error checking (does the array element contain a reasonable value? does this GetIcon() call give me back a non-NULL handle?), and winnow it down over time. A great way to do this ”for free” is with liberal use of assert macros (natively supported by THINK C per the standard library … just #include <assert.h>, the source is included) which, when you eventually recompile with NDEBUG turned on, vanish into nothing.
 

nightingale

Well-known member
And now for something completely fun... I've been working on redesigning the tileset to have a more original look, and I'm looking for some opinions on what people like:

Option A: Black walls
Screen Shot 2022-04-27 at 7.54.49 AM.png

Option B: Grey Walls
Screen Shot 2022-04-27 at 8.07.08 AM.png

Option C: Brick Walls
Screen Shot 2022-04-27 at 7.54.13 AM.png

Which one do you like best for a world of robots?


 

cheesestraws

Well-known member
I think the black is clearest, but both the black and the grey are pretty. I find the brick texture a bit fiddly personally.
 

joshc

Well-known member
I am leaning towards black. I think brick is pretty but something about the black one sticks out to me.
 

nightingale

Well-known member
I started with dark grey walls (same pattern as the default desktop background) with a black top, but the trouble is when I wanted to draw diagonal lines for corners, half the time they would overlap the pattern and not be visible. So I switched to the grey pattern with more “spaced out” dots. The black walls with grey top is what I made next, but I was concerned they would look “inverted” like the walls were going down into a pit rather than up to a flat part on top. I think the brick pattern looks most like a wall, but bricks don’t make a lot of sense with a futuristic robot setting.

interesting that everyone is leaning towards the black…
 

gcp

Well-known member
I think the black walls look great too - and it's probably the most visually clear, since you're maximizing the contrast between the open space where you walk around, and the impassable walls. That reasoning aside, at first glance as I was scrolling the page that image popped out as looking really sharp - even before I saw that you were asking for feedback :)

Nice work!
 

nightingale

Well-known member
So, back again with more questions! Lots of progress made, but not much to show in a screenshot just yet. I'd like to polish up a few more features and then post it to see what folks think.

So here's where I'm stuck today. So far, I have been using ICON resources for the tiles for my game. Using the toolbox call "PlotIcon" and "GetIcon" to construct my levels from the icons, and all working great. However, I want to use CICNs (colour icons) instead, because that includes a mask for each icon, so I can have transparencies for the player and enemies, which greatly simplifies their movement over different tiles. It will also make it simpler when I want to create a colour version of the icons later, as CICNs have both a colour and B&W option for each resource as well as the mask.

So, I need to use the toolbox calls PlotCIcon and GetCIcon instead, and it works fine on newer macs. However, when I use it on my Macintosh Plus, I get an error, "unimplemented trap" and have to restart the system. So I know that this is a newer toolbox routine that didn't exist when the Plus came out, but my understanding was that when Apple released a new version of the System Software, the software included a patch for the machine's ROM to implement new toolbox routines that weren't available in ROM. Inside Macintosh tells me that CICNs were implemented in System 6, so I thought that running my application on System 6.0.8 would include the patch for the new toolbox routine, but I still get this error. I tried it on System 7.1 as well on the Plus, but no luck.

So am I wrong here? If the Mac doesn't have the toolbox routine in ROM, am I just out of luck? Is there a way to use CICN resources (the B&W version) on a Mac Plus? Could I manually add a routine that handles CICNs?
 

cheesestraws

Well-known member
Could I manually add a routine that handles CICNs?

This should be fairly straightforward, though I haven't done it myself. Have a look at the Icon Utilities chapter in 'More Macintosh Toolbox', here, especially page 5-67:


Per IM, a cicn resource contains a CIcon struct:

C:
struct CIcon {
    PixMap iconPMap; /*the icon's pixel map*/
    BitMap iconMask; /*the icon's mask*/
    BitMap iconBMap; /*the icon's bitmap*/
    Handle iconData; /*handle to the icon's data*/
    short iconMaskData: /*the data for the icon's mask*/
};

So, you can just get a bitmap straight out of the struct and pass it to CopyBits without needing support for colour at all.

The best way to do this (or at least the way I'd attempt it, which may not be the same thing) would probably be to check the 'qdrw' Gestalt selector, which lets you query what QuickDraw features are available. This has a flag for whether colour quickdraw is available or not. Check this once at the start of your application and store it, then have a custom "DrawCIcn" routine that checks whether colour quickdraw is available and if so uses PlotCIcon and otherwise just uses CopyBits to draw the bitmap out of the struct.

Though this is all theoretical, I haven't tried it!
 

nightingale

Well-known member
Interesting. Now that I think about it, every machine that is capable of colour would have Colour QuickDraw on ROM, so there would never be any reason for it to be included in the OS itself... Makes perfect sense.

I'm intrigued about trying to implement this myself. This is actually very timely, because I just recently implemented a bunch of custom resource types into my program, so I finally understand how memory blocks and resources work. This seems like it might be a logical next step in my learning journey...

Right now, my program gets the ICON resource and draws it for each grid square then disposes of it and loops the process until the screen is drawn. I feel like this is very inefficient because I feel like my program is repeating a lot of tasks that it doesn't need to. Assuming I can write this routine, which I'm feeling cautiously optimistic about at the moment, is there any reason why I wouldn't load all of my game tiles into memory when the game loads, and just leave them there for the duration, using copybits every time I need to update the screen?
 

cheesestraws

Well-known member
is there any reason why I wouldn't load all of my game tiles into memory when the game loads, and just leave them there for the duration, using copybits every time I need to update the screen?

I'd give this a go :). It will likely speed things up considerably at the cost of using more RAM.
 

Crutch

Well-known member
If you are requiring a Mac Plus (or a 512k Enhanced), the routine you want is CopyMask. It’s documented in Inside Macintosh Volume IV. (This routine is not available in the 64k ROMs.)

You can just grab a bitmap and a mask (which is just another 32x32 1-bit bitmap) from a “cicn” resource (if you want to create it with ResEdit) or anywhere else, and this routine will let you blit it to the screen, precisely like PlotCIcon but in black & white.
 
Last edited:
Top