HD-Park-Switch or how to patch a CMD-HD to your own needs. by Wolfram Sang (Ninja/The Dreams - www.the-dreams.de) =========================================================== One thing I really like about the C64 nowadays is that it is a quiet computer. No fans or similar, wonderful! Unfortunately, the SCSI-HDD inside my CMD-HD is the opposite. When it is running, it sounds like an airplane. Being a curious programmer, I tried to get rid of this annoyance. I realized that I never use the 'Write protect' button. So, maybe I could abuse it to park/unpark my HDD? Well, the forthcoming project might not be too useful for most of you. Nevertheless, it might give you an idea how to apply own patches to the CMD-HD-ROM. You never know when you might need that! How to do First of all, the ROM is not really ROM but in fact RAM which can be protected from storing data to it. This makes sence, as the HD-KERNAL has to be loaded from the system partition when the HD boots up. Of course, applying patches is pretty easy then: unprotect RAM, modify KERNAL, protect RAM. If the 1541 had such capabilities... The patch itself is simple. Install a backpack to that point where the 'Write protect'-flag was toggled. From there, give the corresponding SCSI-jobcode to park/unpark the HD-mechanism. Finally, go back to the standard procedure. ROM-Versions 1.86, 1.90 and 1.92 are handled (are there any other around?), though only 1.92 was tested. As we do only easy stuff, I don't expect too much problems with those older versions. For the rest, I will let the source-code speak. All neccessary information was re-engineered (and that was the main work) by me or Christoph Thelen aka Doc Bacardi/The Dreams. Enjoy, comments are welcome :) ; ------------------------------------------------------------------------ ; HD-Park-Switch V1.0 by Ninja/The Dreams in 2002 org $0801 binclude "help\hdpshead.prg",2 ; include BASIC-header, which contains some information and ; will start the following routine. Works in 64 and 128-mode! align 256 ; start at beginning of a page jmp_in: lda #$0f ; channel #15 ldx $ba ; use current device tay ; use command channel jsr $ffba ; set file-parameters lda $fff6 cmp #$ff ; check platform bne c64_found ; C64, then jump lda #$0f tax ; set mem-config for channel jsr $ff68 ; in C128-mode ldy $2e ; get C128-BASIC-start byt $2c ; skip next opcode c64_found: ldy $2c ; get C64-BASIC-start iny ; increment to point to this page ldx #lo(mw_command) ; lobyte of command lda #hd_code_len+6 ; we send all bytes at once jsr $ffbd ; set up memory-write-command jsr $ffc0 ; send command ldx #$0f jsr $ffc6 ; set channel as input jsr $ffcf ; get char cmp #'0' ; "0" from OK-string? bne drive_err ; if not, skip execution (will be probably ; a non CMD-HD-drive complaining about the ; too long command string) ldx #$0f jsr $ffc9 ; channel as output lda #'U' jsr $ffd2 lda #'3' jsr $ffd2 ; send "U3", executes at $0500 drive_err: jsr $ffcc ; restore input/output lda #$0f jmp $ffc3 ; close channel and go back ; ------------------------------------------------------------------------ mw_command: byt "M-W",0,5,hd_code_len hd_code: phase $0500 ; HD-Code is at $0500 sei ; no interrupts ldy #2 ; check 3 ROM versions (1.86, 1.90, 1.92) next_rom: ldx rom_ofs,y ; get version-specific offset into x lda #$4c ; $4c = JMP opcode cmp $f28a,x ; present in ROM? bne wrong_rom ; no, then next version lda rom_jmplo,y ; get version-specific address_lo cmp $f28b,x ; present in ROM? bne wrong_rom ; no, then next version sta bp_mod+1 ; store address_lo into our backpack lda rom_jmphi,y ; get version-specific address_hi cmp $f28c,x ; present in ROM? beq rom_found ; yes, then go patching wrong_rom: dey ; try next version bpl next_rom ; still one left? cli rts ; no, then goodbye without changes rom_found: sta bp_mod+2 ; store address_hi into our backpack lda $8f00 ora #$20 sta $8f00 ; unprotect RAM ldy #bp_len-1 copy_bp: lda backpack,y sta $ff60,y dey bpl copy_bp ; copy backpack to $FF60 lda #$60 sta $f28b,x lda #$ff ; apply JMP $FF60 to version-specific sta $f28c,x ; address lda $8f00 and #$df sta $8f00 ; protect RAM cli rts ; goodbye ; ------------------------------------------------------------------------ backpack: lda #$f8 ; SCSI-Jobcode 'Start Device' bit $49 ; Check for 'Write Protect' bpl wp_disabled ; disabled, then skip next opcode lda #$fa ; SCSI-Jobcode 'Stop Device' wp_disabled: sta $20 ; into Native-Job-Queue bp_mod: jmp $FFFF ; back to original routine ; self-modified from above bp_len = *-backpack ; ------------------------------------------------------------------------ ; V1.86 V1.90 V1.92 rom_ofs: byt $f28a-$f28a , $f2f6-$f28a , $f331-$f28a ; where to patch rom_jmplo: byt $be , $2a , $65 rom_jmphi: byt $f2 , $f3 , $f3 ; what to patch dephase hd_code_len = *-hd_code end $0801 ; ------------------------------------------------------------------------ And here the uuencoded binary... begin 666 hd-park-switch.prg M`0@?"`H`CR!#340M2$0M4$%22RU35TE40T@@5C$N,`!""!0`CR!"62!.24Y* M02]42$4@1%)%04U3("A!54