use32 org 0x0 db 'MENUET01' ; 8 byte id dd 38 ; required os dd STARTAPP ; program start dd I_END ; program image size dd 0x100000 ; required amount of memory dd 0x100000 ; reserved= extended header dd filename, 0x0 ; I_Param , I_Icon include "aspAPI.inc" ;Clock_Hz equ 4608 ; Frequency of clock ;Monitor_Hz equ 70 ; Frequency of monitor ;Clock_Scale equ Clock_Hz / Monitor_Hz CData equ 0x40 ; Port number of timer 0 CMode equ 0x43 ; Port number of timer control word BufSize equ 65528 ; Frame buffer size - Must be even struc MainHeaderRec { .Padding1 dd ? ; size of the file .ID dw ? ; magic .Frames dw ? ; frames .Padding2 dd ? ; width/height .Padding3 dd ? ; depth/flags .Speed dw ? ; speed .Reserv dw ? ; always = 0 ; Only for FLC .Created dd ? ; date file attribute .Creator dd ? ; creator serial number .Updated dd ? ; date of the last change .Updater dd ? ; updater serial number .Aspectx dw ? ; scale by x .Aspecty dw ? ; scale by Y .Padding4 db 38 dup(?) ; Reserved. All zeroes. .Oframe1 dd ? ; offset to the 1st frame .Oframe2 dd ? ; offset to the 2nd frame .Padding5 db 40 dup(?) ; Reserved. All zeroes. } struc FrameHeaderRec { .Size dd ? ; size .Padding1 dw ? ; magic .Chunks dw ? ; chunks .Padding2 db 8 dup(?) ;Pad to 16 Bytes. All zeroes. } ; in: esi = pointer to the buffer DrawFrame: ; this is the routine that takes a frame and put it on the screen @Fli_Loop: ; main loop that goes through all the chunks in a frame cmp word [Chunks],0 ;are there any more chunks to draw? je @Exit dec word [Chunks] ;decrement Chunks For the chunk to process now mov ax, word [esi+4] ; let AX have the ChunkType add esi, 6 ; skip the ChunkHeader cmp ax, 0Bh ; is it a FLI_COLor chunk? je @Fli_Color cmp ax, 0Ch ; is it a FLI_LC chunk? je @Fli_Lc cmp ax, 0Dh ; is it a FLI_BLACK chunk? je @Fli_Black cmp ax, 0Fh ; is it a FLI_BRUN chunk? je @Fli_Brun cmp ax, 10h ; is it a FLI_COPY chunk? je @Fli_Copy jmp @Fli_Loop ; This command should not be necessary @Fli_Color: mov bx, word [esi] ; number of packets in this chunk (always 1?) add esi, 2 ; skip the NumberofPackets ;_________________________________________________________________________________________ mov al, 0 ; start at color 0 xor cx, cx ; reset CX @Color_Loop: or bx, bx ; set flags jz @Fli_Loop ; Exit if no more packages dec bx ; decrement NumberofPackages For the package to process now mov cl, byte [esi] ; first Byte in packet tells how many colors to skip add al, cl ; add the skiped colors to the start to get the new start mov edi, pal add di, cx ;push cx ;----- save how many colors to skip -----> mov cl, byte [esi+1] ; next Byte in packet tells how many colors to change or cl, cl ; set the flags jnz @Jump_Over ; if NumberstoChange=0 then NumberstoChange=256 inc ch ; CH=1 and CL=0 => CX=256 @Jump_Over: ;add al, cl ; update the color to start at add esi, 2 ; skip the NumberstoSkip and NumberstoChange Bytes .set_next_color: lodsb ; B shl al, 2 ; Enlight the color r*4, g*4, b*4 push ax lodsb ; G shl al, 2 ; Enlight the color r*4, g*4, b*4 push ax lodsb ; R shl al, 2 ; Enlight the color r*4, g*4, b*4 stosb ; R pop ax stosb ; G pop ax stosb ; B xor al, al stosb ; 0 loop .set_next_color jmp @Color_Loop ; finish With this packet - jump back @Fli_Lc: mov di, word [esi] ; put LinestoSkip into DI - mov ax, di ; - to get the offset address to this line we have to multiply With 320 - shl ax, 8 ; - DI = old_DI shl 8 + old_DI shl 6 - shl di, 6 ; - it is the same as DI = old_DI*256 + old_DI*64 = old_DI*320 - add di, ax ; - but this way is faster than a plain mul add edi, dword [image] mov bx, word [esi+2] ; put LinestoChange into BX add esi, 4 ; skip the LinestoSkip and LinestoChange Words xor cx, cx ; reset cx @Line_Loop: or bx, bx ; set flags jz @Fli_Loop ; Exit if no more lines to change dec bx mov dl, byte [esi] ; put PacketsInLine into DL inc esi ; skip the PacketsInLine Byte push edi ; save the offset address of this line @Pack_Loop: or dl, dl ; set flags jz @Next_Line ; Exit if no more packets in this line dec dl mov cl, byte [esi] ; put BytestoSkip into CL add di, cx ; update the offset address mov cl, byte [esi+1] ; put BytesofDatatoCome into CL or cl, cl ; set flags jns @Copy_Bytes ; no SIGN means that CL number of data is to come - ; - else the next data should be put -CL number of times mov al, byte [esi+2] ; put the Byte to be Repeated into AL add esi, 3 ; skip the packet neg cl ; Repeat -CL times rep stosb jmp @Pack_Loop ; finish With this packet @Copy_Bytes: add esi, 2 ; skip the two count Bytes at the start of the packet rep movsb jmp @Pack_Loop ; finish With this packet @Next_Line: pop edi ; restore the old offset address of the current line add edi, 320 ; offset address to the next line jmp @Line_Loop @Fli_Black: mov edi, dword [image] mov cx, 32000 ; number of Words in a screen xor ax, ax ; color 0 is to be put on the screen rep stosw jmp @Fli_Loop ; jump back to main loop @Fli_Brun: mov edi, dword [image] mov bx, 200 ; numbers of lines in a screen xor cx, cx @Line_Loop2: mov dl, byte [esi] ; put PacketsInLine into DL inc esi ; skip the PacketsInLine Byte push edi ; save the offset address of this line @Pack_Loop2: or dl, dl ; set flags jz @Next_Line2 ; Exit if no more packets in this line dec dl mov cl, byte [esi] ; put BytesofDatatoCome into CL or cl, cl ; set flags js @Copy_Bytes2 ; SIGN meens that CL number of data is to come - ; - else the next data should be put -CL number of times mov al, byte [esi+1] ; put the Byte to be Repeated into AL add esi, 2 ; skip the packet rep stosb jmp @Pack_Loop2 ; finish With this packet @Copy_Bytes2: inc esi ; skip the count Byte at the start of the packet neg cl ; Repeat -CL times rep movsb jmp @Pack_Loop2 ; finish With this packet @Next_Line2: pop edi ; restore the old offset address of the current line add edi, 320 ; offset address to the next line dec bx ; any more lines to draw? jnz @Line_Loop2 jmp @Fli_Loop ; jump back to main loop @Fli_Copy: mov edi, dword [image] mov cx, 32000 ; number of Words in a screen rep movsw jmp @Fli_Loop ; jump back to main loop @Exit: mov eax, 65 mov ebx, dword [image] mov ecx, 320*65536+200 mov edx, 10*65536+100 mov esi, 8 mov edi, pal xor ebp, ebp int 0x40 ret ; DrawFrame end. TFliPlayer_Init: mov eax, 68 ; Init process memory mov ebx, 11 int 0x40 cmp eax, BufSize jl .fail .ok: ;GetMem(Buffer,BufSize); mov eax, 68 mov ebx, 12 mov ecx, BufSize int 0x40 mov dword [Buffer], eax ;GetMem(image,32000); mov eax, 68 mov ebx, 12 mov ecx, 320*200*4 ;32000 int 0x40 mov dword [image], eax mov word [Interval], -1 ; ClearSpeed mov ax, 1 ret .fail: xor ax, ax ret ; TFliPlayer_Init end. TFliPlayer_Done: ;FreeMem(Buffer,BufSize); mov eax, 68 mov ebx, 13 mov ecx, dword [Buffer] int 0x40 ;FreeMem(image,32000); mov eax, 68 mov ebx, 13 mov ecx, dword [image] int 0x40 ret ; TFliPlayer_Done end. ; in: ax = Speed ;TFliPlayer_SetSpeed: ; mov bl, byte Clock_Scale ; mul bl ; mov word [Interval], ax ;= Speed * Clock_Scale; ; ret ; TFliPlayer_SetSpeed end. ReadHeader: ;Boolean; ;BlockRead(FliFile,MainHeader,SizeOf(MainHeader)) ; Read header record mov eax, dword [filepos] mov dword [InfoStructure+4], eax mov dword [InfoStructure+12], 128 mov dword [InfoStructure+16], MainHeader mov eax, 70 mov ebx, InfoStructure int 0x40 mov eax, 128 mov dword [filepos], eax mov ax, word [MainHeader.ID] cmp ax, 0xAF11 ; FLI ? je .fli cmp ax, 0xAF12 ; FLC ? je .flc xor ax, ax ; Not a .FLI File ret .fli: mov byte [filetype], 1 jmp .ok .flc: mov byte [filetype], 2 .ok: ; cmp word [Interval], -1 ; jne @f ; ; Read speed from header ; mov ax, word [MainHeader.Speed] ; mov bl, byte Clock_Scale ; mul bl ; mov word [Interval], ax ;= Speed * Clock_Scale; mov ax, 1 ; @@: ret ; ReadHeader end. ReadFrame: ;BlockRead(FliFile,FrameHeader,SizeOf(FrameHeader)); mov eax, dword [filepos] mov dword [InfoStructure+4], eax mov dword [InfoStructure+12], 16 mov dword [InfoStructure+16], FrameHeader mov eax, 70 mov ebx, InfoStructure int 0x40 add dword [filepos], 16 ;FrameSize := FrameHeader.Size - SizeOf(FrameHeader); mov eax, dword [FrameHeader.Size] sub eax, 16 mov dword [FrameSize], eax xor ecx, ecx ret ; ReadFrame end. ProcessFrame: ;BlockRead(FliFile,Buffer^,FrameSize); mov eax, dword [filepos] mov dword [InfoStructure+4], eax mov eax, dword [FrameSize] mov dword [InfoStructure+12], eax mov eax, dword [Buffer] mov dword [InfoStructure+16], eax mov eax, 70 mov ebx, InfoStructure int 0x40 mov eax, dword [FrameSize] add dword [filepos], eax mov esi, dword [Buffer] mov dx, word [FrameHeader.Chunks] mov word [Chunks], dx call DrawFrame ret ; ProcessFrame end. ; in: esi = pointer to the filename TFliPlayer_Play: mov eax, 70 mov ebx, InfoStructure mov dword [InfoStructure+12], 1 mov dword [InfoStructure+16], FrameHeader int 0x40 test ax, ax jnz .err call ReadHeader test ax, ax jz .err call ReadFrame mov eax, dword [FrameSize] add eax, 128+16 mov dword [RestartPos], eax call ProcessFrame .play_again: mov word [Frame], 1 .show_next_frame: call ReadFrame cmp dword [FrameSize], 0 je @f call ProcessFrame @@: ;REPEAT UNTIL GetClock > Timeout; mov eax, 5 mov ebx, 2 int 0x40 push edi call process_events pop edi mov al, byte [stop] cmp al, 1 je .end mov ax, word [Frame] inc ax mov word [Frame], ax cmp ax, word [MainHeader.Frames] jng .show_next_frame mov eax, dword [RestartPos] mov dword [InfoStructure+4], eax mov eax, 128 mov dword [filepos], eax jmp .play_again .end: mov dword [filepos], 0 xor ax, ax .err: ret ; TFliPlayer_Play end. ; in: esi = pointer to filename AAPlay: mov byte [pausetime], 0 mov byte [stop], 0 cmp byte [playtime], 1 je .end call unprint_error mov byte [playtime], 1 call TFliPlayer_Play test ax, ax jz .end call print_error .end: mov byte [playtime], 0 ret ; AAPlay end. N_KEYCOLOR equ 0x00444444 ; Normal button color TEXTCOLOR equ 0x80FFFFFF ; Text color BUTCAPCOLOR equ 0x0000FF00 ; Button caption color unprint_error: mov eax, 13 mov ebx, 10*65536+320 mov ecx, 50*65536+15 mov edx, 0 ; color int 0x40 ret print_error: ;call unprint_error mov ebx, 15*65536+54 mov edx, error_text mov ecx, TEXTCOLOR - 0x0000FFFF mov eax, 4 int 0x40 ret print_filename: mov eax, 13 mov ebx, 10*65536+320 mov ecx, 30*65536+15 mov edx, 0 ; color int 0x40 mov ebx, 15*65536+34 mov edx, filename mov ecx, TEXTCOLOR - 0x00FF00FF mov eax, 4 int 0x40 ret ;********************************** ;* input: ecx = type of map * ;********************************** get_keyboard_map: mov eax, 26 mov ebx, 2 mov edx, keymap int 0x40 ret ;********************************** ;* input: ecx = type of mode * ;********************************** set_keyboard_mode: mov eax, 66 mov ebx, 1 ; Set keyboard mode int 0x40 ret get_control_keys_state: mov eax, 66 mov ebx, 3 int 0x40 ret reload_ascii_keymap: pusha call get_control_keys_state mov ecx, 1 test ax, 1 ; Left Shift pressed ? jnz @f test ax, 2 ; Right Shift pressed ? jnz @f test ax, 0x40 ; Caps Lock on ? jz .load_ascii_keymap @@: mov ecx, 2 .load_ascii_keymap: call get_keyboard_map popa ret STARTAPP: call TFliPlayer_Init test ax, ax jz close_app mov ecx, 1 ; to send scancodes. call set_keyboard_mode call reload_ascii_keymap call draw_window call print_filename cmp [filename], byte 0 je .noparam call AAPlay .noparam: jmp still draw_window: start_draw_window 20,170,340,310,0x14224466,labelt draw_button 15,70,20,20,2,N_KEYCOLOR,keyText,1,BUTCAPCOLOR ; Play mov ecx, BUTCAPCOLOR mov edx, keyText mov ebx, 21*65536+77 ; | call out_symbol mov edx, keyText+1 mov ebx, 22*65536+75 ; - call out_symbol mov ebx, 24*65536+76 ; - @@: call out_symbol inc ebx cmp ebx, 24*65536+79 jl @b mov ebx, 22*65536+79 ; - call out_symbol mov ebx, 26*65536+77 ; - call out_symbol draw_button 45,70,20,20,3,N_KEYCOLOR,keyText,1,BUTCAPCOLOR ; Pause mov ecx, BUTCAPCOLOR mov edx, keyText mov ebx, 49*65536+77 ; | call out_symbol mov ebx, 51*65536+77 ; | call out_symbol mov ebx, 54*65536+77 ; | call out_symbol mov ebx, 55*65536+77 ; | call out_symbol mov ebx, 56*65536+77 ; | call out_symbol draw_button 75,70,20,20,4,N_KEYCOLOR,keyText,1,BUTCAPCOLOR ; Stop bar 81,77,8,7,BUTCAPCOLOR end_draw_window ret process_events: mov eax, 11 ; Test if there is an event in the queue. int 0x40 cmp eax,1 ; redraw request ? jnz @f call red ret @@: cmp eax,3 ; button in buffer ? jnz @f call button ret @@: cmp eax,2 ; key in buffer ? jnz @f call key @@: ;jz key ; cmp eax, 2 ; jnz @f ; ; cmp byte [playtime], 0 ; je @f ;int 0x40 ;@@: ret still: call process_events jmp still red: call draw_window ret ;jmp still key: mov eax, 2 int 0x40 test al, al jnz .end cmp ah, 1 ; Esc jne @f jmp close_app @@: cmp ah, 28 ; Enter jne @f call AAPlay jmp .end @@: cmp ah, 15 ; Tab je .end cmp ah, 29 ; Left Control je .end cmp ah, 42 ; Left Shift je .end cmp ah, 14 ; BackSpace jne @f ; strlen(filename) mov edi, filename xor al, al ; search for the end of the filename repne scasb cmp edi, filename+2 jl .end cmp edi, filename+2 jl .end mov byte [edi-2], 0 call print_filename jmp .end @@: cmp ah, 57 ; Space je .input_symbol cmp ah, 2 jl .end cmp ah, 54 jg .end .input_symbol: mov byte [stop], 1 call reload_ascii_keymap ; strlen(filename) mov edi, filename xor al, al ; search for the end of the filename repne scasb cmp edi, filename+52 jg .end shr ax, 8 and eax, 0x7F mov al, byte [keymap+eax] ; Read ASCII from the keymap table. mov byte [edi-1], al mov byte [edi], 0 call print_filename .end: ret button: mov eax, 17 ; Get pressed button code int 0x40 cmp ah, 1 ; Test x button je close_app cmp ah, 2 ; Test "Play" button jne @f call AAPlay jmp .end @@: cmp ah, 3 ; Test "Pause" button jne @f cmp byte [playtime], 1 jne @f not byte [pausetime] .pause: call process_events cmp byte [pausetime], 0 jne .pause @@: cmp ah, 4 ; Test "Stop" button jne @f mov byte [stop], 1 jne @f @@: .end: ret close_app: cmp dword [image], 0 je @f call TFliPlayer_Done @@: mov eax,-1 ; close this program int 0x40 ; DATA ; Application Title labelt db 'FLI Player v0.31',0 keyText db '|-_' error_text db "Can't load file.",0 filepos dd 0x0 filetype db 0 ; 0 - unsupported, 1 - fli, 2 - flc playtime db 0 pausetime db 0 stop db 0 pal rb 256*4 image dd 0 InfoStructure: dd 0x0 ; subfunction number dd filepos ; position in the file in bytes dd 0x0 ; upper part of the position address dd 0x0 ; number of bytes to read dd 0x0 ; pointer to the buffer to write data db 0 dd filename keymap rb 128 I_END: Buffer dd ? Interval dw ? Chunks dw ? FrameSize dd ? RestartPos dd ? Frame dw ? MainHeader MainHeaderRec FrameHeader FrameHeaderRec filename db '/hd0/2/',0 rb 46