Author Topic: Clock Signal: for the Mac and Linux  (Read 2153 times)

0 Members and 1 Guest are viewing this topic.

Offline ThomH

  • CPC464
  • **
  • Posts: 47
  • Country: us
  • Liked: 37
Clock Signal: for the Mac and Linux
« on: 05:23, 28 August 17 »

I couldn't decide whether to bother mentioning this or not, as it's not immediately going to be of any real interest, but: I've started putting builds of my new CPC emulator online.

To be worth your time you must be: a Mac user, whose primary use for a CPC is games, who thinks an emulator should be as invisible as possible.

Up-front admission: emulation is presently imperfect. I believe this is due to an unrelated collection of small inaccuracies, not due to any bad structural assumptions, but the effect is the same. Moderately-clever titles like Turrican and Axys work correctly. Prehistorik II doesn't even load, as it seems not to like my FDC, but in that it's almost unique. Demos are highly variable.

It does the following things perhaps worthy of mention:
  • it's an ordinary document-centric, fully native application. Load as many titles as you want at the same time, size and position them however you want, across as many screens as you like;
  • don't worry about figuring out what to type to load disks, it'll figure it out for you. The target audience is people who might like to try some CPC software, even if they've not used one before and don't fancy reading a manual. Just double-click the DSK/CDT/HFE and the emulator will take it from there;
  • it's strongly committed to doing the proper signals-processing thing where it can. For example, AY audio is generated as a 1Mhz wave, then FIR resampled to whatever your machine supports. Macs using their internal audio are, I think, 48Khz by default but every single one can be turned up to 96Khz using the built-in hardware. And maybe you have external hardware. Output will scale to it;
  • ditto the display handling differs substantially from the emulator norm: just like if you pointed a 140Hz camera at a CRT, it would produce video with 140 *different* frames per second, if you have a 140Hz monitor you will see 140 different frames produced by the emulator. It's painted live, with an emulation of phosphor decay. For ordinary computer users its main claim to fame is that 50Hz output like that of the CPC is scaled up to the 60Hz of most current computers a lot more intelligently than judder-every-fifth-frame;
  • it tries really hard to avoid latency. Video content isn't held back because the rest of its frame is incomplete, and audio updates are completely decoupled. The emulator aims for 5ms latency, but rounds that buffer to a power of two, so you might get slightly worse; and
  • it is sufficiently dedicated to doing everything using the real processes, that it gets the output aspect ratio correct, without it actually being expressed anywhere. Low-pass filtering makes the output of non-square pixels a non-issue even on my old machine. If you have a 'retina' machine then you'll probably do even better.
It's Mac only 'for now' but consciously seeks not to be so for all eternity.

Various implementation details now follow, because it's a Mac app. So the number of other emulator writers reading this probably outnumbers the potential audience of users.

Other than the Mac parts, it's C++ because it's a multi-machine emulator and templating is a natural way to compose behaviour without undue runtime overhead.

It's one of those that seeks to obtain correct timing through proper strobing of the WAIT line. It has no concept of CPC-specific timings beyond asserting WAIT 75% of the time.

Similarly, the 6845, 8255, FDC and AY have no sense that they're in a CPC. They're completely generic, with the CPC opting to wire everything together.

It's all cycle-oriented, I'm not doing anything crazy like "wait 64 cycles, do another line of output" or whatever. Actually, the Z80 and the CPC bus are clocked in half cycles because the Z80 samples WAIT on the half cycle, not at cycle boundaries.

Similarly, the FDC is doing the real FDC things. It steps at the rate you told it to step. The disk beneath it spins at 300RPM. To load a sector it watches the output of a PLL for the appropriate syncs and marks. There is however an implementation error here: when I built the disk subsystem I erroneously believed that drives are completely passive. They're not: the test for ready is motor on plus two index holes. Correcting that is going to be a minor hassle given that I don't want just to hack it so the ready signal is knowingly wrong at present.

Oh, and DSK files will present as though writeable, and you can modify them in memory, but changes aren't written to the disk image. My in-memory format for disks is well-established and even less restrictive than the usual 'exactly regular bit stream', but as a result I need to write a to-DSK parser and I haven't yet. HFE files know that they're read-only, but should be much easier to write out as I can just fire up another PLL and write whatever it sees in order to regularise the clock.

So, yeah, actually it's a lot more interesting to discuss as an implentation than as a product, given that it does all these knowingly-general things with never a short-cut or a substantial assumption, but still *often gets the answer wrong*.

I'll post updates as and when appropriate, but right now my only concrete plans are as to how to improve the FDC. More enlightenment is required as to the CRTC and gang. So we'll see. I might never catch up with the better options.
« Last Edit: 19:03, 13 June 18 by ThomH »

Offline mr_lou

  • 6128 Plus
  • ******
  • Posts: 2.597
  • Country: dk
    • index.php?action=treasury
    • The Music Resource for the Indie Game Developer
  • Liked: 813
