Detecting Spectrum models

edited November 2009 in Development
Is there any sure-fire way a program can detect the model of machine it's running on (48K, +, 128, +2, +2A, +3, clones) even when running in the 48K mode of the various machines? I know there were changes to the 48K ROM that was put into the 128, as it caused some games to fail that depended on a table of 255s in the ROM to drive their interrupts. Was the same modified 48K ROM put into the +2 or was it changed again? And at some point the Speccy started coming up with an Amstrad copyright message, even in 48K mode.
Post edited by joefish on
Joefish
- IONIAN-GAMES.com -
«1

Comments

  • edited March 2009
    You can detect the original Sinclair/Amstrad ROMs like this:

    PEEK 2898 is 195 on 128k models, 214 on 48k models, else unknown.

    On 128k models, PEEK 2899 is 159 on a 128 or +2, 126 on a +3 or +2a.

    On a 128 or +2, check the copyright message. PEEK 5440 is 83 ('S') on a 128, 65 ('A') on a +2.
  • edited March 2009
    That was quick - thanks.

    I'm not sure whether to just stick to developing for the original 48K (emulated, at the moment) or whether to make allowances for the 128s running in 48K mode. I don't want to get into the extra features of 128K development just yet.
    Joefish
    - IONIAN-GAMES.com -
  • edited March 2009
    What fusetest does: read the frame length. That separates 48K from 128K/+3 from Pentagon from TS2068. To distinguish 128K/+3, check the decoding of "port 0x7ffd". This is probably overkill for what you're trying to do, though.
  • edited March 2009
    Perhaps the best method is just ask user :) That is what i recommend, check availability of extended memory (128 models), perhaps AY chip availability and if you need exact timing for some multicolor stuff just let user choose. It also gives explicit info what timings are supported.

    A bit of topic but still remember the hell with kempston joystick autodetection. Some czechoslovak clones passed the test without kempston attached (hw probably fills port with random values) and you find yourself unable to change controls because you were supposed use the joystick for navigation in menu.
  • edited March 2009
    joefish wrote: »
    That was quick - thanks.

    I'm not sure whether to just stick to developing for the original 48K (emulated, at the moment) or whether to make allowances for the 128s running in 48K mode. I don't want to get into the extra features of 128K development just yet.

    Actually until you want make some multicolor there is no significant difference between 48K and 128K in 48 mode. AFAIK.
  • edited March 2009
    Fikee wrote: »
    A bit of topic but still remember the hell with kempston joystick autodetection. Some czechoslovak clones passed the test without kempston attached (hw probably fills port with random values) and you find yourself unable to change controls because you were supposed use the joystick for navigation in menu.

    Sounds like sloppy programming to me - why disable keyboard input on the title screen just because you've detected the joystick? Auto-detecting it is fine, but then I'd wait for the user to press one of the possible fire buttons to start the game (like R-Type does). Then you can start just reading the one input device. Although it's rather a classic look for a Spectrum game to provide a control menu.
    Joefish
    - IONIAN-GAMES.com -
  • edited March 2009
    Fikee wrote: »
    Actually until you want make some multicolor there is no significant difference between 48K and 128K in 48 mode. AFAIK.

    Unless you're trying to use the table of 0xff in the ROM as has already been mentioned!
  • edited March 2009
    Notes played on the beeper will be out of tune too, with the increased clock speed. Although you'd have to have a very good ear to tell.

    By the way, on the subject of technical stuff, does anyone know how the dual-voice sound was achieved on the original Spectrum? I guess you can't simply superimpose two regular square waveforms when you only have a 0/1 output level. So do you shorten the high cycle of the waves (from e.g. 0000111100001111 to 0000001100000011) then OR them together, or would that sound too awful? Or how else can it be achieved?
    Joefish
    - IONIAN-GAMES.com -
  • edited March 2009
    joefish wrote: »
    Notes played on the beeper will be out of tune too, with the increased clock speed.

    Out of tune with what? The entire thing will be pitch-shifted a fraction of a semitone, but that doesn't affect the musicality of it one bit, unless you're playing it simultaneously with other Spectrums or instruments.

    The general point here is to test for the features you're using, not specific models of Spectrum. If you're doing something intensely timing-critical, test the timing. If you're doing something with 128K memory, try writing to an alternate memory page and reading back. If you're doing something ROM-specific, test the ROM. If you're doing something with the AY chip, just write to the AY chip regardless (Spectrums without one will just ignore it).

    In the specific case of the 0xff table in ROM - see Phil's post from 2 weeks ago. Having your own interrupt table in RAM is the most reliable solution, if you have a suitable 257 bytes to spare.
  • edited March 2009
    As I said, I'm programming for the 48K Spectrum. I'm assuming that if my program is loaded onto a 128K Spectrum it will be in its 48K mode. For safety's sake though, I will need to provide my own interrupt vector table because the 128s do have different ROMs. For the look of the rainbow effects I should also take account of the different timings, though I could have a 'dull mode' switch or even just disregard anything other than 48K users.

    The timing issue is more complicated than simply counting clock cycles between interrupts. The memory contention timings are also different between different 128K models, and it takes some very specific read/writes combined with the timing tests to get an accurate measure. It sounds far, far easier to tune two or three different effects handlers to the different machines, perform a simple test to determine the machine type, then install the relevant one onto the interrupt at startup.
    Joefish
    - IONIAN-GAMES.com -
  • edited March 2009
    joefish wrote: »
    The timing issue is more complicated than simply counting clock cycles between interrupts. The memory contention timings are also different between different 128K models, and it takes some very specific read/writes combined with the timing tests to get an accurate measure.

    Well of course. But if you assume that there are only 3 types of ULA (48K/128K/+3), frame length plus some way of splitting 128K/+3[1] lets you know your contention pattern[2].

    [1] In theory, reading port 0xbffd should split these very easily, but don't try that on emulators if you want the correct result.
    [2] Actually, it doesn't due to the early/late timing differences.
  • edited March 2009
    Unless you're trying to use the table of 0xff in the ROM as has already been mentioned!

    yep, true... just forgot about it as i never used this space saving trick. could be worth when 48K is full from bottom to top but personally i think there is not so many games that really ended with stack just few tens of bytes above screen.

    another fancy trick is making bold font (SHIFT and OR) from original sinclair font. but some clones (for example whole DIDAKTIK line) have font already bolded for some reason. the result is very ugly :P
    joefish wrote: »
    Sounds like sloppy programming to me - why disable keyboard input on the title screen just because you've detected the joystick? Auto-detecting it is fine, but then I'd wait for the user to press one of the possible fire buttons to start the game (like R-Type does). Then you can start just reading the one input device. Although it's rather a classic look for a Spectrum game to provide a control menu.

    i agree. the idea was probably to put player into game instantly. perhaps i did not explain it corectly: it is not true that keyboard was disabled, the menu routine was reading both of keyboard and joystick. as port $1F provide random values (on some not so exact copy of ZX) you as human hardly can be quicker than loop scanning input. and the PRESS FIRE thing was disaster. soon or later (speaking of milliseconds) 4th bit on $1F became set and you were kicked into game. so the real fault was that reading kempston was enabled without explicit confirmation by user.
  • edited March 2009
    joefish wrote: »
    By the way, on the subject of technical stuff, does anyone know how the dual-voice sound was achieved on the original Spectrum? [...] Or how else can it be achieved?

    The 48K Spectrum has a DAC (digital to analogue converter). Yes, really it does. The 48k DAC works exactly like the DAC in Super Audio CD (although perhaps not quite as refined :-)).

    The reactance of the beeper circuit means that the value that the speaker gets doesn't instantly change from 0 to 1 and vice versa; the speaker circuit includes a low pass filter. This allows you to use a digital-to-analog technique such as pulse density modulation (or pulse width modulation, which is just a special case of PDM). You can make a very convincing sine wave, for example, with the beeper circuit.

    Read this thread for more information. It includes screen shots from my oscilloscope, demonstrating what I'm writing about:

    http://www.worldofspectrum.org/forums/showthread.php?t=23456
  • edited March 2009
    Winston wrote: »
    The 48K Spectrum has a DAC (digital to analogue converter). Yes, really it does. The 48k DAC works exactly like the DAC in Super Audio CD (although perhaps not quite as refined :-)).
    http://www.worldofspectrum.org/forums/showthread.php?t=23456

    To quote, "Crikey!"
    That thread does explain a lot. Particularly how some of the really great sounding stuff was done. I think this is beyond what I can attempt at the moment though, so anything I do might just sound a bit crap.
    Joefish
    - IONIAN-GAMES.com -
  • edited March 2009
    aowen wrote: »
    Perfectly decent sound can be achieved in BASIC using the BEEP command. I wrote an editor which can output a data array which is available from WoS:

    http://www.worldofspectrum.org/infoseekid.cgi?id=0022506

    Yes, but the Spectrum can't do anything else at the same time. I'm trying to work out if I can adapt my main program to call out to a function at regular intervals, which I can then use to toggle the speaker in/out based on a pre-calculated crude sample buffer. I can get some squeaky and noisy sound effects out of it, but it's rough as hell so maybe getting it to play a tune is asking too much.
    Joefish
    - IONIAN-GAMES.com -
  • edited March 2009
    joefish wrote: »
    Yes, but the Spectrum can't do anything else at the same time. I'm trying to work out if I can adapt my main program to call out to a function at regular intervals, which I can then use to toggle the speaker in/out based on a pre-calculated crude sample buffer. I can get some squeaky and noisy sound effects out of it, but it's rough as hell so maybe getting it to play a tune is asking too much.

    Wow.. this thread seems to have strayed so far from the original topic that I'm not even sure what you are asking for any more :D

    So what are you trying to do - play an ingame tune from mc? As aowen says - that's completely possible
  • edited March 2009
    Some years ago i did a basic thing that still should turn out to be a SRP, a Screen Resident Program, just like the Utility3 disassembler :razz:

    http://www.worldofspectrum.org/forums/showthread.php?t=6405&highlight=system+checker

    very "experimental" Basic and basic in the sence off basic,
    http://home.hccnet.nl/C.born/S-CHK015E.TAP
    my old website http://home.hccnet.nl/c.born/ has changed to http://www.cborn.nl/zxfiles/ so just click it and select a file
  • edited March 2009
    I cant upload the last work version ,s-chk20.tzx , to my webpage, my password is not accepted but i didn't change it for years!
    strange.Maybe some Linux-code or HCCchips?
    It is not jet a program but more a collection off hardware info with EG the ROM messages which have specific places.
    Meanwhile i rebaptised it into:
    SpSy0.0.4 (Spectrum Sytem v004)
    It MUST be a Screen-Resisdent-Pogram because thats the only reliable place in ALL Speccie clones and variations the be the same.
    Adress 16384 is the primary Screen1 adres with at least 6912 byte to work with.
    If you keep control over the message printing area you have 2k+16 lines or 4k+8line.
    the prog Utility3 even has its own characterset on the screen area!!
    If George changes these to a 64c set he could save some 168 bytes because he uses a smart plotting routine and VERTICAL plotted characters which need only 5 bytes instead off 8!! And that could be a 3 or 4 byte character...

    If some one feels the need to take this up and Code it please go ahead and keep us informed!!
    my old website http://home.hccnet.nl/c.born/ has changed to http://www.cborn.nl/zxfiles/ so just click it and select a file
  • edited March 2009
    evilpaul wrote: »
    Wow.. this thread seems to have strayed so far from the original topic that I'm not even sure what you are asking for any more :D

    So what are you trying to do - play an ingame tune from mc? As aowen says - that's completely possible

    What I'm trying to do is see what version of the Spectrum my code is running on (even though it's supposed to be in 48K mode), so that I can adjust the timing of my time-critical stuff.

    Manic Miner actually puts the main program on hold whilst it plays a quick beep, then continues with the game. This isn't very efficient as it uses up a lot of processor time, and you end up with a farty sound to the music.

    I want to create a sound buffer, then intersperse OUT 254 commands at regular intervals amongst my main program to play it back, so that it doesn't have to keep stopping. However, the result may not be timed sufficiently well to play a tune, much less two channels. That's what I'm trying to fix.
    Joefish
    - IONIAN-GAMES.com -
  • edited March 2009
    No, that's simply not true.

    I'm doing exactly what I said already, and it works. I can get sounds out; now I'm trying to see if I can get a tune. You're trying to tell me what I already have working is impossible. Thanks, I should probably consider that a compliment.

    When playing a sound, you send a byte out on port 254, where one bit will set the speaker either in or out. You then wait a tiny delay, and move it back again. Do it fast, and the in/out pulses make a sound. Do it really fast, and on a real Spectrum apparently you can generate a smooth waveform - but that's going a little far for me.

    Now, the note middle C is only 262 Hz, and the processor is running at 3.5 MHz - a hell of a lot faster. It takes all of 5 µs (18 clock cycles) to write a value out to port 254, and you only have to do that every 1.9 ms. So that means the processor is doing nothing but counting time for 1895 µs for just 5 µs of activity. A usage value of 000.26% is not particularly efficient use of the processor as far as I'm concerned, and I'm trying to do something about it.
    Joefish
    - IONIAN-GAMES.com -
  • edited March 2009
    Well, yes, pretty much every line of assembly has a comment on it with the number of T-states it takes up. I've just written two versions of my sprite routine - one for drawing on interrupts, that uses the stack pointer as an extra fast address register, and a slightly slower but much safer version that uses IX and IY instead.

    But the problem with timing is when I'm using the delay loop to copy data to the screen memory - then you run into the memory contention issues, which means the code slips out of synch, depending on what machine it's running on.
    Joefish
    - IONIAN-GAMES.com -
  • edited March 2009
    joefish wrote: »
    Is there any sure-fire way a program can detect the model of machine it's running on (48K, +, 128, +2, +2A, +3, clones)

    Seems like the best program has been made by X-Agon/AY-RIDERS.
    I'll try to find it (if nobody sent it here before).
    ZX Spectrum 48K BEEPER Music:
    http://mister_beep.republika.pl/
  • edited March 2009
    joefish wrote: »
    Is there any sure-fire way a program can detect the model of machine it's running on (48K, +, 128, +2, +2A, +3, clones)

    To distinguish a +2A/+3 use
    PRINT PEEK 19 which will give 167 for +2A/+3 or 255 for the others.

    To distinguish between a +2A and +3 test bit 4 of FLAGS3 [23398] which is set if disk A is present. (PRINT PEEK 23398 will give 148 on a +3 or 132 on a +2A).

    If PEEK 19 gives 255 then PEEK 1540 will give 83 (S) if it's a
    Sinclair or 65 (A) if it's an Amstrad +2.

    If the result is "S" then it's a Sinclair machine and
    PRINT PEEK 75 will give 110 if it's a 128 machine or 191 if its the original machine.

    PRINT PEEK 23733 will give 127 if it's a 16K machine else 255.

    PRINT PEEK 23734 will give zero if Interface 1 has been paged in else 244.

    If PRINT PEEK (0) gives 47 it's a Commodore 64. Welcome to the World of Spectrum.
  • edited March 2009
    PRINT PEEK 14446 gives 255 on a 48K but 211 on a TC2048.

    You can check for a Pentagon by paging in ROM 0 and checking if the menu text reads TR-DOS (Pentagon) or Tape Tester (128 ).

    If the ROM check seems to be a 48K machine but IN 255 is something other than 255 then you're either on a

    TC2068 with Spectrum emulator cart (or a Spectrum SE but the timings are the same)
    TS2068 with Spectrum emulator cart

    At this point you're back to testing timings. The TC is a 50hz machine. The TS is a 60Hz machine.

    Of course you could choose not to support the Timex clones. Seems a little unfair if you're going to support the Pentagon though.
  • edited March 2009
    Look, is it OK if I have a say in what I'm doing? Who said I'm supporting the Pentagon but not the others? Why am I being accused of being unfair on anyone?

    I wasn't thinking about the clones, but I'm grateful for the tips on how to detect them as I can see the global clone scene is probably bigger than the domestic retro scene. But it's not my fault if they're imperfect copies of the original!

    There's no way I'll be able to support a 60Hz machine, unless the clock speed is scaled up proportionally as well, as it'll throw the graphics out of synch too. For all the time I'm saving on the sound, I'd have to cut back all the graphics routines just to fit in the frame rate of one clone.
    Joefish
    - IONIAN-GAMES.com -
  • edited March 2009
    I'd rather the clones just supported the original - the emulators manage it! But putting in a custom routine for each variant may cause problems with space. Though I may be able to load them up in the slow memory below 32768 and just copy the one I want to use into higher memory before I call it. Once I have the game running in 48K I'll have a look at what I can do for the other machines.

    Under emulation at least, I have the same code running on both 48K, and 128K / +2 in 48K mode. It crashes outright in 128K mode, but I'm not too worried. I may investigate more once it's finished.

    Interestingly, the way that the contention works actually serves to regulate the speed of writes to the lower 16K and knocks the functions into line. It's having less contention on the +2A that mucks me about, but two different hand-tuned versions of the main copying loop are feasible.
    aowen wrote: »
    The TS2068 has a 3.528Mhz CPU which, hopefully, should compensate for the 60hz clock. Not sure how solid the TS2068 emulation is, but there are at least a few enthuisiasts out there who would be willing to test on real hardware.

    Not enough I'm afraid. It would have to be going at 4.2 MHz (3.5*60/50) to be able to do the same amount of processing per display frame, but then of course everything would play faster.
    Joefish
    - IONIAN-GAMES.com -
  • edited March 2009
    aowen wrote: »
    Your program will fail with at least one ROM - the one I created that uses the other screen in the 128. It starts BASIC a bit lower which means you can have bigger basic programs.

    Well so it is not as must to start on screen1 but it needs to know were it is. At least to mention that on screen :roll: but it should not disturp the contence off your Speccy.
    You cant move the sysvars to much with own baked roms, to first check the screen bit, then you know if you are in screen1 or screen2. If the bit is found check for real 128k conditions becouse it might be a random bit in the printer buffer.
    my old website http://home.hccnet.nl/c.born/ has changed to http://www.cborn.nl/zxfiles/ so just click it and select a file
  • edited March 2009
    OK then, here is the tester.
    http://mister_beep.republika.pl/ZX_CHECK_test_detect.TAP
    Supposedly it's not perfect (doesn't detect TR-DOS every time somehow) but I noticed it can recognize both 48K modes in 128K Spectrum so maybe that's what you need.
    ZX Spectrum 48K BEEPER Music:
    http://mister_beep.republika.pl/
  • edited March 2009
    OK then, here is the tester.
    http://mister_beep.republika.pl/ZX_CHECK_test_detect.TAP
    Supposedly it's not perfect (doesn't detect TR-DOS every time somehow) but I noticed it can recognize both 48K modes in 128K Spectrum so maybe that's what you need.

    Thanks Mister Beep,
    But you saved a bunch off 14k with loads off zero's. I think it must be 1400 bytes?
    than it will fit a 16k model.
    do you see peek23388=0 as definitively a 48k?
    that only works if the printer buffer is cleared after use, or with a fresh started Spectrum(clone)
    And the buffer is usually only cleared, 0efd#-CLEAR-PRB, at start and after a COPY command.
    It did recognise +D on FUSE :smile:
    my old website http://home.hccnet.nl/c.born/ has changed to http://www.cborn.nl/zxfiles/ so just click it and select a file
  • edited April 2009
    OK, so now aowen has deleted a load of posts this thread looks a little crazy. I should quote more if this sort of thing is going to happen.

    Anyway, I'm sorry to say that my experiments have failed to get a decent tune out of this system. Unfortunately I can't be doing the synchronised routine for 100% of the time. I can control the speaker at regular intervals over about half of each 50Hz TV frame, but I have to break out to do some irregular stuff every frame and the end result is a very harsh-sounding note as it drops in and out every 10ms.

    With some more planning, I may be able to get the time spent playing the note up to 75% of the time, but I don't think anything less than 100% will be good enough. For that I'd have to have every single function in the code synchronised to the sound routine (and no interrupts), and I don't think I'm able to achieve that at this stage.

    So, for now, I'll still be using this system for sound effects but I won't be inflicting my attempt at a tune on anyone else's ears.
    Joefish
    - IONIAN-GAMES.com -
Sign In or Register to comment.