Bank 7 corruption while loading in Plus2A mode

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
User avatar
jorgegv
Well known member
Posts: 312
Joined: Wed Nov 18, 2020 5:08 pm

Bank 7 corruption while loading in Plus2A mode

Post by jorgegv »

Hi guys, I have the following problem:
  • A 128K game works fine in 128K/Plus2 mode, but crashes in Plus2A mode.
  • The problem has been traced as a corruption of a single byte at position $D600 in Bank 7 (offset $2600 from $C000).
  • The data in that address is compressed, this change makes it decompress incorrectly, and ultimately crashes the game in Plus2A mode.
  • The detection has been done like this: game loaded in 128K mode, and just after loading the game (nothing is running), a snapshot is taken. The same, but in Plus2A mode, again a snapshot is taken.
  • When the interesting banks in both snapshots are compared there is a single byte different in BANK7, at address $E600.
  • Loading the game in Plus2A mode under Fuse and with a write breakpoint at BANK7, offset $2600, the breakpoint it is triggered during the load; it is shown that ROM3 is mapped, and it's forcibly writing to address $E600 (hardcoded in ROM), with BANK7 mapped. The instruction doing this is at address $389A in ROM3. This is what is corrupting the game.
  • Doing the same test but in 128 mode, with the same breakpoint, shows no writing at that address during the load (does not trigger the BP), and no corruption happens.
  • The basic loader is loading the banks by using a trivial bank switching routine in assembler at $8000. This routine only uses port 7FFD to switch banks, leaving port 1FFD untouched. Also, this routine takes into account the current BANKM value, and only modifies the bank number (3 low bits) leaving the remaining bits untouched. there
  • According to documentation, "Bank 7 contains editor scratchpads and +3DOS workspace" (https://worldofspectrum.org/faq/referen ... erence.htm)
Why would any ROM write directly to D600 in bank 7 during program load? ROM3 is supposed to be the 48 ROM, right? Any ideas?
User avatar
dom
Well known member
Posts: 2308
Joined: Sun Jul 15, 2007 10:01 pm

Re: Bank 7 corruption while loading in Plus2A mode

Post by dom »

From memory the interrupt does some stuff up in page 7 - there’s a timer to turn off the disk motor.

Does loading in spectrum mode solve it?
User avatar
dom
Well known member
Posts: 2308
Joined: Sun Jul 15, 2007 10:01 pm

Re: Bank 7 corruption while loading in Plus2A mode

Post by dom »

See the disassembly here: https://github.com/ZXSpectrumVault/rom- ... .asm#L9212

Poking iy+1 should skip that check and prevent the corruption.
User avatar
jorgegv
Well known member
Posts: 312
Joined: Wed Nov 18, 2020 5:08 pm

Re: Bank 7 corruption while loading in Plus2A mode

Post by jorgegv »

THat worked indeed! I added the following to my bankswitch routine:

Code: Select all

                res     4,(iy+1)        ; reset bit 4 of FLAGS to disable
                                        ; floppy motor check while loading
                                        ; (avoids data corruption in BANK7)
And I also move my DI to be before the RES instruction, and now the corruption is no more!

Thanks Dom, this was a tough one for me!

BTW, I was thinking: should this be added to the banked loader routine in CRT? I have checked and there is no provision for this, meaning that anyone who uses BANK7 up to address $E600 will get corrupted data at that address when loading in +2A/+3 machines, right?
User avatar
jorgegv
Well known member
Posts: 312
Joined: Wed Nov 18, 2020 5:08 pm

Re: Bank 7 corruption while loading in Plus2A mode

Post by jorgegv »

Indeed someone already did this before: https://spectrumcomputing.co.uk/forums/ ... 368#p63368
User avatar
dom
Well known member
Posts: 2308
Joined: Sun Jul 15, 2007 10:01 pm

Re: Bank 7 corruption while loading in Plus2A mode

Post by dom »

jorgegv wrote: Tue Feb 27, 2024 12:14 pmBTW, I was thinking: should this be added to the banked loader routine in CRT? I have checked and there is no provision for this, meaning that anyone who uses BANK7 up to address $E600 will get corrupted data at that address when loading in +2A/+3 machines, right?
Good point, I've added it in to the tape loader code.
User avatar
jorgegv
Well known member
Posts: 312
Joined: Wed Nov 18, 2020 5:08 pm

Re: Bank 7 corruption while loading in Plus2A mode

Post by jorgegv »

Just a little update on this one, for future reference:

After I had done the changes indicated above before to my BASIC+ASM loader, I was still having sporadic crashes (but extrenely infrequent), due again to the same issue: corruption at 0xD200 in bank 7. The issue was extrenmely rare, but I managed to get some crashes in +2a mode again.

I even modified the ASM bank switcher routine to leave interrupts disabled, but I verified that on the return path to BASIC, interrupts were reenabled again by BASIC itself (seems logical). So, depending on pure luck (or lack of), very ocasionally an interrupt would trigger just after switching to bank 7, and corrupt the dreaded byte at 0xD200 again.

So finally I implemented the real solution: do away with the BASIC bank loader, and instead do the full switch-bank & load-data dance in assembler, and with interrupts disabled. LD_BYTES does not reenable ints (I had already verified that also), so now everything seems OK (for good).

So now my tool just generates a full ASM loader, with a simple BASIC loader to just do a RAND USR to it (instead of generating a BASIC program with a bank switching helper and switching banks in BASIC).

I took good note of the Classic multiple bank loader in Z88DK's zx_tapeloader.asm and based my code on it.
User avatar
dom
Well known member
Posts: 2308
Joined: Sun Jul 15, 2007 10:01 pm

Re: Bank 7 corruption while loading in Plus2A mode

Post by dom »

Ooo, that's quite nasty. Looking at the disassembly the ROM0, ROM1 and ROM2 interrupt routines don't check the bit. I'm guessing that ROM1 (syntax) is visited for the LOAD command to determine whether to load from disc or tape, before heading back to ROM3 to load via tape.

Furthermore, I suspect all the banking code is surrounded with di/ei so that's why that didn't work for you!
I took good note of the Classic multiple bank loader in Z88DK's zx_tapeloader.asm and based my code on it.
I took another look at it today, it's not quite right with the error handling is it?
Post Reply