home *** CD-ROM | disk | FTP | other *** search
- ; Generic assembler routines that have very little at all
- ; to do with fractals.
- ;
- ; (NOTE: The video routines have been moved over to VIDEO.ASM)
- ;
- ; ---- Overall Support
- ;
- ; initasmvars()
- ;
- ; ---- Quick-copy to/from Extraseg support
- ;
- ; toextra()
- ; fromextra()
- ; cmpextra()
- ;
- ; ---- far memory allocation support
- ;
- ; farmemalloc()
- ; farmemfree()
- ; erasesegment()
- ;
- ; ---- General Turbo-C (artificial) support
- ;
- ; disable()
- ; enable()
- ;
- ; ---- 32-bit Multiply/Divide Routines (includes 16-bit emulation)
- ;
- ; multiply()
- ; divide()
- ;
- ; ---- Keyboard, audio (and, hidden inside them, Mouse) support
- ;
- ; keypressed()
- ; getakey()
- ; buzzer()
- ; delay()
- ; tone()
- ; snd()
- ; nosnd()
- ;
- ; ---- Expanded Memory Support
- ;
- ; emmquery()
- ; emmgetfree()
- ; emmallocate()
- ; emmdeallocate()
- ; emmgetpage()
- ; emmclearpage()
- ;
- ; ---- Extended Memory Support
- ;
- ; xmmquery()
- ; xmmlongest()
- ; xmmallocate()
- ; xmmreallocate()
- ; xmmdeallocate()
- ; xmmmoveextended()
- ;
- ; ---- CPU, FPU Detectors
- ;
- ; cputype()
- ; fputype()
- ;
- ; ---- IIT FPU Support
- ;
- ; load_mat()
- ; mult_vec_iit()
- ; IITCoPro()
- ;
-
-
- ; required for compatibility if Turbo ASM
- IFDEF ??version
- MASM51
- QUIRKS
- ENDIF
-
- .MODEL medium,c
-
- .8086
-
- ; these must NOT be in any segment!!
- ; this get's rid of TURBO-C fixup errors
-
- extrn help:far ; help code (in help.c)
- extrn tab_display:far ; TAB display (in fractint.c)
- ; extrn restore_active_ovly:far
- extrn edit_text_colors:far
- extrn adapter_init:far ; video adapter init (in video.asm)
- extrn slideshw:far
- extrn recordshw:far
- extrn stopslideshow:far
-
- .DATA
-
- ; ************************ External variables *****************************
-
- extrn soundflag:word ; if 0, supress sounds
- extrn debugflag:word ; for debugging purposes only
- extrn helpmode:word ; help mode (AUTHORS is special)
- extrn tabmode:word ; tab key enabled?
- extrn sxdots:word ; horizontal pixels
- extrn timedsave:word ; triggers autosave
- extrn calc_status:word ; in calcfrac.c
- extrn got_status:word ; in calcfrac.c
- extrn currow:word ; in calcfrac.c
- extrn slides:word ; in cmdfiles.c
-
-
- ; ************************ Public variables *****************************
-
- public cpu ; used by 'calcmand'
- public fpu ; will be used by somebody someday
- public iit ; IIT fpu?
- public lookatmouse ; used by 'calcfrac'
- public saveticks ; set by fractint
- public savebase ; set by fractint
- public finishrow ; set by fractint
- public _dataseg_xx ; used by TARGA, other Turbo Code
-
- public extraseg ; extra 64K segment
-
- public overflow ; Mul, Div overflow flag: 0 means none
-
- ; arrays declared here, used elsewhere
- ; arrays not used simultaneously are deliberately overlapped
-
- public keybuffer ; needed for ungetakey
- public prefix, suffix, dstack, decoderline ; for the Decoder
- public tstack ; for the prompting routines
- public strlocn, teststring, block ; used by the Encoder
- public boxx, boxy, boxvalues ; zoom-box arrays
- public olddacbox ; temporary DAC saves
- public rlebuf ; Used ty the TARGA En/Decoder
- public paldata, stbuff ; 8514A arrays, (FR8514A.ASM)
-
- ; ************************* "Shared" array areas **************************
-
- ; Shared near arrays are discussed below. First some comments about "extraseg".
- ; It is a 96k far area permanently allocated during fractint runup.
- ; The first part is used for:
- ; 64k coordinate arrays during image calculation (initialized in fracsubr.c)
- ; 64k create gif save file, encoder.c
- ; 64k 3d transforms, line3d.c
- ; 64k credits screen, intro.c
- ; 22k video mode selection (for fractint.cfg, loadfdos, miscovl)
- ; 2k .frm .ifs .l .par entry selection and file selection (prompts.c)
- ; ??k printing, printer.c
- ; ??k fractint.doc creation, help.c, not important cause it saves/restores
- ; 64K arbitrary precision - critical variables at top, safe from encoder
- ; 10K cmdfiles.c input buffer
- ; 4K miscovl.c PAR file buffer
- ;
- ; The high 32k is used for graphics image save during text mode; video.asm
- ; and realdos.c.
-
- ; Short forms used in subsequent comments:
- ; name........duration of use......................modules....................
- ; encoder "s"aving an image encoder.c
- ; decoder "r"estoring an image decoder.c, gifview.c
- ; zoom zoom box is visible zoom.c, video.asm
- ; vidswitch temp during video mode setting video.asm
- ; 8514a 8514a is in use (graphics only?) fr8514a.asm
- ; tgaview restore of tga image tgaview.c
- ; solidguess image gen with "g", not to disk calcfrac.c
- ; btm image gen with "b", not to disk calcfrac.c
- ; editpal palette editor "heap" editpal.c
- ; cellular cellular fractal type generation misfrac.c
- ; browse browsing loadfile.c
- ; lsystem lsystem fractal type generation lsys.c, lsysf.c, lsysa.asm, lsysaf.asm
- ; Several arrays used in cmdfiles.c and miscovl.c, but are saved and
- ; restored to extraseg so not critical.
- ;
- ; Note that decoder using an 8514a is worst case, uses all arrays at once.
- ; Keep db lengths even so that word alignment is preserved for speed.
-
- block label byte ; encoder(266)
- suffix dw 2048 dup(0) ; decoder(4k), vidswitch(256),
- ; savegraphics/restoregraphics(4k)
-
- tstack label byte ; prompts(4k), ifsload(4k),
- ; make_batch(4k)
- teststring label byte ; encoder(100)
- olddacbox label byte ; fractint(768), prompts(768)
- dstack dw 2048 dup(0) ; decoder(4k), solidguess(4k), btm(2k)
- ; zoom(2k), printer(2400)
- ; loadfdos(2000), cellular(2025)
-
- strlocn label word ; encoder(10k), editpal(10k)
- prefix label word ; decoder(8k), solidguess(6k)
- boxx dw 2048 dup(0) ; zoom(4k), tgaview(4k), prompts(9k)
- ; make_batch(8k), parser(8k)
- ; browse(?)
- boxy dw 2048 dup(0) ; zoom(4k), cellular(2025), browse(?)
- ; lsystem(1000)
- boxvalues label byte ; zoom(2k), browse(?)
- decoderline db 2050 dup(0) ; decoder(2049), btm(2k)
-
- rlebuf label byte ; f16.c(258) .tga save/restore?
- paldata db 1024 dup(0) ; 8514a(1k)
- stbuff db 415 dup(0) ; 8514a(415)
-
- ; ************************ Internal variables *****************************
-
- align 2
- cpu dw 0 ; cpu type: 86, 186, 286, or 386
- fpu dw 0 ; fpu type: 0, 87, 287, 387
- iit dw 0 ; iit fpu: 0=no, 1=yes
- _dataseg_xx dw 0 ; our "near" data segment
-
- overflow dw 0 ; overflow flag
-
- kbd_type db 0 ; type of keyboard
- align 2
- keybuffer dw 0 ; real small keyboard buffer
-
- delayloop dw 32 ; delay loop value
- delaycount dw 0 ; number of delay "loops" per ms.
-
- extraseg dw 0 ; extra 64K segment (allocated by init)
-
- ; ********************** Mouse Support Variables **************************
-
- lookatmouse dw 0 ; see notes at mouseread routine
- prevlamouse dw 0 ; previous lookatmouse value
- mousetime dw 0 ; time of last mouseread call
- mlbtimer dw 0 ; time of left button 1st click
- mrbtimer dw 0 ; time of right button 1st click
- mhtimer dw 0 ; time of last horiz move
- mvtimer dw 0 ; time of last vert move
- mhmickeys dw 0 ; pending horiz movement
- mvmickeys dw 0 ; pending vert movement
- mbstatus db 0 ; status of mouse buttons
- mouse db 0 ; == -1 if/when a mouse is found.
- mbclicks db 0 ; had 1 click so far? &1 mlb, &2 mrb
-
- align 2
- ; timed save variables, handled by readmouse:
- savechktime dw 0 ; time of last autosave check
- savebase dw 2 dup(0) ; base clock ticks
- saveticks dw 2 dup(0) ; save after this many ticks
- finishrow dw 0 ; save when this row is finished
-
-
- .CODE
-
- ; *************** Function toextra(tooffset,fromaddr, fromcount) *********
-
- toextra proc uses es di si, tooffset:word, fromaddr:word, fromcount:word
- cld ; move forward
- mov ax,extraseg ; load ES == extra segment
- mov es,ax ; ..
- mov di,tooffset ; load to here
- mov si,fromaddr ; load from here
- mov cx,fromcount ; this many bytes
- rep movsb ; do it.
- ret ; we done.
- toextra endp
-
-
- ; *************** Function fromextra(fromoffset, toaddr, tocount) *********
-
- fromextra proc uses es di si, fromoffset:word, toaddr:word, tocount:word
- push ds ; save DS for a tad
- pop es ; restore it to ES
- cld ; move forward
- mov si,fromoffset ; load from here
- mov di,toaddr ; load to here
- mov cx,tocount ; this many bytes
- mov ax,extraseg ; load DS == extra segment
- mov ds,ax ; ..
- rep movsb ; do it.
- push es ; save ES again.
- pop ds ; restore DS
- ret ; we done.
- fromextra endp
-
-
- ; *************** Function cmpextra(cmpoffset,cmpaddr, cmpcount) *********
-
- cmpextra proc uses es di si, cmpoffset:word, cmpaddr:word, cmpcount:word
- cld ; move forward
- mov ax,extraseg ; load ES == extra segment
- mov es,ax ; ..
- mov di,cmpoffset ; load to here
- mov si,cmpaddr ; load from here
- mov cx,cmpcount ; this many bytes
- rep cmpsb ; do it.
- jnz cmpbad ; failed.
- sub ax,ax ; 0 == true
- jmp short cmpend
- cmpbad:
- mov ax,1 ; 1 == false
- cmpend:
- ret ; we done.
- cmpextra endp
-
-
- ; =======================================================
- ;
- ; 32-bit integer multiply routine with an 'n'-bit shift.
- ; Overflow condition returns 0x7fffh with overflow = 1;
- ;
- ; long x, y, z, multiply();
- ; int n;
- ;
- ; z = multiply(x,y,n)
- ;
- ; requires the presence of an external variable, 'cpu'.
- ; 'cpu' == 386 if a 386 is present.
-
- .8086
-
- .DATA
-
- temp dw 5 dup(0) ; temporary 64-bit result goes here
- sign db 0 ; sign flag goes here
-
- .CODE
-
- FRAME MACRO regs
- push bp
- mov bp, sp
- IRP reg, <regs>
- push reg
- ENDM
- ENDM
-
- UNFRAME MACRO regs
- IRP reg, <regs>
- pop reg
- ENDM
- pop bp
- ENDM
-
-
- multiply proc x:dword, y:dword, n:word
-
- cmp cpu,386 ; go-fast time?
- jne slowmultiply ; no. yawn...
-
- .386 ; 386-specific code starts here
-
- mov eax,x ; load X into EAX
- imul y ; do the multiply
- mov cx,n ; set up the shift
- cmp cx,32 ; ugly klooge: check for 32-bit shift
- jb short fastm1 ; < 32 bits: no problem
- mov eax,edx ; >= 32 bits: manual shift
- mov edx,0 ; ...
- sub cx,32 ; ...
- fastm1: shrd eax,edx,cl ; shift down 'n' bits
- js fastm3
- sar edx,cl
- jne overmf
- shld edx,eax,16
- ret
- fastm3: sar edx,cl
- inc edx
- jne overmf
- shld edx,eax,16
- ret
- overmf:
- mov ax,0ffffh ; overflow value
- mov dx,07fffh ; overflow value
- mov overflow,1 ; flag overflow
- ret
-
- .8086 ; 386-specific code ends here
-
- slowmultiply: ; (sigh) time to do it the hard way...
- push di
- push si
- push es
-
- mov ax,0
- mov temp+4,ax ; first, zero out the (temporary)
- mov temp+6,ax ; result
- mov temp+8,ax
-
- les bx,x ; move X to SI:BX
- mov si,es ; ...
- les cx,y ; move Y to DI:CX
- mov di,es ; ...
-
- mov sign,0 ; clear out the sign flag
- cmp si,0 ; is X negative?
- jge mults1 ; nope
- not sign ; yup. flip signs
- not bx ; ...
- not si ; ...
- stc ; ...
- adc bx,ax ; ...
- adc si,ax ; ...
- mults1: cmp di,0 ; is DI:CX negative?
- jge mults2 ; nope
- not sign ; yup. flip signs
- not cx ; ...
- not di ; ...
- stc ; ...
- adc cx,ax ; ...
- adc di,ax ; ...
- mults2:
-
- mov ax,bx ; perform BX x CX
- mul cx ; ...
- mov temp,ax ; results in lowest 32 bits
- mov temp+2,dx ; ...
-
- mov ax,bx ; perform BX x DI
- mul di ; ...
- add temp+2,ax ; results in middle 32 bits
- adc temp+4,dx ; ...
- jnc mults3 ; carry bit set?
- inc word ptr temp+6 ; yup. overflow
- mults3:
-
- mov ax,si ; perform SI * CX
- mul cx ; ...
- add temp+2,ax ; results in middle 32 bits
- adc temp+4,dx ; ...
- jnc mults4 ; carry bit set?
- inc word ptr temp+6 ; yup. overflow
- mults4:
-
- mov ax,si ; perform SI * DI
- mul di ; ...
- add temp+4,ax ; results in highest 32 bits
- adc temp+6,dx ; ...
-
- mov cx,n ; set up for the shift loop
- cmp cx,24 ; shifting by three bytes or more?
- jl multc1 ; nope. check for something else
- sub cx,24 ; quick-shift 24 bits
- mov ax,temp+3 ; load up the registers
- mov dx,temp+5 ; ...
- mov si,temp+7 ; ...
- mov bx,0 ; ...
- jmp short multc4 ; branch to common code
- multc1: cmp cx,16 ; shifting by two bytes or more?
- jl multc2 ; nope. check for something else
- sub cx,16 ; quick-shift 16 bits
- mov ax,temp+2 ; load up the registers
- mov dx,temp+4 ; ...
- mov si,temp+6 ; ...
- mov bx,0 ; ...
- jmp short multc4 ; branch to common code
- multc2: cmp cx,8 ; shifting by one byte or more?
- jl multc3 ; nope. check for something else
- sub cx,8 ; quick-shift 8 bits
- mov ax,temp+1 ; load up the registers
- mov dx,temp+3 ; ...
- mov si,temp+5 ; ...
- mov bx,temp+7 ; ...
- jmp short multc4 ; branch to common code
- multc3: mov ax,temp ; load up the regs
- mov dx,temp+2 ; ...
- mov si,temp+4 ; ...
- mov bx,temp+6 ; ...
- multc4: cmp cx,0 ; done shifting?
- je multc5 ; yup. bail out
-
- multloop:
- shr bx,1 ; shift down 1 bit, cascading
- rcr si,1 ; ...
- rcr dx,1 ; ...
- rcr ax,1 ; ...
- loop multloop ; try the next bit, if any
- multc5:
- cmp si,0 ; overflow time?
- jne overm1 ; yup. Bail out.
- cmp bx,0 ; overflow time?
- jne overm1 ; yup. Bail out.
- cmp dx,0 ; overflow time?
- jl overm1 ; yup. Bail out.
-
- cmp sign,0 ; should we negate the result?
- je mults5 ; nope.
- not ax ; yup. flip signs.
- not dx ; ...
- mov bx,0 ; ...
- stc ; ...
- adc ax,bx ; ...
- adc dx,bx ; ...
- mults5:
- jmp multiplyreturn
-
- overm1:
- mov ax,0ffffh ; overflow value
- mov dx,07fffh ; overflow value
- mov overflow,1 ; flag overflow
-
- multiplyreturn: ; that's all, folks!
- pop es
- pop si
- pop di
- ret
- multiply endp
-
-
- ; =======================================================
- ;
- ; 32-bit integer divide routine with an 'n'-bit shift.
- ; Overflow condition returns 0x7fffh with overflow = 1;
- ;
- ; long x, y, z, divide();
- ; int n;
- ;
- ; z = divide(x,y,n); /* z = x / y; */
- ;
- ; requires the presence of an external variable, 'cpu'.
- ; 'cpu' == 386 if a 386 is present.
-
-
- .8086
-
- divide proc uses di si es, x:dword, y:dword, n:word
-
- cmp cpu,386 ; go-fast time?
- jne slowdivide ; no. yawn...
-
- .386 ; 386-specific code starts here
-
- mov edx,x ; load X into EDX (shifts to EDX:EAX)
- mov ebx,y ; load Y into EBX
-
- mov sign,0 ; clear out the sign flag
- cmp edx,0 ; is X negative?
- jge short divides1 ; nope
- not sign ; yup. flip signs
- neg edx ; ...
- divides1:
- cmp ebx,0 ; is Y negative?
- jge short divides2 ; nope
- not sign ; yup. flip signs
- neg ebx ; ...
- divides2:
-
- mov eax,0 ; clear out the low-order bits
- mov cx,32 ; set up the shift
- sub cx,n ; (for large shift counts - faster)
- fastd1: cmp cx,0 ; done shifting?
- je fastd2 ; yup.
- shr edx,1 ; shift one bit
- rcr eax,1 ; ...
- loop fastd1 ; and try again
- fastd2:
- cmp edx,ebx ; umm, will the divide blow out?
- jae overd1 ; yup. better skip it.
- div ebx ; do the divide
- cmp eax,0 ; did the sign flip?
- jl overd1 ; then we overflowed
- cmp sign,0 ; is the sign reversed?
- je short divides3 ; nope
- neg eax ; flip the sign
- divides3:
- push eax ; save the 64-bit result
- pop ax ; low-order 16 bits
- pop dx ; high-order 16 bits
- jmp dividereturn ; back to common code
-
- .8086 ; 386-specific code ends here
-
- slowdivide: ; (sigh) time to do it the hard way...
-
- les ax,x ; move X to DX:AX
- mov dx,es ; ...
-
- mov sign,0 ; clear out the sign flag
- cmp dx,0 ; is X negative?
- jge divides4 ; nope
- not sign ; yup. flip signs
- not ax ; ...
- not dx ; ...
- stc ; ...
- adc ax,0 ; ...
- adc dx,0 ; ...
- divides4:
-
- mov cx,32 ; get ready to shift the bits
- sub cx,n ; (shift down rather than up)
- mov byte ptr temp+4,cl ; ...
-
- mov cx,0 ; clear out low bits of DX:AX:CX:BX
- mov bx,0 ; ...
-
- cmp byte ptr temp+4,16 ; >= 16 bits to shift?
- jl dividex0 ; nope
- mov bx,cx ; yup. Take a short-cut
- mov cx,ax ; ...
- mov ax,dx ; ...
- mov dx,0 ; ...
- sub byte ptr temp+4,16 ; ...
- dividex0:
- cmp byte ptr temp+4,8 ; >= 8 bits to shift?
- jl dividex1 ; nope
- mov bl,bh ; yup. Take a short-cut
- mov bh,cl ; ...
- mov cl,ch ; ...
- mov ch,al ; ...
- mov al,ah ; ...
- mov ah,dl ; ...
- mov dl,dh ; ...
- mov dh,0 ; ...
- sub byte ptr temp+4,8 ; ...
- dividex1:
- cmp byte ptr temp+4,0 ; are we done yet?
- je dividex2 ; yup
- shr dx,1 ; shift all 64 bits
- rcr ax,1 ; ...
- rcr cx,1 ; ...
- rcr bx,1 ; ...
- dec byte ptr temp+4 ; decrement the shift counter
- jmp short dividex1 ; and try again
- dividex2:
-
- les di,y ; move Y to SI:DI
- mov si,es ; ...
-
- cmp si,0 ; is Y negative?
- jge divides5 ; nope
- not sign ; yup. flip signs
- not di ; ...
- not si ; ...
- stc ; ...
- adc di,0 ; ...
- adc si,0 ; ...
- divides5:
-
- mov byte ptr temp+4,33 ; main loop counter
- mov temp,0 ; results in temp
- mov word ptr temp+2,0 ; ...
-
- dividel1:
- shl temp,1 ; shift the result up 1
- rcl word ptr temp+2,1 ; ...
- cmp dx,si ; is DX:AX >= Y?
- jb dividel3 ; nope
- ja dividel2 ; yup
- cmp ax,di ; maybe
- jb dividel3 ; nope
- dividel2:
- cmp byte ptr temp+4,32 ; overflow city?
- jge overd1 ; yup.
- sub ax,di ; subtract Y
- sbb dx,si ; ...
- inc temp ; add 1 to the result
- adc word ptr temp+2,0 ; ...
- dividel3:
- shl bx,1 ; shift all 64 bits
- rcl cx,1 ; ...
- rcl ax,1 ; ...
- rcl dx,1 ; ...
- dec byte ptr temp+4 ; time to quit?
- jnz dividel1 ; nope. try again.
-
- mov ax,temp ; copy the result to DX:AX
- mov dx,word ptr temp+2 ; ...
- cmp sign,0 ; should we negate the result?
- je divides6 ; nope.
- not ax ; yup. flip signs.
- not dx ; ...
- mov bx,0 ; ...
- stc ; ...
- adc ax,0 ; ...
- adc dx,0 ; ...
- divides6:
- jmp short dividereturn
-
- overd1:
- mov ax,0ffffh ; overflow value
- mov dx,07fffh ; overflow value
- mov overflow,1 ; flag overflow
-
- dividereturn: ; that's all, folks!
- ret
- divide endp
-
-
- ; ****************** Function getakey() *****************************
- ; **************** Function keypressed() ****************************
-
- ; 'getakey()' gets a key from either a "normal" or an enhanced
- ; keyboard. Returns either the vanilla ASCII code for regular
- ; keys, or 1000+(the scan code) for special keys (like F1, etc)
- ; Use of this routine permits the Control-Up/Down arrow keys on
- ; enhanced keyboards.
- ;
- ; The concept for this routine was "borrowed" from the MSKermit
- ; SCANCHEK utility
- ;
- ; 'keypressed()' returns a zero if no keypress is outstanding,
- ; and the value that 'getakey()' will return if one is. Note
- ; that you must still call 'getakey()' to flush the character.
- ; As a sidebar function, calls 'help()' if appropriate, or
- ; 'tab_display()' if appropriate.
- ; Think of 'keypressed()' as a super-'kbhit()'.
-
- keypressed proc
- call far ptr getkeynowait ; check for key
- jc keypressed1 ; got a key
- sub ax,ax ; fast no-key return
- ret
- keypressed1:
- FRAME <di,si,es> ; std frame, for TC++ overlays
- mov keybuffer,ax ; remember it for next time
- cmp ax,1059 ; help called?
- jne keypressed2 ; no help asked for.
- cmp helpmode,0 ; help enabled?
- jl keypressedx ; nope.
- mov keybuffer,0 ; say no key hit
- xor ax,ax
- push ax
- call far ptr help ; help!
- pop ax
- ; call far ptr restore_active_ovly ; help might've clobbered ovly
- sub ax,ax
- jmp short keypressedx
- keypressed2:
- cmp ax,9 ; TAB key hit?
- je keypressed3 ; yup. TAB display.
- cmp ax,1148 ; CTL_TAB key hit?
- je keypressed3 ; yup. TAB display.
- jmp keypressedx ; nope. no TAB display.
- keypressed3:
- cmp tabmode,0 ; tab enabled?
- je keypressedx ; nope
- mov keybuffer,0 ; say no key hit
- call far ptr tab_display ; show the TAB status
- ; call far ptr restore_active_ovly ; tab might've clobbered ovly
- sub ax,ax
- keypressedx:
- UNFRAME <es,si,di> ; pop frame
- ret
- keypressed endp
-
- getakeynohelp proc
- gknhloop:
- call far ptr getakey ; get keystroke
- cmp ax,1059 ; help key?
- je gknhloop ; ignore help, none available
- ret
- getakeynohelp endp
-
- getakey proc
- cmp soundflag,1 ; is the sound on?
- jl getakeyloop ; ok, sound is off
- call far ptr nosnd ; turn off sound
- getakeyloop:
- call far ptr getkeynowait ; check for keystroke
- jnc getakeyloop ; no key, loop till we get one
- ret
- getakey endp
-
- getkeynowait proc
- FRAME <di,si,es> ; std frame, for TC++ overlays
- getkeyn0:
- cmp keybuffer,0 ; got a key buffered?
- je getkeynobuf ; nope
- mov ax,keybuffer ; key was buffered here
- mov keybuffer,0 ; clear buffer
- jmp getkeyyup ; exit with the key
- getkeynobuf:
- call mouseread ; mouse activity or savetime?
- jc getkeyn4 ; yup, ax holds the phoney key
- mov ah,kbd_type ; get the keyboard type
- or ah,1 ; check if a key is ready
- int 16h ; now check a key
- jnz gotkeyn ; got one
- cmp slides,1 ; slideshow playback active?
- jne getkeynope ; nope, return no key
- call far ptr slideshw ; check next playback keystroke
- cmp ax,0 ; got one?
- jne getkeyn5 ; yup, use it
- getkeynope:
- clc ; return no key
- UNFRAME <es,si,di> ; pop frame
- ret
- gotkeyn: ; got a real keyboard keystroke
- mov ah,kbd_type ; get the keyboard type
- int 16h ; now get a key
- cmp al,0e0h ; check: Enhanced Keyboard key?
- jne short getkeyn1 ; nope. proceed
- cmp ah,0 ; part 2 of Enhanced Key check
- je short getkeyn1 ; failed. normal key.
- mov al,0 ; Turn enhanced key "normal"
- jmp short getkeyn2 ; jump to common code
- getkeyn1:
- cmp ah,0e0h ; check again: Enhanced Key?
- jne short getkeyn2 ; nope. proceed.
- mov ah,al ; Turn Enhanced key "normal"
- mov al,0 ; ...
- getkeyn2:
- cmp al,0 ; Function Key?
- jne short getkeyn3 ; nope. proceed.
- mov al,ah ; klooge into ASCII Key
- mov ah,0 ; clobber the scan code
- add ax,1000 ; + 1000
- jmp short getkeyn4 ; go to common return
- getkeyn3:
- mov ah,0 ; clobber the scan code
- getkeyn4: ; got real key (not playback)
- cmp ax,9999 ; savetime from mousread?
- je getkeyn6 ; yup, do it and don't record
- cmp slides,1 ; slideshow playback active?
- jne getkeyn5 ; nope
- cmp ax,1bh ; escape?
- jne getkeyn0 ; nope, ignore the key
- call far ptr stopslideshow ; terminate playback
- jmp short getkeyn0 ; go check for another key
- getkeyn5:
- cmp slides,2 ; slideshow record mode?
- jne getkeyn6 ; nope
- push ax
- call far ptr recordshw ; record the key
- pop ax
- getkeyn6:
- cmp debugflag,3000 ; color play enabled?
- jne getkeyyup ; nope
- cmp ax,'~' ; color play requested?
- jne getkeyyup ; nope
- call far ptr edit_text_colors ; play
- ; call far ptr restore_active_ovly ; might've clobbered ovly
- jmp getkeyn0 ; done playing, back around
- getkeyyup:
- stc ; indicate we have a key
- UNFRAME <es,si,di> ; pop frame
- ret
- getkeynowait endp
-
- ; ****************** Function buzzer(int buzzertype) *******************
- ;
- ; Sound a tone based on the value of the parameter
- ;
- ; 0 = normal completion of task
- ; 1 = interrupted task
- ; 2 = error contition
-
- ; "buzzer()" codes: strings of two-word pairs
- ; (frequency in cycles/sec, delay in milliseconds)
- ; frequency == 0 means no sound
- ; delay == 0 means end-of-tune
- buzzer0 dw 1047,100 ; "normal" completion
- dw 1109,100
- dw 1175,100
- dw 0,0
- buzzer1 dw 2093,100 ; "interrupted" completion
- dw 1976,100
- dw 1857,100
- dw 0,0
- buzzer2 dw 40,500 ; "error" condition (razzberry)
- dw 0,0
-
- ; ***********************************************************************
-
- buzzer proc uses si, buzzertype:word
- cmp soundflag,0 ; is the sound supressed?
- je buzzerreturn ; yup. bail out.
- mov si, offset buzzer0 ; normal completion frequency
- cmp buzzertype,0 ; normal completion?
- je buzzerdoit ; do it
- mov si,offset buzzer1 ; interrupted task frequency
- cmp buzzertype,1 ; interrupted task?
- je buzzerdoit ; do it
- mov si,offset buzzer2 ; error condition frequency
- buzzerdoit:
- mov ax,cs:0[si] ; get the (next) frequency
- mov bx,cs:2[si] ; get the (next) delay
- add si,4 ; get ready for the next tone
- cmp bx,0 ; are we done?
- je buzzerreturn ; yup.
- push bx ; put delay time on the stack
- push ax ; put tone value on the stack
- call far ptr tone ; do it
- pop ax ; restore stack
- pop bx ; restore stack
- jmp short buzzerdoit ; get the next tone
- buzzerreturn:
- ret ; we done
- buzzer endp
-
- ; ***************** Function delay(int delaytime) ************************
- ;
- ; performs a delay loop for 'delaytime' milliseconds
- ;
- ; ************************************************************************
-
- delayamillisecond proc near ; internal delay-a-millisecond code
- mov bx,delaycount ; set up to burn another millisecond
- delayamill1:
- mov cx,delayloop ; start up the counter
- delayamill2: ;
- loop delayamill2 ; burn up some time
- dec bx ; have we burned up a millisecond?
- jnz delayamill1 ; nope. try again.
- ret ; we done
- delayamillisecond endp
-
- delay proc uses es, delaytime:word ; delay loop (arg in milliseconds)
- mov ax,delaytime ; get the number of milliseconds
- cmp ax,0 ; any delay time at all?
- je delayreturn ; nope.
- delayloop1:
- call delayamillisecond ; burn up a millisecond of time
- dec ax ; have we burned up enough m-seconds?
- jnz delayloop1 ; nope. try again.
- delayreturn:
- ret ; we done.
- delay endp
-
- ; ************** Function tone(int frequency,int delaytime) **************
- ;
- ; buzzes the speaker with this frequency for this amount of time
- ;
- ; ************************************************************************
-
- tone proc uses es, tonefrequency:word, tonedelay:word
- mov al,0b6h ; latch to channel 2
- out 43h,al ; ...
- cmp tonefrequency,12h ; was there a frequency?
- jbe tonebypass ; nope. delay only
- mov bx,tonefrequency ; get the frequency value
- mov ax,0 ; ugly klooge: convert this to the
- mov dx,12h ; divisor the 8253 wants to see
- div bx ; ...
- out 42h,al ; send the low value
- mov al,ah ; then the high value
- out 42h,al ; ...
- in al,61h ; get the current 8255 bits
- or al,3 ; turn bits 0 and 1 on
- out 61h,al ; ...
- tonebypass:
- mov ax,tonedelay ; get the delay value
- push ax ; set the parameter
- call far ptr delay ; and force a delay
- pop ax ; restore the parameter
-
- in al,61h ; get the current 8255 bits
- and al,11111100b ; turn bits 0 and 1 off
- out 61h,al
-
- ret ; we done
- tone endp
-
- ; ************** Function snd(int hertz) and nosnd() **************
- ;
- ; turn the speaker on with this frequency (snd) or off (nosnd)
- ;
- ; *****************************************************************
-
- snd proc hertz:word ;Sound the speaker
- cmp hertz, 20
- jle hertzbad
- cmp hertz, 5000
- jge hertzbad
- mov ax,0 ;Convert hertz
- mov dx, 12h ;for use by routine
- div hertz
- mov bx, ax
- mov al,10110110b ;Put magic number
- out 43h, al ;into timer2
- mov ax, bx ;Pitch into AX
- out 42h, al ;LSB into timer2
- mov al, ah ;MSB to AL then
- out 42h, al ;to timer2
- in al, 61h ;read I/O port B into AL
- or al,3 ;turn on bits 0 and 1
- out 61h,al ;to turn on speaker
- hertzbad:
- ret
- snd endp
-
- nosnd proc ;Turn off speaker
- in al, 61h ;Read I/O port B into AL
- and al, 11111100b ;mask lower two bits
- out 61h, al ;to turn off speaker
- ret
- nosnd endp
-
-
- ; ****************** Function initasmvars() *****************************
-
- initasmvars proc uses es si di
-
- cmp cpu,0 ; have we been called yet:
- je initasmvarsgo ; nope. proceed.
- jmp initreturn ; yup. no need to be here.
-
- initasmvarsgo:
- mov ax,ds ; save the data segment
- mov _dataseg_xx,ax ; for the C code
-
- mov overflow,0 ; indicate no overflows so far
-
- mov dx,1 ; ask for 96K of far space
- mov ax,8000h ; ...
- push dx ; ...
- push ax ; ...
- call far ptr farmemalloc ; use the assembler routine to do it
- pop ax ; restore the stack
- pop ax ; ...
- mov extraseg,dx ; save the results here.
-
- call adapter_init ; call the video adapter init
-
- ; first see if a mouse is installed
-
- push es ; (no, first check to ensure that
- mov ax,0 ; int 33h doesn't point to 0:0)
- mov es,ax ; ...
- mov ax,es:0cch ; ...
- pop es ; ...
- cmp ax,0 ; does int 33h have a non-zero value?
- je noint33 ; nope. then there's no mouse.
-
- xor ax,ax ; function for mouse check
- int 33h ; call mouse driver
- noint33:
- mov mouse,al ; al holds info about mouse
-
- ; now get the information about the kbd
- push es ; save ES for a tad
- mov ax,40h ; reload ES with BIOS data seg
- mov es,ax ; ...
- mov ah,es:96h ; get the keyboard byte
- pop es ; restore ES
- and ah,10h ; isolate the Enhanced KBD bit
- mov kbd_type,ah ; and save it
-
- call far ptr cputype ; what kind of CPU do we have here?
- cmp ax,0 ; protected mode of some sort?
- jge positive ; nope. proceed.
- neg ax ; yup. flip the sign.
- positive:
- mov cpu,ax ; save the cpu type.
- itsa386:
- cmp debugflag,8088 ; say, should we pretend it's an 8088?
- jne nodebug ; nope.
- mov cpu,86 ; yup. use 16-bit emulation.
- nodebug:
- call far ptr fputype ; what kind of an FPU do we have?
- mov fpu,ax ; save the results
-
- push es ; save ES for a tad
- mov ax,0 ; reset ES to BIOS data area
- mov es,ax ; ...
- mov dx,es:46ch ; obtain the current timer value
- cmp cpu,386 ; are we on a 386 or above?
- jb delaystartuploop ; nope. don't adjust anything
- mov delayloop, 256 ; yup. slow down the timer loop
- delaystartuploop:
- cmp dx,es:46ch ; has the timer value changed?
- je delaystartuploop ; nope. check again.
- mov dx,es:46ch ; obtain the current timer value again
- mov ax,0 ; clear the delay counter
- mov delaycount,55 ; 55 millisecs = 1/18.2 secs
- delaytestloop:
- call delayamillisecond ; burn up a (fake) millisecond
- inc ax ; indicate another loop has passed
- cmp dx,es:46ch ; has the timer value changed?
- je delaytestloop ; nope. burn up some more time.
- mov delaycount,ax ; save the results here
- pop es ; restore ES again
-
- initreturn:
- ret ; return to caller
- initasmvars endp
-
-
- ; New (Apr '90) mouse code by Pieter Branderhorst follows.
- ; The variable lookatmouse controls it all. Callers of keypressed and
- ; getakey should set lookatmouse to:
- ; 0 ignore the mouse entirely
- ; <0 only test for left button click; if it occurs return fake key
- ; number 0-lookatmouse
- ; 1 return enter key for left button, arrow keys for mouse movement,
- ; mouse sensitivity is suitable for graphics cursor
- ; 2 same as 1 but sensitivity is suitable for text cursor
- ; 3 specials for zoombox, left/right double-clicks generate fake
- ; keys, mouse movement generates a variety of fake keys
- ; depending on state of buttons
- ; Mouse movement is accumulated & saved across calls. Eg if mouse has been
- ; moved up-right quickly, the next few calls to getakey might return:
- ; right,right,up,right,up
- ; Minor jiggling of the mouse generates no keystroke, and is forgotten (not
- ; accumulated with additional movement) if no additional movement in the
- ; same direction occurs within a short interval.
- ; Movements on angles near horiz/vert are treated as horiz/vert; the nearness
- ; tolerated varies depending on mode.
- ; Any movement not picked up by calling routine within a short time of mouse
- ; stopping is forgotten. (This does not apply to button pushes in modes<3.)
- ; Mouseread would be more accurate if interrupt-driven, but with the usage
- ; in fractint (tight getakey loops while mouse active) there's no need.
-
- ; translate table for mouse movement -> fake keys
- mousefkey dw 1077,1075,1080,1072 ; right,left,down,up just movement
- dw 0, 0,1081,1073 ; ,pgdn,pgup + left button
- dw 1144,1142,1147,1146 ; kpad+,kpad-,cdel,cins + rt button
- dw 1117,1119,1118,1132 ; ctl-end,home,pgdn,pgup + mid/multi
-
- DclickTime equ 9 ; ticks within which 2nd click must occur
- JitterTime equ 6 ; idle ticks before turfing unreported mickeys
- TextHSens equ 22 ; horizontal sensitivity in text mode
- TextVSens equ 44 ; vertical sensitivity in text mode
- GraphSens equ 5 ; sensitivity in graphics mode; gets lower @ higher res
- ZoomSens equ 20 ; sensitivity for zoom box sizing/rotation
- TextVHLimit equ 6 ; treat angles < 1:6 as straight
- GraphVHLimit equ 14 ; treat angles < 1:14 as straight
- ZoomVHLimit equ 1 ; treat angles < 1:1 as straight
- JitterMickeys equ 3 ; mickeys to ignore before noticing motion
-
- mouseread proc near USES bx cx dx
- local moveaxis:word
-
- ; check if it is time to do an autosave
- cmp saveticks,0 ; autosave timer running?
- je mouse0 ; nope
- sub ax,ax ; reset ES to BIOS data area
- mov es,ax ; see notes at mouse1 in similar code
- tickread:
- mov ax,es:046ch ; obtain the current timer value
- cmp ax,savechktime ; a new clock tick since last check?
- je mouse0 ; nope, save a dozen opcodes or so
- mov dx,es:046eh ; high word of ticker
- cmp ax,es:046ch ; did a tick get counted just as we looked?
- jne tickread ; yep, reread both words to be safe
- mov savechktime,ax
- sub ax,savebase ; calculate ticks since timer started
- sbb dx,savebase+2
- jns tickcompare
- add ax,0b0h ; wrapped past midnight, add a day
- adc dx,018h
- tickcompare:
- cmp dx,saveticks+2 ; check if past autosave time
- jb mouse0
- ja ticksavetime
- cmp ax,saveticks
- jb mouse0
- ticksavetime: ; it is time to do a save
- mov ax,finishrow
- cmp ax,-1 ; waiting for the end of a row before save?
- jne tickcheckrow ; yup, go check row
- cmp calc_status,1 ; safety check, calc active?
- jne tickdosave ; nope, don't check type of calc
- cmp got_status,0 ; 1pass or 2pass?
- je ticknoterow ; yup
- cmp got_status,1 ; solid guessing?
- jne tickdosave ; not 1pass, 2pass, ssg, so save immediately
- ticknoterow:
- mov ax,currow ; note the current row
- mov finishrow,ax ; ...
- jmp short mouse0 ; and keep working for now
- tickcheckrow:
- cmp ax,currow ; started a new row since timer went off?
- je mouse0 ; nope, don't do the save yet
- tickdosave:
- mov timedsave,1 ; tell mainline what's up
- mov ax,9999 ; a dummy key value, never gets used
- jmp mouseret
-
- mouse0: ; now the mouse stuff
- cmp mouse,-1
- jne mouseidle ; no mouse, that was easy
- mov ax,lookatmouse
- cmp ax,prevlamouse
- je mouse1
-
- ; lookatmouse changed, reset everything
- mov prevlamouse,ax
- mov mbclicks,0
- mov mbstatus,0
- mov mhmickeys,0
- mov mvmickeys,0
- ; note: don't use int 33 func 0 nor 21 to reset, they're SLOW
- mov ax,06h ; reset button counts by reading them
- mov bx,0
- int 33h
- mov ax,06h
- mov bx,1
- int 33h
- mov ax,05h
- mov bx,0
- int 33h
- mov ax,0Bh ; reset motion counters by reading
- int 33h
- mov ax,lookatmouse
-
- mouse1: or ax,ax
- jz mouseidle ; check nothing when lookatmouse=0
- ; following code directly accesses bios tick counter; it would be
- ; better not to rely on addr (use int 1A instead) but old PCs don't
- ; have the required int, the addr is constant in bios to date, and
- ; fractint startup already counts on it, so:
- mov ax,0 ; reset ES to BIOS data area
- mov es,ax ; ...
- mov dx,es:46ch ; obtain the current timer value
- cmp dx,mousetime
- ; if timer same as last call, skip int 33s: reduces expense and gives
- ; caller a chance to read all pending stuff and paint something
- jne mnewtick
- cmp lookatmouse,0 ; interested in anything other than left button?
- jl mouseidle ; nope, done
- jmp mouse5
-
- mouseidle:
- clc ; tell caller no mouse activity this time
- ret
-
- mnewtick: ; new tick, read buttons and motion
- mov mousetime,dx ; note current timer
- cmp lookatmouse,3
- je mouse2 ; skip button press if mode 3
-
- ; check press of left button
- mov ax,05h ; get button press info
- mov bx,0 ; for left button
- int 33h
- or bx,bx
- jnz mleftb
- cmp lookatmouse,0
- jl mouseidle ; exit if nothing but left button matters
- jmp mouse3 ; not mode 3 so skip past button release stuff
- mleftb: mov ax,13
- cmp lookatmouse,0
- jg mouser ; return fake key enter
- mov ax,lookatmouse ; return fake key 0-lookatmouse
- neg ax
- mouser: jmp mouseret
-
- mouse2: ; mode 3, check for double clicks
- mov ax,06h ; get button release info
- mov bx,0 ; left button
- int 33h
- mov dx,mousetime
- cmp bx,1 ; left button released?
- jl msnolb ; go check timer if not
- jg mslbgo ; double click
- test mbclicks,1 ; had a 1st click already?
- jnz mslbgo ; yup, double click
- mov mlbtimer,dx ; note time of 1st click
- or mbclicks,1
- jmp short mousrb
- mslbgo: and mbclicks,0ffh-1
- mov ax,13 ; fake key enter
- jmp mouseret
- msnolb: sub dx,mlbtimer ; clear 1st click if its been too long
- cmp dx,DclickTime
- jb mousrb
- and mbclicks,0ffh-1 ; forget 1st click if any
- ; next all the same code for right button
- mousrb: mov ax,06h ; get button release info
- mov bx,1 ; right button
- int 33h
- ; now much the same as for left
- mov dx,mousetime
- cmp bx,1
- jl msnorb
- jg msrbgo
- test mbclicks,2
- jnz msrbgo
- mov mrbtimer,dx
- or mbclicks,2
- jmp short mouse3
- msrbgo: and mbclicks,0ffh-2
- mov ax,1010 ; fake key ctl-enter
- jmp mouseret
- msnorb: sub dx,mrbtimer
- cmp dx,DclickTime
- jb mouse3
- and mbclicks,0ffh-2
-
- ; get buttons state, if any changed reset mickey counters
- mouse3: mov ax,03h ; get button status
- int 33h
- and bl,7 ; just the button bits
- cmp bl,mbstatus ; any changed?
- je mouse4
- mov mbstatus,bl ; yup, reset stuff
- mov mhmickeys,0
- mov mvmickeys,0
- mov ax,0Bh
- int 33h ; reset driver's mickeys by reading them
-
- ; get motion counters, forget any jiggle
- mouse4: mov ax,0Bh ; get motion counters
- int 33h
- mov bx,mousetime ; just to have it in a register
- cmp cx,0 ; horiz motion?
- jne moushm ; yup, go accum it
- mov ax,bx
- sub ax,mhtimer
- cmp ax,JitterTime ; timeout since last horiz motion?
- jb mousev
- mov mhmickeys,0
- jmp short mousev
- moushm: mov mhtimer,bx ; note time of latest motion
- add mhmickeys,cx
- ; same as above for vertical movement:
- mousev: cmp dx,0 ; vert motion?
- jne mousvm
- mov ax,bx
- sub ax,mvtimer
- cmp ax,JitterTime
- jb mouse5
- mov mvmickeys,0
- jmp short mouse5
- mousvm: mov mvtimer,bx
- add mvmickeys,dx
-
- ; pick the axis with largest pending movement
- mouse5: mov bx,mhmickeys
- or bx,bx
- jns mchkv
- neg bx ; make it +ve
- mchkv: mov cx,mvmickeys
- or cx,cx
- jns mchkmx
- neg cx
- mchkmx: mov moveaxis,0 ; flag that we're going horiz
- cmp bx,cx ; horiz>=vert?
- jge mangle
- xchg bx,cx ; nope, use vert
- mov moveaxis,1 ; flag that we're going vert
-
- ; if moving nearly horiz/vert, make it exactly horiz/vert
- mangle: mov ax,TextVHLimit
- cmp lookatmouse,2 ; slow (text) mode?
- je mangl2
- mov ax,GraphVHLimit
- cmp lookatmouse,3 ; special mode?
- jne mangl2
- cmp mbstatus,0 ; yup, any buttons down?
- je mangl2
- mov ax,ZoomVHLimit ; yup, special zoom functions
- mangl2: mul cx ; smaller axis * limit
- cmp ax,bx
- ja mchkmv ; min*ratio <= max?
- cmp moveaxis,0 ; yup, clear the smaller movement axis
- jne mzeroh
- mov mvmickeys,0
- jmp short mchkmv
- mzeroh: mov mhmickeys,0
-
- ; pick sensitivity to use
- mchkmv: cmp lookatmouse,2 ; slow (text) mode?
- je mchkmt
- mov dx,ZoomSens+JitterMickeys
- cmp lookatmouse,3 ; special mode?
- jne mchkmg
- cmp mbstatus,0 ; yup, any buttons down?
- jne mchkm2 ; yup, use zoomsens
- mchkmg: mov dx,GraphSens
- mov cx,sxdots ; reduce sensitivity for higher res
- mchkg2: cmp cx,400 ; horiz dots >= 400?
- jl mchkg3
- shr cx,1 ; horiz/2
- shr dx,1
- inc dx ; sensitivity/2+1
- jmp short mchkg2
- mchkg3: add dx,JitterMickeys
- jmp short mchkm2
- mchkmt: mov dx,TextVSens+JitterMickeys
- cmp moveaxis,0
- jne mchkm2
- mov dx,TextHSens+JitterMickeys ; slower on X axis than Y
-
- ; is largest movement past threshold?
- mchkm2: cmp bx,dx
- jge mmove
- jmp mouseidle ; no movement past threshold, return nothing
-
- ; set bx for right/left/down/up, and reduce the pending mickeys
- mmove: sub dx,JitterMickeys
- cmp moveaxis,0
- jne mmovev
- cmp mhmickeys,0
- jl mmovh2
- sub mhmickeys,dx ; horiz, right
- mov bx,0
- jmp short mmoveb
- mmovh2: add mhmickeys,dx ; horiz, left
- mov bx,2
- jmp short mmoveb
- mmovev: cmp mvmickeys,0
- jl mmovv2
- sub mvmickeys,dx ; vert, down
- mov bx,4
- jmp short mmoveb
- mmovv2: add mvmickeys,dx ; vert, up
- mov bx,6
-
- ; modify bx if a button is being held down
- mmoveb: cmp lookatmouse,3
- jne mmovek ; only modify in mode 3
- cmp mbstatus,1
- jne mmovb2
- add bx,8 ; modify by left button
- jmp short mmovek
- mmovb2: cmp mbstatus,2
- jne mmovb3
- add bx,16 ; modify by rb
- jmp short mmovek
- mmovb3: cmp mbstatus,0
- je mmovek
- add bx,24 ; modify by middle or multiple
-
- ; finally, get the fake key number
- mmovek: mov ax,mousefkey[bx]
-
- mouseret:
- stc
- ret
- mouseread endp
-
-
- ; long readticker() returns current bios ticker value
-
- readticker proc uses es
- sub ax,ax ; reset ES to BIOS data area
- mov es,ax ; see notes at mouse1 in similar code
- tickread:
- mov ax,es:046ch ; obtain the current timer value
- mov dx,es:046eh ; high word of ticker
- cmp ax,es:046ch ; did a tick get counted just as we looked?
- jne tickread ; yep, reread both words to be safe
- ret
- readticker endp
-
-
- ;===============================================================
- ;
- ; CPUTYPE.ASM : C-callable functions cputype() and ndptype() adapted
- ; by Lee Daniel Crocker from code appearing in the late PC Tech Journal,
- ; August 1987 and November 1987. PC Tech Journal was a Ziff-Davis
- ; Publication. Code herein is copyrighted and used with permission.
- ;
- ; The function cputype() returns an integer value based on what kind
- ; of CPU it found, as follows:
- ;
- ; Value CPU Type
- ; ===== ========
- ; 86 8086, 8088, V20, or V30
- ; 186 80186 or 80188
- ; 286 80286
- ; 386 80386 or 80386sx
- ; -286 80286 in protected mode
- ; -386 80386 or 80386sx in protected or 32-bit address mode
- ;
- ; The function ndptype() returns an integer based on the type of NDP
- ; it found, as follows:
- ;
- ; Value NDP Type
- ; ===== ========
- ; 0 No NDP found
- ; 87 8087
- ; 287 80287
- ; 387 80387
- ;
- ; No provisions are made for the 80486 CPU/FPU or Weitek FPA chips.
- ;
- ; Neither function takes any arguments or affects any external storage,
- ; so there should be no memory-model dependencies.
-
- .286P
- .code
-
- cputype proc
- push bp
-
- push sp ; 86/186 will push SP-2;
- pop ax ; 286/386 will push SP.
- cmp ax, sp
- jz not86 ; If equal, SP was pushed
- mov ax, 186
- mov cl, 32 ; 186 uses count mod 32 = 0;
- shl ax, cl ; 86 shifts 32 so ax = 0
- jnz exit ; Non-zero: no shift, so 186
- mov ax, 86 ; Zero: shifted out all bits
- jmp short exit
- not86:
- pushf ; Test 16 or 32 operand size:
- mov ax, sp ; Pushed 2 or 4 bytes of flags?
- popf
- inc ax
- inc ax
- cmp ax, sp ; Did pushf change SP by 2?
- jnz is32bit ; If not, then 4 bytes of flags
- is16bit:
- sub sp, 6 ; Is it 286 or 386 in 16-bit mode?
- mov bp, sp ; Allocate stack space for GDT pointer
- sgdt fword ptr [bp]
- add sp, 4 ; Discard 2 words of GDT pointer
- pop ax ; Get third word
- inc ah ; 286 stores -1, 386 stores 0 or 1
- jnz is386
- is286:
- mov ax, 286
- jmp short testprot ; Check for protected mode
- is32bit:
- db 66h ; 16-bit override in 32-bit mode
- is386:
- mov ax, 386
- testprot:
- smsw cx ; Protected? Machine status -> CX
- ror cx,1 ; Protection bit -> carry flag
- jnc exit ; Real mode if no carry
- neg ax ; Protected: return neg value
- exit:
- pop bp
- ret
- cputype endp
-
- .data
-
- control dw 0 ; Temp storage for 8087 control
- ; and status registers
- .code
-
- fputype proc
- push bp
-
- fninit ; Defaults to 64-bit mantissa
- mov byte ptr control+1, 0
- fnstcw control ; Store control word over 0
- ; dw 3ed9h ; (klooge to avoid the MASM \e switch)
- ; dw offset control ; ((equates to the above 'fnstcw' cmd))
- mov ah, byte ptr control+1 ; Test contents of byte written
- cmp ah, 03h ; Test for 64-bit precision flags
- je gotone ; Got one! Now let's find which
- xor ax, ax
- jmp short fexit ; No NDP found
- gotone:
- and control, not 0080h ; IEM = 0 (interrupts on)
- fldcw control
- fdisi ; Disable ints; 287/387 will ignore
- fstcw control
- test control, 0080h
- jz not87 ; Got 287/387; keep testing
- mov ax, 87
- jmp short freset
- not87:
- finit
- fld1
- fldz
- fdiv ; Divide 1/0 to create infinity
- fld st
- fchs ; Push -infinity on stack
- fcompp ; Compare +-infinity
- fstsw control
- mov ax, control
- sahf
- jnz got387 ; 387 will compare correctly
- mov ax, 287
- jmp short freset
- got387: ; Only one left (until 487/Weitek
- mov ax, 387 ; test is added)
- freset:
- fninit ; in case tests have had strange
- finit ; side-effects, reset
- fexit:
- pop bp
- ret
- fputype endp
-
- ; ************************* Far Segment RAM Support **************************
- ;
- ;
- ; farptr = (char far *)farmemalloc(long bytestoalloc);
- ; (void)farmemfree(farptr);
- ;
- ; alternatives to Microsoft/TurboC routines
- ;
- ;
- .8086
-
- farmemalloc proc uses es, bytestoallocate:dword
- les bx,bytestoallocate ; get the # of bytes into DX:BX
- mov dx,es ; ...
- add bx,15 ; round up to next paragraph boundary
- adc dx,0 ; ...
- shr dx,1 ; convert to paragraphs
- rcr bx,1 ; ...
- shr dx,1 ; ...
- rcr bx,1 ; ...
- shr dx,1 ; ...
- rcr bx,1 ; ...
- shr dx,1 ; ...
- rcr bx,1 ; ...
- cmp dx,0 ; ensure that we don't want > 1MB
- jne farmemallocfailed ; bail out if we do
- mov ah,48h ; invoke DOS to allocate memory
- int 21h ; ...
- jc farmemallocfailed ; bail out on failure
- mov dx,ax ; set up DX:AX as far address
- mov ax,0 ; ...
- jmp short farmemallocreturn ; and return
- farmemallocfailed:
- mov ax,0 ; (load up with a failed response)
- mov dx,0 ; ...
- farmemallocreturn:
- ret ; we done.
- farmemalloc endp
-
- farmemfree proc uses es, farptr:dword
- les ax,farptr ; get the segment into ES
- mov ah,49h ; invoke DOS to free the segment
- int 21h ; ...
- ret
- farmemfree endp
-
- erasesegment proc uses es di si, segaddress:word, segvalue:word
- mov ax,segaddress ; load up the segment address
- mov es,ax ; ...
- mov di,0 ; start at the beginning
- mov ax,segvalue ; use this value
- mov cx,8000h ; over the entire segment
- rep stosw ; do it
- ret ; we done
- erasesegment endp
-
-
- farread proc uses ds, handle:word, buf:dword, len:word
- mov ah, 03Fh
- mov bx, [handle]
- mov cx, [len]
- lds dx, [buf]
- int 21h
- jnc farreaddone
- mov ax, -1
- farreaddone:
- ret
- farread endp
-
-
- farwrite proc uses ds, handle:word, buf:dword, len:word
- mov ah, 040h
- mov bx, [handle]
- mov cx, [len]
- lds dx, [buf]
- int 21h
- jnc farwritedone
- mov ax, -1
- farwritedone:
- ret
- farwrite endp
-
-
- ; Convert segment:offset to equiv pointer with minimum possible offset
- normalize proc p: dword
- ; mov ax, [word ptr p]
- ; mov dx, [word ptr p+2]
- les ax, p
- mov dx, es
- mov bx, ax
- shr bx, 1
- shr bx, 1
- shr bx, 1
- shr bx, 1
- and ax, 0Fh
- add dx, bx
- ret
- normalize endp
-
-
- ; *************** Far string/memory functions *********
- ; far_strlen ( char far *);
- ; far_strcpy ( char far *, char far *);
- ; far_strcmp ( char far *, char far *);
- ; far_stricmp( char far *, char far *);
- ; far_strnicmp(char far *, char far *, int);
- ; far_strcat ( char far *, char far *);
- ; far_memset ( char far *, char far, int);
- ; far_memcpy ( char far *, char far *, int);
- ; far_memcmp ( char far *, char far *, int);
- ; far_memicmp( char far *, char far *, int);
-
- ; xxxfar_routines are called internally with:
- ; ds:si pointing to the source
- ; es:di pointing to the destination
- ; cx containing a byte count
- ; al contining a character (set) value
- ; (and they destroy registers willy-nilly)
-
- xxxfar_memlen proc near ; return string length - INCLUDING the 0
- mov ax,0
- mov cx,1024
- repne scasb
- sub cx,1024
- neg cx
- ret
- xxxfar_memlen endp
-
- xxxfar_memcmp proc near ; compare two strings - length in CX
- mov ax,0
- rep cmpsb
- jz wedone
- mov ax,1
- wedone: ret
- xxxfar_memcmp endp
-
- xxxfar_memicmp proc near ; compare two caseless strings - length in CX
- mov ax,0
- cmp cx,0
- je wedone
- dec si
- dec di
- loop1: inc si
- inc di
- mov al,es:[di]
- mov ah,ds:[si]
- cmp al,ah
- je loop2
- cmp al,'A'
- jb lower1
- cmp al,'Z'
- ja lower1
- add al,20h
- lower1: cmp ah,'A'
- jb lower2
- cmp ah,'Z'
- ja lower2
- add ah,20h
- lower2: cmp al,ah
- jne uneql
- loop2: loop loop1
- mov ax,0
- jmp short wedone
- uneql: mov ax,1
- wedone: ret
- xxxfar_memicmp endp
-
-
- far_strlen proc uses ds es di si, fromaddr:dword
- les di,fromaddr ; point to start-of-string
- call xxxfar_memlen ; find the string length
- mov ax,cx ; return len
- dec ax ; don't count null
- ret ; we done.
- far_strlen endp
-
- far_strnicmp proc uses ds es di si, toaddr:dword, fromaddr:dword, len:word
- les di,fromaddr ; point to start-of-string
- call xxxfar_memlen ; find the string length
- cmp cx,len ; source less than or equal to len?
- jle cxbigger ; yup - use cx
- mov cx,len ; nope - use len
- cxbigger:
- les di,toaddr ; get the dest string
- lds si,fromaddr ; get the source string
- call xxxfar_memicmp ; compare them
- ret ; we done.
- far_strnicmp endp
-
- far_strcpy proc uses ds es di si, toaddr:dword, fromaddr:dword
- les di,fromaddr ; point to start-of-string
- call xxxfar_memlen ; find the string length
- les di,toaddr ; now move to here
- lds si,fromaddr ; from here
- rep movsb ; move them
- ret ; we done.
- far_strcpy endp
-
- far_strcmp proc uses ds es di si, toaddr:dword, fromaddr:dword
- les di,fromaddr ; point to start-of-string
- call xxxfar_memlen ; find the string length
- les di,toaddr ; now compare to here
- lds si,fromaddr ; compare here
- call xxxfar_memcmp ; compare them
- ret ; we done.
- far_strcmp endp
-
- far_stricmp proc uses ds es di si, toaddr:dword, fromaddr:dword
- les di,fromaddr ; point to start-of-string
- call xxxfar_memlen ; find the string length
- les di,toaddr ; get the dest string
- lds si,fromaddr ; get the source string
- call xxxfar_memicmp ; compare them
- ret ; we done.
- far_stricmp endp
-
- far_strcat proc uses ds es di si, toaddr:dword, fromaddr:dword
- les di,fromaddr ; point to start-of-string
- call xxxfar_memlen ; find the string length
- push cx ; save it
- les di,toaddr ; point to start-of-string
- call xxxfar_memlen ; find the string length
- les di,toaddr ; now move to here
- add di,cx ; but start at the end of string
- dec di ; (less the EOS zero)
- lds si,fromaddr ; from here
- pop cx ; get the string length
- rep movsb ; move them
- ret ; we done.
- far_strcat endp
-
- far_memset proc uses es di, toaddr:dword, fromvalue:word, slength:word
- mov ax,fromvalue ; get the value to store
- mov cx,slength ; get the store length
- les di,toaddr ; now move to here
- rep stosb ; store them
- ret ; we done.
- far_memset endp
-
- far_memcpy proc uses ds es di si, toaddr:dword, fromaddr:dword, slength:word
- mov cx,slength ; get the move length
- les di,toaddr ; now move to here
- lds si,fromaddr ; from here
- rep movsb ; move them
- ret ; we done.
- far_memcpy endp
-
- far_memcmp proc uses ds es di si, toaddr:dword, fromaddr:dword, slength:word
- mov cx,slength ; get the compare length
- les di,toaddr ; now compare to here
- lds si,fromaddr ; compare here
- call xxxfar_memcmp ; compare them
- ret ; we done.
- far_memcmp endp
-
- far_memicmp proc uses ds es di si, toaddr:dword, fromaddr:dword, slength:word
- mov cx,slength ; get the compare length
- les di,toaddr ; get the dest string
- lds si,fromaddr ; get the source string
- call xxxfar_memicmp ; compare them
- ret ; we done.
- far_memicmp endp
-
- disable proc ; disable interrupts
- cli
- ret
- disable endp
-
- enable proc ; re-enable interrupts
- sti
- ret
- enable endp
-
- ; *************** Expanded Memory Manager Support Routines ******************
- ; for use with LIM 3.2 or 4.0 Expanded Memory
- ;
- ; farptr = emmquery() ; Query presence of EMM and initialize EMM code
- ; ; returns EMM FAR Address, or 0 if no EMM
- ; freepages = emmgetfree(); Returns the number of pages (1 page = 16K)
- ; ; not already allocated for something else
- ; handle = emmallocate(pages) ; allocate EMM pages (1 page = 16K)
- ; ; returns handle # if OK, or else 0
- ; emmdeallocate(handle) ; return EMM pages to system - MUST BE CALLED
- ; ; or allocated EMM memory fills up
- ; emmgetpage(page, handle); get an EMM page (actually, links the EMM
- ; ; page to the EMM Segment ADDR, saving any
- ; ; prior page in the process)
- ; emmclearpage(page, handle) ; performs an 'emmgetpage()' and then clears
- ; ; it out (quickly) to zeroes with a 'REP STOSW'
-
- .8086
-
- .DATA
-
- emm_name db 'EMMXXXX0',0 ; device driver for EMM
- emm_segment dw 0 ; EMM page frame segment
- emm_zeroflag db 0 ; klooge flag for handle==0
-
- .CODE
-
- emmquery proc
- mov ah,3dh ; function 3dh = open file
- mov al,0 ; read only
- mov dx,offset emm_name ; DS:DX = address of name of EMM
- int 21h ; open it
- jc emmqueryfailed ; oops. no EMM.
-
- mov bx,ax ; BX = handle for EMM
- mov ah,44h ; function 44h = IOCTL
- mov al,7 ; get outo. status
- mov cx,0 ; CX = # of bytes to read
- int 21h ; do it.
- push ax ; save the IOCTL handle.
-
- mov ah,3eh ; function 3H = close
- int 21h ; BX still cintains handle
- pop ax ; restore AX for the status query
- jc emmqueryfailed ; huh? close FAILED?
-
- or al,al ; was the status 0?
- jz emmqueryfailed ; well then, it wasn't EMM!
-
- mov ah,40h ; query EMM: hardware ok?
- int 67h ; EMM call
- cmp ah,0 ; is it ok?
- jne emmqueryfailed ; if not, fail
-
- mov ah,41h ; query EMM: Get Page Frame Segment
- int 67h ; EMM call
- cmp ah,0 ; is it ok?
- jne emmqueryfailed ; if not, fail
- mov emm_segment,bx ; save page frame segment
- mov dx,bx ; return page frame address
- mov ax,0 ; ...
- jmp short emmqueryreturn ; we done.
-
- emmqueryfailed:
- mov ax,0 ; return 0 (no EMM found)
- mov dx,0 ; ...
- emmqueryreturn:
- ret ; we done.
- emmquery endp
-
- emmgetfree proc ; get # of free EMM pages
- mov ah,42h ; EMM call: get total and free pages
- int 67h ; EMM call
- cmp ah,0 ; did we suceed?
- jne emmgetfreefailed ; nope. return 0 free pages
- mov ax,bx ; else return # of free pages
- jmp emmgetfreereturn ; we done.
- emmgetfreefailed:
- mov ax,0 ; failure mode
- emmgetfreereturn:
- ret ; we done
- emmgetfree endp
-
- emmallocate proc pages:word ; allocate EMM pages
- mov bx,pages ; BX = # of 16K pages
- mov ah,43h ; ask for the memory
- int 67h ; EMM call
- mov emm_zeroflag,0 ; clear the klooge flag
- cmp ah,0 ; did the call work?
- jne emmallocatebad ; nope.
- mov ax,dx ; yup. save the handle here
- cmp ax,0 ; was the handle a zero?
- jne emmallocatereturn ; yup. no kloogy fixes
- mov emm_zeroflag,1 ; oops. set an internal flag
- mov ax,1234 ; and make up a dummy handle.
- jmp short emmallocatereturn ; and return
- emmallocatebad:
- mov ax,0 ; indicate no handle
- emmallocatereturn:
- ret ; we done.
- emmallocate endp
-
- emmdeallocate proc emm_handle:word ; De-allocate EMM memory
- emmdeallocatestart:
- mov dx,emm_handle ; get the EMM handle
- cmp dx,1234 ; was it our special klooge value?
- jne emmdeallocatecontinue ; nope. proceed.
- cmp emm_zeroflag,1 ; was it really a zero handle?
- jne emmdeallocatecontinue ; nope. proceed.
- mov dx,0 ; yup. use zero instead.
- emmdeallocatecontinue:
- mov ah,45h ; EMM function: deallocate
- int 67h ; EMM call
- cmp ah,0 ; did it work?
- jne emmdeallocatestart ; well then, try it again!
- emmdeallocatereturn:
- ret ; we done
- emmdeallocate endp
-
- emmgetpage proc pagenum:word, emm_handle:word ; get EMM page
- mov bx,pagenum ; BX = page numper
- mov dx,emm_handle ; DX = EMM handle
- cmp dx,1234 ; was it our special klooge value?
- jne emmgetpagecontinue ; nope. proceed.
- cmp emm_zeroflag,1 ; was it really a zero handle?
- jne emmgetpagecontinue ; nope. proceed.
- mov dx,0 ; yup. use zero instead.
- emmgetpagecontinue:
- mov ah,44h ; EMM call: get page
- mov al,0 ; get it into page 0
- int 67h ; EMM call
- ret ; we done
- emmgetpage endp
-
- emmclearpage proc pagenum:word, emm_handle:word ; clear EMM page
- mov bx,pagenum ; BX = page numper
- mov dx,emm_handle ; DX = EMM handle
- cmp dx,1234 ; was it our special klooge value?
- jne emmclearpagecontinue ; nope. proceed.
- cmp emm_zeroflag,1 ; was it really a zero handle?
- jne emmclearpagecontinue ; nope. proceed.
- mov dx,0 ; yup. use zero instead.
- emmclearpagecontinue:
- mov ah,44h ; EMM call: get page
- mov al,0 ; get it into page 0
- int 67h ; EMM call
- mov ax,emm_segment ; get EMM segment into ES
- push es ; ...
- mov es,ax ; ...
- mov di,0 ; start at offset 0
- mov cx,8192 ; for 16K (in words)
- mov ax,0 ; clear out EMM segment to zeroes
- rep stosw ; clear the page
- pop es ; restore ES
- ret ; we done
- emmclearpage endp
-
- ; *************** Extended Memory Manager Support Routines ******************
- ; for use XMS 2.0 and later Extended Memory
- ;
- ; xmmquery() ; Query presence of XMM and initialize XMM code
- ; ; returns 0 if no XMM
- ; xmmlongest() ; return size of largest available
- ; ; XMM block in Kbytes (or zero if none)
- ; handle = xmmallocate(Kbytes) ; allocate XMM block in Kbytes
- ; ; returns handle # if OK, or else 0
- ; xmmreallocate(handle, Kbytes) ; change size of handle's block
- ; ; to size of Kbytes. Returns 0 if failed
- ; xmmdeallocate(handle) ; return XMM block to system - MUST BE CALLED
- ; ; or allocated XMM memory is not released.
- ; xmmmoveextended(&MoveStruct) ; Moves a block of memory to or
- ; ; from extended memory. Returns 1 if OK
- ; ; else returns 0.
- ; The structure format for use with xmmoveextended is:
- ;
- ; ASM | C
- ;--------------------------------+----------------------------------------
- ; XMM_Move struc | struct XMM_Move
- ; | {
- ; Length dd ? | unsigned long Length;
- ; SourceHandle dw ? | unsigned int SourceHandle;
- ; SourceOffset dd ? | unsigned long SourceOffset;
- ; DestHandle dw ? | unsigned int DestHandle;
- ; DestOffset dd ? | unsigned long DestOffset;
- ; XMM_Move ends | };
- ; |
- ;
- ; Please refer to XMS spec version 2.0 for further information.
-
- .data
- xmscontrol dd dword ptr (0) ; Address of driver's control function
-
- .code
- xmmquery proc
- mov ax,4300h ; Is an XMS driver installed?
- int 2fh
- cmp al, 80h ; Did it succeed?
- jne xmmqueryfailed ; No
- mov ax,4310h ; Get control function address
- int 2fh
- mov word ptr [xmscontrol], bx ; Put address in xmscontrol
- mov word ptr [xmscontrol+2], es ; ...
- mov ah,00h ; Get version number
- call [xmscontrol]
- cmp ax,0200h ; Is 2.00 or higher?
- jge xmmquerydone ; Yes
- xmmqueryfailed:
- mov ax,0 ; return failure
- mov dx,0
- xmmquerydone:
- ret
- xmmquery endp
-
-
- xmmlongest proc ; query length of largest avail block
- mov ah, 08h ;
- call [xmscontrol]
- mov dx, 0
- ret
- xmmlongest endp
-
-
- xmmallocate proc ksize:word
- mov ah,09h ; Allocate extended memory block
- mov dx,ksize ; size of block in Kbytes
- call [xmscontrol]
- cmp ax,0001h ; did it succeed?
- jne xmmallocatefail ; nope
- mov ax,dx ; Put handle here
- jmp short xmmallocatedone
- xmmallocatefail:
- mov ax, 0 ; Indicate failure;
- xmmallocatedone:
- ret
- xmmallocate endp
-
-
- xmmreallocate proc handle:word, newsize:word
- mov ah, 0Fh ; Change size of extended mem block
- mov dx, handle ; handle of block to reallocate
- mov bx, newsize ; new size for block
- call [xmscontrol]
- cmp ax, 0001h ; one indicates success
- je xmmreallocdone
- mov ax, 0 ; we return zero for failure
- xmmreallocdone:
- ret
- xmmreallocate endp
-
-
- xmmdeallocate proc xmm_handle:word
- mov ah,0ah ; Deallocate extended memory block
- mov dx, xmm_handle ; Give it handle
- call [xmscontrol]
- ret
- xmmdeallocate endp
-
- xmmmoveextended proc uses si, MoveStruct:word
-
- ; Call the XMS MoveExtended function.
- mov ah,0Bh
- mov si,MoveStruct ; the move structure.
- call [xmscontrol] ;
-
- ; The call to xmscontrol returns a 1 in AX if successful, 0 otherwise.
-
- ret
-
- xmmmoveextended endp
-
-
- ; ********************* IIT FPU Chip Support Routines ******************
- ; for use with 2C87 and 3C87 FPU chips
- ;
- ; load_mat(double matrix[16]) ; Load a 4x4 matrix of doubles into IIT
- ; ; IIT registers
- ;
- ; mult_vec_iit(double vector[3]) ; Multiply matrix times vector. Routine
- ; ; is not completely general - makes use of
- ; ; the fact that Fractint 3D vectors always
- ; ; have a fourth component of 1. Only three
- ; ; array elements are actually accessed.
- ; ; Source and target vectors are the same.
- ;
- ; IITCoPro() ; Detect IIT chip - return 1. Do not call
- ; ; unless at least a 287 already detected.
- ;
- ; Code adapted by Tim Wegner from IIT documentation and detect routine
- ; sent by Jonathan Osuch and modified by Charles Marslett -- 01/29/91
- ;
- ; The following routines were provided by IIT to implement a semaphore
- ; system to protect the IIT extra registers from multi-tasking:
- ;
- ; F4x4Check() ; returns 1 if semaphore TSR loaded
- ; F4x4Lock() ; returns 1 if semaphore free and locks
- ; F4x4Free() ; frees locked semaphore
-
- .286
- .287
- .data
- one dq 1.0
- .code
- ;
- ;load_mat(double *array)
- ;
- load_mat proc array:WORD
- finit
- db 0DBh,0EBh ; select register set 0
- fwait
- mov bx, array
- fld QWORD PTR [bx+64 ] ; load row 3
- fld QWORD PTR [bx+72 ]
- fld QWORD PTR [bx+80 ]
- fld QWORD PTR [bx+88 ]
- fld QWORD PTR [bx+96 ] ; load row 4
- fld QWORD PTR [bx+104]
- fld QWORD PTR [bx+112]
- fld QWORD PTR [bx+120]
-
- finit
- db 0DBh,0EAh ; select register set 1
- fld QWORD PTR [bx+0 ] ; load row 1
- fld QWORD PTR [bx+8 ]
- fld QWORD PTR [bx+16]
- fld QWORD PTR [bx+24]
- fld QWORD PTR [bx+32] ; load row 2
- fld QWORD PTR [bx+40]
- fld QWORD PTR [bx+48]
- fld QWORD PTR [bx+56]
-
- finit
- db 0DBh,0E8h ; select register set 0
- fwait
- ret
- load_mat endp
-
- .code
- ;
- ;mult_vec_iit(vector)
- ;
- mult_vec_iit proc uses bx, vector:WORD
- mov bx,vector
- fld one ; last component always 1 in fractint
- ; fld QWORD PTR [bx+24 ] ; 4
- fld QWORD PTR [bx+16 ] ; 3
- fld QWORD PTR [bx+8 ] ; 2
- fld QWORD PTR [bx+0 ] ; 1
-
- db 0DBh,0F1h ; multiply the column vector
- fwait
- fstp QWORD PTR [bx+0 ] ; 1
- fstp QWORD PTR [bx+8 ] ; 2
- fstp QWORD PTR [bx+16 ] ; 3
- ; fstp QWORD PTR [bx+24 ] ; 4 vectors length 3 in Fractint
-
- fwait
- ret
- mult_vec_iit endp
-
- ;
- ; IITCoPro()
- ;
-
- .data
- testdata db 0FFh,0FFh,00h,00h,00h,00h,00h,00h,00h,00h
- .code
-
- IITCoPro proc
- finit
- fld tbyte ptr testdata
- fstp tbyte ptr temp
- fwait
- mov ax,word ptr temp
- or ax,ax ; test for 1st word of result zero
- mov ax,1 ; return 1 if next branch taken
- jz must_be_IIT ; result was zero, is IIT
- xor ax,ax ; return 0
- must_be_IIT:
- ret
- IITCoPro endp
-
- .8086
- .8087
-
- eIIT2fService equ 0C0h ; user services: 0C0h - 0FFh
-
- ; services provided by int 2F
- eInstallationCheck equ 0 ; <== must be zero
- eSetSemaphore equ 1
- eClearSemaphore equ 2
-
- .code
- F4x4Check PROC FAR
- ; IIT F4x4 semaphore installation check
-
- inc bp
- push bp
- mov bp, sp
- mov ax, (eIIT2fService SHL 8) + eInstallationCheck
- mov bx, 'II'
- mov cx, 'Ts'
- mov dx, 'em'
- int 2Fh
- cmp ax, (eIIT2fService SHL 8) + 0FFh
- jne not_installed
- cmp bx, 'OK'
- jne not_installed
- cmp cx, ' I'
- jne not_installed
- cmp dx, 'IT'
- jne not_installed
- installed:
- mov ax, 1
- pop bp
- dec bp
- ret
- not_installed:
- xor ax, ax
- pop bp
- dec bp
- ret
- F4x4Check ENDP
-
-
- F4x4Lock PROC FAR
- inc bp
- push bp
- mov bp, sp
- mov ax, (eIIT2fService SHL 8) + eSetSemaphore
- mov bx, 'II'
- mov cx, 'Ts'
- mov dx, 'em'
- int 2Fh
- pop bp
- dec bp
- ret
- F4x4Lock ENDP
-
-
- F4x4Free PROC FAR
- inc bp
- push bp
- mov bp, sp
- mov ax, (eIIT2fService SHL 8) + eClearSemaphore
- mov bx, 'II'
- mov cx, 'Ts'
- mov dx, 'em'
- int 2Fh
- pop bp
- dec bp
- ret
- F4x4Free ENDP
- END
-
-