Help Kodiak64 for FREE!

Click here to read how.

Share this page

Kodiak64 Newsletter

100% free, 100% spam-free!

(You can view a sample here).


Welcome Fellow C64 Fans




Kodiak64 Microblog

Podcast 001: Twofold Purpose of Kodiak64 Website

Kodiak64FM Podcast

Posted on 16-Jan-2021 by Kodiak

Welcome to the first ever "Kodiak64FM" podcast, in which I ramble in a steady sleep-inducing monotone about the twofold purpose of the revamp of Kodiak64.com in recent times, those 2 purposes being:

  • To build my newsletter subscriber list (if my unreliable web host would only get its act together consistently enough for that to occur), and,
  • To get some support to help me justify the time I spend on Parallaxian to my increasingly weary family.


I also talk a little bit about which countries most of my visitors come from and which type of articles are the most popular.

Anyway, it's my first ever attempt at a podcast so lower your expectations accordingly!


VOLUME TOO LOW? If the audio is a little too quiet on your browser, you can always download the podcast from the control bar above and play it back at a higher volume.

permalink to this post

Entering and Exiting Interrupts Efficiently

Posted on 14-Jan-2021 by Kodiak

If you're new to 6502 coding on the Commodore 64 or, at least, new to working with interrupts, you've probably seen the "textbook" way to enter and exit them.

And sure, it's not without good reason it's done that way... it reinforces the need for the programmer to be mindful of certain things that must be taken care of as part of any interrupt code, specifically, recording and recovering the registers and acknowledging the interrupts themselves.

But textbook - or "cargo cult" in the lingo of the coding snobs - is not necessarily optimal in many cases.

However, before elaborating on why that's the case, let's consider the typically taught way of entering an interrupt:

Textbook way to enter an interrupt
(3+2+3+2+3 = 13 cycles to record registers, takes 5 bytes of RAM)

PHA ; [3] Push contents of A-register (Accumulator) on to Stack
TXA ; [2] Since there is no PHX instruction, do X -> A
PHA ; [3] Push contents of X-register on to Stack via A-reg
TYA ; [2] Since there is no PHY instruction, do Y -> A
PHA ; [3] Push contents of Y-register on to Stack via A-reg
; Interrupt's proper tasks begin here


Plainly, therefore, the above does 3 things:

  1. It stores the contents of the Accumulator out of harm's way for later retrieval at the end of the interrupt.
  2. It stores the contents of the X-register out of harm's way for later retrieval at the end of the interrupt.
  3. It stores the contents of the Y-register out of harm's way for later retrieval at the end of the interrupt.


Then, at the end of the interrupt, the standard thing to do is recover the registers in the following fashion, which is cognisant of the first-in, last-out way of using the Stack for storing values:

Textbook way to exit an interrupt
(4+2+4+2+4 = 16 cycles to restore registers, takes 5 bytes of RAM)

; Interrupt acknowledged before this point
PLA ; [4] Pull contents of Stack into Y-reg via A-reg
TAY ; [2] Since there is no PLY instruction, do A -> Y
PLA ; [4] Pull contents of Stack into X-reg via A-reg
TAX ; [2] Since there is no PLX instruction, do A -> X
PLA ; [4] Pull contents of Stack into A-reg
RTI ; Return from interrupt


These actions ensure that, when the interrupt finally finishes and the CPU returns to executing the code in the program's "main loop", all the registers are restored to the exact condition they were in just before the interrupt started.

Now, this becomes a waste of code and CPU cyles when the interrupt handler code only uses 1 or 2, but not all 3 registers, so to enter and exit efficiently, we should only record and recover the actual registers the interrupt handler code uses, as per the example below:

Simple interrupt handler using only A-register
(3 cycles to record A-register, 4 cycles to recover, 2 bytes of RAM)

PHA ; [3] Push contents of A-register on to Stack
LDA #%00001110 ; Set charset to $7800
STA $D018
LDA #06 ; Set background colour = BLUE
STA $D021
LDA #<IRST6 ; Set vectors for next handler
STA $FFFE
LDA #>IRST6
STA $FFFF
LDA #$80 ; Set trigger point for next handler
STA $D012
ASL $D019 ; Acknowledge interrupt
PLA ; [4] Pull contents of Stack into A-reg
RTI ; Return from interrupt


