Rockfall: why does this game crash in 128 mode?

The place for codemasters or beginners to talk about programming any language for the Spectrum.
equinox
Dynamite Dan
Posts: 1052
Joined: Mon Oct 08, 2018 1:57 am
Location: SE England

Rockfall: why does this game crash in 128 mode?

Post by equinox »

Hi guys. Merry Christmas etc. and sorry for being aggressive last time, I know I'm an angry drunk. I don't mean to be such a jerk. Sorry Gareth!

But don't worry! I now have a Z80-ish question relating to the game "Rockfall" published on Crash magazine cover tape in the '90s. It's a sort of "Boulder Dash" clone where you push rocks and collect jewels. Please note: I have very rudimentary asm understanding (registers, memory) but I can't generally read or write Z80.

So: I love this game Rockfall, I've hacked it apart (to the extent that I can, being fairly ignorant in Z80) and recently I have produced 60 levels — a mixture of my 1990s leftovers, and some new puzzles — and I have also produced six sets of new graphics (arctic, desert, etc.). Back in the day, I even got permission from the author (Ian Collier: I think he's a sysadmin at Oxford University these days) to do a sequel to his game.

I have broken this game apart to the point where I can insert my own levels and graphics. The original game had 28 levels. I have 60 new levels, and six new graphics sets (plus metadata): and I want to add a little menu/control system too; so the idea is to have six separate sets of ten levels, and use the remaining space (18 * 1024 bytes) for metadata and control menu. I know the start addresses and where things should go.

Now there are two options. A horrible multiload of six files of ten levels each, OR (my preference) a 128K-only game that's a single load. I know it will fit: I have done the arithmetic. However: for reasons I don't understand, Rockfall always crashed if you load it in 128 mode. It usually seems to crash when it first tries to play an AY sound effect (this is typically when you collect the final jewel that opens the exit to a level, "ching!"). The game always had to be loaded in 48 mode, even though it plays AY sound on a 128.

So what's wrong with it? How can I diagnose this? How can I fix it? Is there a way to pack my mod into a single 128K load, instead of being forced into a 48K multiload due to this weird bug? If anyone wants to diagnose the issue, I can provide snapshot or RZX recording.

SHORT VERSION: If you don't care about the above: is there anyone who can look at my Z80 or RZX file and explain why it crashes when I pick the last jewel? Remember, this is from the original Rockfall (1990s) and I'm not asking you to debug my new code.
equinox
Dynamite Dan
Posts: 1052
Joined: Mon Oct 08, 2018 1:57 am
Location: SE England

Re: Rockfall: why does this game crash in 128 mode?

Post by equinox »

For example why does this crash? What is happening?
(recording of Rockfall Designer tool)

https://cl4.org/__2023-12_rfdesigner_death.rzx
User avatar
ketmar
Manic Miner
Posts: 713
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: Rockfall: why does this game crash in 128 mode?

Post by ketmar »

1. force 48 mode in loader.
2. use better data compression for levels.
3. problem solved. ;-)

sorry, i may look at it later. i bet this is either some lazy port access, or it simply needs 48k rom properly switched in.
User avatar
bob_fossil
Manic Miner
Posts: 661
Joined: Mon Nov 13, 2017 6:09 pm

Re: Rockfall: why does this game crash in 128 mode?

Post by bob_fossil »

equinox wrote: Tue Dec 19, 2023 1:47 am For example why does this crash? What is happening?
(recording of Rockfall Designer tool)

https://cl4.org/__2023-12_rfdesigner_death.rzx
When you collect the diamond, the code enables IM2 and jumps to an interrupt function at $fa01 which looks like it's sending data to the AY registers to do the sound effect. When the interrupt routine returns, it comes back to address $ee5a (previous instruction was HALT). There's some strange code which then gets a value from port $38 and then checks the first byte at address 0. If the normal ROM is there this will be $f3. The code returns if this is true or does some other code - which calls $220 which doesn't appear to be a valid ROM address. Maybe some sort of SoftROM / monitor checking code?

This code seems to be causing a bank switch which then pages out the memory which is currently being executed which doesn't end well. If you do:

Code: Select all

POKE 61019,201
then the sound effect works without crashing. The game crashes when you enter the exit though.
equinox
Dynamite Dan
Posts: 1052
Joined: Mon Oct 08, 2018 1:57 am
Location: SE England

Re: Rockfall: why does this game crash in 128 mode?

