Uzeamp Movie Player Demo

Use this forum to share and discuss Uzebox games and demos.
HardlyUnique
Posts: 65
Joined: Tue Dec 08, 2009 7:44 pm

Re: Uzeamp Movie Player Demo

Post by HardlyUnique »

uze6666 wrote:We would need to gather the manufacturer code and/or model from the card dynamically and match against a table of delay values.
What a glutton for punishment you are!

Anyways, maybe I'm just biased but I like my solution better. :P

I realize now that I probably didn't explain my idea very well and also that not everyone has recently spent hours poring over the sources. :oops: I'll explain it later but first, let me say:
IT WORKS! :D

I was able to incorporate my hack into the mode 7 kernel files where it can now be called a fix. 8-) I'm including a working player showing it off.

The matrix trailer will now play perfectly from any spot on the card, so you can now watch 12 copies back to back :P. Or, do something else cool with mode 7!! It just takes ~1 second to sync when playback starts.

As I expected, 8-bit trip has a little bit of trouble synching up on it's own. For this, I've left my button-press-delay hack in the included player. You just have to press any button a few times and it's good to go.

How it works:
.uzm's are encoded with a 250-byte filler near the beginning of each video frame. I noticed that when the picture lost sync, the filler was all black (as you'd expect) and reasoned that this filler could be used as a sort of VSYNC indicator.

So, I re-wrote read_filler to actually check that this filler is all black and if it isn't, delay playback by leaving render_start set to 0. What happens is that every frame the filler isn't found, playback is skipped to check on the next frame if the next sector is, in fact, the one with the filler. At least, I *think* that's what's going on. ;)

So, if you're making a new video, (say, for a cutscene :mrgreen:) you'd want to make sure not to leave lines of total black, just use very light grey instead.

Here's the new code for VideoMode7.s. The only changes are immediately around read_filler but I'll post it all to assist the lazy:

Code: Select all

;***************************************************
; Video Mode 7
; 170x120
; Movie player
;***************************************************

#define LINE_BUFFER_SIZE 170
#define LINES_PER_SECTOR 6

.global load_sound_buffer
.global render_start
.global playback_start
.global StartPlayback
.global StopPlayback
.global InitializeVideoMode
.global DisplayLogo
.global VideoModeVsync
.global vram

.section .bss
	
	vram: 	  		.space 1
	line_buffer:	.space LINE_BUFFER_SIZE*2
	render_start:	.byte 1
	playback_start:	.byte 1


.section .text

//*** Main routine ****
sub_video_mode7:

	;waste line to align with next hsync in render function
	ldi ZL,222-170-2
mode7_render_delay:
	lpm
	nop
	dec ZL
	brne mode7_render_delay

	lpm
	lpm



	;clear the line buffer
	ldi r16,LINE_BUFFER_SIZE
	clr r17
	ldi XL,lo8(line_buffer)
	ldi XH,hi8(line_buffer)
clr_loop:
	st X+,r17
	st X+,r17
	dec r16
	brne clr_loop


	ldi r16,LINE_BUFFER_SIZE/2
	mov r25,r16
	mov r13,r16

	ldi r16,lo8(LINE_BUFFER_SIZE)
	ldi r17,hi8(LINE_BUFFER_SIZE)
	movw r14,r16

	clr r21			;first frame sector
	ldi r22,224+4	;decremental line counter
	clr r23			;incremental line counter
	ldi r24,LINES_PER_SECTOR 	;lines per SD sector

	ser r20
	clr r6

	lds r18,render_start
	cpi r18,1
	brne next_line_wait

next_line:
	;trigger 1st line pixel read
	out _SFR_IO_ADDR(SPDR),r20

	;***First Line***
	rcall hsync_pulse ;3+144=147

	;draw line
	eor r25,r13	;add half line offset
	rcall render_tile_line

	inc r23
	dec r22
	brne next_line
	rjmp end_frame

next_line_wait:
	rcall hsync_pulse ;3+144=147
	ldi r24,lo8(1670/4)
	ldi r25,hi8(1670/4)