Since the X-reg and Y-reg were not used in the main handler code, there was no need to record and restore them, thus saving 10 CPU cycles on entering the interrupt handler and 12 on exiting it (22 cycles altogether which is approximately one third of a raster line saved); the RAM saved is 4 bytes on entry and 4 on exit = 8 overall.

And if you're not doing anything exotic like interrupting the interrupt handler using the NMI, you could avoid the Stack altogether and just replace the opening PHA with STA ZPHOLDA, where ZPHOLDA is a zero page (or "Zeropage") value that will be used to temporarily hold the A-reg's value on entering the interrupt handler; then, at the end of the handler, you would replace PLA with LDA ZPHOLDA.

That process takes 2 more bytes of RAM overall than just using the PHA/PLA construct, but it takes 1 cycle less because the LDA ZPHOLDA operation only takes 3 cycles, not the 4 cycles the PLA requires.

You could also just enter with some self-modifying code such as STA ARECOVER+1 (4 cycles) and exit with ARECOVER LDA #$00 (2 cycles... immediate value modified via STA ARECOVER+1).

All of the foregoing should, of course, highlight the folly of doing something stupidly unnecessary like this:

The superfluous use of diverse registers
LDX #<IRST6
LDY #>IRST6
STX $FFFE
STY $FFFF


The moral of the story being: never use extra registers unnecessarily!

Of course, where your interrupt handler must use 2 or all 3 registers, you can also apply the zero page holder variable method or the self-modifying code method, as per the technical notes in my Deep Winter Tech Demo article.

Similar posts:

Illegal Opcode SAX/AXS: A Practical Use

ORA: A Special Use in Branch Testing

Interested in coding on the C64? Check out these books on Amazon (and yes, I get a tiny pittance if you buy via any banner below):



permalink to this post

Parallaxian WIP - Quick Update

Posted on 07-01-2021 by Kodiak

Things have been a bit quiet with the blog this week and for good reason; I've been snowed under coding a new explosion sequencer for Parallaxian.

As part of my "all killer, no filler" mantra for the game, these explosions must not look clichéd... out go the stereoptyped 7-8 frame fireballs so popular in shoot-em-ups and in comes an ambitious, bombastic visual effect inspired by the toggleplex concept.

That being said, I am hoping to get my next two blog posts finished very soon; one covers the issue of efficiently entering and exiting interrupts, while the other is a technical critique of Raid Over Moscow, so look out for those coming shortly.

And if all goes to plan, my first toe-dip into podcasting should also be online very soon, so again, look out for that.

Anyway, back to coding fireballs... (or as the Rowlands brothers might have said when coding Creatures 1 & 2, "back to coding furballs").

ORA: A Special Use in Branch Testing

Posted on 02-Jan-2021 by Kodiak

In a recent post, I talked about some special uses for the EOR instruction, particularly with regard to saving CPU time on addition and subtraction.

Now it's the turn of ORA, which can also be used for adding within certain conditions on 6502, as per this Codebase piece on Combining Bits / Substitute Logical Operations.

Changing track from maths, a nice little hack you can apply (and which is used occasionally in Parallaxian) is where you start with something prosaic like this:

Bloaty way to test multiple conditions for same trigger condition
(20* cycles until EFFECT is reached, takes 16 bytes of RAM)

LDA ZPPLANEBLOWMODE ; Disable effect if plane is exploding
BNE QUIT
LDA ZPTAILSLIDE ; Disable effect if plane is tail-sliding
BNE QUIT
LDA ZPTURNSTATUS ; Disable effect if plane is turning
BNE QUIT
LDA ZPRESPAWN ; Disable effect if plane is respawning
BNE QUIT
; EFFECT ...
...
...
QUIT RTS



The above assumes, in all instances of the variables being tested, that 01 = relevant condition is active and 00 = relevant condition is inactive (i.e. turned off).

Note that if any single one - or more - or all - of those conditions is / are active, the effect will not be performed; in other words, all of those conditions must = 00 for the effect to be executed.

You could, in plain English, say this:

"If any one or more of ZPPLANEBLOWMODE or ZPTAILSLIDE or ZPTURNSTATUS or ZPRESPAWN is turned on, then we do not perform the effect."