Post by equinox »

bob_fossil wrote: Tue Dec 19, 2023 11:10 am When you collect the diamond, the code enables IM2 and jumps to an interrupt function at $fa01 which looks like it's sending data to the AY registers to do the sound effect. When the interrupt routine returns, it comes back to address $ee5a (previous instruction was HALT). There's some strange code which then gets a value from port $38 and then checks the first byte at address 0. If the normal ROM is there this will be $f3. The code returns if this is true or does some other code - which calls $220 which doesn't appear to be a valid ROM address. Maybe some sort of SoftROM / monitor checking code?

This code seems to be causing a bank switch which then pages out the memory which is currently being executed which doesn't end well. If you do:

Code: Select all

POKE 61019,201
then the sound effect works without crashing. The game crashes when you enter the exit though.

Thanks bob, this is very detailed, but it doesn't help me as a clueless hacker -- i.e. why was the AY sound effect done on IM2 in the first place (why not do it synchronously) -- and also why was it done wrong and broken. Surely the guy tested it? (Or not: Rockfall never worked properly in 128 mode.)
My main concern is trying to get this thing working in 128 mode so I can load extra levels from the memory banks. If I can't work it out by OOHHHH February then I will just make a Bas**rd multiload.
But if there's any suggestion like "it works in this weird way AND ALSO he should have coded it this way" (maybe a register typo) that would be beautiful.
User avatar
Seven.FFF
Manic Miner
Posts: 744
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Rockfall: why does this game crash in 128 mode?

Post by Seven.FFF »

Port $38 is an even port, so the ULA will respond even if an addon is plugged in externally. And if the upper address byte is not explicitly put on the bus, it won’t even get a consistent keyboard read. The best you’d get is a sample of the EAR signal.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
bob_fossil
Manic Miner
Posts: 661
Joined: Mon Nov 13, 2017 6:09 pm

Re: Rockfall: why does this game crash in 128 mode?

Post by bob_fossil »

http://www.thefossilrecord.co.uk/wp-con ... all128.zip

This should work when loaded from 128k now. The original loader was one large CODE block loaded from 16384 which stomped over the printer buffer which 128 BASIC uses for paging. I've also applied my patch for the sound effects.
User avatar
ketmar
Manic Miner
Posts: 713
Joined: Tue Jun 16, 2020 5:25 pm
Location: Ukraine

Re: Rockfall: why does this game crash in 128 mode?

Post by ketmar »

the exit crash is due to the code at $EAD4: it loads SP from the system variables for some reason. to patch the designer, it is enough to do:

Code: Select all

POKE 60116, 225
POKE 60117, 225
this adjusts SP enough to safely return.

in the real game SP value may be different, though. i don't have enough patience to finish the first level to check it. ;-)
equinox
Dynamite Dan
Posts: 1052
Joined: Mon Oct 08, 2018 1:57 am
Location: SE England

Re: Rockfall: why does this game crash in 128 mode?

Post by equinox »

bob_fossil wrote: Tue Dec 19, 2023 1:15 pm http://www.thefossilrecord.co.uk/wp-con ... all128.zip

This should work when loaded from 128k now. The original loader was one large CODE block loaded from 16384 which stomped over the printer buffer which 128 BASIC uses for paging. I've also applied my patch for the sound effects.
Thanks but you seem to have screwed something up here. I get errors like "J Invalid I/O device" when simply playing the game normally. And once it crashed/hung with no way to get out.
AndyC
Dynamite Dan
Posts: 1409
Joined: Mon Nov 13, 2017 5:12 am

Re: Rockfall: why does this game crash in 128 mode?

Post by AndyC »

Wouldn't it be easier just to recreate the levels in the (vastly superior) Earthshaker? It definitely loads fine on a 128. :lol:
User avatar
PROSM
Manic Miner
Posts: 476
Joined: Fri Nov 17, 2017 7:18 pm
Location: Sunderland, England
Contact:

Re: Rockfall: why does this game crash in 128 mode?

Post by PROSM »

