The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum

The place for codemasters or beginners to talk about programming any language for the Spectrum.
presh
Manic Miner
Posts: 237
Joined: Tue Feb 25, 2020 8:52 pm
Location: York, UK

Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum

Post by presh »

Still mega stumped by this!

I took a backup before I started messing with the interrupts, so I rolled back to that working version.

Ended up in the same situation - interrupt routine runs fine, but gets stuck in the floating bus loop and never "catches" the target value... :cry:

Added DI/EI either side - no effect.

Removed the border colour changing part of the interrupt routine again (in case my OUT (254), colour was messing with things) - no effect.

Same behaviour in Spectaculator & ZX Spin (emulating a +2 throughout development) so not convinced it's an emulator "feature" (also as it's the old "tried & tested" rather than the new +2A/+3 method) :)

Are there any caveats regarding interrupts, interrupt modes, etc I've overlooked?
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum

Post by Ast A. Moore »

Hmm. Could you post the entire code (well, the relevant portions) so I could test it? The only reason for it not to be working I can think of off the top of my head is that it’s sitting somewhere in contended memory (including the respective RAM banks).
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
presh
Manic Miner
Posts: 237
Joined: Tue Feb 25, 2020 8:52 pm
Location: York, UK

Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum

Post by presh »

Sure, my interrupt is set up at the very beginning like so:

Code: Select all

; Set up interrupts 
    DI
    LD A, $65   ; Interrupt table at page $6500
    LD I, A     ; Set the interrupt register to that page
    IM 2        ; Set the interrupt mode
    EI          ; Enable interrupts
The interrupt itself is:

Code: Select all

    ORG $6666   ; 26214
    
INTERRUPT:

    DI
    
    PUSH AF
    PUSH BC
    PUSH DE
    PUSH HL
    EXX
    PUSH AF
    PUSH BC
    PUSH DE
    PUSH HL
    EXX 
    PUSH IX
    PUSH IY
    
    ; --- Main interrupt routine --- ;
    
    ; Update border colour
    LD HL, intrpt_test
    INC (HL)
    LD A, (HL)
    AND 7
    OUT (254), A
    
    ; --- End of main interrupt routine --- ;
    
    POP IY
    POP IX
    EXX
    POP HL
    POP DE
    POP BC
    POP AF
    EXX
    POP HL
    POP DE
    POP BC
    POP AF
    
    EI
    
    RET


intrpt_test:
    DB 0
Interrupt table is 257 bytes of $66. Interrupt runs fine and produces the desired headache-inducing border effect.

The floating bus loop is at $B187 and was working right up until I added the above bits of code in.
Nienn Heskil
Microbot
Posts: 134
Joined: Tue Jun 09, 2020 6:14 am
Contact:

Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum

Post by Nienn Heskil »

presh wrote: Sun Sep 06, 2020 9:43 pm

Code: Select all

  LD D, 8     ; attr: PAPER 1, INK 0
  <...>
  CP D        ;[4]is it D (i.e. INK 1, PAPER 1, BRIGHT 0; FLASH 0)?
If it's not a typo, chances are you're testing for a different attr value rather than the one you put onscreen.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum

Post by Ast A. Moore »

Nienn Heskil wrote: Wed Sep 09, 2020 8:12 pm
presh wrote: Sun Sep 06, 2020 9:43 pm

Code: Select all

  LD D, 8     ; attr: PAPER 1, INK 0
  <...>
  CP D        ;[4]is it D (i.e. INK 1, PAPER 1, BRIGHT 0; FLASH 0)?
If it's not a typo, chances are you're testing for a different attr value rather than the one you put onscreen.
Either that, or the tested area is not wide enough for the loop to catch it. Make sure you have enough consecutive cells with the desired attributes. Depending on which machine you run this on (48K/128K), the loop will take a different amount of time to sync up. To be on the safe side, I recommend setting the same attribute value for an entire row.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum

