_vdrive.tcl 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. set_help_text vdrive \
  2. {v-drive functionality of blueMSX implemented in a Tcl script for openMSX
  3. version 1.0
  4. What does it do:
  5. It is a simple Tcl script that bound to a hotkey (f.i. F9+ALT) allows
  6. users to swap disks without using the commandconsole or Catapult for
  7. file selection. This is especially useful for games and demos that
  8. span over multiple disks.
  9. Preparations:
  10. 1. If you have software that spans multiple disks, you have to name them
  11. according to the scheme: name+digit+extension for example [metal1.dsk,
  12. metal2.dsk, metal3.dsk]
  13. Of course they may all be compressed with gzip, so you'll end up with
  14. [metal1.dsk.gz, metal2.dsk.gz, metal3.dsk.gz].
  15. The script recognizes 'dsk', 'di1', 'di2', 'xsa' and 'dmk' extensions,
  16. with an optional '.gz' or '.zip' suffix.
  17. 2. bind the vdrive script to a hotkey, for instance type in the console:
  18. bind ALT+F9 "vdrive diska"
  19. bind ALT+F10 "vdrive diskb"
  20. vdrive will default to 'diska' when no drive parameter is specified.
  21. Note: the two bind commands above are already the default key bindings;
  22. you only need to execute them if you want a different key binding.
  23. Using:
  24. While emulating an MSX, and the sofware asks for the next disk, simply
  25. press the hot-key. The script will select the next disk in the sequence.
  26. If the last disk is reached, the script will select the first disk
  27. again. So you actually are cycling through the entire disk set as shown
  28. in the diagram below
  29. _"disk1.dsk" => ALT+F9 => "disk2.dsk" => ALT+F9 => "disk3.dsk" _
  30. | |
  31. <= <= <= <= <= <= <= ALT+F9 <= <= <= <= <= <= <= <= <= <= <= <=
  32. credits:
  33. original alt+f9 v-DRIVE idea by the blueMSX crew.
  34. copyright 2005 David Heremans
  35. }
  36. proc vdrive {{diskdrive "diska"} {step 1}} {
  37. # Get current disk
  38. if {[catch {set cmd [$diskdrive]}]} {error "No such drive: $diskdrive"}
  39. # Skip for empty drive or 'special' disk
  40. set options [lindex $cmd 2]
  41. if {"empty" in $options} {
  42. error "No disk in drive: $diskdrive"
  43. } elseif {"ramdsk" in $options} {
  44. error "Vdrive not possible on ramdsk"
  45. } elseif {"dirasdisk" in $options} {
  46. error "Vdrive not possible on DirAsDisk"
  47. }
  48. # Remove (dsk|di1|di2|xsa|dmk)(.gz)? extention
  49. set base [lindex $cmd 1]
  50. set ext ""
  51. set tmp [file extension $base]
  52. foreach i {".gz" ".zip"} {
  53. if {[string equal -nocase $i $tmp]} {
  54. set ext $tmp
  55. set base [file rootname $base]
  56. break
  57. }
  58. }
  59. set tmp [file extension $base]
  60. foreach i {".dsk" ".di1" ".di2" ".xsa" ".dmk"} {
  61. if {[string equal -nocase $i $tmp]} {
  62. set ext ${tmp}${ext}
  63. set base [file rootname $base]
  64. break
  65. }
  66. }
  67. # Split on trailing digits
  68. if {![regexp -indices {[0-9]+$} $base match]} {
  69. error "Name doesn't end in a number"
  70. }
  71. set i [lindex $match 0]
  72. set num [string range $base $i end]
  73. set base [string range $base 0 $i-1]
  74. # Calculate range (number of digits)
  75. # Trim leading zeros (avoid interpreting the value as octal)
  76. set digits [string length $num]
  77. set range [expr {int(pow(10, $digits))}]
  78. set num [string trimleft $num 0]
  79. set fmt "%s%0${digits}d%s"
  80. # Increase (decrease) number until new file is found.
  81. set orig $num
  82. while 1 {
  83. set num [expr {($num + $step) % $range}]
  84. if {$num == $orig} {
  85. # We're back at the original. Explicitly test for this
  86. # because the original file might not exist anymore.
  87. return
  88. }
  89. # Construct new filename (including leading zeros)
  90. set newfile [format $fmt $base $num $ext]
  91. if {[file exists $newfile]} {
  92. # New file exists, insert in the disk drive
  93. diska $newfile
  94. return "New diskimage: $newfile"
  95. }
  96. }
  97. }