
**********************************************************************
files: DB1.TXT
**********************************************************************


** Kobrahsoft DB1 - getting it to work
   ===================================

It's initially running the chunk of code shown below, which is using some unconventional IX/IY index register commands and is doing stuff with the R register that I don't understand. The upshot is that it's copying a chunk of memory to alter the code which follows on from the bit shown here, while altering the two index registers. I presume that it's a decryption routine.

Having done that it drops down and after a short while calls BC_SPACES with zero in BC, attempting to make "no room", which causes an "Out of memory" error, but because the IY register has a vastly wrong value in it the system crashes.

[code]
        JR $8015                 ; 8000 18 13

        XOR H                    ; 8002 AC
        XOR L                    ; 8003 AD
        XOR E                    ; 8004 AB
        XOR D                    ; 8005 AA
        XOR C                    ; 8006 A9
        XOR B                    ; 8007 A8
        EX (SP), HL              ; 8008 E3
        XOR H                    ; 8009 AC
        XOR L                    ; 800A AD
        EX (SP), HL              ; 800B E3
        XOR IXH                  ; 800C DD AC
        XOR IXL                  ; 800E DD AD
        XOR IYH                  ; 8010 FD AC
        XOR IYL                  ; 8012 FD AD
        RET                      ; 8014 C9

        LD SP, $4002             ; 8015 31 02 40
        DI                       ; 8018 F3
        LD IX, $4000             ; 8019 DD 21 00 40
        EXX                      ; 801D D9
        LD DE, $1000             ; 801E 11 00 10
        LD BC, $0020             ; 8021 01 20 00
        EXX                      ; 8024 D9
        LD HL, L_804F            ; 8025 21 4F 80
        LD DE, $C000             ; 8028 11 00 C0
        LD BC, $1E3C             ; 802B 01 3C 1E
        LD A, I                  ; 802E ED 57
        LD R, A                  ; 8030 ED 4F
L_8032: XOR (HL)                 ; 8032 AE
        CALL $8002               ; 8033 CD 02 80
        EXX                      ; 8036 D9
        LD HL, $0000             ; 8037 21 00 00
        ADD HL, SP               ; 803A 39
        CALL $8002               ; 803B CD 02 80
        EX DE, HL                ; 803E EB
        CPI                      ; 803F ED A1
        EX DE, HL                ; 8041 EB
        INC IX                   ; 8042 DD 23
        INC IY                   ; 8044 FD 23
        EXX                      ; 8046 D9
        LD (HL), A               ; 8047 77
        LD A, R                  ; 8048 ED 5F
        LDI                      ; 804A ED A0
        JP PE, L_8032            ; 804C EA 32 80
[/code]

   ===================================

The decryption isn't producing valid code from the loaded data, which may be because the disk image is imperfect or the emulation is imperfect with regard to the particular technique used for decrypting the code - or that the copy protection is doing its job.

I read off the raw file as a data stream and it has a 128 byte header plus three BASIC lines: two REMs holding machine code and a PRINT USR 0 followed by what may be just garbage up to the end of the 66th disk block after which the read quit. The first m/c copies 8192 bytes from PROG+28 to 32768, which is the second m/c chunk. So there's definitely the correct quantity of data there, but I don't know about the quality. The problem could be GIGO or it could be related to the use of the R-register which I didn't know anything about until I read [url=http://www.worldofspectrum.org/faq/reference/z80reference.htm#RRegister]this article[/url] on WoS this morning, other than being vaguely aware of its existence.

Will the I-register always be set to $3F when that routine gets to $802E on a real +3? - because that's what the R-register is getting set to at the start of the decryption loop and it doesn't produce a happy outcome.

Given that it states in the DB1 docs that copies of the DB1 disk won't load and that a +3 DSK image is a copy then I suppose that it shouldn't be surprising that it won't load, as that was the publisher's original intent - but it would be nice to know exactly how it's been designed to fail.

   ===================================

I got that disk to run. Here's the start-up screen:

[center][img]http://www.users.globalnet.co.uk/~jg27paw4/pourri/db1.gif[/img][/center]

Firstly, the disk has to be set to auto-load. If the disk is loaded by pressing Enter for Load on the +3 start-up menu then it won't work, as the I-register will be set to $3F and the decryption routine will give the wrong result. With auto-load set the I-register will be set to $00 and the code will decrypt correctly.

Secondly, set a break at $8BE2: LD SP,$8000; step through that command then skip over the next two CALLs and jump straight to the $8BEB: DI command, then Run and the DB1 start-up screen will be ready to use. I presume that the first CALL is the copy protection, as if it returns NZ (which it does) it makes the second CALL which erases all the memory and does a reset.

I tried the G option to transfer tape-to-disk but I couldn't work out how to complete the procedure and the manual isn't very helpful. It reads the files off tape and updates the header display but I couldn't get it to show the files in the directory. More experimentation is needed. I still had the DB1 disk in the drive, so maybe it's write protected.

--

The tape transfer worked OK when I switched to a blank disk.

   ===================================

