Reclining Model

Go To HomeGEOSGo To E-Mail
GI Joe


geoGlyph - Developer's Diary

This is a Developer's Diary I am keeping during production of my new project, geoGlyph. Recent entries are at the top, so if you want to read in chronological order, start at the very bottom, and work your way up.

* REMINDERS - This is an ongoing project, so when I think of things I need to do, I'll post them here, so I don't forget to include them in the program.

To Read Chronologically, Start At The Bottom and Work Your Way Up. But each day's entry reads top to bottom. Hope that's not too confusing!

 

October 4, 2009 - RELEASE!

geoGlyph is now out in the wild!

Info and Download here:

 

October 3, 2009 - Getting Ready for Release

Re-sent the most recent version out for testing a couple of days ago, and the only report I got back so far is that the bugs I fixed are indeed fixed.

So I'm getting ready for the release of the game. I put up the Info web page, and on it is a Special Offer - For a minimum donation (amount to be decided, depends on how much effort goes into it) you can provide me a geoPaint file with your own Glyphs and I will assemble a Special Version of geoGlyph with your Glyph graphics. I thought that was a cool idea, and if only two or three people take me up on it, they'll be happy to have their own specialized version of geoGlyph they can distribute at will.

But one thing I decided to do before I ship this puppy is to put in a sound effect I've been wanting to put in since the beginning - a swishing wave sound when the logo appears, and just before the Ting! sound goes off when the Singal Hill Light turns on. So instead of just silence, then Ting! You get Swoooisshhhh - Ting! which should be nicer.

The problem is making sounds is not an easy task. So I customized one of the geoProgrammer Sample files (which assemble and link with lightning speed) to play my test sound when you click an icon. This way I can iterate on the sound effect many times in the span of time it would take if I was assembling and linking it into the finished geoGlyph. So for part of today (after I have the place thoroughly cleaned) I will be playing with a simple ramp-up noise sound, and a ramp-down like a breaking wave. If I get it to my satisfaction, I'll add it to geoGlyph and be done with it.

And I am so done with it.

 

September 28, 2009 - All Bugs Fixed (Crosses Fingers)

I had to revert a disk image version because in trying to fix one bug I so messed things up that I couldn't back out the changes easily. When I reverted to the previous version, I found out that I had lost some previous bug fixes. Bad me for not backing up, like I usually do so meticulously.

But I spent a solid day working on these bugs, and the worst was the hardest. But I think it's fixed.

Mainly today I fixed the bug where Special Levels weren't saving. The game would save on a Special Level, but the Special Level itself would not. Man, that was a hard one. But I got it. Saving and loading the data was easy, but making the game start out on a particular level type was killer.

I also fixed a bug where a Saved Game would disappear if you Quit before playing a game. You could Quit, saving your game, then run the game again, Quit a second time, and poof! Saved Game gone. (This would not be a problem if you simply Resumed Game first. Quitting after that successfully saved the game.)

Fixing this, I used the last remaining available byte in the fileHeader, so if anyone wants anything else saved when you save a game, forget it! Not happening!

I also found and fixed a bug where AutoHint would not appear if you Resumed a game. The sound would play after the countdown, but no sprite. Even the Hint button would not work. It does now. The problem was when I was loading a previous game, I wasn't doing the check for matches which stores an array of possible moves, and chooses one of those for a Hint. Now it does.

It's scary when your own project, which you came to know so intimately over a period of 9 months, gets away from you. The game is now so complex that fixing even small bugs is difficult. It is getting easier to fix bugs by patching code than by following it through and fixing them a better way.

So I hereby declare that I am done with geoGlyph, barring any bad bugs that may come back from the Beta Testers. It is thanks to them that most of these bugs were found and fixed.

 

September 27, 2009 - Bugs Being Fixed

One of my Beta Testers has been reporting several bugs, all valid. He caught a bug which happened when I added the Timed Game. I put too much faith in my Pause Game routine, and forgot to turn off Board Selection during a NON-Timed Game, when you are in the Info/Options screens. That was an easy fix.

Another issue he brought up was when you start a second game (after a Game Over) the score bar drew a line, and made a score sound. Basically the problem was when I find the game is over, I enter a routine to draw the Game Over screens. But it was simply returning through the score code.

But I couldn't find out exactly how it was happening. Instead I hacked in some switch statements checking to see if the game was actually running (which it is not during the drawing of the startup screen) and just not do the score routines when the game is not running. It's a bit of a hack but it works.