So we can convert that sentence into code thus:

Compact way to test multiple conditions for same trigger condition
(14* cycles until EFFECT is reached, takes 10 bytes of RAM)

LDA ZPPLANEBLOWMODE ; Disable effect if plane is exploding
ORA ZPTAILSLIDE ; Disable effect if plane is tail-sliding
ORA ZPTURNSTATUS ; Disable effect if plane is turning
ORA ZPRESPAWN ; Disable effect if plane is respawning
BNE QUIT
; EFFECT ...
...
...
QUIT RTS



By the same token, you could use AND everywhere instead of ORA and finish with a BEQ to the exit location, but the key aim is always the same: to save some needless branch-testing cycles and RAM by using ORA or AND in this fashion.

SCHEDULED AS AN EXCLUSIVE FEATURE ARTICLE IN THE JAN 2021 NEWSLETTER: FLD Three Ways - CPU + RAM efficient ways to perform FLD.

____

Similar post:

Illegal Opcode SAX/AXS: A Practical Use

Interested in coding games on the C64? Check out this book on Amazon (and yes, I get a tiny pittance if you buy via the banner below):



permalink to this post

Special Advisory: Email Sign-Up Woes Continue

Posted on 30-Dec-2020 by Kodiak

Ongoing issues with my web hosting provider continue to turn the Newsletter subscription service on and off every day, but I am trying to work with the web hosting provider to resolve the problem.

Again, apologies for any incovenience caused by this; you should still try to use the service to sign-up, but, if it fails, you can alternatively subscribe by emailing me direct on jon (at symbol) kodiak64.com and I can manually add your email to the mailing list.

Deep Winter Thoughts

Posted on 28-Dec-2020 by Kodiak

As the year draws to a close and I sit here mindful of the freezing, snowy scene outside, my thoughts turn again to the tech demo videos I released back in early 2020 of Deep Winter on the Commodore 64, my planned sequel to Parallaxian.

It's true to say I rushed the coding side of it, being pressed for time (as usual), but the fundamentals are there in the form of a nice NMI (Non-Maskable Interrupt) chain that interrupts the IRSTs (Raster Interrupts).

The principle is simple: let the IRSTs do the heavy-lifting of scrolling the parallax landscape and meanwhile we interrupt the scroll code with precisely timed NMIs to nip in quickly, plex the tree sprites, and get out again quickly, without skipping a heartbeat.

Of course, the whole NMI-plexing-while-suspending-IRSTs concept has its origins in Parallaxian and has also been ported into the chase levels of my good friend John Henderson's game in development, The Wild Wood, which I have been helping out with, as per this detailed tech article.

It's a truly great way to mix sprite plexing and scrolling based on screen split effects on the venerable C64, so one day I hope to reveal it in all its gory technical detail, ideally after Parallaxian's release.

In the meantime, check out the snowstorm effect in the clip below; it's a new recording and while it suffers from some of the same video capture problems that plagued the Youtube version, the quality is better; this is an effect that needs a real C64 (or a VICE running without rival applications slowing it down) to truly execute flawlessly.

NOTE: The falling snow effect is sensitive to your stream quality + the processing capabilities of the device it's viewed on. However, you can download it from the settings dialogue on the embedded player above and play back with little or no "banding" spoiling the effect.

That effect is entirely built on the Toggleplex concept; in this example, a sprite "canvas" is projected over the landscape and then simple falling snow sprite definitions are updated as required.

The game itself is to be a survival-against-the-wild experience, where each day you must source enough food, water, heat, medical aid, clothing, shelter, etc., to survive until spring, while also avoiding dangerous interactions with wild animals and other survivalists in the mountains.

Gameplay is envisaged as a combination of problem-solving, exploration and strategy elements, so it should be quite different to almost anything ever seen on the C64 prior to it.

More information on the game concept in this article.

permalink to this post

EOR: Some Special Uses

Posted on 22-Dec-2020 by Kodiak

In my own personal, ongoing quest for doing things quicker or more RAM-efficiently with code, some time ago I blundered into some nice little hacks with the EOR instruction, the "Exclusive OR".

Some of my favourites are:

  1. A tiny EOR-based switch aka "alternator" for frame-skipping in raster interrupts.
  2. Using EOR for faster subtraction.
  3. Using EOR for faster addition.


