_save_msx_screen.tcl 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. set_help_text save_msx_screen \
  2. {Lookup the screen mode and save the current screen to a MSX compatible binary
  3. file. This file can for example be loaded in MSX-BASIC using the BLOAD command.
  4. This script was originally developed by NYYRIKKI, see also this forum thread:
  5. http://www.msx.org/forum/msx-talk/general-discussion/taking-sc5-snapshot-games
  6. }
  7. proc save_msx_screen {basename} {
  8. # Gives an error in case of an invalid screen mode.
  9. set mode_num [get_screen_mode_number]
  10. # Read VDP registers (only once)
  11. foreach n {2 3 4 5 6 9 10 11 23} {
  12. set R$n [vdpreg $n]
  13. }
  14. set name_base [expr {($R2 ) * 0x400}]
  15. set name_base_80 [expr {($R2 & 252) * 0x400}]
  16. set name_base_bitmap [expr {($R2 & 96) * 0x400}]
  17. set color_base [expr {($R3 ) * 0x40 + $R10 * 0x4000}]
  18. set color_base_2 [expr {($R3 & 128) * 0x40 + $R10 * 0x4000}]
  19. set pattern_base [expr {($R4 ) * 0x800}]
  20. set pattern_base_2 [expr {($R4 & 60) * 0x800}]
  21. set spr_att_base [expr {($R5 ) * 0x80 + $R11 * 0x8000}]
  22. set spr_att_base_2 [expr {($R5 & 252) * 0x80 + $R11 * 0x8000 - 0x200}]
  23. set spr_pat_base [expr {($R6 ) * 0x800}]
  24. set interlace [expr {(($R9 & 12) == 12) && ($R2 & (($mode_num < 7) ? 16 : 32))}]
  25. set sections [list]
  26. set sections2 [list]
  27. switch [get_screen_mode] {
  28. "TEXT40" {
  29. lappend sections "VRAM" $name_base 0x400 ;# BG Map
  30. lappend sections "VDP palette" 0 0x20 ;# Palette
  31. lappend sections "VRAM" [expr {$name_base + 0x420}] 0x3E0 ;# Fill (BG Map)
  32. lappend sections "VRAM" $pattern_base 0x800 ;# BG Tiles
  33. }
  34. "TEXT80" {
  35. lappend sections "VRAM" $name_base_80 0x800 ;# BG Map
  36. lappend sections "VRAM" $color_base 0x700 ;# Blink
  37. lappend sections "VDP palette" 0 0x20 ;# Palette
  38. lappend sections "VRAM" [expr {$name_base_80 + 0xF20}] 0xE0 ;# Fill (BG Map)
  39. lappend sections "VRAM" $pattern_base 0x800 ;# BG Tiles
  40. }
  41. "1" {
  42. lappend sections "VRAM" $pattern_base 0x1800 ;# BG Tiles
  43. lappend sections "VRAM" $name_base 0x300 ;# BG Map
  44. lappend sections "VRAM" $spr_att_base 0x500 ;# OBJ Attributes
  45. lappend sections "VRAM" $color_base 0x20 ;# BG Colors
  46. lappend sections "VDP palette" 0 0x20 ;# Palette
  47. lappend sections "VRAM" [expr {$color_base + 0x40}] 0x17C0 ;# Fill (BG Colors)
  48. lappend sections "VRAM" $spr_pat_base 0x800 ;# OBJ Tiles
  49. }
  50. "2" {
  51. lappend sections "VRAM" $pattern_base_2 0x1800 ;# BG Tiles
  52. lappend sections "VRAM" $name_base 0x300 ;# BG Map
  53. lappend sections "VRAM" $spr_att_base 0x80 ;# OBJ Attributes
  54. lappend sections "VDP palette" 0 0x20 ;# Palette
  55. lappend sections "VRAM" [expr {$spr_att_base + 0xA0}] 0x460 ;# Fill (OBJ Attributes)
  56. lappend sections "VRAM" $color_base_2 0x1800 ;# BG Colors
  57. lappend sections "VRAM" $spr_pat_base 0x800 ;# OBJ Tiles
  58. }
  59. "3" {
  60. lappend sections "VRAM" $pattern_base 0x800 ;# BG Tiles
  61. lappend sections "VRAM" $name_base 0x1300 ;# BG Map
  62. lappend sections "VRAM" $spr_att_base 0x520 ;# OBJ Attributes
  63. lappend sections "VDP palette" 0 0x20 ;# Palette
  64. lappend sections "VRAM" [expr {$spr_att_base + 0x540}] 0x17C0 ;# Fill (OBJ Attributes)
  65. lappend sections "VRAM" $spr_pat_base 0x800 ;# OBJ Tiles
  66. }
  67. "4" {
  68. lappend sections "VRAM" $pattern_base_2 0x1800 ;# BG Tiles
  69. lappend sections "VRAM" $name_base 0x380 ;# BG Map
  70. lappend sections "VDP palette" 0 0x20 ;# Palette
  71. lappend sections "VRAM" [expr {$name_base + 0x3A0}] 0x60 ;# Fill (BG Map)
  72. lappend sections "VRAM" $spr_att_base_2 0x400 ;# OBJ Attributes
  73. lappend sections "VRAM" $color_base_2 0x1800 ;# BG Colors
  74. lappend sections "VRAM" $spr_pat_base 0x800 ;# OBJ Tiles
  75. }
  76. "5" - "6" {
  77. set lines1 [expr {$R23 > 24 ? 256 - $R23 : 232}] ;# Store 232 lines, even
  78. set lines2 [expr {232 - $lines1}] ;# though only 212 are visible
  79. set base2 [expr {$name_base_bitmap - (0x8000 * $interlace)}]
  80. set base1 [expr {$base2 + $R23 * 128}]
  81. lappend sections "VRAM" $base1 [expr {$lines1 * 128}] ;# Bitmap (part 1)
  82. lappend sections "VRAM" $base2 [expr {$lines2 * 128}] ;# Bitmap (part 2)
  83. lappend sections "VRAM" $spr_att_base_2 0x280 ;# Sprite colors + attributes
  84. lappend sections "VDP palette" 0 0x20 ;# Palette
  85. lappend sections "VRAM" [expr {$name_base_bitmap - (0x8000 * $interlace) + 0x76A0}] 0x160 ;# Fill (Bitmap)
  86. lappend sections "VRAM" $spr_pat_base 0x800 ;# Sprite character patterns
  87. if {$interlace} {
  88. lappend sections2 "VRAM" [expr {$base1 + 0x8000}] [expr {$lines1 * 128}] ;# Bitmap (part 1)
  89. lappend sections2 "VRAM" [expr {$base2 + 0x8000}] [expr {$lines2 * 128}] ;# Bitmap (part 2)
  90. lappend sections2 "VRAM" [expr {$spr_att_base_2 + 0x8000}] 0x280 ;# Sprite colors + attributes
  91. lappend sections2 "VDP palette" 0 0x20 ;# Palette
  92. lappend sections2 "VRAM" [expr {$name_base_bitmap + 0x76A0}] 0x160 ;# Fill (Bitmap)
  93. lappend sections2 "VRAM" [expr {$spr_pat_base + 0x8000}] 0x800 ;# Sprite character patterns
  94. }
  95. }
  96. "7" - "8" - "11" - "12" {
  97. set lines1 [expr {$R23 > 16 ? 256 - $R23 : 240}] ;# Store 240 lines, even
  98. set lines2 [expr {240 - $lines1}] ;# though only 212 are visible
  99. set base2 [expr {($name_base_bitmap * 2) & 0x10000 - (0x10000 * $interlace)}]
  100. set base1 [expr {$base2 + $R23 * 256}]
  101. lappend sections "VRAM" $base1 [expr {$lines1 * 256}] ;# Bitmap (part 1)
  102. lappend sections "VRAM" $base2 [expr {$lines2 * 256}] ;# Bitmap (part 2)
  103. lappend sections "VRAM" $spr_pat_base 0x800 ;# Sprite character patterns
  104. lappend sections "VRAM" $spr_att_base_2 0x280 ;# Sprite colors + attributes
  105. lappend sections "VDP palette" 0 0x20 ;# Palette
  106. if {$interlace} {
  107. lappend sections2 "VRAM" [expr {$base1 + 0x10000}] [expr {$lines1 * 256}] ;# Bitmap (part 1)
  108. lappend sections2 "VRAM" [expr {$base2 + 0x10000}] [expr {$lines2 * 256}] ;# Bitmap (part 2)
  109. lappend sections2 "VRAM" [expr {$spr_pat_base + 0x10000}] 0x800 ;# Sprite character patterns
  110. lappend sections2 "VRAM" [expr {$spr_att_base_2 + 0x10000}] 0x280 ;# Sprite colors + attributes
  111. lappend sections2 "VDP palette" 0 0x20 ;# Palette
  112. }
  113. }}
  114. set directory [file normalize $::env(OPENMSX_USER_DATA)/../screenshots]
  115. set result ""
  116. foreach {ext sec} [list ".SC" $sections ".S1" $sections2] {
  117. if {[llength $sec] == 0} break
  118. # Open file with correct extension
  119. set fname [file join $directory [format "%s%s%X" $basename $ext $mode_num]]
  120. set out [open $fname w]
  121. fconfigure $out -translation binary
  122. # write header
  123. set end_addr -1
  124. foreach {type addr size} $sec {
  125. incr end_addr $size
  126. }
  127. set header [list 0xFE 0 0 [expr {$end_addr & 255}] [expr {$end_addr / 256}] 0 0]
  128. puts -nonewline $out [binary format c* $header]
  129. # write data sections
  130. foreach {type addr size} $sec {
  131. puts -nonewline $out [debug read_block $type $addr $size]
  132. }
  133. close $out
  134. append result "Screen written to $fname\n"
  135. }
  136. return $result
  137. }