Jump to content


  • Content Count

  • Joined

  • Last visited

Community Reputation

29 Excellent

About ThomH

  • Rank
    Chopper Commander

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. To sneak in some extra information on this while I'm sitting at my desk, watching some very slow automated tasks in my day job: Re: the stencil; this is used because the CRT is its own sealed component trying to act like a real CRT. So it's attempting to sync to any incoming signal, and it paints scans to a virtual set of phosphors, which subsequently suffer exponential decay. It actually does this in a matter decoupled from your machine's frame rate for the reason that if you have a gaming monitor at 120Hz or 144Hz it can then provide 120 or 144 distinct frames per second, just like a real-life CRT doesn't atomically flip from one frame to the next, and you gain a big graphical latency reduction. The stencil is related to the exponential decay — that's just a discrete in-framebuffer effect, as you'd probably guess, but given that machines may not produce regular sync, which may cause the number of pixels painted sometimes not to reach the edges of the display, an extra means is needed to keep track of which pixels haven't been repainted by the normal scan. A ColecoVision produces an entirely stable display, so it's not actually much help here, other than possibly for clearing up after the bouncing that happens during initial switch on. It is nevertheless essential to allow the virtual CRT to fulfill its stated contract, and in practice a big help to other machines the emulator implements. Re: 'revert to saved'; the Mac version is, as stated, a full native application. Specifically it's an NSDocument/NSDocumentController-type application with XIBs aplenty, utilising an NSOpenGLView, CVDisplayLink, CoreAudio and IOKit for joypads and so on. That's nice because I get all the window management and most of the default menu bar items and their implementations for free. But it means I have to respond properly to the NSDocument messages. So every so often it turns out there's a menu option that isn't working because I'm not responding to a message like I should. It's just usually not immediately obvious what I've done wrong because I'm relatively weak at AppKit. It's not like I've tried to add a 'revert to saved' feature and failed to test it, I've actually been entirely oblivious to the menu entry. The SDL port, which allows use under Linux and similar environments, is completely distinct. Not one jot of SDL is used on the Mac. I have every intention of switching to Metal given that OpenGL is now deprecated on the Mac, and as of this overhaul the use of OpenGL by a particular binding is entirely optional. In practice it can be specified at runtime, which gives me a fallback for non-Metal Macs. It's just unfortunate that I don't presently know that much about Metal right now. Tech nerd asides: if you've any experience of pootling around in emulation source code, you might now be imagining a viper's nest of #ifdefs and equivalent runtime selection mechanisms, and a project that will surely die quickly under its own weight. There's none of that. The machine owner supplies the delegates to receive audio and video content, and pushes changes in input controls, and that's the end of that. I keep angling towards a Windows or Android port and, if ever I go that way, that will mean extra code to handle DirectX and/or OpenGL ES, but will require zero lines difference within the emulation. It'll just be a new consumer, or two, of the information the emulation puts out.
  2. Cool! That's the big one dealt with then, at least. It strikes me now that I have actually never once tried to use the 'revert to saved' menu entry with my emulator. So I've no offhand guesses there; I'll file it and fix it, naturally, but it might be more like weeks than days, especially given that the weekend is almost at an end. Thanks again for all your input and help!
  3. Having a quick review, I'm actually asking for a slightly odd stencil mode — a 1bpp stencil. The only reason I did that was that I really only need one bit. Would you be willing to try the attached build, which ups the request to 8 bits, for no reason other than it being a little more likely to be supported? I'm really grateful for the feedback so far, regardless! Clock Signal 8bpp stencil.zip
  4. It's still only S-Video, so the two colour channels are being QAM encoded and decoded, giving them an upper bandwidth bound, but you'll probably be hard-pressed to spot it. It's a completely different issue at least: GL_FRAMEBUFFER_UNSUPPORTED; presumably from my attempt to use a stencil buffer, though that surprises me a lot since they've been supported in hardware for 20 years. Out of interest, which GPU does your Mac have? I've tested on a 2011 MacBook Air, which I had assumed to be one of the lowliest Macs for 10.13 with its Intel integrated non-Metal-compatible GPU, but I guess that wasn't a safe assumption. I'll do some research. You might be able to use one of the older releases, which don't attempt to use a stencil at all. But we'll see. And the timing will be slightly off — no M1 delay, short SN waits — and you'll get composite video only. With some luminance aliasing, but it's another thing it'd possibly be hard to notice with ColecoVision software.
  5. Having tested on a 10.13 Mac, I was easily able to reproduce the issue; it should now be fixed. So I've thrown up a new release.
  6. Attached; a build that allows S-Video output from the ColecoVision. @mumbai it's late, so I might be very askew on my guess, but to me that looks potentially like I've got a dumb race condition on machine startup. So if it correlates at all with running the thing on 10.13 then that's purely luck. Try the attached, but failing that I'll throw myself back at it tomorrow. (there's more complicated threading than most emulators primarily in an attempt to reduce latency — e.g. so that decisions about the size of my audio packets are completely distinct from any video-frame-related considerations. In practice I aim for 5–10ms latency on audio) Clock Signal.zip
  7. Yeah, now I think of it, it's probably very dodgy of me still to claim compatibility back to 10.10 as I haven't tested on anything other than 10.14 for a while; I'll either dig out my 10.13 Mac or, if I can find it for download, put it in a virtual machine. This is absolutely not user error — the app should work exactly like any other native app, including for File -> Open, file associations and — option three — dragging and dropping onto its icon on the Dock. Re: the CRT look, that's actually a consequence of the full composite video pipeline. It's not deliberately downgrading it, that's genuinely the best composite decoding I've so far managed to produce — though the TMS's in-phase video (in NTSC, anyway) makes composite even worse than it usually is. This, I'm certain, is what the Karl Guttag memos mean by the rainbow effect. That excuse being made, the emulator can also do S-Video and RGB pipelines from the TMS. So I'll just enable one or both of those for the ColecoVision. My original thinking was a bit hard line probably, i.e. that the real ColecoVision has only an RF connector, and composite is as close as I get to RF, so that's that. That should be a really easy change. Definitely possible tomorrow. (EDIT: nerd aside: that's not some dumb "startup effect" making the screen bounce like that when you switch the machine on, by the way, that's because my emulated CRT really needs to establish sync with the input machine. Since it's just decoding a linear video stream and all, it doesn't have foreknowledge of the 2d-ness of it all.)
  8. This emulator has been updated to correct two timing errors: an M1 delay has been added; and the SN-generated WAIT has been extended to the correct length, having been off by over 90% (!). Some people don't always spot sentences about clock dividers. Otherwise, as a reminder, it's: a completely Cocoa-native application on the Mac; that also supports building for SDL for other UNIX platforms; which emulates at full cycle fidelity (the CPU, the VDP, everything); including its Super Game Module emulation; which builds its audio stream by producing a full machine clock-rate audio stream and then filtering that down to whatever your machine can handle (so: all speech effects, etc, should work perfectly, despite the code containing zero special cases); which builds its video stream as genuine composite video and then decodes the same on your GPU; which supports USB and Bluetooth joypads; which puts no restrictions whatsoever on window sizes, or how many ColecoVisions you have running at once, across however many screens (or even tabbed); and which requires no setup whatsoever. Just double click your game and play. It's MIT licensed, and available here. Feedback always appreciated!
  9. It's a little reading between the lines, and not exactly how I stated it above, but my expectation in that area comes from the Z80 manual, specifically the Z80 instruction breakdown by machine cycle that begins on page 85 where e.g. the machine cycle breakdown for ALU A, (IX+d) is described as (page 88): OCF(4), OCF(4), OD(3), IO(5), MR(3) Which, to save you the effort of looking up the key, means: opcode fetch (4 cycles), opcode fetch (4 cycles), operand data read (3 cycles), internal operation (5 cycles), memory read (3 cycles) The whole instruction is of course two opcodes plus the offset that forms the '+d', but the time that it takes to read the offset is 3 cycles rather than 4. So immediately you know that there's no refresh cycle in there, and a relatively safe assumption is that it's just a normal read cycle. That's even though the '+d' comes from the program counter like a real opcode. There's certainly no three-cycle pattern documented that signals M1, and M1 is documented as occurring only during "the op code fetch cycle of an instruction execution". That's elsewhere in the manual, alas, but I think it's likely that it means "opcode fetch" in the same sense as does the timing diagram — i.e. not to include operand data reads. Admittedly that doesn't amount to establishing the absence of an M1 beyond reasonable doubt, but I'd argue it's beyond balance of probability. Sadly I'm not aware of anybody that has ever just connected up an oscilloscope and produced hard evidence either way. EDIT: though, actually, further weak evidence on that particular type of instruction being weird is that, if memory serves, immediate operand instructions like LD (IX+2), 32 put the immediate operand before the offset, which means it's the only instruction where the immediate operand isn't the final thing. Or maybe it's just me that often trips up on that.
  10. Great, thanks for your reply! My previous thread, apart from reaching the wrong conclusion, gained no traction whatsoever so the unprompted mention of a sound chip wait period here was too much to pass up. So I guess it depends most strongly on what you think the SN76489 data sheet is trying to communicate with an "approximately" 32-cycle wait — e.g. is it a fixed period independent of the clock rendered into cycles on the assumption of a 4Mhz clock? — but if it were exactly 32 then I'd expect an output cycle to be extended by an additional 31 cycles both naively, given the single cycle of wait that's built in, and by thinking about when WAIT would first be sampled high if the 32 count kicked in exactly on the downward transition of T2. So the whole machine cycle would be 35 cycles. On the separate issue of the M1, yeah, I understand that to be a single cycle delay during the M1 machine cycle. So it's then the same length as every other memory access cycle. So it's five cycles for a plain NOP, as refresh isn't affected, and the differences to more complicated instructions depend on whether they signal M1 during opcode fetch. Speaking extemporaneously only, I think that some of the more compound forms, like the (ix+d)/(iy+d)s, don't actually signal M1 for everything they fetch from the PC — if memory serves then the opcodes after the offset are issued as ordinary read cycles. Or maybe I'm thinking of the offsets. Either way, I'm pretty confident I have it implemented properly in my little simulator.
  11. In case anybody finds this in the future; I had failed to spot the divide-by-eight that precedes the four-cycle number. So the conclusion posited above is incorrect. See http://atariage.com/forums/topic/286986-m1-delay/ for real discussion of this topic.
  12. Apologies, I'm unclear how to interpret this, so I'm going to ask a further follow-up. I'm looking at this timing diagram: I count T1 high, T1 low and T2 high before WR and IORQ go low. So is that not 1.5 cycles before the SN can possibly receive chip enable? (rounded to half cycles, anyway) Then it's another low/high to the first sampling of WAIT, then however long the SN is still holding that for, with that total delay rounded up to a whole number of Z80 clocks because that's how often the Z80 seems to sample, then another low/high/low to complete the machine cycle. ... I think that last part clears it up for me regardless. It really is 32 cycles, in terms of the same clock as the Z80, between chip enable and the WAIT(/READY) line deactivating. I had failed to observe that the same behaviour would happen on an input, but I guess since there's no reason to perform an input that maps to the SN, I hadn't really thought about it. Yes, that sounds like a good excuse.
  13. Actually, belated follow-up on that: is the sound chip delay just a single cycle? The data sheet mentions an "approximately" 32-cycle delay being signalled via the READY line, which goes straight to WAIT, starting from chip select going active. So shouldn't the Z80: begin its output cycle; trigger the SN's chip enable 1.5 cycles after that, when write goes low; 1 cycle after that sample WAIT and spot that it needs to wait; have to wait for "approximately" 32 - 1 = 30 cycles; then do the last cycles and a half of its output cycle? So that's 31 extra cycles? That sounds like a huge amount, so I'm sure I'm getting something wrong here.
  14. Looking at this schematic I see a 74LS74A which appears to be set up to trigger a cycle of WAIT upon every M1. That's not too uncommon for Z80 machines because it extends the opcode fetch read from 2 cycles to 3, moving it into line with most other accesses. It's even offered as a sample external circuit in at least one of the Z80 data sheets. Yet I've never heard about that in ColecoVision world. It would if I'm reading things correctly give operations the same cost as on the MSX. So e.g. NOP would take 5 cycles, not 4. Since I trust my schematic reading maybe only 70%, having no formal grounding in electronics, can anybody confirm or deny that the ColecoVision inserts an extra cycle into every M1 machine cycle?
  15. Being primarily an emulator author [of no significance], I may be viewing this from the other side of the spectrum: lack of in-depth documentation makes it an extraordinarily difficult platform to build a realistic model of; this is reflected in the fact that even with only 73 commercial titles, there still isn't an emulator that runs all of them completely without issues; and the consequence of it is that development is very difficult. If programming for something like a C64, a modern emulator is safe to trust to complete 99% of the job, but on a Lynx I would nowadays be reluctant to write almost anything without verifying it on real hardware regularly. So my argument would be: the absence of exact timing information that can be relied upon is problematic for potential authors of new software because it restricts the tooling. I am absolutely able to believe that the Jaguar is an order of magnitude worse but, no, I've no direct experience.
  • Create New...