Lets consider each of them in turn:

1. EOR-based alternator: At some point in many coding scenarios, you will probably want to perform certain tasks only on every other frame; it could be some game AI, it could be something like Toggleplexing, an audio effect, a scroll event or whatever; the key thing is that you need to do it every other frame.

For this, you could do as follows (which has probably been used by many coders since the 1980s, so it's not my invention!) inside one interrupt handler, so that it fires once every frame (i.e. screen refresh):

LDA ZPTOGGLE
EOR #$01
STA ZPTOGGLE
BNE ODDFRAME ; Branch to ODDFRAME every "odd" frame, whereas this BNE is ignored on every "even" frame

; EVENFRAME code goes here

All you have to do when setting this up at the start of the program is to ensure the variable ZPTOGGLE = either 0 or 1 and EOR will invert that value every frame, producing a 0,1,0,1,0,1,0,1,0 cycle ad infinitum.

SPECIAL NOTE: I like to use another way to perform the toggle logic that saves 1 cycle on both odd and even paths compared to the above, but it requires the use of self-modifying code and consumes more RAM for the logic... this is scheduled for inclusion in the next Newsletter for subscribers.


2. EOR for faster subtraction: Normally you would subtract using SEC and SBC, such as per the following example:

LDA #%00011111
SEC
SBC BITTABLE,Y ; where BITTABLE,Y is known to hold only values less than #%00011111

That takes 2 + 2 + 4* cycles = 8-9 cycles, the actual number depending on whether or not the page boundary is crossed by the SBC,Y operation; and if we say, by way of illustration, that the value in BITTABLE,Y = #%00001111 (15 in decimal), the result will be #%00010000, i.e, 31 - 15 = 16.

So if we can safely predict the range of the value being subtracted, we could use EOR to do the subtraction like this:

LDA BITTABLE,Y
EOR #%00011111 ; Shorthand for subtracting BITTABLE,Y from #%00011111

The same calculation (with the same result, obviously!) now takes 4* + 2 cycles = 6-7 cycles, the actual number depending on whether or not the page boundary is crossed by the LDA,Y operation, with the extra bonus of the carry flag remaining unaltered by the calculation!

Again, the idea of using EOR for this kind of subtraction is not my invention and it's probably impossible to know who did it first, but it's slick and saves 2 precious CPU cycles and 1 byte of RAM from the standard way of subtracting.

(Incidentally, this forms part of the landscape damage encoding routine in Parallaxian, in which trees set on fire by bombing are still on fire next time they scroll on to the screen).


3. EOR for faster addition: Just as you can use EOR for fast subtraction if the constraints of that subtraction are first known and understood, so you can also use it for some fast addition, with the same fundamental proviso.

For example, let's say you want to add any number less than #$F0 (in decimal, 128 or, in binary #%10000000) to #$F0; normally, you would use CLC and ADC to do the following (we should keep it all in binary to help understand what's happening with the various bits):

LDA #%00001010
CLC
ADC #%10000000

That gives a result of #%10001010 (138 in decimal) in the A-reg and takes 2 + 2 + 2 = 6 cycles, but consider that the following will give you the same result:

LDA #%00001010
EOR #%10000000

...which puts #%10001010 (138 in decimal) in the A-reg but takes only 2 + 2 = 4 cycles, with the saving still applying over different addressing modes if you replace like with like and, as with the EOR subtraction, you walk out of the calculation with the carry flag unaffected!


Of course, that's only the tip of the iceberg in terms of what can be done with EOR; for example, you can use it to save space in the VIC bank if you have a sprite that has a flickering flame such as that used by Parallaxian's "Backfire" enemy.

Backfire Sprite

So instead of keeping the full definitions for the craft with and without the flame showing, you only need one and use EOR to manually draw / clear the sprite data for the flame on alternating frames.

Another nice use for EOR I came across was where you can use it to obfuscate code, as per the final example on this Dustlayer post about Bit Manipulation.

Finally, there are some helpful generic, non-C64-related tools online that will allow you to perform tests using the big 3 logical operators of AND, ORA and EOR (which sometimes is known as XOR), such as this one: bitwise-calculator.

