Tornado Low Level
=================

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

The .tzx files converted with fuse tapeconv all produce .tap files which can
be loaded by the Speculator loaders.
Just use any of the TornadoLowLevelTzx*.tap files.
They all seem similar when you play them.

The TornadoLowLevel.tap file is different though, and cannot be loaded.
It requires patching, to make TornadoLowLevelPatched.tap.
Also the Speculator loader requires patching too.
This can be done live using MEMUs -diag-ui-mem feature, or using BE+BEMEMU.
Presumably this was a different release of the software.
Details below...


$ ./showtap.sh TornadoLowLevel.tap
=== TornadoLowLevel.tap
[0x000] : {0x0013,TRUE ,TAPF_HEADER,{TAPD_PROGRAM       ,"TLL       ",0x04f0}}
[0x001] : {0x04f2,TRUE ,TAPF_BLOCK ,@000a2800e7310e00000100003ada310e00000100>}
[0x002] : {0xbf9f,TRUE ,TAPF_BLOCK ,@ffffffffffffffffffffffffffffffffffffffff>}
$ ./showtap.sh TornadoLowLevelPatched.tap
=== TornadoLowLevelPatched.tap
[0x000] : {0x0013,TRUE ,TAPF_HEADER,{TAPD_PROGRAM       ,"TLL       ",0x04f0}}
[0x001] : {0x04f2,TRUE ,TAPF_BLOCK ,@000a2800e7310e00000100003ada310e00000100>}
[0x002] : {0xbf9e,TRUE ,TAPF_BLOCK ,@ffffffffffffffffffffffffffffffffffffffff>}

Supplied file last block is 1 byte longer than the loaders expect.
The original .tap file loads in fuse, and so does the patched file.
The original .tap doesn't load with original Speculator loader.
The patched .tap doesn't load with original Speculator loader.
The patched .tap does load with patched Speculator loader.


The BASIC loader POKEs the following to 40000 and jumps there :-

=== code at 0x9c40 ===

@37	  scf
@3eff     ld	  a,0xff
@dd210040 ld	  ix,0x4000{_3741+0x08bf}
@119cbf   ld	  de,0xbf9c
@cd5605   call    v_load
@c9	  ret

Running in Z, we see that after loading, the ret has been overwritten :-

a=40 f=.ZH... bc=9c40 de=61c7 hl=2d2b ix=0096 iy=5c3a sp=df40 pc=9c40 i=e3 iff=45  37        scf
a=40 f=.Z...C bc=9c40 de=61c7 hl=2d2b ix=0096 iy=5c3a sp=df40 pc=9c41 i=e3 iff=45  3eff      ld      a,ff
a=ff f=.Z...C bc=9c40 de=61c7 hl=2d2b ix=0096 iy=5c3a sp=df40 pc=9c43 i=e3 iff=45  dd210040  ld      ix,4000
a=ff f=.Z...C bc=9c40 de=61c7 hl=2d2b ix=4000 iy=5c3a sp=df40 pc=9c47 i=e3 iff=45  119cbf    ld      de,bf9c
a=ff f=.Z...C bc=9c40 de=bf9c hl=2d2b ix=4000 iy=5c3a sp=df40 pc=9c4a i=e3 iff=45  cd5605    call    0556
a=ff f=.Z...C bc=9c40 de=bf9c hl=2d2b ix=4000 iy=5c3a sp=df3e pc=0556 i=e3 iff=45  c3efe7    jp      e7ef

The area loaded overwrites the stack so it won't return and jump to 0xe7ef.
There is junk there anyway.
Inspection of the code suggests execution starts at 0x66bc

Original Speculator loader looks like this

m$tllc              +0x0000 : @3e02     ld      a,0x02
m$tllc              +0x0002 : @323a37   ld      (keyboard_every),a
m$tllc              +0x0005 : @cd1306   call    c$lprg
m$tllc              +0x0008 : @01e03f   ld      bc,0x3fe0{_3741+0x089f}
m$tllc              +0x000b : @119cbf   ld      de,0xbf9c
m$tllc              +0x000e : @cd5906   call    c$lcoh+0x0003
m$tllc              +0x0011 : @010100   ld      bc,0x0001
m$tllc              +0x0014 : @cd881d   call    set_nmi_urgency
m$tllc              +0x0017 : @3e99     ld      a,0x99
m$tllc              +0x0019 : @329bff   ld      (0xff9b),a
m$tllc              +0x001c : @c3a28d   jp      0x8da2

Patched Speculator loader looks like this

m$tllc              +0x0000 : @3e02     ld      a,0x02
m$tllc              +0x0002 : @323a37   ld	(keyboard_every),a
m$tllc              +0x0005 : @cd1306   call    c$lprg
m$tllc              +0x0008 : @010040   ld	bc,0x4000{_3741+0x08bf}
m$tllc              +0x000b : @119cbf   ld	de,0xbf9c
m$tllc              +0x000e : @cd5906   call    c$lcoh+0x0003
m$tllc              +0x0011 : @010100   ld	bc,0x0001
m$tllc              +0x0014 : @cd881d   call    set_nmi_urgency
m$tllc              +0x0017 : @3e99     ld	a,0x99
m$tllc              +0x0019 : @329bff   ld	(0xff9b),a
m$tllc              +0x001c : @c3bc66   jp      _5c5a+0x0a62

Result! It then runs fine.

