Sunday, November 13, 2011

simplicity of emulation

If everything would be "black and white" , I'm pretty sure that this would help to some extend.
Emulation of retro computers (like ZX Spectrum) looks to be just straight forward if only to follow documentation and theoretical aspects, 
the other question: would be such emulation efficient and more importantly - practical to use?

Here is one description ( ULA stands for uncommitted logic array ):

If the processor reads from a non-existing IN port, for instance FF, the ULA won't stop, but nothing will put anything on the data bus. Therefore, you'll read a mixture of FFs (idle bus), and screen and ATTR data bytes (the latter being very scarce, by the way). This will only happen when the ULA is reading the screen memory, about 60% of the 1/50th second time slice in which a frame is generated. The other 40% the ULA is building the border or generating a vertical retrace. This behaviour is actually used in some programs, for instance, in Arkanoid.

Finally, there is an interesting bug in the ULA which also has to do with this split bus. After each instruction fetch cycle of the processor, the processor puts the I-R register "pair" (not the 8 bit internal Instruction Register, but the Interrupt and R registers) on the address bus. The lowest 7 bits, the R register, are used for memory refresh. However, the ULA gets confused if I is in the range 64-127, because it thinks the processor wants to read from lower 16K ram very, very often. The ULA can't cope with this read-frequency, and regularly misses a screen byte. Instead of the actual byte, the byte previously read is used to build up the video signal. The screen seems to be filled with 'snow'; however, the Spectrum won't crash, and program will continue to run normally. One program which uses this to generate a nice effect is Vectron (which has very nice music too, by the way).

The 50 Hz interrupt is synchronized with the video signal generation by the ULA; both the interrupt and the video signal are generated by it. Many programs use the interrupt to synchronize with the frame cycle. Some use it to generate fantastic effects, such as full-screen characters, full-screen horizon (Aquaplane) or pixel colour (Uridium for instance). Very many modern programs use the fact that the screen is "written" (or "fired") to the CRT in a finite time to do as much time-consuming screen calculations as possible without causing character flickering: although the ULA has started displaying the screen for this frame already, the electron beam will for a moment not "pass" this or that part of the screen so it's safe to change something there. So the exact time in the 1/50 second time-slice at which the screen is updated is very important. Each line takes exactly 224 T states.

As you can see all details - you can also notice that some of such bugs/features(?) been used within applications(bold text).
Which obviously means: would like to run all applications - think about ALL features, including undocumented (unplanned) features and its proper support...

Full reserving of such details just a matter of time: years, dozen of years, even more...
should I say - stay tune for full support across all applications?

PS: quite good book, came out at 2010:
and ZX spectrum came out 1982...

Saturday, November 5, 2011

an idea reconstruction

At some point, having already functional code is good and even perfect,
however try to understand precisely big idea implemented:
    synchronized void updateAudio(int tstates, int value) {
        tstates = tstates - audiotstates;
        audiotstates += tstates;
        float time = tstates;

        synchronized (beeper) {
            if (time + timeRem > spf) {
                level += ((spf - timeRem) / spf) * value;
                time -= spf - timeRem;
                lastLevel = (lastLevel + level) >>> 1;
                beeper[bufp++] = lastLevel;
            } else {
                timeRem += time;
                level += (time / spf) * value;

            while (time > spf) {
                lastLevel = (lastLevel + value) >>> 1;
                beeper[bufp++] = lastLevel;
                time -= spf;

        // calculamos el nivel de sonido de la parte residual de la muestra
        // para el prуximo cambio de estado
        level = (int) (value * (time / spf));
        timeRem = time;

 Now, can you write the own implementation?

time to start?

yet thinking...
concurrently starting ...

stay tune...