ZX Spectrum experts explain me this ( floating bus )
- gilesgoat
- Sheepie Whore

- Posts: 27258
- Joined: Wed Sep 03, 2003 7:54 am 0
- Location: Monfalcone, Italy
- Contact:
ZX Spectrum experts explain me this ( floating bus )
It seems "it's an old trick" that took years to be found ?
In few words it seems "the story goes", on a ZX ( with minor variations it seem on ANY ZX model ) , if you try to read an unamapped ZX port ( usually PORT 255 ) you get :
- 0xFF is the ULA is outputting the border in that moment
- whatever the ULA is fetching from the bus at that moment
Now the lore goes that "if you put an attribute byte that is NOT present anywhere else" in the screen, like in the beginning of some scanline, you can precisely synch on that scanline.
Also some claims ( and I am not convinced of that either ) that the ULA fetches 4 bytes at the time like ATTRX/BITMAPX/ATTRX+1/BITMAPX+1 .. I was convinced it was only fetching 2 bytes at the time.
"To make short a long story" there is THIS LINK ( that explains it all ) : http://sky.relative-path.com/zx/floating_bus.html ( which one guy on Mastdon posted following one link from his own code ) ..
I have a look and a look and I say "this thing as it is cannot work" .. the guy goes "but I implemented it, it works !" .. I keep saying "maybe, but I can't work it out WHY should work as it claims on that article" ..
So the guy re-takes his code, makes a number of tests and .. find out "actually it does not work, it seems to be working only because/if I was putting out no more than 16 frames per second" ..
He found condition(s?) where in effect that code fails.
I look and look at it, I can't see HOW it could even work in the first place !
I mean ok "yes at 255 you are somewhere in the border", I COULD understand IF you do a thing like "if it's 255 wait until it's NOT 255 then check if the byte you got is what you were expecting" ..
But the code doesn't do that .. so how on earth it's suppose to "lock" on that byte ??
Note that article says "even if anywhere else there would be a byte with the same value with my method you'll always lock on the attribute byte" .. which apparently we proven it's not true .. and I can't see HOW that could be true.
In few words it seems "the story goes", on a ZX ( with minor variations it seem on ANY ZX model ) , if you try to read an unamapped ZX port ( usually PORT 255 ) you get :
- 0xFF is the ULA is outputting the border in that moment
- whatever the ULA is fetching from the bus at that moment
Now the lore goes that "if you put an attribute byte that is NOT present anywhere else" in the screen, like in the beginning of some scanline, you can precisely synch on that scanline.
Also some claims ( and I am not convinced of that either ) that the ULA fetches 4 bytes at the time like ATTRX/BITMAPX/ATTRX+1/BITMAPX+1 .. I was convinced it was only fetching 2 bytes at the time.
"To make short a long story" there is THIS LINK ( that explains it all ) : http://sky.relative-path.com/zx/floating_bus.html ( which one guy on Mastdon posted following one link from his own code ) ..
I have a look and a look and I say "this thing as it is cannot work" .. the guy goes "but I implemented it, it works !" .. I keep saying "maybe, but I can't work it out WHY should work as it claims on that article" ..
So the guy re-takes his code, makes a number of tests and .. find out "actually it does not work, it seems to be working only because/if I was putting out no more than 16 frames per second" ..
He found condition(s?) where in effect that code fails.
I look and look at it, I can't see HOW it could even work in the first place !
I mean ok "yes at 255 you are somewhere in the border", I COULD understand IF you do a thing like "if it's 255 wait until it's NOT 255 then check if the byte you got is what you were expecting" ..
But the code doesn't do that .. so how on earth it's suppose to "lock" on that byte ??
Note that article says "even if anywhere else there would be a byte with the same value with my method you'll always lock on the attribute byte" .. which apparently we proven it's not true .. and I can't see HOW that could be true.
Giles the billy goat
"Baa"
"Baa"
Re: ZX Spectrum experts explain me this ( floating bus )
>Also some claims ( and I am not convinced of that either ) that the ULA fetches 4 bytes at the time like ATTRX/BITMAPX/ATTRX+1/BITMAPX+1 .. I was convinced it was only fetching 2 bytes at the time.
It's two pairs of pagemode reads, which takes 4 CPU clock cycles, leaving the other 4 open for CPU use.
I'll try to remember to look at that code above tomorrow.
It's two pairs of pagemode reads, which takes 4 CPU clock cycles, leaving the other 4 open for CPU use.
I'll try to remember to look at that code above tomorrow.
- gilesgoat
- Sheepie Whore