Re: Adding mine to the emulator pool
« Reply #1 on: 07:01, 28 August 17 »
Well I'm not a Mac user, but this sounds like an awesome project!

I especially like just clicking a DSK file. Just like Wine works. That's how it should be. And when it's done like that, we can claim any CPC production to be multi-platform just like any .NET developer does.  :D

I also like the screen frame part, too smooth out the jerkiness otherwise seen on 60 hz displays.

Looking forward to see a YouTube demonstrating this emulator some day in the future.

Offline phi2x

  • 464 Plus
  • *****
  • Posts: 458
  • Country: fr
    • CPCBox - CPC emulator in JavaScript
  • Liked: 151
Re: Adding mine to the emulator pool
« Reply #2 on: 13:56, 28 August 17 »
That's some bold claims ThomH :o

Will you consider adding Amstrad Plus emulation in the future?
That's where Z80 cycle accuracy could truely shine, due to the memory mapped interface to the ASIC chip.
Atwood's law (2007): "Any application that can be written in JavaScript, will eventually be written in JavaScript."

Offline ThomH

  • CPC464
  • **
  • Posts: 47
  • Country: us
  • Liked: 37
Re: Adding mine to the emulator pool
« Reply #3 on: 05:30, 29 August 17 »
That's some bold claims ThomH
Even if my code proves not to be up to snuff, I think there's at least validity in the ideas. From first principles: when a real Amstrad CPC's monitor fires its electron gun, the pixel appears immediately. So that's a latency of 0ms.

By painting pixels as soon as I have them, I inflict a frame's worth of latency on the very first, and 0ms on the very last. So I inflict a fixed average of half a frame of latency.

Assuming otherwise perfect timing, for a whole-frame-at-a-time approach of 50Hz to 60Hz mapping I make the average latency 1.2 frames (workings attached).

Therefore if you accept that the mild frame accumulation that comes with simulating phosphor decay is enough to remedy tearing, and go all in on painting as it comes, you knock 0.7 frames of latency off — from 1.2 frames to 0.5.

Of course, you have to think it's a problem in the first place. But this is why it's good that there's more than one emulator in the world.

If ever I can perceptually match a real CPC or a Raspberry Pi with Arnold configured for 50Hz output, I'll be happy. Probably I'm just picking a different approach towards trying to optimise for the problem.

Will you consider adding Amstrad Plus emulation in the future?
That's where Z80 cycle accuracy could truely shine, due to the memory mapped interface to the ASIC chip.
I think probably I should figure out how to get the base hardware working properly first. If I can't manage that then probably Plus emulation isn't worthwhile for me to attempt.

Well I'm not a Mac user, but this sounds like an awesome project!

I especially like just clicking a DSK file. Just like Wine works. That's how it should be. And when it's done like that, we can claim any CPC production to be multi-platform just like any .NET developer does. 

I also like the screen frame part, too smooth out the jerkiness otherwise seen on 60 hz displays.

Looking forward to see a YouTube demonstrating this emulator some day in the future.
Here's the mea culpa: I changed jobs last week and as a result was required to give up access to an up-to-date retina MacBook Pro and a Mac Pro. I'm back on my six-year-old MacBook Air. Which isn't able to both run my emulator at 60Hz and record a video. So I've uploaded a small window capture of Robocop for the sake of uploading something and learnt that I probably need to do better at optimisation.

After accuracy, of course. That's the main problem.
« Last Edit: 05:33, 29 August 17 by ThomH »

Offline phi2x

  • 464 Plus
  • *****
  • Posts: 458
  • Country: fr
    • CPCBox - CPC emulator in JavaScript
  • Liked: 151
Re: Adding mine to the emulator pool
« Reply #4 on: 10:32, 29 August 17 »
I think probably I should figure out how to get the base hardware working properly first. If I can't manage that then probably Plus emulation isn't worthwhile for me to attempt.

By implementing cycle accuracy from the start, you avoid a lot of traps that we faced as emu authors as we tried to improve and perfect our own emulators.
So I believe that by having such solid foundations already in place you will be able to get record high compatibility real fast.

Frankly, the CRTC is a very primitive chip. It's just a bunch of counters.
By comparing what you get in your emu with the behaviour of top quality CPC emus like WinAPE or ACE I'm sure you'll figure it out in no time.
Those emulators have great debuggers that help a lot in figuring out what happens.

Still, a few things that are really important from the top of my mind:

- On the Z80 the wait line is probed at T3 for I/O access instead of T2 for memory access.
This misalignment matters a lot for CPC emulation as it explains why the OUT (C),r instruction will take 4µs to execute while being a (4,4,4) t-states instruction.

- Every CRTC type except CRTC Type1 use internal buffers for registers 4,5 & 9. That explains why CRTC Type1 is popular among the demoscene as it allows for abuse of the chip.
« Last Edit: 16:51, 29 August 17 by phi2x »
Atwood's law (2007): "Any application that can be written in JavaScript, will eventually be written in JavaScript."

