nametable & double buffering

Page 6/10
1 | 2 | 3 | 4 | 5 | | 7 | 8 | 9 | 10

By ARTRAG

Enlighted (6543)

ARTRAG's picture

18-05-2012, 20:51

Crying
but how does the glitch work?
how is emulated at least?

A new perverson, having double buffer, one could dynamically define moving objects using tiles. At first glance, the problem could be to have, at each step of the scrolling in the map, the list of tiles non being visualised on the screen that can be used for sprites....

By hap

Paragon (2038)

hap's picture

18-05-2012, 21:21

meisei vdp.c, the relevant part:
Please don't ask about the code Tongue it's been years ago since I wrote it.

	/* sprites */
	if (~mode&1) {
		int clone=0x20;
		int clonemask[6]={0xff,0,0,0xff,0,0};	/* line AND, y XOR, y OR */

(...)		
		
		/* init sprite cloning */
		if (regs[0]&2&&(regs[4]&3)!=3&&!toshiba) {
			/* On TMS9xxx(/A) M3, sprites 8-31 Y position(s) is influenced by the least two
			bits of the pattern generator table offset, and somewhat by bits 5 and 6 of the
			colour table register. Sprite locations, mostly those on Y 0-63, will become
			glitchy, and cause a cloning effect similar to tiles with M3 table mirroring.
			This is not just a visual effect, as sprite collision and overflow behave as if
			sprites are normal. If the VDP is running hot, this effect will deteriorate
			(confirmed by flyguille with a blow dryer :) ), starting with block 1, and
			block 2 shortly after (effect deterioration from heat is unemulated). I assume
			the reason for the first 8 sprites not being affected is due to them being
			preprocessed in hblank. This glitch is briefly mentioned in the official
			TMS91xx programming manual btw, meaning that it's not undocumented.
			
			Known software affected by this (not counting tests or small glitches):
			- Alankomaat by Bandwagon, at the fire part (intended)
			- Lotus F3, unintended problems in MSX1 palette mode (black screen on my MSX1s)
			
			The calculations below are done to get the correct result, I can't think of
			a way to solve this logically. This implementation has been tested side by side
			to my MSX1, with all possible sprite Y and addressmasks. */
			
			/* 0-255, 4 blocks of 64 lines */
			if (line>191) {
				/* block 3 (only visible at the far top of the screen)
				Sprites are cloned from block borders. The colour block
				erase effect is the same as on block 2 below. */
				clonemask[0]=0xff; clonemask[2]=~regs[4]<<6&0xc0;
				if (~regs[3]&0x40&&clonemask[2]&0x80) {
					clonemask[0]&=0x7f;
					clonemask[2]&=0x7f;
				}
				
				clonemask[3]=clonemask[0]; clonemask[5]=clonemask[2];
				
				clone=7;
			}
			else if (line>127) {
				/* block 2, sprites are cloned from block 0.
				The bottom part of sprites on block 1+2 is always
				invisible. If this colour block mask is reset, real
				sprites in block 2 will be erased. */
				
				/* only has effect if this pattern block mask is reset */
				if (~regs[4]&2) {
					clonemask[1]=clonemask[4]=0x80;
					clonemask[5]=regs[3]<<1&0x80;
					
					clone=7;
				}
			}
			else if (line>63) {
				/* block 1, sprites are cloned from block 0.
				If this colour block mask is reset, the bottom part of
				sprites on block 0+1 will be invisible. */
				
				/* only has effect if this pattern block mask is reset */
				if (~regs[4]&1) {
					clonemask[0]=0x3f;
					clonemask[5]=~regs[3]<<1&0x40;
					
					clone=7;
				}
			}
			else {
				/* block 0, no effect */
				;
			}
		}
		
		for (;;) {
			/* forced break */
			if ((y=*sa++)==208) break;
			
			/* calculate offset */
			if (statuslow>clone) {
				yc=(line&clonemask[0])-((y^clonemask[1])|clonemask[2]);
				if (yc>smax) yc=(line&clonemask[3])-((y^clonemask[4])|clonemask[5]);
			}
			else yc=line-y;
			
			/* found sprite */
			if (yc<=smax) {

(...)

By hit9918

Prophet (2905)

hit9918's picture

18-05-2012, 22:36

I saw sprite disappearance on real machine.
In the below BASIC app, the three situations:

1. sprite 0 top charset. sprite 8 cloned 3 times.
2. sprite 0 middle charset. sprite 8 in middle charset.
3. sprite 0 in bottom charset. sprite 8 disappearance.

(the below code was copied by hand)

10 screen 2,2
20 sprite$(0) = "askdhsjkdhskjhskjdhskhdskjhdshkddjhskhddsjh"
30 line(0,0)-(255,191)
40 vdp(4)=&b000
50 vdp(3)=&b10011111
60 put sprite 0,(0,y),8,0
70 put sprite 8,(128,y),15,0
80 if inkey$ = "" then 80
90 y = y + 64
100 goto 60

By PingPong

Prophet (3760)

PingPong's picture

18-05-2012, 22:52

Crappy vdp, crappy vdp, crappy vdp, soooooooo crappy....... Sad Sad Sad Sad Sad Sad Sad Sad Sad Sad Sad Sad Sad Sad Sad

By Manuel

Ascended (18151)

Manuel's picture

18-05-2012, 22:54

PingPong, what is your point with these posts?

By ARTRAG

Enlighted (6543)

ARTRAG's picture

18-05-2012, 23:26

Ok things are terrible but not desperate
from what I see sprites [8-31] can stay safely in middle bank (their clone will appear under the border) while only sprites [0-7] can dare to go the the lower bank.
If this is true, I have only to revert the initial strategy, for y>=128 one should use only sprites [0-7] eventually multiplying the by SW, if 64<=y<128 you can use all sprites in [8-31]

By ARTRAG

Enlighted (6543)

ARTRAG's picture

18-05-2012, 23:31

done, is there anyone out there willing to test demo5.dsk (or demo5.rar) on a real msx1 ?

https://sites.google.com/site/testmsx/Home/double-buffer-in-...

now sprites in the lower bank should flicker (they are planes [0-7] multiplexed times 2) while sprites in the middle bank should be perfect (they are planes [8-31] that will go cloned under the border)...

Going to see how meisei goes...

By hap

Paragon (2038)

hap's picture

18-05-2012, 23:43

I ran it on MSX1, and it's the same as meisei: middle block is always stable, lower block always flickers. And there's a small glitch at the topmost scanline when scrolling.

btw, don't forget that a sprite can also be on the middle and lower block at the same time (eg. y=120 -> sprite is on 120-136)

By hit9918

Prophet (2905)

hit9918's picture

19-05-2012, 02:34

"crap VDP", here we go again Wink
The 9918 bitch again caused broken hearts Big smile

Whenever the VDP is called crap, I must answer with scroll obsession Wink
But this time, let's have an entertainment part:

No real Mario Turtles were ever seen on C64, neither in hires nor in two individual colors.
I herewith declare Mario sprites conquered by "the VDP".

And Giana is an ugly fat(pixel) chick compared to Malaika Big smile

And now I got a new idea: dynamic alloc without struct alloc. Fullscreen doublebuffered + full sprites.
The deal: no engine effort like struct alloc.

The screen must be 50% filled with the 0 tile, so you use max 128 tiles, so there you got the fullscreen doublebuffer.
The max 128 tiles is "simultaneously onscreen per charset", not per level.

nametable draw: if not 0, increment tile number. dump that value on port 98.
pattern draw: going thru nametable in same fashion, skipping the 0, pattern draw ends up dumped linear to port 98.
Suddenly the screen 2 scrambeling looks elegant!?
Scan nametable, if 0 then do nothing, else draw pattern: likely lot 1 pixel scroll ZX stuff works like this. No more complaining.

With 16bit nametable and on-the-fly-neighbours-combining methods, could have epic gfx masses.
16bit would be "pop hl + cp h" instead "cp (hl)" for the null check. Make sure non-null tiles have a number with h>=1.

	;hl points to an ordinary level nametable, vram pointer to nametable
	ld a,0
	ld d,0
	ld c,0x98
drawnametable:
	cp (hl)		;a = 0, (hl) = RAM tile number
	jp nz,alloc
	outi		;0 = blank tile, both in RAM nametable and vram nametable
	djnz drawnametable
	
	;outer loops...
	
alloc:
	inc d
	out (c),d	;d = allocated vram tile. not same numbering as RAM tiles.
	inc hl
	djnz drawnametable
	
	;outer loops...
	xor a ;ld a,0
	...


	;hl points to an ordinary level nametable, vram pointer to patterntable
	ld a,0
drawtiles:
	cp (hl)		;a = 0, (hl) = RAM tile number
	jp nz,tilesalloc
	;do nothing
	inc hl
	djnz drawtiles
	
	;outer loops
	xor a ;ld a,0
	...

tilesalloc:
	;draw your ZX stuff
	;input: (hl) = RAM tile number. output: 8 bytes to port 98.
	;as the thing runs thru the same alloc style as nametable draw, 
	;pattern is written just sequential without port 99 setup

	xor a ;ld a,0
	inc hl
	djnz drawtiles

	;outer loops...
	xor a ;ld a,0
	...
	

By hit9918

Prophet (2905)

hit9918's picture

19-05-2012, 02:48

p.s. when entering next charset:
nametable draw: set d back to 0
pattern draw: set vram pointer to that charset. +8 to skip nullchar.

Page 6/10
1 | 2 | 3 | 4 | 5 | | 7 | 8 | 9 | 10