#!/bin/env ruby # ripxplore.rb # # == Synopsis # # Manipulate file system images as used by vintage computer emulators# # # == Usage # # ripxplore.rb [switches] # -a | --add FILENAME (*) add file # -c | --catalog display catalog # -d | --dump FILENAME hex dump # -D | --diskdump hex dump of entire disk # -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 : dos33 # -l | --list FILENAME BASIC files are listed, binary files are disassembled # -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. # -V | --verbose verbose mode # -v | --version show version number # # files with extension .gz will be read & written using gzip # input files can be URLs # # Currently supported image formats: # DSK images as used by Apple 2 emulators # DSK images as used by Tandy CoCo emulators # DSK images as used by TI 99/4a emulators # JV1 DSK images as used by TRS-80 emulators # D64 images as used by C64 emulators # ATR images as used by Atari 400/800 emulators # # Currently supported filesystems: # Atari DOS (read only) # Apple Pascal (read only) # Apple CP/M (read only) # Apple DOS 3.3 (READ/WRITE) # NADOL (read only) # ProDOS 8 (read only) # CBM DOS 2.6 (read only) # TRS-DOS (read only) #pull in the RipXplore lib - we need to give the specific path to it since otherwise on case insensitive OSes (e.g. windows) this file #will get pulled in instead require File.expand_path(File.dirname(__FILE__)+"//..//lib")+'//LibRipXplore' #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 def show_usage RDoc::usage_from_file(__FILE__,'Usage') end catalog=false diskdump=false show_trace=false output_filename=nil extract_filename=nil debug_logging=false add_filename=nil add_file_options={} init_filesystem=nil extract_mode=:default opts=OptionParser.new opts.on("-h","--help") {show_usage} opts.on("-v","--version") do puts File.basename($0)+" "+RipXplore::VERSION exit end opts.on("-r","--raw") {extract_mode=:raw} opts.on("-c","--catalog") {catalog=true} opts.on("-D","--diskdump") {diskdump=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} opts.on("-t","--filetype FILETYPE",String) {|val| add_file_options[:filetype]=val} opts.on("-V","--verbose") {debug_logging=true} opts.on("-I","--init FILESYSTEM",String) {|val| init_filesystem=val} opts.on("-a","--add FILENAME",String) {|val| add_filename=val} filename=opts.parse(ARGV)[0] rescue show_usage show_usage if (filename.nil?) RipXploreLog.debug_logging if debug_logging begin #to wrap a rescue clause fsimage=nil if !init_filesystem.nil? then fsimage=RipXplore.create_new(:"#{init_filesystem}") fsimage.save_as(filename) else begin fsimage=RipXplore.best_fit_from_filename(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 end output_file= case when (output_filename.nil?) then STDOUT else File.open(output_filename,"wb") end if (diskdump) then puts fsimage.to_hex_dump end if(catalog) then [:host_system,:image_format,:file_system].each do |att| if (fsimage.respond_to?(att)) then puts "#{att.to_s}:\t#{fsimage.send(att)}" end end puts fsimage.catalog end if (!add_filename.nil?) then filecontents=File.open(add_filename,"rb").read new_file=fsimage.add_file(add_file_options[:filetype].to_sym,File.basename(add_filename).upcase,filecontents) fsimage.save_as(filename) end if (!extract_filename.nil?) then file=fsimage.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.to_hex_dump when :ascii then file.to_ascii when :list then if file.respond_to?(:to_listing) file.to_listing elsif file.respond_to?(:to_disassembly) file.to_disassembly else puts "'#{extract_filename}' can't be listed" exit end else if file.respond_to?(:to_text) file.to_text else file.contents end end end end rescue puts $! raise if show_trace end # == Author # Jonno Downes (jonno@jamtronix.com) # # == Copyright # Copyright (c) 2008,2009 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.