Similar post:

Illegal Opcode SAX/AXS: A Practical Use

Interested in coding on the C64? Check out this Kindle e-book on Amazon (and yes, I get a tiny pittance if you buy via the banner below):



permalink to this post

What Makes This Game Great: Buggy Boy

Posted on 21-Dec-2020 by Kodiak

Right off the bat, I have to say I have never been a huge fan of racing games on the Commodore 64, especially the ones that aspire to provide more realistic gameplay.

Perhaps it's a frame rate issue... the C64's CPU (the 6510) operates at 1MHz which, even for legacy era 8-bit machines, is slow (by comparison the C64's great rival, the ZX Spectrum, for instance, runs at 3.5MHz) and the screen refresh rate on European + Australian PAL C64s is 50Hz (on American NTSC machines, it's 60Hz), so cooking up a 3D storm on the C64 has always been challenging.

However, when the coin-op conversion for the C64 of Tatsumi's Buggy Boy was released in 1987, suddenly there was an ultra playable, best-in-the-genre racing game for the platform that had me totally hooked from the off.

Buggy Boy West

The UK's gaming press was suitably impressed too, with a staggering 97% rating in this Zzap!64 review and someone in another magazine (the precise details of which I have forgotten over the years) urging its readers to - and I quote this as verbatim as my memory permits - "Buy, beg, borrow or steal a copy" of the game.

(I believe some people have also said, anecdotally, that the C64 version of Buggy Boy is the best version of all!)

So, with such gushing praise still echoing through the mists of time, let's take a fresh look at what makes this game so great:

  • Like all great games, its controls are intuitive and responsive, which is an absolute baseline attribute in establishing good gameplay.
  • It focusses on gameplay first, realism second, rather than making the blunder of doing those two things the other way round.
  • The 3D game environment includes curved cambers, tunnels, chicanes and bridges over water, all rendered in a such a smooth, natural fashion as to draw the player into the game world; in other words, the visual effects automatically make the game immersive.
  • The gameplay hits the sweet spot between fairness on the one hand, while remaining a challenge on the other.
  • The variety of obstacles and landscapes keeps the game as interesting and addictive as its other core ingredients listed above do.
  • Its 3D engine works to the strengths, or more precisely, within the limitations of, the C64's hardware rather than trying to push the machine to do things its speed and processing power were never built to do; rumour has it that the same 3D engine (or an essential part thereof) was also used for the Afterburner clone, First Strike, which was also programmed by Buggy Boy's developer, Dave Thomas.


Of course, like all games, it has a few imperfections and room for improvement, so here's what I - as usual, speaking as a C64 game developer - would change or improve IF allowed to deviate somewhat from total conformity with the arcade original:

  • I would have liked - assuming RAM constraints are not an issue - some dips and rises on the road, as all the game's courses are set on flat ground.
  • I also would like slightly better graphics here and there, with maybe some hi-res overlays, or whatever other expedient capable of reducing the C64's signature blockiness; the water splash effect, for example, is very ugly due to its blockiness.
  • Given my penchant revealed in Parallaxian, I would like some parallax scrolling on the horizon, with the clouds moving slower than the hills.
  • The game woud also benefit from the use of some non-standard colours, as per my Luma-Driven Graphics article.
  • The winter course ("North") needs some ice on the road with an obligatory sliding-out-of-control effect.
  • Buggy Boy North
  • The crash sequences are rather basic and expose the need for the buggy to have a shadow effect, so I would fix those things too.
  • I would polish the presentation; the loading screen is ugly and the title page and interstitials a little too utilitarian looking.
  • Buggy Boy Loading Screen

Those are only minor points, however, so by and large, the game is as close to perfect in its genre for the C64 as attainable, at least within the technical know-how of 1987.

Download it here: Buggy Boy Download.

Similar posts:

What Makes This Game Great: Mayhem in Monsterland

What Makes This Game Great: Nebulus

permalink to this post

C64 Game Wishlist: Creatures III

Posted on 18-Dec-2020 by Kodiak

Without the slightest hint of doubt, Creatures by Apex (published by Thalamus in 1990) was one of the finest developments in Commodore 64 gaming history.

Creatures