Offline ThomH

  • CPC464
  • **
  • Posts: 47
  • Country: us
  • Liked: 37
Re: Adding mine to the emulator pool
« Reply #5 on: 03:28, 30 August 17 »
By implementing cycle accuracy from the start, you avoid a lot of traps that we faced as emu authors as we tried to improve and perfect our own emulators.
So I believe that by having such solid foundations already in place you will be able to get record high compatibility real fast.

Frankly, the CRTC is a very primitive chip. It's just a bunch of counters.
By comparing what you get in your emu with the behaviour of top quality CPC emus like WinAPE or ACE I'm sure you'll figure it out in no time.
Those emulators have great debuggers that help a lot in figuring out what happens.
I certainly hoped so, but right now I just feel like I'm randomly shunting parts of my CRTC to different places within the cycle and hoping for the best. Probably the correct concrete thing is to rig up an automated version of Arnold's compliance tests. Or I should at least come up with a concrete list of the things I think the documentation isn't quite explicit about, and tick off the possibilities systematically.

I guess there's also a chance that I'm getting the interrupt counter and/or Port B of the 8255 wrong in some sufficiently subtle way, but I think the CRTC itself is more likely. I've had to make some basic assumptions — e.g. that when people say that the counter is reset on vsync they mean "on vsync becoming active" (rather than in the other direction, as with hsync), and that when Grimware says "If the counter>=32 (bit5=1), then no interrupt request is issued" it actually means exactly the opposite — but I think they're all sound.

Still, a few things that are really important from the top of my mind:

- On the Z80 the wait line is probed at T3 for I/O access instead of T2 for memory access.
This misalignment matters a lot for CPC emulation as it explains why the OUT (C),r instruction will take 4µs to execute while being a (4,4,4) t-states instruction.
I think I have that correct. But for obvious reasons it isn't really covered by the standard tests (Zexall, the FUSE collection, etc), so that's definitely an area that is more suspicious than most. But mine should announce (i) 3 half-cycles of preparation; (ii) 2 half-cycles of enforced waiting; (iii) if the WAIT line is set then as many whole cycles as it takes to get to the next time when it is reset; then (iv) 3 more half-cycles of activity, before sampling the bus. And I'm strobing WAIT for three continuous cycles out of each four. It's probably worth putting a specific test in though.

As I write this I realise that actually means I'm sampling the bus half a cycle late, at least per this diagram, but I guess that I'll get away with it in a CPC because my CRTC doesn't mutate during the cycle immediately after the WAIT strobe, and therefore sampling it halfway through or at the end should give the same effect.

- Every CRTC type except CRTC Type1 use internal buffers for registers 4,5 & 9. That explains why CRTC Type1 is popular among the demoscene as it allows for abuse of the chip.
That I did not know, and mine is a type 0. Buffered at frame start, presumably?

Offline arnoldemu

  • Supporter
  • 6128 Plus
  • *
  • Posts: 5.273
  • Country: gb
    • Unofficial Amstrad WWW Resource
  • Liked: 2152
Re: Adding mine to the emulator pool
« Reply #6 on: 11:12, 30 August 17 »
I guess there's also a chance that I'm getting the interrupt counter and/or Port B of the 8255 wrong in some sufficiently subtle way, but I think the CRTC itself is more likely. I've had to make some basic assumptions — e.g. that when people say that the counter is reset on vsync they mean "on vsync becoming active" (rather than in the other direction, as with hsync), and that when Grimware says "If the counter>=32 (bit5=1), then no interrupt request is issued" it actually means exactly the opposite — but I think they're all sound.
The counter is reset 2 HSYNCs following the start of the VSYNC and it is the same time in the HSYNC when the counter is normally incremented (at the end of the HSYNC from the CRTC, not the cropped one from the GA).

If the counter has bit 5 set then the GA will not request an interrupt, this prevents no interrupt being closer than 32 "lines" but in effect it means 32 HSYNCs.


As I write this I realise that actually means I'm sampling the bus half a cycle late, at least per this diagram, but I guess that I'll get away with it in a CPC because my CRTC doesn't mutate during the cycle immediately after the WAIT strobe, and therefore sampling it halfway through or at the end should give the same effect.
That I did not know, and mine is a type 0. Buffered at frame start, presumably?
I do need to do work more on my tests because some of them are not automated and on the crtc ones you must read the source and move a line on the screen to observe the result. Not ideal.

In terms of CRTC's latching information, I don't know the implementation details (I don't know what the die says), but it's likely to be 1 bit of information for each thing it's remembering and it's more likely to be the comparison state rather than the register value.

So when VCC=R4 for example, some CRTCs (and I need to check which) will latch this. So that if you the re-program R4 it will still continue to remember the comparison and the frame will restart (VCC reset back to 0).

On some CRTC (again I will check - most likely type 1), if you set VCC=R4 then set it to another value, the comparison is immediate and it doesn't latch it.

My tests do show this but not all the tests are "run and it tells you if it's right or not" (I am trying to aim for this where possible) especially the crtc ones which I need to do more work on.

Sorry it took quite a lot of time to write the tests and to ensure they present some useful information and are accurate across various cpc configurations, so it does take a bit of time to update them and make them better, but I am making progress :)