These patches to the disk image file will get it to load & run normally, using either the auto- or manual load options.

At $1ACA, change [b]ED 57[/b] to [b]3E 00[/b]
This changes LD A,I to LD A,$00 so that the subsequent LD R,A always starts off at zero.

At $2781, change [b]FC 36 B2 BF EF 84[/b] to [b]31 77 39 7B 41 0F[/b]
This changes the encrypted calls to the copy protection routine and error reset so that they decrypt to six NOPs.

   ===================================

It has "SamDisk090906" at the top of the image file.

That line in the top corner of the screen is because the decryption routine puts the stack at $4002 and is continually swapping stuff on & off the top with "EX (SP), HL".

The explanation for the failures would probably lie in the security routine at $8B41 and its subordinate routines, which access ports $1FFD / $2FFD / $3FFD, accessing the disk motor, disk status register and disk data register (according to page 181 in the +3 manual).

--

I checked those four emulators again; Fuse, RealSpectrum and EightyOne all complete the decryption OK as they start off with the I-register reset; Fuse and RealSpectrum then fail the disk security check and crash; whereas EightyOne gets stuck in a little loop at $8E33, accessing the disk registers. Spin is the only one which fails the decryption as it starts off with the wrong value ($3F) in the I-register, unless auto-load is enabled. If it is enabled it then fails the security check just like the others.

   ===================================

I expect those other programs don't like the DSK file because of the abnormal sectors used by the copy protection which obo mentioned earlier.

That patch is just for the DB1 loader program, not the DB1 program itself. It calls the security routine at $8B41 from within itself (at $838D) to check for an original disk, so without disabling the call at $838D it fails the security check if you try to copy it with the Clone option.

If you replace the CALL $8B41 at $838D with XOR A : NOP : NOP then the clone to tape (or disk, presumably) will work and then you can try out your original plan with the TAP file it produces.

--

Note that the code isn't at that location until the prompt:
"INSERT ORIGINAL KOBRAHSOFT DISC PRESS ANY KEY"
appears and a key has been pressed, so it's necessary to set a break in "empty space" at that address and then change the line when the break is triggered.

--

I've tried both the tape & disk clone options and although they appear to copy the disk they don't create anything useful. I expect that the clone routine recognises its own code file and won't copy it. Further patching would be needed. I'll check what it's doing later this evening.

   ===================================

I'm not having much luck so far with copying stuff reliably. I've been trying the "G Tape to Disk" option, but the results haven't been very promising.

* The free disk space figure at the top only shows half what CAT shows.

* It copies tape files regardless of their names, so if the name includes punctuation characters then it gets created on disk with the exact same name and, as punctuation characters are invalid in disk file names, nothing can be done with the file after that.

* It will also copy files from tape to disk which are already on the disk with the same name, but doesn't replace them. They show as duplicate files in DB1 but only show once with CAT.

* When pressing A to show the disk directory it only shows files copied by itself; other files I've put on with COPY from the BASIC command line don't show in DB1. They all show if I do a CAT from BASIC.

* The G option puts an extra 16k of garbage on the disk which CAT shows with the name " >bM"f?.>cM ", although the hex code on disk is actually:
" 3E 62 CD 22 66 01 08 00 3E 63 CD ".

The clone option to disk currently appears to copy a disk but the destination is always empty afterwards, even if the source was an ordinary unprotected disk. Clone to tape creates some files, but the header has an invalid file type of 8 so it can't be loaded from BASIC.

I'm not very impressed with it so far.

   ===================================

I finally got DB1 to copy itself (the patched version) and was able to run the program from the copy. I couldn't get the C-Clone option to work - at least, it wouldn't transfer the DB1 "DISK" program file - but the T-Transfer Disk to Disk did it. The key point was only to use 180k disks; most of the options seemed to work with that - except Format, which went through the prompts but didn't format the disk.

--

The P-Disk to Tape option worked as well, so I was able to transfer DB1 to a TAP file and run it from that. If there's no disk in the drive the program gives a "No Disk In Drive" error once the program has loaded from tape, but pressing A and then Y to the "Abort?" question brings up the screen.

   ===================================

I tried doing an RZX of the loading procedure, but it seems that RZX recordings don't work very well when a tape is being loaded. ZXSpin hung up as soon as I typed LOAD "" and although Fuse appeared to record a file neither Fuse or ZXSpin could play it back past the LOAD "" stage.

Anyway, it loads & runs independently of the DB1 disk. Just select +3 BASIC then LOAD "T:" for tape and LOAD "" and it loads, decrypts the code and starts off displaying the directory of whatever's in drive A.

Looking back at the original post, the intention was to create TAP files and transfer them to real +3 disks. Presuming that there's some facility for getting TAP files onto cassette then the DB1 G-Tape to Disk option would copy them to disk. It would only handle standard loaders, as it just calls the normal ROM tape routines, but that's all that TAPs use anyway. Any TZX transfers with custom loaders wouldn't work.

Be careful that the tape file names are compliant with disk file naming rules as DB1 doesn't check that tape files have valid names when it copies them to disk.

   ===================================
