Taking SC5 snapshot of games

Page 5/5
1 | 2 | 3 | 4 |

By wouter_

Champion (418)

wouter_'s picture

04-01-2014, 21:57

sd_snatcher wrote:

I've found another bug in save_msx_screen. It ignores the horizontal scroll register ...

Thanks for your feedback.
That's correct. And the same for vertical scroll, and for the border color, and probably some other VDP registers as well. Though the 'screen shot' created via this script only contains VRAM data. So it's not possible to include the state of all VDP registers.

Though (I think) you're suggesting we should alter the dumped VRAM so that, when loading the dump (without changing VDP registers), the result should be visually the same as the current image. Is that correct? For vertical scroll this might be possible. But for horizontal scroll in screen 11/12 this is only possible for integer multiples of 4 pixels.

But I consider both horizontal and vertical scroll to be outside the scope of this simple script. You can always use the real 'screenshot' command to get an actual screenshot (.png image) or the 'vramdump' command (possibly in combination with a VDP register and palette dump) if you want a 'msx screen shot' of a more complex msx screen (meaning screen with non-default VDP register settings).

That said, if someone is willing to do the effort to extend the script, I'll probably include it. Though personally I think this is very low priority.

By sd_snatcher

Prophet (3068)

sd_snatcher's picture

05-01-2014, 20:32

Ok, I implemented the vertical scroll fix, which was the worst problem because data outside the screen didn't end up in the save file, making any post correction impossible.

This is the part of the _save_msx_screen.tcl that was changed:

	"5" - "6" {

		set name_base_bitmap_window1 [expr {$name_base_bitmap +[vdpreg 23] *128  }]
		set name_base_bitmap_size1 [expr { 0x7400 -([vdpreg 23]>44? ([vdpreg 23] -24) *128: 0 ) }]
		set name_base_bitmap_window2 $name_base_bitmap
		set name_base_bitmap_size2 [expr { [vdpreg 23]>44? ([vdpreg 23] -24) *128: 0 }]
#		lappend sections "VRAM" $name_base_bitmap 0x7400                ;# Bitmap

		lappend sections "VRAM" $name_base_bitmap_window1 $name_base_bitmap_size1      ;# Bitmap
		lappend sections "VRAM" $name_base_bitmap_window2 $name_base_bitmap_size2      ;# Bitmap
		puts $name_base_bitmap_window1,$name_base_bitmap_size1
		puts $name_base_bitmap_window2,$name_base_bitmap_size2
		puts [expr {$name_base_bitmap_size1 + $name_base_bitmap_size2 }]


		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 + 0x76A0}] 0x160 ;# Fill (Bitmap)
		lappend sections "VRAM" $spr_pat_base 0x800                     ;# Sprite character patterns
	}
	"7" - "8" - "11" - "12" {
		set name_base_bitmap_window1 [expr {$name_base_bitmap +[vdpreg 23] *256  }]
		set name_base_bitmap_size1 [expr { 0xF000 -([vdpreg 23]>44? ([vdpreg 23] -16) *256: 0 ) }]
		set name_base_bitmap_window2 $name_base_bitmap
		set name_base_bitmap_size2 [expr { [vdpreg 23]>44? ([vdpreg 23] -16) *256: 0 }]

#		lappend sections "VRAM" $name_base_bitmap 0xF000            ;# Bitmap
		lappend sections "VRAM" $name_base_bitmap_window1 $name_base_bitmap_size1      ;# Bitmap
		lappend sections "VRAM" $name_base_bitmap_window2 $name_base_bitmap_size2      ;# Bitmap
		puts $name_base_bitmap_window1,$name_base_bitmap_size1
		puts $name_base_bitmap_window2,$name_base_bitmap_size2
		puts [expr {$name_base_bitmap_size1 + $name_base_bitmap_size2 }]

		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
	}}

The horizontal scroll issue can be post-fixed using the following MSX-BASIC program:

10 'save"swapimg.bas":' By SD-Snatcher Alpha
20 'Used to swap the two sides of a screen dump to fix the horizontal scroll shift
30 'Controls:
40 ' LEFT/RIGHT: Set the swap point
50 ' UP/DOWN: Set the upper limit
60 ' CTRL+UP/DOWN: Set the lower limit
70 ' SHIFT: Speed up
80 ' SPACE: Swap the selected sides
90 ' ESC: Exit
100 ' RETURN: Save & exit
110 '
120 DEFINT A-Z
130 CLS:FILES"*.sc?":PRINT
140 INPUT"File Name: ";N$
150 SCR=VAL("&H"+RIGHT$(N$,1))
160 COLOR,,0:SCREEN SCR,2
170 LC=15:IF SCR=8 OR SCR>10 THEN LC=255:'Set line color
180 XSTP=1:XLIM=255:IF (SCR=6 OR SCR=7) THEN XSTP=2:XLIM=511 ELSE IF SCR>9 THEN XSTP=4:' Set step and x max for that screen
190 IE=&H7FFF:IF SCR>6 THEN IE=&HFA9F
200 BLOAD N$,S:COLOR=RESTORE
210 X=127:Y1=0:Y2=211
220 'Choose swap point
230 TIME=0:LINE(X,Y1)-(X,Y2),LC,,XOR:LINE(0,Y1)-(XLIM,Y1),LC,,XOR:LINE(0,Y2)-(XLIM,Y2),LC,,XOR
240 IF TIME<2 THEN 240
250 TIME=0:LINE(X,Y1)-(X,Y2),LC,,XOR:LINE(0,Y1)-(XLIM,Y1),LC,,XOR:LINE(0,Y2)-(XLIM,Y2),LC,,XOR
260 K$=INKEY$:IF K$<>""THEN GOSUB280
270 IF TIME<2 THEN 270 ELSE 230
280 'Deal with key presses
290 KC=ASC(K$):SK=(PEEK(&HFBEB)AND1XOR1)*8:CK=(PEEK(&HFBEB)AND2)<2:' get keys
300 IF KC=27 THEN END
310 IF KC=29 THEN X=X-XSTP-SK:IF XXLIM-XSTP THEN X=XLIM-XSTP
330 IF KC=30 AND NOT CK THEN Y1=Y1-1-SK
340 IF KC=31 AND NOT CK THEN Y1=Y1+1+SK
350 IF KC=30 AND CK THEN Y2=Y2-1-SK
360 IF KC=31 AND CK THEN Y2=Y2+1+SK
370 IF KC=32 THEN GOSUB 400:'Space = swap
380 IF KC=13 THEN BSAVE N$,0,IE,S
390 RETURN
400 'swap areas
410 COPY(0,Y1)-(X,Y2),0TO(0,0),1
420 COPY(X+1,Y1)-(XLIM,Y2),0TO(0,Y1),0
430 COPY(0,Y1)-(X,Y2),1TO(XLIM-X,Y1),0
440 X=XLIM-X-1
450 RETURN


PS: I'm not exactly an experienced TCL programmer. I hope the parts I added don't look too ugly. Wink

By wouter_

Champion (418)

wouter_'s picture

20-01-2014, 20:16

sd_snatcher wrote:

Ok, I implemented the vertical scroll fix, ...

I finally found time to look at this. I've added your change (with a bug fix) in the the latest version of the script.

By sd_snatcher

Prophet (3068)

sd_snatcher's picture

01-02-2014, 17:11

Thanks, wouter_!

By sd_snatcher

Prophet (3068)

sd_snatcher's picture

14-10-2019, 02:50

I extended the save_msx_screen script to be able to save interlaced images:

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:
  <a href="http://www.msx.org/forum/msx-talk/general-discussion/taking-sc5-snapshot-games" title="http://www.msx.org/forum/msx-talk/general-discussion/taking-sc5-snapshot-games">http://www.msx.org/forum/msx-talk/general-discussion/taking-...</a>
}