- Posts: 27258
- Joined: Wed Sep 03, 2003 7:54 am 0
- Location: Monfalcone, Italy
- Contact:
Re: ZX Spectrum experts explain me this ( floating bus )
... REMINDER ...Dio wrote:>Also some claims ( and I am not convinced of that either ) that the ULA fetches 4 bytes at the time like ATTRX/BITMAPX/ATTRX+1/BITMAPX+1 .. I was convinced it was only fetching 2 bytes at the time.
It's two pairs of pagemode reads, which takes 4 CPU clock cycles, leaving the other 4 open for CPU use.
I'll try to remember to look at that code above tomorrow.
Giles the billy goat
"Baa"
"Baa"
- _TinOmen_
- Baaaa!

- Posts: 744
- Joined: Wed Feb 12, 2003 10:52 pm 0
- Location: Stockholm, Sweden
- Contact:
Re: ZX Spectrum experts explain me this ( floating bus )
I thought the main idea of the floating bus trick is to be able to detect when the raster has passed a certain area of the screen so it is safe to start painting the next screen without risk of tearing. And precise sync is not needed for that usage.
- gilesgoat
- Sheepie Whore

- Posts: 27258
- Joined: Wed Sep 03, 2003 7:54 am 0
- Location: Monfalcone, Italy
- Contact:
Re: ZX Spectrum experts explain me this ( floating bus )
I still that "unless used in some way I still haven't think about" it's a bit of "time waster" because forces you to be in a busy loop where you can't do anything else until you reached that 'T', unforunately there's no way to get "int on scanline" or something similar on the ZX._TinOmen_ wrote:I thought the main idea of the floating bus trick is to be able to detect when the raster has passed a certain area of the screen so it is safe to start painting the next screen without risk of tearing. And precise sync is not needed for that usage.
Giles the billy goat
"Baa"
"Baa"
Re: ZX Spectrum experts explain me this ( floating bus )
#C64MasterRacegilesgoat wrote:unforunately there's no way to get "int on scanline" or something similar on the ZX.
"Words ought to be a little wild - for they are assaults of thought on the unthinking."
- John Maynard Keynes
- John Maynard Keynes
Re: ZX Spectrum experts explain me this ( floating bus )
He's just looking for a 9, which is the attribute value under search. If that never occurs in the attribute file, and the floating read is timed to only see attribute reads, this is fine.gilesgoat wrote:I mean ok "yes at 255 you are somewhere in the border", I COULD understand IF you do a thing like "if it's 255 wait until it's NOT 255 then check if the byte you got is what you were expecting" ..
But the code doesn't do that .. so how on earth it's suppose to "lock" on that byte ??
I've never tried to write one of these though, but I do think his code is a bit wonky:
- The loop should really be a multiple of 8 cycles long to ensure it always hits the same timing relative to the pagemode reads. It may only work because there isn't a 9 anywhere else on the screen and it eventually hits it at 'some point' in the line but not immediately.
- It is only inadvertently phase locked to contended screen timing (by the first OUT, which happens during screen time). It should have some earlier explicit phase lock.
Re: ZX Spectrum experts explain me this ( floating bus )
#Atari8bitSuperiority

- gilesgoat
- Sheepie Whore

