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