• 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
So, update time! I've been working away, and have made some great progress! A lot of trial and error, but once I figured out CopyBits, everything started flowing nicely, and I'm really happy with the progress I've made! I'm now able to use my CICN resources even on a black and white system, which means I get my masks for transparency. I've made some great speed improvements by loading all of my resources into memory and keeping them there, and I'm really pleased with how fast the game runs. Feeling pretty good!

For a few weeks I've been working on drawing to an offscreen buffer and using CopyBits to blit it to the screen, and finally got it working... sort of. The speed boost is tremendous, and I'm very happy with the speed of my game even on real hardware -- runs great on my Mac Plus.

However, one thing I just can't figure out, is how to increase the size of the GrafPort I created for my offscreen buffer. I've created a GrafPort and a BitMap, and set the port bits to the new bitmap to draw to, but it seems to cut off at the size of my screen resolution. Inside Macintosh tells me that the screen bounds are the default size of a GrafPort, so this is not unexpected, but I can't figure out how to change it! I want to create a bitmap the size of my entire map and draw it when a level loads and then copy the visible portion to the screen. But no matter what I try, I can't seem to figure out how to change the size. I've tried using SetRect to adjust portRect in my GrafPort, but that does nothing.

This is what I get, no matter what I try (I've scrolled down and to the right -- the portion to the left and up is drawn correctly):

Screen Shot 2022-08-17 at 9.31.38 PM.png

The portion of the map that draws correctly is exactly the screen size -- if I use a higher resolution, more of the map draws correctly, and I can scroll further.

Inside Macintosh leads me to believe I can change the size of the GrafPort, but it does not seem to be well documented. It talks about using GrafPorts for offscreen drawing in passing, then tells you to use GWorlds instead, and goes into great detail about that. Since my target is System 6 on a Macintosh Plus, I don't think that's an option for me. IM says you can use GWorlds on Macs that "work with System 7".

I've found a few books that talk about creating a GrafPort for offscreen drawing, and it has brought be to this point, but they were all written after System 7 came out, and don't really spend a lot of time on the topic, instead focusing on GWorlds.

I am truly stumped here. I've managed to overcome many of my dead ends by reading and experimenting, but this one has me totally puzzled. If anyone can offer any advice, it's much appreciated!
 

Crutch

Well-known member
You should be able to create a BitMap, make it as big as you want (set bounds and rowBytes appropriately), make it the portBits of the current GrafPort by calling SetPortBits(), then draw into it. Is it possible you are setting the clipRgn somewhere to the size of the screen?

You can resize a GrafPort by calling PortSize(), but you should not need to do this.
 

nightingale

Well-known member
I think the creation of the bitmap is working correctly, because if I use an emulator and set the screen resolution very high, the whole map draws offscreen correctly. That's what makes me think I'm doing something wrong with the GrafPort rather than the bitmap. I am not intentionally setting clipRgn, but is it possible that it is set to the screen bounds by default? I could try setting that before creating the bitmap and drawing.

For reference, here is the relevant part of the code:


GetPort(&prevPortPtr); /* remember original Port */
OpenPort(&offscreenPort); /* Open offscreen port */
SetPort(&offscreenPort); /* Set offscreen Port to current Port */
GetPort(&offscreenPtr); /* Get pointer to offscreen port */

offscreenBitmap = MakeBitMap(mapWidth*32, mapHeight * 32); /* create BitMap size of map */

SetPortBits(&offscreenBitmap);

/* draw map offscreen here */
while(iy < mapHeight)
{
while(ix < mapWidth)
{
drawTileXLoc = ix * 32;
drawTileYLoc = iy * 32;
DrawTile(mapTile[ix][iy], drawTileXLoc, drawTileYLoc);
ix = ix + 1;
}
ix = 0;
iy = iy+1;
}
/* SetPort(&prevPortPtr); */ /* For some reason this freezes the system... and works okay with out it... not sure why */

SetRect (&GameBoardSrc, scrollX*32, scrollY*32, (scrollX+9)*32, (scrollY+9)*32);
SetRect (&GameBoardDest, 0, 0, 288, 288);

CopyBits(&offscreenBitmap,
&robotsWindow->portBits,
&GameBoardSrc,
&GameBoardDest,
srcCopy, nil);

BitMap MakeBitMap(short wantedHeight, short wantedWidth)
{
BitMap aBitMap;
short numberRows;
short tempRowBytes;
Rect bitMapBounds;

tempRowBytes = ((wantedWidth /16) +1) *2;

aBitMap.baseAddr = NewPtr((long)tempRowBytes * (long)wantedHeight);
aBitMap.rowBytes = tempRowBytes;
SetRect(&aBitMap.bounds, 0, 0, wantedWidth, wantedHeight);

return (aBitMap);
}
 

Crutch

Well-known member
This looks OK to me. Your rowBytes will be too big if wantedWidth is an exact multiple of 16, but that’s not a big deal.

I would try setting the ClipRgn right before your DrawTile loop just as a sanity check. ClipRect(&offscreenPort.portRect) or similar.

Minor points:

Though commented out … assuming prevPortPtr is a GrafPtr, SetPort(&prevPortPtr) is wrong and I’m surprised it even complies. SetPort takes a GrafPtr, you are giving it a pointer to a GrafPtr. You want just “SetPort(prevPortPtr)”. But yes, you MAY be OK without it because CopyBits doesn’t care what the current GrafPort is. (If you try to draw on the screen later though, it won’t work, because you are leaving the current GrafPort set as your offscreen port.)

“GetPort(&offscreenPtr)” is unnecessary, you already have offscreenPort and &offscreenPort is a GrafPtr to it.
 

nightingale

Well-known member
Okay, those last few points actually clear up a lot for me!! I will admit that I still struggle with pointers and handles sometimes. At a high level, I understand what they are and the need for them and what they do, but I admit that I don’t always understand when they are required. I totally get what your saying and the light bulb just went on about a lot of things.

I will try setting the ClipRgn when I get home and see if that helps. Thank you!
 

Crutch

Well-known member
I made a mistake above, I meant ClipRect(&offscreenBitmap.bounds).

The typical rowBytes math is ((wantedWidth - 1) / 16) + 1) * 2. This prevents you from being needlessly big if wantedWidth is a multiple of 1.
 

