bin/dsktool.rb in dsktool-0.2.1 vs bin/dsktool.rb in dsktool-0.4.1

- old
+ new

@@ -1,150 +1,251 @@ -#!/usr/bin/ruby -# dsktool.rb -# -# == Synopsis -# -# Manipulate DSK format files (as used by Apple 2 emulators) -# -# == Usage -# -# dsktool.rb [switches] <filename.dsk> -# -c | --catalog display catalog -# -e | --extract FILENAME extract file by name (either to stdout, -# or file specified by --output) -# -h | --help display this message -# -d | --dump FILENAME hex dump -# -l | --list FILENAME monitor style listing (disassembles 65C02 opcodes) -# -o | --output FILENAME specify name to save extracted file as -# -r | --raw don't convert basic files to ASCII -# -x | --explode extract all files -# -v | --version show version number -# -# Currently only works with DOS 3.3 and NADOL format DSK images -# Will uncompress gzipped files (with extension .gz) -# input files can be URLs -# -# examples: -# dsktool.rb -c DOS3MASTR.dsk.gz -# dsktool.rb -l FID DOS3MASTR.dsk -# dsktool.rb --list fid -o fid.lst DOS3MASTR.dsk -# dsktool.rb --extract "COLOR DEMOSOFT" DOS3MASTR.dsk -# dsktool.rb -e HELLO -o HELLO.bas DOS3MASTR.dsk -# dsktool.rb -x DOS3MASTR.dsk.gz -# dsktool.rb -x DOS3MASTR.dsk.gz -o /tmp/DOS3MASTR/ -# dsktool.rb -c http://jamtronix.com/dsks/apshai.dsk.gz +#!/usr/bin/env ruby -DSKTOOL_VERSION="0.2.1" - -#make sure the relevant folder with our libraries is in the require path -lib_path=File.expand_path(File.dirname(__FILE__)+"//..//lib") -$:.unshift(lib_path) unless $:.include?(lib_path) - -require 'optparse' -require 'rdoc_patch' #RDoc::usage patched to work under gem executables - -catalog=false -explode=false -output_filename=nil -extract_filename=nil -extract_mode=:default -explode_directory=nil -opts=OptionParser.new -opts.on("-h","--help") {RDoc::usage_from_file(__FILE__)} -opts.on("-v","--version") do - puts File.basename($0)+" "+DSKTOOL_VERSION - exit -end -opts.on("-r","--") {extract_mode=:raw} -opts.on("-c","--catalog") {catalog=true} -opts.on("-x","--explode") {explode=true} +# dsktool.rb +# +# == Synopsis +# +# Manipulate DSK format files (as used by Apple 2 emulators) +# +# == Usage +# +# dsktool.rb [switches] <filename.dsk> +# -a | --add FILENAME (*) add file +# -b | --base BASE use BASE as address to load Binary File +# this will add 2 bytes to the start of file +# BASE should be a hex number +# (can be prefixed with $, 0x, or nothing) +# -B | --bootcode FILENAME FILENAME gets written to track 0, sector 0 +# FILENAME should be compiled to run at $0801 +# FILENAME can be up to 4Kb in size. +# -c | --catalog display catalog +# -d | --dump FILENAME hex dump +# -D | --diskdump hex dump of entire disk +# --delete FILENAME (*) delete named file +# -e | --extract FILENAME extract file by name (either to stdout, +# or file specified by --output) +# -h | --help display this message +# -I | --init FILESYSTEM initialise the disk with the specified filesytem +# DSK will be created if it doesn't exist. +# FILESYSTEM can be : prodos,dos33,nadol,pascal,none +# -l | --list FILENAME monitor style listing (disassembles 65C02 opcodes) +# -o | --output FILENAME specify name to save extracted file as +# -r | --raw don't convert files to ASCII +# -S | --showtrace show full stack trace on any error +# -t | --filetype FILETYPE file type for file being added. +# Can be a single letter (A/I/B/T) or number. +# Default for DOS 3.3 is 0x00 (Text) +# -T | --tokenise (*) tokenise input file before adding +# -v | --version show version number +# -x | --explode extract all files +# +# (*) options marked with an asterisk are only available for +# file systems that have READ/WRITE support. +# +# Currently supported filesystems: +# Apple Pascal (read only) +# DOS 3.3 (READ/WRITE) +# NADOL (READ/WRITE) +# ProDOS 8 (read only) +# +# Supports 16 sector DSK images +# files with extension .gz will be read & written using gzip +# input files can be URLs +# +# examples: +# dsktool.rb -c http://jamtronix.com/dsks/apshai.dsk.gz +# dsktool.rb --list fid -o fid.lst DOS3MASTR.dsk +# dsktool.rb --extract "COLOR DEMOSOFT" DOS3MASTR.dsk +# dsktool.rb -e HELLO -o HELLO.bas DOS3MASTR.dsk +# dsktool.rb -x DOS3MASTR.dsk.gz -o /tmp/DOS3MASTR/ +# dsktool.rb --add STARTUP -T nadol.po +# dsktool.rb --add c:\src\dosdemo\a.out -t B -b $2000 dosdemo.dsk +# dsktool.rb --init dos33 new_dos_disk.dsk.gz +# dsktool.rb --I none -B /tmp/a.out demo1.dsk + + +DSKTOOL_VERSION="0.4.1" + +#make sure the relevant folder with our libraries is in the require path +lib_path=File.expand_path(File.dirname(__FILE__)+"//..//lib") +$:.unshift(lib_path) unless $:.include?(lib_path) +require 'rubygems' +require 'optparse' +require 'rdoc_patch' #RDoc::usage patched to work under gem executables + +catalog=false +explode=false +diskdump=false +show_trace=false +add_filename=nil +output_filename=nil +extract_filename=nil +delete_filename=nil +add_file_options={} +init_filesystem=nil +boot_filename=nil + +extract_mode=:default +explode_directory=nil +opts=OptionParser.new +opts.on("-h","--help") {RDoc::usage_from_file(__FILE__)} +opts.on("-v","--version") do + puts File.basename($0)+" "+DSKTOOL_VERSION + exit +end +opts.on("-r","--raw") {extract_mode=:raw} +opts.on("-c","--catalog") {catalog=true} +opts.on("-D","--diskdump") {diskdump=true} +opts.on("-x","--explode") {explode=true} opts.on("-l","--list FILENAME",String) do |val| extract_filename=val.upcase extract_mode=:list end + +opts.on("-S","--showtrace") {show_trace=true} + opts.on("-d","--dump FILENAME",String) do |val| extract_filename=val.upcase extract_mode=:hex -end -opts.on("-e","--extract FILENAME",String) {|val| extract_filename=val.upcase} -opts.on("-o","--output FILENAME",String) {|val| output_filename=val} -filename=opts.parse(ARGV)[0] rescue RDoc::usage_from_file(__FILE__,'Usage') -RDoc::usage_from_file(__FILE__,'Usage') if (filename.nil?) - - -require 'DSK' -dsk=DSK.read(filename) -output_file= case - when (output_filename.nil?) || (explode) then STDOUT - else File.open(output_filename,"wb") -end - -if(catalog) then - if (dsk.respond_to?(:dump_catalog)) then - dsk.dump_catalog - else - puts "#{filename} does not have a recognised file system" - end -end - -if(explode) then - output_dir=output_filename.nil??File.basename(filename,".*"):output_filename - if !(File.exists?(output_dir)) then - Dir.mkdir(output_dir) - end - - dsk.files.each_value do |f| - if (extract_mode==:raw) then - output_filename=output_dir+"/"+f.filename+".raw" - File.open(output_filename,"wb") <<f.contents - else - output_filename=output_dir+"/"+f.filename+f.file_extension - File.open(output_filename,"wb") <<f - end - end -end - - -if (!extract_filename.nil?) then - file=dsk.files[extract_filename] - if file.nil? then - puts "'#{extract_filename}' not found in #{filename}" - else - output_file<< case extract_mode - when :raw then file.contents - when :hex then file.hex_dump - when :list then - if file.respond_to?(:disassembly) - file.disassembly - else - puts "'#{extract_filename}' is not a binary file" - exit - end - else file.to_s - end - end -end - -# == Author -# Jonno Downes (jonno@jamtronix.com) -# -# == Copyright -# Copyright (c) 2007 Jonno Downes (jonno@jamtronix.com) -# -#Permission is hereby granted, free of charge, to any person obtaining -#a copy of this software and associated documentation files (the -#"Software"), to deal in the Software without restriction, including -#without limitation the rights to use, copy, modify, merge, publish, -#distribute, sublicense, and/or sell copies of the Software, and to -#permit persons to whom the Software is furnished to do so, subject to -#the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +end +opts.on("-e","--extract FILENAME",String) {|val| extract_filename=val.upcase} +opts.on("-o","--output FILENAME",String) {|val| output_filename=val} +opts.on("-a","--add FILENAME",String) {|val| add_filename=val} +opts.on("-I","--init FILESYSTEM",String) {|val| init_filesystem=val} +opts.on("-B","--bootcode FILENAME",String) {|val| boot_filename=val} +opts.on("-t","--filetype FILETYPE",String) {|val| add_file_options[:filetype]=val} +opts.on("-T","--tokenise") {add_file_options[:tokenise]=true} +opts.on("-delete","--delete FILENAME",String) {|val| delete_filename=val} +opts.on("-b","--base BASE",String) {|val| add_file_options[:base]=val} + +filename=opts.parse(ARGV)[0] rescue RDoc::usage_from_file(__FILE__,'Usage') +RDoc::usage_from_file(__FILE__,'Usage') if (filename.nil?) + + +require 'DSK' + +begin #to wrap a rescue clause + + begin + + if !init_filesystem.nil? then + dsk=DSK.create_new(:"#{init_filesystem}") + dsk.save_as(filename) + end + + + dsk=DSK.read(filename) + rescue + #if we run dsktool.rb in a batch or shell file iterating over a bunch of dsk files, we may not know what file + #has the error + STDERR << "error while parsing #{filename}\n" + raise + end + + output_file= case + when (output_filename.nil?) || (explode) then STDOUT + else File.open(output_filename,"wb") + end + + puts "#{filename}\nsector order:\t#{dsk.sector_order}\nfilesystem:\t#{dsk.file_system}" + if (dsk.respond_to?(:volume_name)) then + puts "volume name:\t#{dsk.volume_name}" + end + if (diskdump) then + puts dsk.hex_dump + end + + if !boot_filename.nil? then + dsk.set_boot_track(File.open(boot_filename,"rb").read) + dsk.save_as(filename) + end + + if (!delete_filename.nil?) then + if dsk.files[delete_filename].nil? then + puts "#{delete_filename.upcase} not found in #{filename}" + else + puts "deleting #{delete_filename}" + dsk.delete_file(delete_filename) + dsk.save_as(filename) + end + end + + if (!add_filename.nil?) then + filecontents=File.open(add_filename,"rb").read + new_file=dsk.make_file(File.basename(add_filename).upcase,filecontents,add_file_options) + dsk.add_file(new_file) + dsk.save_as(filename) + end + + if(catalog) then + if (dsk.respond_to?(:dump_catalog)) then + puts dsk.dump_catalog + else + puts "#{filename} does not have a recognised file system" + end + end + + if(explode) then + output_dir=output_filename.nil??File.basename(filename,".*"):output_filename + if !(File.exists?(output_dir)) then + Dir.mkdir(output_dir) + end + + dsk.files.each_value do |f| + if (extract_mode==:raw) then + output_filename=output_dir+"/"+f.filename+".raw" + File.open(output_filename,"wb") <<f.contents + else + output_filename=output_dir+"/"+f.filename+f.file_extension + File.open(output_filename,"wb") <<f + end + end + end + + + if (!extract_filename.nil?) then + file=dsk.files[extract_filename] + if file.nil? then + puts "'#{extract_filename}' not found in #{filename}" + else + output_file<< case extract_mode + when :raw then file.contents + when :hex then file.hex_dump + when :list then + if file.respond_to?(:disassembly) + file.disassembly + else + puts "'#{extract_filename}' is not a binary file" + exit + end + else file.to_s + end + end + end +rescue + puts $! + raise if show_trace +end +# == Author +# Jonno Downes (jonno@jamtronix.com) +# +# == Copyright +# Copyright (c) 2007 Jonno Downes (jonno@jamtronix.com) +# +#Permission is hereby granted, free of charge, to any person obtaining +#a copy of this software and associated documentation files (the +#"Software"), to deal in the Software without restriction, including +#without limitation the rights to use, copy, modify, merge, publish, +#distribute, sublicense, and/or sell copies of the Software, and to +#permit persons to whom the Software is furnished to do so, subject to +#the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.