Also, when a Timed Game is over, it prints a screen asking if you want to play again, and the FlashScoreBar code (which flashes the score bar when you're down in the bottom color card) was still running, even though I make sure I stop it. It's another case of code falling through and executing. I put the same conditional switch in and that now works too.

The only remaining bug I'm aware of (except not saving High Score if you break the game by rolling over the Level or Score) is that if you quit the game during a Special Level, it does not save the Special Level state. When you Restart, it's just a normal level. I can fix this, I think, but it's close. I have to use another byte in the Saved Game area, in the game's Header Block, and I believe I have just one byte left unused. Then I have to load and save that value, and ensure the game plays the right level when it starts up. This could be complicated.

 

September 13, 2009 - Beta Sent Out!

Yup. I spent two hours today removing some debug code and cleaning up a build that is V0.5, my first real Beta build. I sent it out to four volunteers.

Already I got one report back letting me know that some of my debug code got left in by mistake. And hard to spot too! In testing to see if I could alter the fileHeader block and re-save it to disk, I had the code change my name from "Sean" to "Tean" to test. The game's INFO block would come up with "Sean" the first time you ran it, but after that, it would say "Tean". And one of my Beta testers actually caught that. Wow.

Anyway, remove one line of code and that's fixed.

So this could be a very productive Beta Cycle.

Then when I'm confident the major bugs are gone, I'm going to let this baby out into the wilderness and then return to my Piracy 2.0 game and fix some bugs in that. I finished that project almost exactly a year ago, and it irks me that there are still some nagging little bugs in it. That's my next project.

 

September 10, 2009 - Quick Bug Fix

Last night I looked into the bug I discovered while testing on the C128. It seemed that when I went to the Options panel, I was storing the current Level in a temporary variable, and replacing it when done. Since Info uses the same exit routine as Options, which copies that variable back into Level, Info was messing up, but Options was doing fine. One line later, and that bug was squashed.

Now all that remains for now is to get it ready for beta. Which I did once. Now I have to do again because of that bug.

 

September 9, 2009 - 09-09-09

Tested the program on GEOS 128 on my real 128 last night, and I have to say the sound feedback is much better on the real machine. It seems the VICE emulator causes sound to lag a bit.

But in playing with all the buttons I noticed a new bug which I have logged. Just as I'm getting it ready to send out to Beta Testers a new fairly major bug appears - When you go to the INFO panel and back, the Level gets reduced. Not right away, it re-draws the number correctly, but then when you advance to the next level the number reduces, rather than increases.

Spent some time last night grabbing graphics from the game so I could create the official page, and this morning I put them into the page and did some editing. When I get it all together the page will go live. Probably not until Beta Testing is over.

 

September 8, 2009 - I'm Calling It A Beta!

I know of one bug that it would take a miracle to catch. Other than that, I'm pretty sure that geoGlyph is pretty solid. If you roll over the score, (past about 65,000 or so) it does not save the High Score. I'll try to fix this during Beta.

I'm preparing V0.5 to send out to testers tomorrow.

Yesterday, today and tonight I did the following:

When you select Hint, or AutoHint kicks in and displays the Hint, pausing the game or going to Options/Info now comes back to the hint displayed again.

Pausing before Hint is displayed would not reset the AutoHint timer, so if you were 14 seconds into a 15-second AutoHint, and paused the Timed Game, unpausing would start over. That's fixed

If you hit Pause, and then (!) to start a new game, but hit the X button (to refuse) the Gameboard was selectable, even though it was not visible.

Displaying the Hint grays out the ? button, and any selection turns it purple again.

Hitting the ? button when the hint is selected doesn't do anything, as it should be.

I now disable the Cursor sprite before printing the Pause screen.

Any redisplay of the Hint no longer makes the Hint sound, Tuh-Ting!

(C) screen did not pause the AutoHint. Now it does.

If you go to Options or Info while a Special Level is going on, the Special Level name now displays again when you return to the game.

Once again fixed the Timer Decrement. It was once again not working, after I know it was. Fixed it anyway, again, hopefully this time for good.

I set the Header up for V0.5 with values suitable for testing.

New icon, which reflects actual Glyphs in the game, unlike the one I've been using since I started, which I created before I decided on the final Glyphs.

 

September 6, 2009 - Huh. Must Be A Weekend Again

Yeah, during the weeks these days I don't code much on this project. Since it's so close to being done and the only thing left to do is pick the carcass clean of bugs, my obsession level has dropped dramatically. That means I'm not up all night coding during the week like I was during the meat of the project. Now it's just bug fixes and minor additions, and thanks to the Timed Game option each one of those is harder to fix.

But I'm close. I'm now in the process of allowing you to redisplay the Hint after a Pause, or Options/Info screen without penalty. I'm considering just letting the Hint turn back on automatically when you come back to the game screen IF the hint has already been displayed. But it's difficult. Moreso than it should be.

And dammit, in trying to fix this, I discovered another serious bug - when you're paused (in a Timed Game) and you hit (!) New Game, and then select X (No), the screen restores as if it's in a paused state, and I even believe the Timer is paused, but the GameBoard allows you to select Glyphs, even though the Paused Screen is showing. - GRRR! Must fix that one!

I'm seriously trying to get this done so I can send it out to Beta Testers early in the week.

Tomorrow is Labour Day and so I don't really want to do much work on it then, since it's the last day of Summer for my family, and we'll likely spend it outside doing something fun.

 

Aug 30, 2009 - Fixing Some Last Bugs

I hope they're the last bugs. In fact I know only of a few at this point that are still outstanding.

I fixed the bug where coming back from Options/Info in a Timed Game shows the game state in Paused mode, but the ? Hint button is purple, or active, when it should be grey or inactive - This one took a bit of time to find the right place to fix it, but I eventually got it.

I also fixed the one where if you show the Hint and then Pause, the Hint sprite is displayed, when it shouldn't be.

I did some testing to see if High Score was saving (becuase there is a bug that won't save the High Score if you roll over) and while I found that it was saving the High Score, it once reset the score from 128 to 0 on return from Options screen at level 3. Could not repro.

Another outstanding one I noticed tonight: If you go to Info/Options on a Special Level, the screen redraws with geoGlyph, not the type of level.

 

Aug 23, 2009 - Penalizing Hints!

It's never easy is it?

The last feature I intended to add to this game is the penalization of the player for using the Hint button.

The first issue - How much to penalize?

I figured Level+5 would work. 5 is the base penalty, plus the Level number, so at Level 8, you get penalized 13 points. But that seems a bit steep. What if you hit Level 100? 105 points seems a lot to lose when a simple match only gets you 3 points.

You don't get penalized below the score of 0.

When you get penalized a -5 shows up in the Points area of the screen in red.

I eventually settled upon Level/4 + 5. So at Level 4 it goes up from 5 points to 6. At level 8, it's 7 points. I think that's fair. At Level 100, you get penalized 29 points. A bit steep, sure. I may have to revisit this a bit more.

Second issue - You can hit the Hint button multiple times. Should you lose points each time?

Of course not. So I had to code it up so that pressin the Hint button reduced your score but only if the Hint button hasn't been pushed already.

This causes problems, so I had to come up with code to penalize the player only on using the Hint button, and not when the Hint Timer runs out. And then once the Hint is displayed, hitting the Hint button should not penalize.

But since a new Hint selection only happens after a Match/Collapse pass, any time you hit the Hint button you get the same result, so it only made sense to reset the Penalized flag when a Match/Collapse pass has been made.

So now the game penalizes you only when you ask for a Hint, and then only once, and never when the Auto Hint timer reveals it.

But for what seemed like such a simple task, this took a lot longer than I had hoped.

I dearly hope this is the last thing I have to add to this game! I'm past tired of it, and I'm once again nearing the apparent limit of 20K for a Desk Accessory.

I think it's time to send it to the Beta Testers who volunteered.

 

Aug 22, 2009 - The Puzzle Analogy

The closer I get to finishing this runaway monster of a project, the more I have been thinking of it as a puzzle. As a challenge in much the same way completing a difficult crossword or a picture puzzle is a challenge. You set out to complete the picture, or fill in the crossword grid. You know what the final result is supposed to be, or at least you have a very good idea of what the final result should be. And then you set out to complete that picture or grid. A hesitant step here and there, perhaps a mistake, the wrong piece, or the wrong word... then you erase that and try again. Usually you take a small section of the picture and try to fill it in before moving on to the next small section.

Eventually you can see the bigger picture filling in and you continue to sub-divide it and conquer it, until more and more of the picture appears.

Then there's that stage when you only have three pieces to fill in, or three words to complete, and you sort of lose interest in completing it because the challenge is now over.

But the thing about that is that if you set for yourself the goal of finishing the puzzle, you should then transfer the challenge mentally not to solving the individual segments, but to actually finishing it. That in itself is challenge - the challenge of overcoming the malaise and just getting it finished.

I'm at that stage now. I have one more task to complete - some method of penalizing the use of the Hint button, and then it's just fixing some bugs.

 

Aug 17, 2009 - Tiny Bug Fixes

I spent a whole evening in front of this computer fixing bugs.

The game now increases the Timer Speed successfully. This was working and then not working. Weird. I think my problem is that when in geoProgrammer I set a variable as a decimal value, such as COUNTMIN=22, and I do a CmpBI CountTime,#COUNTMIN, it's actually comparing the the address 22, not the number 22. Fixed that, I think.

I also fixed the issue of the red card showing up at the bottom of the Game Over screen.

I also fixed the issue of the Score Bar printing a line when a new game starts after Game Over.

I spent a lot of time getting the GameBusted code to save the High Score, and that is still not working!

Some progress, but to me, not enough for the amount of time I put in.

 

Aug 16, 2009 - Score Flashing is Now Working

I considered the Timed Game done, after some major testing. Turns out, though, there is a minor bug so far. When I load a saved Timed Game, the CountTime loads in, and is then decremented. So I need to either increment the CountTime when loaded, or when saved. One or the other will solve this issue.

So I put my efforts towards making a cool change that makes the Score Bar flash when it's in the last 8 pixels, conveying the urgency of the situation. This was very easy to do, thanks to GEOS Processes, and I just turn it on and off whenever I turn the timer on and off, and it all just works.

There are a few bits, like when the GameOver screen happens, it colors that bottom color card red. I may have to put an "if GameOver" conditional in there to prevent the Flash code from coloring the color card if the game is over. Should be an easy fix.

I fixed another few bugs on my list too.

So now, on my check-list of things that need fixing or adding, I am down to about 8.

Here's a new animated gif of geoGlyph. This one shows off the new Timed Game features. It starts with a Saved Timed Game, shows the timer counting down, the yellow flashing when it drops below 8 pixels, and the various Pause features.

You may notice I've replaced the gradated Score Bar. A friend advised me it looked like a mistake. It took a while, but as I implemented the Timed Game option, I noticed that dipping into the low area of the Score Bar was very un-dramatic. The new Score Bar is a series of four-pixel arrows and shows the way up. I like this much better.

While you can't hear it, this version also added a sound for when the Timer drops into the yellow. Each time it drops you hear a Ding sound.

I spent some time tonight nailing a few more bugs:

It's been a fairly busy day.

 

Aug 14, 2009 - "Major Combat Operations Are Over"

The two most major things that I had left outstanding in the Timed Game option were ensuring that the game loaded and saved correctly. Saving was easy - I just had to ensure that two variables were getting stored, and I had already made room for one of those. I had two bytes left in the Header file in which to store the game data. I had to use one of those to store the Timer Speed, because it's important that that be maintained.

Loading was a bit different. I had a piece of code that loaded in the untimed game, but loading in the timed game required ensuring that the timer started up, and a bunch of other things.

That turned out to be very simple, I just had to write a quick section of code that did those things, and used a conditional based on GameType.

And the other thing I did last night was draw the Paused Game screen. To ensure you can't study the board while paused, I blank it out and fill it with text telling you the game is paused. This was a bit more difficult than it might have been because the game also pauses when you bring up a different (Info/Options/New Game) screen, and when you come back, the screen normally does a Redraw. I had to put a conditional in Redraw to make it draw the Paused screen if the game was paused. That also worked.

Truly, now it's all details and bugs.

 

Aug 12, 2009 - Time's Time and We're Gone Away

(Lyrics from Dead Reckoning's "Time's Time".)

Early this morning I coded in last night's hand-written code work (which was short and easy) to fix the issue with the Score Tone being correct.

The code was supposed to keep track fo ScorBarY (the variable that decides the height of the current Score Bar) and use that for the Score tone (after some math is applied.) It started the tone correctly, but did not ramp the tone up. Instead it blipped it up. Then I realized that the loop that graphically loops up the Score Bar is not dynamically changing the ScorBarY variable. ScorBarY gets Points added to it in a lump sum. Then a loop draws the graph up line by line (to make it nice and smooth.)

So it was a quick fix tonight to set up a new variable to ramp up with the Score Bar itself, and use that variable in the sound loop.

That worked. Then it was a simple matter of adjusting the number I subtract ScorBarY from to ensure I get a nice range of sound from bottom to top. That worked too.

Tonight's second issue is to determine why my TimerDec code (which increases the rate of the CountTimer each level for a Timed Game) doesn't actually do anything. I know it executes because the code changes a color card at the top left every time it fires off. But the variable does not change. Trying to work out why. There is a simple condition before it runs, and if the CountTime is greater than the minimum it should fire off, but isn't.

To test this I took out the condition (which is a bad idea because it will eventually go down to zero and roll over to 255) but at least it will test the logic of the code, and I can worry about correcting the condtional problem later.

And this all worked too. The timer got faster and faster. It also exposed an interesting bug - When I display a New Glyph or Special Level screen, and redraw, it incorrectly redraws the Score Bar height.

That's good for one evening.

 

Aug 11, 2009 - It's All In The Timing

I can't keep coming up with good Timing titles for my entries.

Anyway tonight I fixed the Confirm screen, so that when you Stop a game in progress and go to the "Do You Want To Start A New Game" dialog window, it pauses the game, grays out the Hint icon, and coming back from that screen refreshes the screen but remains paused.

Pushing Play colors the icon back to purple again.

I also laid the groundwork for making the Score Bar rising note work perfectly. Currently it relies on the score rising (and lowering) to set that tone. But it was getting out of sync in Timed mode. A new Timed Game was obviously not initializing that tone correctly. Not to mention, when you load a saved game it wouldn't know what tone to play because I don't store it.

So instead I just hand-coded (on paper) a simple routine to determine that tone based on the current height of the ScorBarY variable, so no matter what happens it will always play the right tone, even after loading a saved game.

It's not in-game yet, because it's late and I want to watch an episode of TinTin I just got. Tomorrow for sure.

It's going well.

 

Aug 10, 2009 - More Timing

Because my code puts a color card in the top left corner every time my CountDown timer triggers, and another to tell me if the game state is supposdely Paused or not, I noticed that the game Pauses when coming back from Info/Options, even in a non-timed game. I should never need to pause a non-timed game, so I changed the code last night to ensure the game does not pause if it is a No Pressure game.

I also fixed the Hint code to ensure it's always flashing. Somehow I have some code that stops the Hint cursor from flashing, so the first time you hit the Hint button it wasn't flashing. Fixed that.

I also put in code to prevent the Hint button from triggering if the game is paused.

Enough for one night. Next: Fix the NewGame screen so it pauses and recovers properly like Info and Options now do. And gray out the AutoHint button while paused.

 

Aug 9, 2009 - Timing Tweaks

Spent this morning watching the last three out of four Sea Patrol episodes (an amazingly good Australian TV show about the Australian Navy). But it's getting close to movie time, so I have to leave the Season Finalé for tonight. But also I have to write a toy review tonight, which is the first I've written in some time. We're soon off to see GI Joe.

Movie's over, it was way better than I expected. And now I'm sitting in front of my computer trying to figure out how to sew together the Paused Game features into my game.

And I have to tell you that it's driving me crazy, and that this project is making me sick to even think about. I'm tired of it. I want it done. And the nitpicky details of making sure the game recovers back to a perfect game state any time I go to Info or Options or start a new game and Cancel... it's just making me poke code into places I'm not sure it should go, and eventually I'm sure it will be a spider's web of deceit and intrigue that even I won't be able to figure out anymore.

And what really pisses me off is not when I make mistakes, but when the linker comes back and tells me I have errors that just don't exist.

I just want this Timed Game option in and done, so I can call this project over.

Of course that won't mean anything because once I'm done adding features, and once I think it's done, I'm going to hand it over to a few Beta Testers who are going to come back with problems and I'm going to have to dive back in and figure out how I screwed it all up.

It's late again, midnight, and I'm still sitting and coding. I've been trying to patch holes in this code for hours now, trying to ensure that coming back from Info and Options I get a perfectly paused game.

Weirdly, I useFreezeProcess on the CountDown timer when I call Info and Options, and when I come back, it's paused, but then when I hit the Play button, the Paused flag gets reset to 0, but dammit, the CountDown did not Unfreeze like I told it to. So I had to resort to trying Restart instead, which not only forces the process to run, but resets its timer. This gives the player extra time I didn't want to give him. But since it works, I'll live with it.

And then I had to ensure that it all worked fine with the No Pressure (untimed) game.

During the process of fixing this, I discovered I was setting the GameType variable byte in two separate places, which for some reason worked fine until I tried accessing the variable outside those files. I fixed that, and it seems there was no harm done, but that in itself confuses me. Having GameType in two files - did it use each one locally to its own file? Or what? Either way, when I tried to access it from a third file, it caused problems.

I still have a long list of fixes and tweaks, but nothing hugely major. Mainly I have to make sure that the New Game screen behaves like the Info and Options screens, and recovers identically if you Cancel.

Then I have to make sure that while you're paused you don't get to study the game screen, so a screen of random imagery will replace it. To do this, I figure I simply have to edit Rdrw so if the game is paused it draws the PauseScreen instead of the GameScreen. Then when I hit Play after pausing, it does another Rdrw, only this time unpaused, so it draws the normal GameScreen.

Another 13 bullet-points exist that I have to go through and ensure are working correctly. After that, I can call the game finished, and do serious bug testing.

When this project is over, I think I'll edit Piracy 2.0 and resubmit it to the Interactive Fiction community. There are a handful of annoying bugs that require attention. Then when that's done, I'm hunkering down on iPhone Ap development. Not sure when, but I'd still like to finish the Bots game for GEOS and perhaps write the Sudoku game I've been planning.

 

Aug 8, 2009 - Timing Issues

Lately I've been tired at night, making it hard for me to code, but I did get some solid work done. The Timed Game now pauses the countdown when off-game, even during the Match/Collapse sequence, so valuable time is not ticking away when you are not directly in control. Now, the timer should only count down when you are in control.

A lot of my recent tweaks had to do with that. Making sure the timer is not counting down when the game is busy doing its own thing.

I'm still plagued by the NewLevel not reducing the CountTime properly. I'll have to work on that.

And the next and I believe last addition to the game feature list is the Pause button. The code for that is drastically simple, as I have a working TimerOff and TimerOn function which I can use at the moment tied to dummy icons for testing, and it appears to work well.

More work tonight, I hope.

Well that was quick. Despite some math issues I was able to get the Pause/Play button in and working like a charm with zero difficulties.

Yeah, right!

Ok, so when I started thinking of how to make a Timed Game work based on the framework of a casual un-timed game, I wrote up a doc on what changes needed to be made, and it was fairly minimal, even taking into account some of the quirks of the game. Last night I got it all working, except when you come back from the Info or Options screen while you are paused, the game still thinks the timer is on, so it continues to count down, despite the fact that the Play button is still active (meaning the Pause button was activated before I went to Info or Options.)

So now I need to find and change the code that restores the game screen after Options and Info, and add a check to see if it's paused or not. This may not work, however, because GSelect, the loop that allows Glyph Selection, turns the Timer off and on based on the Match/Collapse sequence.

The change needed could be as simple as adding a check on the Paused variable, and set TimerOff or TimerOn depending on that, upon exit of Options/Info.

Or it could be a bit more complicated, in that I have to make that check and do a TimerOff or TimerOn in the GSelect loop itself, which is already a complicated loop.

But the fact that it works otherwise was very heartening.

 

Aug 1, 2009 - Back from Vacation

We're back from vacation. After I logged some bugs and tasks for geoGlyph, I put the project away for a week, and now I'm enjoying a relaxing weekend at home. Will likely get back to the project tomorrow (Sunday). Spent most of this afternoon blogging my vacation.

 

July 26, 2009 - Actually Got Some Work Done

Family visiting, going nuts each day, no time for coding. But we got back from Six Flags last night, and everyone went to bed early (exhausted) so I did about an hour's work.

I fixed the HorizontalLine bug. The manual says I should load the accumulator with a pattern byte, and HorizontalLine uses that pattern to draw. Well, every time I tried, it did a pattern of random bits. No idea why. So I converted the code to use Rectangle instead. It worked.

But it was drawing one below the top line, leaving a line of score. I fixed that by decrementing the counter after printing the line. This also solved the issue with the count bar drawing on the game frame line at the bottom.

I also fixed the score tone sound so it sets itself at middle each new level, and drops when the score bar drops.

That was actually a nice piece of work for just an hour, and I was tired. Today it's a Red Sox game in Boston, so it's go-go-go again.

 

July 18, 2009 - Main Sounds Done

Spent most of today playing with sound. Now, I have all of the main sounds done.

Now I simply have to create some 3-voice fanfare chords, one for each Special Level, and one for a New Glyph. And something for the Busted screen!

I won't be making sounds for icon clicking, I don't think, such as the Options screen... that's overkill. As long as the game has a decent, recognizable soundscape, I'm happy.

By the way, it is interesting (to me at least) to note that for the chord progressions that announce Special Levels and New Glyphs, I'm getting my daughter to write them on her piano, and I'm going to translate those notes directly to my game.

 

July 16, 2009 - Bing! Bong! Swish! Kyewww! Click-click-click-click! Tuh-Ting!

Wow. Progress! Tonight and last night I spent a lot of time putting sound into the game and refining that sound.

I played with the sounds a bit, refining them. Even now they're tentative. Ok for now. But open to further refinement.

I also fixed the AutoHint code. After putting in a sound that triggers when the Hint appears (whether by clicking the Hint button or waiting for the AutoHint to come on) it suddenly became evident that AutoHint triggers every X seconds, and not just the first time. Tonight I put code in to check first to see if the Hint was on, and if so, not to draw it again, nor play the tone.

Right now, Hint makes a tinny single bell sound.

I also decided to head off any sound voice conflict during the Click-Click-Click-Click stage by alternating between Voice1 and Voice2. Now, every second click is sounded by one voice, and every other one is sounded by the second voice. This way we get fewer conflicts which would cause a tone to cut short before its sustain played out.

Further, I took all current sound effects and made them obey the Sound toggle. Sound Off? No sound. Sound On? Sound.

Tomorrow: Score Bar rise. Bloooop!

 

July 14, 2009 - Sound Execution

Last night I decided to bite the bullet and begin adding sound. First, I wanted to split out all the sound functions to a new source file, so I set it up with a new file, moved a very simple sound routine out to it and reassembled. Damned game crashed! Or hung.

A similar thing happened a week or two ago when I added a new file to store processes in (which was getting ready for sound and the Timed Game since processes would be key to both) but it didn't tweak with me.

I still don't know if geoProgrammer has an upper limit on how many source files the Assembler/Linker can handle, but I'm attesting now that it does. And I breached it. Twice. Each time the code was the same, just moved to a new file, and it crashed on execution.

So now that I know, I spent more time last night undoing what I did and setting Sound up in G-Sprite.s, renaming it to G-SpritSnd.s. Then it began to work.

So last night I coded BING and BONG, the two sounds you get when you select two Glyphs. It worked, but there's a tiny bit of lag between the mouse click and the response sound. That may be a result of the emulator, but I doubt it. It may just be the code. I can't trigger the sound until I know the event, and the event only happens once some calculation of the mouse's position is done, and that takes a tiny bit of time, so that may be that. Nothing to remedy the situation. But it's still pretty cool.

But I notice that I also went over the 20K limit again, and thought that was my problem before I tweaked that it was the number of source files, so I decided for good to remove the animated logo, which does little but take up about 3K of memory. Removed that and now I'm at 17K. Plenty of room to add the sound and Timed Game option (I hope!)

I stayed up way later than I wanted (2:00am) and just as I was getting ready to fall asleep Wanda began yowling and freaking out. I heard a crash and yowl... I thought she had hurt herself by falling or something. I went running, and she was huge-tailed, staring out the kitchen window. I opened the blinds and outside the window was a black cat, eyes shining, staring up at Wanda. She was freakin! Other cat Willow came running and the second Wanda saw her, she pounced on her and attacked her. Not nice. I had to go calm Willow down, but she hissed at me. I talked softly to her and petted her and she seemed better, but still on her guard. Third cat Rowan had no idea what was up, so she just watched. Later, at about 5:30, it happened again, only louder! I opened the blinds to see the outdoor cat standing on our window sill staring nose-to-nose at Wanda, who was taking a SERIUOS hissy fit! Not much sleep last night, is the upshot.

Tonight, however, I intend to do the Swish sound during Swap. Open the V1 gate, drop the frequency during the Swap loop (which is only 8 steps) and see if that granularity is obvious. If it is, I'll have to change it to a Process which can drop frequency at a 60th of a second if I desire, using the interrupt-driven Process system. We'll see which is necessary.

Well, it turns out that after putting it in, the 8-step frequency swoop is fine. But all my sounds are lagging by about 1/8 of a second. Even to the point that the Swish sound is swishing AFTER the Glyphs swap, which is impossible, because the drop in frequency which I'm hearing is happening after the code is running. I'm thinking the VICE Emulator may be at fault, so I took some disks in to work today and transferred the files to disk so I can test it on a REAL C64/128.

July 12, 2009 - Sound Practices

Not much serious work over the past several days - been busy with family vacationing and stuff. But I did manage to play with sound a bit, as reported earlier. To help, I may be able to use the SOUND command of the C128, which allows for a lot of variables to be passed to a single command for immediate results. Those values can then be translated back to individual registers for probably some useful results.

But the single-most important thing I did was find the SID Memory Map in the C128 Programmers' Reference Guide, which is an awesome book about the 128 and goes into great detail (in surprisingly few pages) about how the SID chip works.

The SID Memory Map (which I scanned in and augmented a bit to make it more readable/usable:


(Clicky)

This now allows me to much easier play with sound and start coding sound events and processes.

For some of my code, a sound event will be sufficient. An event triggers at a specific time. So the Select Code, for example, can make a BING! when you make your first selection. It's a one-off. It triggers the sound and it's done. Same for the second selection, it can go BONG!.

However, for some sounds, I may want the sound to dynamically change after triggering. Say, the "Swish" sound when Glyphs swap. I can go about that two different ways. Since the Glyph Swap itself takes a short amount of time, I can trigger a dynamic drop in pitch during the Glyph Swap loop. This would mean I can trigger an event during each of the loop cycles. But since the Swish only has 7 significant cycles, the dropping in pitch will happen in 7 discreet steps. This may be noticeable to the ear, and undesirable. (I'm not sure yet. I have to test it.)

But if I use a Process instead, I can trigger the process (which will cycle through more pitch drops, making for a much smoother pitch drop) which can have as many interrupt loops as I desire, and when the process is over it kills itself. This is a fire-and-forget style that allows me to trigger the sound, and my code no longer has to worry about it.

Processes for sound, however, may be slightly dangerous. If one process starts, and it's needed again before it finishes, it may cause issues.

So for sound, I have decided to use events for some things, and process for others. Processes for things that require dynamic sound changes over time that don't sync up well with loop cycles, and events for those single triggerings, or triggerings that can be adequately controlled during a given loop cycle.

Examples:

Trigger
Sound

Event/Process

Select1 BING! Event
Select2 BONG! Event
Glyph Swap Swish Event Looped or Process
Match Fail Buzzz... Event
Match 'Splode Kyewww... Event Looped or Process
Collapse Series of clicks like dominoes falling Event. Once per level hitting bottom
Score Bar Rises Bwooom Event Looped or Process
Hint Buh-Ling! Both
Level Over Swisshh Process

Example: Score Bar Rises

Since the Score Bar goes from Y1 to Y2, and the loop depends on that difference (a score of 5 loops five times, rising the bar up on pixel per loop cycle) I can simply use that loop cycle. But if the rise is noticeably steppy, I can create a Process instead that takes Y1 and Y2 and cuts it up into much finer slices and rises up in much faster loop cycles (since its loop cycle is determined by interrupts instead of my few loop cycles). So this will be a question of experimentation. Which method is better? Won't know until I try both.

During a Timed Game, the Score Bar will drop every X interrupts (depending on the level). It will make a low BOOP sound, which only needs to be triggered when it happens.

Example: Hint

Since the Hint shows up as a single event, if I would like it to make a double-sound like Buh-LING! I need time between the first note to the second. Since the Hint arrival is a single event, I can't do that, so I can instead trigger a single sound when the event happens, and also start a process which simply waits a certain amount of time and triggers a second sound, and disables the process. GEOS's Sleep routine would be ideal here, but my early tests show that Sleep Timer and Processes don't work together. All my early efforts crashed the system if I had both Sleep timers and Process timers running at the same time. Each worked on its own, but not together. So the Process would simply run once and disable itself.

Example: Level Over

Level Over uses one of five screen swipes. Each is different in duration, and the smoothness of the loops can differ. So I can just trigger a Process regardless of which swipe is used, which will allow for a much finer loop, and for this case, I don't care so much when it finishes, though I could also use the different swipes to tell the Process how often to run, so it can finish faster for some, slower for others. (ie: the left/right swipes are slower due to GEOS BitmapUp code taking longer to draw, while up/down swipes are faster because I'm drawing one graphic of 8 Glyphs instead of 8 individual Glyphs, as I am vertically*, and the full-screen explode is much faster than either.) If I didn't mind the granularity of the pitch decrease I could just use the loop to do the triggering. I suspect, though, since the loop only runs 6 cycles, it will be too noticeable.

I'm also hoping to be quite clever and use muliple voice channels for looping events like the Collapse (which will be a series of quick clicks) so sounds can overlap rather than cut each other off. If I trigger Voice1, and then need it again before its release is finished - which would depend on how quickly I would need it versus how long I have made the sustain fade out - using Voice2 on the next loop cycle, and then Voice3, and back to Voice1, I can safely allow the sounds to overlap. I'm not sure this will be necessary, but one thing to watch for is if another event happens that requires a voice, it will mess this up. And since Hint can happen at any time, I may have to reserve a voice just for the Hint, otherwise it may fail badly.

Still, this is all hypothetical at the moment as I have not yet done any serious sound testing in-game. I look forward to it, though.

I can also do sound in geoGlyph as I see fit. I mean I don't have to make noises at every single action. I can just do a few and get away with it, or I can do more to fill out the polish if I have time. And since I really have no deadline other than my growing impatience to finish this project, I may do it all. Or I may compromise and do only some.

Either way, for the RetroChallenge 2009 deadline which looms, I will likely do only those most important sounds, if any, and then expand on that for the full release.

I think that for the RetroChallenge 2009, I will have to submit a version that does not contain the Timed Game option, which will require some small changes. Then, if I get sound and the Timed Game done by July 30, I will re-submit.

I spent some time tonight removing those bits of code that imply there is a Timed Game option. I removed the Sound option because there is no sound currently. I removed the saved game in the header. I removed the test icons for the Special Level testing. I removed unnecessary graphics now that I don't need them. I created a new graphic for Start New Game. I fixed the color for the Start Game screen. I also removed a saved High Score, and altered the Header Text to reflect V0.9, Special RetroChalleng version. Other than that it was just tidying up after those fixes.

* - I originally wrote the left/right/down/up Glyph swipes for Level Over to use individual Glyph graphics, drawing each row or column as 8 individual Glyph explode frames, because those graphics already existed in memory. But the code was slow due to BitmapUp being slow. But since for the full-screen explode, I already had graphics representing a single row of 8 of each of the 6 Explode graphics including spaces, I re-wrote the up/down explodes to use the row of 8 instead. This was much faster for up/down. However, I also tried doing that vertically - making 6 columns of 8 explode graphics and drawing a full column for each loop for the left/right swipes, and the speed did not change. I imagine it has to do with how Bitmap calculates vertical positions on the screen which must take longer. So I reverted back to using single images for the left/right swipes to save the unnecessary extra memory used by the column graphics.

 

July 8, 2009 - Progress over the past few days

Played with sound a bit in BASIC. I'm reading through COMPUTE!'s Beginners' Guide to C64 Sound and doing some of the exercizes in the book. I made some rudimentary beeps and hisses. I did make a nice decreasing hiss that might make a nice "Swish" for Glyph sliding. I know enough about the SID chip to know where to put the ADSR envelope, how to trigger it, but things like ring modulation and tone alteration are beyond me at this point. I'm hoping going through the book's exercizes will provide me with a primer (pronounced PRIME-er, not PRIMMER, because there's only one fucking M, ok?) for doing some of the things I've never done with sound on the C64/128.

Got the Info screen in roughly, then spent about two solid hours tweaking positions until it looked ok. Stayed up way later than planned and then got woken by a phone call for my sister-in-law (who's visiting) who had gotten up at 3:00am (with my wife) to go to Western Massachusetts for a balloon ride. The pilot called me at about 4:45 or so asking for them, because he saw on his radar a thunderstorm moving in from the west. "Looks beautiful to the east though", he said. Uh... so? You're not East. You're where you are, and the storm from the West is moving towards you. Anyway, that balloon flight was cancelled, but I got so little sleep I was awful when I had to get up to get my daughter to her Drama class at 9:00. But though it took time, I got it into shape, ready to put in Info Screens 2 and 3.

Last night I dummied in Info Screens 2 and 3, which for the moment printed the same data, but at least I could navigate back and forth. Or so I would have thought. Then when I ran the Desk Accessory it gave me a disk error. At which point I started thinking: Oh. So that's the upper limit on memory size for a Desk Accessory. The GEOS Programmers' Reference Guide mentions that Desk Accessories have specific limitations, and tells you that it describes those limitations later in the book, but I have never been able to find where. I'm guessing like a lot of the book, the promise of more info later was ignored or forgotten, and got published without it.

So the issue is that I am now at 21K, and when I load the DA it gives me a disk error. My guess (without having looked up the error code) is that Desk Accessories are allowed to be 20K but no more, otherwise the code that swaps out the application fails, because it doesn't have enough room to do its job.

The first thing I did is decide not to do Three Info screens, and to keep it to the one. And that one would have my URL so any further info could be put up on my website, where I can talk about the origin of the game and how to ensure it will save options and game state (by not renaming the DA)

One other thing I did last night was to go through the Glyph.s main code file and comment out a lot of old test code, which I hoped would shrink the DA's max size. Did that, reassembled and relinked, found the areas where code was calling commented-out routines, fixed that, removed the second and third Info Screen dummy code, and the DA reduced itself from 21K to 19K. Win! (But win enough? Once I add the sound code, and Timed Game options, will it bump it over 20K again?)

I may have to cut deeper, and if I do I can easily remove the aniamted Logo, and just have the lighthouse show up dark, and have the window light up. BING! I'm guessing due to the sheer number and size of the animated frames, I'd lose at least another 2K. Might be worth it. A Desk Accessory should be a pared-down application anyway. I guess I'm already overblown on that respect. There's a lot of flare in there that is not strictly necessary, but it does present a polished game.

RetroChallenge 2009 update - My entry has been acknowledged, and links to this Dev page are up on RetroChallenge's page. Now I just have to finish this thing.

 

July 4, 2009 - Happy Fourth, America!

Been fairly busy for the past few days - we went down to Sandwich, MA (on the Cape) yesterday to have Tea at Dunbar Tea Room. Boy, I think I'll never go to the Cape for a day trip again. Getting off that place in afternoon is aggravating.

I'm in semi-vacation mode, but I got a few replies to my inquiry as to why my game wasn't saving in GEOS 64. Greg King gave me some pointers, saying I had to load the Hile Header Block again using getFHdrInfo. It's because GEOS 128 uses RAM to store the swap file when loading a Desk Accessory, and GEOS 64 uses a swap file. The problem is that while the Header Block is loaded automatically when loading a Desk Accessory, GEOS 64 then overwrites that data writing a Swap File.

So I tried setting the pointer to dirEntryBuf and ran getFHdrInfo, but that didn't work either. Greg tells me that's because dirEntryBuf is set to the Swap File, which makes sense, so I was only overwriting the Swap File.

So he suggested using FindFile first, which refreshes dirEntryBuf, so if I use FindFile, and then getFHdrInfo I should be able to successfully save my game data.

And it worked! Wow! Finally! GEOS 64 now saves the data just like GEOS 128 always did.

He also suggested, though, that since FindFile looks for the filename "geoGlyph", if a player renamed the Desk Accessory it would fail the FindFile.

So I'm going to use FindFTypes using the Permanent Filename. I'll search the disk for Desk Accessories whose permanent name is "geoGlyph" and I should be able to use that filename for FindFile and all should be well. The only problem then should be if someone duplicated the file to disk and renamed both.

Well, it could be just something I messed up, but the Permanent Filename search failed. But I'm just going to put in an error dialog that will tell the user that the saving ability has been disabled because the Desk Accessory has been renamed, and advise him/her to change it back to geoGlyph.

Also today I spent some time planning out the Info screens. But as this Desk Accessory is now reaching the size of 20K I may have to cut back on extras at this point. I may even have to remove the cool animated starting logo, because it's really just a waste of memory for a Desk Accessory which should remain fairly small in memory footprint. Perhaps I'll just do a one-page Info sheet that points to my web page, where any extra info will reside.

And I also spent some time tonight in BASIC playing with the sound chip. Planning out sounds. I think I came up with a fairly decent Swish sound for the Glyph Swap. I should try to incorporate it tomorrow sometime, but I'm going to the beach, so when I'll get the chance I don't know.

 

 

June 28, 2009 - Cooking with Gas!

Wow. I got a lot done this weekend. Not only did I write all of the various Special Levels, I coded when they come in, and now I have the screens explain what the Special Levels mean.

There are a few problems, mostly having to do with the timing of the screens. Right now we get an extra Redraw of the game screen before the level comes in, and I have to fix that.

I played around with the Special Level order of events to ensure I got no extra screen redraws, and now it looks just lovely. I had originally put in a set delay, but now the delay checks for a mouse click and ends the delay if it detects one, so you can quickly skip past these informational screens as they appear if you wish.

And here's what the Special Levels look like in action:

After this, I am going to play with sound. I have some solid ideas, I just have to find a good C64 sound editor and play with sound values to see what I want, and get those values into the code.

 

June 27, 2009 - Special Levels Going Very Well

Thankfully, when I created the code that clears Glyphs after a match, I made it in such a way that swapping out different clearance methods was dead easy.

Now, when it finds three-in-a-row, it clears those three. But it can also do other things as well. So for each horizontal match, I do a regular clear (the three found) and then for each LevelType I can add other clearance methods. And then I do the same for the vertical match.

So within hours I had all the clearance methods I wanted to do done. And I'm glad I did it, because two of my original methods were way too aggressive, and caused almost endless cascading. Now I have them much more balanced. I only have one more to do before I call that done, and then have to create the code that draws the explanation screens so people know what kind of level they're playing.

Ah, it's good when things go smoothly.

And now I have the "geoGlyph" at the bottom being replaced by the name of the special level. Excellent.

 

June 26, 2009 - Timed Game or Different Levels?

I have done a lot of setup work for the Timed Game option. That is, I have flowcharted most of the work required to get it to work. I did play with a simple routine to count down the Score Bar every 3 seconds, but it didn't work, or at least it didn't visibly work. I was just rushing it, and testing it, so I may not have been careful enough.

Either way I think it may be wise to go with my original plan - and that is to complete the normal game before adding a timed option, and that includes adding different level clearance methods.

I've decided that every 4 levels I will do a randomly-chosen different level type. (I'm going to have to offset it by 1 though, so at each 16 levels I'm not introducing a new Glyph and at the same time playing a different kind of level. It might be nice to have the special level just before adding the new Glyph.

I've done the groundwork required to get started, and to get started I have to change the Match code so that it currently does what it already does, but with the code organized a very different way, to make way for the other various levels.

So for now, Timed Game gets pushed back a bit.

And by the way, still no update on why this thing is not saving on GEOS C64. Just further confirmation (from a tester) that it's true. Yet it works on GEOS 128. Go figure.

 

June 21, 2009 - So It's Not Me!

It struck me that I had learned a lesson from the Sprite issue - the fact that the sprites would not take color commands. The IO_Out/In routines allowed that to work on the 64. Then it struck me that the same problem could be happening when I save the Header Block in geoGlyph.

After all, GEOS says it requires the routine InitForIO to allow programs to access the serial bus, which the drive is part of. So I did that, and the DoneWithIO when I was done. It did nothing bad to the 128 version, but on the 64 it then crashed right out of GEOS.

I played with this for some time, including using my own routine which just swapped the value of address #$1, and that also did not work.

I'm back to square one on this topic. I have no idea why the C64 version won't save the Header Block, but the 128 version does.

I have put in a request for help on comp.sys.cbm, and if I don't get a response, I'm not sure what I can do. I'm at my wit's end.

My option is to go through the program ripping out those parts that save data, but that would only cripple it so it won't save on a 128 which it does perfectly now, and would change nothing on the 64 version. If I can't sort this out by ship time, I'll just have to put a notice in the Info that saving data may not work on a 64.

I will also investigate Hazard, which has a save high score option, first to see if it's actually working, and if it is, I can dip into the code to see if I did anything special to get it to work. (Actually I just checked the code, and I'm doing exactly the same thing. This is weird, because earlier I tried using the code from Hazard that inputs the player's name, and that just didn't work at all.)

So I'm at an impasse here. But with no obvious fix, I'm going to go ahead and work on the other unfinished aspects of the project and hope a solution presents itself. Otherwise I will have to ship it flawed. And anyone who knows me knows how much that irks me.

 

June 20, 2009 - I Hate When I'm Stupid

(I began this sentence four times before I got the first word right and didn't have to backspace:) Tonight I went to the Norwood High play "Snow White", and on my way home I went to my office to transfer some files. Since my second computer is down (the one with the 3.5" floppy that can actually transfer .d81 files to 3.5" disks) due to a failed power supply, and my main computer has no floppy drive, I could only do that job while I was at work.

While there I was testing to see if my fix for the C64 actually worked, by using the C64 emulator (I'm coding this on a C128 emulator) and sure enough all of the sprite coloring issues are fixed.

However, this isn't all good news.

Somehow the program stopped saving data to the header file. It no longer saves the Options, and does not successfully save a game.

I don't know when this happened, but I'm sure it must have been when I added the Score Rollover code. I'm only guessing.

So I was going to sit down now and see if some other pages of code (those that save data) didn't get corrupted along with the DoNewLevel code that got corrupted recently (see last post) when I added the Score Rollover contingency code.

So I go to check - and realize I left my flash drive with all my dev files on it - in my computer at work.

Now it's not an hour away, it's more like 15 minutes, but it also means going over 10 fucking speed bumps (and harsh ones too) to get out of Windsor Gardens, and then drive to work and then go over those damned bumps again to get home.

Not this late at night (It's now 11:15pm).

So I'm going to just chill here and go get the flash drive tomorrow, so I can track down this problem, and:

Last night and this morning I spent some time writing down segments of code I would need to successfully add a Timed Game option. It's a remarkably small number of changes, but I'm sure I'm missing some things.

I was going to try my hand at the CountDown code (the code that counts down the Score Bar every few seconds or so) tonight - but I left my flash drive at work.

Then I figured I may know what was causing the problem with Rand Test 2, the random number tester I wrote last year. (On a real C64 it doesn't register random numbers from the SID chip random register like it should, but I believe my IO_Out/In fix will solve that issue as well, considering the problem only exists on the 64, not the 128, and that I am trying to read directly from the SID chip, which is swapped out while GEOS is running.

I figure I can fix that problem in about 15 minutes.

Except that my damned flash drive is at work.

Lucky I have a fairly recent backup here, and my most recent changes to that code was sometime in November, I should be safe. I just have to remember to copy it back to the Flash Drive.

I went to the old backup and tried it, and it worked like a charm. Fixed.

I hate when I'm stupid. Did I mention that?

 

June 19, 2009 - Dammit! geoWrite File Corruption!

A while back I was editing Glyph.s, the main source file for geoGlyph. Using geoWrite, it stores each page in a VLIR record. I was thinking I had fewer pages than I did. I scrolled a page, which added a page, and it must have gone over the GEOS page number limit, because weird things began to happen.

I'm guessing that once you roll over the maximum number of pages, page additions that happen during edit (when you scroll over a page onto a new one) no longer work correctly.

I fixed the immediate problem with the file, finding pages I could remove to make room, but the corruption seems to have remained. Since I don't edit that file much anymore (most of it is solid, unchanging code) I haven't had a problem with it since.

But last night I was adding the code to go to GameBusted if you roll over the Score. (I successfully added the code to go to GameBusted if you roll over the Level.) This should have been a simple task. It turned out not to be.

So now I set it to a max score of #$ff00 (65,280). Now, when a level ends, I do a compare of the high byte to see if it's #$ff, and if so, I stop the game and go to GameBusted. (Famous last words: I fully expect no one ever to reach that score. But just in case, I coded this contingency.)

But many attempts last night to get this to work all failed.

Then today I printed out the pages of code that I changed (in the previously solid Glyph.s file) and part of the code at the bottom of the page was missing!!!one one one!

The trailing part of the code on that page, forced down by my additional lies did NOT scroll to the next page. It was just gone!

So the DoNewLevel code (which is vital to even start the game, and to start every level) was busted. Instead of setting otherPressVector to GSelect which allows Glyph selection, it went on to a piece of code that colors the system icons.

So the subtle corruption of Glyph.s got me in the end!

But now that I realize the problem, I went back to an old copy of that file, retrieved the vital missing lines, and have manually re-inserted them into the corrupted Glyph.s file.

I just now assembled the file, and with proper save-game data placed in the Header, I am now able to test it. I set the Saved Game to be a score just under #$ff00, so now I can roll the level over once without going over the score. The second level rolls over the score, and correctly does GameBusted, stopping the game properly.

Whew! I was seriously thinking I had my code logic messed up, but it didn't make sense.

Only in light of what I now know about that corrupted file did the failure make sense.

So I must remember to be very careful with that file. I think that once you go past the maximum page number in a geoWrite file, it breaks, and no longer correctly handles page addition during edits. Damn.

Now do you see the benefit of code that properly handles maximum number rollovers??? I'm spending time to elegantly handle it in this game, and the coders of geoWrite seem like they did not do the same thing!

But the good news is it seems to work.

The bad news is that to add a Timed Game option, I will have to do some hard editing of that mysteriously corrupted file, and further code may go missing unless I am very careful.

 

June 16, 2009 - Two Odd Things

Odd thing one: and this is cool. I did not know about Frodo, a C64 emulator for the Palm OS systems. My Palm TX is capable of running it, so I took some time today and set it up. It's not a perfect system, and running GEOS on it was iffy, but I did get it to run. I copied geoGlyph to a GEOS Boot disk in .d64 format, converted it to Palm .pdb and installed it.

Here, Frodo is loading GEOS.
Here, GEOS is loaded, waiting for me to run geoGlyph.

It is a very limied emulator. It has no ability to emulate an REU RAM expansion, and is limited to only one 1541 drive, and no other options. It is very unstable loading GEOS, and has no mouse emulation either. So I'm stuck with joystick input, which is far from optimal, and other issues. But I did manage to get it to run.

The result:


Odd thing two: and this is not cool. When I played geoGlyph on the Palm TX I noticed that the Glyph sprites that appear and slide during the Swap, were the wrong color. Then I noticed the Hint sprite wasn't flashing, and the Selection sprite was the wrong color.

Oh dear. All this time I'm developing on the C128 and it worked. Suddenly I'm seeing something broken that I have never seen broken before.

So whenever I store the sprite colors into memory, the C64 is not getting those instructions. I fired off a request for advice on comp.sys.cbm, but have gotten no responses yet.

Then I rememberd geoMimic. My first attempt at a GEOS game. I remembered that whenever I poked into the SID chip for sound, I had to execute a special GEOS command, InitForIO, which stops interrupts, swaps out some memory banks, and stores the values. Then DoneWithIO restores the system, job done.

This is a command that swaps back the C64's video memory bank, if I undersand it only a little. But it is essential for directly accessing the sprite memory, or that's my working theory. For the rest of my sprite action I am using GEOS Kernal routines, which I assume perform this switch during each operation.

So my task for tonight is to put those commands in place and see if it suddenly works for the C64.

Cross your fingers.

Ok, so that worked. It turned out to be a little simpler, but finding out how simple would have been impossible had it not been for my geoMimic game.

Rather than calling InitForIO and DoneWithIO, I had a command in geoMimic (that allowed me to access the sound chip) that did a much simpler thing.

IO_Out:

MoveB 1,IO_Store
LoadB 1,#$35
rts

IO_In:

MoveB IO_Store,1

This allows me access to the video memory that GEOS swaps out. I couldn't find this in the GEOS Programmer's Reference Guide, and I can't recall where I got it, but I'm sure I found it out during the development of geoMimic, which is the only game I have written in GEOS that uses sound, until this one.

 

June 14, 2009 - Some Things Are Better Left Alone

Trying to improve the FallbyRows code, I hoped to be able to prevent it from drawing all the unnecessary blank Glyphs (The last frame of a five-frame explosion) but couldn't do it. Tried everything. I let the code that decrements the array wrap around from 0 to 255 and so on, which should have done it, but the problem was I couldn't figure out then, based on the array, how to tell the iteration code the job had been completed. Whenever I ran it, it did the collapse, then kept going for ages until the array had gone through way more decrements than needed.

After many attempts, I gave up and left the code as it was.

Complicating matters, I thought it would be a good idea yesterday to make it so that when a level ended, the board cleared in a random way. I mean it would choose randomly between several different schemes - Fall Down by Rows, Fall Up by Rows, Fall Left by Rows and Fall Right by Rows.

I may spend some time today seeing how easy that is.

Fall Up by Rows should be easy. I just have to fill the Row Array with the same numbers backwards.

Falling Left and Right will require a new routine that changes the order of the looping, but should otherwise work as well.

And let we believe I'm rearranging deck chairs on the Titanic again, I'm not really. I want the game fully functional before I add a Timed Game option. Because I want the game to operate perfectly before adding code that changes the fundamental way the game is scored, and if I started doing that now, I'd find that things I want to add will require special cases for the two game types, complicating matters beyond my willingness to allow.

So really, before I add the Timed Game option, I'm also going to add the different clearing methods (ie: Clear a random extra Glyph from the board, Clear a random extra color Glyph from the board, Clear any contiguous colored Glyphs from the board, etc.) After which point I will consider the game functionally complete and will add the Timed Option.

And here it is a sunny Sunday, and I may get something done today.

Last night when I was trying to make the FallbyRows more efficient, I made such a mess of it I went back to a previous version of the file. Sensing something wasn't right (because parts of the code was on different pages than before) I continued on and made the FallUpbyRows code, which was a simple change, and even wrote LevelScreen, a routine that picks randomly from the various screen-endings I had available, so each time a level ends, you get a random ending, not the same one each time.

In testing that, I discovered I had blown away my GameBusted code, the part that tells you you Busted the Game if you went over level 255 (and will soon do the same if you go over a maximum score.)

So I spent some time today recovering two pages of code. Not a long task, but once I had done it, I somehow crashed GEOS doing a search in a geoWrite file, blowing away my fix. I had to reboot my Emulator and re-fix the code.

But thankfully that's done now. So I can stash away a backup that has the End of Level screen system working (or as much as can work now, until I put in the FallbyColumns code) and the GameBusted code working.

I spent some time this evening, after burnishing down today's work (checking its solidity, and making a backup) looking at the Glyph themselves, and their colors. I wanted to make sure that no matter how many Glyphs you have on-screen at once (from 3 to 12, although the release game will never have fewer than 5) to make sure that the Glyph distribution and color distribution makes sense.

I found one Glyph - - (which in my version was actually dark blue because I had changed it some time ago) was very plain. So I invented a new Glyph, drawing one out that was a bit Target-like: . I not only swapped the two, but put the new Target lower on the list so you'd see it sooner.

I ended up with the above screen, showing all 12 Glyphs. I may do another pass on this later before I release the game, but for now, I'm happy with it. Happier than I was with how it was this morning.

On the comp.sys.cbm newsgroup today RetroChallenge posted an announcement of the 2009 Retro Challenge, a competition challenging people to enter a retro-computing project, and I figured this one just might be perfect for the job.

Entry window is from July 1 to July 30, and by that time I hope to have this game finished. Or at least releasable. (Is anything ever finished?)

More on this as events unfold.

 

June 12, 2009 - Baby Steps Are Safer

So yesterday I coded the entire row collapse code, and of course it didn't work. So whenever this happens, I break the task into the most basic loops. First, I set up a loop that went through the screen just once. And it just drew one exploding Glyph per row of the Game board.

Eventually I got that working.

But it wasn't scrolling. The 8-byte array (that ranges from 6 to 14) that controls which row is exploding at which frame wasn't being decremented as planned. Each time I ran the routine that decreased each item in the array by one, I ran a routine to display those colors at the top left corner, and it wasn't changing, which means the entire code couldn't run properly, and I couldn't figure out why.

A quick consultation with a 6502 Instruction Set guide showed me that I couldn't dec RowValue,y for some reason, but I needed to. However I found I could dec RowValue,x using the x register instead of the y register. Who knows why...

So I changed that part, switching my use of the y register for x and it just worked. Then I was able to put back the part of the code that checks to see if the RowValue array is all zeroes (which it should be after running through the whole screen 8 times) and stops when it's done. Suddenly it was working.

So then I extended the DrawRow routine to draw 8 Glyphs side-by-side rather than just the one at the left edge of the screen.

The next step once it was all working was to play with the delay timing until it felt right. The sad part is I still don't think it feels right, and I may have to make changes.

My first approach was to type it all in and hope it worked, but as I have oft-discovered, that doesn't work. So cutting it up into each loop and getting each loop right before refining the next seemed to be the wisest approach. And now it's all working correctly.

But I noticed something I didn't like, something the opposite of what I desired for this code. As the Glyph explosion cascades down the rows, the code got slower. This is obvious, since it only draws an exploding Glyph graphic when the number in the array is less than 6. This means in the first iteration, it only draws the top row, leaving the bottom 7 alone. In the next iteration it draws the top two rows, etc. This makes sense, since drawing these graphics is inherently slow. Drawing 8 of them is faster than drawing 16 of them, and I had no special code to stop drawing them at 0, and all rows end up as 0 by the end, and by the end, I'm actually drawing 64 Glyph graphics, even though most of them are blank spaces. So the whole loop inherently gets slower and slower, while I wanted them to speed up and up simulating gravity.

So I put in a variable Delay loop. Each iteration, I reduced the wait loop between screen-draws. It was a delicate balance, because a few times the amount I reduced the loop caused the loop delay count to wrap around from a very low number to a number in the 65-thousands, and I'd get a several-second delay. Once I ironed out the right numbers it still jitters a bit, and while it doesn't get slower as it goes, it doesn't appear to accelerate as desired either. I could tweak the numbers a bit, but I believe to get it to work I have to make the slowest delay too slow for what I want.

The effect is fairly decent. But I'm not yet convinced it was better than clearing the whole board simultaneously.

And after getting that satisfactorialy under my belt I decided to add code for one of the two Rollover contingencies - If we ever reach Level 255. I'm only using a single byte for Level, so I don't want it to roll over from 255 to 0. So NextLevel checks to see if it's already at level 255. If it is, it puts a stop to the game and tells the player the game is over.

I took some time to print "Congrats! You Busted geoGlyph!" and have the OK button there to start a new game. But now it's working.

Next I have to do the same for Score Rollover. And since I can't predict where my score is going to roll over to, I decided to limit the max score to something nice and even like 64,000. Rather than having a more complex score rollover catch routine, I'll just stop it at an even 64,000.

I doubt anyone can ever reach either Rollover, but just in case...

 

June 11, 2009 - Row Cascade - Not Easy!

As a next step, and close to the last aesthetic addition, next to the max-out screens (where you either hit the high score value or the high level) I wanted to work next on getting the Glyphs to collapse row-by-row, rather than by whole screen at once when a level ends.

This is similar in many ways to the Game Over screen which kind of threads through the board exploding kind of in parallel.

This code would store values in an array of 8 bytes, each reprsenting a row of the game board. I would then draw a Glyph exploding at whatever frame we're at for that row until it all collapsed downward smoothly.

Damn.

This is proving very hard.

I coded it up and typed it in, and I swear it made sense on paper. But it just isn't executing correctly.

So I opted to simplify for now. For now I'd go through the screen once only, and draw the graphics only on the left side of the Game Board, just to see if it was working, as a lot of what could be messed up might be in the looping code that draws all 8 Glyphs across on the same row. Since I can't push and pop values I have to reassign my looping variables and restore them when jsring to a new routine.

So suddenly it's working a bit. I can now draw the correct Glyph down the row, but it never decreases the values in the array that govern the collapse.

Now I have to get that array to decrease, and redraw again. Then it's draw 8 Glyphs across instead of just one.

 

June 7, 2009 - Adding A Glyph!

This weekend I added fairly simple code that checks to see if the level is evenly divisible by 16, and if it is, a new Glyph is added, until we get to MAXGLYPHS (12).

The code seems to work. It's very hard to test of course, but I trust it works.

Then I had to create a temporary screen that pops up when a Glyph is added, which shows the new Glyph that was introduced.

I'm thinking of changing the code to draw a Sprite instead, bit-doubled in the X and Y. Now that I'm displaying the Glyph this should be fairly easy, but I will have to prove that.

I also altered the animated logo screen so that there is a delay at the end before the window lights up, then it lights up, and another delay, before starting the game.

I also did some more thinking about exactly what's required to make a timed game. More FreezProcess commands than I had expected, but any time the game itself is not on-screen, I have to FreezProcess CountDown.

 

June 3, 2009 - Touching Up Glyph Swapping

Glyph Swapping was in pretty good shape when I left it yesterday. There was a minor blip, and until I got rid of it I never noticed that there was a delay on the last pixel move of the Glyph that is not needed.

The delay as I slide the Glyphs is based on a curve, so it accelerates and decelerates, rather than smoothly sliding. I do this by calling on a different delay time for each pixel the Glyphs slide, times stored in an array. The last number in that array should have been zero, but wasn't.

Then I set it to zero and saw a worse problem. You can't set the Delay value to 0 because the first thing the Delay routine does is decrement that value, which means it rolls over to $ffff, which means a loooooong delay. So I fixed that.

And now here's a short video of Glyph Swapping as it should be:

 

June 2, 2009 - Plugging Away

Much progress was made today. Yesterday I left off with placing two Glyphs, one in white and one in cyan so I could tell them apart, and be sure I could see them on the screen.

Tonight I did SlideGlyphs, which actually slides the Glyphs during the swap. This is achieved by placing two sprites, which are drawn to match the pixels on the screen in the chosen Glyph areas.

First I had to change the IsNextTo code, code which, during selection, decides if your second selection is next to your first. If not, it chooses the second selection as the new selection, so it is easy to change your mind in this version. This code used to simply return a 1 if your second Glyph choice was next to your first.

But to make SlideGlyphs work I had to change IsNextTo so it instead returned a number based on the direction of the glyph that's next to the first selection.

Using that data, I can choose which direction to slide the two Glyphs.

Here's video I shot of the game using this new SlideGlyph code.

There is a bit of a problem though, as now, when the Glyphs swap, they disappear in a blip. This was intentional, as we disable the sprites once the Swap is complete. This, however, causes the sprites to be removed before Redrawing the screen. This is exacerbated when the swap is invalid and it has to swap back.

This should be a fairly simple fix. Instead of Disabling the sprites at the end of this code, I should disable them during the Select code, after we're sure the Glyphs don't have to be re-swapped.

 

June 1, 2009 - Progress, But Guarded Progress

The next task I have taken on is a bit complicated, but I consider it important - making the Glyph Swap work as an animation, and not a blip. (This will also probably want to tie in to the Animation Option, so if that's turned off, it should not animate, and if it's on, it should obey the Animation Speed.)

But it presents several interesting problems.

First, I have to get the Sprite coordinates from the Index into the Gameboard array. Turns out I already coded this for the HINT function, because the Hint uses the index to place a sprite on-screen. Those two coordinate systems do not relate to each other easily, but I already worked on that, some weeks back.

Now it becomes useful again because my two selected Glyphs are selected by two indices into that array. From those indices, I need to find the Sprite coordinates so I can lay down two sprites over the two selected Glyphs.

That was the easy part.

However, the hard part is to draw those sprites to mimic the Glyphs underneath them.

I thought my first plan was easy, and I thought it would work.

GEOS stores its graphical data as compressed data. Very clever. It takes a lot less time to load up small, compressed graphical data, even if it takes longer to draw it. Using the compaction, I figured that a single 8x8 graphic would not be compressed, but I was wrong, and I found that out.

I originally used that index number to find out what Glyph is there, and then using a lengthy series of IF statements (well, cmp) I found the address of those Glyph graphics already coded, and copied 8 bytes from there to the Sprite buffer before drawing the sprite.

Well, it drew in the right position (well, off by one in each X and Y direction) but drew gibberish. What it was drawing was the compressed data, not the actual graphical data.

My original plan was to just read the pixels right off the screen, since those pixels exist in memory. This way I could just read the Glyph and write it to the sprite. No problem, right? Well, it turns out to be difficult to get the address of those 8 bytes in memory based on your position in the Gameboard Index.

So my next plan was to make a second set of Glyph graphics, stored elsewhere in memory not compressed. The problem with that, besides adding more memory to the game (72 bytes, not much, sure, but lengthy code to determine which one to use) I had the extra problem that if I ever changed the Glyph graphics, I'd have to manually change their representations here too. It is also incredibly inelegant.

So I went back to my original plan - to read the pixels off the screen and transfer them to the sprite. Besides being damned clever (if I get it working) it means I never have to duplicate the Glyph graphical data. Whatever gets drawn on the Glyph space, I can copy that to the sprite.

However, I was not kidding when I said it was hard to convert the Glyph's index in the Gameboard to a memory location on-screen.

I was sure I had it right:

GlyphBase = Screen_Base + ( 40 * Y ) + X

(where GlyphBase is the address I'm trying to find, and Screen_Base is the start of video memory, $A000 or #40960.)

However, when I tried this the Sprite pixels still turned out to be gibberish. So I added some print statements to tell me the GlyphBase, based on the sprite's X and Y coords, and I printed those too.

Turns out I have the X and Y right. However, the formula is not working. Every 8 pixels I drop down vertically, instead of increasing 320 bytes (which is an 8-pixel-tall row of the screen) it is dropping down some 2068 bytes. This is of course wrong, and very bad. Because before I get half-way down my game screen, I'm already rolling over the 65535-byte memory and rolling over. The lower part of the gameboard reports that the GlyphBase is 2038 or some low number.

So obviously the formula is incorrect. And since the C-64's screen memory is done in cards, and not linearly, it's a non-obvious formula.

In fact, as I click on the upper-left Glyph on the board, I'm getting a value far higher than I should. The next row down is, instead of 320 bytes more, 2068 bytes more. The good news is that I am adding X correctly, because the Glyph next to the upper-left-corner is 1 byte more than the one to its left, which is correct.

So now I think I'll succeed once I fix the GlyphBase formula. How? I do not know. But I know I can. It's just going to take some time.

Tonight I re-discovered something - Words and Bytes do not mix!

Using the above formula, I should have gotten accurate indices into the Video memory so I could copy the Glyphs to sprites. But for some reason I was getting crazy numbers.

The only way to fix it was to put in print statements into my program to ensure the numbers I thought I was using were really the ones I was using.

The first numbers I printed, the memory address of the Glyph, and the Sprite's X and Y position printed, and while the X and Y were correct, the final address after calculation was completely wrong.

So I put a print statement (well, PutDecimal) printing out various variables to prove I was right. The first one, the constant number 40, printed correctly.

Then I found that the Sprite's Y coord was printing perfectly. And the X.

Then when I multiplied Y by 40 that came out correctly.

And then when I added the X - That's where it was wrong!

The thing is, for most of the operations I am using words, or two bytes, to represent the number I am calculating. Mostly because GEOS's multiply routine uses two word values to get a third word value. To multiply my Y coordinate by 40, I needed two bytes for 40, and two bytes for the Y coord. Since GEOS's DMult function uses pseudoregisters to store the numbers, I carefully put a 0 in the high byte of the source and the destination pseudoregister before putting the byte-value in the low byte. This was perfect. And printing out these values bore that out.

But when I added the Sprite's X coordinate, I had to use the geoProgrammer macro AddW which adds one word value to another. Stupid me, though, was adding the byte for the Sprite's X coord to the word of the address gotten by multipying Sprite Y by 40.

That is a no-no!

So it was an easy fix. I simply put a trailing 0 byte after my GBX value, so that any time I wanted to access GBY (the Sprite's X coordinate) I could simply access it by GBY for a byte, since that is where the data is stored, but I could also consider it a word because it always has a 0 in the High Byte.

Once I did that, my Glyphs began showing up not only in the right place, but the CopyIt routine that copies the data to the sprite worked perfectly.

Well, almost.

It prints one sprite with the Glyph it's on, but it also prints the second sprite with the same Glyph image, so there's a small problem (not a big one) with the code to ensure it copies the right one each time, and not the same one twice.

And after fixing the rest, I found out that I was simply transferring Sprite 1's X and Y into the routine that draws Sprite 2, so that was an easy fix.

But other than that, this evening of debugging was highly successful.

 

May 30, 2009 - Ennui Has Set In

When a project takes about double the length of time you thought it would, and you's still only seeing a shade of light down the distant tunnel, your enthusiasm can sink a bit.

I'm trying to spend time doing this, but at the same time my daughter's crazy schedule has me picking her up at drama practice around 8:00 or 8:30 some evenings, and it's hard to settle down and code. Worse, it's hard to settle down and figure out why your code is not working.

I fixed a few bugs the last update and that left me with a couple of more major tasks ahead:

To get the Glyphs to smoothly swap, I have to:

    1. Ttake my Selection1 and Selection2 and get their Sprite X,Y coordinates from their index numbers into the Board array.
    2. Draw a sprite based on the graphical data of whatever is in Selection1, and place it at the X,Y coordinates of Selection1.
    3. Draw a sprite based on the graphical data of whatever is in Selection2, and place it at the X,Y coordinates of Selection2.
    4. Blank out the graphical data under them.
    5. Based on position, I have to slide Sprite1 in one direction while sliding Sprite2 in the other for 7 pixels.
    6. Do a Screen Redraw which will redraw the two chosen Glyphs on-screen underneath the sprites.
    7. Remove the sprites. Voila!

I coded up the part that does 1 and 2. And it's not working.

So now I'm poised to spend a week debugging this fairly simple code and figuring out why it doesn't work so I can do 3,4,5,6,7, each of which will likely take a bit of time to debug. Without a working debugger (thanks to what appears to be VICE's problems with the Commodore Restore key) I have to debug by hand, and using print statements on-screen for data. So I have to now print an area of screen that tells me what X,Y coordinates the code is returning.

I know this code should work - I'm using it to successfully place the Selection Cursor and the Hint Sprite. But it's not working for this, and the reasons could be many. I first have to determine if I'm getting the right coordinates. (Print statements) Then I have to determine if I'm actually drawing any sprite data, or just a blank sprite. (Draw a definite sprite and place it. See if it looks right.)

It's at times like this that I really lose enthusiasm for what was supposed to be a fairly small project. The silver lining is that once it's done, this will be a very good program.

From the day I began I estimated finishing this by June. Or hopefully mid-May. It is now almost June, and I have another month of work to do before I can release this, even without a Timed Game option.

I was hoping by June to get started on the iPhone/iPod Touch system and begin working on a project for that platform, but it's now looking like I won't get a chance to go at it until September.

So for now it's back to figuring out why I am not drawing a sprite at the coordinates of Selection1... wish me luck. And energy.

 

May 25, 2009 - I Fixed A Bug And I Liked It!

I had been noticing a strange thing lately. Sometimes, when I finish a level, a new level appears, and two Glyphs swap where my cursor was. It seemed to me that the Glyphs in question were the last two chosen.

So I figured the part of the code that clears the two selections before doing a Match/Collapse sequence was not clearing the selections properly. But that wasn't it. I made sure I was clearing the selections, (which the code indicated I was doing correctly anyway) and it still did it. But only sometimes.

Another good look at the code showed me what a doofus I was being.

In the GSelect code (Glyph Select) I have a condition that will cause a call to NewLevel. But after that line in the code I should have done an RTS but did not.

So in a rare case where the game redraws a new level without finding any hidden matches first, the code falls through and does an extra Swap. This means that two Glyphs on the new board actually swap, meaning I could start the game with a match that is not detected. Theoretically at least. In all the times I saw this bug, I did not see it create an undetected match, but that had to be coincidence, because it was possible.

Anyway, I found the problem and put in an RTS after jsr NewLevel, and that prevents that extra Glyph Swap.

I also flow-charted the code for the Sprite Glyph Swap. This is my next step.

 

May 24, 2009 - Finally Back At It

I've been a bit tired lately, with this damned Bronchitis just taking it out of me. Also, I knew that to fix the problem I was having with the Level screwing up every time I click the X button when I ask to start a new game.

It should go back to the original game screen unchanged. But it didn't.

It was incrementing the Level number. But only once. It was driving me crazy. And the routines that redraw all of the details of the screen were many, and spread throughout several files, and to figure this out I thought I would have to find and print about a dozen routines, which would be a bit of an ordeal.

So I did some testing last night. I coded some changes to display the Level properly. It was then I realized that one of the things that was happening was that I was printing the Level number before incrementing it when I leveled up. So it turned out that my code was always displaying the previous level. And when I go back to the screen I was printing the correct level.

But even after what I thought was a proper fix, it was displaying the level above the real level number.

Long story short, today I changed some code so the Level only got incremented when NewLevel was called. The problem being that NewLevel is actually used in several situations. And some of those are for when the game is in progress, so it does different things, and in some of these cases it was incrementing the Level anyway, even when it shouldn't.

The proper fix was for NewLevel not to increment Level. Now, Level only got incremented when a new level was called, and that calls NewLevel.

So that worked.

The rest of today was to play with the location of the Level and High Score text.

Next up: I think I'm going to rewrite the Explode screen for when we level up.

After that:

So still lots to do.

 

May 17, 2009 - Saving Saved Game Function

At one point I realized that if you had the Auto Save Game turned on, but you were now at the New Game screen, it didn't save correctly. If I Quit the program at the Game Over screen (where the Score is displayed) it forgets to force a NON-saved game, so the game thinks it has a saved game when it doesn't. This was a problem.

Today, I changed the DoQuit code to fix that. Then I added in the Confirmation screen for when you hit the New Game (!) button. And the Quit icon on that screen should still quit the game. It's the only of the general game icons that remains active during the Game Over screen as well as the New Game screen. Because at any point there, you should be able to quit the program properly, saving any game in progress if requeseted to.

This was when I noticed the problem with saving the game state on Quit at the End Game screen was still there. And I figured it had to be something to do with the new additions. But when I played the game, I didn't even access the new additions and it still messed up. So the changes I made yesterday to ensure a game would be saved if required, totally messed it up.

Today I tracked down the problem and redid my DoQuit logic with a flowchart, and I have it functional again.

And the bonus is that the Confirm Screen I added now works perfectly too, from what I can tell. (Knock wood!)

Next up, I have to replace the standard Quit icon in the Options panel with a Done icon like originally planned, because the Quit icon should really only be used to quit the program, not quit that particular window.

Also, I re-did the OK button on the Game Over screen.

I should have knocked wood much much harder. The Confirm screen is not perfect. When I hit the check-mark button to start a new game, the level did not reset, so the next game began at the same level the previous game ended on. Easy fix, and it is now fixed.

However...

For some reason when I hit the X button (saying I do not want to start a new game) it raises the level you're on. Which would be easy to fix. Except that it only does it once. All subsequent times it does not raise the level!

 

May 16, 2009 - Taking Care Of A Few Odds And Ends

Up to now, which has been very convenient for testing purposes, the arrows in the Options Panel that allow you to select Start With X Glyphs has immediately changed the variable NumGlyphs which is used to decide how many Glyphs to choose from when populating the screen with new, random Glyphs. This includes the startup screen, and all subsequent Glyphs brought in after a match/collapse.

But this is not desired behavior for the released game. Rather, that number, which you set in the Options panel, should only take effect when you select New Game and choose which type of game you wish to play, Timed or Regular. (Keep in mind I may not do a Timed game, if it proves to be too difficult.)

With a very few simple changes, I got it working.

    1. Had to change the variable name that is changed by the arrows in the Options panel - NewNumGlyphs instead of NumGlyphs, which the game code uses.
    2. Had to change the code that loads and saves the saved data so that it saves the new variable in the slot preserved for that data.
    3. Had to change the NewGame code to move the value from NewNumGlyphs to NumGlyphs

A fairly simple set of changes, and now it works as intended for release.

Next:

 

May 15, 2009 - Centering a Decimal Value in GEOS - How?

GEOS is a great operating system. Imagine. It was written around the time of the MacIntosh's introduction - and for a chip that had a limited instruction set, on a machine with limited memory and some issues with buss speed and storage speed. It was an amazing feat, written by people who were used to writing software for an Atari 2600, so they knew how to do a lot with little. The word genius comes to mind.

But I found one limitation that bothered me. In the routines to print text, you can left and right-justify text, but there is no automatic centering option. This is fine, as GEOS provides an ability to take a text string and find the width of each letter in the string in the current font and font size, as well as font type (ie: italic, bolt, etc.) These values can be counted up to get the width of any text string, which is important as GEOS fonts are of variable width, another amazing idea for its time.

But the GEOS routine PutDecimal prints a decimal value stored in two bytes (so from 0 to 65535). However, it does not pre-convert it to a text string, as far as I know, so I can't take the width values of the digits to find out how wide it is so I can center it.

I had no idea how to do this.

Most operating systems allow a conversion of a decimal value to a string, at which point I could cycle through adding up the widths. But GEOS has no such direct conversion routine, so this would not work for PutDecimal.

So I figured I would do the following:

X = value at center where I want to place the text
X=X-2 ; most GEOS standard 9-point font digits are 4-5 pixels wide, the 1 is only 3 or so, in bold. To center the first digit, you must subtract once.
i f N > 9 then X=X-3 ; for each extra digit, subtract again. I alternate between 2 and 3 because 5 is the average digit width
if N > 99 then X=X-2
if N > 999 then X=X-3
if N > 9999 then X=X-2
print the decimal at the new X position

Now this is an imperfect system, because it assumes the width of the digits to be consistent, when they're not. But this actually works fairly nicely, with the number centering itself fairly well. I now use this for my printing of the Final Score in the End Game screen.

But a poster on comp.sys.cbm, where I posited the problem and asked for solutions, had an interesting method to get it exactly right. (I may not use it now since this works fairly well, but in future projects where proper centering is required, this just might work:)

While GEOS has no way to measure the width of a decimal that you may want to print, it does keep track of the cursor position after actually printing it. So if I start printing at X, and the width of the value 32981 is, say, 24 pixels, after printing it, the cursor will be at X+24, waiting to print the next character.

Using the displayBuffer flag, which decides whether printing happens in the foreground, background, or both, I could print the value starting at X in the background, and then get the value of the cursor position where the next character is ready to print. The difference would be the exact width of the Decimal value printed. And since this is done in the background, no one sees it. I can then divide that value by 2, subtract it from X and print it in the foreground, and voila! A perfectly-centered decimal value.

I like it! A very smart workaround that might not work in all situations, but would work fine for most.

The result. The the value 1384 is printed in three places here. The one on the left in the Game Over screen is centered using my routine. By design, the other two are not centered.

 

May 14, 2009 - I'm Good At Infinite Loops!

I spent some time last night refining the hand-written code to redo my GameOver screen. As it was originally, the 64 Glyphs would be chosen one-by-one, randomly, and exploded. Of course this means each Glyph has to go through a 5-frame explode sequentially until all 64 Glyphs are done. So that's really 64 Glyphs multiplied by 5 frames or 320 Glyph frames drawn, with a delay to make it look good.

This took time, as my entry for yesterday mentioned.

So my plan was to stagger the explosions so that we actually get one Glyph begin its explosion, and after it draws its first frame, a second Glyph begins its explosion, and so on until all 64 Glyphs have exploded. And since it's staggered, the game should actually draw 64 + 5 Glyph frames drawn, or 69, rather than 320. This happens in much less time, and the result is much more organic.

Of course most of this evening, while I was watching a serendipitous airing of "love, actually", one of my newest favorite movies, I struggled with this code. I got myself into a corner at one point, because while the code would choose a random index, begin the explosion, at the end of every screen redraw it would get a count of how many frames were counting down, and if it's not zero, it tries again. The infinite loop I alluded to was due to the situation that once all Glyphs were actually counting down, there are no more 7s on the board. I inintialize my board with 7s (where there is no BORDER) so I can know it hasn't been chosen yet. Then when I choose it, I set it to 6 which begins its countdown to 0, at which point it is replaced by a BORDER value, taking it out of contention for choice.

Then when the whole board is beginning to count down, it would try again, only to find no unchosen Glyphs, leaving the board hanging with 5 Glyphs in unfinished stages of exploding. Add to that that the Glypsh were not playing the final frame of the explosion, it wasn't working, and I got into an infinite loop.

I figured it out and set myself up a plan for tomorrow night. But then I realized the fix could be coded in just a few minutes, I did so, and imagine my surprise when I saw this:

Not too shabby.

In contrast, here is what it looked like before, when each Glyph fully exploded before going on to the next one:

This one was much slower, and didn't have that organic feel.

I'm glad I took the extra effort to do this, and even more glad that it is now working!

 

May 13, 2009 - It's Fractal

As I quoted on Facebook recently, I knew that once 90% of the project is over, all that's left is the other 90%. Well I learned on the weekend that there is a third 90% hidden behind the second. My friend Sean said, very wisely, "It's fractal". And I saw what he meant. The closer you look, the same it looks. Meaning that no matter how many bugs you fix, there's always the same amount left. And he should know. He spent years working in QA for Turbine.

Anyway, undaunted, I moved on. I coded a "No More Moves" screen this weekend. It randomly chooses a space on the board and explodes that Glyph. Then it chooses another random one, and explodes it. It keeps doing this until all 64 are done. The problem is that to see the explosion, it takes time. And since it all happens sequentially, it takes about a second to explode any 4 Glyphs. So that's about 16 seconds of waiting for it to finish before reporting the score and giving the player the option to play again.

And while it worked just about the first time after typing in the code (a surprise) I decided there is a better way to do it - a more organic way - that won't take nearly as long.

It will still choose a random board square and explode that Glyph, but after it plays one frame of its six-frame explosion, another begins. And this should result in a very organic-looking cascading collapse.

Later, for the New Level screen, I want to do a similar thing, except start at the top and explode the rows, but in an organic, collapsing way. ie: when the top row begins its six-frame explosion, it does one frame, then the next row down begins while the top row plays frame 2 of its explode. And it creeps down-screen until it looks like a wall collapsing from top to bottom. Should be nice.

So anyway, that's the code I'm currently working on. But first, to do it, I needed a routine that displayed a single Glyph, in a single frame of its Explosion sequence, depending on a value on the board. Then I realized instead of coding that again, I already have it in my regular ExplodeGlyphs code, used after a match/clear sequence.

But it required me moving that piece of code out to its own routine instead of living in the middle of a double-nested loop. This way I could call it in my regular ExplodeGlyph routine, as well as my routine to explode them all organically.

So that worked, which was very promising. And now that that piece of code is now an independent routine, I can call it in my special Explode screen routine.

The core of that routine has been coded on paper, waiting for some time for me to type it in.

And then tonight I also fixed a small bug that - bugged me. When you select a new game, the graphics of the board clear, but the color does not. This means it leaves a green, red and blue stripe on the board after it clears to get ready for its game board.

I also logged a bug which Swaps Glyphs on a new level's screen, basically trying to undo the Glyph swap I did to finish out the previous level. Will have to look into that.

And also I created some test graphics to see how I could center a Decimal value in GEOS. There is no string generated when I do PutDecimal, unlike PutString. PutString acts upon a string. If I have a string, I have a way of finding out the length of that string in pixels depending on the current font and text style. But PutDecimal doesn't pre-generate a string, it just seems to print the decimal value as-is, and there is no way to garner its width in pixels.

So I'm going to try the old basic. If it's <10 it's one digit, so I'll move it over a bit. If it's <100, it's two digits, so I move it over a bit less. If it's <1000 it has 3 digits and I move it even less, and the same goes for 4 and 5 digits. It's simple, but should help me center the High Score routinely.

 

May 11, 2009 - Game Over

Tonight I spent a lot of time getting the Game Over screen right. If your score is a High Score, it will print "High Score", otherwise it prints "Your Score".

I also wrote code to gray-out the ? and (!) icons during the Game Over and New Game screens.

I still have to work to center the High Score. This isn't easy as GEOS doesn't let me know the width of a decimal string in a given font. I can do it for a real string, but that's not how it works. I'll have to approximate depending on if it's a multiple of 10, 100, 1000, 10000, and get close. But I'll save that for later.

 

May 10, 2009 - Fixing Some Aggravating Issues

This weekend was glorious, weather-wise. But I love coding on a Sunday when it's nice out. Cleaned up some code here and there that was bugging me.

I created an End-Game screen that randomly explodes Glyphs until they're all gone. During this, I noticed that ExplodeGlyph was too fast during normal operation, so I spent some time trying to figure out why. I think the numbers were just too small. I fixed it by putting in a large number on a static delay. Normally, ExplodeGlyph's delay is variable depending on how many Glyphs are exploding, because it takes more time to draw more Glyphs. The Delay was meant to compensate for that. But it was too fast. Next time I have to put that code back, but keep the numbers much higher.

I was bothered by the button outline for Resume Saved Game. It was using two of the graphics for the Timed Game and No Pressure icons, stacked on top of each other to make it taller. Two problems with this method - one was that when the second graphic printed over the first, it left gaps in the sides, and the second was you could see the second one drawing, causing a yellow line across the screen a split-second before the button is filled with text. So I wrote a routine to draw the button with GraphicsString instead. Much better now. There is still an isuse with the GameBoard screen clearing when you select a button, though.

I also fixed some bugs I noticed during testing on Sunday.

My next tasks:

And that's not bad for one busy weekend.

 

May 8, 2009 - More Fixing

Tonight I recoded the Explode code. This original version cleared the entire GameBoard with EMPTY, and called ExplodeGlyph, which explodes any Emtpy Glyphs. This is used for the normal Glyph explosion after matching. But if I clear the entire board, it explodes them all. The problem is this is cycling 64 graphics, which takes time. I figured my problem with the Delay. We were already not delaying at all, and it was too slow.

So instead of doing 8 rows of 8 graphics, six times (one for each frame of the explosion) I now use a single row of 8 graphics, six times. This allows me to explode the screen after a level faster, with no delay, and it looks pretty good.

I also touched up the Resume Saved Game button, which is actually made up of two buttons stacked on top of each other. But when the BitmapUp puts those up there, it leaves some gaps where the two overlap. So I use i_GraphicsString to fill in those little, wee gaps.

So after doing those things, I cut a new animated GIF video of geoGlyph in progress as of today:

Whaddya think?

 

May 5, 2009 - What Day de Mayo Is It? Cinqo!

Been very tired at night lately, so this is the first time I went at the project after the weekend.

But tonight I had a little energy after watching part of Fringe, reading to my daughter, watching the rest of Fringe, and while the Daily Show and Colbert Report were on, I added the part that saves the Level as well as the score for the game. I thought I could re-purpose one of the save bytes, but it turned out I couldn’t. I thought I had two Level variables stored, but I only had one. I did have two NumGlyphs stored, but those were important. NumGlyphs that you change in Options, and NumGlyphs that the saved game had. Both vital.

Luckily after saving everything else, and eliminating a saved NAME, I had 4 bytes left over that I could store in the fileHeader. I used one of those.

So the work to do Levels wasn’t difficult. I had to create a new variable, initialize it at 0 on startup, and at 1 on NewGame, test it for 255 on every NewLevel (to ensure we don’t roll over) and if it was 255, do GameOver (eventually, I will likely do something special for a roll-over, but in reality no one will ever likely reach level 255 once I remove the option to go below 6 Glyphs.) Increment the Level every NewLevel. Print the Level on the scoreboard. Done.

There’s one issue I’m having, a small one, where my GraphicsString code, after an ESC_PUTSTRING (which switches from graphics to string printing on the fly) is not printing my “Lvl:” text. Should be an easy fix, except I can’t see why it’s not working NOW. Anyway, I had to move the High Score printing down a bit to make room, but I had the room reserved for it anyway.

Then LoadGame loads the Level variable, and SaveGame saves it. Voila. Done.

Then I noticed something on loading a saved game: The Score Bar goes to zero (well, the lowest value on the bar.) So I realized there was no way to figure that out from the score of a saved game, so I had no choice but to save the Score Bar’s Y value if I wanted the Score Bar to reflect its saved state.

Since I still had 3 bytes free in the fileHeader, I used one. It was easy enough to save and load that value, and then do a jsr RefreshBar to redraw the bar at its current height.

Now I’m pretty convinced Load and Save game works except for one outlying issue:

HINT does not work after a load. For some reason, when I load the game data and populate the GameBoard with it, that all works, and the game continues as normal. But HINT doesn’t work. Not sure why. I have a jsr Detect routine that searches the GameBoard in its current state and finds potential matches, makes a list of those, and randomly chooses from that list one hint which is stored for when you hit the HINT button, or AutoHint kicks in.

I’m sure I can fix it.

And while I was up anyway, I thought I’d fix the ExplodeGlyph routine to not be quite so slow. I put in a conditional statement that should be skipping the Delay function when I tell it to (ie: when the WholeScreen is exploding – which happens at the end of a level.) But it still seems to do it at the same speed.

This may be because it’s already as fast as it can be. I already coded EXPDelay (the delay I use to delay the drawing during a normal Glyph explosion – after a match) to reduce the delay the more Glyphs are exploding. This in theory allows the explode speed to remain the same no matter how many Glyphs I’m exploding. That’s because to draw 3 Glyphs takes much less time than drawing 6 or 9, so I reduce the delay for 6 and 9 proportionally, to ensure a roughly similar explode time for all cases.

It could be that by the time we get to 64 Glyphs (the whole screen) we may have reduced the Delay to 0, or no delay.

So to get this to work faster I may have to write my own BitmapUp routine that quickly takes the 8 bytes of each Glyph exploding frame and poke it directly to the screen where it belongs. This may be faster. It may not be. BitmapUp does so much more than just copying graphical data that it should save a lot of time at run-time. But it will be harder to code.

I also played with the idea of using 8 rows of a single graphic that explodes the entire row in one BitmapUp, which should be faster. But it will take up much more code-space memory. Not a tragic thing, but could be wasteful. But then again, adding my own code to draw these faster would take up memory too. Probably an equal amount.

I’ll try that to see. As it is, my current executable Desk Accessory is 14K. And that includes an 8-frame animated title, which I may eliminate if the game continues to grow.

But as of now, Load and Save Game seem to work fine.

I also used 1581disk to copy my work disk to a real 1581 3.5" floppy, and tested it on my real C128, and was delighted to find it all seemed to work fine. So that's good. Even though the computer I bought for the purpose (a used PC) has just died again, twice since I bought it. The power supplies seem to die. No idea why. It's not like I keep it turned on either. I turn it on, use it, and turn it off again. It's being looked at now.

 

May 3, 2009 - It's Easier to Compress than DeCompress

So today I got back to it. I was left with the somewhat difficult task of taking the saved game data which is saved in nybbles, so that 32 bytes can store the entire 64-byte board, not including the board's BORDER spaces; ie: the top row, and the right row. (Really, if you've read all the way through so far, you know that the board is actually 9x9, with a strip at the top and at the right which I find very useful.)

So the code to encode the saved game data skips the first row of the matrix, because it's all BORDER pieces, then if it finds a BORDER piece as it traverses the rest of the array (which is in fact linear) it skips that space. It takes every two data bytes and stores the first one in the high nybble, and the second one in the low nybble. (I take the first value and rotate it four times left, moving all the bits four to the left, and then put it into the same byte as the second value.)

This wasn't terribly hard.

What was a little harder is decoding that data. Now I have to run a nested loop and for each "row", I do the following, four times:

Get the stored byte.
Put it in variable GS1 - temporarily
I perform an AND #%00001111 - which gets the low nybble.
I store that in GS2
I get GS1 again, and rotate it four times right, which moves the high nybble down to the low nybble.
I store that in GS1
Then I put GS1 in Scrn1+9,x - where x is the index into the Game Board array
Then I put GS2 in Scrn1+10,x - the +9 and +10 skips the first row of BORDERS which is not needed in this operation.

However, after doing this four times, I have to skip a cell in the GameBoard due to the BORDER strip, but not skip the SavedGame data, which has no extra BORDER spaces.

So after four times, I inc GSIndex, which is the index on the GameBoard we are incrementing twice normally. So when we get to what should be a BORDER space, we skip GSIndex a third time, and continue on until GSIndex reaches 70, which will fill out the GameBoard.

It took some thinking, but I finally got it working.

The next problem was my test code. I printed out the colors corresponding to the values on the GameBoard to show that my SavedGame space was accurate. The colors feed into a ColorTable to print the actual Glyph colors. I could easily see from this code that I was in fact saving the correct data. The upper and lower nybbles of each byte was printing a foreground and background color on-screen, so I could easily see it was correct.

Then the LoadGame code (outlined above) is run, forcing the SavedGame data back into the GameBoard data every single turn to ensure the GameBoard isn't inappropriately changed by incorrectly-stored game data.

One problem. It seemed the colors were still printing correctly, but the graphical Glyphs themselves were not. At least for the first two Glyphs. The rest seemed to print correctly.

Somehow something in this new code was over-writing my graphical space!

I found out what, and promptly smacked my head repeatedly.

I was storing my Glyphs in G1 and G2 when I was loading the game data.

The problem was that in the Save Game routine, I was storing them in GS1 and GS2. Two completely differently-named variables.

And guess what G1 and G2 were used for? The graphical data for Glyph 1 and Glyph 2.

So each time, I was overwriting the graphical data with the value data for GS1 and GS2, meaning Glyph 1 and Glyph 2 always drew wrong.

But after I realized that, it was a matter of seconds to fix it.

And I am now confident my LoadGame and SaveGame routines work perfectly.

Next step: I have to check to see if I actually saved a game when I quit. I'll do this by doing a check on the Option "Auto-Save Game On Exit" and if it's on, I will save the game data to disk intact. If it is off I will store a #00 in the first SavedGame data byte. Then, on loading the game, it will check that space for #00. If it finds it, it will know no saved game exists. And the user sees two buttons on the start screen instead of three. The third shows up if there is no #00 in the first SavedGame space, which indicates there was a saved game, and it uses that data.

That's the next part of code I have to do. Once that's done, man, I'm pretty close to finished.

I will still have to fix the NumGlyphs option so instead of immediately changing the number of Glyphs available (which will change the number of glyphs available in a currently-running game which is not desirable) so that instead it changes an indirect variable that gets checked when a new game begins only.

After that I have some thinking to do. Will I just call that a game? Will I add rudimentary sound? Will I actually do what I wanted to do - which was to set up various differently-functioning levels, where matches are calculated differently? If so, I have a lot more work to do. I have to have some controlling code keep track of the level sequence, and to do much more testing to ensure each different level with different rules works correctly, and doesn't screw up regular levels.

We'll see about that. That may be a 2.0 game feature. But since I am not really intending on coming back and adding to this project, I should either decide to do it or not to do it. We'll see. It may just be a timing issue. I wanted to release this thing early June, and it's now early May. One month is not much time to do all that I still want to do. And people will have a lot of fun with just the regular level rules.

And I'm no expert on sound, so that may take some time too, even if it's not going to get too complicated.

Whew. It's now late Sunday night, and I've been working on this most of the day. I did take a break, go out shopping, and grabbed some Five Guys fries and a dog, bought a Star Trek Communicator, and went home again, continuing to work on this.

But for the longest time this evening, it almost worked. I put a saved game in the Header file, so that when the game first ran, it would ask if I wanted to Resume a Saved Game. I did. When I did, the screen would be black. But the select code was working, so I could select any two adjacent empty spots, and the entire screen would cascade in afresh. (Actually, it was a nice looking thing - I am now thinking about loading up new screens that way. But there are problems preventing the score from increasing during this. I'd need a NewScreen flag to stop scoring, but that might do it. But not now.)

It took a while, but I soon discovered that the reason it was loading up a blank screen was that I was pulling from the SavedGSpace, but I had not loaded that space with the saved game from the fileHeader+GAME_PLACE, which is where the saved game is loaded on startup. So the SavedGame was all zeros.

And the Option to AutoSave Game on Exit works. If it's not clicked on, it does not save a game. If it is, it saves a game.

So the result for this weekend is - I have Saved Game working. With one minor caveat - no Level is saved yet.

See, my game so far does not keep track of Level, but it has to. So that's my next step. I set up the variable, and I'm saving it with a saved game, but I'm not so far using it.

Next step - At the start of a game, load Level with 0, and then on NewLevel, increment it. Each time a new screen is created, it increments Level. It will need to have a cap so that if it gets through 255 levels, the game must end with a special screen. A similar screen will have to play if I score higher than $ffff, or whatever number that rolls over at.

After that, I have to fix the Option that allows me to change the number of Glyphs to play with. Right now this changes that number directly, which is bad because I can change it during a game. That is bad. I need instead to let those arrows change a temporary value which is called upon every New Game.

Once that's done, I have to ensure that when a game saves, it saves all of the appropriate info - Score, Level, Type of Game (Timed or Regular) and the Game Board.

So I'm quite satisfied so far for this weekend.

 

April 27, 2009 - Save Me!

Spent tonight with the code I wrote to compress the 8x8 game area of the GameBoard into a 32-byte Save Game area. The code requires going through the GameBoard matrix and take two adjacent Glyphs, do a logical shift left four times for one, then adding them together and storing those as two nybbles, or half-bytes, into one byte. It's the only way I could save the game in the meager storage area the Header block has to offer.

So I printed a bunch of blocks at the top of the screen and then used the code to print the color of the values of the high and low halves of each saved byte, to test whether or not it worked.

Of course I don't print the color value of what is in the GameBoard. That is, instead, an index into a color array, which prints a different color from the color table I created for the game.

But I can use those colors as numbers, and then look up the number in my color table, and I found out that - damn - it works.

Then I have that data copied to the fileHeader, and have that fileHeader saved back to disk.

More code proved that upon loading it indeed saved the correct data. This is all good.

Now I have code to save that data when I Quit the game. But if AutoSave is clicked off in the Options, it over-writes a $00 in the first cell of the Saved Game data. This will later indicate no game was saved.

This will be used to determine whether or not, on run, that a saved game exists, and if so, ask the user if he/she wants to continue playing it. Otherwise, if a $00 appears in the first cell, it will act as if no game was saved, and not show the Continue Saved Game option.

Also, coming up, I have to ensure that whenever a game ends, I put a $00 in that cell so that if you quit at that point there will be no game in progress saved. The idea is it will only save a game if I Quit while the AutoSave option is on, and a game is, in fact, in progress.

To do: (Hopefully tomorrow night)

- At the very start of the program, check the first cell in the Saved Game fileHeader area, and if $00 is found, SavedGame=0, so when the New Game comes up, the Resume Saved Game button won't show up. Then the only option is to start a new game.

- Write the other half of the Save Game code - the part that takes those 32 bytes and re-expands it to the 8x8 GameBoard matrix. This happens if $00 is not in the first cell of the Saved Game memory.

- Make sure that when a game ends, a $00 is written to the first cell of the Saved Game Header memory area.

Good progress for one night.

 

April 26, 2009 - Moving Again

Sickness gone (as of Thursday) I feel a lot better. But only on Saturday did I start coding again.

I got option-saving working. Now when you exit the Options panel it saves its options to disk. I removed the extraneous "Save" icon because I couldn't think of a reason not to save the options. Then I replaced the "Done" icon with a standard window close icon.

Fixed it so the greyed-out icons color again when needed.

Clear Score now works. Prints "Score Cleared" when it's finished doing it.

The only option left now is Save Game which is probably what I'm going to tackle next.

 

April 22, 2009 - SICK of being SICK

So I just spent two days on my back being sick, sick, sick. Finally last night I started feeling normal again, and I'm off to work. No progress at all on geoGlyph, even though I had some quick tasks I could have taken care of with two days at home, but I just was too busy being in misery.

 

April 20, 2009 - Admitting Defeat

One of the goals of this project was to save a High Score in the Header block. This includes not just the score itself, but a 6-letter name as well.

Now this is not new to me. I have done this before. In my game, Hazard, I allow the user to input a 6-letter name to store in the Header block.

I copied the code directly to geoGlyph and - it just will not work.

The problems are numerous, and inexplicable.

I played with this for hours today, on my day off. And I have thrown my hands up in defeat.

So for now I will not succeed in allowing a user to save his name when he gets a high score. Hopefully I can save the High Score at least. That part is working in memory, it's just a matter of saving it in the Header block, which should just work.

So after all that, I am moving on. I'm loading the options from the Header, and setting them on load so when you go to the Options panel, the settings will be what were saved. (Well, hopefully this will just set the Defaults, because up to now no settings have actually been saved.)

The options must save the binary status of all the checkboxes, as well as the number of seconds for Auto Hint, and number of Glyphs available, as well as the Anim Speed.

So it's back to it, somewhat defeated, with my expectations just a tad lowered.

 

April 19, 2009 - Making Progress Again

The intense fatigue I've been feeling seems to have abated. I'm back at it, coding at night.

Last night I spent time figuring out how much data I can store in the Header block of the Desk Accessory. There are a number of bytes left to use by the programmer. But there weren't enough for me to do what I wanted to do. I had to store:

This was too much for the user area of the Header block. So I looked elsewhere. Most of the space in the Header had to be there. But there was one field which gives the programmer 20 characters for the programmer's name including trailing 0. But when a string is printed in GEOS, it stops printing after the first 0. This means it doesn't print all 20 characters in this field. It will print up to the first 0. If I use my name "Sean Huxter",0 that uses 12 of the 20 bytes giving me 8 more to use. Using this scheme, I think I still have 2 bytes left that I can use if I feel like it.

When an application loads in GEOS the Header block gets stored in memory in a location labelled fileHeader. GEOS also stores a file sector and track table. The first entry in that table is the address of the Header block of the file.

So at any time I can write to the fileHeader memory space to replace the data there. This means I can store all the game data I want. I can even do fun things like replace the Author's name, change the type of file, etc. But mostly we don't ever want to touch those areas, because they may change the behavior of the program. Like changing it from a Desk Accessory to an Application would have staggering consequences. On the other hand, I'm free to update the program's icon at will. Which gives me a good idea. I'm going to store the Game's top 3x3 glyphs back into the Icon image on exit.

But for now at least I can read the High Score and High Score Name, and I can write new data back if that changes. I haven't actually coded that yet, but that's next.

What I did do was create code that automatically changes the High Score if you get a new one. So far it does not ask for your name, but that's coming soon. Nor does it currently save the High Score back into the header, but that is also coming soon.

I have to change the Game Over code which really only blanks the Game Screen, so it will prompt input name if the score is now the new High Score, and to display "GAME OVER. HIGH SCORE. PLAY AGAIN?" with an OK button. Then it will go back to the New Game screen.

Hopefully I'll get this done this weekend. It's a long weekend, and I intend to spend some of Monday doing this.

In the short term, I intend to write good start-up data to the Header, and have the game check those stats and use them to update the Options panel. For now we'll ignore the saved game feature and concentrate on the other data. Later, we will do the Saved Game data too.

There is still a long way to go on this project, but the majority is really done now.

 

April 16, 2009 - Tired! Sooooo Tired!

For the past few days I have done nothing on geoGlyph, mostly because not long after I get home, I crash. I crash hard. I crash about 8-9:00pm and don't wake up again until about 2:00am or so. Then it's back to sleep so I can get up to go to work.

Tonight is the first time I've had any energy almost all week. So I took advantage of it.

Didn't do anything too momentous, but I did set up the code to display the High Score, and to set a new High Score if one is reached. (No saving of score yet, but that will come later.)

I also fixed a bug where the main screen had a bad pixel in it on the Score Board where the + symbol goes, when you score points.

Hmmm... that doesn't seem like a ton of work, come to think of it.

But at least it's forward movement. I also came up with a few bugs to fix, and started a Bugs page to track the rest of development. We are now getting down to a very countable set of tasks before I can call this a completed game.

 

April 13, 2009 - Happy Easter

Here I was, set to spend most of my Sunday working on geoGlyph (changing the options panel so the Hint delay time can be raised or lowered, and hopefully going on to more) and my computer wouldn't boot up properly. With this new monitor, nothing was showing up, and my Sony VAIO was flashing the words "Sony VAIO" on its LCD panel, with an occasional "HARDDISK" flashing as well. But not booting up. Oh dear. Shut it down, and restarted it a few times. Nothing

Then later I let it go, and it eventually came up. But with no video being displayed on my new monitor I couldn't tell what was going on. On restart it reported a corrupted restore file, and suggested I do a chkdsk. Which I did, but while in Windows, it will only allow a read-only version, which I did anyway. It scheduled a chkdsk on startup, and when I restarted, it did the whole thing again. Now I believe that while I originally thought it was not booting earlier, it was actually doing a scheduled chkdsk, but the new video monitor required compatible video to show me what was going on, and the DOS startup isn't compatible with the monitor's frequency or something. It kept telling me it had no signal, but the computer was obviously doing something.

Anyway, since I haven't backed up the precious data on this thing in a while (well, bits and pieces here and there, but there is a lot on this machine I'd hate to lose) I spent most of the day copying files upstairs to my secondary machine. This meant I couldn't really work on geoGlyph. Which sucked because I had plans. But in a way it was a forced break, for which my family was appreciattive. Called up a friend and invited him over for Easter supper and we all had a great time. Great meal, lovely TV (watched the new Doctor Who: Planet of the Dead) and played a great game called "25 Words Or Less" which my wife and daughter trounced me and my friend in. Man, they're a smokin' team.

My family commented that it was nice to see me not tensed out over this project. Apparently this project, which has consumed a lot of my time and effort since January (and here it is mid-April) that they've been noticing me getting tense and snappy. Of course this project has consumed me. Projects usually do. I am very single-minded once I start a project. Until it's done. But when it's done, it'll be damn-well done well.

So I'm hoping this project is over by June. I'm really getting down now to countable changes and additions I have to make. It's no longer this long, uncertain list. It's actually down to a fairly small number of things left to do before I can release it.

Here's hoping tonight, I can move it forward a bit.

The computer seems fine, but with the disk trouble, it may give up the ghost at any time, but at least I've backed up my most important data. And I'm working on geoGlyph from a Flash drive, so there's not much danger there. I back that up every few days. (Though I should back it up every night.)

Tonight I finally got back to it. I only really took a full day off, but it feels like more.

So I altered the Options panel to include a variable number of seconds for the Auto Hint to appear after each move, from 5 to 60. And it all works. I had to re-initialize and restart the process each time because once you alter the time it takes for the process to time down and trigger, you have to re-initialize, otherwise GEOS doesn't know the time has changed.

So that all works now. Will try to shoot another video as soon as I can, but it's late now, and I'm off to bed.

 

April 11, 2009 - First Time In A While - A Free Weekend

Been very busy on weekends, and this Saturday I intended to get a lot of geoGlyph work done. Over the past few days I planned the next steps, but didn't do any paper coding, or at least not much.

I wanted to achive the following on this weekend:

That would be enough. But I set my sights high this weekend, and wanted to include the following as well:

But it is now 5:22pm on a Saturday and I have little done.

The reason?

Well, I'm changing the Select code a lot here, and that's in the huge Glyph.s source file. I wanted to take the whole GSelect code and move it out to its own file. 8 pages. This was a slow process. And when I did it, nothing assembled. And I can not figure out why.

So I went back to my backup, reversed all of that work, all of which took a few hours to move, assemble, link, and test, only to find out that no matter what I tried would not work. Wasted time.

Then I got back to it and at least now have a handle on getting the cursor to ramp up in color from DkGrey to MidGrey to LtGrey to White, with a delay in between so the user will perceive it. When it's perfected it should be quite nice.

Oh, it never rains but it pours. Yes, it's raining today, and a cold dreary day it is - but it also snowed. In April. I expected it. Not much, but enough to see, and that's too much for me.

But that's not the worst of it. In shuffling a few backup files around I lost some work. When I added the code to fade the cursor up, the Auto Hint showed up immediately, meaning I was adding code to a previous version from before I added the process work I added on the 7th.

Now I had to spend another half-hour finding which file had the Process code working, and then find the screwed up file so I could retrieve the code I just added, copy it to the Text Scrap file, and then copy the Text Scrap file to the right .d81 disk and hope it all worked.

More time wasted. Thank you fate!

Got my act together and moved on. After some effort, I now have the Selection code fading the cursor up from black to white (through DkGrey, MidGrey and Ltgrey) and down again when we select a second Glyph before it does the Glyph swap. And if you re-select (by selecting an invalid next selection) the cursor fades up again in its new position. It's quite nice.

Next up is what I had hoped to achieve first - have a sprite show up for the Show Hint code, rather than color the background white.

But this has its own problems. Once again I have to convert one selection type to another. I have no idea now how often this program is doing that. Moving from one selection system (say, your offset along the GameBoard array, or the offset along the Color Matrix, or the X and Y position of the mouse) to another. This time I have to go from the Game Board offset to an X and Y coordinate for the sprite.

I'd be willing to bet I have this same function happening in more than one place in my code - moving from one particular set of selection coords to another - and yet here I have to do it again, and to be quite honest, it's easier to just do it again than to find it in code and re-use it.

This one takes the position on the GameBoard (because that's how the Hint Glyph is chosen) and convert it to a full-screen X and Y pixel coordinate so I can lay down a sprite.

The forumula seems to be:

X = (Remainder(Offset-9/9) + DA_LEFT + GS_LEFT) * 8
Y= ((Offset-9/9) + DA_TOP + GS_TOP) * 8

So now I have to do another conversion before I can place the Hint cursor. But hey, par for the course, eh?

Well, I got the Hint working. Now a sprite cursor shows up over the Hint Glyph. Once I got that working, I set up a second GEOS Process to make the cursor flash a list of colors. I decided to go with blue. It flashes from Blue, Lt Blue, Cyan, White, Cyan, Lt Blue, Blue.

The effect is not bad.

Now I have to disable the AutoHint Process when I bring up the Options panel. Because right now the Hint will appear if you call up the Options panel. Easy fix, I think. Perhaps not tonight, though, because it's getting late.

I also have to Restart the Process when I do a NewLevel.

Tomorrow I intend to set HintTime using two arrows in the Options panel, like the Anim Speed.

 

April 7, 2009 - It's a Process

After this exhausting weekend I had the New Game screen almost working. It displayed two buttons, Timed Game and No Pressure!, and if I manually set SavedGame to 1, it displayed a third, Resume Saved Game. Yay.

And selecting any button started a new standard game. (Timed games don't exist yet. But they will.)

But I ran into problems with the Options panel. Options, during a game, exit cleanly, and bring you right back to the game as you left it. But before a new game is started, Options didn't know how to take you back properly because a game hadn't started yet. Quitting Options actually set up the screen as if a game was running.

Fixing this meant using an existing flag, GameRunning, and on hitting the Done button in the Options panel, it decided whether to set up the screen for a running game, or for the New Game screen.

Which worked fine, except it would now run the animated logo again because InitScreen does that. So I created a new flag called AnimRun which sets itself right after the animated logo runs the first time, because we don't want it to run again when you InitScreen (unless we manually set AnimRun to 0 at which point it will run the animated logo again if we ever need it to.)

And now Options works fine. Nice and clean.

And I discovered why the New Game panel wouldn't color. Hey, I copied some code directly to work there. But it was a copy error. Instead of using Copy/Paste, I typed it in. And I substituted the GEOS Macro AddVW with AddW. Uh... instead of adding 40 to the current color card location (to drop down a line) I was actually adding the contents of address 40, which was random, essentially, so it wasn't doing it right. Simple mistake. Simple fix. Hard to find.

That done, the next thing I want to do is test Processes in GEOS. Processes will allow automated things to happen on a timer in the background, so I don't have to worry about mannaging it. For example, right now, Auto Hint shows a valid potential match on the Game Board as soon as you make a move. This is not what we eventually want. Eventually we want Auto Hint to wait X seconds before revealing the hint. Ideally between 5 and 10 or so. In fact, I'll be putting that time into the Options Panel so you can choose for yourself, with a default of perhaps 10 seconds.

In an event-driven program like this, there are ways to do this, but the easiest is with GEOS Processes.

One function in the Process control stuff for GEOS is a Sleep function that allows a piece of code to run after X interrupts (1:60th of a second). But I haven't played with GEOS Process control before now. Well, I did, but it was unsuccessful.

So I spent some time this morning setting up a disk with the SamDA program from geoProgrammer so I could play with Processes. I set up a simple process which points to a routine called IncColor that simply incremented the value at COLOR_MATRIX. A process accepts a number (of interrupts) and when that number counts down internally, GEOS triggers the routine specified. So when I assembled and linked the code, every second, that color in the upper left corner incremented, and I rejoiced. Processes worked fine.

Better, the Sleep function doesn't actually require you to set up a process table. Rather, Sleep uses the Process timer code to delay some code from running until the timer counts down to 0.

So using this code, I re-assembled it using the Sleep code. I told the IncColor process to run after 600 interrupts. (10 seconds). When I ran the program, I waited, and voila! 10 seconds later, the color incremented. Once. This use of Sleep is for delaying a one-time execution, and is not in itself a process which is usually intended for repeating timed tasks.

So now, armed with this new knowledge, I should be able to call the AutoHint routine after each turn (if the option is turned on) and have it just show up on-screen X seconds after the move is done, which is exactly what I want.

Will test this more tonight.

And here it is tonight. Colbert Report is on and I'm done for the night.

Tonight I noticed that using the Sleep and a table of Processes at the same time seems to cause a crash. But I realized Sleep isn't the process I need. After having done more tests I discovered that if I set Sleep each time I make a game move, and the Sleep routine waits X seconds before showing me a hint, it would restart that for each move. In essence it stacks up processes waiting to time down. So by the time 30 seconds have passed, if you've done 10 or 15 moves, it will suddenly do 10 or 15 (accordingly) Hint showings, as they all time down.

But I determined that the Process worked better. This way I can RestartProcess at any time I want to hold off the showing of the Hint. Like during the Match/Cascade loop. I can hold off the hint from displaying by Restarting the Process each Match/Cascade collapse, and again when that loop ends. So in essence once a turn completes, it restarts the process and we don't see a hint until X seconds after the move.

I also set it up so that during Options, the process is blocked, and unblocked when the Options panel is over

I also now know (thanks to multiple tests) that if I want to re-inject a new time into the Process table (ie: if we use Options to lengthen or shorten the Hint delay) and reInitialize the table and now the Hint will delay the new time. This must be done in the Options panel. Each time you select a new Time Delay it will InitProcesses, which resets the Processes with the new time. Then on exit of Options it will Unblock the process.

So far this works very well.

Tomorrow - I change the Hint Highlight to use a Sprite instead. And I'm going to try to start a second process that flashes the Hint sprite's color.

Also tomorrow I intend to change the Options panel to include arrows that change the time. I think I'll increment it from 5 seconds to 30 in 5-second increments.

And this means I'll move the Sound option down to the bottom just above the Save/Done icons.

A nice, respectable amount of work done today.

 

 

April 4, 2009 - Taxing Efforts

Got my taxes done today, and it appears after last year's debacle, we still didn't adjust our witholdings enough, and have to pay in about twice what we did last year, and last year was not good.

But to get my mind off that, I spent some time redesigning the UI a bit.

When I say that the game is at the 90/90 stage (the first 90% is done, now all that's left is the other 90%) I mean it.

When you take on a project like this you think "Oh, this will be fairly easy. The game has to do these things, and some of it is quite difficult, but when it's done I'll be satisfied." But what you forget while you're up late at night struggling with code to make the game itself work, you forget all the details.

Like making the selection cursors do nice things. Like doing a Start screen that loads the options and if it finds a saved game, have an icon indicating you can Resume Game. But also you need to have a Timed Game and a Normal game (if I do a timed game, which seems likely).

This requires a fair amount of effort to make it look good. And most of my projects are designed around the visual look as much as the game itself. I'm not just a coder, I'm also an artist.

I still have a mountain of work to do to make this look and play right. I have to allow you to save the game, save the options, save the high score (all of which will be stored in spare space in the Header block of the GEOS file.) You have to load that data, use it to set the options accordingly, then it has to go to a Start Game screen with choice icons.

As the game evolved, some of the original icons have changed thier purpose. For example, recently, the ? button which used to give you a Hint because the Options button. Soon, when I put up the New Game screen, the Play button becomes useless. But it gives me the ability to put back the Info button that I had originally planned. (Info will print one or more screens of information including my web address, copyright info, etc.)

So today I added a new ? button and an Stop button, on the Score board. This is the new Hint button, as well as a Stop Game button. At one point this will be supplemented with a Pause button if it's a timed game. But the Stop button allows you to stop this current game and start afresh.

Currently, the Stop button is the New Game button, because I don't have those buttons working yet.

But you get the idea. Then I'll add sound, and a cool dual-sprite Glyph Swap where I write a sprite with the image of the first Glyph, and a second sprite with the image of the second Glyph, and then place them, and slide them, so they smoothly slide. And if there is no match, they slide back. This should be nice.

Also, Sean Dickinson, a friend and fellow coder, gave me a great idea. When I told him about the ability to save data back to the Header file, he suggested changing the game's icon to reflect the state of the actual game board. Now this is not possible in its entirety because the icon can display a 3x3 Glyph matrix, not the full 8x8. But it's still a great idea, and I will try to do it so it changes the icon to reflect the top left 3x3 state of the board. This is cool. Every time you quit the game (if you have Save Game on Exit selected) it will change the icon to match the upper 3x3 of the game board. I like this idea.

So this weekend, though it's been very busy and continues to be busy tomorrow, (my daughter's Honor Choir took a Gold Medal at MICCA last night, and tries for another medal in Orchestra tomorrow) I intend to get the Start Game screen working (with a Resume Game option even though I don't yet save the game on exit. But I will eventually.

But you see, don't you?

There is always something else to do. The core game itself, though it caused me great pains and effort, was only a tiny portion of the work needed to make this game presentable. And I always make my games presentable. No shoddy look for me.

So here's the latest, showing some of the options in action, and the new buttons. There's still more to put on the Score Board like Level, etc. And eventually, High Score and Name.

Tonight was spent putting the New Game options (including a switch that allows you to Resume Saved Game if one exists. This is a set flag right now, just for testing, but eventually will be set by the fact that there is a game saved.

It was a fair amount of code to get in, so of course I struggled with errors and stuff, but eventually I got it in with one exception - the code to color the Game board (which is a copy of code elsewhere that does exactly the same thing) isn't working, so I left that for the moment.

But for the most part it worked when I was done tonight.

I still have to use the GameRunning variable to determine what happens when you leave Options. Right now if you go to the Options panel before starting a game, it doesn't quite know what to do when you quit Options. That's for tomorrow. But for tonight, I can use it. I can start a new game, and once I do, it all behaves normally.

For a while there it wasn't working.

First, the Resume Saved Game, Timed Game and No Pressure! icons weren't working. Then I realized that my Start code loads up the original Icon Table, which would deactivate thesese icons. Fixed that.

But whenever I clicked on the game board the game restarted. Actually, not every time. Just in certain areas. Then I realized I had the same problem again - calling up the wrong icon table. In this case, when I started the game, I didn't load the gameplay icons, so the New Game icons were still there, though the Game Board redrew over them so you couldn't see them. But they were still clickable.

So naturally when I clicked on the Game board, sometimes it made a match, and sometimes it started a new game. DUH... So I fixed it so the gameplay icons are drawn after you start a new game, restore a new game.

(Note: So far each of the buttons, though they indicate a different thing, just start a fresh game. This will get fixed over time too.

 

April 3, 2009 - Matters of Timing

After having done some thought on the delay issue (which caused a noticeable delay in Glyph dropping between steps - not as noticeable after a horizontal match, but very noticeable during a vertical match - reason why later) I think I've solved it, or at least I've 90% solved it.

My code does this:

Starting at the bottom of the screen, it goes across the row looking for Empty spaces (spaces removed due to a match). For each spot in the row it checks to see if there is an Empty space. If not it simply does a NEXT. This Next, happening at every spot should be lightning fast, and a whole row with no Emtpy spaces should whip by blazingly fast.

If, however, it finds an Empty space, it goes into action pulling the above Glyph down.

But to animate the Glyphs dropping we go through every row 8 times. This 8x loop allows us to draw the Glyph in 8 different positions, sliding down one pixel at a time until it lands where it belongs. Still, 8 times is a lot, no? But if a row has no spaces, it simply does NEXT each time, so we go through the row 8 times even if there is nothing to do on that row. And NEXT is a very quick thing to do.

However, silly me, I put in a delay at the end of every check of that row, so that a falling Glyph will draw smoothly, and not blip down so fast the eye can't see it. And there was the problem, you see...

Even if a row was not an "action" row. (ie: there was no Glyph to drop) it was doing 8 delays, just like it would have if there was a Glyph to drop.

I noticed the problem when a horizontal match at the bottom row dropped immediately but the same horizontal match at the top took almost a second before the Glyph above it dropped. This meant the check routine was slowly creeping up the board (with nothing to do but still doing the delays) until it reached the top row, where it began to drop those Glyphs.

So I determined that I needed a flag, cleared at the beginning of every row check, and turned on if that row contained a Glyph that had to drop. And at the end of that row's check, I check that flag to see if I needed to delay. If there was no "action" on that row, I could skip the delay.

And this really worked.

It still meant I was iterating through the row 8 times, though, even though I knew there was no need. If there is no Glyph to drop, I don't need to check that row 7 more times. Once should be enough.

I also tried to fix that by skipping the rest of the 8x loop, but my first attempt broke things. On the last pass, I do the essential step of actually bringing the Glyph down one space on the game board. And this was breaking. I can still work on a fix, but I came to the conclusion that now, without the delay, 8 times through the row would appear to a human eye to be about the same as one time through the row. Assembler code of tight loops is very fast.

So I think I've essentially fixed it. Now, a horizontal match on the top row begins to fall nearly immediately, just like a bottom-row match. Yay!

Now the reason the delay problem is not noticeable on horizontal matches, but very noticeable on vertical matches is simple. A horizontal match does one pass of the board. Starting at the bottom row it finds a Glyph (row of Glyphs in this case) to drop, and drops it. The next row up is the next one checked, and it drops down those same positioned Glyphs, and this cascade happens all the way up to the top row when new Glyphs drop in.

This all happens in one pass.

However, a vertical match of three has to go through 3 full screen passes. Each time one Glyph drops (or for that matter a row of Glyphs) it's a single pass. So, for example, if we have a 5-high vertical match, we go through five passes like the one we do for horizontal cascades. The horizontal collapse is moving, essentially, one Glyph down. It doesn't matter if it's one or the entire row. It's the same. But a column means you have to go through and drop once per column height. So a vertical match of 3 means you have to undergo three passes of the board. A vertical match of 5 means you have to undergo five passes of the board.

And the kicker is that with each pass causing that unnecessary delay, vertical drops were excruciatingly slow for no proper reason. There was a delay where there shouldn't have been.

I truly hope I have fixed this. And explained it adequately.

One other thing I'm working on is decreasing this delay with each Glyph drop so the whole drop appears to be accelerating, as if with gravity. The snag here is that the code I did for it seemed not to work. Even set to the slowest Anim Speed in Options, the Glyph dropping was happening fast.

I think I may know why, though. I think I was reducing the delay too much each step, because I was underestimating the number of loops that were being performed, so we were dropping the delay down to zero nearly immediately. I have a reasonble fix for this, so hopefully tonight I'll fix that.

This morning I think I figured out how to make geoGlyph a timed game, like the Bejeweled option.

Here are the steps I believe I need to do:

If TimedGame = True:

NewLevel (and StartGame) put the Score Bar at the half-way point (instead of bottom).

appMain is extended to tick off a counter.

If the counter reaches a certain number (basically a delay of X seconds) then the Score Bar will drop one pixel

After the drop it checks to see if it has reached the bottom.

If it has, stop the appMain extension and run Game Over.

I don't think I even need to change the Score code, because it will do what it does now - if Score Bar goes over the top, it starts a new level.

I think that does it. Scoring will raise the bar, time will lower the bar. If it ever reaches bottom, Game Over.

I think I will also penalize a person (by dropping the Score Bar a pixel or so) each time they hit the HINT button. I think that's only fair.

So if all goes well, after I finish the rest of the game, I might be able to add the Timed mode as well, making for a much more complete game. Woot! Go me!

 

April 1, 2009 - Some Issues Being Tackled

As noted on Mar 31, my quick fix for the delay that happens after the last of the Cascade steps caused a minor issue which you can actually see in the animated screen movie below. When a cascade reaches one away from bottom, the bottom-most Glyph pops down, instead of smoothly dropping down. This is because I was checking a variable to see if anything had dropped. But what happened was that during each step for that animation it was doing this and not using the delay. But what I needed was it to not use the delay only on the final drop step.

I'm not entirely sure my fix works perfectly, but it is better than it was this morning, and I will allow my brain to ruminate on it for a while. (No, not marinate.) It may come up with a better solution while I'm thinking about something else. I find my brain does that. It goes off on its own for a while and works on a problem when I don't even know it's doing it. Then pow! The answer appears.

But I also noticed that my scheme to begin a new level after the Score Bar goes over the top was not working as I had intended either. It was doing it as programmed of course... that's what computers do - they do what you tell them, not what you want to do. What it was doing was starting a new level after the Score Bar goes over the top, once the cascades stop for that match loop. However, sometimes the screen that clears to make way for a new level had valid matches on it. And that is disappointing while playing. I know I would feel cheated watching a nice line of five drop down perfectly only to have the screen disappear because a new level was starting.

So I fixed it so that even after the Score Bar goes over the top, the game continues to Match and Cascade until it finds no more matches. Then I check to see if the level is actually over. And then I start a new level.

I also noticed that when my Options panel shows up, I can click on parts of the panel that are not valid icons, and my selection cursor shows up. This was due to a simple error. When the Options panel comes up, I was supposed to set otherPressVector to #0000, which means that only valid icons will react to the mouse. Normally, otherPressVector is set to GSelect which is the selection code. But silly me, I actually set appMain to #0000 instead. appMain is an extension to the main loop, allowing code to happen while GEOS is otherwise waiting for a mouse press or some other event. Fixed that.

Also, I added an accelerated drop. I think. Theoretically it is working, but it's not terribly noticeable. I guess I have to tweak some values. The idea is that when a Glyph falls, it delays between pixels. But my changes mean that each time a Glyph drops, the one above it drops a bit faster, and in a cascade, by the time a tall cascade ends, the top Glyph should be dropping much faster than the lowest one did.

And if this isn't noticeable, I'm going to move the increase so that it happens on each pixel drop.

But it doesn't appear to be working. In fact, after I got what I thought should work in, it paused only between Glyph drops, not during.

Ok, I think I've tracked down the delay problem. And it's going to take a bit of fixing. (I've said that before, only to be wrong, but this time I think I have it.)

My original intent when I do a collapse was to search the current row to see if there are any Glyphs removed by Match. If not, it should simply do nothing, making this process fairly fast, because it ignores spaces that don't need to drop a Glyph.

However, to get the Glyphs to smoothly drop, I check that row 7 times. And after each time I run a Delay. If there is a drop, I print the Glyph that number of pixels up from where it is dropping. This causes a nice smooth animation as it repeats this process 7 times, until the Glyph has been printed 7 times, each time one pixel lower until it lands where it belongs.

But the problem is that it is not doing nothing when it should be doing nothing. It is actually performing that delay even on rows that have no Glyphs to fall.

I noticed the problem because if a horizontal match happened at the top of the GameBoard, it took a long time for anything to drop. However, if the horizontal match is at the bottom row, it dropped immediately. That's because it's doing a slow creep up the board, finding no Glyphs to drop, when instead it should be doing a very fast whip up the board until it finds a valid Glyph to drop.

So now I have to have the code create a flag and clear it on each X pass, and set it if it finds a hole for a Glyph to drop into. This way, when it gets through a whole X row with no holes, it can tell the looping code not to execute the delay. This should cause "no action" rows to go lightning fast.

The other indicator which made this the most likely problem is that when everything drops, it appears to make an extra, slow pass once more before scoring. This makes sense, because to determine that the cascading is all over, I do a last pass on the whole screen and if it finds no Glyphs to drop, it reports back, and the cascading stops. Of course with the way this is now coded, it is doing that and running many, many delays, even on the last pass of the screen when no delays should be happening.

So the upshot is the delay should only happen if an actual Glyph is dropped in the current space. So the code will simply reset at every X row, and set if it finds any Glyph in that row that needs to be dropped. This should result in no delays unless there is a valid Glyph to drop. So a blank pass should now be damned near instantaneous.

Whew. Let's hope this is it. This is another case of my brain figuring it out while I was doing something else.

But now it's getting way too late. I was going to fix the selection code so it displays the Cursor on the second item selected briefly, but as I said, it is now late. I'll do that tomorrow.

 

Mar 31, 2009 - Improved Selection, a Possible New Hint on the Delay Problem, a New Movie, and a Proposed Solution To Leveling Up

Tonight I wrote the code to replace my temporary selection method - inverting the Glyph - with the final method - using an adaptive sprite on the first selected Glyph. An adaptive sprite draws four arrows in each direction from the Glyph, showing possible second selections. If you select an edge, you don't see the arrow that would point off the Game Board. Select a corner piece and you only see two arrows.

Then I ran Camtasia to take another video to show off the options I've been working on.

I do notice that when collapsing, the first tier sometimes happens without using the Delay code. This is due to my rather cursory finding of the delay problem, and fixing it quickly. I think it needs more thought. There is a special case I have to consider, I think. And I think it's just a matter of not checking for GlyphsFallen on the first pass only.

I also have decided to fix the LevelUp code so that when the Score Bar fills up, it doesn't automatically start a new level - rather it sets a flag, then when the Match/Collapse loop is over, it checks that flag and then starts a new level. I felt it was a bit disappointing if the Score Bar goes over the top, and the subsequent collapse causes other matches. I felt a bit cheated that those matches were not detected and scored. So tomorrow I intend to write code to fix this so that a new level only begins when the Score Bar goes over the top and there are no more matches.

 

Mar 29, 2009 - Options are Coming Along Nicely Thank You!

Saturday we went to the Whaling Museum in New Bedford. Had a great day trip. I didn't think about geoGlyph all day - until I got home. Then I started to actually encode the Options.

Mouse Off Between Turns - I started with the easy one - Mouse Off Between Turns. This one was simple. Simply put in a conditional before I jsr MouseOff.

Auto Hints - The next one was a bit harder, but not too bad. Auto Hints. Since I currently lost my Hint button (the ? button is now Options like originally intended) and I still haven't mastered GEOS Processes, I simply made Auto Hint display a hint after every turn. This will change. Soon, I will put this on a timer so it only displays the hint after 10 seconds (or some arbitrary number) if this option is on. GEOS Processes will allow me to set a timer and forget it. Then when the timer counts down, it will show the hint. I could extend the mainLoop but that is not time-dependent. I will have to do my own maintenance. Plus, it's time I figured out Processes. My first attempt to play with them resulted only in crashing. But I'll figure it out. And then I will have to create a new icon for the Game Screen to click to get an immediate hint. This will likely change the Play button to the Hint button. Which means I will likely have to move the Play icon to the Score Board where you can click on it between games. Or perhaps on the GameBoard itself.

Animated Cascades - The third option I coded was not hard either, though it presented some logical problems. Since I wrote the new Collapse code that smoothly animates Glyphs as they collapse, I did not get rid of the original, which was a simple calculate and redraw. But the benefit there was that during the off-screen cascades (when a new level begins - a screen is randomized, but then it goes through a loop of Match/Collapse until there are no more matches, and there is at least one potential match for the player to find - it is done in the background, and not drawn to the screen) I don't want the screen to redraw. The old method did this well, but the new, animated Collapse actually had to have a switch added so it would not draw the graphic if the internal flag, RedrawOn, was set to OFF. And this was kind of already tied up with the old method, since my Debug flag reverted back to the old Collapse method of the simple redraw. I had to go back to flow charts to get this working, but it is now fine.

A funny thing happened during this change, though. I noticed twice after a level was completed and a new one drawn, that there was an undetected and unremoved match on-screen. That should never happen. But twice, three vertical Glyphs matched, and the computer did not detect it, leaving it there for the player to see. After re-coding it again using my flow-chart (originally I did it on the fly hoping I had it right) this problem seemed to go away.

Once those three options were working, work got harder because I needed to bite the bullet and begin using sprites.

The Speed Bar needs an indicator that slides along the red/green stripe. I didn't want to use numbers, and I couldn't use line graphics because the card background and foreground were already being used (red and green), I needed a way to highlight the current setting along the bar. So of course I needed Sprites.

So I added a new file to the set, called G-Sprites.s, in which I use the GEOS routines to create 3 sprites. Since GEOS does not supply commands to color the sprites I simply used the Commodore registers for that. But GEOS conveniently allows us to copy image data to sprite data by using a simple subroutine. This allows me to allow GEOS to worry about where that sprite exists in memory, and I don't have to set my own pointer to that part of the computer's memory. Using sprite 7, the last one available, I created a simple graphic to show where on the graph our value was.

Then I coded the buttons to increase and reduce the Anim Speed.

Using that number, I find the coordinates where the sprite should be, and use another GEOS routine to enable it (show it) and position it.

And it worked.

It allowed me to test the speed of the delays I have currently in-game. And I found that the slower it got, the slower things happened between the falling of Glyphs. This has been a problem for a while now as I suspected there was an extraneous Delay call being made, making the Glyphs pause between rows as a row falls. It stymied me, but I had another look at the code.

When I slowed the Delay down to a crawl, I noticed the space between falls was also slowed down a lot. So I realized that the first step is to remove the delay for the last stage of a Glyph's fall. This is a no duh moment. Of course if you're having a Glyph fall 8 pixels, you only need a delay between the pixels, not at the end. So I put in a conditional to test to see if this is the last pixel the Glyph has to fall, and if so, I do not delay.

Still it delayed between falling between the rows. But not as much.

My suspicion turned to the possibility that between the screen checks (after a Glyph falls 8 pixels) it must be doing an extra scan of the board, and even if it isn't actually drawing any Glyphs falling, it still puts in that delay, so between rows, as a Glyph falls, it is doing an unnecessary delay.

I put in another conditional to not delay if no Glyphs had actually fallen.

Then I could test things. My Speed Bar now has 24 settings from Slow to Fast. The game defaults it at the middle, or 12.

How this works is that my Delay code counts down from a delay number (say, 1000) by DecValue. If DecValue is 1, it takes 1000 iterations to complete the delay. However, as you raise the speed, DecValue raises too, so at the very fastest, DecValue is 24, meaning it subtracts 24 from 1000 each time, meaning it completes the delay in about 40 iterations. Much faster.

Then I found that since the score bar (which smoothly rises as points are added) was speeding up too, since it used Delay, now intrinsically tied to the Anim Speed, and I didn't want that. It got so fast as to be instantaneous, and that wasn't attractive. Since I want players to see the score smoothly rise, not blip upward, I put a new delay in that piece of code that was not affected by the AnimSpeed bar's value.

I was able to put the Sprite up easily enough, and position it, and it all worked. Then I had to add a couple of lines in the code that ends the Options screen and restores the game. These lines turn that Sprite off. And that works too.

So this has been an incredibly productive Sunday for this game. Four options work. Well, Auto Hint partly works, and a fifth, the Start with X Glyphs option works, but currently not the way it should. What it does is reduces or increases the number of Glyphs available to choose from when a new one is added to the board at the top. So if you start with 7 Glyphs, jump to my Options screen, and lower that to 3, whenever a new Glyph appears at the top, it is limited to the first 3 colors. Of course if you restart a game, it will use that number, so will properly create a game starting with X Glyphs as specified.

So to fix that, I have to store the value in a temporary variable until a New Game is started. Then the value is transferred. This will allow you to set Start with X Glyphs to any number, and it won't affect gameplay until a new game is started, which will be as intended once I code that.

And of course there are options that aren't ready to be coded yet:

Sound On - I haven't added any sound yet.

Clear High Score - I'm not tracking High Score yet. Once I do, I will be saving it in the Header (See next point.)

Autosave Game on Exit - This isn't done yet. I will have to re-research how to store this in the Header part of the file, and how to read that in and write it back. To save space, I'm ever-so-cleverly going to cut the current state of the GameBoard up into Nybbles, so I can store the entire 64 valid spaces on the board into 32 bytes. Each byte will store two Glyph values in it.

Save - Saving the state of the options will eventually save to the Header file just like the current state of the game.

Done - Of course Done works. It took some time, but I managed to figure out the proper sequence of events to restore the gamescreen and game state after quitting Options. Mostly it was a matter of calling subroutines that already existed, and are used when a new game or a new level starts.

However, I had to write a piece of code that re-drew the Score Bar as there is no routine that draws it from scratch. The routine that draws it only draws it as updated from its previous level. This wasn't hard.

To complete this evening's work, I simply had to turn off sprite 7 on quitting the Options panel.

Since I was coding sprite data anyway, I opted to also code the Sprites that I am going to use for my Selection, and for Hints. Although I haven't done anything with them yet (that starts tomorrow) the Sprites are designed and loaded with their graphical data. Now I just have to put them to use.

I used an interesting way to create my sprites which should be taking up less room than the 64 bytes of the sprite. Since most of the sprite is filled with 0s, I use ClearRam to fill the temporary sprite area with 0s and then since the sprites are vertically symmetrical, I simply start putting values in the right places in the 64 byte array. Something like:

lda #%11111000
sta TmpSprtDef+4
sta TmpSprtDef+5
...etc...

This allows me to use a minimum number of commands, instead of a loop, to fill the sprite's data. The loop would require 64 bytes per sprite. This method probably uses about 20 per. Well, one of the sprites is complicated enough to maybe be on par. But it's a net win memory-wise.

Which I will be doing next. I will be replacing the code that inverts the chosen Glyph, and instead using the Cursor Sprite.

And I will be using the Cursor sprite too, soon. I designed both Indicators so they don't conflict with each other on-screen. One draws brackets around the corners (Hint) and the other (Cursor) puts arrows on all four sides of the chosen Glyph. Hopefully this works out ok.

Tomorrow I try to add those sprites in lieu of the current highlighting schemes.

Wow, what a productive day.

Tomorrow: Replace my Selection and Hint highlighting with Sprites. Then: Make the new Hint button.

 

Mar 27, 2009 - Options Now Displaying Properly - But What Should They Be?

After the problems of this morning and last night, where I could select the options but the first time always kept them as green checks, I figured out what I was doing wrong and it was one of those classic mistakes. I was checking to see if the Option in question was on, and branching to a routine that displayed it as on. But then I didn't do a jump past that line if it was not on. So in effect, I was displaying them off and on, for each option.

So each time I redrew the Options Icons, they would each turn red and green regardless of the value there. This wasn't happening after clicking each option once because when I click an option, I update each icon individually and I was not making the same mistake in that code. Easy fix.

 

Mar 26, 2009 - Something's Not Quite Right

I have the Options screen finished, and the toggles working. (Some options don't yet change anything, like Anim Speed, Clear High Score, Save and Done. The others toggle their states. (But still do nothing in-game.)

But the interesting thing is, I draw the Options screen, then do a RefreshIcons, which draws in the icon for the current toggled state of each of the On/Off options, putting in a green checkmark or a red X .

But despite the fact that all of the options are set to OFF, they all display as ON. I'm sure I just have something backwards.

Once it does that, I can toggle the states, and the checkmark is replaced by the X and vice versa - except the first time. Again, leading me to believe something's backwards when I start it up. Because when I first click on any option, the green checkmark (which should be a red X) is replaced by - a green checkmark. and once that's happened once, it all seems to work fine, each button toggling perfectly. So something in the initial state is hosed.

Anyway, here's the Options screen as coded currently, with some options toggled on. (Note, there is no indicator yet for the AnimSpeed bar. That will be a sprite, and will come later.

Mar 25, 2009 - Full Steam Ahead

Last night I put in a lot of code to make the Options Panel work. I updated the positioning of all text to make it align to my geoPaint-planned layout. I set all the color cards properly, and while doing all that I fell asleep while coding, and went to bed with broken code, something that usually keeps me up at night.

But I watched a bit of Enter the Dragon which I happened to catch while flipping around. Fell asleep.

This morning I woke up, got Charlotte a Meunster Omelet and when she was off to school I set to fixing what I had half-done last night. By the time 9:00 rolled around I had the Options Panel complete, with icons that displayed, although I'm not 100% sure they're displaying opposite of what they should be.

And I got one of the clickable settings togglable, and proved that that is working.

Tonight - ensure the ticks are coming up correctly (green check-mark for ON, red X for OFF) and toggle the rest.

Then either tonight or soon: A slider indicator for AnimSpeed which is going to have to be a sprite.

Mar 24, 2009 - Been Busy!

Now that the hardest part of coding is done, I've found my obsession level dropping. This is normal for me and projects. It does not mean I'm giving up or slacking.

This weekend we bought our daughter a new desk at IKEA, went to a movie, went out to dinner, spent most of Sunday rearranging her room and constructing the desk, and making it a nice, functional, fun room. Not much time in there for coding, even though I actually did some.

I spent a lot of time laying out the Options screen in geoPaint, which is what I do before laying down an opcode. The result of the planning, in geoPaint:

Not bad. Laid out vertically on color cards so I can color the option ticks, it's a bit cramped, but very workable. Note the various options.

So then I started coding it, and there's a fair amount of code here. The first thing is to clear the game screen and color it. Then each tick, arrow and button is an icon. But the ticks will be blank when first drawn. A second routine will be run that checks the current status of each option and draws the correct tick and color there.

But I'm having troubles. No idea why, but some of my text, though it appears to be coded correctly, is not drawing. And I have been so busy lately, I haven't had the time to debug it.

I just bought a used Mac Laptop so I can begin work on iPod Touch/iPhone applications. Kind of a birthday gift to myself. (Yesterday I reached what I call "an advanced age.")

But I remain focused on this project until I'm happy releasing it.

So here's the first draft of the actual Options screen, as opposed to a carefully laid-out mock-up:

The very fist block of text is missing. No idea why. And the other lines are off their vertical lines. I'll be fixing this. Also, no color has been applied yet. The Options title will be colored, the arrows, the speed bar, all will eventually get color. And when I've fixed the text layout, I'm going to draw in the little frame I planned.

That's my project for this week.

Mar 18, 2009 - Saving Data

In my previous game, Hazard, I allow people to save the high score with a name attached. I do this by writing the header block of the file, which has some unused space after the end of the normally-used header data.

I have to check to see how much actual space there is there, because I just came up with a way to save the game's Options and the game state, if there's enough room:

So if I have 45 bytes free in the header, I can do this. Also, I can increase the name length if there's more room.

More on this as events develop.

 

Mar 17, 2009 - Score!

Now, I score up, though the numbers just appear alone on the score pad. And now, not only the total, but the score for each turn is printed too, and if a cascade happens, those points appear as well, before adding to the score.

And I've been experimenting with score augmentation - in this case, I add the number of cascades as a bonus for each match.

So now, if you match 3 Glyphs, you get 3 points. If it cascades to form another match, those 3 Glyphs will get you 4 points. Next cascade a 3 Glyph match will get you 5, etc.

The way scoring works now, is you get bonuses for longer matches. In fact, you get 3 points for each 3-Glyph sub-match. So in a 4-Glyph match, you can count 2 sub-matches of 3: m; and m.

For a 5-Glyph match, you can find 3 3-Glyph sub-matches:

m, mm and m

So:

- 3 points + number of cascade

- 6 points + number of cascade

- 9 points + number of cascade

m- This gives you 6 points, one for each 3 match. No real bonus for an intersection. May not seem particularly fair, but it's very easy to code, and that's good enough for me.

Also, now, the bar will fill up before a LevelUp if it goes over the top. And it still prints out the points garnered in that turn. This was harder to code than I thought. My original code called NewLevel as soon as the bar went over the top, but that meant it didn't finish displaying the results of the scoring round.

Now, which is as it should be, if the score bar overflows, it fills to the top, the Points print, then the Score prints, then the bar empties and we get a new screen.

Not bad progress for one evening where I wasn't feeling well.

I still have to lay out the Score Panel.

 

Mar 16, 2009 - En Avant!

The school colors of my high school, Grant Collegiate, were Green and Gold. The slogan: En Avant - Forever Forward.

Tonight I changed the DoStart code so it could be subdivided into two routines: One to start the game, and the lower portion of it to start a new level.

My current NewLevel code simply resets the score bar. When the score bar goes over the top, the next turn resets it, and we just continue on.

Tonight I fixed it so that NewLevel now actually clears the current screen, re-randomizes the board, and basically starts a new level, even though nothing has really changed.

Eventually it will select a new level type, either a normal level or a special one (based on a fixed sequence I will come up with).

Right now it explodes out all the Glyphs, but it's a bit jerky. Eventually I'm planning a nicer explosion, row by row, from top to bottom, in a nice, hopefully smooth cascade. But for now, this suits the purpose.

Then it randomizes a new screen and does the simple Redraw.

Then I will write a better Redraw that will bring in a new level nicely.

Then I should code up some Options.

Then I have to code up some special levels, and ensure that calling special levels works fine.

Then it's Info, High Score, Saving High Score, and Sound. I think then I'm basically done.

En Avant!

 

Mar 15, 2009 - Mission Accomplished!

Like Bush announcing "Mission Accomplished" on the deck of an aircraft carrier, I now declare major combat missions officially over for geoGlyph.

And that's a bit like what it feels like. It feels like some major tasks are completed, but the war is far, far from over.

I played with BitmapClip, the code that allows a clipped portion of a graphic to be displayed in GEOS. You specify a number of variables, and do a jsr BitmapClip.

You must pass:

Since I was creating a window of one card by 8 scanlines (an 8x8 area) r11L and r11H was set to 0, because the graphic was printing its full width. The problem I encountered was that I was creating a window of 8x8 pixels, and displaying only a portion of the graphic in the window (while clipping part of it above the window.) At first, only one byte, the last byte in the graphic. The problem is that it tries to continue to draw the rest of the graphic in the lower part of the window. So this printed one byte of gibberish (likely a part of the code used to store the graphic in GEOS format, and then a portion of the next graphic, since they were contiguous in memory.

I drew a test card above the board. The result looked like this: - It displayed the first half of the graphic correctly (I drew it above the screen just to test it)

But it then drew a control byte for the next graphic, and part of the next graphic, because it bled over, drawing the next 4 bytes of memory.

So I spent about three hours writing my own code to write the graphic bytes directly to video memory myself, with an offset that draws only a part of the graphic.

This required something I've never had to do before, but lots of programmers probably have: I had to determine a formula to convert a coordinate in X Cards and Y Scanlines into the video memory of the C64.

Most people who know the 64 know that the 64's video memory is not laid out like a Cartesian grid with an X and a Y coordinate. No, that would be too easy. Instead they decided to zig-zag memory all over the screen. Byte 0 is the top left byte. The next byte is the one directly below it. And so on for 8 bytes. Then the 9th byte is one to the right of the 0th byte. It zigzags like this, rather than being directly accessible like many computers do it.

So I needed to write a formula to get the Video Memory byte from the Card and Scanline coordinate. I was only worried about even card boundaries, so the formula was a bit simpler, but it was still not easy to figure out. Armed with a grid of the screen on paper, I figured out the following:

Byte# = Screen_Base + (ScanY*40) + (CardX*8)

This only works on even card boundaries. But as an exercise in curiosity I wondered how I would find a particular byte if it was NOT on a card boundary... and it turns out it is this:

Byte# = Screen_Base + Q[(ScanY/8)]* 320 + R[(ScanY/8)] + (CardX*8)

I coded up this on paper, then the code to copy a portion of the graphic to this byte. Only then did I realize my original mistake! I would need none of this.

My mistake was that when I was drawing only part of the Glyph in the 8x8 window, I really needed an 8xY window, where Y is the number of bytes (or scanlines) of the Glyph I was drawing. So I not only had to vary the amount of the Glyph being drawn, but vary the size of the window, so it always filled the window to the bottom.

So what I did was not only drop the Glyph down, but expand the window from 1 scanline tall the first time, to 8 scanlines tall at the end, something like this graphic decpits. Picture the brighter turquoise color being the window size, and the dark turquoise color being the entire card being written to.

I tried coding this into the game, and things failed. But to do iterations on testing the code, I had to pull a routine out of the largest source file (to save assembly time - as it's getting over 50 pages in length for just one file!) and put it in the Collapse source file, which is smaller. It sort of belongs there anyway. But to be sure, I had to assemble it to be sure that worked before proceeding. Got that working, and then I played with the code that basically checks to see if we're drawing on the top row of the Game Board, and if so, run BitmapClip instead of BitmapUp, with the extra data needed.

I think I messed up a simple subtraction, because when I fixed it, it all just worked. Lovely!

This was the last bit of complicated code I had to do to get this game working.

And here's how it looks now:

What's left now?

    1. Refining the score display
    2. High Score keeping
    3. High Score saving
    4. Level Up display (explode Glyphs, Display name of next level, bring in new screen undrawn, then implode them in.)
    5. Options panel
    6. Sound (I have some interesting ideas, but sound is my weak area, so there will be much iteration.)
    7. Different Matching Criteria for Special Levels
    8. Adding a Glyph after a full cycle of levels.
    9. Info Screen

So yeah, major combat missions are officially over.

 

Mar 13, 2009 - Life Is Good. Animated Glyph Drop Is In!

I have to say, it was a daunting piece of code, and I couldn't test it in little pieces because the entire flow of the game relied upon this code working in its entirety, and it was a triple-nested loop.

For Rows = 7 to 0 (Start at bottom of screen, and move upward)
- Go across top row and if there's a space, put a random Glyph in the hidden row above
- For Loop = 7 to 0 (Draw each row 8 times, with each glyph drawing Loop pixels above its final resting location)
- - For Columns = 7 to 0 (Do each Glyph location)
- - - If this space is empty, bring the color from the Glyph above down
- - - Draw the graphic at X, Y-Loop (drawing it 7 pixels above, then 6, then 5, and so on until it ends up where it should be)
- - - If this is the last pass (Loop == 0) then bring the Glyph value from above, down one.
- - Next Columns
- Next Loop
- Go across top row and fill it with BORDER values
Next Rows

This was insanely difficult for me. And that's putting it mildly.

But tonight I decided to tackle it, after I came to the revelation that the easiest way to deal with the special case (the top row, which does not just drop down the Glyph above, but actually has to create a new, Random Glyph) by doing it first. By checking the top row for spaces, and putting a new random Glyph above in the special, hidden row, I can suddenly treat all 8 rows identically when I Collapse them all down. All I have to remember is to fill that row with BORDER values again when done. This was always one benefit of having that extra, Border row above the top real row.

So I typed in the necessary code, after massaging the way the loops were done last night, and I'll be damned if it didn't just work.

Well, sort of.

Some things worked, at first. Glyphs drew, smoothly, but sometimes spaces were left in the grid. And when Match explodes the Glyphs, it was exploding the entire top, hidden row, which shouldn't happen.

Then I realized I was forgetting the step of putting BORDER values back on the hidden, border row, after collapsing down one iteration. Once I fixed that, it all worked.

Now the main problem is that I'm drawing the graphic in its entirety, which means that when a new Glyph drops down from the hidden row, it draws it in its entirety, which wipes out part of the game screen's border.

My intent has always been to use the special GEOS code BitmapClip, rather than BitmapUp. BitmapUp draws a rectangle of graphic data. BitmapClip does something better - it draws it within a defined window.

So now I have to change the code so if the Row is 0 (top row), it uses BitmapClip rather than BitmapUp, with the window being the top row, and not the hidden row above. This will prevent the graphic from drawing over the data there. It will look like the Glyph is coming in from under the game screen, which should be excellent.

And if that doesn't work, my original plan, long ago when I came up with this project, was to use a sprite sheild. A sprite which looks just like the top area above the GameScreen, but sprites draw over the screen graphcis (if they're set to) and I could hide all this nastiness using that sprite. But that's a bit of a hack. There is a proper way, and I'll do that.

My original intent was to have this animating graphic section done, and painstakingly debugged by the end of the weekend, but now it's done and it's not even Friday yet. That leaves this weekend to change it so the BitmapClip code fixes the problem with the upper row.

The result so far:

Man, I'm very happy with tonight's work. It looks good! And it feels good!

 

Mar 12, 2009 - Sick, Sick, Sick...

So today I was sick. Second day of a hard head cold, sinus pain, sore throat, but luckily, no lung symptoms.

So while I took today off, I figured I'd type in the code for the Smooth Collapse.

Damn, it's tough. And it's not the kind of code that can go in in stages, making part of it work, then expanding to make more of it work, which is my usual way, (because typing it all in hoping it will just work is a recipe for disaster.)

But since this part of the code is so depended on by other parts, it has to go in working. And that's tough.

I wrestled with it all day, to some success, but so far I don't do the random new Glyph that comes in from the top, so that is messing up the state of the Game Board Array, somehow messing things up and causing an infinite loop.

I struggled with it and fought with it... and tonight I go to bed unsatisfied - because it's not working. I hate leaving code unfinished as I go to bed.

I'm going to toy with this until it's working, and now it's looking like end-of-weekend is a bit optimistic. But you never know.

 

Mar 9, 2009 - Now It Blows Up Good! Real Good!

So I saw Watchmen on Sunday. Friday night was busy, no work on the project, Saturday I spent the entire day in Boston taking my daughter to America's Got Talent auditions (7.5 hours of waiting, 90 seconds of singing) and then to dinner at The Black Rose, and coffee afterwards at Vittorio's in the North End. Great day, but no work on this. Sunday I saw Watchmen which rocked my world.

I did do one small thing on the project, though. I changed the "explosion" animation. The Glyphs no longer just shrink to nothing in 4 frames. Now they kind of rise up and drop over 6 frames. I think it looks better, gives it a more distinct look and feel, and it extends the gravity metaphor. Since the Glyphs drop down, seemingly due to gravity, it makes sense that when they explode upward and then down as well. Looks good.

I did solidify the pseudocode for the gravity drop, though, and will be working on that this week. By week's end I hope to have the Glyphs falling into place nicely, and if I do it right, it should accelerate like gravity too, not just slide at one speed. Still, that will depend a lot on how fast I can draw those graphics. Since the Explode graphics draw very quickly (so much so that I have to put in a fairly large delay in between frames) I am assuming I won't have any difficulty with the cascading, falling Glyphs. But it's still untested.

I hope to shoot another GIF video of my game in operation today, to show off the new explosion animation.

(It's taken me most of this morning to adjust to the time difference, having to get up an hour earlier than normal to get my daughter ready for school.

And in the mean time I ordered a pair of Converse Chucks in Turquoise off Amazon.com.

Today I shot another in-game video. Using Camtasia, which makes an animated GIF from live screen video. It's very clever. Each frame is a transparent GIF frame that uses JUST the difference in the images from the background screen. It's brilliant.

Anyway, here's a video of gameplay now that I've change the Explode graphics to be more of an explosion. Now Glyphs pop up, and drop down as they shrink:

Tonight I'm writing up code to do the smooth collapsing Glyph cascade. But it requires a hard three-tiered nested loop. Very hard for me.

 

Mar 6, 2009 - Nothing to Report

Yep. Here's my report telling you there's nothing to report.

It's been a crazy week, busy, tired... and tonight's the Watchmen movie (probably) and tomorrow I'm in Boston spending a large part of my day in a lineup for "America's Got Talent" because my daughter wants to try out for it.

Sunday will be a lovely day, weather-wise, so I'm thinking I'd rather just give this project a miss for a week and get back to it on Monday. We'll see. Who knows? By the time I write up a Monday update, I may have animated Glyph falling done. But don't count on it.

Ok, so I did spend some time tonight on the game.

I changed the "Flow" code (which shows the score by sliding up the Score Bar, then it shows the two pipes bulging from left to right, and then non-bulging, left to right. It was an easy fix.

Also, I changed the highlight color to white when you ask for a hint. The dark gray color was hard to see. Eventually this might use a sprite. For now, though, this is good.

By the way, this is some video of the game as it looks right now (before I made the flow changes, so rest assured, the part where the line slides across the pipes is much better after tonight's effort.

 

Mar 3, 2009 - Making Up For Snow Day

Work was crazy today, and I won't to into details, but taking a snow day was a bad idea. Had to hustle and didn't get finished until 8:00pm

Top of that I left my Flash drive (with my project on it) at work, so no geoGlyph work for me tonight. Which is fine. Time to take a break.

But that didn't stop me from thinking about it.

This past weekend I was pondering letting the entire screen of gems fall at once during Collapse. Bitmap-wise, it could be done. However, I was forgetting the color cards. If I were to collapse thusly:

Note the space in the bottom row. Now, say I were to collapse the cyan symbol above it. First thing I have to do is drop the cyan color down into the space. This will not be visible yet because the space is blank and has no drawn pixels. Now we animate the downward. Right away, it's going to be in two color card cells at one time. Its own, and the one below. Both of these are cyan now, so it looks perfect. Then, when it's down, the configuration looks like this:

Now we move up one row and when we encounter the space, we drop the down. First, we move the yellow color down into the space, again, invisible now, and then we smoothly animate the yellow one down. And it looks perfect.

Now, assume we do the entire screen at once, rather than doing it row-by-row. The second we drop all the colors down from the above spaces, in the first example, the symbol would turn yellow because the first thing done is the color of the Glyph above moves down one.

So this is only doable row-by-row, if I want to keep the colors looking right, and I do.

Also, I had some time to plan out the special levels, and how I'd denote them. I decided to name each level and put that name over the geoGlyph title during the special rounds, but then put geoGlyph back during regular rounds.

Hopefully I start coding the cascading redraw tonight.

 

Mar 2, 2009 - Snow Day

I'm taking a personal day today. We had about a foot of snow, and roads and conditions in Massachusetts are making driving dangerous, so I'm taking a day off.

During this time, though, I'll be adding to the game.

Next two items to do:

Actually, I decided instead to begin devoting time to the Collapse Redraw, which will loop through each row, or each full screen, not sure yet, 8 times, drawing each Glyph 8 times, from 7 pixels above to where it should be, after a Collapse.

There are some sticky issues, but I think it can be done in a week. Not sure, but I'm hoping to have it done by the end of next weekend.

I'm playing with doing it on a full-screen basis, so all Glyphs fall simultaneously, rather than row-by-row.

But today I spent time getting the Exploding Glyph code working. At least the first stage.

Stage 1 is just drawing a static EMPTY Glyph, which took a while, but I got it working. I was being stupid again, and mis-using variables. I went through the cleared-out array (after a Match, with all the Empty spaces) and did a cmp MT which should compare the Glyph with my variable for an Empty space. However, I forgot that MT is actually the address for the Empty Square graphic. The variable for an Empty Space is actually EMPTY. Once I fixed that, I was off by one vertically. Spaces would clear out below the Glyph I was clearing. So I fixed that.

Now it works.

I also spent some time on some weirdness happening with my Flow routine, which inve rts a vertical line, scrolling across the two Pipes that connect the Game Board to the Score Board. It still isn't perfect, but it's closer.

Now I have to spend some time in geoPaint and make a 4-graphic sequence of a Glyph exploding, keeping in mind these graphics will be used for each Glyph, regardless of what that Glyph looks like. So a decreasing-sized box might be a good idea. Or an outward explosion, but that would feel wrong, considering it would go from a card practically filled, to one that has nothing in it. A bit jarring, I think.

So the shrink way seems to be better.

I drew the shrink graphics. I used two existing Glyphs, and . Those are the first two steps in an explosion. Not in those colors, of course. The color behind the graphic will be whatever the Glyph color was, so you get a sequence, say, like this: If the Glyph is Cyan:

Even if the Glyph is not a filled-out square, the first stage of the explosion looks like it's expanded before shrinking, and that's rather a nice effect.

I also got a bit clever. After a few test runs, it became obvious that the Delay I used after each pass (otherwise it would draw the explosion so fast you wouldn't notice it) caused the redraw to take a lot longer if a lot of Glyphs exploded. So I came up with the clever idea of reducing the delay if there were more Matches. A simple division allowed me to set the delay up so that if there were 3 Matched Glyphs emptied, it takes almost the same amount of time as it does if 20 are removed. The delay between the passes is much shorter if there are 20 Glyphs to remove, because of the extra time it takes to draw the graphics for 20 of these during a redraw, as opposed to if just 3 were removed.

After some problems (as usual) I got it all working, and it really works.

Then I took a few minutes and set up the game so that it only draws the Debug Icons (Loop, Debug, Increase MaxGlyphs, Decrease MaxGlyphs) if you hold down the mouse button as the application starts up and draws its opening screen. Otherwise those icons don't show up. This allows me now to set the Scoreboard area up properly.

I also took a bit of time to fix the Flow code, the section that flicks a line across the two pipes between the Score Bar and the Score Board.

What's next? I'm not sure. I need to let the Collapse Redraw code I pseudocoded earlier today ruminate around my head a bit before actually attempting to insert that code into the Collapse routine.

But I think I figured out how to get the entire screen to drop at once, rather than row-by-row or Glyph-by-Glyph. I opted to do it row-by-row earlier, but now I'm thinking it would all look much nicer if the entire screen just collapsed down at once.

And the pseudocode I wrote takes into account the new, random Glyph entering from the top, and I believe I can do it so the entire screen just flows down properly.

And since, like the Explosion code, only those Glyphs above empty spaces fall, this code should work fairly efficiently. And I can also pull the variable delay trick again, where there is less delay if there are more Glyphs falling. It should work.

I think, though, as more deck-chair rearranging, I may first code the Scoreboard and what it will look like in its final form, and code that up.

 

Mar 1, 2009 - Rearranging Deck Chairs Again - Only This Time It Feels Good

In a previous entry (Jan 25) I talked about rearranging the deck chairs on the Titanic. It was a time when I had several very daunting tasks ahead of me in this project. In an effort to not go insane I instead took care of some aesthetic issues rather than tackling the harder stuff. This is how I work sometimes. And just keeping myself in the project, even if superficially, by doing some aesthetic work, it gives my brain time to prepare and take on the harder tasks. So even though I decided to stop berating myself for the practice, I still feel bad, normally, when rearranging the deck chairs.

But not today.

Many of those daunting tasks are now done, and it was time to do some authoritative deck-chair rearranging. I examined my Glyph-filled screen and decided to play with the colors and which Glyphs get priority. (ie: which ones would be 1-7, and then which would follow, making sure the ones I liked the least showed up later in the list, because people are less likely ever to see those.)

So I opted to play with which ones to use, and which colors to use, so the colors balanced well, and that no two Glyphs with a similar color (like brown and orange, for example) have Glyph symbols too similar. The entire exercise is to make sure the Glyphs are visually different from each other.

Here's a shot of what the screen looks like with all 12 Glyphs present. (Most players should never reach this level.)

I'm confident that I like my choices, and last night I began to pseudocode the Scoring routine.

How will scoring work?

Well, this is not a simple question. Do I want the game to score a point for each Glyph removed? Or do I want it to be more complicated than that? If I go with this scheme, if you get a T-Intersection cleared, you get 5 points. Clearing a T-Intersection should get you something extra. So I thought I'd let the code take care of this.

The Match code looks at the visible screen, and removes Glyphs that are in rows of 3 or more, and copies an Empty square to a second screen. This way, if I clear the same space twice, it still looks like it only cleared it once. Then the second screen gets copied back to the main screen, and the result is a perfect version of the main screen with only the matches missing. However, internally, it may clear the same square more than once - but the user never sees that happening. However, it can be useful for scoring. If, instead, I score a point for eveyr Glyph removed from the main screen - including duplicates - I award bonus points for longer matches, and for intersections.

So I think that's how I'm going to go with it, with the proviso that that may change if the play experience isn't a good one. But I suspect it will be.

Then comes the aesthetics. Sure, I'll add to a Score variable that's zeroed out at the beginning of every game, but I also want the Score Bar to rise. So I wrote pseudocode that would allow that.

What it would do is add Points to Score (where POINTS is the number of points gained after each Match iteration) but I would also add it to ScoreBarY. This is the current Y position of the Score Bar (the little red line to the right of the screen.) In reality, I'll be subtracting, because I'm moving UP the Y scale, which is at 111 at the bottom of the Score Bar, and 48 at the top.

If, when I've subtracted the Points from ScoreBarY the difference is negative (ie: the ScoreBarY is now above the top of the area for the ScoreBar, we set a variable called NewLevel to True. That way, when this scoring round is complete, a new level will start.

But in the mean time the Score Bar will rise up actively (animating in a loop from its old position to its new position) after each Match round.

This should work nicely.

Since I already set up the Score Bar Graphic, here's how this will work.

GEOS provides a foreground screen and a background screen. Printing on the foreground is immediately visible. Printing on the background is invisible, unless I use a GEOS routine to pull that graphic forward to the foreground. For the Score Bar, I print the pattern I came up with on the background screen only. Then, when I animate the Score Bar, I pull that graphic forward line by line. The result should look pretty good.

Then, later, I have another cute trick. I'm going to animate the little pipes between the Game Board and the Score Board. I'm going to make it look like a fluid is going through the pipes. It's like the score is a fluid, and is flowing from the gameboard into the Score Bar (like a thermometer) and then flow over to the Game Board. Should be cute.

But before I begin any of that, I have to shut down my computer. I just bought a USB 2.0 card to install, so all my USB interactions (and I use that a lot on this machine) will go much faster. Even the Iomega external drive is connected through my current, SLOOOOOW USB ports.

See you soon.

Scoring is going fairly well so far. Just putting in the rudimentary basics so far, but at least that's working. I moved the location of the left and right arrows which increase and decrease the number of Glyphs (which will be going away shortly anyway) down a bit to make room for Score, which will now print in blue bold.

Then I have to actually have to start accumulating points, which I will try to code tonight.

Hopefully by the end of tonight I will have some scoring going on. Then it's really a game.

But of course that's not all. I already described what I want to do for scoring, but for now, just the number will do.

So after working most of the day on it, not only do I have score printing, but the Score Bar rises up smoothly after each cascade, and when it reaches the top it resets (which will later be replaced by a Next Level routine) but also I have the two little pipes flashing from left to right indicating the score is flowing from the GameBoard to the Score Bar over to the Score Board where it's finally printed.

That's a hell of a lot of progress for today.

I set out to have the Redraw working by the end of the weekend. I got the Scoring done too, and that's a major bonus!

 

Feb 28, 2009 - geoProgrammer Issues?

This morning I even just used the BitmapUp routine straight-up by filling it with specific data and displaying one of my Glyph graphics. Guess what? It still didn't work. So I started to suspect how geoWrite imports these graphics. I haven't had much trouble with this before, but sometimes if I don't put a carriage return after one of the pasted graphics, it mangles the data somehow.

As a test I ran geoLinker and printed out a symbol table and found that the addresses for all of my Glyphs read the same. And that's just wrong. I'm beginning to think I'm closer to being right in my code than I thought I was, but it's actually geoProgrammer which is at fault.

So I could do one of two things:

I'll let you know where I go from here.

Great. I move a few lines around near the Glyph graphics, and suddenly the file won't assemble without 98 errors. Unknown opcode. That means something got corrupted, and I don't know what. Is it no longer reading the Symbol file? Oh, perhaps it isn't. I opened the GeosSym file and closed it to print the symbols. Perhaps I corrupted it?

Know what I hate?

I hate it when I take a half-hour to type in new code, then spend three days figuring out what I did wrong.

But it's far, far worse when it's nothing I did wrong, but something the program did wrong. What I surmised (see above) about the way geoWrite stored the graphics or how geoProgrammer interpreted them was correct. It was munging up the addresses for the graphics of the Glyphs. So weird was it that when I tried to delete the pasted-in bitmaps, the editor froze. Corrupted data.

So I cleared the entire page, without crash, and re-entered the 13 Glyph graphics (including the empty space).

When I fixed this, and began experimenting again, it worked. I edited the code so that every time a Glyph was updated during Rdrw, it would display the correct Glyph but in the same bottom-right corner of the GameBoard. And that worked. It flipped like crazy as it redrew.

Now I'm going to dive back in and un-comment out the code in the loop that updates the position of the graphic. This should result in the Glyphs displaying in the GameBoard as they should. Still, I won't know that until I try...

More later...

And again, what should work doesn't. Sure, it fills the screen with Glyphs just like I ask... but what else? It's also filling parts of the screen with Empty Glyphs. Parts of the screen I didn't ask to be filled!

I think it's in how I reset the CardX variable, but I'm not sure. It's almost like two routines are filling the screen, because one does the entire GameBoard correctly, and the other is filling in other areas.

Going to have to print out the code pages that deal with this and look through again. During testing I put in various code that should later be removed. Perhaps that's the case here. Perhaps I put in some test code that didnt' work, and that's executing along with the code that does work. Who knows?

In intend to find out.

Remember when I said (just up there a bit) that I somehow messed up the loop? Well, yeah, I did. Here's how:

Here's the code for the nested x,y loop that fills the GameBoard with color: (Note. This worked perfectly, filling the screen from top to bottom)

Rdrw8:
LoadW r10,#COLOR_MATRIX+((DA_TOP+GS_TOP)*40)+DA_LEFT+GS_LEFT
LoadW r2,#Scrn1 + GS_HEIGHT+1
ldx #GS_HEIGHT-1 ; Number of rows in the array
10$: ldy #GS_WIDTH-1 ; Number of columns in array
20$: lda (r2),y ; Get Glyph value at Scrn1,y
sta (r10),y ; and poke it into the Color Memory at the proper location
dey ; y = y -1
bpl 20$ ; If it isn't 0, loop to 20$ which does NEXT Y
AddVW #GS_WIDTH+1,r2 ; Add 9 to r2, which finds the next row of the Scrn1 array
AddVW #40,r10 ; Adds 40 to Screen's Color area, dropping down one row on-screen
dex ; x = x -1
bpl 10$ ; Which basically performs a NEXT X
rts

LoadW and LoadB are geoProgrammer Macros that simply use the accumulator to load word or byte values into memory.

AddVW adds a value to a word, and AddB adds a value to a byte.

So the loop is pretty solid, but now I want to draw Bitmaps as well, using the same loop to go over the same areas on the GameBoard. So now it would not only fill in color, but draw a Bitmap as well in the same spot.

To do this, I need a new pair of coordinates, CardX (for BitmapUp uses an X coordinate in Cards, not pixels.) and ScanY (because BitmapUp uses Y in pixels, or scanlines.) So I just figured, when y (the horizontal index) is decremented, I can simply decrement CardX. When x is decremented, I add 8 to ScanY, dropping down 8 pixels.

So I did this:

Rdrw8:
LoadW r10,#COLOR_MATRIX+((DA_TOP+GS_TOP)*40)+DA_LEFT+GS_LEFT
LoadW r2,#Scrn1 + GS_HEIGHT+1
LoadB ScanY,#48 ; Location of top row scanline Glyph will draw at.
ldx #GS_HEIGHT-1 ; Number of rows in the array
10$: ldy #GS_WIDTH-1 ; Number of columns in array
LoadB CardX,#19 ; Rightmost position on game board
20$: lda (r2),y ; Get Glyph value at Scrn1,y
sta (r10),y ; and poke it into the Color Memory at the proper location
dey ; y = y -1 - move one to the left
dec CardX ; CardX = CardX-1 - or move one to the left
bpl 20$ ; If it isn't 0, loop to 20$ which does NEXT Y
AddVW #GS_WIDTH+1,r2 ; Add 9 to r2, which finds the next row of the Scrn1 array
AddVW #40,r10 ; Adds 40 to Screen's Color area, dropping down one row on-screen
dex ; x = x -1
bpl 10$ ; Which basically performs a NEXT X
rts

The lines in red update the CardX and ScanY position for where the bitmaps are to draw.

See what I did there? I figured, hey, when I dey, I should also dec CardX, which is true. But the problem is, right after dec CardX is a bpl conditional. This basically means that in the first example, I dey and then bpl 10$ which is correct. When I dey, it automatically does a check against 0, and bpl says do something if it's >0.

When I added dec CardX after dey in the second example, I'm in effect, inadvertently switching my looping index variable. Instead of y being my looping variable, I turned CardX into my looping variable, because now, bpl is checking against dec CardX and checking to see if that is 0 instead; and since it starts at #19 each loop, instead of #7, My loop goes on longer than anticipated, trying to draw Glyphs to the edge of the computer's screen. It draws gibberish there too, because it's trying to access Scrn1 array positions that don't even exist. (They exist, but as code, not data, since the loop now goes outside the bounds of Scrn1.)

Once I reversed it, and made sure bpl was working based on dey instead of dec CardX, it worked fine.

'Ray!

 

Feb 27, 2009 - Variable Integrity

This morning I'm frustrated because last night I tried to figure out why my code to display the Glyph graphics messed up. Badly. It's a lengthy bit of code, and it relies on the nested looping structure of the x and y registers in the Rdrw routine. Right now, x and y are initialized to 7 (the width and height of the GameBoard, minus one.) The thing to remember is that x is actually controlling the vertical index, and y the horizontal, due to my use of relative y addressing.

Every loop it now calls ColorGlyph which puts a color value down in the correct location on the GameBoard. The color is pulled from a table, and that all works.

When I then jsr PrintGlyph, which is the routine which obtains a CardX and ScanlineY value from the x and y registers to put a graphic in the correct location, everything messes up. Even if I comment out the part that actually draws the graphic, my colors are getting completely messed up.

Eureka!

This obviously means that my PrintGlyph routine is messing up x and y in some way, even though I thought I was being very careful to push those registers to temporary memory and pop them back afterwards, apparently I was not careful enough. Just running through the data alteration in the routine messes up my Rdrw loop, so the first step in tracking down what's wrong is finding out why my routine is messing with the integrity of the x and y registers.

I store x and y into TmpX and TmpY. These are variables I use at other times as well to store those registers. Perhaps I need to create two new variables.

Sometimes I do things the hard way!

I was using the x and y registers in the Rdrw double-loop to try to derive the CardX and ScanlineY of the location of the Bitmap I have to display. There were problems.

I originally wrote the Rdrw code to work from bottom to top. I changed that for some reason a while back, and so this means my vertical loop is going the wrong way to derive the ScanlineY value properly.

So I decided to try updating CardX and ScanlineY in the loop itself, just like the GameBoard's color card location and the location in the array are altered in that nested loop.

I'm still getting weirdness, but I'm on the right track.

I intend to set it up so that CardX and ScanlineY don't actually change yet, and see if it draws multiple bitmaps at that location for each Glyph on the board. No guarantees, but it should work.

Oh, and one major issue was that while I thought that saving the accumulator, and the x and y registers would preserve the integrity of my variables, so when I did the jsr to BitmapUp it would restore those values and the loop could continue where it left off.

But I forgot that the GEOS pseudoregisters r2 and r10 which was storing the color card location as well as the location in the GameBoard array were not being preserved, and BitmapUp, GEOS's routine for displaying a bitmapped graphic, destroys just about all of the GEOS pseudoregisters. So I had to store those values to temp locations too, and restore them after I was done.

It's still not working, but at least I have an excellent tack to take. This should be working by the end of the weekend.

 

Feb 26, 2009 - Begin Prettification

So for this to be a fully-functional game, all I have to do now is add scoring. But before I do, I want to gauge the speed the game is going to play at when I use the BitmapUp code to display the Glyphs. Up to now, I have not been displaying the Glyphs on redraw, just the color. The color behind a single image of a bunch of circles, just for testing purposes. But to be a final game, it has to print the Glyphs as individual shapes.

Last night I hand-coded part of what I needed to do. This morning I coded it, and it displays gibberish on the screen. And that's after about an hour just fixing what I typed in. geoProgrammer must have more bugs than I'm aware of, because it began complaining I had too many local labels. Which was not true, if you believe the geoProgrammer manual. It says you can have up to 20 local labels, and they must be in the form of one to four digits followed by a $. They complied perfectly. Mine were in the proper form, from 10$ to 130$ (for 13) and then a final one at 200$ for a total of 14.

So I had to recode that with absolute labels, which I shouldn't have had to do.

Then I realized that my Redraw code was using the x register for vertical position in the GameBoard, and the y register for horizontal position in the GameBoard. Backwards. So I fixed that part of the code and reassembled. It is still printing gibberish, but differently.

Tonight I will try to determine if I'm mistaking what x and y are doing, so I may be sure that it is at least passing the correct information to the PrintGlyph function.

 

Feb 25, 2009 - Some Refinement

This morning I quickly wrote the code that displays the correct color of the Glyphs, rather than the natural order of Commodore colors. So instead of 1 being White, 2 being Red and 3 being Cyan, it now displays correctly. 1 is now Green, 2 is now Yellow and 3 is Red, etc.

These values are actually using the four high bits in each color card byte, rather than the low four like I had been using for quick convenience.

That prompted me to change my Hint highlight value from $b0 to $0b, because now the low four bits get set, rather than the high four bits.

 

Feb 24, 2009 - Gettling Closer to a Game

Tonight I did some substantial, though small, changes to the project to turn it into a game, rather than a test environment.

This is great progress for one night.

Next up:

That should give me enough to do for the rest of the week and the weekend.

Feb 23, 2009 - Graphical Refinement

For the project to this stage, I had designed the screen with testing in mind. Today I spent some time thinking about the final game screen. I liked what I had done with geoMimic, which has an industrial machine-like look to the game board.

The corner bolts and deep drop shadow have become a signature of my games. I don't think I used it every time, but I'm trying. The new geoGlyph screen looks like this. I added the mechanical pipes between the Score Bar and the Score Display window, and colored them green and red, to correspond with the color of the Score Bar.

This is how it should look during play. Though it's still not certain exactly what will go in the light green screen. Not just the level number, but a name for the specialty levels may appear there. Also, options will go in that window before playing. Also, the High Score will be displayed there at some point too. The final icons have not yet been decided either. The ? icon was to be an INFO screen, but may double as the HINT feature.

I created the score bar last night too. I didn't like just a green box creeping up a red background. I thought it looked too plain. So I played with ideas of what to put in the column to make it look a bit more interesting. I opted to try the gradated pattern I created for geoComix and The Runner. For now it looks good. Unless I come up with another, more interesting concept, like something machine-like. Perhaps a circuit board? For now this is it.

My next actual coding task is either to make the game display the actual Glyphs in their actual colors (as seen above, rather than the colored circles in screenshots from here down) or perhaps adding an actual scoring function, along with creeping the Score Bar upward.

I still haven't decided which Glyph graphics to use, or their colors. But for now...

 

Feb 22, 2009 - Highlighting The Problems

When I finally thought for the third time I had nailed Match Detection, my skeptical mind sprang to the front, saying "Dude, you thought you had it twice before, what makes you think you're right this time?"

So I contacted a guy who volunteered to do some testing for me. Having a second eye on the task would convince me I have this right. Because if I don't, it's a broken game. I can't have the game end because the code thinks there is no possible match available, nor can I have the game continue without a possible match.

At the time the code spewed two numbers, one for the total number of matches the code found, and the second being a randomly-chosen instance from that list. The second number represented the linear position in the GameBoard array. But this required counting in the array to be sure the position it read out was the right Glyph, and that's tedious.

So I opted to write the Hint feature including a highlighting code, which pops a color in the background of the Glyph, so any testers could see the Glyph referred to, rather than having to count. (This feature will later be used to show players a Hint, either by clicking a button, or by waiting long enough without making a move.)

Now this seems to be the pertinent point of this whole project - coding this thing is like pulling teeth, and I'm not sure I have many teeth left.

This game currently uses two highlighting methods. The first is used in the Selection code, which finds an X and Y coordinate in the GameBoard, and uses those values to highlight the two chosen Glyphs. The second was a bit harder to do. I had to take the linear value of the array, so for example, the result may be 56. How does that translate to a two-dimensional position so I can highlight the Glyph found in the Detection code?

The forumula was not difficult, but it required a division, which is something I have never coded in Assembler. Luckily we have GEOS to help. It has a number of useful mathematical functions to call on. And that caused one of my problems.

The formula was: COLOR_MATRIX + (40*DA_TOP) + DA_LEFT + GS_LEFT + (40*PossChosen/9) + (Remainder(PossChosen/9)

The first part of the formula (in caps) is a constant, interpreted by the Assembler from a number of constants already set up, and the 40* in there is handled by the Assembler, so that's not a problem. However, the second 40* has to be done in real-time in Assembler, as does the /9.

To multiply something by 40, you can add binary multiples, because binary multiples are fast in Assembler. To multiply something by 2, you just do a, ASL, (Arithmatic Shift Left) which shifts the bits in the byte to the left, effectively multiplying by 2. To get to 40, however, you can only multiply by 32. And to get 40* you can then add a multiple of 8. But GEOS also provides a multiplication routine, and while it may be a tad slower, it's fast enough for my purposes, so I used it.

But division is a harder task. GEOS to the rescue again. Ddiv, a GEOS routine, finds the Quotient and Remainder of a two-byte division operation. Using those, the above formula can find the screen color location for the chosen Glyph and I can then highlight it.

The problem was that to find out if each step was correct, I had to print out a decimal value of my results, step by step, so I could determine where I was going wrong when it all inevitably failed to highlight anything.

The thing is, GEOS's routine to print a decimal value destroys the contents of all the pseudoregisters, and my code used one of those pseudoregisters to keep track of my location on the COLOR_MATRIX to highlight. It took a long time to finally figure out that I was setting that pseudoregister before calling PutDecimal, which was destroying that pseudoregister.

So like I have said before, and if I haven't, it needs to be said: Even tiny, simple things can take a long time in Assembler, things that in, say, BASIC, would have taken minutes, can take days (working as I work, when I can.)

But right now, my highlighting code works, and the Detection code can finally be tested without a lot of frustrating counting.

 

Feb 19, 2009 - I Think I've Nailed Match Detection

Last night I coded all of the Match Detection and plugged it in. I tested it a bit, and found that at times, when it reported 0 possible matches (ie: game over) I could see a match on-screen. After some testing, I discovered the problem was in the left and right move match detection.

Each time the pattern was the same, but inverted.

m&m

 

So tonight I was tired, and didn't get any coding time until I woke up at 2:00 restless and not tired. I had a quick glance at the code and determined that I was dead-ending one condition, which was exactly the condition I was getting onscreen. ie: I was doing a NEXT before testing this one situation, meaning it skipped this particular match configuration.

Two quick line deletions and it was working.

So now I may ask one or two people to test this for me, if they have time, with the intent of reporting any false reports. If the code returns a 0 possible matches, and one is visible on-screen, I have a problem. Similarly, if the code returns >0 and no matches are visible, I have a problem.

Right now I'm confident I don't have a problem, but that's the usual situation when testing for bugs.

I now go back to bed, confident and hopeful that I can move on.

 

Feb 18, 2009 - Much Better Match Detection

Well, using Lars's idea below, I was able to code the detection faster and eaiser, but now I realized that my Success code, code I call when a potential match is detected, needs to do more than just pick the first one it finds. This will almost always find matches in the low right of the screen, and that's not quite what I'm looking for.

But before I continue doing this I have to get all 8 patterns successfully coded. Right now I have 6 of the 8 coded, and I'm testing 5 and 6, the up and down linear checks:

Checks 7 and 8 require specialized looping code because the array is really one-dimensional, not two-dimensional, so it's harder to do part of a row, but that's essential, otherwise the left and right checks may bleed over the right side into the left side. I have to prevent that.

But that shouldn't take too long, and when this is over, I have to update the Success code to store each success into an array, rather than just picking the last one found. Then a random number will select from those if HINT is requested or required (after a pause.)

To continue the game, I really only need to know that #Possibles != 0 after each turn, or else the game has to end.

We're getting there.

So I spent some more time tonight on linear detection, and found a way to do it accurately without having to cut my loop up into part of each line. Now, while this would mean checking fewer spaces, it is also much more complicated, and I came up with an alternative way.

Up to now I simply check the screen at index x, comparing the contents at x with the contents of offsets of x. But since I can't cross the GameBoard side boundaries, (which are all filled with #BORDER), I came up with the idea of checking the contents at the offsets of x before comparing them with the Glyph at x. This means that as I approach a side border, it will find that border edge during checking, which my other directions do not have to worry about.

So within an hour I had the remaining checks done and working.

The result: I hereby declare my Detect code works!

Now I still have to code Success to put all detection results into an array, rather than just logging the last pre-match found, so I can randomly choose from them whenever a player asks for a HINT or when the game has gone on long enough without a match that a HINT is forced upon the player (I have to make an option for that, by the way.)

Ok, so I was sitting here watching TV, and I know I should be in bed, it is after 1:30am after all, but I decided to code Success to fill out an array of Possibles, and got that working. Then I got it to randomly print out one of those items, which it does.

So - complete game, no?

I wish. Twice, I found that when Detect came back empty, I could clearly see a possible match on the GameBoard. So there's something wrong here. What it is I don't know, but I will work to track it down with printouts of the GameBoard, and my code, so I can trace the problem.

I have to revert the Success/PutPossibles code so it doesn't build the array, or randomly print from it, but instead does what it used to do, so I can test to see if it ever returns a 0 Detections, and shows a clear possible match. If it doesn't, then the problem is probably in the reporting code, which prints Possibles.

 

Feb 17, 2009 - Better Match Detection

After being somewhat frustrated all weekend with code that I thought should work, I posted a message to the comp.sys.cbm group telling them my problem, and asking what I was missing.

Apparently, you must Set the Carry Flag (SEC) before doing an SBC (Subtract with Carry) operation.

But one helpful guy gave me a much more elegant solution, where I don't change the x index at all. Instead, I change the base address I'm checking against.

So I do this:

lda Scrn1,x
cmp Scrn1-9,x
beq WHEREVER

So tonight, I got three of the four first patterns done, with the fourth causing some mysterious difficulty, yet it seems to be very similar. Still, having three directions work in about a tenth of the lines of code previously required, I'm quite happy! Thanks, Lars!

But as I have a houseful of teenaged girls on a sleepover, four feet from my ears as I try to code, I realize that there's not much coding going to happen tonight. Hopefully, tomorrow, I'll get the first four patterns working, and I can put it through many, many tests. I can even run the first two (up and down) linear checks too, since they don't require special looping that will only do part of each array line.

My goal by the end of the weekend coming is to have all 8 match routines working, and hopefully putting a Detect in the startup sequence, so it gets a hint right out of the gate.

 

Feb 16, 2009 - More on Match Detection

Sigh. Why do so many of these things begin with "Sigh"?

Again, some assembler code that should work isn't, and I have no idea why despite some experience in this area. My loop through the GameBoard tried to check for a BORDER spot, and do a NEXT before it did any testing. However, for some reason when I did this, it messed up my indexing.

But if, instead, I stopped my check before two rows from the top, it all worked.

I mean I shouldn't complain. My testing code for the up direction now works, or at least it appears to after much testing. (Will have to do more.) and so I implemented the down direction check, and that, too, now appears to work.

Before moving on to the sideways ones, I'm going to do the linear ones in the up and down directions. Doing the linear ones in the left and right directions may require a different looping system, so that may take longer, since I have to do part of a line, for the entire array. This works easier for up and down because it only requires I go through part of the full array, leaving off part of the end or beginning. Leaving off part of each line requires a dual indexing, which I can do, but will take some thought.

This is the decision tree I'm checking against:

 

Feb 15, 2009 - Match Detection is Going Well, Sort Of

I spent some time tonight working on my code for Match Detection.

The first problem was just getting the damned thing to assemble. I was having all sorts of difficulties with assembling, and then linking, until I realized that the assembler directives may have been wrong for my first file. It differed from all the subsequent files which also get linked, and when I changed that it seemed to work better. It was still not functional code, though.

First, of course, before writing all of the checks, I am just testing checks for any Glyph that can make a match if it moves up. The other checks will be written after I prove this one works 100%.

After a few hand-traces, I figured out a few issues, some of which were causing crashes, or infinite loops. I kept massaging it, getting the code to print the X Index after completing a Detect check. Often I ended up with 17, which doesn't make much sense, considering the code loops until X is 8, which is obviously not 17.

Playing with it, I noticed a good number showing up, and after looking at the resulting screen, sure enough, it appears to work.

However, it's still not 100%. Sometimes, the index ends at 79, which is the last one in the array, and it is clearly not able to be moved up to make a match, so something is wrong with my code, and I still have to work out what. Once I do, I can write the other checks.

Then, I will modularize the checks, so the loop itself just does a jsr to the check module for that direction, rather than having a long, long string of code.

Still, I'm confident about tonight's work. Getting so many positive results that are confirmable is a good thing. Now I just have to track down why a screen with no matches ends at 17, and why sometimes I get 79.

 

Feb 14, 2009 - We All Need A Break For Valentine's Day!

 

Feb 13, 2009 - Time and Match Detection

So I've been so tired in the evenings lately that I barely get time to do anything with geoGlyph. I did some hand-written code in the evening to start the Detect code, coding the first three possible match patterns. Then I read to my daughter, and for the first time in several nights, I felt I had some energy. It was gone by the time I had finished reading, actually falling asleep while reading. Then that was it for the night. I laid down and was out like a light. This is a pattern over the past week. Perhaps I'm fighting one of the various viruses my family has been attacked by.

Regardless, I spent some time this morning typing in that hand-written code, and now three of my code files are causing errors when I Link the files. Note: Two of those files I did not change at all. I added code to the Match.s file is all I did.

No time this morning to debug what I did so I figured I'd just write up a dev diary entry and go to work. Will work on this this weekend. I vowed by the end of last weekend I would have selection working. I almost made it, figuring most of it out, with just weird register activity messing me up. Changing to the x register from the accumulator worked, and I still don't know why. Regardless, now the code works perfectly, and I have most of an actual game.

So this weekend I vow to get Detection working. Once I get the first pass working (3 of the 4 matches that can be made by moving a given Glyph up one) and once I'm confident it's working, I'll put in the other checks, which is basically a copy of the first, in different directions. Shouldn't be too bad once the first one is solid. Then I have to put in the linear matches, which will require different looping functions (since I'll only be looping half the array each time).

And once that's working, I really do have a working game, which will end if there are no more possible matches. The one thing missing then would be scoring, which I will then do, and should be simple, and just requires me to consider my scoring philosophy:

Should I:

 

Feb 12, 2009 - Match Detection Planning

Much of yesterday and today's work on this project had to do with planning the code for Possible Match Detection, a step necessary after every player move to determine whether or not there is another valid move. If not, game over.

So I determined that there are 16 different patterns that will determine whether there is a match for any given Glyph on the board. Four in each direction. Originally, I compared the patterns, and determined that for checking each Glyph, I could eliminate certain copies. But since what I really want to do is check not every Glyph for all patterns, but what I really want to do is check the patterns for each Glyph that is the one that must be moved to make the match.

This allows me to then highlight the movable Glyph for the player if a hint is requested or warranted. (After a certain delay, a hint will automatically highlight).

And since each pattern requires two checks, some of which are common among the sets, I will be writing a series of decision trees. It should go something like this:

For the current Glyph, if the Glyph to the upper right matches, it could mean one of two different matches, so the next if statement checks one of them. If it fails, it checks the other. This should work. I wish there was a quick way to repeat this for each of the four directions, but sadly, as far as I can determine, it all has to be brute-forced, in a long routine of if statements.

And for four of the matches, I can run all of the matches on each Glyph on the board in one long loop through the array. (Then four more loops have to be run, one for each of the linear match possibilities: Each of these only have to check a smaller part of the array.)

But the it occurs to me that an individual loop through the array for each condition should take equally as long, but there are actually savings to be made by doing a single loop of the array for each condition because some patterns don't require testing the top row, the bottom row, the left column and the right column, so I might gain some speed by doing it this way.

So I have to loop through the array 8 times, rather than once, doing 8 checks.

The bad news: If the only potential match on the board is the last Glyph checked, in the last pattern checked, it runs through the maximum amount of code, taking the maximum amount of time.

The good news: It only has to find one of any possible matches on the board to know the game can continue, so the likelihood of that being the worst case is small.

So now, the next time I get some coding time, I have to create the long decision tree that checks every possibility.

The plan of attack, though, is to pick the first set of patterns and do that, then test it, looking for only those patterns. I'll highlight any Glyphs that can be moved to make a match, which will show me the code is working.

Then I'll add the second pattern, and test again, continuing this until all 8 pattern passes match.

And these are the possible matches I could think of. The first three columns can be done on all the Glyphs because the first test is only one cell away, which works on my GameBoard thanks to the one row and column buffer I put there. It will never test across one side of the board, wrapping to the other.

However, the last column, the linear match possibility, must be run as separate passes, and it only needs to check four rows or columns of the board, since these patterns only work if there is room for four more Glyphs. So each of these will be done in separate loops that include only certain board rows or columns, which differ for each direction.

-
-
-

Yeah, good luck coding this in an evening.

 

Feb 10, 2009 - So Why Is This Working???

After beating my head against this wall here to my left for what felt like days, decided to put some Print code in the IsNextTo checking code. This confirmed to me that my Offset0 and Offset1 (the Offsets derived from my two selections) are one apart when they're to the left or right of each other. So why the heck isn't my code working? It was pretty simple code.

lda Off0
sbc #1 ; This checks one side. To check the other, I use adc #1 - Note this works when using #9 instead of #1 to check vertically.
cmp Off1
beq 100$ - This basically says a=Off0, a=a-1, is a = Off1? 100$ sets NextTo to TRUE and returns.

When doing this, one side worked, and the other was off by 1. It would only return TRUE if I was selecting the Glyph two away to the left, but one away on the right. Why?

Then it hit me... the accumulator is necessary for the vertical checking, because I have to add 9 and subtract 9, and that code was working. No need to mess with it.

But for adding and subtracting 1, I could just try using the X register instead. It was a stretch, since it should not have behaved any differently. So I wrote this code:

ldx Off0
dex ; (and inx for the other side's check) - Note: In the above code, I also tried dec a and inc a, and it also failed.
cpx Off1
beq 100$

Guess what? Suddenly I have a 100% functional, playable game. Oh sure, there's no score, no routine to detect potential matches, no bitmapped Glyphs yet, but the game mechanism works.

So while I would now like to run around in small circles screaming "Why the hell is the x register working, but the accumulator isn't?" for a few days, I would rather just breathe a sigh of relief and move on to the next step:

Rewrite Rdrw to draw bitmapped Glyphs.

OH FOR GODSAKE!!!

Now, though it works perfectly everywhere, it does NOT allow me to select the very top corner of the GameBoard, and then the one directly below it. Every other case works!!! ARRRRGHHH!!!!

I think I'll go insane now...

So I went back to the code, and altered it so that even the vertical checks use the x register, not the accumulator. Don't ask me why one spot on the board didn't work. No idea. So instead of using:

sbc #9

I had to use:

dex
dex
dex
dex
dex
dex
dex
dex
dex

Both of these do the same thing, but one takes 9 instructions. It's also probably a bit slower, but hey, it actually worked.

Tonight I realized that to have a complete game I needed to do two more things:

  1. Make the Glyphs swap back if no match is made
  2. Detect potential matches, so if there are none, the game ends.

So I worked a bit to get 1. to work. Now the game actually works. If you try to swap Glyphs that aren't adjacent, it selects a new Glyph instead. If you swap two Glyphs, but this doesn't result in a match, they re-swap.

The next part is a bit harder. Potential Match Detection requires a loop to go through the GameBoard array, and check each Glyph and its neighbors to comply to 12 possible combinations of positions that can make a match. Once I code this, the game is complete, minus scoring and with it levels and the rest.

Then: Prettification.

Oh, and there are more than 12 possible combinations that can make a match. I'll need to look into this further before coding.

 

Feb 8, 2009 - Remember Your Units! And, It Turns Out, Your Variables!

So last night I left it at basically playable, without checking to see if Glyphs were next to each other. This played well. I could nab a Glyph from anywhere on the board and place it where it could make a match, and Bob's yer uncle, it worked.

(Which actually made me think of another game, very similar, but different. This game uses not only 7 Glyph designs, but 7 different colors, and any Glyph can be any color. And then it's your job to find matches from anywhere else on the board, which I think could be quite fun, and it may sneak in here as its own level. And I could still up the Glyph number to a max of 12 (for 144 different Glyphs) and still have a fun game. But I digress...)

Anyway, the selection inversion wasn't working. First of all, it took several clicks to get anything to invert, and when it did, it was way off my selected Glyph. I figured out the non-inverting this morning. Turns out my code was inverting a selection twice if it was the first selection, so it didn't look like it was inverting at all. This is just a problem with the flowchart, and I fixed that, or at least to a point.

The real troublesome part was - why was my inversion area always off, and by the same amount?

The code basically takes the pixel position of the corner of the GameBoard, then takes the S1X and S1Y (which range from 0 to 7) multiplies that by 8 and adds it to the original location. But here's where remembering your units comes in. I multiplied the sum of the starting location and the local location in the array. So I added the pixel position of the GameBoard and multiplied that by 8 as well, which was wrong.

I'm measuring my mouse location by cards inside the GameBoard, but by adding pixels to it. So I was in essence multiplying the starting offset by 64, not 8.

Sigh. Again, this is one of those situations where the simplest thing is turning out to be the hardest, and the real problem is that it was hard due to my own stupidity.

I was using the variables DA_LEFT and GS_WIDTH to find the left offset to my GameBoard, and same for the vertical dimensions. However, DA_LEFT = 11, and GS_WIDTH = 8. I needed GS_LEFT, which is 1, not GS_WIDTH, which is 8. This of course threw my selection's pixel location off.

Here's the irony - that the use of variables for things like this adds flexibility to the program, so if I move a screen element, code should still work properly, whereas if I used numbers, I'd have to track down all places where I used those numbers and change them manually. But the key element to this philosophy or programming requires you remember what the hell your variables meant!!!

So now that works, I have to make sure IsNextTo works and returns true or false properly.

Actually, this code gave me a great idea for a very special level where you can swap non-adjacent Glyphs. This would be far too easy, of course, with just the 7 different Glyphs on the board. In fact, it would be far too easy with the max of 12 Glyphs on the board. We could make this a special level that uses not only the 7 Glyph colors, but the 7 Glyph shapes in any of the 7 colors, for 49 distinct Glyphs. (Max is 144.) This special level would ask the player to make matches from anywhere on the board, and not rely on adjacency. But it would be rather difficult, I think. But the plus side is that determining if there is a valid move would be fairly easy. Just check for any two adjacent Glyphs, and then check to see if there are any more of that exact same Glyph on the board. If so, a match is possible.

Fun.

Next: Make sure IsNextTo works.

God, sometimes projects like this feel like I'm painting the ceiling of the Sistine Chapel with a toothpick. So much refining and tweaking just to get one tiny thing working!

Now the selection code seems to work fine, and I've put back the IsNextTo code so if the Glyph you choose second is not next to the first one, the first one is de-selected, and the new selection becomes the first. This should work perfectly, and does - for three of the four directions! Select left-right and it's fine, it swaps, and does the right thing. Select right-left, and no go. It re-selects, thinking it is non-adjacent. Yet the vertical code seems to work fine, and the code is practically identical for horizontal and vertical.

adc #1 adds one to the Offset, and that seems to work. But sbc #1, subtracting one from the Offset does not seem to work. But this is only true horizontally. Vertically, I'm doing adc #9, and sbc #9 and both work perfectly. GRRR!

Would you believe it? Vertically it works perfectly. Horizontally? It returns true if you select left-right, but if you select right-left, it only returns true when you select the Glyph two to the left. WTF?

 

Feb 7, 2009 - Selection Is Nice.

Why did this take so long? Look, I altered the code this morning to print the raw X and Y the mouse returns when clicked in the GameBoard. It also prints the X and Y cards I was calculating from those raw coordinates, and the Offset (in the array) of those coords. And while the math seemed right in code, every time I clicked the upper right half of a Glyph, it would return the coordinates of the Glyph to the upper right. In other words, the entire selection grid had shifted down and right by 4 pixels, and I had no idea why. A hand-trace of my code showed me I should be getting the correct results.

But by dividing my Raw X and Y by 8, I did three lsr commands, shifting the bits right (dividing by 2) three times. This should have worked, but then I would add an offset to the accumulator and store it. It seemed to somehow care about the carry flag, which may have thrown my division off, but I still don't know why. I think it was because the subtract opcode (sbc) was caring about the carry, and somehow affecting the outcome, because when I cleared the carry flag after each lsr, it seemed to work. Kind of.

I was still getting the wrong number for the X and Y card, though. But since I was consistently off by 1, I simply had to decrement the X and Y variables and bang! Got my accurate selection working. Here's a very promising screenie:

In this example, the mouse is on a green Glyph at coord 5,3 (where 0,0 is upper corner.) The upper left corner of the Desk Accessory increments with each mainLoop, so this card is just merrily flashing color after color. The raw X and Y of the mouse is 139, 77 (from the upper left of the whole screen.) This translates to 5,3 in the GameBoard, which is correct. The Glyph at 5,3 is green. The color card at the upper right of the GameBoard is green, reflecting that choice. And lastly, the Offset is 41, which is correct. So my single selection code is working perfectly.

With this working correctly, I should be able to now go ahead and do multiple selection. Then, when I get that working, I'm going to highlight the background of the selected Glyphs. Once that's done, to do it properly, I should switch to displaying accurate colors, not just the color that corresponds to the Glyph number. (See this comment, below on how colors are supposed to be working.)

Sad news on the C128 monitor front. While the Commodore 1080 monitor my friend sent me seems to work perfectly in Composite mode, I don't yet have a real Commodore 80 column RGB cable, so I went out and bought what should be the same cable - an RS232 serial male-to-female cable. Plugging that in this morning shows color and pixels, but they're wonky. The whole screen is squished and angled, leading me to believe the Commodore 128 RGB cable is not exactly the same as a serial cable extender. This means going back to eBay to find a real one, which might take another week to get here. Sigh. Some day this computer will be working again, I promise!

Ok, so after flowcharting my dual-selection code this evening, then coding it on paper, and typing it in and making sure all the typos were fixed, the thing actually assembled, and worked!

I'm not kidding! It worked! Or at least sort-of.

This section was supposed to allow for a selection, invert the selection, then allow for a second selection. If the first and second selections were adjacent (side by side, or up and down) it would swap them, and do a Match/Collapse pass. And damn, if it didn't just work first time I tried it!

Well, I say sort of. The inversion routine missed the location entirely, and it only seemed to work for vertical matches, but wow. It actually swapped Glyphs, and did a Match/Collapse properly!

So to ensure that the vertical worked and horizontal didn't only because my IsNextTo routine was wonky, I temporarily set IsNextTo to always return True, and now I can select any two Glyphs on the board and they will swap. And if the swap results in a 3-way match, it works.

Of course this isn't finished. There's a lot to do. Fix the inversion, make sure the IsNextTo code works, and one other problem. When I get two selections, and swap, it seems to think the last one was the previous selection, rather than causing a total de-selection, which it should after a valid swap. That's just a simple error.

But wow. What progress today! And I'm aiming to do more tonight. Going to go through the code by hand and see what's wrong with the inversion and other things.

But watching it play was amazing. This was five pages of code I typed in, fixed typos until it assembled, and it just worked. That's unprecedented. Usually just a half-page requires tweaking and fixing for it to work.

It does turn out, though, that my dual-selection isn't really a dual-selection. After a valid swap, it must reset the selection to 0, but isn't currently doing that.

Well, it turns out that in a moment of indecision, I inserted a single line of code that I thought should go there, but wasn't in my original code. This was messing up my dual-select code, so that a swap doesn't deselect both, and that the most recent selection always thinks its selection one. This is now fixed, and I can swap any two Glyphs reliably. Of course I haven't fixed the IsNextTo code yet, so it works on any two Glyphs, which is fine for testing. If this continues to work perfectly, then I can debug IsNextTo to figure out why it's failing. Once I do, I can put it back in and it will not accept non-adjacent selections. Instead, if the second selection is not adjacent, it clears the first selection and becomes the first selection.

I'm wondering if I should go this way. I think I should, but I'm open to this situation just causing a de-selection. But I like it the other way better.

Currently working to debug the InvertS1XY code to see why it's not inverting the right area.

 

Feb 6, 2009 - Selection.

In the morning, after driving my daughter to school (it's -6 Fahrenheit here today!!!) and before going to work, I put in routines to print the absolute X and Y of the mouse's position, if I click within the game board. Happy to report this worked perfectly, reporting back accurate X,Y coords.

Then I altered the print function to print the card X,Y on the GameBoard. This prints the absolute X,Y divided by 8, with proper offsets added so that it tells me from 0-7 where on the GameBoard the mouse is, and print those values. Happy to report this is almost working. right now, if I click the bottom right of any Glyph, it reports the correct position, but if I click the upper left, it is not. This means I'm almost right, but I'm offset by about 4 pixels or so in each direction, something I can change easily once I have a look at the code, but that's going to have to wait for this evening.

Next: Fix the Card selection, then print the Offset, calculated from the formula: Offset = X + (Y*9) + 9, and print that. Once I get that value correctly, I'll grab the value at that Glyph's position in the array, and paint a screen card that color. When I get the same color consistently, I know my selection code works.

Then it's writing the dual-select logic, which shouldn't be too hard. Once that's done, I can swap Glyphs, and run a Match pass, and when that works, I have a playable game. That's my goal for this weekend.

Then the prettifying can begin, drawing the correct colors, and drawing the Glyphs, and not just circles.

Got home from work and coded the Offset printout, so I could tell what my X and Y translate to. I was way off. In fact, I had one of the opcodes completely wrong, thinking it was doing something it wasn't. Within 5 minutes, I had it fixed.

And now, while I do get the correct offset, I'm still having the problem where only the lower right corner of the Glyph (and the upper right of the next one down and right) gives the proper coordinates, so that's my next fix, hopefully tonight.

 

Feb 5, 2009 - Nothing Again.

Another day in which I saw no opportunity to further this project. Oh well. Tomorrow for sure. And I'm still committed to having selection working by the end of the weekend.

 

Feb 4, 2009 - It's Busy Here. No Time To Work On geoGlyph!

Didn't do anything today. Got a second Commodore monitor in the mail. I bought one from a seller on eBay a couple of weeks ago, it arrived completely broken and unusable, so a friend told me he had one in a closet he didn't use, so he sold me that one. I got a refund from the eBay sale, and the new one arrived and works perfectly. But I had to buy a cable on eBay, and bought the wrong one. I have to send it back and get the proper one now. A straight D9 male to female cable.

Other than that, I took my daughter out to supper and some clothes shopping, and we came home and watched some TV, and I let her stay up late to watch a show she likes, but then she went to bed and I was so tired I did the same. Those are the hours I usually get most done on projects like this, but I was too tired.

Tomorrow: I'm going to put some print statements in the code to tell me where my mouse is clicking, and what that translates to.

I need the following data, and to make sure it's converting correctly:

Then I can be sure of my selection, and when I am, I can continue the selection code to select two valid Glyphs, and make a valid game move.

 

Feb 3, 2009 - Stupid Mechanics!

No, I don't mean the people who fix cars. I mean the mechanics of the assembler files. I typed in a bunch of code tonight to start the selection code. And when I assemble it, I get a cryptic error "Hidden Error Found", with no indication of what it might be. The geoProgrammer book says get rid of the .if Pass1 label and reassemble, get the real error, and then put it back. But when I did that, I still got "Hidden Error Found".

ARGH!

I don't know what to do with this, so I'm printing it out to see if I did anything stupid in typing in the code - some typo that may have caused the problem. I'm still a bit unclear as to whether or not I need to add my equates into each source file, if those are being used. I did add them, and perhaps that's the problem. Because now, linking all my files gives me 8 errors in Glyph.s, which I know to be perfect, because it assembles fine without this new, G-Select.s file added into the linking process. And the 8 errors seem to be the same number as the 8 equates I put in that file. So who knows?

I'm going to slog away, and read the code, see if I did anything obviously stupid. Failing that, I'll put this code into a file that already exists, see if that assembles.

I have no idea why, but the equates I used successfully elsewhere in code were just not doing it for the geoProgrammer Macros I was trying to use. So I did several things, like moving the code to a file that I know assembled fine before, and only when I removed those equates and put in hard numbers (a very bad programming tactic) did it work. And in this case, when I saw work I mean "work". The code assembled and linked ok, but weird things happened.

One thing was my Desk Accessory ran, then crashed the system. I removed the animated logo file from the code (removing it from the Link file and removing the jsr call to that code) and it worked fine. Am I running into memory issues here? I have no idea.

My Desk Accessory now assembles to 7K, which doesn't seem huge for a DA. But removing the animated logo (a fair amount of data) allowed the program to run again. I don't know what else could be causing that issue. I checked another game I wrote, Hazard and found that it was 9K and it runs fine.

So what up? No idea.

And then I set the otherPressVector to my new GSelect code, (so that when you click the mouse on the game board it uses the mouse's coordinates to get selection data) and nothing happens. Nothing crashes or anything, just nothing happens. Yet the code is practically identical to the code used in Hazard to do exactly the same thing.

I'm stymied. This happens a lot, I notice.

Giving it up for the night. It's at this point I begin to wonder if the version of geoProgrammer I have (which was copied from my original geoProgrammer disks to .d81 file, then "broken" so I could use it with the GEOS boot disk I have (not my own original, but the one that is now freely available at the official site) because my copy is serial-number-locked to my boot disks of GEOS, but I can't do a successful transfer of my GEOS boot disks to emulator files for some reason. (I just get an infinite loop while loading.) And then I have the patch applied so it can run in 128 mode. This is all stuff I did on my own C128 over a decade ago, so it should just work. But practices I used to assemble Hazard don't seem to be doing the same thing here.

Undaunted, tonight I will press on. I'll put in some test conditions on my GSelect code so I can see if it's registering the mouse press at all, and if it is, then I'll see if it's really checking the right gameboard area, and then hopefully narrow down the problem until I can actually select a Glyph accurately. Once that's done, I can continue the Selection code so I can select two Glyphs. Once that's done, the basic meat of the game is done. No scoring, no special levels, or even levels at all yet, but the basics will be - a playable game.

Once that's done, the next must-have section of code checks to see if there is a potential match on-screen, so the game knows when to tell the player there are no matches left, and end the game.

After that, it's all polish. Getting the Glyphs to display, instead of just the card colors, animating falling Glyphs, Scoring, a Scoring bar (that animates, rather than blips, to its current position from its previous position), levels, special levels, etc. All of the things that take this project from a program to a game.

Good news everyone! (Said in my best Farnsworthian voice.) I put in a simple piece of code to change a color card in the left corner of the DA if my otherPressVector was working. If I pressed the mouse (off any valid icons) one of the color cards changes color. If I pressed off the gameboard, one color changed, and if I pressed on the gameboard, the next one over changed. And this is working! YAY!

That means I can now go through the rest of my code, the part that determines the coordinates of the Glyph you clicked on, and if I can use that data to change another color card to the same color as the Glyph selected, I'll know it's working. And if it works, I can move on and my guess is that by the end of the weekend, I'll have selection working completely. Hopefully.

 

Feb 2, 2009 - Pseudo Work!

The only thing I did for geoGlyph today was flow-chart the selection process and write it up in pseudo-code. Since this is a bi-modal selection game (where you have to select two valid things before anything happens) it is not a completely simple process. First, when you select something, I have to determine if it is the first or second selection. If it is the first, fairly easy. If it is the second, I have to check to see if it is next to the first, and if so, swap the two Glyphs and do a CalcJoins. If it is not next to the first, it becomes the first, and the previous selection is de-selected. So you can select a Glyph, change your mind and select another in another (non-adjacent) spot.

I guess that's not terribly difficult. Harder right now is finding time to code it.

Tonight, after making supper for my daughter, helping her study math, making her smoothies, then popcorn, so we could watch the 3D Chuck episode, then reading to her, I was so tired I couldn't even finish the chapter I was reading. I went straight to bed and fell asleep, waking several times in the night, around 12:30, 1:00, 3:00 and 4:30 before finally waking up at 5:15, when I had to get up at 5:45 anyway, so I snoozed until I had to get up.

Obviously, nothing concrete got done in geoGlyph. Perhaps tonight.

But I'm reminded that rather than work on Selection code, tonight I should work on looping the Match/Collapse cycle. Right now we Match and Collapse until we can't Collapse anymore, then we wait for a button click. If I hit the Loop button, it will do it again. Tonight, I have to get it so it will do this cycle until there are also no more Matches. So you'll see it Match/Collapse, Match/Collapse until there are no more matches.

Then I'll work on Selection.

 

Feb 1, 2009 - Time to Get Selective!

With last night's revelation in-hand, the Match/Cascade code is now well-tested, and seems to work perfectly.

So I opted next to make it so I could increase and decrease the Max number of Glyphs on any screen. Using the left and right arrows I can now decrease and increase the number of Glyphs from a minimum of 3 to a maximum of 12. As you can guess, 3 is good for match/collapse testing, because there will be a heck of a lot of matches. Conversely, at 12, we almost never get a match/collapse. Testing each set of numbers shows me whether or not my Match/Collapse code works. And it appears to, flawlessly.

I was considering making the graphics display next. And I've already begin thinking about the initial screen display. I want it to randomize, match and collapse without redrawing, or scoring, so that internally, it reaches a point where there are no matches. Then it will display, but I want it to display by dropping in the entire screen, row-by-row, in a smoothly-animated collapse.

But I think that what's most important to do next is selection. If I can get selection working, I can then get swapping working, and then I actually have a game I can play. No scoring, but it will play out, allowing me to select Glyphs, swap and match/collapse until I can't anymore.

But that brings up an important point. One of the hardest parts of this game is going to be coding the section of code that detects whether or not there is a potential match on the current screen. This is vital because otherwise the game will never know that there are no moves left, and to end the game.

But that can come later, even after I get graphics displaying and animating correctly.

 

Jan 31, 2009 - Talk It Out. It Always Helps!

Today I didn't spend that much time on geoGlyph. But the time spent mostly dealt with making sure I was displaying the AnyCleared and GlyphsFallen variables correctly. I was. But still I had no idea why they sometimes showed up consistently as 6,6 or 7,6. And then sometimes 0,0, which it should be all the time. My friend Sean came over, and as I was explaining it to him, going through the steps carefully, it hit me.

I find explaining things out loud seriously helps me figure things out. With another person to bounce it off, (and he/she doesn't even have to know what you're talking about) talking about the problem helps solve it. Sean, however, does know what we're talking about, so that only helped.

I determined finally that every time it worked properly, I had hit the Info button, which initializes the Game Screen, putting BORDER in all of the game screen array. Other times, I don't, so it's filled with 0s. Stupid me!

I was not initializing the game screen by filling it with BORDER markings. And without that little thing, it consistently got the wrong numbers!

So within 10 minutes, I had the damn thing working. Looping correctly.

Now it does a Match, then collapses, and continues to collapse until there are no more spaces on the board for Glyphs to fall into. And then it returns, so the next click of Loop starts a new match, and series of collapses. This is how it should be! And it is! 'Grats, Hux!

And now that it's working, I can take out that display code, and put in the looping code so it collapses until it can't anymore before making another attempt at matching. Once this is working, the actual game code will be working as intended, and I can call it done and move on.

While I was working on this, I also set up the right/left arrow buttons to lower and raise the MaxGlyphs in the game, even though right now I don't use that variable. Once I am sure my looping works, I will fix it so the screen will always choose random numbers between 1 and MaxGlyphs, whereas right now it's always choosing 1-4 (for testing purposes, the number is small so I get a lot more matches.)

So I set it up to use that variable, and consistenty, whenever I wanted up to X Glyphs to draw, I was getting one less. So if I wanted 1-7, it would only ever draw 1-6. There was an off-by-one error going on there somewhere. Finally, I fixed the RndGlyph code segment to add a 1 for all Random Numbers. Once that was fixed, it all worked fine. Now I can change the game so the screen will draw random Glyphs from 3-12 colors.

What's next? Tomorrow - Make it so the Glyph colors display as the chosen list of colors, and not the colors that correspond to the Glyph number.

 

Jan 30, 2009 - WTF!

Mostly what I did today was try to figure out what the heck is going on with my Match and Collapse code that could be causing AnyCleared and GlyphsFallen (two variables that check how many Glyphs were cleared due to matches, and how many Glyphs fell due to Collapses) could possibly end up as non-zero when there were no more matches or collapses! I hand-traced the code and found nothing wrong.

The rest of this day was taken up with my daughter. I left work early, took her to her music lessons, hung out at a cafe figuring out what was wrong with this code, then went to see "The Uninvited", the teen girl horror movie that turned out to be pretty good. And the cinema was filled to the brim with girls from 13-18, with about 10% males in the audience.

 

Jan 29, 2009 - Debugging.

Didn't do anything last night, watched a movie with my daughter. I did print out three pages of code so I could trace it though I didn't actually do anything. The previous night I added code to print two numbers, one for how many cleared Glyphs there are after each Match, and one for how many Glyphs dropped during the Collapse phase. When these two numbers reach 0, the matching and collapsing is done. This is how we'll do the collapse code. But for some reason it was looping infinitely.

I found out why. Sometimes, these numbers never get to zero, even when there are no more matches or collapses. Witness:

Oh, and I changed the Glyphs to larger images for now, to easier see matches, visually.

 

Jan 28, 2009 - Back to it.

So I got back to coding.

I coded the Collapse code, the section that makes the Glyphs drop into the empty space below them. I coded it all up and hand-traced it and it seemed to work. The problem with hand-tracing Assembler code is your brain is not a computer. It sometimes does what it thinks it sees on the page, not what actually is on the page. So it's inherently error-prone.

I typed in the code, and when I ran it, it crashed GEOS. But when I ran it again, it worked. Once. Then on the second attempt it crashed GEOS.

Since the time it worked, no Glyphs near the top line (which is special-coded because it has to generate random gems instead of making the one above it fall down) collapsed, leading me to believe my top-line code is what's broken. So I tested it without executing the top-line code, and yay, it worked fine. Every time.

Of course what's happening now is every time I push the Loop button it does this:

jsr Match

jsr Rdrw

jsr Collapse

jsr Rdrw

So it checks for a match, redraws the screen, and collapses once, and redraws the screen. To get a column to collapse, I need to run this several times, so the Glyph above the empty column can reach all the way to the bottom. The problem with this sequence is that after just one collapse it checks for matches again, in other words, it's checking for matches as it collapses, not after it finishes collapsing.

This is minor, and I encountered it when I was coding the BASIC test version too. The solution is easy to fix, so I'm now going to concentrate on debugging the top-line code which is obviously causing the crash.

Once that's working, I will implement a checking code to find out if, during a single Collapse, anything fell. If nothing fell, then I can quit, and go back and do another Match test. If any Glyph fell, it loops again without checking for a Match, so that part should be easy. The final code should resemble:

jsr Match
jsr Rdrw
10$ jsr Collapse

jsr Rdrw
if any collapsed, 10

Which actually brings up an interesting level-type - The Live Level where matches are made during collapse.

Yesterday, while at work, I came up with the idea of animating the Cabot Tower logo. I like it. I'm going to start on a black screen, then have the moon rise over 8-12 frames, revealing the tower in silhouette, and at the last frame have the Tower light go on, and the sea light up. The logo text will fade in as the moon rises, or it will pop in when the light goes on.

Tonight I fixed the Collapse code, finishing off the top-line code, and tested it. The problem with testing Glyph is your eyes don't see all the matches. So when I hit Loop, and it makes the next set of matches and collapses, I can't tell why suddenly some Glyphs disappeared. So a second screen displaying the previous screen was necessary, which I draw to the left of the Desk Accessory during Debug mode.

It looks like this:

Note on the left is the screen as it was before we checked for matches and did one collapse. After, we can see the four vertical whites in the second column are gone, and the two above that have dropped, and a new, purple Glyph has been added. Same goes across the board.

Repeated pressing of the Debug key walks through the collapses, and as far as I can tell, with the aid of the left, Debug screen, it all seems to work. For the moment, and to ensure more matches, I'm running with just four color Glyphs.

Watch the cascade! Keep in mind that this version is also matching on the fly, which is not how the final game will work. (Although I reserve the right to use this as a specialized level.

Next up: Make sure no matches happen during the multiple cascading collapses.

It should be a very simple matter to do this. The logic goes like this:

AnyCleared = 0
10$ Match
Redraw
If AnyCleared = 0 then rts ; If no matches, then rts - (start with a new random screen)
GlyphsFallen = 0
20$ Collapse
Redraw
If GlyphsFallen = 0 then 10$ ; If nothing fell, then we're done collapsing, and we must check again for a new match, causing a cascade.
Goto 20$ ; This means there were some fallen Glyphs, and we have to collapse again before doing another match.

But several attempts at coding this failed. And while it did cascade multiple times, once it got to a point where there were no more matches, it would go into an infinite loop. I have to figure this out.

To help, I now print AnyCleared (which adds up for each Glyph cleared) and GlyphsFallen (which adds up for every Glyph fallen) on the game-board so I can see what those values are, and find out why the looping I set up isn't working.

 

Jan 27, 2009 - Family Tragedy

Without going into specifics, nothing is getting posted today. A pair of deaths in our immediate family makes projects like this seem a bit less important, somehow.

 

Jan 26, 2009 - We've Got Vertical!

After last night's eventual success getting horizontal matching working, I spent about 10 minutes this morning fixing the vertical matching. Observe:

Yay!

 

Jan 25, 2009 - Rearranging Deck Chairs on the Titanic

I find that when I'm involved in a project this complicated (though it's not as complex as some I've written) I spend a lot of time moving code around, tidying it up, separating files out, doing things that I think the project needs, but just not right now. It's an avoidance tactic, and I'm very good at it. Watch the National Film Board film "Getting Started". It explains it all in great detail.

I'm forgetting a major principle in Assembler coding. (Especially important since my Debugger isn't working in VICE - I can't use the Commodore's RESTORE key properly, so I can't switch back and forth from the application window to the Debug window.) Do something simple and expland on it.

I typed in the full code for the Matching routine, and the program kept crashing. Now, I've hand-traced this code logic several times, and it should work. But it crashes GEOS. In fact, it filled the mouse's sprite data with garbage. Ok...

But I lost that code (see previous post) and I'm about to type it in again. This code goes through the whole Game Screen array and checks for matches, replacing the Glyphs with Empty whenenever it finds a 3-Glyph match.

But I forgot previous experience in coding these games - simple first - complicated later.

So now, my first pass will be to go through the Game Screen array, find a particular color and replace it with a new color. That is much simpler, and if it works, proves my looping code and Glyph-testing code works. (It should work as it is, but since it isn't, I have to prove it.)

Then, when that's done, I'll change the code to check for horizontal matches.

When that's working, I'll change the code to check for vertical matches.

So that's the new plan for today.

And, in another effort to rearrange the deck chairs on the Titanic I am going to (Ooooh! Look! A shiny object!... where was I?) Oh yeah, I'm going to do some clean-up and rearrangement of our office room, which took a serious dumping-on during Christmas, storing all the extra boxes and other crud in there, making it nigh impossible to even reach my real Commodore 128, and the PC I bought as a dev machine.

So I tried changing my addressing mode to Indirect X, which should allow me to use the actual address of the Screen array, rather than putting it into a register and accessing it indirectly from the y register. Neither way was working. I used a very tight little loop to get the first Glyph in the array, and change every other Glyph in that array that matched to a new color. All that happened, was the first item in the array got turned to 0, which is just epic fail.

So I changed the code to even more simple. I changed the value of the 12th value in the array to a number. It turned to black (0). Which at least shows I'm accessing the array properly, but not putting a correct value there.

I suspected my problem was in the Redraw code, which was just created for debugging, but that appears to work correctly. So I checked the Random code that puts random values into the array, and I rememberd that I was getting a random number from 1-7 and copying the lower four bits to the upper four bits so the color card on my screen would turn solid (both drawn and undrawn pixels would turn the same color, making a solid card.)

So I decided to change things. I fixed the Random code to put numbers from 1-7 in, leaving the upper nybble empty. This should color only the background pixels. This required me changing the start screen so it draws a graphic that would make it easy to see the foreground and background colors. Once I did that, I should be able to have an accurate array, filled with correct values, and I can go from there.

How about a screen cap of my progress?

Oh, and I've decided to stop beating myself up over rearranging the deck chairs. By doing some of that work, I made it more modular and easier to make changes, or at least for now. And I re-discovered how easy it is to include new files of code without a lot of prep work, so large new modules will likely now all be done as separate files. This may require renaming my files from GlyphMatch.s to GMatch.s. Change all Glyph to G or GG (geoGlyph) just to save name length. In GEOS file names can be 16 characters, but the Assembler creates .rel files, requiring 4 letters, leaving me with 12, and Glyph takes up 5. More rearranging, but I figure each deck chair I shuffle around makes my job ultimately easier.

I think it's possible some of my code wasn't working because it assumed the buffer row and column were filled with 0, but they were'nt. Because my Info button fills that array out with a random number. Then Start fills the Game Array with random values. My array-checking code was checking for 0s, and finding none. Not sure that's important, but I just changed the code so that Info zeroes out the whole array, no longer filling it with a random number. That code was put in to see if the array was displaying properly, and it is, so no more need for it. So now, ClrScrn will actually clear it.

Oh, God, I'm such a Doofus! That's right, Huxter, I'm Addressing you!

Today I spent way too much time trying to figure out why my indexed addressing modes failed to work. In trying to get some of this code working, I followed my new creedo: Start simple, and expand. I started simple. For the matching code, I simply wanted to change one Glyph to a new color.

Whenever I tried it using the Assembler's equates, it worked:

lda 8
sta Scrn1+40

My aim was to take the Glyph at position 40 and color it 8 (Orange). Now, the Glyph changed, alright. But to gray. Huh?

Since it worked (partially) I then expanded to an indexed addressing mode. I used the y indexing because that's what I was using to fill out the array with random numbers. So:

LoadW r2,#Scrn1 - This is a GEOS Macro that loads the zero-page pseudoregister with the address of my Scrn1 array
lda 8 - loads the accumulator with the number 8
ldy 40 - loads the y register with the number 40
sta (r2),y - places the contents of the accumulator in #Scrn1 + 40

...and for some damned reason it was placing a gray block at the first position in the Scrn1 array. GRRR!

Then it hit me. I'm used to using GEOS equates for whole numbers, and the Assembler thinks that when I say lda 40, it means I want to load the accumulator with the contents of the memory location 40, rather than the number 40. Duh.

So when I tried putting # in front of the absolute numbers, it began to work.

A lot of my day was spent banging my head against another damned wall, and all based on an incorrect precept of how the Assembler handled addressing.

Well, at least now I know, and I can actually get this to work. I then coded something that picks the first color in the array, and changes every other gem that color to orange. And to prove it worked, I did it only for half of the array. It worked. Perfectly. Whew. Now I can get back to it.

So more work tonight, but this time, it was all coming up roses. I actually got the code working that checked the first spot on the Game Screen array, and changed all Glyphs of that color to orange. No problems at all.

This encouraged me to move forward, and soon, I had the code finding and emptying all groups of 3, but only 3. This is because I was emptying the same screen as I went, so what used to be a 4-match would not be a match at all. Imagine:

- there is a match of 4 in the middle there. My early code would go through each Glyph, checking to see if the adjacent two and only two Glyphs (to the right) match, and empty them. Result:

- The Glyph we're testing against was the first light green Glyph. Since the next two to the right match, we empty them.

But I think you can see what's wrong with this picture right away - When I move to the next position to the right, what used to be a light green Glyph is now Empty, and the next two Glyphs to the right do not match, because they are not both empty. So we don't empty that last light green Glyph.

This is a problem inherent with emptying the same board you are checking. The solution was, before doing any checking, copy the board to a second board, and when you empty a Glyph, empty it on the second board, not the main board. Then, on the second board, (shown here directly below the first:


- Now, when I move from the first light green Glyph to the second on the main board, it has matches two to the right. I can then empty those three, which redundantly empties the middle two again, but that's no big deal. When we do our scoring later, we will only count empty spaces, not how many times the same space was emptied.

Final result:


Then we copy the second board back up to the first, for a final result:

And this code now works:

Check out. How Sweeeeeet it is! This screen shows examples of a 3-match, 2 4-matches, and one 5-match! And it works!

 

Jan 24, 2009 - It's A Process

Ugh. Went to sleep last night defeated. Processes did not work for me. I set up the process table, I initialized the processes, then I ran a routine to start the processes and GEOS crashed. Every time. Then I ran just one of the four processes I started, and still, GEOS crashed. Tried again this morning. I even found Error Trap, (SystemError2.1), a program that supposedly inserts itself into the GEOS Panic routine and instead of just telling me it crashed, the Dialog Box was supposed to have a button to return you to DeskTop. I recall this working when I was coding in the 90s, but perhasp it only works on GEOS 64... because it didn't work for me. Without it running, geoGlyph crashes to the System Error window. With Error Trap installed, it just locks up. So that's no better.

Abandoning Processes for the moment. I'll come back to it later, when I'm further along and actually need them. Right now it was just an experiment, a lesson in how to get Processes working.

Moving on...

Awesome. I was looking up some info on the C128, and found this website about the C128. Below the article is a letter posted by Bill Herd, creator of the C128, so I just fired off a letter of thanks to him for creating my favorite machine.

Then I spent some time remembering how to separate out source files. Why assemble every time, the old screen code that works fine, and you never change? Put it in a separate file, assemble it once, and link it in. But it took a while to get it right. Using older programs I wrote, I figured it out, and finally got it working bug-free. But for the life of me I can't figure out why splitting out even more of the code into separate files caused a linker error... will try again later. Not important enough for now.

I duplicated my main source file, put in the assemble code on the first page, left in the equates I put in for the Desk Accessory dimensions, and deleted the rest of the code except for those standard screen routines, and saved it as a separate file, then deleted those parts from the main game source file. Now I have two files that assemble and link exactly the same as the one file before.

My goal is to push out code that doesn't change much into separate modules. All graphical data, for example, texture clips, color data, icons, etc, should go out to a separate file. I'll do that later when I have some time.

It's time for me now to stop distracting myself (a major flaw in my personality - when a daunting task is at hand, I distract myself quite effectively with other things) and get on with typing in that Matching Code.

Gave it up for a while, went out to lunch with my family, got groceries, visited an art store and a comic store, got back, watched a movie, some TV with my daughter, read to her (a chapter from "Skybreaker") and then got back at it.

I typed in the code I had hand-written on the 22nd, printed it out so I could do a hand-trace again, and hand-traced it. Found one tiny flaw (heh...) and fixed it. Now this is the Matching code, so it needs to be triggered. For now, since I don't have a game loop yet, I'm going to tie the Matching Code to the Loop button which currently does nothing. So now, when you start the game, it shows the logo. Push the Info button and it fills the Game Screen array with a single number (to show it's filled) and displays it. Push the Start button and it generates a randomized Game Screen array, and displays it. Now, I'll tie in the Loop button and it will do a Match run and display it. If I get no blacks spaces, I know my code didn't work.

I'll also know my code didn't work when it crashes too... or if nothing at all happens when I push Loop.

If it does work, then my next step is putting in the second color display (below the actual desk accessory) when Debug is pressed, so I can see what the screen looked like before matching, and the upper screen will be what it looks like after the matching.

Then if this just works 100%, I can begin the cascading code.

Not so fast, Huxter... typing that all in and assembling it proved to be a pain. Assembly showed I had made some typos, but most seriously I was relying on a pair of opcodes that didn't exist - TXY and TYX. Transfer x-register to y-register, and vice versa. We do have TYA and TAY, which transfer the y-register to the accumulator, and vice versa, and the same for the x-register, but nothing to transfer directly between the x and y. I had to code it so instead it put the value of the y-register into a variable byte. Got that done, and it still isn't assembling. Now after fixing a number of problems, it's complaining of an undefined local label.

Printing out those pages and trying to see what the problem is... grrrrr.

Gah! Don't ask me how, but I lost most of the work I did tonight. I found myself finding a backup of the main source file, and redoing some things I did last night, and of course my Matching Code got disappeared.

So I decided instead of diving into that again tonight, I just did a few little things, like make the Redraw routine check for the Debug flag, and draw the 8x8 grid if no flag, or the 9x9 grid if the flag is set. I had that check done at the time of calling Redraw, but I opted to have Redraw decide that for us.

Anyway, it's 3:00am and I'm going to sleep now. Tomorrow, if I am not nearly as disgusted as I am right now, I'll retype in that code (thankfully I kept a hard copy before losing that file) and test it. Ugh... I'm not happy right now.

 

Jan 23, 2009 - Boo for Me!

Not at all tired this morning, though I'm disappointed at what I got done last night - which was bupkiss. Almost.

Ok, so I did start the Debugger tutorial, but I immediately ran into a problem using VICE. Once the Debugger switches to full-execute mode, and switches out to the main screen, you have to hit the RESTORE key to get back to the debug window. The problem with that is that in VICE, (the amazingly excellent Commodore emulator) the RESTORE key doesn't seem to take me back. I do recall on the C64 you had to actually hit the RESTORE key, not just press it... but that can't be translated in an emulator. So I'm not sure how to get back to the Debug window. Which makes the Debugger useless unless I'm working on the actual machine, which would completely change the way I'm working. Perhaps I'll have to actually bite the bullet and work on my real machine, but that's in an office room and I like to have a TV on while I'm working.

Other than that, what I did last night was spend a couple of hours helping my daughter study for math. Didn't do anything on geoGlyph. Sorry. Hopefully tonight...

Tonight I'm investigating Processes in GEOS. Earlier this evening I sent out a post to the comp.sys.cbm group to ask if anyone there is interested in helping me provide some sound for geoGlyph. It got me thinking about Interrupt-level code, which would be necessary to run music behind my game.

I don't know enough about sound on the C64 to do anything that sounds good, oh, I've played with the SID chip and done some fun stuff, but nothing I consider good enough to release. My geoMimic game is the closest thing I've done to music on the C64. That and my Boxxy game played a cruddy version of "Greensleeves" as boxxy jumped from box to box, but it didn't sound good.

Ideally, I'd love to incorporate the music from the Synth Sample, (a famous C64 program that blew people away when it was released.) It was written with a small segment of interrupt code that played through the music data, leaving BASIC free to do whatever. If I could get that code and data into my game, I'd have a nice sounding game as well as a nice playing game.

It got me to thinking about Interrupt-level code. I haven't done a lot of that, if any, but I understand the concept. However GEOS provides something better - Processes. Literally a table of routines to run, with a counter that decrements every interrupt, (60 times per second.) So if I have the concept right, I can set up a routine that does a simple operation (like change the color of a color card, or play the next note in a list of musical notes) and if I set the interval up at 60, it will flash that card, or play that next note, once a second.

To test this, I'm writing a simple set of four processes (with different timers) that will flash color cards on my screen for now, to see if it works. And GEOS provides ways to halt, pause, force and restart processes. Sounds like this may be the way to go to do several things:

  1. Flash Glyphs on-screen
  2. Play music
  3. Flash my logo color, etc.

More on this later, as I test it.

This morning I was browsing images of Cabot Tower, because I was concerned something was wrong with my logo. Then I discovered Cabot Tower doesn't have a flag pole on the upper deck. Instead it has a few of them on the second deck down, though there is a chimney on the upper deck. Will redesign the logo to be a bit more accurate. Also, I'm not sure I like the corporate-sounding name "Cabot Tower Software" so I'm thinking of going with just "Cabot Tower".

I spent time fixing the logo, and separating out the logo image from the main screen's background, so I could redisplay them both.

But I got side-tracked playing with Processes. Nothing I tried worked. It crashed on running the program. I'll keep trying, later.

 

Jan 22, 2009 - Array for Me!

Damn. Tired this morning. I have to stop working until 1:00am. The problem is that's when my mind is at its most active and accute. That's when I can hand-trace three written pages of assembler code and discover problems with it, and fix those problems without effort. But I'm paying for it now. Have to get up at 6:00 every morning to get my daughter ready for school, and this morning I'm tired. Luckily, once she leaves by 6:45, I have about two hours to veg before work.

This morning, I finished watching Repo: The Genetic Opera. Not sure what to think of it... but there you go. This is very incidental to the topic at hand, which is coding geoGlyph.

My aim for today: Get this code input into geoWrite128 and assemble it cleanly. And then test it, preparing for the inevitable crashes. Well, talk to you then.

Oh. Good point. I coded all of my previous Assembler programs (about 8 completed programs that are relatively bug-free) without using geoDebugger. In retrospect, this was a stupid thing to do, but I always felt time spent coding and fixing was more valuable than learning a complicated Debugger tool.

Enough of that nonsense. During the run of this project, one important aspect will not go missing. I will set aside a bit of time each day to read up on and do the in-manual tutorials for geoDebugger, because it will provide tools I need to see inside what's happening in the program. Like recently, when I realized I didn't know what the final array I was creating for the game screen actually looked like. So I wrote code to display it properly until I was satisfied it was being created properly, and displayed properly. With the help of a Debugger, I could simply have looked at the contents of the array and not needed to write that extra code.

So for the half-hour I have until I go to work, I'm going to read the first pages of the Debugger chapters of the manual. During the weekend, I'm going to go through the tutorials, so I can learn how to probe memory and check the state of the code.

Here's a sample of the code I hand-wrote. This is page 2 of 3.


(Clicky)

 

Jan 21, 2009 - The Match Game

Last night I flow-charted the Matching Code. I had done this before, and coded it in BASIC 8.0 on my 128 (well, on VICE, not MY 128. Vice was quicker.) And I had it all working. But last night I re-flowcharted it with detailed commands, with Assembler in mind. Satisfied that it should work, I'll start coding that tonight. With any luck, by the end of this weekend, matching will work, and it will blank out any spaces that follow the 3-or-more-in-a-row matching rules.

If I can get that much done this weekend, effectively, I'll be happy. And if so, I'll also implement the Previous Screen code, which will, (if Debug is ON) print a copy of the original screen (before matching) at the bottom of the desk accessory. This is so I can make sure all the right matches were made. I can see the screen before matching (below) and the main screen will show the after-match configuration.

And if that all works before the weekend is over, I'll begin the Glyph Dropping code, which will blip Glyphs down to the empty space below them until they reach bottom of a given column. (Later this will be animated. But for now, and until the game is fully working, I'm not going to bother.)

Also, at this stage, the Glyphs will not actually draw. I'll continue to use the color card painting, as that is sufficient for testing.

Now I start to worry about speed. I was always worried about speed, on a Commodore 64 in GEOS. This game will be a tradeoff between speed and good looks. If I have to sacrifice sliding Glyphs to make it more playable, I will. But until it's shown I have to, I won't.

I'm going to play it this way: Pack the game with nice features, and then later if necessary remove those that are both too slow and not absolutely important for game-play, like animated swapping, sliding Glyphs and exploding Glyphs.

I'm already concerned (if you've read this far) about the speed of random number generation, but now I'm worried about the speed of looping code, and the response time of GEOS after a mouse click. After spending some time last night playing my old game Hazard I found the response time was a bit slow. It's been a while of course, but it seemed slower in VICE than on my physical computer with the Commodore 1351a mouse. But in reality, this game can move fairly slowly. Once you select the two Glyphs to swap, it can take a while for the game to match, and cascade, and match again and cascade again until no more matches are found.

One more thing to do this weekend - transfer the executable to my physical C128 and test the speed so far in GEOS.

Oh dear. As I was hand-writing on paper the assembler code for my flow chart for the Matching Code, I tried to do it with a nested X,Y loop, but when you're dealing with a two-dimensional array in Assembler, it's really just a long one-dimension array, and looping once through a long array is a lot faster, and a heck of a lot easier on the noggin.

But here's where that extra column is coming back to haunt me. Kind of. I mean, I still need it, otherwise when I got to the last Glyph of, say, row 3, and the Glyph is there, I can't simply look one to the right, because that would actually drop me down to the first Glyph of row 4, and if that also was a , it would register as a match, and that would be bad.

So now I'm cycling linearly through the array, (skipping the first, buffer row) and I'm checking to see if the space is filled with a 0, (which the buffer row and column is) and if it reaches one, it skips this space and moves on (to the first Glyph on the next row down.)

At first, I thought, "Oh. Now I have to fill the buffers with something unique, besides 0-12, because 0 is reserved for Emtpy, and we will have Glyphs that go up to 12." So I chose $F0, the far left bit. But then I realized this isn't necessary because during the Matching Code phase, there will never be an empty space, so the empty spaces of the buffer row and column will be the only 0s in the array. So I can use the 0 to skip that space and move on to the next space.

Whew. I thought I'd have to go back and change a few things, but I can keep things as they are now, as long as whenever I fill the Screen array, I remember to fill the buffer row and column with 0s.

I'm pretty sure the hand-written code I'm working on now will work. My flow chart is far more complex than this code. At first, I was having to calculate indices by multiplying the y register by 9, and adding the x register, to get the position in the array of any given space, which mimics the way a two dimensional array works. So I was going to do the following:

     tya ; transfer y to accumulator
     asl a ; multiply a by 2
     asl a ; multiply a by 2 (x4)
     asl a ; multiply a by 2 (x8)
     adc 8 ; add 8 to a
     sta TMP ; stick a in TMP
     txa ; move x into a
     adc TMP ; add value of x to TMP
     sta TMP ; store back in TMP

And I'd do this on the fly every time to find the index of the current array space. What nonsense. A linear array is much easier. If I want to move one to the right or left, I simply add or subtract one. If I want to go up or down, I subract or add 9. And the Matching Code should just work with this scheme.

As I type this I have the horizontal check written out by hand, and am about to repeat the section vertically.

But I got this note from the guy who suggested some assembler code to choose a random number:

	LDA Random
	TAX
	AND #$07
	TAY
	TXA
	LDX AddBits ;Number of bits to add:0/7,1/8,2/9,3/10,4/11,5/12
	BEQ L1
L3	ASL A
	BCC L2
	INY
L2	DEX
	BNE L3
L1	TYA
	RTS

This won't be reliable for numbers greater than 12, so if you need 13+ (6 or more bits) you can't just plug a 6 into AddBits. You'd need to get another random byte.

Luckily I don't have to go past 12, as at that point, I effectively run out of Glyph colors that would be useful, (with 16 colors to choose from, and black is the background, leaving me with 14...) I should type this in and try it. But I'll leave that for the weekend.

I kind of hope this code does work, because it would save me the trouble of writing out a new Random Lookup Table every time I add a new Glyph. Still, it may slow things down, as the look-up table will be faster.

Oh well, back to hand-writing code.

So that was fun. I wrote out the code, corrected it a couple of times, and wrote out a final copy. Then I hand-traced the program with a paper grid, and checked if the code should do what it did. I had a few wrong steps in there, that hand-tracing discovered, and when I ended work tonight (at 1:00am) I am confident the code will work. No typing it in yet, though. It's far too late at night. Going to bed now.

 

Jan 20, 2009 - A Random Epiphane. (Oh, and it's Innauguration Day!)

One of my main concerns at the moment is how to do in Assembler what is very simple in BASIC or other high-level languages - X = rnd(MAX)

The idea is that when the game starts, you have 7 Glyphs, and so I need to generate random numbers from 1-7 (0 is an empty square).

I want to do it without having to loop too much. So if I was to do a random byte, and check to see if it's > MAX, I could be looping a lot each time I want a new random number. Imagine:

10 X = rnd(255)
20 if X > 17 then 10 - this would mean that MOST times, it would loop back, wasting valuable time.

I thought in this case, since I have 7 Glyphs to start, I could do this. It would work if I AND the Random number with 7. Then I simply have to loop if the result is 0. That's a 1/8 chance of looping each time. Acceptable.

But I'm intending on adding up to 12 Glyphs. Then, I have to AND it with 15 and check. Now I have to loop on the values 0, 13, 14, 15, which is 1/4 of the time. Less acceptable, but still probably workable.

But at MAX 8, I'm looping for 0, 9, 10, 11, 12, which is a 5/16 chance, nearly a third, of repeating.

This wastes valuable time during game-play when the code should be as tight as possible. Hey, this is a 1MHz CPU after all.

John Russell, who has helped me many times in the past with programming dilemmas, said, something along these lines: Hey, why not fill out a large array pre-loaded with random numbers you generated in BASIC, and then just walk through that sequence every time I need a random number? Well, that would be bad because the sequence would have to repeat at some point to be useful.

But it gave me an idea of using a Look-up Table. But in a slightly different way:

Before the game begins, I'll fill out a 255-byte array with a sequence from 1-MAX (which starts at 7). So:

1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6,7... 7,1,2,3

Then, my Random routine will get a random number from 0-255, then use that as an index into that array. Immediate random number in the range I need!

And then, since speed is what I'm hoping to achieve, and speed is NOT important between levels, and I'll be adding Glyphs between levels, I can fill out that array again when I add a Glyph. So by the time I get to 12, I have this sequence:

1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12,1,2,3... ... 12,1,2,3

Hot damn. This will work! And it's brilliant! I waste no time, because it's done at a part of the game when fast execution is not important.

It still means that when I'm filling out that look-up table, I'll AND my Random number with 15, and check for >MAX. This means that there will be a lot of out-of-range choices and looping, but it should't affect the game too much, since it should still happen before you can blink. But since the first part of the game, MAX will be 7, I'll AND 7 until MAX > 7. This will mean faster table fill-in for the first levels of the game, and when MAX is set to 8, it will be noticeably slower, but again, this happens between levels, so no huge big deal.

Thanks, John.

But this morning, before work, I wanted to confirm I was actually displaying the game screen array properly, and since a bunch of random numbers is impossible to determine order, I coded a temporary routine that set the array to a rising sequence of numbers, with 0 in the right-most column.

00,01,02,03,04,05,06,07,00
08,09,10,11,12,13,14,15,00
     ...
64,65,66,67,68,69,70,71,00

Then I print the screen. If my display code is working correctly, the top row should all have black pixels, and the backgrounds should be black, white, red, cyan, purple, green, blue, yellow and black again. The next row begins with orange pixels, (which you can't see because it's solid), then brown, pink, dk gray, lt gray, lt green, lt blue and lt gray. The third row will have a white background and black pixels, and so on. It should end with a yellow background with purple pixels, and a black/black. Here is the actual result:


(Note that in the TM in the bottom right corner, the pixels are the purple bits, and the background is the yellow.)

The picture bears the truth. The array is printing perfectly, from 0 (black/black) at the top left, to 71(purple/yellow) one in from the bottom right, with a 0 at bottom right. I can now remove that code, satisfied that I am correctly displaying my array. YAY!

How about that Inauguration, eh?

Here's where I show my inexperience in Assembler. I asked the comp.sys.cbm group how to go about getting a random range, and I got a response:

	LDA Random
	STA $FB
	AND #$0F
	TAX
	BIT $FB
	BMI L1
	INX
L1	BVS L2
	INX
L2	TXA
	RTS

What this code is doing is a bit beyond me at the moment. The BIT opcode itself is a bit of a mystery to me. Still, I'm going to try it out, see what it does. It occurs to me I could plug this code into my RandTest program (which I wrote a couple of months ago to test three methods of getting random numbers in GEOS. It plots the occurrences of the random numbers on a vertical graph, and looks like this: (Click any image to enlarge it)

This is the second time I've written a graphing program to track random numbers. In the above screen, 39129 calls to GEOS's GetRandom routine were called, and the High Byte (of the Word) used, and graphed. This program lets me mouse over each line to see how many times that number was called. This screen showed that the random number my mouse is on (127) was called 146 times. (The graphic stops when any number reaches 199.)

This screen shows the same GetRandom routine used, but this one plots the Low Byte of the resulting random Word. Here, the number 133 was chosen 183 times with 38585 GetRandoms run. Note that both seem to be fairly random. Repeated runs look very similar.

See how the SID chip's noise register, often used to get random numbers, does some very bad wave-like trending.

Anyway, I'm going to plug in this bit of code above, and see what happens.

Incidentally, this is the second RandTest I wrote. The first tracks bits, not bytes, and tracks the low and high byte of the GEOS GetRandom result:

Sadly, I was very bad at the UI on this one, and didn't even indicate which 8 lines are the Low and the High bytes of the random Word. But you can see that one byte is far more evenly random than the other. Repeated runs reveal similar trends in the lower half of this graph.

If this succinct piece of code works, I'll use it. If it makes it hard to increment my MAX, then I'll have to come up with something else.

There is one other option: Different RND commands depending on the number I choose:

MAX = Current Number of Glyphs
if MAX = 7, goto RND7
if MAX = 8, goto RND8
       ...
if MAX = 12, goto RND12

Then each RND* function does its own thing to limit the random range, like so:

RND10:
       jsr GetRandom ; GEOS routine to generate a random        Word (two bytes)
       lda random ; get the low byte of the random Word GetRandom        returns
       and 7 ; AND it with 7 (which eliminates any number >7)
       sta TMP ; store it in TMP
       lda random ; load a with the same random number
       and 3 ; AND it with 3 (which eliminates any number >3)
       adc TMP ; and add them together. Result should be rnd(10)

The other RND* routines do the same, testing combinations of bits that add up to the number I need.

Problem: When I tried this in BASIC for a quick check, I almost never got a 1 value. I think I'll abandon this way and stick with the lookup table.


So what did I do tonight? Well, I pondered the code above a bit, updated this page, found RandTest and replied to the person who suggested that code above. Not as much as I'd like. But now I'm going to watch "The Colbert Report" and flow-chart the code to do match-testing.

(By the way, I realize that I can't just do a 6x6 loooping test, because I test both horizontally and vertically on each gem in sequence. This means I have to do the full 8x8 check. However, if I was doing it in TWO loops, one horizontal, and one vertical, I could loop a 6x8 and an 8x6 loop of tests. But I'm pretty sure that doing two loops of 48 with two checks in each loop (X+1, X+2) I end up doing 96 checks per loop, for 192 checks.

As it is now, I do an 8x8 loop, checking four times at each square, two across and two vertically, and end up doing 64 x 4 checks, or 256 checks, but I'd only be doing one loop, so I'm guessing that the overhead for doing two loops might remove any gain I'd get, and I already know that my 8x8 code works. Proven in BASIC.

Now, off to flow-chart. G'night. Happy Obama, America!

 

Jan 19, 2009 - Fixing Some Obvious Boo-Boos

I was right, more or less. I was initializing the screen array properly, but printing it improperly. I stupidly set the start of the array to 8 more than 0, so it was starting to print the array 8 in, and when it reached the end, it went 8 past the end of the array, which was another array initialized to 0, so that explained the 8 black spaces after the one colored space at the bottom of my screen. A quick code fix fixed that. So that fixes my 9x9 Redraw routine.

Now I will likely have to make a similar fix to my 8x8 Redraw. but then maybe not, because that's supposed to skip the first 9, since those are the non-drawn buffer spaces.

My friend and co-6502-assembly-coder John Russell pointed out to me that when it comes time to do my checking for matches, I never need to go past the sixth position in the array, because there's no way you can have a 3-length match starting at position 7 or 8. He just sped my checkin code (when I write it) up by nearly double. Now, instead of having to check an 8x8 array (for 64 checks) I can check the 6x6 corner of the array (for 36 checks - just over half of the operations required!)

This also makes me think that the right-most buffer column in my array isn't necessary. When I first devised it, it was so I could check X+1 at position 8, so it needed a position 9. Since I really don't need to check that far, I can make the array one less horizontally.

But I figure I still need the top line, because I intend to use it to put in new Glyphs when the top space cascades to empty.

Should I work tonight to change the array size? Or just leave it as it is for now and fix it later?

I coded it to print 9x9 and 8x8 and both seemed to work perfectly. Then I coded the Debug button so it prints 9x9 in Debug mode, and 8x8 in non-Debug mode. But I noticed that once you print the 9x9 array, printing the 8x8 array doesn't help because the top line remains printed red/white

So I'm going to make Start (temporarily) recolor the game board from the original color data. That won't stay around long, though.

So for tonight's work so far - I got the cleared array working, and the random screen seems to work fine. At this point, I can actually begin work on the matching code. Amazing! But in reality, I have to start drawing gems.

What you're seeing is a jumble of color over my Cabot Tower Software logo. The jumble of color is the Glyph screen array, displayed properly, with a random number between 0 and 255 in each square. (The left four bits color the pixels, the right four bits color the background.) Also you see a gray-and-white line at the top and down the right side. These are the buffer lines I needed, filled in with gray-and-white before drawing the multicolred Game screen array.

On the right, you see two red arrows. Those will raise and lower the number of Glyphs available, and that number will sit between the arrows, in blue, when I code that.

Below that, the Loop button (which does nothing yet) and the Debug button which currently decides whether to draw the 8x8 array or the full 9x9 array.

Then below that, Info, Start and Quit, which right now Fill the Array with One value, Fill the Array with Random Glyph values, and Quit.

This is a current test screen. The Cabot Tower Software logo is obscured by the array color display. Eventually the color "cards" will be behind actual images of the Glyphs themselves, and it will begin to look a heck of a lot better.

So now what?

Now I'm going to make sure the random number we choose for the array is between 1 and 7. So I get a random number between 0 and 255. Then I AND it with 17, giving me a number between 0 and 17. But I don't want 0, so I check. If it is 0, it does it again until it isn't 0.

Now I need to put the value I got, which exists in the low 4 bits of my random byte, and copy those bits in the high 4 bits of the same byte. This will result in the pixels and background squares in my Glyph screen to be solid color cards.

I do this by storing the value in a Tmp byte. Then I shift the byte left four times, scrolling the low 4 bits to the high 4 bits.

Then I get that Tmp value back and OR it to the original, making the top half match the bottom half of the byte.

This code won't be necessary after I start actually drawing Glyphs in that window. But that comes later, so for now I need it.

But man, it was hard to get that low half the same as the high half, because I assumed a value was getting stored when it wasn't, so I was basically throwing away the work, and loading the accumulator with only half of the byte again. Once I figured that out, now it works perfectly.


See? An 8x8 array of numbers from 1-7, with low half of byte same as high half of byte. Keep in mind that that black column on the right will eventually be the scoring bar, which will, like a thermometer, rise up from the bottom of the window to the top, indicating the level is over.

Tomorrow: (It's 12:30am now, and I'm kind of trying to keep to a schedule which has me call it quits for the night at midnight, so I'm already a half-hour over.)

Instead of the random array displaying the colors numbered from 1-7, I will program it to pick from a color table, so that the values at that table from 1-7 will display instead. So instead of

White, Red, Cyan, Purple, Green, Blue, Yellow
- I'll get -
Green, Yellow, Red, Purple, Light Blue, Orange, Blue

But that's it for tonight.

 

Jan 19, 2009 - Debugging Assembler is Not Fun

When I finished last night, I filled out the Scrn1 array larger than the array should be, filling 92 bytes instead of 82, and the display of it worked perfectly. For a while I thought I had the array size wrong, but that's not right. The array is 9x9 which is 81 bytes. I usually put an extra one at the end for safety. Call me paranoid.

Anyway, because it was printing the first 8 lines, and only 1 byte of the 9th line, I questioned my array size, knowing better. Late last night, when I called it quits for the evening, it came to me that - DUH - I was starting the display of my array at a position further along than its beginning, so it's running out at the first byte of the 9th line. So I'm starting 8 too late. That should be an easy fix.

But as I had to get up early today, help my wife clean off her car so she could attend a workshop, then clean off my car (and while I was out there, my neighbor's) so I don't have time right now to fix the problem, but at least I appear to have identified it.

The upshot is that at the moment, what I programmed mostly works:

What doesn't work:

Once I get those things working, I'm going to employ the Debug button in order to print the full 9x9 array when turned on (so I can see what's happening in the extra row and column) and the 8x8 array in place when turned off. Eventually this will also print the previous screen too, below the DA, to verify correct things happen.

Then I start drawing the actual graphic instead of the color cards only.

 

Jan 18, 2009 - Displaying Glyphs and Failed Efficiency

Starting today, I tried to split out from the main program several routines used in all my Desk Accessories, that save and restore the screen graphics and color. This is code that existed in the sample Desk Accessory program Berkley Softworks provided with geoProgrammer, and is quite useful.

I split it out only to find that variables set in the main file are required again in the DAScreens file. This is problematic because it means that the DAScreen file can't be a standard include. It has to have information specific to the current Desk Accessory you're programming, so it becomes pointless. Oh well... Reverted.

And I was getting annoyed at using the geoMimic icon for geoGlyph so I captured a 3x3 matrix of gems, moved them up a pixel each and used that for my icon. Since an icon is 24 pixels by 21 (and not 24) I had to move the Glyphs up one each.

(The reason it's not square 24x24 is technical, having to do with the memory map of the Commodore 64/128. Basically, 3 bytes (24 pixels) x 21 lines = 63, which is almost a perfect 64 bytes. 8-bit computers like binary multpiles, and 64 is perfect. If a sprite was to be a perfect 24x24 it would mean it takes up 72 bytes, which is 8 over a nice convenient block of 64.)

Now for the Glyphs. Simple, 8x8 color images that have to look distinct from each other not only in color but in look. So I came up with the following progression. The first seven will be the standard Glyphs. In my version of the game I intend to add more Glyphs as you level up, so I created a maximum of 12 Glyphs, the tentative designs for which are seen here:

Now it's off to geoPaint to cut'n'paste them all individuall into the Photo Album. - Done

What next? I had to write a nested loop to fill the Screen matrix (8x8 with one extra column to the right, and one extra row at the top) with random numbers. This is not a simple task for me in Assembler. First, I have to write a nested loop because I don't want the full 9x9 matrix filled up with random numbers, the top row and right column must remain zero, so I do a nested X,Y loop to do this matrix:

0
0
0
0
0
0
0
0
0
2
3
5
3
2
1
7
6
0
3
4
4
2
1
6
7
5
0
5
5
2
4
5
6
7
6
0
3
4
1
3
5
7
7
6
0
2
2
4
2
5
6
1
7
0
4
4
3
2
5
6
7
1
0
3
3
2
3
3
4
6
2
0
7
1
1
2
6
4
5
5
0

Carefully hand-tracing the looping code, it seems to work. However, when it came time to jumping to my routine that gets random numbers, the program froze. The real RndGlyph routine should store the x and y registers, and get a random number and put it into the accumulator, a. Then that a value gets stored in the appropriate location in the above matrix.

But something is wrong with the RndGlyph routine. It was locking up the program. Probably caught in an endless loop.

Fixed that for now by filling the matrix with a single number. This should be fine for now, just so I can write a routine that will also print out that number in the upper corner of the Desk Accessory by re-painting the color cards there based on that number. This should result in visible color changes in an 8x8 grid at the top left of the Desk Accessory, if it works and doesn't hopelessly crash.

Well, it didn't crash. And it printed in the upper left block of the DA, but it printed all black, meaning the value was 0, even though I attempted to fill it with $12, which is hex for 17, which should paint the pixels white, and the background red. Hmmm... the looping logic appears to work, because I'm using the same looping structure to print it, and it's printing the proper format.

I think I'll directly put a random number in there and see if that works.

Yup. Almost there. It prints the matrix, but in the wrong place. That's just an offset issue, which I'll fix now.

Yeah, so this gets tricky. I want the matrix to NOT fill out the top, but it appears to be NOT filling out the bottom. More fixing. Isn't this fun?

I opted to write a redraw routine that draws the whole 9x9 matrix, and then one that does the 8x8 matrix, to ensure it's working. And I'll link that to the DEBUG button. If Debug, then draw the 9x9 screen.

So this isn't working yet. I have to hand-trace the looping structure, to see what's wrong. But in the meantime, I coded the Debug Flag to toggle, complete with inverted icon when on. And now the Start icon randomizes the Glyph screen, and the Info icon clears it. The clearing is still off. Either that or the redraw is off.

 

Jan 17, 2009 - VICE Emulator, GEOS and Beginning to Code

GEOS programs like this require graphics for the gameboard and UI. Icons, titles, etc. I always design my screens in geoPaint before doing a single line of code. This is no different. I spent days designing the screen, the various glyph, the icons I would use, layout of the score, and thought out where control icons would go, etc. And since I was now working on Stage One of the game (random screen - find matches - collapse screen - find matches - repeat when no more matches) I needed special icons that will not be seen in the final game:

#Glyphs - A left and right arrow with a printed number between them. This would indicate how many unique glyphs I would use for this run. Bejeweled has 7 unique glyphs. But to test matching code and recursive cascading effectively on an 8x8 grid, you need to have fewer than 7 glyphs. Ideally, 3 or 4. Otherwise matches would be rare and testing matching code would be more difficult and/or time consuming. The arrows will allow me to select a range from 2 (1 is invalid, as everything will always match) up to whatever maximum I wish, but practically, I will not allow it go go above 12 for now. Why not 7? Because my version of this game will add more unique glyphs as you get to higher levels.

Loop - I want to be able to see every single screen's action, so my intent was to hit the Start icon after every single screen redraw, so I can examine the screen and see if the program found all the matches and acted accordingly. This button would allow me to do that, unless turned on, at which point the entire procedure would continue to loop until I stopped it. This is an ON/OFF toggle.

Debug - I need a Debug button to add certain features while debugging the code. Mostly, what this one should do is put up a second screen, which would always be the previous screen, as it was before the matching code removed any glyphs. This way I can verify that any valid matches did not get missed, and false matches didn't happen. This was greatly useful in my BASIC version, and I determined that my code worked perfectly. Now, however, I'm re-writing that code in Assembler, and I will have to verify that the new version works too. This screen will be drawn OFF the game's main UI board, below the game. This is an ON/OFF toggle.

Info - This will do nothing at the moment, but will eventually call up a series of INFO screens in the board's glyph screen, or, more likely, like geoMimic, the whole game screen. When you're done reading, it will replace the INFO screen with the current glyph screen, and you can continue playing. During Stage One this does nothing, but as it is going to be on the main screen, I'll put it in now.

Start - This starts the program after each screen redraw, so I can carefully watch what's happening to the glyph matching code, and the glyph collapsing code. This will not be necessary if the Loop toggle is ON. The final function for this icon will be to start a new game.

Quit - Every application has to be able to quit.

Being a bit rusty in GEOS coding (I did do a RandTest in November) I forgot that unlike random bitmaps, GEOS will only allow icons at byte card coordinates, so I had to redesign the main screen a few times to get it right.

After copying the bitmap scraps to a photo album, I prepared the code for geoMimic, which is another simple Desk Accessory game I wrote. (Desk Accessories are capable of being run as standalone applications, or from the menu of many major GEOS applications, so you can have a little diversion while working.)

The base work for geoGlyph is the same as geoMimic, so I copied that code to new filenames and started replacing the screen and icon graphics in GEOS 128 using the VICE Emulator. Unfortunately, the VICE Emulator crashed on me several times, making me lose my work! This hasn't happened a lot until now. When coding RandTest2 in November, I don't recall getting frequent crashes.

Now it's so bad I can't start up the emulator anymore. I will be rebooting the computer and trying again after finishing this entry.

Undaunted I continue. I paused for a while to set up this Developer's Diary, but am now about to go back at it. By the end of tonight I hope to have the main screen drawing, being colored, and the icons operable, even if they do nothing (but Quit) for now.

I finalized the graphics and inserted them into the source file. I eliminated a bunch of code used in geoMimic that I wouldn't need. But of course that caused issues, because some other pieces of code required some of that data. Had to put some variables back.

One piece of code reads an array of color data and puts it behind the graphic screen. But it's been so long that I didn't remember that the data has to be entered right-to-left, not left-to-right. I plotted the data left-to-right, so I had to reverse 12 lines of 18 numbers manually, and that sucks.

One thing this program makes me want to do is write a program that will read the color data of a given area of a geoPaint file. That will write out the color data automatically.

Anyway, it's midnight now and it runs. All buttons just make it quit.

Next up:

Damn. Signal Software is a fairly common name, so I can't use it. But I couldn't find a Cabot Tower Software, so I'm going with that. So I changed the game screen to reflect that, and when I assembled that, the screen blew up while drawing the graphic! SUCKS!

 

Jan 16, 2009 - Humble Beginnings

Over the past week or so I've been drawing flow-charts and writing BASIC code to prove the concept. Could I create a game with an 8x8 grid with 7 unique glyph types, and successfully write code to find 3 glyph or more matches, remove the matches, collapse the screen, and repeat until there are no more matches?

After flowcharting repeatedly, I thought I had it. Assuming a random screen is the same as a screen after you've selected and swapped two adjacent glyphs, I wrote code to ferret out 3-or-more matches, but would also extend to all contiguous glyphs along a horizontal or vertical line. So a 4-glyph match would work, as would a 5-glyph match. I coded it out like this:

For each glyph on the screen, I'd check to see if the horizontal next glyph AND the next one were matches. If so, I'd remove all three. I'd do the same vertically.

Then I thought that that would only get sets of 3, so I then extended the logic to check the fourth and fifth glyphs and if they also matched, remove those as well. But there was a flaw in that logic. That should only catch matches of 5, no more. I would have to extend the code again. Only after I did did I notice that I didn't need to do that at all, if I were to be more clever about it.

Say, you have these glyphs: ABCDDDDEF in a horizontal line.

Using my routine, it would do nothing on A, B and C. Then it would look at D, D+1 and D+2, find they matched, and empty them like so: ABCxxxDEF

So my code would then extend to the fourth glyph, and get this: ABCxxxxEF because it would do nothing on the emptied glyph spaces to check to see that fourth D glyph.

And I didn't notice the problem until I got to the point where I had to check vertically. An isolated vertical set of three also worked. But I noticed that if I had a T intersection going up, I wouldn't find a match on the vertical line. Why? Because I emptied the glyph at the intersecting line already. That means the glyph I was comparing to was an empty space, and I'd never find the vertical component of the match.

Then I had the smart idea to use two game boards. One with the glyphs in the current configuration. Before the glyph matching code, that board would get copied to a new board. Any time I removed a glyph, I would leave the glyph on the original board, but remove it on the new board. Then, as I compared the glyphs on the original board, I would not only find the vertical matches, because I had not emptied any glyphs, I would also not need to check the fourth or fifth (or more) glyphs. I only ever needed to check for three. Here's why:

ABCDDDDEF - my start board

ABCDDDDEF - ABCDDDEF - and my "new" board

A - no match. B - no match. C - no match. D - checking the next glyph I find a match. Which would only matter if the third glyph matched as well, and it did, so I would empty the three Ds from the "new" board, thusly: ABCDDDDEF - ABCxxxDEF

Now my code would proceed to the second D on my original board, and find that the next and subsequent glyph also matched, and removed those from the "new" board: ABCxxxxEF.

But not only that, during my first pass, after finding the three horizontal match, I check for a vertical match, and if there was one, it would find it, because no glyph had been removed.

It turns out that this code works perfectly for any length of match of 3 or more.

But it would only work if my board was one square larger than the game board to the right and at the top. Why? Because when I get to the extreme right edge, I cannot check the array past its boundaries, so I can't check X+1, as the array ends at X. So I solved that issue by making the grid one size larger to the right (because I always check horizontal matches to the right of the original glyph) and one size larger at the top because I always check the glyph at Y-1 (above) the current glyph. And it still works because when it is at the right edge and checks X+1 if finds no match (as it is always empty) and never has to check X+2. (The code only checks X+2 if X+1 is a match.)

So it turns out that all this worked perfectly, and as long as I copy the contents of the newly-emptied "new" board back to the "original" board, all was well, and I coded it up in BASIC, and it works.

 

January, 2009 - geoGlyph Intentions

When this project is finished, completely finished, I hope to have achieved the basics of Bejeweled in GEOS on a Commodore 64/128 (runnable in 40 columns only, but that's ok.)

But not only will this game be like Bejeweled, it will have some touches of my own.

Various diffeent Bonus Rounds will behave differently. Some thoughts may be:

There are many different types of play I could encorporate. Even Bejeweled Twist, where selecting a glyph makes the 2x2 array it is in rotate. More on that later, if this all works.

Some of the finesse I would like to add before calling it done:

GI Joe

Go To HomeGEOSGo To E-Mail

 

All content of these pages © Sean Huxter.