bob_fossil wrote: Tue Dec 19, 2023 11:10 am [...]
There's some strange code which then gets a value from port $38 and then checks the first byte at address 0. If the normal ROM is there this will be $f3. The code returns if this is true or does some other code - which calls $220 which doesn't appear to be a valid ROM address. Maybe some sort of SoftROM / monitor checking code?
That code is checking for the presence of a Currah uSpeech module - putting $0038 on the address bus (whether as an I/O or memory read) toggles whether the uSpeech ROM is paged in over the Sinclair ROM. See this page (particularly the "reverse engineering" section, which covers this exact routine): https://maziac.github.io/currah_uspeech_tests/
All software to-date
Working on something, as always.
User avatar
bob_fossil
Manic Miner
Posts: 661
Joined: Mon Nov 13, 2017 6:09 pm

Re: Rockfall: why does this game crash in 128 mode?

Post by bob_fossil »

equinox wrote: Tue Dec 19, 2023 8:13 pm Thanks but you seem to have screwed something up here. I get errors like "J Invalid I/O device" when simply playing the game normally. And once it crashed/hung with no way to get out.
I've re uploaded my .tap file with ketmar's additional POKES. Completed the 1st level okay but it still bombs out back to BASIC after you lose a life. Looks like the extra POKES which do 2 pop hl instructions work okay when you complete the level but pop one too many addresses off the stack when you get killed.
User avatar
bob_fossil
Manic Miner
Posts: 661
Joined: Mon Nov 13, 2017 6:09 pm

Re: Rockfall: why does this game crash in 128 mode?

Post by bob_fossil »

I've re-uploaded a version which no longer crashes when you lose a life. When you lose a life the code sets the stack pointer to a value held in $5b88. On 48k machines this address is inside the printer buffer area at $5b00 which is a safe area to store your own data and code. 128 BASIC however uses this area for memory paging and additional system variables. This wouldn't normally be an issue but Rockfall is a mix of BASIC and machine code - the front end is BASIC so it's actively being used. I've patched the code at $ead4 to just load the stack pointer to the the value it's expecting from $5b88 ($69e8). The author of this game went to a lot of trouble - unintentionally I'm sure - to make sure it wouldn't work on a 128k machine.
equinox
Dynamite Dan
Posts: 1052
Joined: Mon Oct 08, 2018 1:57 am
Location: SE England

Re: Rockfall: why does this game crash in 128 mode?

Post by equinox »

AndyC wrote: Tue Dec 19, 2023 10:45 pm Wouldn't it be easier just to recreate the levels in the (vastly superior) Earthshaker? It definitely loads fine on a 128. :lol:
I take your point, but this isn't about what is best. I love Rockfall; it was my first Boulder Dash-like experience; I was one of the Crash magazine readers who contributed levels to Rockfall II; and it has all its own little quirks and oddities, which I appreciate.
And of course you can't just "recreate levels" because the exact rules of physics and gravity differ between games.

Earth Shaker is great though (especially the weird sound effects, which are some of the best ever heard on a Speccy). But don't derail my Rockfall crash thread.
equinox
Dynamite Dan
Posts: 1052
Joined: Mon Oct 08, 2018 1:57 am
Location: SE England

Re: Rockfall: why does this game crash in 128 mode?

Post by equinox »