- Posts: 27258
- Joined: Wed Sep 03, 2003 7:54 am 0
- Location: Monfalcone, Italy
- Contact:
Re: ZX Spectrum experts explain me this ( floating bus )
What I don't understand HOW the read "is timed to see ONLY attributes" .. it still doesn't make much sense to me, can you explain that ?Dio wrote:He's just looking for a 9, which is the attribute value under search. If that never occurs in the attribute file, and the floating read is timed to only see attribute reads, this is fine.gilesgoat wrote:I mean ok "yes at 255 you are somewhere in the border", I COULD understand IF you do a thing like "if it's 255 wait until it's NOT 255 then check if the byte you got is what you were expecting" ..
But the code doesn't do that .. so how on earth it's suppose to "lock" on that byte ??
I've never tried to write one of these though, but I do think his code is a bit wonky:
- The loop should really be a multiple of 8 cycles long to ensure it always hits the same timing relative to the pagemode reads. It may only work because there isn't a 9 anywhere else on the screen and it eventually hits it at 'some point' in the line but not immediately.
- It is only inadvertently phase locked to contended screen timing (by the first OUT, which happens during screen time). It should have some earlier explicit phase lock.
Giles the billy goat
"Baa"
"Baa"
Re: ZX Spectrum experts explain me this ( floating bus )
During the visible screen the Spectrum operates an interleaved bus on the lower 16KB, 4 cycles to the ULA, 4 cycles to the CPU. Accessing ROM, upper RAM or any port other than the ULA (including port FF which is used to read the floating bus) doesn't respect the phase, which is why it can see which read is going on through the bank of 330-ohm resistors that act as the bus gateway.
In the 4 ULA-owned cycles, it manages (just) to squeeze in two pairs of pagemode reads for attribute then data, and the CAS pulses are on the bus for about 1 CPU cycle each. So if you time the read such that it latches data on a given cycle in that 8-cycle range you can pick which of the four bytes you read. Keep the loop 8 cycles aligned in length and you're always reading the same one.
In the 4 ULA-owned cycles, it manages (just) to squeeze in two pairs of pagemode reads for attribute then data, and the CAS pulses are on the bus for about 1 CPU cycle each. So if you time the read such that it latches data on a given cycle in that 8-cycle range you can pick which of the four bytes you read. Keep the loop 8 cycles aligned in length and you're always reading the same one.
- gilesgoat
- Sheepie Whore

- Posts: 27258
- Joined: Wed Sep 03, 2003 7:54 am 0
- Location: Monfalcone, Italy
- Contact:
Re: ZX Spectrum experts explain me this ( floating bus )
"If you time your read" .. BUT YOU NEED A STARTING POINT ..Dio wrote:During the visible screen the Spectrum operates an interleaved bus on the lower 16KB, 4 cycles to the ULA, 4 cycles to the CPU. Accessing ROM, upper RAM or any port other than the ULA (including port FF which is used to read the floating bus) doesn't respect the phase, which is why it can see which read is going on through the bank of 330-ohm resistors that act as the bus gateway.
In the 4 ULA-owned cycles, it manages (just) to squeeze in two pairs of pagemode reads for attribute then data, and the CAS pulses are on the bus for about 1 CPU cycle each. So if you time the read such that it latches data on a given cycle in that 8-cycle range you can pick which of the four bytes you read. Keep the loop 8 cycles aligned in length and you're always reading the same one.
I can say "ok wait X cycles and then read" .. or "read and wait X cycles and read again".
But I need some "synch point" to start with !
If I just "read" at point 'A' I know that "at some point the ULA will stop me" .. BUT WHEN PRECISELY ? Could it be "in the middle of any cycle" ?
How do I know "I got stopped precisely in the point that if I wait X time the next thing I read is an attribute byte" ?
Should not at least wait for the 50/60 Hz int or something before to do that ?
Giles the billy goat
"Baa"
"Baa"
Re: ZX Spectrum experts explain me this ( floating bus )
You can sync up precisely by doing two consecutive LD A,(HL) with HL set to 0x4000 during the screen active time (which you can find by looking for FF then anything else on the floating bus).
That instruction takes 7 cycles, which on the memory bus is a 2 cycle read from high memory, a 2 cycle refresh, then a 3 cycle read from 0x4000.
As reads take either 3 or 4 cycles, the ULA only releases the CPU on cycles 4 or 5 of the 8-cycle block. If the first low ram read lands on any cycle other than cycle 4, you get aligned to cycle 7 (read starts on cycle 4, completes on 7); the second video read then ends up on cycle 3 and takes an extra cycle leaving you aligned on cycle 7. If the first read ends up starting on cycle 5, then the second one starts on cycle 4 and so you are also aligned on cycle 7.
That instruction takes 7 cycles, which on the memory bus is a 2 cycle read from high memory, a 2 cycle refresh, then a 3 cycle read from 0x4000.
As reads take either 3 or 4 cycles, the ULA only releases the CPU on cycles 4 or 5 of the 8-cycle block. If the first low ram read lands on any cycle other than cycle 4, you get aligned to cycle 7 (read starts on cycle 4, completes on 7); the second video read then ends up on cycle 3 and takes an extra cycle leaving you aligned on cycle 7. If the first read ends up starting on cycle 5, then the second one starts on cycle 4 and so you are also aligned on cycle 7.

