mirror of
https://github.com/ISpillMyDrink/OpenSuperClone.git
synced 2026-05-03 21:40:33 +00:00
604 lines
17 KiB
Plaintext
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
|
|
|
|
|
|
|