wait:
	sbiw r24,1
	brne wait
	rjmp .

	dec r22
	brne next_line_wait
	
end_frame:
	;frame rendering finished
	rcall hsync_pulse ;145

	;set vsync flag if beginning of next frame (each two fields)
	ldi r17,1
	lds r16,curr_field
	eor r16,r17
	sts curr_field,r16

	lds r18,curr_frame
	tst r16
	breq .+2
	eor r18,r17
	sts curr_frame,r18

	;set vsync flag if beginning of next frame
	ldi ZL,1
	sts vsync_flag,ZL

	;clear any pending timer int
	ldi ZL,(1<<OCF1A)
	sts _SFR_MEM_ADDR(TIFR1),ZL

//	call load_sound_buffer

	ret



;*************************************************
; RENDER SCANLINE
;
; r22     = Lines remaining
; r23 	  = current line
; r24     = sector lines left
; r25     = next line buffer displacement
;
; cycles  = 1679
;*************************************************

render_tile_line:


	;current buffer
	ldi XL,lo8(line_buffer)
	ldi XH,hi8(line_buffer)
	movw YL,XL

	sbrc r23,1
	add XL,r14
	sbrc r23,1
	adc XH,r15

	;next line buffer
	sbrs r23,1
	add YL,r14
	sbrs r23,1
	adc YH,r15
	
	;add half line offset each other line
	add YL,r25
	adc YH,r6
		
	ldi r18,84
loop:
	nop
	;in r17,_SFR_IO_ADDR(SPSR) ;clear flag
	in r17,_SFR_IO_ADDR(SPDR) ;read next pixel
	out _SFR_IO_ADDR(SPDR),r20
	ld r19,X+
	out _SFR_IO_ADDR(DATA_PORT),r19
	st Y+,r17
	rjmp .
	rjmp .
	ld r19,X+
	out _SFR_IO_ADDR(DATA_PORT),r19
	dec r18
	brne loop ;18*84=1512


	;write last line pixel
	;in r17,_SFR_IO_ADDR(SPSR) ;clear flag
	nop
	in r17,_SFR_IO_ADDR(SPDR) ;read next pixel
	st Y+,r17

	out _SFR_IO_ADDR(DATA_PORT),r6

	dec r24
	breq next_sector
	
	
	
	ldi r19,42
	dec r19
	brne .-4 
	rjmp .
	
	ret 
	;1660

next_sector:

	;-read the two last sector's bytes
	;-2 CRC bytes
	;-wait 8 clocks
	;-read next data token (0xfe)
	ldi r19,6

read_blocks:
	;read first  CRC byte
	out _SFR_IO_ADDR(SPDR),r20
	ldi r18,5
	dec r18
	brne .-4 ;wait 15 cycles
	dec r19
	;in r17,_SFR_IO_ADDR(SPSR) ;clear flag
	nop
	in r17,_SFR_IO_ADDR(SPDR) ;read crc
	brne read_blocks ;21

	ldi r24,LINES_PER_SECTOR

	ret
	;1660

;********************************
; Can destroy r18-r27 and r30-r31
;********************************
load_sound_buffer:

	;set target bank adress
	lds r18,mix_bank
	tst r18
	breq lset_hi_bank
	ldi ZL,lo8(mix_buf)
	ldi ZH,hi8(mix_buf)
	rjmp lend_set_bank
lset_hi_bank:
	ldi ZL,lo8(mix_buf+MIX_BANK_SIZE)
	ldi ZH,hi8(mix_buf+MIX_BANK_SIZE)
lend_set_bank:


	ldi r24,lo8(262)
	ldi r25,hi8(262)
	ser r20