nightingale

Well-known member
Alrighty! First of all, all the trouble I've been having with pointers is now solved thanks to your advice!

I did some more reading in IM, and I've added this code (just arbitrary numbers for now):

PortSize(1600,1600);
ClipRect(&offscreenPort.portRect);
RectRgn(offscreenPort.visRgn, &offscreenPort.portRect);

And now it's working perfectly! I had to set the portRect and clipRgn, as you advised, but also had to update the visRgn!

I can't thank you enough, it has been weeks of pulling my hair out!

I have absolutely nothing of value to add here, except…can I try the game out?

Absolutely! In fact, the machine I'm doing most of my testing on is the Macintosh Plus that you kindly donated to me a few years ago!

Now that I have this offscreen buffer issue fixed, I just have a some housekeeping matters to attend to in order to bring the rest of my drawing into the offscreen, and then I think I'll be ready to post a stable working demo for some feedback. Right now, I'd say the game engine is about 75% finished, but level design is only about 5% finished. I'd like to get some beta testers trying it out before I turn my attention to cranking out some levels!

Thanks again, everyone!
 

nightingale

Well-known member
Demo time!!

Here is a (zipped) disk image file (bootable in vMac if you like) with a few sample levels for testing.

Still lots of work to do on artwork and level design, but this demo should give you an idea of the gameplay. I would love any and all feedback!

A few known bugs/missing features:
- Some menu items not implemented yet
- When you walk on the ? tiles you should get a hint, but there is a bug that I forgot to squash since I changed the way my drawing routines work
- You can also use the "Goto Level" command without any passwords.
- On some machines (I don't understand why yet) the conveyor belts (the arrow tiles) don't whisk you along like they are supposed to, your robot just stands there. If others encounter this, I'll be curious to know the hardware you are using.
- Bottom right tile of every map is garbled

Still some features left to implement, more types of robots to make, but I'd say I'm about 75% done the game engine, so any feedback or bugs is most welcome before I turn my attention to pumping out levels!

I'd just like to say how grateful I am to everyone in this community for the advice and help you've given me! Hard to believe I started on this a year ago. My progress has gone in waves of productivity and lulls of de-motivation when things just wouldn't work, but it's been a fun project so far, and I feel like I'm over the hump. I never would have gotten this far without everyone sharing their knowledge and experience, so thank you again!

Enjoy the demo!
 

Attachments

  • disk1.dsk.zip
    771.6 KB · Views: 6

LaPorta

Well-known member
Three observations so far:

1. I get corrupted text when I am on the ? (I assume this is what you alluded to in your post).

2. The directions via keyboard arrows works fine, but the mouse is very spotty. I can click and click over and over and sometimes I get movement, sometimes I do not. One way that I consistently do not get movement is if I click in any square directly next to the player.

3. Starting from your floppy nets a system bomb with Address Error when the game loads. Copying the game to the HD and running it from the HD-started system works fine.

This was all tested from a real physical floppy made via AppleSauce on my SE FDHD.
 

nightingale

Well-known member
Ah, you found the hidden mouse control!! I actually plan to implement proper mouse control where you can click a tile and your character will make its way to that square. But that isn't done yet. What you found was a quick and dirty hack job I put in so I could test it on the real Mac Plus for which I still don't have a keyboard. There are four hidden squares, top-centre, bottom-centre, left-centre, and right-centre which act as arrow buttons. The garbled text is indeed what I mentioned in my post.

And in my haste to share this with everyone, I admit I didn't try it out on real hardware. I had it working on real hardware a few days ago, but the last few days worth of polishing and bug-fixing seems to have actually broken it... It works perfectly in emulation, at least for me, but I just tried it on my Mac Plus and my LC 580 and it bombs instantly. My SE/30 will successfully play one level and then bomb. A very perplexing issue. I will try to hunt that down tonight and re-post.


Edit: You can also use WASD, because the cursor key layout on most early macs was just awful for games.
 

LaPorta

Well-known member
The funny thing is that my first instinct was to just use the mouse; I only found out about the arrow key movement after getting to the second level! Almost all Mac games of the time (including Dungeon of Doom, which is somewhat like your game) were all mouse-controlled. So, I just figured it was a mouse game off the bat!

As for it not working, as long as I used it with the System on my SE running, there were no bombs and no issues. Only starting from the System on your floppy caused the issue.
 

nightingale

Well-known member
Okay, bug is squashed! Turns out I just had a corrupt tile on each map and I have no error handling to deal with that. I don't know why it worked sometimes. But I have it working consistently now on every system I've tried it on. Take two!
 

Attachments

  • disk1.dsk.zip
    732.6 KB · Views: 6

LaPorta

Well-known member
Workes perfectly from the floppy! That is a pretty slick game, I actually am having a real good time of it!
 

nightingale

Well-known member
Thanks! Now I just need to finish up the last few few features and make like 90 more levels with increasingly difficult puzzles!
 

LaPorta

Well-known member
Do you actually have the level editor application? I’d give it a go here as well to make levels.
 
Top