RAND USR that doesn't work in emulators and clones

edited January 2015 in Emulators
Eons ago, I "discovered" a strange RANDOMIZE USR. This is it:
RANDOMIZE USR 46578

Using it on a genuine ZX Spectrum rubber key or Plus model, just after a power cycle (not RESET) and without any interface attached, after a second, the following pattern shows up on screen:
rand_usr_46578_p1.jpg

The computer is operating just like if it were waiting for a cassette signal (border changing from cyan to red and viceversa). If I press SPACE, this happens:
rand_usr_46578_p2.jpg

If I do a CPU reset (on a Plus), or if I try to use this RAND USR in an emulator in 48K emulation mode, or if I try to use this on a Spectrum which is not a 48K/Plus model, the behaviour is completely different (normally, the computer just reboots).

I never managed to find out what's happening here. The RAND USR proposed just begins executing NOP's until the CPU meets the stack, and then it interprets the bytes there as instructions.
But AFAIK, the stack contains the same values after each reboot, no matter if it boots as a consequence of a power cycle, or because the RESET button has been pressed. The same goes for emulators in 48K emultion mode.

But there's more: if, in the genuine Spectrum, I use 46577 or 46579 as parameter for the RAND USR, the pattern doesn't show up. It only happens with 46578.

Does anyone knows what would be happening here?
Post edited by mcleod_ideafix on
«1

