News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu

VSync help! (Sharp MZ-80A !)

Started by kelp7, 09:49, 06 February 14

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

kelp7

Apologies for the n00b question, but I really would love to have a bit of help understanding the bit of code at the top of this page:


Synchronising with the CRTC and display - CPCWiki


We're loading the b register with $F5 and immediately afterwards using the IN opcode which specifies the c register. I understand that it implies using the address held in the BC register pair. Why does the code not need to load the c register with any value before doing this? Presumably there could be garbage in the c register at this point? Or does it not matter when the address range begins at $F5xx


Thanks for any help understanding this!


kelp

fano

#1
The Z80 places BC on address bus when doing IN or OUT.On CPC , only high byte is decoded for PPI so you can have garbage in C.

ld B,#F5
.sync
in A,(C)
rra
jr nc,.sync



Will wait the start of the Vsync but logicaly you can do :


ld B,#F5
.sync
inc C,(C)
rr C
jr nc,.sync
"NOP" is the perfect program : short , fast and (known) bug free

Follow Easter Egg products on Facebook !

kelp7

Perfect, thank you for the very quick answer!
kelp

kelp7

Actually, is your inc C,(C) correct in the 2nd example?Also, I do have another question. Is it ever useful to wait for HSYNC? Can you wait for a specific line of the display to make changes while the beam creates the image? Or can you only do this at the top of the screen, not an arbitrary location any line down the screen? I presume it uses up a lot of CPU time...

arnoldemu

Quote from: kelp7 on 14:17, 07 February 14
Actually, is your inc C,(C) correct in the 2nd example?Also, I do have another question. Is it ever useful to wait for HSYNC? Can you wait for a specific line of the display to make changes while the beam creates the image? Or can you only do this at the top of the screen, not an arbitrary location any line down the screen? I presume it uses up a lot of CPU time...
I think this is a mistake and should be


in c,(c)


it's not possible to wait for hsync.

What you need to do is wait for a specific interrupt.
Then use NOPs to burn cycles until you get to the position you want.
Now you can change colours.

Like this:
http://cpctech.cpc-live.com/source/hwintdelay.asm

Look on Unofficial Amstrad WWW Resource and look in the "source" section and under "source-interrupt".

Lots of examples here show various methods for waiting for using interrupts, and the delay example shows how you then burn cycles to get to a point after an interrupt.


Look for this too "Border colours indicating the interrupt position and how the vsync relates to the position".
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

If you use a ctc-ay hardware device you have programmable raster interrupts.
In addition you can have programmable raster interrupts on the amstrad plus.

More examples on my website show this. (no example for ctc-ay based interrupt yet).
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

kelp7

I think that tells me everything I need to know! :) Thanks very much for your help both of you...
kelp

kelp7

Actually, there is just one last question and I'll be happy :)


On the CPC, what is the trigger of the interrupt? Is this different for different Z80-based computers?


thanks!

arnoldemu

#8
Quote from: kelp7 on 17:34, 07 February 14
Actually, there is just one last question and I'll be happy :)


On the CPC, what is the trigger of the interrupt? Is this different for different Z80-based computers?


thanks!

The Gate-Array chip inside the CPC counts HSYNCs. When it counts 52 of them it triggers an interrupt and then resets the counter.
so each interrupt is 52 lines apart. There are 6 per frame. One coincides with the vsync.

The spectrum for example has a single interrupt happening at vsync time. That is it.

The Amstrad plus can have raster interrupts where you can say which line it will interrupt on. To use this you need to activate the special features first.

The CTC-AY hardware for the CPC has a timer chip inside it. You can define the frequency at which it interrupts. One of the triggers is HSYNC, so you can tell it to count x number of hsyncs and interrupt.


It depends on the hardware that is in the machine generally.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

kelp7

Thanks so much for your help arnoldemu (and for being patient with me!). This is a massive help for me!
Cheers
Kelp

arnoldemu