« Last Edit: 11:30, 30 August 17 by arnoldemu »
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Offline ThomH

  • CPC464
  • **
  • Posts: 47
  • Country: us
  • Liked: 37
Re: Adding mine to the emulator pool
« Reply #7 on: 14:11, 30 August 17 »
The counter is reset 2 HSYNCs following the start of the VSYNC and it is the same time in the HSYNC when the counter is normally incremented (at the end of the HSYNC from the CRTC, not the cropped one from the GA).

If the counter has bit 5 set then the GA will not request an interrupt, this prevents no interrupt being closer than 32 "lines" but in effect it means 32 HSYNCs.
I still maintain that either the description is backwards or the test is. I've assumed the test, since inverting that makes no useful guarantee as to apacing.

At the beginning of signalling for the last interrupt, the counter was zeroed. Therefore if bit 5 is now set then it *has* been at least 32 HSYNCs. So to obey the not-closer-than-32 constraint, the test must be that if bit 5 *is set* then the gate array *will* request an interrupt. Not set => no interrupt.

Otherwise, a scenario if applied as written on (/by?) Grimware: interrupt occurs, is acknowledged almost immediately. So counter is now zero. This is also the vsync line. Two lines later, the counter is checked. It has value 2. So bit 5 is not set. So another interrupt is requested. That's two lines between interrupts.

Compare and contrast with doing the opposite test on bit 5: interrupt only if set.

Am I suffering a logic deficiency?

Offline arnoldemu

  • Supporter
  • 6128 Plus
  • *
  • Posts: 5.273
  • Country: gb
    • Unofficial Amstrad WWW Resource
  • Liked: 2152
Re: Adding mine to the emulator pool
« Reply #8 on: 14:57, 30 August 17 »
I still maintain that either the description is backwards or the test is. I've assumed the test, since inverting that makes no useful guarantee as to apacing.

At the beginning of signalling for the last interrupt, the counter was zeroed. Therefore if bit 5 is now set then it *has* been at least 32 HSYNCs. So to obey the not-closer-than-32 constraint, the test must be that if bit 5 *is set* then the gate array *will* request an interrupt. Not set => no interrupt.

Otherwise, a scenario if applied as written on (/by?) Grimware: interrupt occurs, is acknowledged almost immediately. So counter is now zero. This is also the vsync line. Two lines later, the counter is checked. It has value 2. So bit 5 is not set. So another interrupt is requested. That's two lines between interrupts.

Compare and contrast with doing the opposite test on bit 5: interrupt only if set.

Am I suffering a logic deficiency?
No you're not. I am.

You are correct with bit 5.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Offline robcfg

  • Supporter
  • 6128 Plus
  • *
  • Posts: 1.931
  • Country: se
  • 8-Bit Technomancer
    • index.php?action=treasury
  • Liked: 775
Re: Adding mine to the emulator pool
« Reply #9 on: 21:54, 31 August 17 »
Hi @ThomH !


I downloaded your emulator from github, but when I run the app file, I get no window at all, just the icon sitting on the taskbar.


Am I doing anything wrong or is it malfunctioning on my Mac?

Offline ThomH

  • CPC464
  • **
  • Posts: 47
  • Country: us
  • Liked: 37
Re: Adding mine to the emulator pool
« Reply #10 on: 00:12, 01 September 17 »
Hi @ThomH !

I downloaded your emulator from github, but when I run the app file, I get no window at all, just the icon sitting on the taskbar.

Am I doing anything wrong or is it malfunctioning on my Mac?

Apologies; being so new to the forum I just responded to the email that contains this message, but suspect that won't go anywhere. Hopefully this isn't a restatement.

Now that the emulator is on your system, you've a bunch of options. They're all the Mac norms, once you start thinking of each disk or tape image as a separate document.

So: launch it and use File -> Open... . Or, equivalently, drag and drop some media over its icon in the Dock.

It'll also be available as an associated application for DSK, HFE and CDT files so you can also get to it from the Finder. Right click and use 'Open With...', or set it as the default file type handler, or set it as the handler for each appropriate media image individually (which is easiest via the pull-down menu in each file's Info dialogue — either right click and open from the context menu, or select and press command+I).

To replace or augment the media in a running machine, drag and drop onto that machine's window. That's how you'd do something like insert a second disk rather than ending up with two different CPCs with two different disks inserted.

I almost certainly need to do the modern-Mac thing of throwing an Open dialogue in your face if you launch without any windows to restore. I think I need implicitly to opt in by declaring appropriate iCloud interoperability since Apple probably uses that as a hint. But I'll need to look that up.

For the record, it doesn't just show a machine with no media inserted because it wouldn't know which machine to show.