Although widely perceived as a platform game, Creatures was technically a hybrid platformer-shooter or a variation on the so-called "run-n'-gun" style of games, set in a compelling environment built around a cartoonish graphical theme with a distinctive and consistent style that made it look much superior to most other late era C64 games.

I would, of course, elaborate on what makes Creatures a classic, but that's the subject for another "What Makes This Game Great" post, so I'll table that idea for now and focus instead on what form a Creatures 3 on the C64 would take.

First of all, however, I would like to comment on Creatures 2 and state the 2 big reasons why I personally think it was not a worthy successor to the original game.

  • While it was visually stunning and deserved an Oscar for its musical score, Creatures 2 lacked the single most important ingredient - in my view at least - that made its predecessor so compelling: an explorable scrolling environment.
  • Its interludes were not particularly fun and (again, for me) quickly became something to be endured rather than enjoyed.


So, somewhat disappointed by Creatures 2, I would like to see a better sequel to the first game... a Creatures 3, which for me would feature the following:

  • Fundamentally, more scrolling based exploration, but this time with the possibility of occasional back-tracking and the ability to explore a little above and below the default screen zone, thus requiring some vertical scrolling as well; I'm not proposing a Sam's Journey redux, just some degree of expanded play area in the vertical axis.
  • Momentum and possible "shifting camera" perspective on the scrolling, of the variety seen in the aforementioned Sam's Journey.
  • The weather effects of Creatures 2 (i.e. the lovely snowfall effect) worked into the scrolling landscape, plus a similar rain effect.
  • Creatures 2
  • An expanded suite of weaponry, including all or most of the original, but with some novel weapons as well.
  • More extensive use of hi-res / ECM graphics to make everything less blocky and more "next gen", but without losing the charm and essential vibe of the original design motif.
  • Liberal use of non-standard colours - see my Luma-Driven Graphics article for more.
  • Aircraft and vehicles that Clyde can commandeer to travel faster in certain regions of the new game world.
  • A Steve Rowlands sound track... okay, given it would presumably be impossible to persuade him to provide that, and close to impossible (one surmises) to replicate his style, something on a par by an elite scene musician; for me, this would pose the greatest development challenge in creating a Creatures 3.


A Creatures 3 would, of course, pose a monumental coding and design challenge for anyone taking the project on, plus it would likely require the approval of the Rowlands brothers or whoever else holds any rights to the original games, so its chances of ever coming to fruition might be slim.

That said, it's nice to dream!

Similar posts:

What Makes This Game Great: Mayhem in Monsterland

Game Wishlist: Uridium II / Next

permalink to this post

Dec 2020 Kodiak64 Newsletter

Posted on 17-Dec-2020 by Kodiak

The December 2020 Kodiak64 Newsletter is ready for my subscribers to download.

December 2020 Newsletter
permalink to this post

Illegal Opcode SAX/AXS: A Practical Use

Posted on 15-Dec-2020 by Kodiak

As a 6502 coder on the Commodore 64, sooner or later you may, if trying to trim down raster time, find the use of one or more of the so-called illegal opcodes (aka undocumented or unintended opcodes) the solution to your problem.

For example, often when working with sprites you'll want to switch off some of a specific sprite's characteristics (such as MCM mode, x-expand, y-expand, char priority, etc.)

In standard code (i.e., without using illegals), you might write something like this for sprite 04 (for example) to un-expand in the x- and y-directions, and to set the MSB to 0 and to turn MCM off (which is the same as turning hi-res mode back on, obviously):

(In the snippets below, please note that ZP is my standard prefix on all Zero-Page variables, and also note, using binary when working with the VIC registers (or SID registers, for that matter) makes life so much easier than using raw hexadecimal or even decimal).

LDA ZPSPREXPANDX04
AND #%11101111
STA ZPSPREXPANDX04

LDA ZPSPREXPANDY04
AND #%11101111
STA ZPSPREXPANDY04

LDA ZPSPRMSB
AND #%11101111
STA ZPSPRMSB

LDA ZPSPRMCMMODE
AND #%11101111
STA ZPSPRMCMMODE

Each 3 instruction cluster in the above code snippet takes 8 CPU cycles, so 8 x 4 = 32 cycles, which is approximately half of a raster line (63 cycles on PAL, 65 on NTSC).

