openMSX "sprite rivelator"

Page 1/3
| 2 | 3

Par PingPong

Prophet (3898)

Portrait de PingPong

01-01-2022, 23:44

Hi, i know that openMSX could be "extended" with the use of TCL scripts.
I do not know TCL, so i ask to an openMSX & TCL expert if it's possible to implement a simple "sprite rivelator" function that i describe below:

- display a simple square overlayed over the screen position where a sprite is displayed
- should take into account sprite size (8x8 or 16x16 msx pixels, magnification on/off)
- should work in any screen enabled sprite
- should work on msx1 or msx2 video modes.

The rationale is to allow easily to discover some tricks used by some sw that mix sprites and tiles.
one could disable sprite display but a similar feature is more useful as it does allow to see more dynamically how a sw manages sprites, (for example some tricks used by konami in some games to allow a sprite to disappear when it's y position is greater than a specific position, overusing the scanline sprite limit)

Can a similar thing be done in openMSX?

!login ou Inscrivez-vous pour poster

Par sd_snatcher

Prophet (3509)

Portrait de sd_snatcher

02-01-2022, 16:46

When I want to check for such tricks, I usually just disable de sprites on the openMSX-Debugger.

Works like a charm on FireHawk, i.e.

Par Manuel

Ascended (18853)

Portrait de Manuel

02-01-2022, 18:06

If you can tell me where all this sprite data is available, it wouldn't be too hard to make a quick script to show them...

Par PingPong

Prophet (3898)

Portrait de PingPong

02-01-2022, 22:27

Emh manuel, i'm not sure about your question can you elaborate this "if you tell me where all this sprite data is available".
sprite data are the SAT contents. the real vdp itself know through its registers where sat data is placed. in "msx basic pseudo code" is some thing like this:

BASEADDR=vdp(5)*256*vdp(12)*128 : REM not sure about this, but should be the base SAT address....
FOR T=0 To 31
y=vpeek(BASEADDR+T*4)
x=vpeek(BASEADDR+1+T*4)
line (x,y)-step(15,15),15,b: REM i assume 16x16 pixel wide sprites.... should be adapted to vdp sprite size and magnification settings
next T

this should draw squared box but on the openMSX overlayed - emulated msx screen not on the msx vram itself of course. It's only to show what i mean. This should also work at every frame rendering in openMSX window...

Par Manuel

Ascended (18853)

Portrait de Manuel

02-01-2022, 22:28

Well, this is quite easy to put in a Tcl script, but it would help if you know that the addresses are actually correct Smile

Par Manuel

Ascended (18853)

Portrait de Manuel

03-01-2022, 00:44

OK, I made a prototype, got the addressing from the Wiki, but the addressing isn't (apparently) fully clear to me for MSX2 modes, as it's not working there. This is what I got so far:

namespace eval sprite_locator {

variable sprite_locator_enabled false
variable sprite_locator_after_id 0

set_help_text toggle_sprite_locator \
"Shows the locations of all 32 sprites according to the current VDP state."

proc toggle_sprite_locator {} {
	variable sprite_locator_enabled
	variable sprite_locator_after_id

	if {$sprite_locator_enabled} {
		set sprite_locator_enabled false
		osd destroy sprite_locator
		catch { after cancel $sprite_locator_after_id }
		return "Sprite locator disabled"
	} else {
		set sprite_locator_enabled true
		osd_widgets::msx_init sprite_locator

		for {set i 0} {$i < 32} {incr i} {
			osd create rectangle sprite_locator.box$i -relx -100 -rely -100 -relh 8 -relw 8 \
				-rgba 0xFF111140 -borderrgba 0xFF1111C0 -bordersize 1
			osd create text sprite_locator.box$i.snr -text $i -size 6 -y -6 -rgba 0xFFFFFFFF
			osd create text sprite_locator.box$i.pnr -text "" -size 6 -y  0 -rgba 0xFFFFFFFF
		}
		set sprite_locator_after_id [after frame [namespace code update_locator]]
		return "Sprite locator enabled, showing red rectangles around sprites..."
	}
}

proc update_locator {} {
	variable sprite_locator_enabled
	variable sprite_locator_after_id
	if {$sprite_locator_enabled} {
		osd_widgets::msx_update sprite_locator
		set mode_num [get_screen_mode_number]
		if {$mode_num == 0} return
		set r5 [vdpreg 5]
		set r11 [vdpreg 11]
		set special_y 216
		switch [get_screen_mode] {
			"1" -
			"2" -
			"3" {
				set base_addr [expr {$r5 * 0x80}]
				set special_y 208
			}
			"4" -
			"5" -
			"6" {
				set base_addr [expr {($r5 - 3) * 0x80}]
			}
			default {
				set base_addr [expr {($r5 + 256 * $r11) * 0x80}]
			}
		}
		# sprite size
		set size [expr {([vdpreg 1] & 2) == 2 ? 16 : 8}]
		# sprite magnification
		if {[expr {([vdpreg 1] & 1) == 1}]} {
			set size [expr {$size * 2}]
		}
		set next_are_hidden false
		for {set i 0} {$i < 32} {incr i} {
			if {$next_are_hidden} {
				set y -100
				set x -100
			} else {
				set y [vpeek [expr {$base_addr + 0 + 4*$i}]]
				if {$y == $special_y} {
					set next_are_hidden true
					set x -100
					set y -100
				} else {
					set x [vpeek [expr {$base_addr + 1 + 4*$i}]]
					incr y; # seems to be needed to make it look good... bug in osd_widgets::msx_init?
					set pnr [vpeek [expr {$base_addr + 2 + 4*$i}]]
					osd configure sprite_locator.box$i.pnr -text $pnr
				}
			}
			osd configure sprite_locator.box$i -relx $x -rely $y -relw $size -relh $size
		}
		set sprite_locator_after_id [after frame [namespace code update_locator]]
	}
}

namespace export toggle_sprite_locator

};# namespace sprite_locator

namespace import sprite_locator::*

The important bits are in in the update_locator proc of course. Please send in your fixes...

How to use: save somewhere, in the console use the source /path/to/script.tcl command to load it and then type toggle_sprite_locator to activate.

Again: please fix the addressing and stuff for me Smile

Par Manuel

Ascended (18853)

Portrait de Manuel

03-01-2022, 00:56

The script shows a red box around the sprites, adjusts for size and magnification (latter is not tested) and puts the sprite number on top of the box and the pattern number inside (as how it is in VRAM... would be nice if it would show all 4 pattern numbers for 16x16 sprites, but how to find these wasn't fully clear to me; the technical databook is very... brief.)

Examples:


Par PingPong

Prophet (3898)

Portrait de PingPong

03-01-2022, 12:05

thanks, i will check the correctness of addresses asap and let you know.
For now, i'm impressed on how konami "abused" those tricks to achieve gfx looking good

Par jltursan

Prophet (2619)

Portrait de jltursan

03-01-2022, 16:11

Way cool!, I guess it's working fine now for MSX1 machines and thus, I can't really understand why Konami used, as PingPong says, so many sprites in the Galious castle screen example,

Par Parn

Paladin (791)

Portrait de Parn

03-01-2022, 19:31

Manuel wrote:

(as how it is in VRAM... would be nice if it would show all 4 pattern numbers for 16x16 sprites, but how to find these wasn't fully clear to me; the technical databook is very... brief.)

You can't set all four pattern numbers in 16x16 sprites. You just set the first one and the VDP gets the following three patterns, so you don't really need to show all four.

jltursan wrote:

Way cool!, I guess it's working fine now for MSX1 machines and thus, I can't really understand why Konami used, as PingPong says, so many sprites in the Galious castle screen example,

Perhaps those are leftovers from previous screens.

Par PingPong

Prophet (3898)

Portrait de PingPong

03-01-2022, 20:39

hi, i've verified the addresses. the calculations are correct for screen modes 1-2-3
they get wrong on screen 4-5-6-7-8

10 S$=string$(32,255)
20 FOR T%=1 TO 8
30 SCREEN T%,2,0: COLOR 15,1,1: CLS
40 SPRITE$(1)= S$
50 PUT SPRITE 2, (35, 18), 14, 1
60 REM 
70 A!=(VDP(5)+VDP(12)*256.0)*128
80 IF T%=1 THEN PRINT A! ELSE OPEN "GRP:"AS #1:PRINT #1,A!;" - Y="; VPEEK(A!+8); " -X="; VPEEK(A!+9):CLOSE#1
90 T$=INPUT$(1)
100 NEXT T%
110 END

the code above is used to check the address calculation.
this code places a sprite plane 2 at 35, 18 using basic then calculate base SAT address (line 70).
it then display the calculated address and the first and second byte of SAT of sprite plane 2 holding y and x coords.
Effectively it does work on msx1 screen modes, while the same calculate wrong addresses on screen 4->8

however, i cannot figure why. as said in docs the bits A7 to A16 are packed into registers 5, and 11 so the effective address should be calculated as line 70 does.

maybe one should check the openMSX source code to see if there is some VDP quirk in sat address calculation?

Page 1/3
| 2 | 3