... and let me know how it goes! I've identified a race condition that can lead to a crash during machine shutdown through an accidental piece of circular logic that violates a safety mechanism in the threading*, but it's improbable and an easy fix. (EDIT: fixed; new binary provided, see same GutHub link)


* there's at least four of them for a CPC: that hosting most of the UI, that on which vertical retrace announcements are received from macOS, that on which almost all of the CPC runs, and that on which AY audio is generated and supplied to macOS. The CPC work thread can also paint OpenGL and usually does, but the UI thread also might do so, if it's responding to window resizing. The "paint whatever the current state of the CRT is" method is re-entrant and callable from any thread.
« Last Edit: 14:08, 01 September 17 by ThomH »

Offline Gryzor

  • Administrator
  • 6128 Plus
  • *****
  • Posts: 14.356
  • Country: gr
  • CPC-Wiki maintainer
    • CPCWiki
  • Liked: 2576
Re: Adding mine to the emulator pool
« Reply #11 on: 16:45, 01 September 17 »
No Mac here, but the more, the merrier :) Hope to see a Windows build sometime soon!


If I may suggest: accuracy is one thing, major one of course. Usability -UI and UX- is another, which I personally find very important... For a while WinCPC was my favorite emulator, despite it clearly not being the best out there, because I loved using it.


Also, yes, replying to the email notification goes back to me personally instead of the forum, hence the warning "do not reply to this message" :D

Offline ThomH

  • CPC464
  • **
  • Posts: 47
  • Country: us
  • Liked: 37
Re: Adding mine to the emulator pool
« Reply #12 on: 17:26, 01 September 17 »
No Mac here, but the more, the merriersmiley.gif Hope to see a Windows build sometime soon!

I've just started my first non-Mac-centric job in about a decade, so my horizons are widening again. So hopefully soon. In terms of what I can easily do without a Windows licence: how terrible are Qt applications on Windows? I might have biased that question a little.

I also really want to look at an Android solution, for Chromebooks mainly, but I keep dithering as to how best to handle the difference between desktop OpenGL and OpenGL ES without constantly breaking whatever I do. It's complicated by my dedication to proper composite video, though that isn't a CPC concern. Am I right to think that virtually nobody used one with a TV?


If I may suggest: accuracy is one thing, major one of course. Usability -UI and UX- is another, which I personally find very important... For a while WinCPC was my favorite emulator, despite it clearly not being the best out there, because I loved using it.

As implied above, at present there is no UI, to the point of being jarring. I've just used the native Mac class for being a multiple-document application and from that the OS inherently does the usual menu bar, segueing into lots of open documents, spread out as you like, etc. I'm optimistic that steps like automatic entry of disk loading commands go as far as possible in making the emulator invisible.

What I really want is that if somebody reads that Chase HQ is really good on the CPC, they can download it, double click it, and then play Chase HQ. No intermediate steps.


Also, yes, replying to the email notification goes back to me personally instead of the forum, hence the warning "do not reply to this message"cheesy.gif

Although it wouldn't be too startling if I'd missed such a warning, there was none in the email. Not in my phone's native mail application, and not via the GMail web interface. Can forward the original verbatim if it would help, but it's likely all there in my original reply.
« Last Edit: 17:57, 01 September 17 by Gryzor »

Offline Gryzor

  • Administrator
  • 6128 Plus
  • *****
  • Posts: 14.356
  • Country: gr
  • CPC-Wiki maintainer
    • CPCWiki
  • Liked: 2576
Re: Adding mine to the emulator pool
« Reply #13 on: 18:03, 01 September 17 »
I've just started my first non-Mac-centric job in about a decade, so my horizons are widening again. So hopefully soon. In terms of what I can easily do without a Windows licence: how terrible are Qt applications on Windows? I might have biased that question a little.


Ah ok, I skimmed the Mac description stuff because I don't know much about it anyway.


From experience, QT apps are not terrible. Sure, they feel a bit... strange in the non-native meaning, but it doesn't affect usability; so if you build it right, it'll be ok.

Quote
I also really want to look at an Android solution, for Chromebooks mainly, but I keep dithering as to how best to handle the difference between desktop OpenGL and OpenGL ES without constantly breaking whatever I do. It's complicated by my dedication to proper composite video, though that isn't a CPC concern. Am I right to think that virtually nobody used one with a TV?


Used what with a TV? A CPC? of course, many of us here :) If you're talking Android, I'd loooooove to see an emulator that can run on my Nvidia Shield and supporting controllers, though it would take quite some thinking to make it usable.


Quote
What I really want is that if somebody reads that Chase HQ is really good on the CPC, they can download it, double click it, and then play Chase HQ. No intermediate steps.


Reading again your description, that's an admirable approach. Kind like what TheCompany are doing with Amiga games, though from a different PoV.


Although it wouldn't be too startling if I'd missed such a warning, there was none in the email. Not in my phone's native mail application, and not via the GMail web interface. Can forward the original verbatim if it would help, but it's likely all there in my original reply.



