aboutsummaryrefslogtreecommitdiff
Commit message (Collapse)AuthorAgeFilesLines
* Let SUSE's coin to appear at stage 16Miquel Sabaté Solà2026-04-052-2/+2
| | | | | | | We want every shuttle kind to appear at least once before rewarding the player with the coin. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Add the rest of shuttle kinds into the CHR fileMiquel Sabaté Solà2026-04-053-35/+33
| | | | Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Add a table with tile IDs for shuttle partsMiquel Sabaté Solà2026-04-033-20/+56
| | | | | | | | | This will allow us to select the proper shuttle depending on 'Globals::zp_shuttle_kind'. Hence, now only the actual shuttle parts on the CHR file are missing, which is why I left a couple of TODOs on the table itself. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Cycle the kind of shuttle to be usedMiquel Sabaté Solà2026-04-025-6/+22
| | | | | | | | | | In preparation to having multiple kinds of shuttles as in the original game, introduce the 'Globals::zp_shuttle_kind' variable, which is just a helper value by masking out the 'Globals::zp_level' variable. This in turn will be the index for selecting which tile IDs for each shuttle part. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Remove lowest part of the shuttle from spritesMiquel Sabaté Solà2026-04-023-35/+35
| | | | | | | | | On the sprites tileset, the lowest part of the shuttle is not needed since that is only used as a sprite on take off, but then the firing variant should be picked instead. Remove it from the CHR file and update tile IDs. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Fix wrong initialization on shuttle reassembleMiquel Sabaté Solà2026-04-022-6/+10
| | | | | | | | The shuttle should be reassembled every 4 stages, not 8. I did not remember well how this worked and I jumped ahead with the conveniency of the 'Globals::zp_level_kind' variable. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Add a small signature in ROM spaceMiquel Sabaté Solà2026-04-022-1/+2
| | | | Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Fix overwrite issues when adding scoresMiquel Sabaté Solà2026-03-284-38/+45
| | | | | | | | | | | | | | | | | | | | | | | The add_to_player() function relied on parameters to be passed on the 'Globals::zp_tmpX' variables, but that's just plain stupid. First, because these memory addresses are not meant for arguments; but most importantly, because callers actually needed some of these values before calling this function. Hence, everything went into chaos and sprites began to act wrongly in all sorts of random ways. Moreover, some of the callers also needed a guarantee on either the 'x' or the 'y' registers. Since this wasn't always feasible, we needed to store/load these registers' values case by case. All in all, now add_to_player() accepts only one argument via the 'y' register (which callers already knew it was going to be messed with). The value on 'y' has to be set via some helper constants. As a cherry on top, this not only fixes a nasty bug, but it also makes things more performant and with less code. Fixes: 63ef73de3bdd ("Update scores on screen") Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Add copyright notices on the title screenMiquel Sabaté Solà2026-03-275-48/+50
| | | | Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Save the high score after game overMiquel Sabaté Solà2026-03-274-5/+103
| | | | Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Update scores on screenMiquel Sabaté Solà2026-03-259-6/+114
| | | | Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Add support for adding scoresMiquel Sabaté Solà2026-03-254-3/+176
| | | | Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Don't use dark green for itemsMiquel Sabaté Solà2026-03-242-26/+26
| | | | | | It's a really bad color given a black background. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Decrease a bit the items' timerMiquel Sabaté Solà2026-03-241-1/+1
| | | | | | While playtesting I found the given timer's value a bit too much. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Use the 'nmi_' prefix for NMI-only functionsMiquel Sabaté Solà2026-03-244-15/+9
| | | | Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Implement the "take off" animationMiquel Sabaté Solà2026-03-238-116/+498
| | | | | | | | This is the animation that is done after clearing a stage. Moreover, and for the first time since I started development, now we can move into the next level as intended from the game's design. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Try to initialize enemies on unique Y coordinatesMiquel Sabaté Solà2026-03-225-3/+40
| | | | | | | | | | | | That is, our PRNG algorithm is so stupid that sometimes it cycles into the same value multiple times. While play testing, sometimes we were so unlucky that we got all enemies on the same Y screen coordinate. As funny as these situations can be, this shouldn't happen, so I have introduced an (awesomely named) function that makes a harder effort at finding a unique random number. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Restart the blinking animation after player's deathMiquel Sabaté Solà2026-03-202-3/+9
| | | | | | | | I believe this case was broken since the very beginning when I implemented it in commit b891997ab597 ("Add a blinking animation on player selection"). Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Center "game over (coin)" textMiquel Sabaté Solà2026-03-204-31/+32
| | | | | | Moreover, add a "!" character at the end. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Don't rely on the 'y' register in Over::handle()Miquel Sabaté Solà2026-03-202-4/+5
| | | | | | | Some of the functions being called from within will in fact tamper with this value. Hence, use the free 'Globals::zp_arg3' variable. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Set the proper "game over" flagMiquel Sabaté Solà2026-03-202-3/+5
| | | | Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Push the value from Over::handle() to the stackMiquel Sabaté Solà2026-03-201-2/+2
| | | | | | | Setting 'Globals::zp_tmp0' with it is potentially dangerous given how volatile this temporary memory address is. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Add support for the SUSE coinMiquel Sabaté Solà2026-03-208-36/+152
| | | | | | | | This is a coin that appears after going through a first cycle of levels and that allows the player to get a different game over screen than usual. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Remove stale commentMiquel Sabaté Solà2026-03-191-1/+1
| | | | Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Let fuel tanks be delivered separatelyMiquel Sabaté Solà2026-03-183-4/+32
| | | | | | | | | Fuel tanks follow a different logic than regular items, in which they should be delivered almost instantaniously whenever they are needed. Hence, a new (much shorter/snappier) timer is provided for fuel tanks alone. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Increase the item's timer for non-dev buildsMiquel Sabaté Solà2026-03-181-1/+5
| | | | | | Set a more realistic value for the timer for non-dev builds. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Fix the high byte for the timer initializationMiquel Sabaté Solà2026-03-181-1/+1
| | | | | | | | | | | | | | | | In my infinite wisdom, in order to compute the high byte of the 16-bit timer I masked away the most significant byte, but then shifted right only for a nibble instead of a full byte. This went mostly unnoticed as the value I'm setting for the timer actually falls below of what a byte can represent and, thus, the high byte was always zero. But this was noticeable when I was testing larger numbers which, unsurprisingly, turned out to be _huge_. Fix this by shifting right a full byte instead of a mere nibble. Fixes: cf3a0c963225 ("Implement falling items") Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Expand documentation on items.sMiquel Sabaté Solà2026-03-181-10/+29
| | | | | | | The format of buffers are somewhat stable now, so we can expand the documentation to write down what I've finally settled on. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Use specific variables for cached player's tile coordinatesMiquel Sabaté Solà2026-03-183-9/+16
| | | | | | | | | Before this commit we were using the zp_argX variables, but this can go wrong, and more so considering other functions like background collision checking also use these variables. All in all, since we have plenty of RAM to spare, let's just allocate a new set of bytes just for that. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Add missing 'Items::zp_current_tiles' updatesMiquel Sabaté Solà2026-03-182-3/+16
| | | | | | | Collisions are based on this, so we better not forget updating these values. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Avoid a jmp by moving update_sprites()Miquel Sabaté Solà2026-03-162-19/+19
| | | | Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Improve the accuracy of the dropping zoneMiquel Sabaté Solà2026-03-162-10/+8
| | | | | | | | | | We were abusing on tile collision for this, and it wasn't exact. Not only that, but if the player was fast enough, sometimes the item wouldn't drop as the accelaration would pass through that zone. Avoid that by simply using regular screen coordinates, which aren't too hard to check in this case. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Wait for items to fall before changing screenMiquel Sabaté Solà2026-03-165-106/+138
| | | | | | | | | | | More specifically, whenever the player dies and we need to reset the screen, wait for items to fall in the same way as we do for explosions to disappear. This also brought with it some other changes like removing sprite reset on screen initialization. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Account for items switching to following the player in mid-airMiquel Sabaté Solà2026-03-152-5/+16
| | | | Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Update the shuttle as fuel is getting inMiquel Sabaté Solà2026-03-152-10/+80
| | | | | | | | | | Just like in the original, the shuttle turns purple for each fuel tank. That being said, due to the restriction from the NES/Famicom on updating background tile attributes, a "half-filled" strategy is being used here to convey the same idea for a total of 6 fuel tanks to be delivered. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Implement falling itemsMiquel Sabaté Solà2026-03-137-96/+403
| | | | | | | | | Every now and then an item will fall and, as in the original game, a fuel tank will be delivered whenever needed. There are still some things left out for later changes, like picking up items mid-air, or background effects for the rocket being filled with fuel. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* debug: Add another value for debugging purposesMiquel Sabaté Solà2026-03-131-0/+3
| | | | Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Add missing items from the assetsMiquel Sabaté Solà2026-03-122-30/+30
| | | | Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Join 'zp_moved_out' and 'zp_pause_toggle'Miquel Sabaté Solà2026-03-123-24/+32
| | | | | | | It was wasteful, and it was there just because of my lazyness. Let's be a bit less careless. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Initial implementation for itemsMiquel Sabaté Solà2026-03-1112-46/+720
| | | | | | | | | | This now only supports the appearance of shuttle parts and the fact that the player can collect them at a very specific order and drop them so to stack up the final shuttle. This is of course just the skeleton and there's a bunch of TODO's left. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Don't skip the title page on a DEV buildMiquel Sabaté Solà2026-03-112-16/+7
| | | | | | | Just bumping up timers is enough, and we don't get weird "this does not load _exactly_ as the final game" situations. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Rename init_x() to init_enemy_x()Miquel Sabaté Solà2026-03-111-4/+4
| | | | | | | This is just a minor fix for an overstep from commit 270d60d58d3e ("Rename scoped variables without being redundant"). Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Fix a slight misalignment when spreading out bulletsMiquel Sabaté Solà2026-03-111-0/+1
| | | | Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Add a mock cover imageMiquel Sabaté Solà2026-03-112-1/+3
| | | | | | This image can later be used for cartridge labels and such. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Apply a correction on enemy movement for PALMiquel Sabaté Solà2026-03-113-43/+93
| | | | | | | | | | We cannot just "inc"/"dec" for enemy movement, but we have to apply an overstep on PAL every 5 frames in order to be equivalent to the NTSC version. This has been abstracted away on a macro that just does "inc"/"dec" on NTSC, but does this proper "adc"/"sbc" instructions with a helper memory region which is updated every 5 frames. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Remove outdated asan:ignore commentsMiquel Sabaté Solà2026-03-101-2/+2
| | | | | | This was just fixed on nasm, so it's no longer needed. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Add a blinking animation on player selectionMiquel Sabaté Solà2026-03-087-35/+151
| | | | Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Support reading from the second controllerMiquel Sabaté Solà2026-03-088-41/+41
| | | | Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* Skip initialization of first nametable after game overMiquel Sabaté Solà2026-03-081-1/+12
| | | | Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
* State game over only when all players are deadMiquel Sabaté Solà2026-03-086-34/+81
| | | | | | | This is a bit contrary to the original game, where each player would get its own "Game over" event. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>