seti $printhelp = $printhelp
seti $help = $help
if $help = 1
  echo 'Western Digital ROYL dump ROM to file using vendor specific commands.'
  echo 'By default this will dump the ROM on the PCB to the file "rom.bin".'
  if $printhelp = 1
    exit 0
  endif
  echo 'Hit ENTER to continue...'
  userinput $choicestring
  previousscript
endif

include good_subroutines

# set the filename to be written to
sets $filename = "rom.bin"
# delete existing file so there is no confusion
deletefile $filename

# get model and serial using identify device command
buffersize 512
setreadpio
ata28cmd 0 0 0 0 0 0xa0 0xec
# check if command failed
gosub status_check
wordflipbuffer 0 512

# extract model and serial and trim leading and trailing spaces
sets $model = "null"
sets $serial = "null"
seti $count = 0
seti $start_offset = 54
while $count < 40
  seti $byte = buffer $start_offset
  if $byte > 0x20
    break
  endif
  seti $start_offset = $start_offset + 1
  seti $count = $count + 1
done
seti $count = 0
seti $end_offset = 93
while $count < 40
  seti $byte = buffer $end_offset
  if $byte > 0x20
    break
  endif
  seti $end_offset = $end_offset - 1
  seti $count = $count + 1
done
seti $end_offset = $end_offset + 1
seti $size = $end_offset - $start_offset
if $size > 0
  sets $model = buffer $start_offset $size
endif
# find out if it is a WD drive
sets $wdcheck = buffer $start_offset 3
sets $compare = "WDC"
if $wdcheck != $compare
  echo "Model: " $model
  echo "Drive is not WD, exiting
  previousscript
endif

seti $count = 0
seti $start_offset = 20
while $count < 20
  seti $byte = buffer $start_offset
  if $byte > 0x20
    break
  endif
  seti $start_offset = $start_offset + 1
  seti $count = $count + 1
done
seti $count = 0
seti $end_offset = 39
while $count < 20
  seti $byte = buffer $end_offset
  if $byte > 0x20
    break
  endif
  seti $end_offset = $end_offset - 1
  seti $count = $count + 1
done
seti $end_offset = $end_offset + 1
seti $size = $end_offset - $start_offset
if $size > 0
  sets $serial = buffer $start_offset $size
endif

echo "Model: " $model
echo "Serial: " $serial

clearbuffer


# enable vendor specific commands
buffersize 0
setreadpio
ata28cmd 0x45 0x0b 0x00 0x44 0x57 0xa0 0x80
# check if command failed
gosub status_check

# vsc to prepare (specify ROM size in bytes = 0x10000 * number of chunks)
#  192KB = 3 chunks, 256KB = 4 chunks, 512KB = 8 chunks, etc
seti $chunks = 4
buffersize 0x200
clearbuffer
setbuffer 0
  24 00 01 00 00 00 00 00 00 00 04
endbuffer
setwritepio
ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0
# check if command failed
gosub status_check

# setup the scratchpad
seti $scratchpad_size = $chunks * 0x10000
scratchpadsize $scratchpad_size

# vsc to read ROM in 64KB chunks
seti $count = 0
while $count < $chunks
  buffersize 0x10000
  clearbuffer
  ata28cmd 0xd5 0x80 0xbf 0x4f 0xc2 0xa0 0xb0
  # check if command failed
  gosub status_check
  # copy the sectors to the scratchpad
  seti $offset = $count * 0x10000
  copybuffertoscratchpad 0 $offset 0x10000
  seti $count = $count + 1
done

# write the sectors to the file
writescratchpad $filename 0 0 $scratchpad_size
# show it on the screen
printscratchpad 0 $scratchpad_size

# disable vendor specific commands
buffersize 0
setreadpio
ata28cmd 0x44 0x0b 0x00 0x44 0x57 0xa0 0x80
# check if command failed
gosub status_check

previousscript
end



subroutine status_check
  seti $command_failed = 0
  gosub check_command_status
  if $command_failed = 1
    echo "Command failed!"
    gosub show_sense_data
    gosub show_ata_return_status
    previousscript
  endif
endsubroutine