Quote from: kelp7 on 21:09, 07 February 14
Thanks so much for your help arnoldemu (and for being patient with me!). This is a massive help for me!
Cheers
Kelp
no problem at all :)

If I can make my examples more friendly please tell me and I will add extra comments/information.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

fano

Quote from: kelp7 on 14:17, 07 February 14
Actually, is your inc C,(C) correct in the 2nd example?
my bad , typed to fast , lol , yep it is in C,(C)
"NOP" is the perfect program : short , fast and (known) bug free

Follow Easter Egg products on Facebook !

kelp7

Heh, no probs. I thought that might have been a mistake ;-)


Out of curiosity, is there any reason to use IN instruction rather than LD instruction. Seems you have to do more preparation with IN than if you just used LD A,($xxxx) ? More clock cycles?

fano

Simply because LD and IN/OUT are not in same logical space, LD is for memory space (ram/rom) , IN/OUT for I/O space ("active" chips), they share data and address buses but behaves on a diffrent way (memory are just storage and other chips have a specific behaviour).Some computers like Plus series uses IO mapped in memory space but the "active" chips have to be fast.


I/O instructions are slower because Z80 has to 'wait' other chips that are slower than CPU.
"NOP" is the perfect program : short , fast and (known) bug free

Follow Easter Egg products on Facebook !

kelp7

Very interesting, thank you! That explains a lot.

kelp7

Hi again,


I think i've come up with one more question on this subject  ;D


When you consider the code of your main game loop, would you wait for vsync to begin and then carry out all the main game code. Or, a different scenario : would you perhaps wait for vsync to finish, carry out all operations that aren't related to the screen (such as key / joystick movements, calculating opponent AI etc) and then wait for vsync to begin and carry out all screen operations? What's the best method?


Thanks
Kelp

redbox

Quote from: kelp7 on 22:39, 03 March 14
When you consider the code of your main game loop, would you wait for vsync to begin and then carry out all the main game code. Or, a different scenario : would you perhaps wait for vsync to finish, carry out all operations that aren't related to the screen (such as key / joystick movements, calculating opponent AI etc) and then wait for vsync to begin and carry out all screen operations? What's the best method?

Usually best to avoid graphics routines during the frame time where the screen is displayed as otherwise you can get flicker or tearing.

If this isn't possible, you can double buffer - i.e. have two screens (one displayed, one hidden) and you draw to the hidden one and switch between them each frame.

kelp7

