Enterprise Forever
:UK => Emulators => Topic started by: TomH on 2021.July.03. 20:00:21
-
Very minor: I've added Enterprise emulation to the emulator that I write, Clock Signal, for macOS and other Unixes.
GitHub (https://github.com/TomHarte/CLK); macOS binary releases (https://github.com/TomHarte/CLK/releases); Linux binary releases via Snapcraft (https://snapcraft.io/clock-signal).
On macOS it's a fully-native, signed application using Metal and the native UI. Elsewhere it is available both as a Qt GUI application and as an SDL build that's more useful for command-line invocation and for file associations.
Probably its most interesting feature is that it can simulate composite video by generating and then decoding the actual composite video stream. No post hoc blur-it-up-a-bit filters here. It also does audio by sampling internally at a sensible native rate for the emulated machine and then low-pass filtering down to whatever your host machine can output. So e.g. on any garden-variety Mac from the last decade or so you can listen to your Enterprise at 96 kHz.
That all being said, Enterprise support is very provisional and known to be imperfect. So tolerate it only as far as you can.
Specifically:
- it supports IMG files only, there's presently no other way to load software; and
- something is definitely off in terms of timing.
Notable software issues of which I'm aware include the conversion of the CPC version of Chase HQ playing its sampled sound (like 'Let's go, Mr Driver!' way too quickly, but then weirdly slowing way down every time it would make a sound effect that the Spectrum would use its toggle speaker for; and SIDBASIC reporting a 3MHz CPU And then just not playing any audio. Like, no Dave writes at all, not like I'm processing the audio incorrectly.
Any other feedback would be greatly appreciated. Some screenshots are attached. Alternatively, here it is on YouTube (https://www.youtube.com/watch?v=bweTA1xrf3M).
---
Some random technical details, in case they're interesting:
In this implementation Nick runs 40434603/11360000ths as fast as the CPU, which is currently always 4Mhz. So I've clocked Nick at around 14.2375Mhz.
If the Z80 performs a Nick access it must wait to start the final clock cycle of its machine cycle until it is in the first two Nick cycles of the six-cycle block allocated for Z80 access. I should read mode on this. I observed that the entire six-cycle window is only around 1.68 Z80 cycles long, but of course the Z80 is paused in half-cycle increments so the maximum it could depend upon getting is 1.18 cycles of clear space. Hence fitting the final cycle into that window.
Nick's interrupt output is adjusted immediately after reading that byte of the mode line.
I wasn't clear on the correct way to transition between noise polynomials on Dave, so that's probably inaccurate. But the LFSRs all use IstvanV's documented polynomials, at least.
lgb.hu (http://ep.lgb.hu/doc/ports.html) mentions that "There is some odd behaviour that you can read the (Nick's) bus state on these I/O ports. In theory it can be used for some video effects. I can't say I can understand that very well though :)"; through a lack of further information reads from my Dave return the last byte fetched, if any, otherwise 0xff. That's permitting for the fact that I haven't read up on how the refresh addresses are generated though.
As per my reading of the documentation, column 10 is the first one output in composite mode. The colour burst covers columns 8 and 9. Output starts at column 8 in RGB mode, even on lines in which a mode line isn't read.
There's a simulated spinning platter for disks, so floppy access should be approximately real time.
Because the simulated CRT runs a couple of phase-locked loops to track discriminated syncs, you'll get some screen bouncing during phase-breaking display transitions.
It's likely I'll add tape image support before figuring out a way to bridge to the local filing system, though for the latter I'm thinking of maybe implementing an IDE drive and mapping FAT back and forth. That'd be more reusable with other machines I implement, e.g. the MSX and Atari ST both also use FAT12 and FAT16.
I forgot I hadn't yet implemented the 8/12MHz Dave divider. It'll be in the next release. I don't think it factors into any of the known incompatibilities.
-
Cool :-)
I will try to test it next week if i have time.
what i saw in the video i r-type, the ship is flashing when crane lift it up, it does not flash on a 4MHz Ep, left 1-2 column is not visible of the demo end screen, as i remember it has 46 char width.
-
SidBasic plays digi from Dave interrupt, and interrupt frequency is set by frequency of tone channel 1 or 2, and this frequency is calculated by CPU speed, which is get by number of 1KHz Dave interrupts within a 50Hz video interrupt. Probably there is small problem in Dave emulation.
Other thing, Let's go driver, and speccy emulated beeps are played by cpu (no interrupt is used for playback) as i remember, so it is very strange one is fast, the other is slow.
-
Cool :-)
I will try to test it next week if i have time.
what i saw in the video i r-type, the ship is flashing when crane lift it up, it does not flash on a 4MHz Ep, left 1-2 column is not visible of the demo end screen, as i remember it has 46 char width.
I guess I need to take another swing at video access timing; probably I have some sort of error in the way that fractional offsets between the two clocks pan out.
Otherwise: for now I'm still taking the official documentation as the best reference on column visibility; it has the colour burst active until the beginning of column 10 so in composite mode my emulator is producing a colour burst until column 10. R-Type tries to display pixels prior to column 10, so those pixels are usurped.
SidBasic plays digi from Dave interrupt, and interrupt frequency is set by frequency of tone channel 1 or 2, and this frequency is calculated by CPU speed, which is get by number of 1KHz Dave interrupts within a 50Hz video interrupt. Probably there is small problem in Dave emulation.
I spoke too soon; SIDBasic is indeed receiving those interrupts and responding to them by adjusting the channel 0 volume, but since the last thing it wrote to port A7 was $65, it has channel 0 in sync mode, i.e. held at level 0, and hasn't activated direct-output mode. Therefore its adjustments of the channel 0 volume have no effect per my current implementation.
So I guess my next task is to figure out why $65 doesn't mean what I think it means, or else figure out what my emulator is doing incorrectly such that SIDBasic ends up writing $65.
It's a shame that the SIDBasic repository (https://github.com/istvan-v/sidbasic) appears to contain the Spectrum player only.
Other thing, Let's go driver, and speccy emulated beeps are played by cpu (no interrupt is used for playback) as i remember, so it is very strange one is fast, the other is slow.
Yeah, that one remains a mystery to me too. I'm going to focus on SIDBasic first, I think, and maybe I'll get lucky and the same fix will fix both. If not, more work to do.
-
SIDBasic can be downloaded from the forum from downloads.
I hope it contains the sources also (https://enterpriseforever.com/letoltesek-downloads/enterprise-software/?action=dlattach;attach=17876)
Latest release (https://enterpriseforever.com/letoltesek-downloads/enterprise-software/?action=dlattach;attach=17876)
-
SIDBasic can be downloaded from the forum from downloads.
I hope it contains the sources also (https://enterpriseforever.com/letoltesek-downloads/enterprise-software/?action=dlattach;attach=17876)
Latest release (https://enterpriseforever.com/letoltesek-downloads/enterprise-software/?action=dlattach;attach=17876)
No, no sources included. A .com and a .rom and nothing more. And since it's described as working on an unmodified Enterprise, I've not even been using the .rom.
-
This post contains the main source file, if you need more, i can send you.
https://enterpriseforever.com/sound/sid-lejatszo/msg63231/#msg63231
-
This post contains the main source file, if you need more, i can send you.
https://enterpriseforever.com/sound/sid-lejatszo/msg63231/#msg63231
Oh, fantastic! You're a hero!
I hope to be suitably ashamed about whatever my dumb error was, soon.
EDIT: after reading that, especially the speedts routine, and taking another look at the Dave documentation I can already see a flaw; my B4 b0 is toggling at the rate of the attached tone generator, or correspondingly at 2KHz or 100Hz for 1KHz and 50Hz interrupts, with the interrupt occurring on the downward toggle. So it's the exact same logic as for the external inputs. And ditto the 1Hz bit toggles at 2Hz.
But clearly the relevant bit is supposed to toggle at 1KHz or 50Hz or only upon the tone generator's downward stroke — the documentation is completely straightforward now that I review: "two flip-flops toggling off the timer interrupts". I dare imagine SIDBasic's false clock-speed conclusion is a direct result of that.
It also strikes me as I'm writing this that my implementation of the 1Hz input as completely disjoint from the 1KHz/50Hz, and the latter two as another programmable counter with limited reload options, is probably wrong. There's probably just some sort of internal cascading clock division going on, such that all three remain exactly in-phase for as long as the machine runs?
Anyway, thanks again! That's already really helped.
-
This post contains the main source file, if you need more, i can send you.
https://enterpriseforever.com/sound/sid-lejatszo/msg63231/#msg63231
Thanks again for this! The main emulation bugs affecting SIDBasic were:
- a very faulty conditional meant that for M1 cycles 'not video' + 'no wait states' => wait for a video slot. Hence the low CPU speed detection (and, it seems, the flickering ship in R-Type); and
- I wasn't applying ring modulation to channels in sync mode, hence the lack of audio production subsequently.
So: fixed, and here's the YouTube proof (https://youtu.be/Ebt8ubYsPFA?t=11).
Time to start worrying about Chase HQ, I guess. I'll aim for a new binary release this weekend, most likely, as I'm sure more corrections will be identified before then.
-
cool :-) I do not know this Axel Foley sid tune, it sounds a littlebit strange to me, but it can happen the original sounds the same, or use filters which are not implemented in Sidbasic.
I will check if there is any trick in digi playback in Chase HQ, but as i remember there is nothing.
-
I checked Chase HQ:
I think you solved also problem of Chase HQ with your fix, because as i remember you mentioned that the digi played well, and the effects were slow, from codes below i see delay is a self jumping DJNZ in digi routine, but in effect routines 0A51 called always which contains extra instruction.
The following is the digi playback code:
0B85 21 5D 0B LD HL, 0B5D
0B88 4F LD C, A
0B89 06 00 LD B, 00
0B8B 09 ADD HL, BC
0B8C 5E LD E, (HL)
0B8D 23 INC HL
0B8E 56 LD D, (HL)
0B8F 23 INC HL
0B90 7E LD A, (HL)
0B91 23 INC HL
0B92 66 LD H, (HL)
0B93 6F LD L, A
0B94 0E 02 LD C, 02
0B96 7E LD A, (HL)
0B97 1F RRA
0B98 1F RRA
0B99 E6 3C AND 3C
0B9B D3 A8 OUT (A8), A
0B9D D3 AC OUT (AC), A
0B9F 06 1F LD B, 1F
0BA1 10 FE DJNZ 0BA1
0BA3 7E LD A, (HL)
0BA4 17 RLA
0BA5 17 RLA
0BA6 0D DEC C
0BA7 20 F0 JR NZ, 0B99
0BA9 23 INC HL
0BAA 1B DEC DE
0BAB 7A LD A, D
0BAC B3 OR E
0BAD 20 E5 JR NZ, 0B94
These are some effect play code:
09AF AF XOR A
09B0 CD 51 0A CALL 0A51
*09B3 CB 06 RLC (HL)
09B5 10 F2 DJNZ 09A9
09B7 23 INC HL
09B8 0D DEC C
09B9 C2 A8 09 JP NZ, 09A8
0A51 D3 A8 OUT (A8), A
0A53 D3 AC OUT (AC), A
0A55 C5 PUSH BC
0A56 06 09 LD B, 09
0A58 FE 00 CP 00
0A5A 10 FC DJNZ 0A58
0A5C C1 POP BC
0A5D C9 RET
0A7A 4B LD C, E
0A7B CD AA 37 CALL 37AA
0A7E E6 10 AND 10
0A80 28 12 JR Z, 0A94
0A82 3E 18 LD A, 18
0A84 92 SUB D
0A85 47 LD B, A
0A86 10 FE DJNZ 0A86
0A88 3E 3F LD A, 3F
0A8A CD 51 0A CALL 0A51
0A8D 42 LD B, D
0A8E 10 FE DJNZ 0A8E
0A90 AF XOR A
0A91 CD 51 0A CALL 0A51
0A94 0D DEC C
0A95 20 E4 JR NZ, 0A7B
0A97 15 DEC D
0A98 20 E0 JR NZ, 0A7A
0A9A C9 RET
0A9B 0E 0A LD C, 0A
0A9D 21 05 05 LD HL, 0505
0AA0 15 DEC D
0AA1 20 FD JR NZ, 0AA0
0AA3 53 LD D, E
0AA4 3E 18 LD A, 18
0AA6 91 SUB C
0AA7 47 LD B, A
0AA8 10 FE DJNZ 0AA8
0AAA 3E 3F LD A, 3F
0AAC CD 51 0A CALL 0A51
0AAF 41 LD B, C
0AB0 10 FE DJNZ 0AB0
0AB2 AF XOR A
0AB3 CD 51 0A CALL 0A51
0AB6 25 DEC H
0AB7 20 E7 JR NZ, 0AA0
0AB9 65 LD H, L
0ABA 0D DEC C
0ABB 20 E3 JR NZ, 0AA0
0ABD C9 RET
-
Alas, no, things have actually gone the other way; since eliminating the '[not video] + [no wait states] + [M1 cycle] = [wait for video]' bug, Chase HQ now exhibits two faults:
- the added introductary music plays way too fast, as do and did the sampled sound effects; and
- the game occasionally pauses for several frames, which I think correlate to where the Spectrum and MSX would play speaker sound effects (and, honestly, I'm not sure what the CPC does).
I added a 6MHz CPU option in the hope of getting more input data, but it didn't reveal much. Though SIDBasic does correctly detect a 6MHz CPU and then output at a higher rate, so that's nice and reassuring.
So I'm extremely grateful for your having dug out the relevant routines. I note that, luckily for me, they're running from no-wait-state memory, and interacting only with Dave ports, so I think the smart thing to do next is to get pen and paper, figure out how many cycles I think the full loop should take, then see how many the emulator seems to think it should take.
The exact same Z80 has passed relevant timing tests on the ZX80/81, CPC and ZX Spectrum with the relevant WAIT and clock-stretching schemes in place, so I'm at least mildly optimistic that the problem is small and local. But we'll see. Almost a 100% chance it's a dumb coding error very specific to me rather than an Enteprise comprehension error that I could reasonably expect somebody else to know about.
-
Quick summary: new release available, in the same locations as before: macOS (https://github.com/TomHarte/CLK/releases), Snapcraft (https://snapcraft.io/clock-signal), repository (https://github.com/tomharte/CLK).
---
The issue with Chase HQ is that there's a timing calibration routine around $680 which compares Dave's 50Hz counter and the rate at which the INT1 input changes. It dynamically reprograms the values loaded to B prior to the DJNZ busy loops in the assembly above, e.g. it'd write a suitable constant to $0BA0 in the first case.
I had bit 4 of $B4 reflecting the state of the input as active low. It appears that active high is correct. From this flowed all timing issues.
There is now only one weirdness that I know of in Enterprise emulation: outputting an entire frame of sync doesn't cause any visible output — my GPU handler, I think both the Metal and OpenGL versions, thinks that frame skipping must be afoot and leaves up what is currently on screen rather than blanking it out. This has probably been a bug in my display simulation for this emulator's entire lifespan, it just so happens that I've never realised.
I'll fix it in the near future.
-
Cool :-)
That routine is used to check the CPU speed and based on that sets delay values in digi playback to keep digi at nearly the same speed.
-
Hi Tom,
not sure if you're still active here, anyway someone else may also have experience with this :)
I compiled and tried Clock Signal on Linux, but could not get Enterprise to start. If I supply a disk image, some disk activity will be shown (I guess that is the green dot that appears), but no actual content is shown, screen remains blank. I supplied the ROMs that are used for ep128emu (changed the file names to match clock-signal expectations), but I am not sure if that's the right approach?
(I had even less success with the snap version, it just crashes complaining about "Could not link shader program: "" ".)