0,0 → 1,784 |
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 |
|