proc save_msx_screen {basename} {
	set directory [file normalize $::env(OPENMSX_USER_DATA)/../screenshots]
	# Create filename with correct extension (also gives an error in
	# case of an invalid screen mode).
	set fname [file join $directory [format "%s.SC%X" $basename [get_screen_mode_number]]]
	set fname2 [file join $directory [format "%s.S1%X" $basename [get_screen_mode_number]]]

	set name_base        [expr { [vdpreg 2]        * 0x400}]
	set name_base_80     [expr {([vdpreg 2] & 252) * 0x400}]
	set name_base_bitmap [expr {([vdpreg 2] &  96) * 0x400}]
	set color_base       [expr { [vdpreg 3]        * 0x40 + [vdpreg 10] * 0x4000}]
	set color_base_2     [expr {([vdpreg 3] & 128) * 0x40 + [vdpreg 10] * 0x4000}]
	set pattern_base     [expr { [vdpreg 4]        * 0x800}]
	set pattern_base_2   [expr {([vdpreg 4] & 60)  * 0x800}]
	set spr_att_base     [expr { [vdpreg 5]        * 0x80 + [vdpreg 11] * 0x8000}]
	set spr_att_base_2   [expr {([vdpreg 5] & 252) * 0x80 + [vdpreg 11] * 0x8000 - 0x200}]
	set spr_pat_base     [expr { [vdpreg 6]        * 0x800}]
	set interlace        [expr {([vdpreg 9] >> 2 ) & ([vdpreg 9] >> 3 ) & [expr {[vdpreg 2] >> [expr {[get_screen_mode] < 7 ? 4:5}]}] & 1 }]

	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 {[vdpreg 23] > 24 ? 256 - [vdpreg 23] : 232}] ;# Store 232 lines, even
		set lines2 [expr {232 - $lines1}]                              ;# though only 212 are visible
		set base1 [expr {$name_base_bitmap -(0x8000 * $interlace) + [vdpreg 23] * 128}]
		set base2 [expr {$name_base_bitmap -(0x8000 * $interlace)}]
		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 == 1 } {
			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 {[vdpreg 23] > 16 ? 256 - [vdpreg 23] : 240}] ;# Store 240 lines, even
		set lines2 [expr {240 - $lines1}]                              ;# though only 212 are visible
		set base1 [expr {($name_base_bitmap * 2) & 0x10000 - (0x10000 * $interlace) + [vdpreg 23] * 256}]
		set base2 [expr {($name_base_bitmap * 2) & 0x10000 - (0x10000 * $interlace) }]
		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 == 1 } {
			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
		}
	}}

	# open file
	set out [open $fname w]
	fconfigure $out -translation binary

	# write header
	set end_addr -1
	foreach {type addr size} $sections {
		incr end_addr $size
	}
	set header [ 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} $sections {
		puts -nonewline $out [debug read_block $type $addr $size]
	}
	close $out

	if { $interlace == 1 } {		# Write the 2nd part of an interlaced image
		# open file
		set out [open $fname2 w]
		fconfigure $out -translation binary
	
		# write header
		set end_addr -1
		foreach {type addr size} $sections2 {
			incr end_addr $size
		}
		puts -nonewline $out [binary format c* $header]
	
		# write data sections
		foreach {type addr size} $sections2 {
			puts -nonewline $out [debug read_block $type $addr $size]
		}
		close $out
	}

	return [expr { $interlace==0 ? "Screen written to $fname":"Screen written to $fname + $fname2" }]
}

[/]

By wouter_

Champion (418)

wouter_'s picture

28-10-2019, 17:58

I somehow missed this post, but Manuel pointed me to it. I've integrated your script in the latest openMSX revision.
Thanks.

By sd_snatcher

Prophet (3068)

sd_snatcher's picture

28-10-2019, 22:02

You're welcome! Smile

Page 5/5
1 | 2 | 3 | 4 |