But by using the illegal opcode SAX (aka AXS or AAX, perhaps historically confusingly also known as, or conflated with, SHA), you can rewrite this as follows (and I use this method a lot in Parallaxian):

; Define the "mask" by storing it in the x-register
;
LDX #%11101111

LDA ZPSPREXPANDX04
SAX ZPSPREXPANDX04

LDA ZPSPREXPANDY04
SAX ZPSPREXPANDY04

LDA ZPSPRMSB
SAX ZPSPRMSB

LDA ZPSPRMCMMODE
SAX ZPSPRMCMMODE

This way we only need to set one mask and the same workload now takes 2 + (6 x 4) = 26 cycles, which saves 6 cycles from the standard opcode method; so, the more things you use the mask for, the more cycles you can save.

SAX thus performs an AND operation between the A-register and the X-register - without affecting the contents of either - and then stores the result in the target memory location (in the above examples, that would be in the relevant Zero Page variables).

So, in situations where you need to save every cycle of raster time, this kind of application of illegal opcodes is very desirable.

Further reading:

  1. Codebase64 resource on illegal opcodes.
  2. Pagetable article: How MOS 6502 Illegal Opcodes really work.
  3. PDF e-book: No More Secrets.

permalink to this post

What Makes This Game Great: Nebulus

Posted on 14-Dec-2020 by Kodiak

Originality in any gaming genre is as rare as the proverbial hen's teeth, but with Hewson's release in 1987 of Nebulus, a truly unique, quirky (in a good way) and wonderfully playable game for the Commodore 64 entered the annals of 8-bit gaming lore and, who knows, probably helped the developer pay off his mortgage, such were its sales levels across a host of platforms.

So let's take a closer look at what makes Nebulus on the C64 great!

Nebulus
  • Its fundamental gameplay totally rocks; at the crux of this is the intuitive control of the main character, an essential ingredient in attaining immersive symbiosis with the game environment.
  • It's addictive, because building on the core movement mechanics, there are many satisfying interactions along the way, chiefly based on avoiding contact with hostile objects, but also on encounters with native-feeling game-world obstacles, lifts, steps and doorways leading to the other side of the tower, etc., in the pursuit of progress, which, in the form of advancing to completely new locations (i.e. additional towers), draws the player to probe further into the game world.
  • Fairness: It has a reasonable, if inconsistent (which I explain below), difficulty curve which right away lifts it head and shoulders above 90% of C64 games, such as the vast bulk of Ocean's huge portfolio of slickly packaged, overpriced rubbish; this fairness is underlined by the relative ease with which additional lives in the game may be obtained.
  • It has a great and - for its era - almost unmatched interlude level in the form of a submarine shoot-em-up sequence with parallax scrolling.
  • Its graphics, in particular the rotating tower effect, were state of the art and even now remain top notch, having stood the test of time very well, unlike many popular titles from the mid-to-late 1980s.
  • Its bubbly, watery sfx endow the game with distinctive audio as well, which is another way in which it stands out from the crowd.
  • It has a sprinkling of little, barely noticeable snippets of finesse; for example, the shadow underneath the submarine in the interlude gets darker the closer you get to the seabed. Slick.
Nebulus Interlude

With such an abundance of lavish praise, surely this game is close to perfection?

Well, no... Not quite.

It has a few blemishes which we'll consider now, as I turn to list the things I would do differently (speaking as a C64 game developer myself):

  • Though few and very far between, it suffers from that staple annoyance that plagues many platform games: pixel-perfect jumps... So I would remove those rare instances.
  • You know how I said the controls are intuitive? Well, for me personally, they would be even more so if we didn't have to press fire + up to jump; up alone would suffice.
  • Nebulus has two coding bugs, the first of which sees the occasional mistiming of the “flying spanner attack”, but this only emerges as an issue on very rare and unpredictable occasions (hence it would have been hard to debug and either missed or quietly swept under the carpet, so to speak...) but I would like that fixed!
  • A worse bug is that the entire sprite movement and scrolling (in fact, the whole system) slows down under high CPU load, notably at the start of level 6 ("The Swimmer's Delight"), which is a less excusable bug than the previous one and could and should have been resolved by better coding or optimisation.
  • The levels are not strictly ordered in difficulty ranking; for example, in my experience, level 5 is much harder than most of the others that follow, so that's another thing I would want addressed.
  • I would like it to have in-game music as an option, but this may have been difficult given the already heavily tasked CPU and probable RAM constraints... a modern cartridge reboot would overcome the RAM issue though and the advances in reducing raster time over the years might also make it viable.
  • A time-addition pick-up would be a welcome new feature.
  • One final wish-list improvement would be a bit more variety in the enemy sprite designs, but again, this likely boiled down to RAM limitations on what was a single-load game.