I'll start eating my hat. I was sure there was such a warning like there is for PM notification, but there isn't :D Probably because it just doesn't make sense replying through email to a forum post, but I was wrong anyhow. 

Offline andycadley

  • Supporter
  • 6128 Plus
  • *
  • Posts: 770
  • Liked: 334
Re: Adding mine to the emulator pool
« Reply #14 on: 20:09, 01 September 17 »


how terrible are Qt applications on Windows? I might have biased that question a little.
QT is, well, functional probably best describes it. Using OpenGL over DirectX is probably a more troublesome choice on Windows, though I don't know how much that is abstracted away. Is the source on Github or something, I'd be quite interested in taking a look.

Offline ThomH

  • CPC464
  • **
  • Posts: 47
  • Country: us
  • Liked: 37
Re: Adding mine to the emulator pool
« Reply #15 on: 20:51, 01 September 17 »
QT is, well, functional probably best describes it. Using OpenGL over DirectX is probably a more troublesome choice on Windows, though I don't know how much that is abstracted away. Is the source on Github or something, I'd be quite interested in taking a look.


It is, but substantial disclaimers apply: having never actually been a serious C++ programmer before, this project has at least the partly selfish motivation of giving me an opportunity to learn modern C++. With the effect that several sections of it still look like the output of somebody learning C++. I think the largest error affecting the CPC side of things is that the penny dropped only yesterday that just because something is a template and therefore needs to provide its implementation for all to see, doesn't mean the implementation has to sit there within the class definition. So right now if you wanted to answer the question "what interface does the Z80 provide?" then you'd have to wade through the combined interface plus implementation. Ditto for many other things, but they tend to be much smaller — e.g. the 8255 just doesn't take up a lot of real estate.

See the 6502 pull request from yesterday for evidence that I am clearing this up.

Also I initially set out using the curiously-recurring template pattern, but have subsequently decided it was an inappropriate crutch, which I was leaning on because I was coming from the Java/Objective-C school of class hierarchies, without properly starting to embrace generic programming. That's now thrown out from everywhere the CPC touches except the AY. It's not a huge ugliness, just a semantic ugliness, and I'll fix it.

Also I've been a little too keen to embrace unsigned types where logically unsigned, but now understand that to be a mistake for various reasons. So I'm feeling that in.

Oh, and the 8272 implementation is moderately ugly. The main body of it looks a lot like machine code because of the way I've made it act a lot like a coroutine. I think it reads in a more straightfotward way than a bunch of other implementations I've subsequently seen, but I also think that I can do better. If you also check out the 1770 you'll see it does a very similar thing, but independently. I'm waiting until I'm fully convinced before I push them both into a final form.

Also, I intend to move the best-effort updater (the thing responsible for time counting) into the C++ world and come up with some sort of generalisation as to keyboard mapping before worrying about non-Mac platforms. But both are small tasks.

Preamble being done, important links are:

The CPC itself — everything specific to that hardware. Includes the gate array, so pixels embark from here.
The 6845 — needs the interface/implementation separation as above, but is less than 300 lines so you'll cope.
The 8255 — also will be separated, but is even more tiny.
The 8272 — such as it currently is. Lots of gaps as to properly representing the hardware but for the CPC the absence of the scan commands is the main one.
The AY — the first file I've linked to that predates my work on the CPC and fairly straightforward though if you check the commit history you'll see I've changed my guess as to when counters are reloaded since working on the CPC.
The Z80 — the very next thing I'm going to clean. Will look much better in a week. Key things to read are that machines with a Z80 must compose it with a BusHandler in order to effect that machine's bus. They'll receive PartialMachineCycles. Those are guaranteed to be sent at least once per Z80 decision. So they're effectively telling you the amount of time between bus samplings. With one caveat: whether to take an interrupt depends on historic bus state. So you can backdate that input signal. It's a pragmatic implementation decision. There's only one more thing the interface needs: to offer foresight of bus activity for any machine I might want to implement where the Z80 can't also be in charge of counting time. It's a small fix, and planned. The 6502 already doesn't have that problem.

The DSK, HFE and CDT implementations aren't that interesting, and I'll skip trying to explain the static analyser for brevity, but suffice to say it is meant to answer the question: "given this file, what machine and what configuration is needed to run it?". The CPC is currently implemented not to accept any file formats where the answer would currently be ambiguous but at some point it will involve a tape audio parser, which I'll then also leverage to offer fast ROM-format tape loading as an option. Correct hardware emulation is the default, conveniences are optional.

Offline andycadley

  • Supporter
  • 6128 Plus
  • *
  • Posts: 770
  • Liked: 334
Re: Adding mine to the emulator pool
« Reply #16 on: 21:44, 01 September 17 »


It is, but substantial disclaimers apply: having never actually been a serious C++ programmer before, this project has at least the partly selfish motivation of giving me an opportunity to learn modern C++.

