seti $printhelp = $printhelp seti $help = $help if $help = 1 echo 'WD patch ram test' if $printhelp = 1 exit 0 endif echo 'Hit ENTER to continue...' userinput $choicestring previousscript endif echo "" include good_subroutines # set a blank string variable to compare with user input # make sure not to set this anyplace else sets $null = "" # set this to itself for use with the menu system # make sure not to set this anyplace else # if it was not previously set it will = 0 seti $using_menu = $using_menu # set these for later, and to make it easy to change if needed seti $rom_read_block_size = 65536 seti $ram_read_block_size = 65536 seti $ram_start = 0x8000000 seti $ram_size = 0x40000 seti $max_ram_size = 0x2000000 if $ram_size < $ram_read_block_size seti $ram_read_block_size = $ram_size endif seti $divide_check = $rom_read_block_size % 512 if $divide_check != 0 echo "rom_read_block_size is not dividable by 512" previousscript endif seti $divide_check = $ram_read_block_size % 512 if $divide_check != 0 echo "ram_read_block_size is not dividable by 512" previousscript endif gosub find_ram_size gosub dump_ram gosub process_ram previousscript end subroutine find_ram_size gosub enable_vsc seti $find_ram_read_size = 0x200 scratchpadsize $find_ram_read_size seti $position = $ram_start seti $remainder = $find_ram_read_size if $remainder != 0 seti $write_offset = 0 seti $read_size = $remainder hex echo "position=0x" $position " rsize=0x" $read_size decimal # vsc to prepare for ram read #echo "prepare to read ram" buffersize 0x200 clearbuffer seti $offsetl = $position & 0xff seti $offsetm1 = $position > 8 seti $offsetm1 = $offsetm1 & 0xff seti $offsetm2 = $position > 16 seti $offsetm2 = $offsetm2 & 0xff seti $offseth = $position > 24 seti $offseth = $offseth & 0xff seti $sizel = $read_size & 0xff seti $sizem1 = $read_size > 8 seti $sizem1 = $sizem1 & 0xff seti $sizem2 = $read_size > 16 seti $sizem2 = $sizem2 & 0xff seti $sizeh = $read_size > 24 seti $sizeh = $sizeh & 0xff setbuffer 0 13 00 01 00 $offsetl $offsetm1 $offsetm2 $offseth $sizel $sizem1 $sizem2 $sizeh endbuffer setwritepio ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0 # check if command failed gosub status_check # vsc to get the ram seti $sectors = $read_size / 512 buffersize $read_size clearbuffer setreadpio #echo "reading ram" ata28cmd 0xd5 $sectors 0xbf 0x4f 0xc2 0xa0 0xb0 # check if command failed gosub status_check # copy the buffer to the scratchpad copybuffertoscratchpad 0 $write_offset $read_size endif printscratchpad 0 32 seti $check1 = scratchpad 0 qw seti $check2 = scratchpad 8 qw seti $read_size = $find_ram_read_size while 1 = 1 seti $position = $ram_start + $ram_size hex echo "position=0x" $position " size=0x" $read_size decimal # vsc to prepare for ram read #echo "prepare to read ram" buffersize 0x200 clearbuffer seti $offsetl = $position & 0xff seti $offsetm1 = $position > 8 seti $offsetm1 = $offsetm1 & 0xff seti $offsetm2 = $position > 16 seti $offsetm2 = $offsetm2 & 0xff seti $offseth = $position > 24 seti $offseth = $offseth & 0xff seti $sizel = $read_size & 0xff seti $sizem1 = $read_size > 8 seti $sizem1 = $sizem1 & 0xff seti $sizem2 = $read_size > 16 seti $sizem2 = $sizem2 & 0xff seti $sizeh = $read_size > 24 seti $sizeh = $sizeh & 0xff setbuffer 0 13 00 01 00 $offsetl $offsetm1 $offsetm2 $offseth $sizel $sizem1 $sizem2 $sizeh endbuffer setwritepio ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0 # check if command failed gosub status_check # vsc to get the ram seti $sectors = $read_size / 512 buffersize $read_size clearbuffer setreadpio #echo "reading ram" ata28cmd 0xd5 $sectors 0xbf 0x4f 0xc2 0xa0 0xb0 # check if command failed gosub status_check seti $cmp1 = buffer 0 qw seti $cmp2 = buffer 8 qw if $cmp1 = $check1 if $cmp2 = $check2 hex echo "ram size is 0x" $ram_size decimal break endif endif seti $ram_size = $ram_size * 2 if $ram_size > $max_ram_size hex echo "ram size not found, using default maximum size of 0x" $max_ram_size decimal seti $ram_size = $max_ram_size break endif done gosub disable_vsc endsubroutine subroutine dump_ram gosub enable_vsc scratchpadsize $ram_size seti $position = $ram_start seti $read_size = $ram_read_block_size seti $block_count = $ram_size / $ram_read_block_size seti $remainder = $ram_size % $ram_read_block_size seti $count = 0 while $count < $block_count hex echo "position=0x" $position " size=0x" $read_size decimal # vsc to prepare for ram read #echo "prepare to read ram" buffersize 0x200 clearbuffer seti $offsetl = $position & 0xff seti $offsetm1 = $position > 8 seti $offsetm1 = $offsetm1 & 0xff seti $offsetm2 = $position > 16 seti $offsetm2 = $offsetm2 & 0xff seti $offseth = $position > 24 seti $offseth = $offseth & 0xff seti $sizel = $read_size & 0xff seti $sizem1 = $read_size > 8 seti $sizem1 = $sizem1 & 0xff seti $sizem2 = $read_size > 16 seti $sizem2 = $sizem2 & 0xff seti $sizeh = $read_size > 24 seti $sizeh = $sizeh & 0xff setbuffer 0 13 00 01 00 $offsetl $offsetm1 $offsetm2 $offseth $sizel $sizem1 $sizem2 $sizeh endbuffer setwritepio ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0 # check if command failed gosub status_check # send again ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0 # check if command failed gosub status_check # vsc to get the ram seti $sectors = $read_size / 512 buffersize $read_size clearbuffer setreadpio #echo "reading ram" ata28cmd 0xd5 $sectors 0xbf 0x4f 0xc2 0xa0 0xb0 # check if command failed gosub status_check seti $write_offset = $count * $read_size # copy the buffer to the scratchpad copybuffertoscratchpad 0 $write_offset $read_size # write the buffer to file #writebuffer $file 0 $write_offset $read_size seti $count = $count + 1 seti $position = $position + $ram_read_block_size done if remainder != 0 seti $write_offset = $write_offset + $read_size seti $read_size = $remainder hex echo "position=0x" $position " rsize=0x" $read_size decimal # vsc to prepare for ram read echo "prepare to read ram" buffersize 0x200 clearbuffer seti $offsetl = $position & 0xff seti $offsetm1 = $position > 8 seti $offsetm1 = $offsetm1 & 0xff seti $offsetm2 = $position > 16 seti $offsetm2 = $offsetm2 & 0xff seti $offseth = $position > 24 seti $offseth = $offseth & 0xff seti $sizel = $read_size & 0xff seti $sizem1 = $read_size > 8 seti $sizem1 = $sizem1 & 0xff seti $sizem2 = $read_size > 16 seti $sizem2 = $sizem2 & 0xff seti $sizeh = $read_size > 24 seti $sizeh = $sizeh & 0xff setbuffer 0 13 00 01 00 $offsetl $offsetm1 $offsetm2 $offseth $sizel $sizem1 $sizem2 $sizeh endbuffer setwritepio ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0 # check if command failed gosub status_check # send again ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0 # check if command failed gosub status_check # vsc to get the ram seti $sectors = $read_size / 512 buffersize $read_size clearbuffer setreadpio echo "reading ram" ata28cmd 0xd5 $sectors 0xbf 0x4f 0xc2 0xa0 0xb0 # check if command failed gosub status_check # copy the buffer to the scratchpad copybuffertoscratchpad 0 $write_offset $read_size # write the buffer to file #writebuffer $file 0 $write_offset $read_size endif gosub disable_vsc echo "ram dump successful" endsubroutine subroutine process_ram echo "processing ram" printscratchpad 0 512 seti $pmcblock_number = 0 seti $error = 0 while 1 = 1 seti $table_offset = $pmcblock_number * 32 seti $working_offset = $table_offset seti $block_number = scratchpad $table_offset if $pmcblock_number = 0 if $block_number != 0x5a hex echo "ERROR: expecting first byte of 0x5a but found 0x" $block_number decimal seti $error = $error + 1 break endif elseif $pmcblock_number != $block_number hex echo "ERROR: expecting block number 0x" $pmcblock_number " but found 0x" $block_number decimal seti $error = $error + 1 break endif seti $working_offset = $table_offset + 4 seti $checksum_location = scratchpad $working_offset dw seti $working_offset = $table_offset + 8 seti $block_size = scratchpad $working_offset dw seti $checksum_length = $checksum_location - $block_size seti $working_offset = $table_offset + 0x0c seti $block_start = scratchpad $working_offset dw seti $block_end = $block_start + $checksum_location seti $working_offset = $table_offset + 0x0e seti $last_entry = scratchpad $working_offset seti $working_offset = $table_offset + 0x1f seti $table_checksum = scratchpad $working_offset seti $working_offset = $table_offset + 0x10 seti $load_pos1 = scratchpad $working_offset dw seti $working_offset = $table_offset + 0x14 seti $load_pos2 = scratchpad $working_offset dw seti $calulated_tablechk = 0 seti $count = 0 while $count < 31 seti $position = $table_offset + $count seti $byte = scratchpad $position seti $calulated_tablechk = $calulated_tablechk + $byte seti $count = $count + 1 done seti $calulated_tablechk = $calulated_tablechk & 0xff if $table_checksum != $calulated_tablechk echo "ERROR: bad table checksum" endif hex sets $name = "n0x" $pmcblock_number "_a0x" $load_pos1 "_b0x" $load_pos2 "_s0x" $block_size decimal deletefile $name writescratchpad $name $block_start 0 $block_size if $checksum_length = 1 seti $position = $block_start + $block_size seti $checksum = scratchpad $position seti $calculated_checksum = 0 seti $count = 0 while $count < $block_size seti $position = $block_start + $count seti $byte = scratchpad $position seti $calculated_checksum = $calculated_checksum + $byte seti $count = $count + 1 done seti $calculated_checksum = $calculated_checksum & 0xff elseif $checksum_length = 2 seti $position = $block_start + $block_size seti $checksum = scratchpad $position w seti $calculated_checksum = 0 seti $count = 0 while $count < $block_size seti $position = $block_start + $count seti $word = scratchpad $position w seti $calculated_checksum = $calculated_checksum + $word seti $count = $count + 2 done seti $calculated_checksum = $calculated_checksum & 0xffff #seti $calculated_checksum = 0xffff - $calculated_checksum #seti $calculated_checksum = $calculated_checksum + 1 else echo "ERROR: bad checksum length of " $checksum_length seti $checkerr = 1 endif hex if $checksum = $calculated_checksum sets $checkstring = " calulated=0x" $calculated_checksum " (good)" else sets $checkstring = " calulated=0x" $calculated_checksum " (BAD)" endif echo "block=0x" $pmcblock_number " start=0x" $block_start " size=0x" $block_size " checksum=0x" $checksum $checkstring decimal if $last_entry != 0 echo "finished processing blocks" break endif seti $pmcblock_number = $pmcblock_number + 1 done # search for modules and check them, starting from the end of the last rom entry echo "Searching for modules." echo "Note that it is normal for some module checksums to be bad," echo "as they are not full size in the ROM." sets $header_check = "ROYL" seti $position = $block_end + 0x0e0000 seti $search_end = $ram_size - 4 while $position < $search_end sets $header = scratchpad $position 4 if $header = $header_check # process the module seti $working_offset = $position #echo "Header:" #printscratchpad $working_offset 4 seti $working_offset = $position + 8 seti $mod_id = scratchpad $working_offset w hex #echo "Module ID = 0x" $mod_id # find how many sectors the module contains seti $working_offset = $position + 0xa seti $mod_length_sectors = scratchpad $working_offset seti $working_offset = $position + 0xb seti $tempnum = scratchpad $working_offset seti $tempnum = $tempnum > 8 seti $mod_length_sectors = $mod_length_sectors + $tempnum #echo "Size in sectors = 0x" $mod_length_sectors seti $working_offset = $position + 0xc seti $checksum = scratchpad $working_offset dw #echo "32 bit checksum = 0x" $checksum seti $working_offset = $position + 0x10 #echo "Mod version:" #printscratchpad $working_offset 8 decimal seti $module_size = $mod_length_sectors * 512 seti $calculated_checksum = 0 seti $count = 0 while $count < $module_size seti $working_offset = $position + $count if $working_offset > $search_end echo "end of module is past end of rom" break endif seti $dword = scratchpad $working_offset dw seti $calculated_checksum = $calculated_checksum + $dword seti $count = $count + 4 # skip the actual checksum bytes if $count = 0xc seti $count = $count + 4 endif done seti $calculated_checksum = $calculated_checksum & 0xffffffff seti $calculated_checksum = 0xffffffff - $calculated_checksum seti $calculated_checksum = $calculated_checksum + 1 hex if $checksum = $calculated_checksum sets $checkstring = " calulated=0x" $calculated_checksum " (good)" else sets $checkstring = " calulated=0x" $calculated_checksum " (bad)" endif echo "pos=0x" $position " ModID=0x" $mod_id " size=0x" $mod_length_sectors $checkstring decimal if $mod_id = 2 seti $module_position = $position seti $module_length = $mod_length_sectors * 512 gosub patch_module endif endif seti $position = $position + 1 done endsubroutine subroutine patch_module buffersize $module_length clearbuffer copyscratchpadtobuffer $module_position 0 $module_length printbuffer 0 $module_length seti $pcount = 26 seti $poffset = $pcount * 4 seti $pcount = $pcount + 1 seti $poffset = $poffset + 0x32 seti $record_offset = buffer $poffset w seti $poffset = $poffset + 2 seti $record_size = buffer $poffset w echo "" echo "Data record #" $pcount ":" printbuffer $record_offset $record_size seti $byte_offset = $record_offset + 2 setbuffer $byte_offset 00 endbuffer echo "Data record #" $pcount " after patch:" printbuffer $record_offset $record_size if 1 = 1 gosub enable_vsc seti $wposition = $byte_offset + $module_position seti $wposition = $wposition + 0x8000000 seti $write_size = 0x01 hex echo "wposition=0x" $wposition " wsize=0x" $write_size decimal # vsc to prepare for ram write echo "prepare to write ram" buffersize 0x200 clearbuffer seti $offsetl = $wposition & 0xff seti $offsetm1 = $wposition > 8 seti $offsetm1 = $offsetm1 & 0xff seti $offsetm2 = $wposition > 16 seti $offsetm2 = $offsetm2 & 0xff seti $offseth = $wposition > 24 seti $offseth = $offseth & 0xff seti $sizel = $write_size & 0xff seti $sizem1 = $write_size > 8 seti $sizem1 = $sizem1 & 0xff seti $sizem2 = $write_size > 16 seti $sizem2 = $sizem2 & 0xff seti $sizeh = $write_size > 24 seti $sizeh = $sizeh & 0xff setbuffer 0 13 00 02 00 $offsetl $offsetm1 $offsetm2 $offseth $sizel $sizem1 $sizem2 $sizeh endbuffer hex echo $offsetl " " $offsetm1 " " $offsetm2 " " $offseth " " $sizel " " $sizem1 " " $sizem2 " " $sizeh decimal setwritepio ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0 # check if command failed gosub status_check # vsc to get the ram seti $sectors = $read_size / 512 buffersize 0x200 clearbuffer setbuffer 0 02 endbuffer setwritepio echo "writing ram" ata28cmd 0xd6 0x01 0xbf 0x4f 0xc2 0xa0 0xb0 # check if command failed gosub status_check gosub disable_vsc endif endsubroutine 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 subroutine enable_vsc # enable vendor specific commands echo "enable vsc" buffersize 0 setreadpio ata28cmd 0x45 0x0b 0x00 0x44 0x57 0xa0 0x80 # check if command failed gosub status_check endsubroutine subroutine disable_vsc # disable vendor specific commands echo "disable vsc" buffersize 0 setreadpio ata28cmd 0x44 0x0b 0x00 0x44 0x57 0xa0 0x80 # check if command failed gosub status_check endsubroutine