Files
2026-02-23 11:01:15 +01:00

604 lines
17 KiB
Plaintext

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.osc
# 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 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