Edge Grinder for the Spectrum

Show us what you're working on, (preferably with screenshots).
User avatar
R-Tape
Site Admin
Posts: 251
Joined: Thu Nov 09, 2017 11:46 am

Re: Edge Grinder for the Spectrum

Post by R-Tape » Mon Nov 13, 2017 4:10 pm

Ast A. Moore wrote:
Mon Nov 13, 2017 3:34 pm
R-Tape wrote:
Sun Nov 12, 2017 3:39 pm
I want it to run without a HALT for speed reasons, so AY will be an issue.
Use the floating bus trick for syncing and IM2 for music only?
I'm outside my comfort zone already. I understand how to use the floating bus to wait for the top or bottom part of the screen, but I don't see how it helps here. Wouldn't the program still need to wait for the fb?
0 x

User avatar
Ast A. Moore
Dizzy
Posts: 72
Joined: Mon Nov 13, 2017 3:16 pm

Re: Edge Grinder for the Spectrum

Post by Ast A. Moore » Mon Nov 13, 2017 4:46 pm

R-Tape wrote:
Mon Nov 13, 2017 4:10 pm
Ast A. Moore wrote:
Mon Nov 13, 2017 3:34 pm
R-Tape wrote:
Sun Nov 12, 2017 3:39 pm
I want it to run without a HALT for speed reasons, so AY will be an issue.
Use the floating bus trick for syncing and IM2 for music only?
I'm outside my comfort zone already. I understand how to use the floating bus to wait for the top or bottom part of the screen, but I don't see how it helps here. Wouldn't the program still need to wait for the fb?
Well, the FB can land you fairly reliably on any part of the screen, not just the top or bottom (so you can start updating the top of the screen, say, right before the raster lands on the status panel). But yes, the program will sit in a loop waiting for the expected byte to appear on the data bus. The disadvantage is that you lose it when the screen data in that particular area changes, which is okay for gameplay, generally speaking, but not okay if you want the music to keep playing. That’s why I suggest syncing the music player to interrupts and screen updates to the FB.

Just a suggestion, of course. It’s all pretty case-specific.
0 x
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.

Ralf
Microbot
Posts: 123
Joined: Mon Nov 13, 2017 11:59 am
Location: Poland

Re: Edge Grinder for the Spectrum

Post by Ralf » Mon Nov 13, 2017 9:01 pm

Not this one - I started it around May this year, with EG specifically in mind.
So I must have been confusing it with some other project, these space shootemups are a bit similar, aren't they? ;)

I had the chance of running it now.

It's a really good engine. You have a chance to make a second Zynaps :)

At this moment there is bad colour clash but I'm sure it will be gone in final version.

Good luck with it!
0 x

AndyC
Berk
Posts: 10
Joined: Mon Nov 13, 2017 5:12 am

Re: Edge Grinder for the Spectrum

Post by AndyC » Mon Nov 13, 2017 11:53 pm

There was definitely some talk of how you could do it, back when the game originally came out for the C64 and CPC. Don't remember anyway actually starting it though. Looking forward to seeing how it comes out. :)
0 x

User avatar
R-Tape
Site Admin
Posts: 251
Joined: Thu Nov 09, 2017 11:46 am

Re: Edge Grinder for the Spectrum

Post by R-Tape » Tue Nov 14, 2017 7:16 am

Ralf wrote:
Mon Nov 13, 2017 9:01 pm
It's a really good engine. You have a chance to make a second Zynaps :)
:shock:
AndyC wrote:
Mon Nov 13, 2017 11:53 pm
There was definitely some talk of how you could do it, back when the game originally came out for the C64 and CPC. Don't remember anyway actually starting it though. Looking forward to seeing how it comes out. :)
Cheers.

I've had a few chats about how to do it and here's the reasoning behind my design choices:

The main problem is speed, 12.5fps (main loop takes 3 frames) looks too slow. How to rotate the buffer and move it to the screen fast enough?

The options:

RL (HL) the buffer and LDI to the screen. More Tea Vicar does this, and while that's a great game it's farrr to slow for this.

RLD the buffer and PUSH to the screen. Like a faster Cronos (but that uses LDI). Would look fast but jerky. Maybe.

PUSH scroller. Like Cobra, Steel Eagle, 50Hurts and CATs engines. Easily 25fps and very fast but you are forced to use simple graphics.

Rotate on the screen. The Zynaps and R-Type scroller. Scroll the blocks on the screen, not the empty space. no need to move a buffer to the screen. Huge time saving and probably the best way to do it, the small downside is that background interaction with sprites sometimes looks a bit odd. Trouble is, as beautifully simple as the concept is, I can't do it. I've tried it a few times and it melts my brain.

RL (HL) the buffer and PUSH to the screen with a HALT in the code. Ends up a constant 12.5 fps at best. Too slow.

RL (HL) the buffer and PUSH to the screen, no HALT, not constant frame rate.

So I went with the last one. So far the speed is okay and I don't have much more to add. To PUSH the screen takes 2/3 of a frame and RL (HL) the buffer is 1 frame, add the rest of the code and it takes ~2 and a third frames per pass of the main loop.
0 x

Ralf
Microbot
Posts: 123
Joined: Mon Nov 13, 2017 11:59 am
Location: Poland

Re: Edge Grinder for the Spectrum

