I have repaired a fair amount of drives, and every time I find myself loading a test or a diagnostic software from disk. This is a bit of a contradiction since the drive being tested, or repaired, might not even be able to load a program. I also have a variety of tools for different purposes and wanted to have everything in one place.
This is why i created a 1541 Diagnostic Cartridge.
The challenge was to get all these tools to fit into a 8K cart. I wanted to keep the hardware simple and a 16K cart would have overwritten the Basic interpreter.
Therefor I have optimized both code and visual on the tools to keep the size down. Some tools are old, others were written from scratch and a few I rewrote in machine code instead of basic. A couple of the tools are still in Basic, but optimized.
The cartridge is an 8K ROM at $8000-$9FFF
You can also use RESTORE to return to the menu.
You may need to send a “I0:” or turn the drive off/on before running further tests if an previous error has occurred.
Alignment
Occasionally I get questions about alignment and aligning the drive. There are some differences of opinion how to align a diskdrive, my personal view, and how I do it, is to use a special analogue disk and a dual trace oscilloscope. The analogue disk is a factory produced disk and has patterns written on specific tracks. An analogue alignment disk can not be duplicated.
1541 Diagnostic Cartridge Alignment Check. This program was distributed with a computer magazine and gives a quick drive alignment health instead of hooking up an oscilloscope. The program was completely disassembled, compacted (code and texts) and disk routines rewritten to share I/O routines just to fit onto the cart with the other tools.
The Alignment check program can (I, however, do not recommend doing it this way) be used to adjust the alignment but it will only be as accurate as the drive, or system, the disk was written with.
The two first columns should be identical, otherwise the alignment is off by a whole track(or more), most often this indicates an incorrectly positioned head stop. The third column indicates how well the drive can read data off each track, its alignment, and should be 100%, or atleast very close to. Fourth column is between tracks (or half tracks), this value can fluctuate a bit even on a well aligned drive. The 1541 allows for some tolerance and therefore some values can be within reasonable limits.
It is very seldom when you actually need to align a drive for proper functionality. If the drive works in daily usage and does not make noise or do continious re-reads or searches it is probably ok. If a drive fails to read disks, begin with cleaning the head and lubricate the rails. If this does not help, the R/W head might be damaged, quite often seen on the Mitsumi D500 mechanism. You can verify it by measuring the R/W head using an ohm-meter. Remember that a slightly misaligned drive is probably able to format and read its own formatted disk.
Most important, if it works, don’t fix it 😉
Recommended reading : Commodore Diskette Diagnostic Manual Version 2 (3140451-01) and Commodore 1541 Troubleshooting & Repair Guide (SAMS)
Update 2020.09: C64iSTANBUL designed a PCB, You can find it on pcbway 🙂
Update 2019.12: A few words about alignment.
Update 2019.12: TFW8B is selling their version of the cartridge.
Update 2017.09: The Cartridge is also available at the Protovision shop.
Update 2015.12: Upon request from their customers, The Shareware PLUS Commodore 64 & 128 Blog asked me if they could offer the 1541 diagnostic cartridge in their product sortiment.
1541 Diagnostic PCB by C64iSTANBUL. Looking great, thanks ! 🙂
Update
CHECK64 is an updated package for 586220/781220/789010 diagnostics, see Diagnostic Carts and Manuals.
This post spawned out of a discussion at a facebook group about the commodore diagnostics reporting errors when using custom kernals. I decided to modify the kernal detection routine to identify good known kernals from a checksum table. Thanks to Jonny Hylander, Fredric QJ Blåholtz and Krister Andersson for ideas and suggestions.
586220+ : Initial version. Disassembly and kernel identification routines by www.worldofjani.com.
586220+ v0.4 : Marty/Radwar sent a huge list of kernal checksums. This version is able to identify a staggering 49 different kernals, for example Professional Dos, RapiDos, DolphinDos and Speeddos. Download the v0.4 sourcecode for a full list.
586220++ v0.5 SX-64 Tape Port check removal : KiWi at www.SX-64.de sent me a version which works correctly on the SX-64. Scroll down for the download and sourcecode. See his page here.
586220++ v0.5 Expanded window for paddle test by Sven Arke. Klick here.
586220* Proper chip number display for SX-64 and C-64 by Ted Saari. Readme.
See Diagnostic Carts and Manuals for information about the harness for this ROM.
2020-06 : giox sent me an updated standalone program which identifies 137 kernals. There is an ID clash (which can be expected at some point) for 901246-01(4064 Kernal) and Armageddon.
Background.
The diagnostic 586220 does a checksum on the kernal ROM to verify if it is ok. It will only identify the original CBM ROMs. All other (even good, for example JiffyDos) kernals will be marked as “BAD”.
The 586220 was used since i have done an reassembly/disassembly of it earlier.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
$892f ;KERNAL ROM TEST LDA #$37 STA A01 LDA #>$E000 STA AF9 LDA #$20 ;$2000 bytes of memory (20 pages) STA A0F LDA #$00 ;set checksum = 0 STA AF8 TAY CLC I8941 ADC (PF8),Y ;+ INY BNE I8941 INC AF9 DEC A0F ;page counter BNE I8941 ADC #$00 ;< A-register holds checksum |
Code to calculate the checksum.
Depending on $FF80(Kernel revision) the checksum is either $E0 or $E1. This determines if Kernal is marked as “OK” or “BAD” by the diagnostic test.
I remembered that the C128 diagnostic cart displays the checksum. When running the C128 diagnostic(789010) the checksum on the C64 Kernal is reported as $D4. After investigating the code, which is identical to the one above except for the fact that only $1F00 of memory is checked, this is probably due to $FF00-$FF04 belong to the MMU.
We shared ideas about how this would be accomplished, but also noticed that some of the different kernals generated the same checksum. This might be deliberate for them to pass a diagnostic test.
All code below is compatible with 64tass (i.e. Turbo Assembler compatible).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
lda #0 sta zp_chk1 ;csum1 lo sta zp_chk2 ;csum2 mid sta zp_chk3 ;csum3 hi sta zp_addr+0 ;addr lo tay ;=0 chkloop clc adc (zp_addr),y ;+ bcc chkskip inc zp_chk2 ;csum2 mid bne chkskip pha tya ;addr lo(y) eor zp_chk3 ;csum3 hi sta zp_chk3 pla chkskip iny bne chkloop inc zp_addr+1 ;addr hi dex ;pages to check bne chkloop sta zp_chk1 ; |
The new checksum routine. To make a distinction, the address lowbyte is xor:ed and therefor not resulting in an identical checksum.
…I made a program that can identify the kernal ROM.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
checksumtbl .word rom_name_1 .byte $bb,$d4,$fd ;checksum 901227-01 .word rom_name_2 .byte $b6,$c7,$0a ;checksum 901227-03 .word rom_name_3 .byte $bd,$c7,$0b ;checksum sx.251104-04 rom_name_1 .text "901227-01",0 rom_name_2 .text "901227-03",0 rom_name_3 .text "251104-04 sx64",0 |
A table is used for the checksum and a pointer(.word) to the matching ROM name. You can easily add new checksums and ROMs to the code.
Incorporate the checksum with Diagnostic 586220
The goal is to replace the original checksum routine with the code above.
1 2 3 4 5 |
I822C JSR I8888 ;COLOR RAM test JSR I890E ;KERNAL/BASIC/CHARAC ROM test JSR I8A44 ;CASSETTE test |
As we can see in the disassembly, the routine for ROM tests are at $890E. Further investigations reveal that code between $890E and $8A44 can be replaced. This area also has the routines to check BASIC and CHARACTER ROM.
1 2 3 4 5 6 7 8 9 10 |
I8926 LDA F9946,X ;"CHARAC" STA F05B8,X DEX BPL I8926 ;-------------------------------------------------------- ; CALCULATE CHECKSUMS FOR ROMs ; clear from current position up to $8A44 |
Checksum routine is located a few lines below $8926.
After inserting the code, you can now assemble(compile) the code with c64tass. I won’t go into details about the code itself, but it is presented and downloadable further down on the page.
1 2 3 |
64tass -a 586220plus.tas -o 586220plus.o64 |
The output file (.o64) can now be written to an eprom. Skip the two first bytes (0x00, 0x80) which is the loadingadress of the file.
1 2 3 4 5 |
cartconv -t normal -name "586220plus" -i 586220plus.o64 -o 586220plus.crt winvice\x64.exe -cartcrt 586220plus.crt -kernal 901227-03.bin |
You can also test the cart in vice by converting it to a crt. Cartconv.exe is included with the Vice emulator.
586220+ diagnostic, it is now possible to identify the kernal ROM.
The new checksum code.
Checksums for BASIC and CHAR are also displayed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
; code by jani@worldofjani.com outscrnadr = kern_out kern_out = A0575 basic_out = A059D char_out = A05C5 KERNAL_ROM = $E000 BASIC_ROM = $A000 CHAR_ROM = $D000 zp_offs = $f0 zp_chk1 = $f1 zp_chk2 = $f2 zp_chk3 = $f3 zp_addr = $f4 ;+1 LDA #$37 STA A01 lda #>KERNAL_ROM ldx #$20 ldy #(kern_out-outscrnadr) jsr newchecksum jsr id_kROM lda #>BASIC_ROM ldx #$20 ldy #(basic_out-outscrnadr) jsr newchecksum LDA #$33 STA A01 LDA #>CHAR_ROM ldx #$10 ldy #(char_out-outscrnadr) jsr newchecksum LDA #$37 STA A01 jmp exit_chksum id_kROM lda #<checksumtbl sta zp_addr+0 lda #>checksumtbl sta zp_addr+1 id_loop ldy #4 lda (zp_addr),y cmp #$ff beq id_notfound cmp zp_chk1 bne id_noteq dey lda (zp_addr),y cmp zp_chk2 bne id_noteq dey lda (zp_addr),y cmp zp_chk3 beq id_found id_noteq lda zp_addr+0 clc adc #5 sta zp_addr+0 lda zp_addr+1 adc #0 sta zp_addr+1 bne id_loop id_notfound lda #<rom_name0 ldx #>rom_name0 ldy #0 beq id_unknown id_found dey lda (zp_addr),y tax dey lda (zp_addr),y id_unknown sta zp_chk1+0 stx zp_chk1+1 id_txtl lda (zp_chk1),y beq id_exitx sta $0750+1,y iny bne id_txtl id_exitx rts newchecksum sta zp_addr+1 sty zp_offs lda #0 sta zp_chk1 ;csum1 lo sta zp_chk2 ;csum2 mid sta zp_chk3 ;csum3 hi sta zp_addr+0 ;addr lo tay ;=0 chkloop clc adc (zp_addr),y ;+ bcc chkskip inc zp_chk2 ;csum2 mid bne chkskip pha tya ;addr lo(y) eor zp_chk3 ;csum3 hi sta zp_chk3 pla chkskip iny bne chkloop inc zp_addr+1 ;addr hi dex bne chkloop sta zp_chk1 ldy zp_offs jsr hex2XA ;lo sta outscrnadr+4,y txa sta outscrnadr+5,y lda zp_chk2 ;mid jsr hex2XA sta outscrnadr+2,y txa sta outscrnadr+3,y lda zp_chk3 ;hi jsr hex2XA sta outscrnadr+0,y txa sta outscrnadr+1,y rts hex2XA pha and #$0f jsr hex2sa tax pla lsr lsr lsr lsr hex2sa clc adc #$30 cmp #$3a bmi hex2sb sbc #$39 hex2sb rts ;-------------------------------------------------------- checksumtbl = *-5 .word rom_name1 .byte $bb,$d4,$fd ;checksum 901227-01 .word rom_name2 .byte $8b,$c7,$0b ;901227-02 .word rom_name3 .byte $b6,$c7,$0a ;901227-03 .word rom_name4 .byte $ea,$c9,$09 ;901227-03-DK .word rom_name5 .byte $b3,$c5,$ca ;swedish-02 .word rom_name6 .byte $b0,$c5,$c9 ;swedish-03 .word rom_name7 .byte $bd,$c7,$0b ;sx.251104-04 .word rom_name8 .byte $ba,$c7,$88 ;sx64-scand.bin .word rom_name9 .byte $5c,$d1,$83 ;906145-02-jp .word rom_name10 .byte $56,$b5,$ca ;c64gs .word rom_name11 .byte $68,$a9,$e5 ;Jiffydos6.01 .word $ffff .byte $ff,$ff,$ff ;END ;-------------------------------------------------------- .enc "screen" rom_name0 .text "unknown",0 rom_name1 .text "901227-01",0 rom_name2 .text "901227-02",0 rom_name3 .text "901227-03",0 rom_name4 .text "901227-03 dk",0 rom_name5 .text "swedish-02",0 ;325017-02 rom_name6 .text "swedish-03",0 ;325182-01 (c128) rom_name7 .text "251104-04 sx64",0 rom_name8 .text "sx64-scand",0 rom_name9 .text "906145-02 jp",0 rom_name10 .text "390852-01 gs64",0 rom_name11 .text "jiffydos 6.01",0 .enc "none" ;-------------------------------------------------------- |