The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
On Spectrum we always got good emulators IMO. I think part of the problem was the transition from DOS to Windows. A lot of good emulators where left behind during that period. Take for example Ramsoft's RealSpectrum for DOS. I used that emulator to preserve REAL 5 1/4 40 SD Disciple discs, using the PC floppy drive.
- Blerkotron
- Dizzy
- Posts: 90
- Joined: Mon Nov 13, 2017 12:36 pm
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
This is fascinating, and very clearly explained - thanks for taking the time, [mention]Ast A. Moore[/mention]!
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
Nice article on something that's had me a bit perplexed when people have been talking about it.
I think it's a good point you make about the programmers back in the day - it probably wouldn't have been worth their while taking time to implement this with the different model changes, given the tight deadlines everyone seemed to be working under and general craziness (if a lot of the stories are true!).
I think it's a good point you make about the programmers back in the day - it probably wouldn't have been worth their while taking time to implement this with the different model changes, given the tight deadlines everyone seemed to be working under and general craziness (if a lot of the stories are true!).
My Speccy site: thirdharmoniser.com
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
Thank you for an excellent guide (and the effort to investigate this issue)!
My emulator now handles the +2A/+3 floating bus correctly I think. Here it is running "Woody’s Special" test (epileptics look away ):
.
My emulator now handles the +2A/+3 floating bus correctly I think. Here it is running "Woody’s Special" test (epileptics look away ):
.
My ZX Spectrum emulator project: https://softspectrum48.weebly.com.
- Ast A. Moore
- Rick Dangerous
- Posts: 2643
- Joined: Mon Nov 13, 2017 3:16 pm
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
Det här ser perfekt ut (unlike my Swedish). Grattis, Magnus!
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.
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.
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
Also the 2019 Turner Prize winner: "Floating Booc", visuals played to the sound of interstellar noise.
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
Thank you Ast A. Moore for such great well-written info and for introducing me to this fascinating & useful quirk!
My "lockdown project" is coming along nicely and I'm looking to implement the floating bus trick to fix the currently horrific display shredding.
Initially I'm planning to implement the 48/128/+2 version the figure out the +2A/+3 variations via self modification at the start of execution.
There's a couple of things I'm unsure of though!
How do I determine which of the floating bus methods is available?
Are there any emulators which don't support the 48/138/+2 floating bus trick? As I notice there aren't many supporting the +2A/+3 variant.
(Aside: What happens if I run the code on an emulator which doesn't support it? I'm not planning to code around the quirks of an emulator, mind.)
Where to put it? This is the biggie... My game loop looks like this:
By the time we reach Copy display buffer to display, the beam could be anywhere. I could just wait until I pick up my target value on the floating bus (in the bottom 1/3 of the display), but that seems wasteful... what if we're in the bottom border?
So it'd make sense to carry on into the other parts, checking again every so often. One concern is that I don't really want the player's input being read waaay before the display has been updated, in case the controls appear to lag as a result
It's probably worth mentioning here that there's a huuuuuge variation in how many T-states the whole loop takes depending on number of enemies, bullets, what type enemy/bullet they are... I think it's running at ~8 fps when things get really busy so maybe it won't be noticeable - though on the flip side I don't want it appearing any worse! And this of course makes it impossible to predict the number of T-states an entire "frame" requires, so no hints available there.
I guess I'm hoping to stumble upon the correct floating bus value between iterations of my Move/AI all loop, but would probably have to extend it to check throughout my game loop. But then I'm conscious of slowing the whole game down by checking too often!
So then I'm thinking - as a "get out" clause, if I reach a certain point (say, the collision detection all loop section) and it's still not happened, then it's probably a "quiet" loop with not much going on... so just sit and wait at that point until we catch our value, then draw the screen. Any delay should feel no worse than on a "busy" loop anyway.
Am I on the right track, or am I missing a trick? I find code comes together much easier the better planned it is, nevertheless I'm anticipating a ton of trial & error, rinse & repeat to get it nailed though... so I'm keen to know if I've overlooked or misinterpreted anything!
My "lockdown project" is coming along nicely and I'm looking to implement the floating bus trick to fix the currently horrific display shredding.
Initially I'm planning to implement the 48/128/+2 version the figure out the +2A/+3 variations via self modification at the start of execution.
There's a couple of things I'm unsure of though!
How do I determine which of the floating bus methods is available?
Are there any emulators which don't support the 48/138/+2 floating bus trick? As I notice there aren't many supporting the +2A/+3 variant.
(Aside: What happens if I run the code on an emulator which doesn't support it? I'm not planning to code around the quirks of an emulator, mind.)
Where to put it? This is the biggie... My game loop looks like this:
Code: Select all
Background buffer updates (scroll map etc here)
Collision map write all loop
Collision detection all loop
Copy background buffer to display buffer
Draw all to display buffer loop
*Copy display buffer to display*
Handle player input
Move/AI all loop
... repeat ...
So it'd make sense to carry on into the other parts, checking again every so often. One concern is that I don't really want the player's input being read waaay before the display has been updated, in case the controls appear to lag as a result
It's probably worth mentioning here that there's a huuuuuge variation in how many T-states the whole loop takes depending on number of enemies, bullets, what type enemy/bullet they are... I think it's running at ~8 fps when things get really busy so maybe it won't be noticeable - though on the flip side I don't want it appearing any worse! And this of course makes it impossible to predict the number of T-states an entire "frame" requires, so no hints available there.
I guess I'm hoping to stumble upon the correct floating bus value between iterations of my Move/AI all loop, but would probably have to extend it to check throughout my game loop. But then I'm conscious of slowing the whole game down by checking too often!
So then I'm thinking - as a "get out" clause, if I reach a certain point (say, the collision detection all loop section) and it's still not happened, then it's probably a "quiet" loop with not much going on... so just sit and wait at that point until we catch our value, then draw the screen. Any delay should feel no worse than on a "busy" loop anyway.
Am I on the right track, or am I missing a trick? I find code comes together much easier the better planned it is, nevertheless I'm anticipating a ton of trial & error, rinse & repeat to get it nailed though... so I'm keen to know if I've overlooked or misinterpreted anything!
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
Hmm, looks like I was getting rather too ahead of myself. Initial tests still contain a lot of shredding in the middle 1/3rd of the screen.
My "buffer to screen" routine is just an unrolled loop of 16 x CALL LDI_256 (which as you may have guessed is just 256 LDI's and a RET) so I figured it'd be fast enough... however I now learn that each of these 16 CALLs is 17 + (256 * 16) + 10 = 4123 T-states, 65968 in total... almost a full frame of T-states to draw 2/3rds of the screen!
How do other implementations using a display buffer manage it? ... or is that a question for another thread?
My "buffer to screen" routine is just an unrolled loop of 16 x CALL LDI_256 (which as you may have guessed is just 256 LDI's and a RET) so I figured it'd be fast enough... however I now learn that each of these 16 CALLs is 17 + (256 * 16) + 10 = 4123 T-states, 65968 in total... almost a full frame of T-states to draw 2/3rds of the screen!
How do other implementations using a display buffer manage it? ... or is that a question for another thread?
- Ast A. Moore
- Rick Dangerous
- Posts: 2643
- Joined: Mon Nov 13, 2017 3:16 pm
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
Thanks! I’m glad you liked it.
There are various methods for determining which platform your code is running on. I test a specific ROM address (2899) for a particular value. A +2A/+3 returns a value of 126 (on all the ROMs I’ve tested it). I then use self-modifying code (for speed) in the main loop, and replace the port number to poll and the padding instruction accordingly.
There are other, more sophisticated, methods for determining a machine’s architecture, but so far I haven’t found much use for them.
Often, the fastest method is to use the stack. Particular implementations will affect the effectiveness, naturally, but pushing a register pair onto the stack is the fastest way of moving two bytes the Z80 can manage.
Still, I suggest you create a separate thread for your question. The floating bus trick won’t give you more T states per frame. It’s just a method for syncing your main loop to a (more or less) arbitrary vertical position, instead of relying on the usual fixed top-of-the-frame interrupt.
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.
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.
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
A relatively simple method I use to distinguish a 128/+2 machine from a +2A/+3 is checking for the existence of port $3ffd. On the 128/+2 this port controls memory paging, so you can write to it and test known memory values in the $c000-$ffff range to see if they change. If they don't, then trying port $7ffd will let you know whether it's a +2A/+3. (As an aside, port $3ffd is generally preferable to the official paging port because it's not affected by contention.)
- Ast A. Moore
- Rick Dangerous
- Posts: 2643
- Joined: Mon Nov 13, 2017 3:16 pm
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
Yes, that’s a valid method; but for the floating bus behavior you only need to differentiate between a +2A/+3 and anything else, since the 48K/128K/+2 looping code will be identical. That’s why I opt for an even simpler method.
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.
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.
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
Thanks for this! Nice & simpleAst A. Moore wrote: ↑Sun May 31, 2020 10:48 am There are various methods for determining which platform your code is running on. I test a specific ROM address (2899) for a particular value. A +2A/+3 returns a value of 126 (on all the ROMs I’ve tested it). I then use self-modifying code (for speed) in the main loop, and replace the port number to poll and the padding instruction accordingly.
Yes, I'd come across the stack-based method in Jonathan Cauldwell's How To Write ZX Spectrum Games – Chapter 13 where he talks about unrolled LDI loops as well as the PUSH/POP method. The display screen area he mentions amounts to 4224 bytes, so I just assumed my 4096 byte unrolled LDI loop would do the job... oops!Ast A. Moore wrote: ↑Sun May 31, 2020 10:48 amOften, the fastest method is to use the stack. Particular implementations will affect the effectiveness, naturally, but pushing a register pair onto the stack is the fastest way of moving two bytes the Z80 can manage.
Still, I suggest you create a separate thread for your question. The floating bus trick won’t give you more T states per frame. It’s just a method for syncing your main loop to a (more or less) arbitrary vertical position, instead of relying on the usual fixed top-of-the-frame interrupt.
I'd spent all day sat outside enjoying the sunshine, reading & planning how I was going to tackle this once it was time to head back indoors, hence my enormous rambling stream-of-consciousness post... I thought I had it all nailed down! Sigh
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
Turns out I wasn't far off anyway... You can probably guess where my floating bus target values are!
Originally I had the play area at the top, energy bar directly beneath that, hoping my LDIs would complete before the beam got back around... they didn't!
So now the approach I have is to try & get behind the beam as soon as possible... by actually starting drawing a wee bit in front of it
- upon discovering our value on the floating bus, immediately begin transferring stuff to the screen... but instead of just doing a ton of LDIs (which due to the Spectrum's screen layout, will jump between being in front of / behind the beam), traverse down pixel-by-pixel during the first block.
- by the 2nd block, the beam is way in front of where we're writing - so just do 2048 LDIs (CALL LDI_256, 8 times) for speed
This seems to work pretty well - there's a bit of attribute misalignment and tearing in the top few rows until the beam catches up, but it's barely noticeable. Good enough!!
The overall game is a bit slower than before due to waiting for the beam and the 1st block taking longer to transfer than before, but I've a ton of optimisations to do still so hoping to claw a decent chunk of that back.
Last edited by presh on Mon Jun 01, 2020 2:46 pm, edited 1 time in total.
- Ast A. Moore
- Rick Dangerous
- Posts: 2643
- Joined: Mon Nov 13, 2017 3:16 pm
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
Looks great! Love the graphics.
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.
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.
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
Very impressed with this, great for my new project where I needed to clear the sprites at at the bottom of the screen as I pushed the sprite drawing to the limit. I normally either redraw the entire screen from a back buffer or clear after a halt before plot if fast enough. That wasn't working for this so I started with an arbitrary wait loop which was tricky to get right if the number of sprites fluctuated. This seems to have solved that.
Any chance you could share your code to check if 48k/128k or +2A/+3 and how you modify the code for each?
At the moment I'm using the method you put on WoS
ld a,(2899) ;+2A/+3 ROMs return 126
cp 126
jr z,its_a_plus
and I just flip between the two versions of the fl_bus code.
Thanks in advance.
TomD
Any chance you could share your code to check if 48k/128k or +2A/+3 and how you modify the code for each?
At the moment I'm using the method you put on WoS
ld a,(2899) ;+2A/+3 ROMs return 126
cp 126
jr z,its_a_plus
and I just flip between the two versions of the fl_bus code.
Thanks in advance.
TomD
Retro enthusiast and author of Flynn's Adventure in Bombland, The Order of Mazes & Maze Death Rally-X. Check them out at http://tomdalby.com
- Ast A. Moore
- Rick Dangerous
- Posts: 2643
- Joined: Mon Nov 13, 2017 3:16 pm
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
The above is exactly what I use in my real-world code for machine detection. The vanilla code is written for the +2A/+3, so the its_a_plus label just jumps forward without modifying anything. If the condition is not met, then I modify the floating bus sync code:TomD wrote: ↑Mon Jun 01, 2020 10:15 pm Any chance you could share your code to check if 48k/128k or +2A/+3 and how you modify the code for each?
At the moment I'm using the method you put on WoS
ld a,(2899) ;+2A/+3 ROMs return 126
cp 126
jr z,its_a_plus
and I just flip between the two versions of the fl_bus code.
Code: Select all
ld hl,v_sync+2
ld (hl),$2b ;opcode for the DEC HL instruction [6]
ld (v_sync_sw+1),hl ;redirect the JP NZ,** to DEC HL
ld a,$40 ;change top half of port addr (must be in the $40–$7f range)
ld (port1+1),a
ld a,$ff ;change bottom half of port addr
ld (port2+1),a
Code: Select all
port1 ld de,$xx0f ;ATTR color (xx) into D, top half of port to read into E
v_sync ld a,($5800) ;[13]point to contended memory and fetch a "blanking" attr
;or DEC HL [6] for the 48K/128K/+2
ld a,e ;[4]top half of port into A
port2 in a,($fd) ;[11]read port formed by A (MSB) and FDh (LSB) into A
cp d ;[4]test for ATTR color
v_sync_sw jp nz,v_sync ;[10]
Code: Select all
port1 ld de,$xx40 ;ATTR color (xx) into D, top half of port to read into E
v_sync ld a,($2b00) ;this makes no sense, but we’re only interested in the third byte,
;which is the opcode for the DEC HL instruction
ld a,e ;[4]top half of port into A
port2 in a,($ff) ;[11]read port formed by A (MSB) and FFh (LSB) into A
cp d ;[4]test for ATTR color
v_sync_sw jp nz,v_sync+2 ;[10]note the changed jump address
Code: Select all
SMC_v_sync dec hl ;[6]the padding instruction necessary for syncing
ld a,e ;[4]top half of port into A
port2 in a,($ff) ;[11]read port formed by A (MSB) and FFh (LSB) into A
cp d ;[4]test for ATTR color
v_sync_sw jp nz,SMC_v_sync ;[10]jumping to the last byte of the “nonsensical” LD A,($2B00) instruction
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.
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.
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
Many thanks, I went with the following so it does the check on the fly rather than SMC, guess not great if you change the ROM in the middle of the program but I'm not planning on doing that
One thing I did notice is the +2/+3 routine doesn't work on the Next (using Next/+3 mode). Works fine if you select 128k or Usr 0 mode though so not a major issue.
TomD
Code: Select all
; ==========================================+==================================
; floating bus wait routines (35b)
; ------------------------------------------+----------------------------------
; _fl_bus is for Sinclair 48/128k & Amstrad +2 (taken from sidewize)
; _fl2_bus is for Amstrad +2A/B & +3 (by Ast A. Moore)
; ==========================================+==================================
_fl_bus:
ld a,($0b53) ; 13t - +2A/+3 ROMs return 126
cp $7e ; 7t
jr z,_fl2_bus ; 12/7t
ld bc,$40ff ; 10t - port
ld e,$18 ; 7t - attr to compare to
_fl_bus100:
ld a,r ; 4t
in a,(c) ; 12t
cp e ; 4t - is it >=check attr
jp nc,_fl_bus100 ; 10t - loop till <
ret ; 10t
_fl2_bus:
ld de,$180f ; 10t - attr into d, MSB of port addr into e
_fl2_bus100:
ld a,($5800) ; 13t - point to contended memory and fetch a "blanking" attr
ld a,e ; 4t - MSB of port addr into a
in a,($fd) ; 11t - read port $0ffd into a
cp d ; 4t - is it >=check attr
jp nc,_fl2_bus100 ; 10t - loop till <
ret ; 10t
Retro enthusiast and author of Flynn's Adventure in Bombland, The Order of Mazes & Maze Death Rally-X. Check them out at http://tomdalby.com
- Ast A. Moore
- Rick Dangerous
- Posts: 2643
- Joined: Mon Nov 13, 2017 3:16 pm
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
I’m not familiar with the Next well enough to comment, but keep in mind that on a real +2A/+3, the trick only works if paging hasn’t been explicitly disabled (i.e. it won’t work in 48K BASIC mode).
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.
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.
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
Next/+3 mode runs with +3 timings and the NextZXOS ROMs, which are significantly different from the +3 ROMs, given that they’re entirely rewritten with new NextBASIC functionality for new machine features. This tape loading mode is meant for loading new Next programs rather than for compatibility. So reading an arbitrary ROM byte in this mode isn’t a particularly good way to detect +3 timings.
Some of the other modes are intended for compatibility: 48K mode runs with 48K timings and the original 48K ROMs, with Next And 128K features disabled; 128K mode runs with 128K timings Bd the original 128K ROMs, with Next features disabled. Pentagon mode runs with Pentagon timings, and Pentagon/Profi paging. USR0 mode is not really a compatibility mode, it runs in +3 timings with Next features after invoking USR0.
It happens that there isn’t a dedicated +3 compatibility mode yet, because there is insufficient space to hold all 64K of alternate +3ROMs in the memory map. Alternate ROMs are a relatively new feature that avoided the need to endlessly patch the NextZXOS ROMs for compatibility with a succession of individual games. There was only 32K available to give to the scheme though, so it hasn’t yet been implemented for +2A/+3. This could change later after some other things have been reorganised.
As I said earlier in the thread, don’t get too hung up on expecting every program to work in every mode. The modes are pragmatic tools to let every program run in at least one common configuration, with some extra advanced options and manually applied disables to further tweak the environment where needed.
Some of the other modes are intended for compatibility: 48K mode runs with 48K timings and the original 48K ROMs, with Next And 128K features disabled; 128K mode runs with 128K timings Bd the original 128K ROMs, with Next features disabled. Pentagon mode runs with Pentagon timings, and Pentagon/Profi paging. USR0 mode is not really a compatibility mode, it runs in +3 timings with Next features after invoking USR0.
It happens that there isn’t a dedicated +3 compatibility mode yet, because there is insufficient space to hold all 64K of alternate +3ROMs in the memory map. Alternate ROMs are a relatively new feature that avoided the need to endlessly patch the NextZXOS ROMs for compatibility with a succession of individual games. There was only 32K available to give to the scheme though, so it hasn’t yet been implemented for +2A/+3. This could change later after some other things have been reorganised.
As I said earlier in the thread, don’t get too hung up on expecting every program to work in every mode. The modes are pragmatic tools to let every program run in at least one common configuration, with some extra advanced options and manually applied disables to further tweak the environment where needed.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel • NXTP • ESP Update • ESP Reset • CSpect Plugins
SevenFFF / Threetwosevensixseven / colonel32
NXtel • NXTP • ESP Update • ESP Reset • CSpect Plugins
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
* Oops, I said it in another Next thread somewhere else on this forum, not earlier in this thread. Soz.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel • NXTP • ESP Update • ESP Reset • CSpect Plugins
SevenFFF / Threetwosevensixseven / colonel32
NXtel • NXTP • ESP Update • ESP Reset • CSpect Plugins
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
the emulation it is not completely right (i think), but ZXEmuT now can run Yankee in +2A/+3 mode! ;-)
thank you for your hard work, and for detailed explanations!
thank you for your hard work, and for detailed explanations!
- Ast A. Moore
- Rick Dangerous
- Posts: 2643
- Joined: Mon Nov 13, 2017 3:16 pm
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
Glad you found my little writeup useful! When I was helping Mark Woodmass to perfect the timings in SpecEmu, I made a special version of my test for him. Feel free to use it, tweak your emulator, and compare the results with this 50 fps video of my +2A running it. You can advance the video frame by frame and make sure the vertical shifts in the black gaps of the yellow border alight with the correct vertical white bars. Mark was able to nail it with the help of my test.
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.
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.
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
thank you even more! ;-)
for now it looks like my contention pattern for +2A is totally broken (no wonder, ZXEmuT couldn't properly run +2A/+3 at all until yesterday ;-), and Yankee works due to very specific timings. your test will definitely help to fix it all.
for now it looks like my contention pattern for +2A is totally broken (no wonder, ZXEmuT couldn't properly run +2A/+3 at all until yesterday ;-), and Yankee works due to very specific timings. your test will definitely help to fix it all.
Re: The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum
OK, so I had this working fine until I started messing around with interrupts - with IM2 enabled, the game locks up and the debugger shows it's stuck in the "floating_bus_loop" (see below).
At first I thought it might be because I hadn't DI / EI 'd either side of the code, but even after adding them it still locks up.
Any idea why this is happening?
(My interrupt code just cycles the border colour through 0-7 at the moment - a simple test routine, so that I can see it's being called successfully. Removing the bit of code which changes the border doesn't fix things either!)
At first I thought it might be because I hadn't DI / EI 'd either side of the code, but even after adding them it still locks up.
Any idea why this is happening?
(My interrupt code just cycles the border colour through 0-7 at the moment - a simple test routine, so that I can see it's being called successfully. Removing the bit of code which changes the border doesn't fix things either!)
Code: Select all
DI
LD D, 8 ; attr: PAPER 1, INK 0
LD E, $40 ; MSB of port address ($40FF)
floating_bus_loop:
DEC HL ;[6]padding instruction
LD A,E ;[4]MSB of port addr into A
IN A,($FF) ;[11]read port 0x40FF into A
CP D ;[4]is it D (i.e. INK 1, PAPER 1, BRIGHT 0; FLASH 0)?
JP NZ, floating_bus_loop ;[10]no? keep trying
; Found it!
EI