Post by Ast A. Moore »

presh wrote: Mon Sep 07, 2020 1:57 am Are there any caveats regarding interrupts, interrupt modes, etc I've overlooked?
Yes, your interrupt vector is pointing to the contended RAM area ($40–$7f). This will trigger the ULA snow effect. You should always make sure it’s outside that range. The ISR itself can sit anywhere in RAM, but the interrupt vector table must reside in non-contended RAM.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
presh
Manic Miner
Posts: 237
Joined: Tue Feb 25, 2020 8:52 pm
Location: York, UK

Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum

Post by presh »

Nienn Heskil wrote: Wed Sep 09, 2020 8:12 pm
presh wrote: Sun Sep 06, 2020 9:43 pm

Code: Select all

  LD D, 8     ; attr: PAPER 1, INK 0
  <...>
  CP D        ;[4]is it D (i.e. INK 1, PAPER 1, BRIGHT 0; FLASH 0)?
If it's not a typo, chances are you're testing for a different attr value rather than the one you put onscreen.
Haha, yes. Those are [mention]Ast A. Moore[/mention]'s original comments which I hadn't updated! Well spotted :)
presh
Manic Miner
Posts: 237
Joined: Tue Feb 25, 2020 8:52 pm
Location: York, UK

Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum

Post by presh »

Ast A. Moore wrote: Wed Sep 09, 2020 10:08 pm
presh wrote: Mon Sep 07, 2020 1:57 am Are there any caveats regarding interrupts, interrupt modes, etc I've overlooked?
Yes, your interrupt vector is pointing to the contended RAM area ($40–$7f). This will trigger the ULA snow effect. You should always make sure it’s outside that range. The ISR itself can sit anywhere in RAM, but the interrupt vector table must reside in non-contended RAM.
Ah! Another one of those "quirks" I've heard about but never encountered and thus forgotten. Thanks for the explanation. I shall attempt to find room up there, but it's pretty... RAMmed :lol: :roll:
DoctorRad
Drutt
Posts: 27
Joined: Mon Mar 18, 2024 4:40 pm

Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum

Post by DoctorRad »

Ast A. Moore wrote: Wed Sep 09, 2020 9:59 pmEither that, or the tested area is not wide enough for the loop to catch it. Make sure you have enough consecutive cells with the desired attributes. Depending on which machine you run this on (48K/128K), the loop will take a different amount of time to sync up. To be on the safe side, I recommend setting the same attribute value for an entire row.
Having read through this thread and your webpage am I right in thinking that your code loop will catch one of the attribute bytes on the relevant row, but you can't be sure which one? And is it also the case that you're not 100% sure why this 35 t-state loop only catches attributes?
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum

Post by Ast A. Moore »

DoctorRad wrote: Wed Mar 27, 2024 2:55 pm Having read through this thread and your webpage am I right in thinking that your code loop will catch one of the attribute bytes on the relevant row, but you can't be sure which one? And is it also the case that you're not 100% sure why this 35 t-state loop only catches attributes?
True, you can’t be absolutely sure which attribute cell the loop will catch, but if I remember correctly, an entire row is certainly overkill. However, it would be difficult to set up a test that would reveal the exact pattern definitively. Moreover, I suspect that the exact timing of the triggering will depend on the length of the instructions preceding the sync loop and will thus be pretty much unpredictable.

As for why the loop takes the number of T states it does (note that it’ll differ on different Spectrum models), you’re right, I can’t fully explain it. I ran a few dozen tests with different padding instructions and the example outlined in my writeup is just the quickest one that works. It’s reasonable to assume that using another padding instruction (or, indeed, instructions) will let you be more precise in picking and choosing the exact attribute location at the expense of causing a significant delay (for example, you may be limited to just a single attribute per two or more rows). I’d argue it is possible to create a very sophisticated timing pattern for several consecutive loops (each with its own timing) and get very precise indeed. However practical that would be, I am not certain.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Post Reply