Oh yeah definitely! That I understand without question. What I mean is, do you separate out your game code so that all the non-screen updating code happens during screen draw (when it doesn't matter) and then do all screen-updating code during vertical flyback ? Or do you just try and fit all of your game code into the vertical flyback?


I know this is probably a silly question!

Axelay

Quote from: kelp7 on 09:04, 04 March 14
Oh yeah definitely! That I understand without question. What I mean is, do you separate out your game code so that all the non-screen updating code happens during screen draw (when it doesn't matter) and then do all screen-updating code during vertical flyback ? Or do you just try and fit all of your game code into the vertical flyback?


You wouldnt get a lot of graphics drawn during vsync, it doesnt take that long!   :) Check the image halfway down this page under the CRTC heading, Vsync lasts just 3 characters out of a frame that's 39 characters long (or high, if you prefer, I think of it as cpu time though).


But you dont need to restrict graphical operations on the visible screen to during vsync, you can do them whenever you like, so long as the beam isnt updating that part of the screen at that very moment.  So if you have a 20 character high play area, then looking at that diagram of the screen I linked, you'd still have almost half the screen worth of cpu time where you could write anywhere you like to the play area and it wont be visible as flicker or tearing.  After that though, you'd need to start considering Y ordering your sprite updates, double buffering, or whatever other approach suited your game.


arnoldemu

Quote from: kelp7 on 09:04, 04 March 14
Oh yeah definitely! That I understand without question. What I mean is, do you separate out your game code so that all the non-screen updating code happens during screen draw (when it doesn't matter) and then do all screen-updating code during vertical flyback ? Or do you just try and fit all of your game code into the vertical flyback?


I know this is probably a silly question!
I use the hardware double buffering so I have an entire frame for all my game logic and drawing.

If I didn't use that, then I would draw my sprites from bottom to top (minimises tearing), and composite sprites to an off screen buffer before drawing.

EDIT: I do wait for vsync in my loop, but generally that is more for synchronisation rather than to decide when to draw.

I hope some of this helps. Please feel free to check out my website to see examples of some of these:

Unofficial Amstrad WWW Resource
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

kelp7

Thanks both of you! Yeah, that makes a lot more sense now and thanks for the links!

arnoldemu

The time that should be more interesting is not the vsync time but the time where there are borders.

You can safely do screen updates during border time. In reality this reduces to the time you have during the bottom and top borders. Doing useful time during the side borders is possible but harder to code.

The time where the borders are active depends on the screen size (which can be altered by programming the crtc). The time is much longer than the vsync.

In addition, you can potentially do work during the graphics display if you work "behind" the screen refresh. This means waiting for the graphics to start drawing, then doing your drawing code. The time between vsync and the first graphical line is quite a bit of time. The "waiting" time could be used for ai, keyboard, sound updates that kind of thing.

But, to make this latter method work you need to do everything with 1 frame or you'll get flickering.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

kelp7

Okay, time to confess, (as I already have in private message to arnoldemu) : I am actually trying to code Z80 for another machine other than an Amstrad CPC. I should have stated this at the start of the discussion. I came here because there is little to no help anywhere else for the machine I am coding for. I'm pretty much on my own here. I'm programming the Sharp MZ-80A which I feel has been grossly under appreciated and never had the kind of games that I think it has the potential for. Sorry, I wasn't trying to deceive anyone but just felt a bit embarrassed that there was nowhere else to ask.


That said, should this thread perhaps be moved to the 'other retro' forum perhaps?


I still very much appreciate the help I have been given so far. It's all given me a deeper understanding of how to code around graphics / vblank etc. The MZ machine has no real graphics of its own, it is all text based. There is a character ROM which contains 255 different symbols (including standard ASCII of course) but this is not changeable. I am trying to work out if I can do some tricks with this machine to enable me to show graphics on the screen in a way that no-one has managed to do before for the MZ.


Luckily, I am working just with a text-based screen, therefore, of dimensions 40x25 so any screen updates are going to be pretty quick. For instance, the screen memory starts at $D000 and if you "LD ($D000),0" you instantly see display code 0 on the top-left corner. So I was hoping that there'd be enough speed on this 2Mhz machine to fill the screen with bytes or do entire screen displays within the time limit given during vertical flyback.


Perhaps, as arnoldemu has suggested privately to me, I need to update the screen behind the beam so that the change is only seen on the next frame. I guess this will require some precise code timings.


Anyway, if I can just get the synchronisation with Vsync working on this machine (it's in a memory mapped I/O address of $E002 at the most significant bit) and prove that it works then this could potentially open up the opportunity of just waiting for Vsync to begin, then burning lots of cycles with NOPs and attempting to alter the display scanline by scanline. That way I could really prove to do some interesting effects that have never been done before.


So thanks again for all your help. I think if I can just master programming this machine and do something great with it that hasn't been done before then perhaps I can move onto another machine, say, the Amstrad CPC  ;)


Thanks
kelp

Xifos

The problem is that you've got only char generator without changes ability.
Maybe you could achieve 80x50 graphics if there are four "quarter squares" in the character set ?
Or go for the sharp mz-800 ?
;)

arnoldemu

You could potentially switch between 2 characters. 1 character is shown one frame, other the next etc.
It would flicker.

another possibility is changing colour, you could change colour and perhaps achieve 8 colours in a cell?
this may be possible.

Or even, say goodbye to the graphics, and just change colours?

Have you tried writing random numbers to these mapped i/o? Perhaps you can get it to do something which is not documented?

Is there a picture of all the characters available?
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Powered by SMFPacks Menu Editor Mod