| 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 |
|
| 5 |
This script was originally developed by NYYRIKKI, see also this forum thread: |
| 6 |
http://www.msx.org/forum/msx-talk/general-discussion/taking-sc5-snapshot-games |
| 7 |
} |
| 8 |
|
| 9 |
proc save_msx_screen {basename} { |
| 10 |
|
| 11 |
set mode_num [get_screen_mode_number] |
| 12 |
|
| 13 |
|
| 14 |
foreach n {2 3 4 5 6 9 10 11 23} { |
| 15 |
set R$n [vdpreg $n] |
| 16 |
} |
| 17 |
|
| 18 |
set name_base [expr {($R2 ) * 0x400}] |
| 19 |
set name_base_80 [expr {($R2 & 252) * 0x400}] |
| 20 |
set name_base_bitmap [expr {($R2 & 96) * 0x400}] |
| 21 |
set color_base [expr {($R3 ) * 0x40 + $R10 * 0x4000}] |
| 22 |
set color_base_2 [expr {($R3 & 128) * 0x40 + $R10 * 0x4000}] |
| 23 |
set pattern_base [expr {($R4 ) * 0x800}] |
| 24 |
set pattern_base_2 [expr {($R4 & 60) * 0x800}] |
| 25 |
set spr_att_base [expr {($R5 ) * 0x80 + $R11 * 0x8000}] |
| 26 |
set spr_att_base_2 [expr {($R5 & 252) * 0x80 + $R11 * 0x8000 - 0x200}] |
| 27 |
set spr_pat_base [expr {($R6 ) * 0x800}] |
| 28 |
set interlace [expr {(($R9 & 12) == 12) && ($R2 & (($mode_num < 7) ? 16 : 32))}] |
| 29 |
|
| 30 |
set sections [list] |
| 31 |
set sections2 [list] |
| 32 |
switch [get_screen_mode] { |
| 33 |
"TEXT40" { |
| 34 |
lappend sections "VRAM" $name_base 0x400 ; |
| 35 |
lappend sections "VDP palette" 0 0x20 ; |
| 36 |
lappend sections "VRAM" [expr {$name_base + 0x420}] 0x3E0 ; |
| 37 |
lappend sections "VRAM" $pattern_base 0x800 ; |
| 38 |
} |
| 39 |
"TEXT80" { |
| 40 |
lappend sections "VRAM" $name_base_80 0x800 ; |
| 41 |
lappend sections "VRAM" $color_base 0x700 ; |
| 42 |
lappend sections "VDP palette" 0 0x20 ; |
| 43 |
lappend sections "VRAM" [expr {$name_base_80 + 0xF20}] 0xE0 ; |
| 44 |
lappend sections "VRAM" $pattern_base 0x800 ; |
| 45 |
} |
| 46 |
"1" { |
| 47 |
lappend sections "VRAM" $pattern_base 0x1800 ; |
| 48 |
lappend sections "VRAM" $name_base 0x300 ; |
| 49 |
lappend sections "VRAM" $spr_att_base 0x500 ; |
| 50 |
lappend sections "VRAM" $color_base 0x20 ; |
| 51 |
lappend sections "VDP palette" 0 0x20 ; |
| 52 |
lappend sections "VRAM" [expr {$color_base + 0x40}] 0x17C0 ; |
| 53 |
lappend sections "VRAM" $spr_pat_base 0x800 ; |
| 54 |
} |
| 55 |
"2" { |
| 56 |
lappend sections "VRAM" $pattern_base_2 0x1800 ; |
| 57 |
lappend sections "VRAM" $name_base 0x300 ; |
| 58 |
lappend sections "VRAM" $spr_att_base 0x80 ; |
| 59 |
lappend sections "VDP palette" 0 0x20 ; |
| 60 |
lappend sections "VRAM" [expr {$spr_att_base + 0xA0}] 0x460 ; |
| 61 |
lappend sections "VRAM" $color_base_2 0x1800 ; |
| 62 |
lappend sections "VRAM" $spr_pat_base 0x800 ; |
| 63 |
} |
| 64 |
"3" { |
| 65 |
lappend sections "VRAM" $pattern_base 0x800 ; |
| 66 |
lappend sections "VRAM" $name_base 0x1300 ; |
| 67 |
lappend sections "VRAM" $spr_att_base 0x520 ; |
| 68 |
lappend sections "VDP palette" 0 0x20 ; |
| 69 |
lappend sections "VRAM" [expr {$spr_att_base + 0x540}] 0x17C0 ; |
| 70 |
lappend sections "VRAM" $spr_pat_base 0x800 ; |
| 71 |
} |
| 72 |
"4" { |
| 73 |
lappend sections "VRAM" $pattern_base_2 0x1800 ; |
| 74 |
lappend sections "VRAM" $name_base 0x380 ; |
| 75 |
lappend sections "VDP palette" 0 0x20 ; |
| 76 |
lappend sections "VRAM" [expr {$name_base + 0x3A0}] 0x60 ; |
| 77 |
lappend sections "VRAM" $spr_att_base_2 0x400 ; |
| 78 |
lappend sections "VRAM" $color_base_2 0x1800 ; |
| 79 |
lappend sections "VRAM" $spr_pat_base 0x800 ; |
| 80 |
} |
| 81 |
"5" - "6" { |
| 82 |
set lines1 [expr {$R23 > 24 ? 256 - $R23 : 232}] ; |
| 83 |
set lines2 [expr {232 - $lines1}] ; |
| 84 |
set base2 [expr {$name_base_bitmap ^ (0x8000 * $interlace)}] |
| 85 |
set base1 [expr {$base2 + $R23 * 128}] |
| 86 |
lappend sections "VRAM" $base1 [expr {$lines1 * 128}] ; |
| 87 |
lappend sections "VRAM" $base2 [expr {$lines2 * 128}] ; |
| 88 |
lappend sections "VRAM" $spr_att_base_2 0x280 ; |
| 89 |
lappend sections "VDP palette" 0 0x20 ; |
| 90 |
lappend sections "VRAM" [expr {$name_base_bitmap ^ (0x8000 * $interlace) + 0x76A0}] 0x160 ; |
| 91 |
lappend sections "VRAM" $spr_pat_base 0x800 ; |
| 92 |
if {$interlace} { |
| 93 |
lappend sections2 "VRAM" [expr {$base1 ^ 0x8000}] [expr {$lines1 * 128}] ; |
| 94 |
lappend sections2 "VRAM" [expr {$base2 ^ 0x8000}] [expr {$lines2 * 128}] ; |
| 95 |
lappend sections2 "VRAM" [expr {$spr_att_base_2 ^ 0x8000}] 0x280 ; |
| 96 |
lappend sections2 "VDP palette" 0 0x20 ; |
| 97 |
lappend sections2 "VRAM" [expr {$name_base_bitmap + 0x76A0}] 0x160 ; |
| 98 |
lappend sections2 "VRAM" [expr {$spr_pat_base ^ 0x8000}] 0x800 ; |
| 99 |
} |
| 100 |
} |
| 101 |
"7" - "8" - "11" - "12" { |
| 102 |
set lines1 [expr {$R23 > 16 ? 256 - $R23 : 240}] ; |
| 103 |
set lines2 [expr {240 - $lines1}] ; |
| 104 |
set base2 [expr {($name_base_bitmap * 2) & 0x10000 - (0x10000 * $interlace)}] |
| 105 |
set base1 [expr {$base2 + $R23 * 256}] |
| 106 |
lappend sections "VRAM" $base1 [expr {$lines1 * 256}] ; |
| 107 |
lappend sections "VRAM" $base2 [expr {$lines2 * 256}] ; |
| 108 |
lappend sections "VRAM" $spr_pat_base 0x800 ; |
| 109 |
lappend sections "VRAM" $spr_att_base_2 0x280 ; |
| 110 |
lappend sections "VDP palette" 0 0x20 ; |
| 111 |
if {$interlace} { |
| 112 |
lappend sections2 "VRAM" [expr {$base1 ^ 0x10000}] [expr {$lines1 * 256}] ; |
| 113 |
lappend sections2 "VRAM" [expr {$base2 ^ 0x10000}] [expr {$lines2 * 256}] ; |
| 114 |
lappend sections2 "VRAM" [expr {$spr_pat_base ^ 0x10000}] 0x800 ; |
| 115 |
lappend sections2 "VRAM" [expr {$spr_att_base_2 ^ 0x10000}] 0x280 ; |
| 116 |
lappend sections2 "VDP palette" 0 0x20 ; |
| 117 |
} |
| 118 |
}} |
| 119 |
|
| 120 |
set directory [file normalize $::env(OPENMSX_USER_DATA)/../screenshots] |
| 121 |
|
| 122 |
set result "" |
| 123 |
foreach {ext sec} [list ".SC" $sections ".S1" $sections2] { |
| 124 |
if {[llength $sec] == 0} break |
| 125 |
|
| 126 |
|
| 127 |
set fname [file join $directory [format "%s%s%X" $basename $ext $mode_num]] |
| 128 |
set out [open $fname w] |
| 129 |
fconfigure $out -translation binary |
| 130 |
|
| 131 |
|
| 132 |
set end_addr -1 |
| 133 |
foreach {type addr size} $sec { |
| 134 |
incr end_addr $size |
| 135 |
} |
| 136 |
set header [list 0xFE 0 0 [expr {$end_addr & 255}] [expr {$end_addr / 256}] 0 0] |
| 137 |
puts -nonewline $out [binary format c* $header] |
| 138 |
|
| 139 |
|
| 140 |
foreach {type addr size} $sec { |
| 141 |
puts -nonewline $out [debug read_block $type $addr $size] |
| 142 |
} |
| 143 |
close $out |
| 144 |
|
| 145 |
append result "Screen written to $fname\n" |
| 146 |
} |
| 147 |
return $result |
| 148 |
} |