Comments

  • edited May 2011
    RANDOMIZE USR 46578

    The fact that it works on more than one machine is interesting. There shouldn't be anything at that address besides NOPs, eventually running into the machine stack. Would be helpful to know what was actually in RAM. PEEK might be enough. If you wait for a certain amount of time does the behaviour still occur?
  • edited May 2011
    aowen wrote: »
    RANDOMIZE USR 46578

    Would be helpful to know what was actually in RAM. PEEK might be enough. If you wait for a certain amount of time does the behaviour still occur?

    I've performed a power cycle to the machine (this time, a different one from the one showed in the pictures), waited for 15 minutes with the (C)1982... on screen, typed the RAND USR and the pattern did showed up!

    Did a RESET (it's a rubber key model with a reset button added), and inmediately after the copyright message I repeated the RAND USR, and nothing!
  • edited May 2011
    I've performed a power cycle to the machine (this time, a different one from the one showed in the pictures), waited for 15 minutes with the (C)1982... on screen, typed the RAND USR and the pattern did showed up!

    Did a RESET (it's a rubber key model with a reset button added), and inmediately after the copyright message I repeated the RAND USR, and nothing!

    If it was only on a single machine I'd say faulty RAM, but it seems unlikely you'd get the exact same behaviour on two different machines.
  • edited May 2011
    Up to now, the only way I knew of differetiating a genuine non-modded ZX Spectrum 48K from anything else was this little program:
    org 29952-15
    
    Main                    proc
                            di
                            ld hl,65536-256
                            ld de,65536-255
                            ld bc,255
                            ld (hl),0
                            ldir
                            xor a
                            ld b,16   ;A[7..0] = 00-01h   R=6
    BucExt                  ld hl,0   ;A[7..0] = 02-04h   R=7
    Sigue                   ld r,a    ;A[7..0] = 05-06h   R=0
                            ld r,a    ;A[7..0] = 07-08h   R=0
                            ld r,a    ;A[7..0] = 09-0Ah   R=0
                            ld r,a    ;A[7..0] = 0B-0Ch   R=0
                            dec hl    ;A[7..0] = 0D-0Eh   R=1
                            dec h     ;A[7..0] = 0F-10h   R=2
                            inc h     ;A[7..0] = 11-12h   R=3
                            jp nz,Sigue   ;A[7..0] = 13-15h   R=4
                            djnz BucExt   ;A[7..0] = 16-17h   R=5
    
                            ei
                            ld bc,1
                            ld d,0
                            ld hl,65536-256
    CheckPat                ld a,(hl)
                            or a
                            ret nz
                            inc hl
                            dec d
                            jp nz,CheckPat
    
                            ld bc,0
                            ret
                            endp
    
                            end Main
    

    If you run this (it takes about 1 minute), BC will return 1 if this is a genuine, non modded ZX Spectrum 48K, and 0 for any other case, including all the emulators and clones I'm aware of.

    It works by forcing A0-A7 on the CPU address bus not reaching certain values. To acomplish it, the R register is reseted periodically, so the refresh cycle is only performed on low value rows.

    Anyway, the Spectrum doesn't use only the refresh bus cycle to refresh non contended memory, but all and every memory access, so I wrote the program so that the main part (the double nested loop) begins at a memory address so that A[7..0] = 00000000 .

    Being the program short enough, A7-A0 won't never reach a value greater than 17h during the execution of the loop, hence, DRAM rows greater than 17h won't be refreshed. A group of 256 consecutive memory positions (the last 256 bytes of RAM) are filled with 0 just before the loop, and checked after it has ended.

    It seems that a DRAM cell fades its value to "1" when refresh ceases to occur, so any non-zero value is an indication of a refresh failure, and hence, the presence of a true DRAM memory, and hence, a true ZX Spectrum 48K.

    The greater the value in B (after the XOR A instruction), the greater the "effect" acomplished. That is, more memory cells will become "damaged" by the lack of refresh.

    Of course, the damage is not by any means permanent :) Once "normal execution" is restored, the refresh operation behaves normally again.
  • edited May 2011
    Up to now, the only way I knew of differetiating a genuine non-modded ZX Spectrum 48K from anything else was this little program

    Testing for real DRAM. Neat trick. I'd expect clones that used DRAM to pass it as well though, so probably anything made before about 1990 at least.
  • edited May 2011
    aowen wrote: »
    Would be helpful to know what was actually in RAM. PEEK might be enough.

    PEEK returns the same values no matter if I reboot the computer with a power cycle or reset. Besides, if I run a little program (inmediate mode) to show some values from RAM, and inmediately after I do the RAND USR, it doesn't work.

    I'm afraid the only way to see what's really happening here is to plug some kind of bus sniffer to see the very same values the CPU sees, but my concern is about WHY is this happening. The fact that this happens means that, against all proofs, the complete state of the machine is not the same after it is rebooted by a reset switch than by a power cycle. And... it should be the same, shouldn't it?
  • edited May 2011
    The fact that it happens at that specific address but not one above/below suggests that this is extremely time-sensitive. (Or, possibly, the effect relies on the USR call itself putting the machine into a certain state - putting the call address in BC, for example - but the fact that it fails on emulators is a strike against that theory.) Perhaps it relies on an interrupt being triggered at a very specific moment and modifying the stack just as it's approaching SP, so the memory state as 'seen' by PC is one that doesn't occur at any other time. I guess you could test this theory by poking the free space above 46578 with do-nothing instructions that have slightly different timings per byte (like INC HL/DEC HL pairs).

    Actually, come to think of it... perhaps the instructions it eventually hits are doing something with the R register, which would introduce an element of timing-sensitivity without the need for a well-timed interrupt? Either way... for this theory to hold up, the ROM would have to be written in such a way that the variable (R register or tstates-since-interrupt) is in a predictable state at the point where it receives your ENTER keypress... I don't know whether this is true.

    I don't have any good explanations for why it fails on emulators, though... my best ideas are that it's dependent on 'early' versus 'late' Z80 timings (and your Spectrums both happen to have whichever one it is that emulators don't use), or that it's something to do with emulators handling the keypress differently - although then I'd expect the emulator to be the one with the reproducible time-sensitive effect (because they typically only scan the keyboard every frame, rather than continuously).
  • edited May 2011
    Woody figured it out. Your Z80s are setting the registers to #FF by default. Most Z80s, emulators included, set the registers to 0. This can be reproduced in an emulator by setting a breakpoint of zero and manually adjusting all the registers to #FF and then continuing execution. And the reset switch uses the reset pin of the Z80 which sets the registers to 0.
  • edited May 2011
    aowen wrote: »
    Woody figured it out. Your Z80s are setting the registers to #FF by default... This can be reproduced in an emulator by setting a breakpoint of zero and manually adjusting all the registers to #FF...

    True! I've just did and it works! Thanks!! :)
  • edited May 2011
    But... wait a minute! Ok, my Z80's put all registers to $FF at power on. What happens when I do a reset using the button? You say that the CPU reset puts all registers to 0, but this also happens when I power on the machine: an RC circuit pulls down the reset line for a brief moment. There's more: I've tried pressing the reset button while I power on the machine, hold the reset button for a few seconds, release it, try the RAND USR and works.

    Could it be that the reset condition affects only to a subset of the registers and doesn't touch others?
  • edited May 2011
    But... wait a minute! Ok, my Z80's put all registers to $FF at power on. What happens when I do a reset using the button?

    The reset button is hooked up to the RESET line of the chip which puts all the registers to 0. But the RESET line is *not* invoked on power-up.
    There's more: I've tried pressing the reset button while I power on the machine, hold the reset button for a few seconds, release it, try the RAND USR and works.

    I can only assume the Z80 must already be running for the RESET line to have any effect.
    Could it be that the reset condition affects only to a subset of the registers and doesn't touch others?

    No. If that were the case then you ought to be able to do a reset immediately after the cold start and the RANDOMIZE USR should still work.
  • edited May 2011
    aowen wrote: »
    The reset button is hooked up to the RESET line of the chip which puts all the registers to 0. But the RESET line is *not* invoked on power-up.

    Are you sure of that? Then, what is the purpose of this circuit?

    reset_circuit.png

    AFAIK, C27 and R31 form an RC cell. The voltage at C27 begins at 0V at power up, so it's the voltage at the RESET pin. As C27 is being charged through R31, its voltage increases until a point in which the CPU interprets it as a logic "1", so finishing the reset condition.

    The test I did (maybe I didn't explain myself well) is as follows: with the computer off, I press and hold the reset button, power on the machine, and the computer shows a random pattern on screen and stays freezed. Release the reset button and the CPU starts booting. After the booting is complete, I type the RAND USR command and it works.

    This is why I think that not all registers inside the CPU are modified. The only difference I can think about a power-cycle startup (the machine is off, then on) and a reset startup (the machine is on, reset is pressed, the machine stays on) is to assume that at power on, all registers contain $FF (or whatever value is the default for the flipflops that forms the internal registers), then the RC circuit pulls down RESET causing some (but not all) registers to go to $0000, the PC among them, causing the computer to reboot.

    Using the emulator, I've seen that after a complete reboot, when the machine has just showed the copyright message, the IX register keeps the value I manually entered to it while inside the breakpoint at $0000, and the value of BC' at startup is now in BC register.

    Even more: I've found that if I manually initialize the HL' register with $FFFF at reset, the RAND USR works. Strage, because HL' is initialized by the ROM to hold some calculator-related value. My assumption is that before that initialization is performed, the original value ($FFFF) is stored somehow, somewhere in memory.
  • edited May 2011
    My assumption is that before that initialization is performed, the original value ($FFFF) is stored somehow, somewhere in memory.

    Where? At $FF4A and $FF4B. If you poke these two addresses with $FF and do the RAND USR, it works (but it doesn't if you use the POKE command to perform that, you have to use the memory editor utility from your emulator)
    How? Surely by PRINT-A-2, which has a EXX instruction followed by PUSH HL. There's more places in the ROM with similar instructions, including a calculator routine that performs EXX followed by EX (SP),HL
  • edited May 2011
    aowen wrote: »
    The reset button is hooked up to the RESET line of the chip which puts all the registers to 0...

    Well, I've just find out that, after all, not all registers are set to 0 upon a reset. At least, not on the CPU I've tested.

    I've written a little program to be used as a ROM. For this to work I've got a home-made ROM cartridge with a 128K Flash-EPROM that can hold eight 16K images, which I can select using three jumpers. Position 000 belongs to this new ROM.

    The program retrieves the values of all registers, including I and R, and store them into memory. Later, a print routine builds a nice report on screen, as you can see.

    z80_startup_setup.jpg

    At the end, all registers are loaded with predefined values, and the CPU is locked using DI / HALT. If I press the reset button, the program starts again. The values I load into the registers just before locking the CPU are these:
    At this moment, after the program have finished and just before the CPU is locked, the registers are set with the following values (hex):
    AF  = 1111
    AF' = 2222
    BC  = 3333
    DE  = 4444
    HL  = 5555
    BC' = 6666
    DE' = 7777
    HL' = 8888
    IX  = 9999
    IY  = AAAA
    SP  = BBBB
    IR  = CCCC
    

    FIXED!!!! Thanks to all your warnings and advices, I've written a (hopefully) fixed version of the "Register retriever ROM" (to give it some name). I've also tested it with different Z80 versions: these are my guests :smile:

    pcb_collection.jpg

    In the following pictures, "cold start" refers to a power cycle (Spectrum OFF, then ON). Whenever possible, the cold start has been performed with the computer OFF for a long time previous to the power up.

    Zilog Z8400APS. Z80A CPU.

    Cold start:
    z8400aps_cold_start.jpg

    Warm start:
    z8400aps_warm_start.jpg

    About the cold start values: all registers set to $FFFF. SP set to $6003, sometimes $6004. IR set to $0000.

    For the warm start values, it's worth noting that these values are not always like this, but the fact that sometimes they are like this means that with a proper (maybe short enough) reset pulse, registers values are preserved. Nevertheless, both the RC reset circuit and the reset user button doesn't allow for a clean reset signal, so expect only IX and IY to be preserved.

    NEC D780C-1. This is the most common CPU I have installed in my ZX Spectrum 16K/48K PCB's. Zilog being the most common on +2 / +3.

    Cold start:
    nec_d780_cold_start.jpg

    Warm start:
    nec_d780_warm_start.jpg

    The cold start values seem to obey (not always) the values from this table:
    AF  = xx40 (being xx=00 or 07 most of the times)
    AF' = xx40 (being xx=00 or 07 most of the times)
    BC  = 17xx
    DE  = 40xx
    HL  = 40xx
    BC' = 17xx (sometimes FFFF)
    DE' = 40xx (sometimes FFFF)
    HL' = 40xx (sometimes FFFF)
    IX  = FFFF
    IY  = FFBF
    SP  = sometimes 6003, sometimes 6004, sometimes preserve its previous value)
    IR  = 0000
    
    And of course, not included, but assumed that:
    PC = 0000
    

    A curious thing: the SP is set to 7FFFh during the program execution. At the end, and as the last instruction before the HALT, SP is set to BBBBh. However, when a warm reset has been performed, the 7FFFh value is still there! The cold start picture were not the first one to be shooted, and you can see how the 7FFFh in SP is there even after a couple of minutes without power.

    Zilog Z0840004PSC. Z80A CPU. This the most common CPU installed in +2A/+3 computers.

    Cold start:
    z0840004psc_cold_start.jpg

    Warm start:
    z0840004psc_warm_start.jpg

    This CPU behaves roughly the same as NEC does. IX and IY are commonly preserved through a reset operation. Note that sometimes, R is not set to 00 during cold start.

    SGS Z8400AB1. Z80A CPU. Not as common as the NEC version, but still frequently seen on 16K/48K PCB's.

    Cold start:
    sgs_z8400ab1_cold_start.jpg

    Warm start:
    sgs_z8400ab1_warm_start.jpg

    The last two are CPU's not or rarely found in original Spectrums, but spares I have at home that work nicely with any of them. The first one is a 8MHz version (NMOS I pressume), and the last one is a 20MHz CMOS version. Both from Zilog.

    Zilog Z0840008PSC. Z80 CPU, 8MHz

    Cold start:
    z0840008psc_cold_start.jpg

    Warm start:
    z0840008psc_warm_start.jpg

    The cold start values differ from the one seen on NEC and SGS CPU's. Nevertheless, these values also differ every power cycle applied to the machine, so I think it's safe to say that this CPU behaves the same as its 4MHz version.

    Zilog Z0840020PEC. CMOS Z80 CPU, 20MHz

    Cold start:
    z0840020pec_cold_start.jpg

    Warm start:
    z0840020pec_warm_start.jpg

    It's easier to get the register values preserved during a reset operation in this CPU. I mean, the preservation happens more frequently, but not always. The "7FFF issue" for SP register is present here as well.

    So, it seems that:
    - The values of the Z80 registers upon power up are not 00, nor FF, but a mixture of values.
    - The RESET line does not set all registers to a predefined value, only a few of them. Commonly set registers are: IR to 0000 and PC (obviously) to 0000.
    - Some internal flipflops, like the one that controls which bank is the main one and which is the alternative, are not set to a predefined value. It doesn't hold their last value. The same goes for the flipflop that controls which AF pair is active, as you can see here (SGS)
    sgs_z8400ab1_warm_start_banks_changed.jpg
    - Registers IX and IY commonly hold their last value after a warm reset (using the reset button with the computer powered all the time). I think that a proper reset pulse (short enough, or syncronized somehow to the clock) would preserve all register values except IR and PC.

    In the "The undocumented Z80 documented" this can be read:
    Matt has done some excellent research on this. He found that AF and SP are always set to
    FFFFh after a reset, and all other registers are undefined (different depending on how long the
    CPU has been powered off, different for different Z80 chips). Of course the PC should be set to
    0 after a reset, and so should the IFF1 and IFF2 flags (otherwise strange things could happen).
    Also since the Z80 is 8080 compatible, interrupt mode is probably 0.

    This is the program (hopefully fixed) I've used (source code + ROM file)

    As a final thought... I'm considering repeating the tests but this time with a clean as possible reset pulse. The fact that I'm seeing 7FFFh as SP value after a warm start, plus values such as 40xx for the main registers (values which has to do with screen addressing) lead me to consider that the warm reset I'm using has too much noise, and the computer is actually resetted many times in which it could have enough time to execute so many instructions that confuse the results obtained (registers with different values as expected). It could be happening with the cold start as well (noise in the RC circuit that produces multiple reset pulses) and that would explain why I see 7FFFh in SP even after having the computer disconnected for several minutes.
  • edited May 2011
    Well, I've just find out that, after all, not all registers are set to 0 upon a reset. At least, not on the CPU I've tested.

    Fascintating research there. Well done. One thing to note is that apparently esxDOS assumes registers default to 0. It's going to need a rewrite if that's the case.
  • jpjp
    edited May 2011
    ...I've written a little program to be used as a ROM. For this to work I've got a home-made ROM cartridge with a 128K Flash-EPROM that can hold eight 16K images, which I can select using three jumpers....

    Without checking, I wonder if your test code would work ported to a ZXC3 cartridge?
    Perhaps there's scope for a test suite? Who knows who's CPU will do what?
    Brilliant find and well documented!
  • edited May 2011
    Main proc
    di
    ld (RegSP),sp
    ld sp,RegAF
    pop af


    Don't you mean push? It looks like the first thing the code does with AF is copy from memory to registers....not the other way around.
  • edited May 2011
    Gedlion wrote: »
    Main proc
    di
    ld (RegSP),sp
    ld sp,RegAF
    pop af


    Don't you mean push? It looks like the first thing the code does with AF is copy from memory to registers....not the other way around.

    OMG! You're right!!!!!! I knew 4:30 AM was not a good time to code (at least this time).
    Forget all I've said. I have to check things again :(

    Well... atworst, only AF and AF' values have been compromised. The rest of registers have been retrieved correctly. I will edit my original post with the fixed code.
  • edited May 2011
    OMG! You're right!!!!!! I knew 4:30 AM was not a good time to code (at least this time).
    Forget all I've said. I have to check things again :(

    Well... atworst, only AF and AF' values have been compromised. The rest of registers have been retrieved correctly. I will edit my original post with the fixed code.

    You should change the two pop af (for af and af') but also the location where
    you're putting them must 2 bytes after, because push writes at SP-2,SP-1

    lines 6,7 become:

    ld sp,RegAFa (or RegAF+2)
    push af

    and lines 18,19 become:

    ld sp,RegBC (or RegAFa+2)
    push af

    Or, for readability sake, instead of using this new label for the ld,sp instructions above, modify lines 263,264,265 to
    RegAF equ Attr+3
    RegAFa equ RegAF+2
    RegBC equ RegAFa
    and keep the original instructions before the push af.

    Also, you're storing IR in the wrong order to be printed using the common
    routine (you're printing IR, so you should store lower first, R), lines 275,276 should read:

    RegR equ RegIR
    RegI equ RegR+1

    Anyway, this is a very impressive tool to find out this remaining Z80 mystery! Congrats!
  • edited May 2011
    aowen wrote: »
    Woody figured it out.

    Only about initial register value(s) being involved. Gaming withdrawal kicked in then :p
  • edited May 2011
    As you see, this is not the same as you can read in the "The undocumented Z80 documented":

    This is the program I've used (source code + ROM file)

    TAP file for test on DIVIDE interface (connect this 16kB rom image instead zx rom):
    http://velesoft.speccy.cz/other/valor-reg-rom-for-divide.zip
  • edited May 2011
    Thanks, Velesoft! I've just repeated the tests with an updated code. Results in the original post.
  • edited June 2011
    As a final thought... I'm considering repeating the tests but this time with a clean as possible reset pulse. The fact that I'm seeing 7FFFh as SP value after a warm start, plus values such as 40xx for the main registers (values which has to do with screen addressing) lead me to consider that the warm reset I'm using has too much noise, and the computer is actually resetted many times in which it could have enough time to execute so many instructions that confuse the results obtained (registers with different values as expected). It could be happening with the cold start as well (noise in the RC circuit that produces multiple reset pulses) and that would explain why I see 7FFFh in SP even after having the computer disconnected for several minutes.

    As I expected...
    Today, I've tried two of the most usual CPU's: NEC and Zilog. For the warm reset, I've simply joined pins HALT and RESET. So, every time the HALT instruction is executed (at the very end of the program), the corresponding HALT line is asserted, causing a low level pulse at the RESET pin, rising HALT, and starting all over again. The effect is that the program executes in an endless loop, with the RESET pin triggering the beginning of each loop.

    About warm start, both behave the same: all registers, except IR, keep their previous values. IR are set to 0000.

    NEC WARM START (clean RESET pulse)

    nec_clean_warm_reset.jpg

    ZILOG WARM START (clean RESET pulse)

    zilog_clean_warm_reset.jpg

    Sometimes (Zilog) The I register keeps its value as well, but when this happens, SP is decremented by two and R gives a value between 13h and 17h. Could it be that after RESET is asserted and the HALT condition is exited, the CPU has time to fetch, decode and execute one more instruction before PC is set to 0000? The instruction inmediately following HALT is PUSH DE, so if this is executed, the value shown at SP may have sense. To find out if this is true, I have to be able to lock the CPU in a reset status, switch to a ROM that doesn't clear memory at the BBB9-BBBAh address positions, release the reset condition, and peek locations BBB9 and BBBA to see what value was kept there. If I'm true, that value will be the last value of DE register, that is, 4444h.

    So here we go. First, we get the condition in which "something" has been pushed onto the stack...

    zilog_clean_warm_reset2.jpg

    Then we lock the CPU to a permanent reset. Now I have to be very quickly because while the CPU is under a reset condition, memory is not being refreshed.

    locking_z80_reset.jpg

    Quickly I change the jumpers on my ROM cartridge to select a 16K BASIC ROM. This is a normal ZX Spectrum ROM but with the initial RAM value changed so this ROM never touches memory above 7FFFh.

    changing_rom.jpg

    Release the reset and let the computer boots.

    rom_16k_booted.jpg

    BBB9h is 48057, so BBBA is 48058. We peek at them...

    peeking_bbb9.jpg

    And the result is...

    peek_result_4444.jpg

    68d = 44h, so the value at the top of the stack was 4444h. The PUSH DE instruction was indeed executed... after a reset!!??!!

    The instruction following PUSH DE is LD A,B and as A has not changed, I can assume that this instruction fails to execute.

    I repeat that this doesn't always happens. The most of the times, SP keeps its value and IR is set to 0000h, so, could it be some kind of race condition in the logic that governs the reset behaviour?


    About cold start, I've tried only with the Zilog CPU, using a bounce-free pulse generator. All registers are set to FFFFh except IR which is set to 0000h

    ZILOG COLD START

    zilog_clean_cold_reset.jpg
  • edited June 2011
    Very nice work mcleod!

    I had a quick look at the ZiLOG Z8400/Z84C00 datasheet and read this:

    "/RESET initializes the CPU as follows: it resets the interrupt enable flip-flop, clears the PC and Registers I and R, and sets the interrupt status to Mode 0. During reset time, the address and data bus goto a high-impedance state, and all control output signals go to the inactive state."

    And it follows:

    "Once /RESET goes inactive, three internal T cycles are consumed before the CPU resumes normal processing operation. /RESET clears the PC register, so the first opcode fetch will be to location 0000."

    These 3 T cycles must belong to the HALT (looped) opcode fetch. In my opinion, the PUSH DE instruction could then be executed only if all conditions below are satisfied:

    1) the /HALT state is exited after the 1st or 2nd T cycle since /RESET gets activated: this could explain why a new fetch is started at the next PC address
    2) the fetch cycle cannot be interrupted and the CPU internal state is not changed by the RESET assertion: this could explain why even if I, R, PC and IFFs are reset the CPU completes the current fetch and executes the opcode.

    I know that all of this may look foolish, and extremely hard to demonstrate too. Anyway, in order to verify point 1) I'd start feeding the CPU with single- or double-T reset pulses; for point 2) it could be interesting to check if double-byte opcodes (such as PUSH IX) are executed as well.

    Just my 2 p.

    Stefano.
  • edited July 2011
    You know, I wouldn't tell many people this, but this is possibly one of the most interesting things I've ready anywhere for some time. Excellent work!

    Possibly related to your puzzle with PUSH DE, isn't the HALT instruction spread over two M cycles so that in reality /HALT is only asserted in T2 of PUSH DE's M1 cycle (instruction overlap)? Perhaps this might interact with jitter in the circuit to cause the unpredictable behaviour.

    Edit: Forget what I said there. I just checked it on real hardware and /HALT goes low just after the falling edge of the clock in T4 of HALT's M1 cycle.
  • edited December 2014
    Sometimes (Zilog) The I register keeps its value as well, but when this happens, SP is decremented by two and R gives a value between 13h and 17h. Could it be that after RESET is asserted and the HALT condition is exited, the CPU has time to fetch, decode and execute one more instruction before PC is set to 0000? The instruction inmediately following HALT is PUSH DE, so if this is executed, the value shown at SP may have sense. To find out if this is true, I have to be able to lock the CPU in a reset status, switch to a ROM that doesn't clear memory at the BBB9-BBBAh address positions, release the reset condition, and peek locations BBB9 and BBBA to see what value was kept there. If I'm true, that value will be the last value of DE register, that is, 4444h.
    <snip>
    68d = 44h, so the value at the top of the stack was 4444h. The PUSH DE instruction was indeed executed... after a reset!!??!!

    The instruction following PUSH DE is LD A,B and as A has not changed, I can assume that this instruction fails to execute.

    I repeat that this doesn't always happens. The most of the times, SP keeps its value and IR is set to 0000h, so, could it be some kind of race condition in the logic that governs the reset behaviour?

    In a quite remarkable piece of detective work you have discovered the Z80 Special Reset
    http://www.primrosebank.net/computers/z80/z80_special_reset.htm
  • edited December 2014
  • edited January 2015
    Eons ago, I "discovered" a strange RANDOMIZE USR. This is it:
    RANDOMIZE USR 46578

    If I do a CPU reset (on a Plus), or if I try to use this RAND USR in an emulator in 48K emulation mode, or if I try to use this on a Spectrum which is not a 48K/Plus model, the behaviour is completely different (normally, the computer just reboots).
    Indeed on FBZX Wii (also the windows version) this behaviour is correctly emulated except the border changing from cyan to red and viceversa
  • edited January 2015
    As the Z80 is specified to clear the I register on RESET, testing the I register is the only way to distinguish between a RESET and a RST &00 or JP &0000, as long as I is normally set to a non-zero value:
    LD A,I
    OR A
    JR NZ,NotAReset ; I<>0, not a RESET
    LD A,&3F
    LD I,A          ; Ensure I<>0
    

    Unfortunately, almost all emulators I have tested implement a user reset as a JP &0000.
  • edited January 2015
    jgharston wrote: »
    As the Z80 is specified to clear the I register on RESET

    This is true for a normal reset, but not a special one.
    http://www.worldofspectrum.org/forums/showpost.php?p=811612&postcount=1
    jgharston wrote: »
    Unfortunately, almost all emulators I have tested implement a user reset as a JP &0000.

    It's good to know there are emulators that support the special reset, albeit without realising I suspect!
Sign In or Register to comment.