mirror of
https://github.com/ISpillMyDrink/OpenSuperClone.git
synced 2026-05-04 05:50:51 +00:00
462 lines
13 KiB
Plaintext
462 lines
13 KiB
Plaintext
|
|
|
|
|
|
|
|
seti $printhelp = $printhelp
|
|
seti $help = $help
|
|
if $help = 1
|
|
echo 'Western Digital ROYL check ROM file.'
|
|
echo 'This script performs some checks on a ROM file.'
|
|
echo 'This requires the text variable "file" to be set.'
|
|
echo '"file" is the name of the file containing the ROM.'
|
|
echo 'This scipt does not perform any disk IO,'
|
|
echo 'so it can be ran with any target, even /dev/zero.'
|
|
|
|
if $printhelp = 1
|
|
exit 0
|
|
endif
|
|
echo 'Hit ENTER to continue...'
|
|
userinput $choicestring
|
|
previousscript
|
|
endif
|
|
|
|
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 the file name to be written
|
|
while 1 = 1
|
|
variablecheck $file
|
|
if $error_level < 16
|
|
seti $ask = 1
|
|
elseif $using_menu = 1
|
|
seti $ask = 1
|
|
endif
|
|
if $ask = 1
|
|
echo "Enter file name:"
|
|
userinput $choicestring
|
|
if $choicestring != $null
|
|
sets $file = $choicestring
|
|
break
|
|
else
|
|
echo "Choice cannot be blank!"
|
|
endif
|
|
else
|
|
break
|
|
endif
|
|
done
|
|
|
|
getfilesize $file
|
|
seti $file_size = $error_level
|
|
if $file_size < 0
|
|
echo "ERROR! File " $file " not found!"
|
|
previousscript
|
|
endif
|
|
echo "Reading the rom file"
|
|
seti $rom_size = $file_size
|
|
scratchpadsize $rom_size
|
|
clearscratchpad
|
|
readscratchpad $file 0 0 $rom_size
|
|
|
|
gosub process_rom
|
|
gosub process_rom
|
|
|
|
gosub save_patched_rom
|
|
|
|
|
|
previousscript
|
|
end
|
|
|
|
|
|
|
|
|
|
subroutine process_rom
|
|
echo "processing rom"
|
|
#printscratchpad 0 512
|
|
seti $pmcblock_number = 0
|
|
seti $error = 0
|
|
seti $first_block = $rom_size
|
|
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
|
|
if $table_offset < $first_block
|
|
echo "Warning, there is a gap between table end and first block start."
|
|
echo "This could mean a bad table entry, or it could be normal."
|
|
endif
|
|
echo "finished processing blocks"
|
|
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 + 0x1f
|
|
seti $table_checksum = scratchpad $working_offset
|
|
|
|
if $block_start < $first_block
|
|
seti $first_block = $block_start
|
|
endif
|
|
|
|
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
|
|
|
|
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 $error = $error + 1
|
|
endif
|
|
|
|
hex
|
|
if $checksum = $calculated_checksum
|
|
sets $checkstring = " calulated=0x" $calculated_checksum " (good)"
|
|
else
|
|
sets $checkstring = " calulated=0x" $calculated_checksum " (BAD)"
|
|
seti $error = $error + 1
|
|
endif
|
|
echo "block=0x" $pmcblock_number " start=0x" $block_start " size=0x" $block_size " checksum=0x" $checksum $checkstring
|
|
decimal
|
|
|
|
seti $pmcblock_number = $pmcblock_number + 1
|
|
done
|
|
if $error = 0
|
|
echo "ROM blocks appear to be good."
|
|
else
|
|
echo "WARNING: There were errors with the ROM blocks."
|
|
endif
|
|
|
|
# search for modules and check them, starting from the end of the last rom entry
|
|
echo "Searching for modules."
|
|
sets $header_check = "ROYL"
|
|
seti $position = $block_end
|
|
seti $search_end = $rom_size - 4
|
|
while $position < $search_end
|
|
sets $header = scratchpad $position 4
|
|
if $header = $header_check
|
|
seti $working_offset = $position + 8
|
|
seti $mod_id = scratchpad $working_offset w
|
|
hex
|
|
#echo "Module ID = 0x" $mod_id
|
|
if $mod_id = 0xb
|
|
gosub process_directory
|
|
elseif $mod_id = 0x20b
|
|
gosub process_directory
|
|
endif
|
|
endif
|
|
seti $position = $position + 1
|
|
done
|
|
endsubroutine
|
|
|
|
|
|
|
|
|
|
|
|
subroutine process_directory
|
|
echo "Directory module 0x" $mod_id " found, processing"
|
|
#printscratchpad $position 512
|
|
seti $directory_id = $mod_id
|
|
seti $directory_size = 0
|
|
seti $directory_offset = $position + 0x1e
|
|
seti $directory_total_count = scratchpad $directory_offset b
|
|
seti $directory_count = 0
|
|
seti $directory_offset = $position + 0x1f
|
|
while $directory_count < $directory_total_count
|
|
seti $entry_size = scratchpad $directory_offset b
|
|
seti $working_offset = $directory_offset + 0x1
|
|
seti $mod_copies = scratchpad $working_offset b
|
|
seti $working_offset = $directory_offset + 0x2
|
|
seti $mod_id = scratchpad $working_offset w
|
|
seti $working_offset = $directory_offset + 0x4
|
|
seti $mod_size = scratchpad $working_offset w
|
|
if $entry_size = 0
|
|
seti $entry_size = $last_entry_size
|
|
else
|
|
seti $last_entry_size = $entry_size
|
|
endif
|
|
if $mod_id = 1
|
|
seti $mod_size = $mod_size * 512
|
|
endif
|
|
#printscratchpad $directory_offset $entry_size
|
|
if $directory_id = $mod_id
|
|
seti $directory_size = $mod_size
|
|
endif
|
|
seti $working_offset = $directory_offset + 0xa
|
|
seti $mod_location = scratchpad $working_offset dw
|
|
seti $working_offset = $working_offset + 4
|
|
seti $mod_location1 = scratchpad $working_offset dw
|
|
seti $working_offset = $working_offset + 4
|
|
seti $mod_location2 = scratchpad $working_offset dw
|
|
seti $working_offset = $working_offset + 4
|
|
seti $mod_location3 = scratchpad $working_offset dw
|
|
if $mod_id = 0
|
|
hex
|
|
echo "ModID=0x" $mod_id " size=0x" $mod_size " location=0x" $mod_location
|
|
decimal
|
|
elseif $mod_id = 1
|
|
hex
|
|
echo "ModID=0x" $mod_id " size=0x" $mod_size " copies=0x" $mod_copies " locations=0x" $mod_location " 0x" $mod_location1 " 0x" $mod_location2 " 0x" $mod_location3
|
|
decimal
|
|
else
|
|
gosub process_module
|
|
endif
|
|
seti $directory_offset = $directory_offset + $entry_size
|
|
seti $directory_count = $directory_count + 1
|
|
done
|
|
seti $check_byte = scratchpad $directory_offset b
|
|
if $check_byte = 0x46
|
|
seti $working_offset = $directory_offset + 1
|
|
seti $total_regions = scratchpad $working_offset b
|
|
seti $working_offset = $directory_offset + 4
|
|
seti $region_bitmap = scratchpad $working_offset w
|
|
if $directory_id = 0xb
|
|
seti $modb_bitmap_location = $working_offset
|
|
hex
|
|
echo "setting modb=0x" $working_offset
|
|
decimal
|
|
elseif $directory_id = 0x20b
|
|
seti $mod20b_bitmap_location = $working_offset
|
|
hex
|
|
echo "setting mod20b=0x" $working_offset
|
|
decimal
|
|
endif
|
|
hex
|
|
echo "SA regions=0x" $total_regions " region bitmap=0x" $region_bitmap
|
|
decimal
|
|
seti $region_count = 0
|
|
while $region_count < $total_regions
|
|
seti $offset_adustment = $region_count * 8
|
|
seti $working_offset = $directory_offset + $offset_adustment
|
|
seti $working_offset = $working_offset + 6
|
|
seti $region_size = scratchpad $working_offset dw
|
|
seti $working_offset = $working_offset + 4
|
|
seti $region_location = scratchpad $working_offset dw
|
|
hex
|
|
echo "Region=0x" $region_count " Location=0x" $region_location " Size=0x" $region_size
|
|
decimal
|
|
seti $region_count = $region_count + 1
|
|
done
|
|
else
|
|
echo "SA regions not found"
|
|
seti $remainder = $directory_offset - $position
|
|
printscratchpad $directory_offset $remainder
|
|
endif
|
|
endsubroutine
|
|
|
|
|
|
|
|
|
|
|
|
subroutine process_module
|
|
# process the module
|
|
seti $working_offset = $mod_location
|
|
#echo "Header:"
|
|
#printscratchpad $working_offset 4
|
|
seti $working_offset = $mod_location + 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 = $mod_location + 0xa
|
|
seti $mod_length_sectors = scratchpad $working_offset
|
|
seti $working_offset = $mod_location + 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 = $mod_location + 0xc
|
|
seti $checksum = scratchpad $working_offset dw
|
|
#echo "32 bit checksum = 0x" $checksum
|
|
seti $working_offset = $mod_location + 0x10
|
|
#echo "Mod version:"
|
|
#printscratchpad $working_offset 8
|
|
decimal
|
|
|
|
seti $module_size = $mod_size
|
|
seti $calculated_checksum = 0
|
|
seti $count = 0
|
|
while $count < $module_size
|
|
seti $working_offset = $mod_location + $count
|
|
if $working_offset > $search_end
|
|
#echo "end of module is past end of rom"
|
|
break
|
|
endif
|
|
seti $dword = scratchpad $working_offset dw
|
|
seti $remainder = $module_size - $count
|
|
if $remainder < 4
|
|
if $remainder = 3
|
|
seti $dword = $dword & 0xffffff
|
|
elseif $remainder = 2
|
|
seti $dword = $dword & 0xffff
|
|
elseif $remainder = 1
|
|
seti $dword = $dword & 0xff
|
|
endif
|
|
endif
|
|
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 "0x" $mod_location " ModID=0x" $mod_id " size=0x" $mod_size " checksum=0x" $checksum $checkstring
|
|
decimal
|
|
|
|
if $mod_id = 0xb
|
|
gosub patch_rom
|
|
elseif $mod_id = 0x20b
|
|
gosub patch_rom
|
|
endif
|
|
endsubroutine
|
|
|
|
|
|
|
|
|
|
|
|
subroutine patch_rom
|
|
echo "Patching rom"
|
|
if $mod_id = 0xb
|
|
hex
|
|
echo "modb=0x" $modb_bitmap_location
|
|
decimal
|
|
if $modb_bitmap_location > 0
|
|
setscratchpad $modb_bitmap_location
|
|
00
|
|
endscratchpad
|
|
endif
|
|
elseif $mod_id = 0x20b
|
|
hex
|
|
echo "mod20b=0x" $mod20b_bitmap_location
|
|
decimal
|
|
if $mod20b_bitmap_location > 0
|
|
setscratchpad $mod20b_bitmap_location
|
|
00
|
|
endscratchpad
|
|
endif
|
|
endif
|
|
# calculate new checksum and insert it
|
|
seti $calculated_checksum = 0
|
|
seti $count = 0
|
|
while $count < $module_size
|
|
seti $working_offset = $mod_location + $count
|
|
if $working_offset > $search_end
|
|
#echo "end of module is past end of rom"
|
|
break
|
|
endif
|
|
seti $dword = scratchpad $working_offset dw
|
|
seti $remainder = $module_size - $count
|
|
if $remainder < 4
|
|
if $remainder = 3
|
|
seti $dword = $dword & 0xffffff
|
|
elseif $remainder = 2
|
|
seti $dword = $dword & 0xffff
|
|
elseif $remainder = 1
|
|
seti $dword = $dword & 0xff
|
|
endif
|
|
endif
|
|
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
|
|
echo "New Calculated Checksum = 0x" $calculated_checksum
|
|
decimal
|
|
seti $b1 = $calculated_checksum & 0xff
|
|
seti $calculated_checksum = $calculated_checksum > 8
|
|
seti $b2 = $calculated_checksum & 0xff
|
|
seti $calculated_checksum = $calculated_checksum > 8
|
|
seti $b3 = $calculated_checksum & 0xff
|
|
seti $calculated_checksum = $calculated_checksum > 8
|
|
seti $b4 = $calculated_checksum & 0xff
|
|
seti $working_offset = $mod_location + 0x0c
|
|
setscratchpad $working_offset
|
|
$b1 $b2 $b3 $b4
|
|
endscratchpad
|
|
endsubroutine
|
|
|
|
|
|
|
|
|
|
|
|
subroutine save_patched_rom
|
|
sets $new_file = "patched_" $file
|
|
writescratchpad $new_file 0 0 $rom_size
|
|
endsubroutine
|
|
|
|
|
|
|
|
|