I haven't written C++ since before standardization was a thing, but it's one of those things I'd not mind trying again. I might take a look just to see but I'd by no means claim to offer expert advise!

Offline ThomH

  • CPC464
  • **
  • Posts: 47
  • Country: us
  • Liked: 37
Re: Adding mine to the emulator pool
« Reply #17 on: 03:55, 02 September 17 »
Minor update: the Z80 has been significantly tidied up. Z80.hpp is now just a clean statement of the interface, with all the mess that results from it being a template now residing elsewhere. Other work will appear as it is completed, but that's the largest CPC-adjacent stain dealt with in terms of code quality — more than 2000 lines of intermingled interface and implementation* is now about 280 of pure interface, with complete and accurate documentation.


* again, to emphasise: having not fully considered the options, I believed this to be unavoidable when formulating as a template until a few days ago. So I was as unhappy about it as one can be, but believed it to be a language cost. Since it isn't, it is now corrected.
« Last Edit: 03:58, 02 September 17 by ThomH »

Offline ThomH

  • CPC464
  • **
  • Posts: 47
  • Country: us
  • Liked: 37
Re: Adding mine to the emulator pool
« Reply #18 on: 01:45, 05 September 17 »
Used what with a TV? A CPC? of course, many of us here :) If you're talking Android, I'd loooooove to see an emulator that can run on my Nvidia Shield and supporting controllers, though it would take quite some thinking to make it usable.
I meant the CPC, since everybody I knew as a child had the pack-in monitor.

Follow-up question though: is anything known about the logic used by an MP1/MP2 for generating the back porch and, in particular, the colour burst? Is it just throwing it out each time the signal exists sync? If so then do demos like Sugarlumps — which is one of those that allows consecutive scan lines to run without any sync — show black and white for large portions of the display? A fully standards-compliant PAL set is supposed to suppress colour decoding in the absence of a colour burst, as maybe it's receiving a black and white transmission, and if it's a real analogue set probably doesn't have any sort of memory that would allow it to apply a threshold test to that.
« Last Edit: 02:07, 05 September 17 by ThomH »

Offline arnoldemu

  • Supporter
  • 6128 Plus
  • *
  • Posts: 5.273
  • Country: gb
    • Unofficial Amstrad WWW Resource
  • Liked: 2152
Re: Adding mine to the emulator pool
« Reply #19 on: 11:39, 05 September 17 »
@ThomH:

It has been reported in Amstrad magazines that with the Amstrad modulator that if you set a short HSYNC then the image goes black and white. It was reported it happened with Ghosts n Goblins because it switches between a length of 5/6 for smoother horizontal scrolling. I haven't had any experience with this directly.

What I have seen with a SCART cable is that the image goes darker. You can also see colouration in the border above the display. When the border is set to black this problem is eliminated for normal screen sizes.

I have written a test that shows that pixels appear in the 4us HSYNC region when it's short. So it shows the GA doesn't clean the signal.

On the video master I set HSYNC to less than 5 and the display went black and white with a visible pattern moving over it. I had to turn the computer on and off to restore the colour because this caused the IC inside it to reset.

I think it depends on the IC used in the Amstrad modulators and what it does with the image. I believe the schematic is on the wiki.



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

Offline arnoldemu

  • Supporter
  • 6128 Plus
  • *
  • Posts: 5.273
  • Country: gb
    • Unofficial Amstrad WWW Resource
  • Liked: 2152
Re: Adding mine to the emulator pool
« Reply #20 on: 11:42, 05 September 17 »
I'll try and get some pictures of what I see but I'll be using a mobile phone not any special setup so the result may not be that clear.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Offline ThomH

  • CPC464
  • **
  • Posts: 47
  • Country: us
  • Liked: 37
Re: Adding mine to the emulator pool
« Reply #21 on: 03:42, 07 September 17 »
So based on the description it sounds like the implementation with at least one modulator is to use the luminance output from the CPC and add — possibly in the literal additive sense — a colour burst after each Gate Array sync? That would fit with the description of shortened horizontal syncs being problematic, as luminance wouldn't be at the blanking level even if the border is black, and if it's not black then there's probably colour information that would cause the colour burst not to be recognised?

My emulator has code in it already to do a composite encode and decode, because composite decode is what I do with machines that natively produce a composite signal, and a default composite encoder is available for machines which you'd expect to be used with a TV but for which further specifics aren't known. But to cut down redundant costs I've applied a rule that the composite signal is specified in segments — "blank for x cycles, then this byte stream for y cycles, using this GLSL snippet to convert between bytes and signal levels" and so far every machine has been able just to say "... and then a colour burst for z cycles". So I have a PLL that should be able to support genuine no-prior-knowledge PAL (and NTSC) composite colour decoding but so far have never tested it. I'll have to make a judgment call on whether to bother with that here, or just to insert an ideal colour subcarrier after every sync ends, I guess. I'll need to think about it.