lsb_loop:
	out _SFR_IO_ADDR(SPDR),r20
	ldi r18,4
	dec r18
	brne .-4 ;wait 12 cycles
	sbiw r24,1
	nop
	in r19,_SFR_IO_ADDR(SPSR) ;clear flag
	in r19,_SFR_IO_ADDR(SPDR) ;read crc
	st Z+,r19
	brne lsb_loop ;22



	; 262 sound bytes were read.
	;-250 filler bytes ?
	;-2 CRC bytes
	;-wait 8 clocks
	;-read next data token (0xfe) (twice, presumably)
	ldi r19,250
	ldi r21,0	; keeps track of filler
	ldi r18,0	
	;read first filler byte
read_filler:
	out _SFR_IO_ADDR(SPDR),r20

	or r21, r18		; or the most recent filler byte with r21
	nop
	nop

	ldi r18,4
	dec r18
	brne .-4 ;wait 12 cycles

	; read some more filler bytes
	dec r19
	in r17,_SFR_IO_ADDR(SPSR) ;clear flag
	in r18,_SFR_IO_ADDR(SPDR) ;read next byte
	brne read_filler ;21

	; read four more bytes that we don't care about (CRC and such)
	ldi r19, 4
read_dont_care:
	out _SFR_IO_ADDR(SPDR),r20

	ldi r18,5
	dec r18
	brne .-4 ;wait 15 cycles

	; read some more dont_care bytes
	dec r19
	in r17,_SFR_IO_ADDR(SPSR) ;clear flag
	in r18,_SFR_IO_ADDR(SPDR) ;read whatever
	brne read_dont_care ;21

	ldi r18,1
	sts render_start,r18

	cpi r21, 0		; ensure that we only read black for the duration of the filler,
	brne Offsync	; otherwise, we know the video is out-of-sync

	ret

Offsync:
	ldi r18,0
	sts render_start,r18	; just kidding; don't start rendering until we're sycnhronized :)
	ret


StartPlayback:
	ldi r24,1
	sts playback_start,r24
	ret

StopPlayback:
	ldi r24,0
	sts render_start,r24
	sts playback_start,r24
	ret


;No logo for this mode
DisplayLogo:
	ret


VideoModeVsync:

	lds r24,playback_start
	cpi r24,0
	breq skip
	rcall load_sound_buffer
skip:
	ret


InitializeVideoMode:

	ldi XL,lo8(line_buffer)
	ldi XH,hi8(line_buffer)
	ldi r24,64*2
	ldi r25,0xff
m7_init_loop:
	st X+,r25
	dec r24
	brne m7_init_loop

	sts render_start,r1
	sts playback_start,r1

	ret
EDIT: I didn't like the idea of making people re-encode their .uzm's. So, I wrote a couple of little "blank" .uzm's to concatenate with other .uzm's like 8-bit trip.

I've attached the blanks in a .zip. (Windows) Instructions included.
Attachments
blanks.zip
(5.44 KiB) Downloaded 368 times
SyncDemo.hex
(25.19 KiB) Downloaded 354 times
SyncDemo.uze
(9.45 KiB) Downloaded 360 times
User avatar
JRoatch
Posts: 108
Joined: Mon May 11, 2009 11:48 pm
Contact:

Re: Uzeamp Movie Player Demo

Post by JRoatch »

HardlyUnique wrote:So, if you're making a new video, (say, for a cutscene :mrgreen:) you'd want to make sure not to leave lines of total black, just use very light grey instead.
Would putting something in the 2 bytes of video sector filler work, or is that simply skipped over for receiving MMC checksum?

If it can be used, it could be a block counter that counts from 1 to 38 for video sectors, and 0 for audio sectors.
HardlyUnique
Posts: 65
Joined: Tue Dec 08, 2009 7:44 pm

Re: Uzeamp Movie Player Demo

Post by HardlyUnique »

That's an interesting idea. I'm pretty sure you could put data there; you get about 15 unused cycles to play with in between each sd byte read. No bytes are skipped from the card's perspective; everything is streamed out.

However, unless you have some ideas for this filler beyond image sync data, it's probably way more work than it's worth.

The image already sync's really fast as it is, and once it is in sync, it stays there. Once in sync, you will already be able to tell which line you are drawing at any time.
Post Reply