bob_fossil wrote: Thu Dec 21, 2023 10:40 am I've re-uploaded a version which no longer crashes when you lose a life. When you lose a life the code sets the stack pointer to a value held in $5b88. On 48k machines this address is inside the printer buffer area at $5b00 which is a safe area to store your own data and code. 128 BASIC however uses this area for memory paging and additional system variables. This wouldn't normally be an issue but Rockfall is a mix of BASIC and machine code - the front end is BASIC so it's actively being used. I've patched the code at $ead4 to just load the stack pointer to the the value it's expecting from $5b88 ($69e8). The author of this game went to a lot of trouble - unintentionally I'm sure - to make sure it wouldn't work on a 128k machine.
This seems to work -- and I very much appreciate your time looking at it. Yes, Rockfall 1 has some underlying BASIC (Rockfall 2 doesn't) and there's a lot of LET s$="(yuuu) (diii)eddd" lol to support the Currah speech. There is also one particular Currah speech that plays when you get the last jewel (and I suddenly understand where the technical problem is), saying something like "level complete" (but really meaning "exit open, you still have to get there").

Thanks again, Bob, this is great. Could you possibly summarise the changes (byte-wise), because I need to take a Rockfall 1 "engine" and patch it, basically. For example "start at 0xZZZ and replace these four bytes".
equinox
Dynamite Dan
Posts: 1052
Joined: Mon Oct 08, 2018 1:57 am
Location: SE England

Re: Rockfall: why does this game crash in 128 mode?

Post by equinox »

For fun: here are preview screenshots of new levels in the six worlds (6 x 10 = 60 levels):
https://ibb.co/WVpLKBT

Wish me luck in getting it all to work. Then we will have a 128K single load. I've also designed the levels so that each one has a basic solution PLUS a challenge, which means potentially 60 x 2 = 120 levels. Although the challenges are mostly insane.
User avatar
bob_fossil
Manic Miner
Posts: 661
Joined: Mon Nov 13, 2017 6:09 pm

Re: Rockfall: why does this game crash in 128 mode?

Post by bob_fossil »

equinox wrote: Wed Dec 27, 2023 11:54 pm This seems to work -- and I very much appreciate your time looking at it. Yes, Rockfall 1 has some underlying BASIC (Rockfall 2 doesn't) and there's a lot of LET s$="(yuuu) (diii)eddd" lol to support the Currah speech. There is also one particular Currah speech that plays when you get the last jewel (and I suddenly understand where the technical problem is), saying something like "level complete" (but really meaning "exit open, you still have to get there").

Thanks again, Bob, this is great. Could you possibly summarise the changes (byte-wise), because I need to take a Rockfall 1 "engine" and patch it, basically. For example "start at 0xZZZ and replace these four bytes".

Code: Select all


61019, 201 - stop crash when collecting last diamond (stops call to Currah speech routine by doing a 'ret')

60116, 49  - code was loading SP from value at $5b88 - ld sp, ($5b88) - which isn't valid in 128 BASIC. Replace
60117, 232   with - ld sp, $69e8 - as this is what is what $5b88 contains in 48k mode
60118, 105
60119, 0
My .tap file has these pokes applied to patch the game code for 128 compatibility. The main game code is at address 27136 and is 38400 bytes long, excluding the BASIC frontend.
equinox
Dynamite Dan
Posts: 1052
Joined: Mon Oct 08, 2018 1:57 am
Location: SE England

Re: Rockfall: why does this game crash in 128 mode?

Post by equinox »

Thank you. Incidentally, it might be worth uploading the fixed Rockfall 1 as a "MOD"/hack/whatever-we-call-it to the archive, since it makes the game work better without changing anything. Well, it's a bug fix, a very late bug fix.

Meanwhile I've almost got my 128 version working... There's a new menu system to move between worlds and levels, and keep track of what you have solved, etc. and all kinds of crazy POKEing and PEEKing. Rather hilariously I am essentially writing assembler in BASIC and then compiling it, because I will do absolutely anything other than read that Zaks book. It's interop, baby!

There is still an annoying bug where the "move the start/exit position of the level" tends to dump you rudely in the middle of a wall, and/or crash the game. This is because I suck at arithmetic. I'll get there...

Image
equinox
Dynamite Dan
Posts: 1052
Joined: Mon Oct 08, 2018 1:57 am
Location: SE England

Re: Rockfall: why does this game crash in 128 mode?

Post by equinox »

bob_fossil wrote: Thu Dec 28, 2023 2:42 pm My .tap file has these pokes applied to patch the game code for 128 compatibility. The main game code is at address 27136 and is 38400 bytes long, excluding the BASIC frontend.
Hi Bob: unfortunately I have another question about this, as there is an issue that seems to prevent me from using the fix in my modified version.

Your fixed 128 version works if loaded and played exactly as supplied, within the Rockfall 1 BASIC. However, as you know, I want to use this code within a new and different menu program. So let's start with a minimal scenario for testing. I load and run your fixed game in in 128 BASIC, like this:

Code: Select all

CLEAR 27135: LOAD "RFC" CODE: RANDOMIZE USR 61856: PRINT #1;: RANDOMIZE USR 60312
[The first USR call initialises AY sound. The second one plays the first game level. The PRINT #1; is necessary to make the status line (score, jewels, etc.) appear in the bottom row, as otherwise it gets incorrectly superimposed over the playfield on the main screen.]

The game starts playing. (Default control keys are ZXPL.) Either finish the level (if you can be bothered) or just get killed. You return to BASIC with the expected OK prompt.

Now play the level again:

Code: Select all

PRINT #1;: RANDOMIZE USR 60312
This time, when you come out, you get "B Integer out of range".

I can't work out how to stop this from happening, when I use the code in my own program. And I don't understand why the error doesn't appear the first time you run the code -- or why it only happens in 128 mode and not 48 mode (though that might possibly relate to the PRINT #1 thing, and the fact that the 128 BASIC editor is full-screen while the 48 editor is at the bottom.) The Rockfall 1 BASIC does include some special POKE+USR stuff in line 1010 (immediately after loading) that seems to set up the screen in some way, but if that's what is needed, it doesn't seem to work when I use it in my own program.

I've been hopelessly experimenting with this for ages -- any idea what's wrong?
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Rockfall: why does this game crash in 128 mode?

Post by ParadigmShifter »

Sounds like the magic number needed in H'L' when returning to basic is modified.

Have a look here on the other forum

https://worldofspectrum.org/forums/disc ... y-from-asm

If you know where it returns from and can do this before it returns

LD HL,$2758 ; Restore HL' to the address in SCANNING of the 'end-calc' instruction as per The Complete Spectrum ROM Disassembly (p201)
EXX

that may work.

If you can debug it in an emulator you can probably look in the debugger to see if H'L' is not $2758 when you return to basic?
equinox
Dynamite Dan
Posts: 1052
Joined: Mon Oct 08, 2018 1:57 am
Location: SE England

Re: Rockfall: why does this game crash in 128 mode?

Post by equinox »

ParadigmShifter wrote: Sat Jan 13, 2024 11:16 am If you know where it returns from and can do this before it returns [...]
that may work.
If you can debug it in an emulator you can probably look in the debugger to see if H'L' is not $2758 when you return to basic?
So if I understand correctly: I would need to find the final RET, and replace it with (decimal) bytes 33 88 39 217 201, representing LD HL,$2758; EXX; RET ?

Spectaculator has a debugger and breakpoints but I don't know how I would locate the correct RET, or how I know when it's going to return to BASIC, etc. I am quite clueless with Z80.
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Rockfall: why does this game crash in 128 mode?

Post by ParadigmShifter »

First check whether H'L' has that value or not on return to basic, if it does then the proposed fix will not work. Basic should not modify it at any time (I think) so it should still have same value on return.

As to finding which ret it is could be tricky. If you know it is about to return when you do some action I guess you could put a breakpoint on every RET instruction before you do that?

Or - better idea - you could put a breakpoint in the ROM where the USR function exits which looks to be here in the 48K ROM

https://skoolkid.github.io/rom/asm/34B3.html

at address $34BB

But I don't know if the 128K machine still uses that or not, sorry (48K guy only).

EDIT: Hmm in Spin H'L' seems to be not constant $2758 :( Although it is set to $2758 on exit from a RANDOMIZE USR #### call (when I put a breakpoint at $34BB).

That page in the skoolkit rom disassembly mentions H'L' should be $2758 at that point anyway for a successful return to BASIC. I have seen problems like you mention (strange errors) when I try to return from basic without restoring H'L' to the correct value before anyway which is why I suggested it.

EDIT2: If that is the issue you ay not be able to replace a RET with those opcodes, it is unlikely there will be enough space? You may have to replace several of the bytes before the RET with a JP <some unused space in the code> and at that location you would have to put the instructions you replaced with the JP #### (not including the RET) followed by the patch (which would end with a RET).
AndyC
Dynamite Dan
Posts: 1409
Joined: Mon Nov 13, 2017 5:12 am

Re: Rockfall: why does this game crash in 128 mode?

Post by AndyC »

You probably only need find about 9 bytes somewhere:

Code: Select all

CALL original _usr_address
EXX
LD HL,$2758
EXX
RET
And then just call that in place of whatever the original USR was doing. Could possibly save another byte if the return value in BC doesn't matter at all. That way it shouldn't matter which RET actually returns to BASIC.
Last edited by AndyC on Sun Jan 14, 2024 10:42 am, edited 1 time in total.
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Rockfall: why does this game crash in 128 mode?

Post by ParadigmShifter »

I don't think BC will matter since it is called via RANDOMIZE USR (unless setting the BASIC random seed is important, I doubt it). IY must not be modified of course (should have value $5C3A probably)
User avatar
ParadigmShifter
Manic Miner
Posts: 671
Joined: Sat Sep 09, 2023 4:55 am

Re: Rockfall: why does this game crash in 128 mode?

Post by ParadigmShifter »

I think the RET I said to put a breakpoint on is where it does the call rather than the return, the return seems to be at the end of this routine

https://skoolkid.github.io/rom/asm/2D2B.html

at $2D3A

PUSH BC
RET

has the effect of doing a CALL BC
Post Reply