org 0x8000 tv_flag equ 0x5c3c ld hl,video_offsets ld (next_video_ptr),hl xor a ld (video_count),a call 3435 ; clear screen ; set up text printing xor a ld (tv_flag),a ; scan disk for the 'DivIDEOg\1' signature ; set sector number to 0, LBA mode xor a ld (sector_number),a ld (sector_number+1),a ld (sector_number+2),a or 0x40 ld (sector_number+3),a ; read sectors until we get an error scan_sectors call set_sector_number ld a,1 out (0xab),a ; read one sector ld a,0x20 ; READ SECTOR out (0xbf),a ; command reg wait_ready in a,(0xbf) ; wait for 'ready' status and 0x80 ; test bit 7 jr nz,wait_ready ; check for error in a,(0xa7) ; error reg bit 4,a ; if set, sector-out-of-range error occurred. TODO: use an AND instead jr nz, choose_video ; check for user quit (Q key) ld bc,0xfbfe in a,(c) and 1 jr z,choose_video ld b,signature_end - signature ld hl,sector_buffer read_signature in a,(0xa3) ld (hl),a inc hl djnz read_signature ; does signature match? ld hl,signature ld de,sector_buffer ld b,signature_end - signature check_signature ld a,(de) cpi jr nz,ignore_sector inc de djnz check_signature ; fetch initial sector count in a,(0xa3) ld l,a ; fetch border colour in a,(0xa3) ld h,a push hl ; skip 21 bytes (reserved for future use) ld b,21 skip_reserved in a,(0xa3) djnz skip_reserved ld b,32 read_video_name ld c,0xa3 in a,(c) or a jr nz,read_video_name_nonzero ld a,' ' read_video_name_nonzero push bc rst 0x10 pop bc djnz read_video_name call advance_sector ld de,(next_video_ptr) ld hl,sector_number ldi ldi ldi ldi pop hl ; recall initial-sector-count and border colour ld a,l ld (de),a inc de ld a,h ld (de),a inc de inc de inc de ; align video entries on 8 byte boundaries ld (next_video_ptr),de ld hl,video_count inc (hl) jp scan_sectors ignore_sector call advance_sector jp scan_sectors ; video chooser choose_video xor a ld (video_number),a call highlight_video choose_video_lp ; check for Q key ld bc,0xfbfe in a,(c) and 1 jr z,key_q ; check for A key ld bc,0xfdfe in a,(c) and 1 jr z,key_a ; check for space key ld bc,0x7ffe in a,(c) and 1 jr z,key_space jr choose_video_lp key_q ld a,(video_number) or a jr z, choose_video_lp call unhighlight_video ld hl,video_number dec (hl) call highlight_video call wait_nokey jr choose_video_lp key_a ld a,(video_number) inc a ld hl,video_count cp (hl) jr z,choose_video_lp ld a,(video_number) call unhighlight_video ld hl,video_number inc (hl) call highlight_video call wait_nokey jr choose_video_lp wait_nokey ; wait until none of Q, A, space are pressed ld bc,0x79fe in a,(c) and 1 jr z,wait_nokey ret key_space ; translate video number into lookup position in table ld a,(video_number) ld l,a ld h,0 add hl,hl add hl,hl add hl,hl ld de,video_offsets add hl,de ; now hl points to the start sector of the video data push hl ; also want to point ix there, so that we can grab the initial sector count and border colour pop ix ld de,sector_number ldi ldi ldi ldi play_video ; clear screen (to black on black) ld hl,0x4000 ld de,0x4001 ld bc,0x1aff ld (hl),l ldir ld bc,0x7ffd ; clear second screen too ld a,0x17 out (c),a ld hl,0xc000 ld de,0xc001 ld bc,0x1aff ld (hl),l ldir ld a,(ix+5) ; retrieve border colour out (254),a ; set up AY for sample playback ld bc,0xfffd ld a,7 ; AY mixer channel out (c),a ld bc,0xbffd ld a,0x3f ; set all channels to 'muted' (always high) out (c),a ld bc,0xfffd ld a,8 ; volume channel A out (c),a ; start interrupts di ld a,0xbc ld i,a im 2 ei ld iy,sector_number ld l,(ix+4) ; retrieve initial-sector-count byte ld ixh,0xbe ; address of INI jump table xor a ; so that the initial OR L will test zero-ness of L jp next_frame ; start the loop! advance_sector ; increment sector ld hl,sector_number inc (hl) ret nz inc hl inc (hl) ret nz inc hl inc (hl) ret nz inc hl inc (hl) ret set_sector_number ld ix,sector_number ld a,(ix) out (0xaf),a ld a,(ix+1) out (0xb3),a ld a,(ix+2) out (0xb7),a ld a,(ix+3) out (0xbb),a ret highlight_video ld a,(video_number) or 0xc0 ld l,a ld h,0x02 add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl ld b,32 highlight_vid_lp set 6,(hl) inc hl djnz highlight_vid_lp ret unhighlight_video ld a,(video_number) or 0xc0 ld l,a ld h,0x02 add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl ld b,32 unhighlight_vid_lp res 6,(hl) inc hl djnz unhighlight_vid_lp ret sector_number db 0,0,0,0 signature db "DivIDEog",1 signature_end next_video_ptr ; where in video_offsets to place the next one dw 0 video_number ; currently selected video index db 0 video_count db 0 video_offsets ds 24*8 sector_buffer ds 512 ; null interrupt routine org 0xbbbb ei ret ; interrupt table org 0xbc00 rept 257 db 0xbb endm org 0xbd80 exit im 1 ld bc,0x7ffd ld a,0x10 out (c),a ret next_frame or l jr z,exit out (0xab),a ; sector count register ld a,(iy+0) out (0xaf),a ; LBA 0..7 add a,l ld (iy+0),a ld a,(iy+1) out (0xb3),a ; LBA 8..15 adc a,0 ld (iy+1),a ld a,(iy+2) out (0xb7),a ; LBA 16..23 adc a,0 ld (iy+2),a ld a,(iy+3) out (0xbb),a ; LBA 24..28 adc a,0 ld (iy+3),a ld a,0x20 ; command for READ SECTORS out (0xbf),a ; xor a ; border colour change - use for debugging ; out (254),a halt ; ld a,2 ; out (254),a video_page ld a,0x17 xor 0x0a ; toggle between page 5 shown/page 7 in memory and page 7 shown/page 5 in memory ld (video_page+1),a ld bc,0x7ffd out (c),a ld c,0xa3 ; IDE data register ld e,0x3f ; used to reset B register out of contended port ranges jp wait_ready_2 ; entry point to reading chunks org 0xbe00 jr next_frame rept 126 ini endm wait_ready_2 in a,(0xbf) ; wait for 'ready' status ; T=11 add a,a ; test bit 7; will carry if set (meaning not ready) ; T=4 jr c,wait_ready_2 ; T=7 (most of the time the branch won't be taken) in l,(c) ; read address (or number of sectors in next frame) ; T=12 in h,(c) ; T=12 in a,(0xa3) ; read delta length (or 0 for next frame); T=11 ld ixl,a ; T=8 (assuming it's four more than LD L,A) ld b,e ; ensures b is in range 0..63 (provided delta is length <64), avoiding contended port reads ; T=4 ; sample playback in a,(c) ; returns 10x0nnnn where nnnn = sample volume ; T=12 (in a,(0xa3) would be 11 tstates but previous value of A is likely to be >0xc0 and therefore a contended port read out (0xfd),a ; AY chip is preconfigured to write to register 8 ; T=11 jp (ix) ; T=8 ; Tstates per packet = 100+INIs (say 18.625T each, if there's an average of 2.625T contention)