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