In more practical terms, I'm working immediately on resolving the drive logic ownership design error as mentioned earlier. So I'm hoping to do that, then power onwards back up to the 8272. My short-term objective is that everything be able to load, even if it then acts incorrectly. A cool thing about the way I've set it up is that arbitrarily-timed flux transitions plus a PLL in principle allows weak sectors to be modelled just like on the real hardware, as simply having some bits right on window boundaries and having those happen to fall one way or the other due to random rotation speed noise. And this will be my first opportunity to find out whether that works.

Offline ThomH

  • CPC464
  • **
  • Posts: 47
  • Country: us
  • Liked: 37
Re: Adding mine to the emulator pool
« Reply #22 on: 23:20, 07 November 17 »
It's barely substantial enough to mention, but the latest release (at the top of here, as ever) has a few fixes over the previous for CPC users:
  • both HFE and DSK files are now writable — previously they were read-only;
  • there are some minor 8272 and 6845 improvements, though nothing huge; and
  • an alignment error in video output was fixed, making that slightly faster.
Most work has been under-the-hood, as towards working on platforms other than the Mac. An SDL proof-of-concept is pretty much ready to go, as long as you hate UIs, but that hasn't even quite formulated into a complete pull request yet.

Oh, and the 'ready' signal from the disk drive now does what it's really meant to do, though I'm not aware of any software on which that has an effect. General theme of my progress: everything's probably going to remain very incremental.

EDIT: minor note on DSK writing: it's a bit brute-force. It'll keep an in-memory copy of your complete disk image, and rewrite your entire DSK file at appropriate intervals. As a side effect, plain DSK files will be upgraded to Extended DSK. Can anybody think of a reason why that silent upgrade might be problematic? What about if it were to switch in the other direction if and when contents allow (i.e. all tracks the same size or close enough, no sectors that aren't either a real supported power of two or the 0x1800 special case)?
« Last Edit: 23:54, 07 November 17 by ThomH »

Offline ThomH

  • CPC464
  • **
  • Posts: 47
  • Country: us
  • Liked: 37
Re: Adding mine to the emulator pool
« Reply #23 on: 18:06, 13 November 17 »
Update on Linux compatibility:

The SDL-based UI-less mode has a build system and builds without warnings or errors under both Ubuntu 16.04 and 17.10. However my virtual machine doesn't support OpenGL 3 so I can't test locally. The one person who has tested remotely reported that although audio played, the emulator's window didn't paint. So I suspect an error in my use of SDL, but it's also possible that I've a mistake or two lurking on the OpenGL code. I'm possibly going to have to abandon the virtual machine, but we'll see, as I wanted to back-port to support GL ES 2+ anyway, even though it'll be a hassle not having access to integer operations on the GPU.

If anybody is curious enough, download or clone the latest source from GitHub, and run scons in OSBindings/SDL. Prerequisites are SDL 2, ZLib and OpenGL. That should produce a binary, clksignal. You'll want to put the CPC ROMs into either /usr/share/CLK/AmstradCPC or /usr/local/share/CLK/AmstradCPC. See here for a complete list of the filenames I selected, but if you're only going to load disk images then amsdos.rom, basic6128.rom and os6128.rom will suffice as it always picks 6128 emulation when loading disks*. Then launch with clksignal yourfile.dsk/hfe.

All SDL code is contained entirely within OSBindings/SDL/main.cpp as it's the sort of emulator that's designed to keep the platform binding out at the fringe. If you know SDL and can spot anything obvious that I'm doing wrong, let me know. I used to use 1.3 a lot but this is my first meeting with SDL 2.0. Also, if anybody tries it, and it doesn't work, a capture of the console might be helpful, though it'll mostly be 8272 logging after a couple of helpful comments re: the environment provided by SDL.

* actually, I think I might have left it as always picking the 6128 for everything, because I'm lazy.

EDIT: quick addendum: the problem seems not to be SDL misuse but rather some other issue in my OpenGL code. Given that it works correctly on the Mac but seemingly fails on an Intel-chipset-powered Ubuntu box there's a possibility you might be more lucky if you're an AMD or Nvidia user. In the meantime, I'm working on it.
« Last Edit: 23:06, 13 November 17 by ThomH »

Offline ThomH

  • CPC464
  • **
  • Posts: 47
  • Country: us
  • Liked: 37
Re: Adding mine to the emulator pool (EDIT: now also for Linux)
« Reply #24 on: 19:38, 26 November 17 »
Minor step forward, as per the title: this emulator now sports a Linux target.

Prerequisites are SDL 2, ZLib and OpenGL, plus Scons to build:
You'll end up with a clksignal binary. You'll need to supply the system ROMs; it'll tell you what you need if necessary.

Then launch with clksignal [your game].

That's the whole story, as I remain at the hard emulators-should-be-invisible end of the spectrum. An expected use case is setting up clksignal as an associated file handler for DSK, HFE, etc. Then just double click the DSK to run whatever's on it. The original software itself is the primary thing of interest, not the emulator.