Post by Ralf » Tue Nov 14, 2017 9:48 am

Rotate on the screen. The Zynaps and R-Type scroller. Scroll the blocks on the screen, not the empty space. no need to move a buffer to the screen. Huge time saving and probably the best way to do it, the small downside is that background interaction with sprites sometimes looks a bit odd. Trouble is, as beautifully simple as the concept is, I can't do it. I've tried it a few times and it melts my brain.

I have an unfinished project using this technique. I'll try to write more about it later in programming section.
0 x

User avatar
Ivanzx
Site Admin
Posts: 54
Joined: Tue Nov 14, 2017 9:51 am

Re: Edge Grinder for the Spectrum

Post by Ivanzx » Tue Nov 14, 2017 10:33 am

Considering that this is an early stage, it is looking good! I have to check the C64 and CPC versions too ;)
0 x

Joefish
Berk
Posts: 49
Joined: Tue Nov 14, 2017 10:26 am

Re: Edge Grinder for the Spectrum

Post by Joefish » Tue Nov 14, 2017 10:46 am

To speed up your buffer scroll:

Align it with a memory address divisible by 32, then use SLA (HL) for the first byte, RL (HL) for subsequent bytes. Use DEC L between bytes and only use DEC HL at the end of a row.

To optimise it more, make two instruction buffers(one for each third of the screen you're scrolling) and allocate it two bytes per character (2 bytes x 8 rows x 32 chars). Put in the SLA (HL), DEC L, RL (HL), DEC L, ... RL (HL), DEC HL eight times for each row. And call each one 8 times. That scrolls your screen buffer.

Now the trick is, you can actually put in NOPs instead of RL (HL) where there is no data to scroll, and so save time. And you can shift the SLA (HL) / RL (HL) / NOP bytes 2-bytes to the left to shift your pattern along one character to the left as the screen and attributes move. And fill in SLA (HL) / RL (HL) / NOP instructions from the right depending on whether grpahics are present or not. (You could optimise this further, but then you end up with variable-length lines in your instruction list).

You can apply this technique to the buffer or to the screen. R-Type re-generates its list of scrolls on-the-fly. You don't need to do that if your scenery isn't changing.

The trick with scrolling the screen like this is a sprite engine that draws character-by-character and can stop drawing if some scenery is already there (use 0-attributes in the scenery to designate empty cells).
1 x

Hikaru
Dizzy
Posts: 51
Joined: Mon Nov 13, 2017 1:42 pm
Location: Russia
Contact:

Re: Edge Grinder for the Spectrum

Post by Hikaru » Tue Nov 14, 2017 1:30 pm

R-Tape wrote:
Tue Nov 14, 2017 7:16 am
Rotate on the screen. The Zynaps and R-Type scroller. Scroll the blocks on the screen, not the empty space. no need to move a buffer to the screen. Huge time saving and probably the best way to do it, the small downside is that background interaction with sprites sometimes looks a bit odd. Trouble is, as beautifully simple as the concept is, I can't do it. I've tried it a few times and it melts my brain.
I'm not sure how you're doing sprite/bg collision testing, but if we take that out of the picture for a moment, then a variant of this would really only need a minor modification on top of what you already have.

1. XOR out the sprites
2. Rotate the bg in place
3. XOR in the sprites

Do this in a top to bottom fashion, for instance using 2 passes for a start (third 1, third 2). In this case, you'll need to start when the raster is approaching third 2. It's a bit hard to estimate the actual speedup because, although you would no longer have the 'buffer copy' phase, you would have the 'XOR out the sprites' phase instead, and also the rotating would occur in contended memory which is slower. But in any case I'm pretty sure it will be fairly significant and would probably allow for 25FPS + HALT.

Regarding skipping over the empty space (R-Type like). This is an option but is significantly more work compared to the above, and it might not necessarily give an improvement. For instance if there's lots of bg anyway, it might be more effective to just rotate everything in an unrolled loop.

Regarding the AY music, specifically if you want the AY music player to run at 50Hz but it's inconvenient for some reason. Typically, AY players have a buffer for AY register values which are OUTput at the end of its execution, independently from parsing the song data. It's possible to separate the parsing stage and the OUTput stage completely in the player code, so instead of a single CALL Player, you would have two: CALL ParseSong: CALL OutputAYRegs. In that case, you can do this. After a HALT, do CALL ParseSong: CALL OutputAYRegs: CALL ParseSong. Then after 'roughly' a frame worth of other tasks (a second HALT might be useful here), CALL OutputAYRegs again. Due to the fact that the OUTput stage itself is fairly fast, it shouldn't disturb the flow of your other procedures much, even if this has to happen amidst the 'critical' screen stuff updates.
2 x

AndyC
Berk
Posts: 10
Joined: Mon Nov 13, 2017 5:12 am

Re: Edge Grinder for the Spectrum

Post by AndyC » Tue Nov 14, 2017 6:34 pm

If you need the AY routine to be called at 50fps but don't want to wait for HALTs, why not just call it from within the interrupt handler itself? Your music might go iffy I suppose if you DI for too long, but that's probably as true for any other strategy. Alternatively count frames in the interrupt handler, call a music handler whenever you can and only have that actually call the real AY routine if the frame count has increased.
0 x

Post Reply