I would have to concede, however, that all of the above are minor issues and Nebulus, despite them, was and remains an enduring classic on the Commodore 64.

And yes, would you believe me if I said its main sprite, the little frog-like creature, had a direct influence on Parallaxian?

The way he rotates as he turns inspired the animation frames for the main craft in my game as it turns, so that's perhaps a somewhat surprising connection with Nebulus.

You can download Nebulus here.

Similar posts:

What Makes This Game Great: Mayhem in Monsterland

Game Wishlist: Uridium II / Next

permalink to this post

Hot in the C64 Scene

On Twitter: Runn n' Gunn WIP Latest

On Twitter: Stoker WIP Latest

On YouTube: Commodore Building Walkthrough

With Bil Herd.

Jan 10, 2021



On YouTube: WOR2ONE

Gameplay preview.

Jan 10, 2021



On YouTube: Gravity Duck

New C64 Game WIP.

Jan 10, 2021



On YouTube: My Day on the Highway

First Look.

Jan 10, 2021



On the Web: Sprite Invaders

New Space Invaders style game: Sprite Invaders

Sprite Invaders

On the Web: Ditheridoo V1.0

New multicolour bitmap editor: Ditheridoo V1.0

Ditheridoo V1.0

On the Web: Lovecats Demo

UNMISSABLE!: Lovecats Demo

Lovecats Demo

On Twitter: The Wild Wood (Game WIP)

On Twitter: Muddy Racers (Game WIP)

On Twitter: Monstro Giganto

Help Make Parallaxian Happen

If you really want to help get Parallaxian finished, kindly support the continuation of its development via one of the options below, so that I can devote the necessary time to it; it's a truly huge project and although the toughest technical challenges have been completed, there remains a lot of hard work to get it over the finishing line.

Way #1: Start Your Amazon Sessions via Kodiak64.com (Costs You Nothing!)


This one should be the easiest because it's a painless and indirect way to help me for something you would be doing anyway, regardless of my request for help.

So how does it work?

Well, it makes no difference what you're buying on Amazon... whether it's a garden gnome for your dad, jewellery for your wife, the new C64 Maxi for yourself or an obscure first edition by an even more obscure 17th century Belgian poet for someone you very much dislike.

The point is, if you buy anything on Amazon, even your groceries, I will automatically receive a commission as long as your Amazon session begins as a click on an Amazon product banner on this website or just on any generic Amazon link on this website (such as those listed below):

amazon.co.uk

amazon.com

amazon.it

amazon.de

amazon.se


So, you would make your daily visit to Kodiak64.com to check out what's new and then, while you're here, enter Amazon via one of those links to order whatever you were planning on buying anyway, thus doing your bit to advance Parallaxian's development.

Simple!

Way #2: Purchase Merch from the Kodiak64 Shop


Hosted externally (for now) on Teespring, the Kodiak64 shop features limited edition C64-related merchandise, for which I have mostly set my margin at 15% of the retail price (to keep it as low as worthwhile).

6502 LOVE


I intend to change designs every month to keep things fresh, albeit with the core themes remaining Commodore 64 centric.

Way #3: PayPal Donation


Finally, at the highest rung of the altruism ladder among the 3 options, maybe you could consider a small, recurring monthly donation (and depending on your tax situation, you might even be able to designate it as a charitable donation rather than let the taxman have it).

And don't worry, you can cancel at any time... but in the meantime, it would be a welcome contribution, however petite.

Oh, and as a special thank you, all who do this will be credited in the game (unless you opt out of it if you have the same kind of incognito hermit tendencies I do).



Help Kodiak64 for FREE!

Click here to read how.

Share this page

Kodiak64 Newsletter

100% free, 100% spam-free!

(You can view a sample here).