;================================================================ ; Timer & Copper ;================================================================ ;################################################################ ; Copper simulator :-) ; Don't play with this one! ALIGN 16 coppercount dw 0 public _longframecount _longframecount dw 0,0 copperframecount dw 0 timermode equ 36h ;30h timermode2 equ 06h ;30h frametime dw 16000 frameheigth dw 100 ;from hseq !! copperlstpnt dw 0 scanline dw 0 reinitds dw 0 enable db 0 copperborder db 0 callme dw 0 writeme dw 0 PUBLIC _runcloop _runcloop dw 0 listoffsets dw OFFSET copperlst0 copperlst dw 64 dup(0,0,0,0); ;copper list... Well, sort of... copperlst0 LABEL WORD dw 0 dw 20,OFFSET copper_doit dw 95,0 ALIGN 16 copper_int0 dd copper_intretf copper_int1 dd copper_intretf copper_int2 dd copper_intretf copper_int0flag db 0 public _asmcopperinit,_asmcopperdeinit oldint8 dd ? PUSHALL MACRO pusha push ds push es ENDM POPALL MACRO pop es pop ds popa ENDM copper_intretf PROC FAR ;; call testbar ;!! ret copper_intretf ENDP copperwaitborder PROC NEAR mov dx,03dah cbl1: in al,dx test al,8 jnz cbl1 cbl2: in al,dx test al,8 jz cbl2 ret copperwaitborder ENDP copperwaitscreen PROC NEAR mov dx,03dah cbl3: in al,dx test al,8 jz cbl3 cbl4: in al,dx test al,8 jnz cbl4 ret copperwaitscreen ENDP _asmcopperinit PROC FAR call syncronize mov cs:frametime,ax cli in al,21h and al,not 1 out 21h,al xor ax,ax mov es,ax mov bx,8h*4 mov di,OFFSET oldint8 mov si,OFFSET intti8 mov ax,es:[bx] mov cs:[di],ax mov ax,es:[bx+2] mov cs:[di+2],ax mov es:[bx],si mov es:[bx+2],cs mov si,OFFSET copperlst0 call loadcopperlist mov al,timermode out 43h,al mov ax,65535 out 40h,al mov al,ah out 40h,al ;mov cs:enable,0 ;mov cs:writeme,65535 call copper_end sti ret _asmcopperinit ENDP _asmcopperdeinit PROC FAR cli xor ax,ax mov es,ax mov bx,8h*4 mov di,OFFSET oldint8 mov ax,cs:[di] mov es:[bx],ax mov ax,cs:[di+2] mov es:[bx+2],ax mov al,36h out 43h,al mov ax,65535 out 40h,al mov al,ah out 40h,al sti ret _asmcopperdeinit ENDP ALIGN 4 dolistentry PROC NEAR mov bx,cs:copperlstpnt mov ax,cs:copperlst[bx+2] mov cs:callme,ax mov ax,cs:copperlst[bx] mov cs:scanline,ax mov ax,cs:copperlst[bx+4] mov cs:writeme,ax add bx,8 mov cs:copperlstpnt,bx ret dolistentry ENDP loadcopperlist PROC NEAR cmp word ptr cs:[si],0 je icl4 call cs:[si] icl4: add si,2 mov bx,0 mov ax,cs:[si] mov cs:scanline,ax lcl1: mov cx,cs:[si+2] mov cs:copperlst[bx+2],cx mov dx,cs:[si] mov cs:copperlst[bx+0],dx cmp cx,0 jne lcl2 ;last one mov ax,cs:scanline jmp lcl3 lcl2: mov ax,cs:[si+4] sub ax,dx lcl3: mul cs:frametime div cs:frameheigth mov cs:copperlst[bx+4],ax add bx,8 add si,4 cmp cx,0 jne lcl1 mov cs:scanline,0 mov cs:copperlst[bx+4],cx mov bx,OFFSET copperlst ret loadcopperlist ENDP inhere db 0 intti8 PROC FAR push ax mov al,20h out 20h,al cmp cs:inhere,0 jne eoix inc cs:inhere mov al,timermode out 43h,al mov ax,cs:writeme out 40h,al mov al,ah out 40h,al sti ;cmp cs:enable,0 ;je notactive push bx push cx push dx cmp cs:callme,0 je eos call cs:callme call dolistentry jmp eoi eos: ;call testbar call copper_end eoi: dec cs:inhere pop dx pop cx pop bx eoix: pop ax iret notactive: mov al,20h out 20h,al pop ax iret intti8 ENDP colorcounter db 0 setcolor PROC NEAR add cs:colorcounter,20 mov cl,cs:colorcounter xor ch,ch jmp setblack0 setcolor ENDP setcolor0 PROC NEAR xor cx,cx jmp setblack0 setcolor0 ENDP setblack PROC NEAR ret cmp cs:copperborder,0 je noblack setblack0: mov dx,3c8h mov al,0 out dx,al inc dx mov al,cl out dx,al mov al,ch out dx,al xor al,al out dx,al noblack: ret setblack ENDP copper_nop PROC NEAR mov cx,100 dingdong: loop dingdong ret copper_nop ENDP copper_start PROC NEAR xor cx,cx call setblack ret copper_start ENDP copper_end PROC NEAR mov al,timermode out 43h,al xor ax,ax out 40h,al out 40h,al xor ax,ax mov cs:colorcounter,al mov cs:copperlstpnt,ax mov cs:scanline,ax push cs:writeme call dolistentry PUSHALL call cs:copper_int1 POPALL pop bx mov dx,03dah cel3: in al,dx test al,8 jnz cel3 cel4: in al,dx test al,8 jz cel4 mov al,timermode out 43h,al mov ax,bx out 40h,al mov al,ah out 40h,al ;mov cs:enable,1 inc cs:coppercount inc cs:copperframecount ;used by dis for waitb returns PUSHALL call cs:copper_int2 POPALL ret copper_end ENDP syncronize0 PROC NEAR ;wait till start of screen †† sti mov al,timermode out 43h,al mov ax,65535 out 40h,al mov al,ah out 40h,al mov dx,3dah scrz1: in al,dx test al,8 jnz scrz1 scrz2: in al,dx test al,8 jz scrz2 mov al,timermode out 43h,al mov ax,65535 out 40h,al mov al,ah out 40h,al ;wait till end of visible screen mov dx,3dah scrz6: in al,dx test al,8 jnz scrz6 scrz7: in al,dx test al,8 jz scrz7 mov al,timermode2 out 43h,al in al,40h mov ah,al in al,40h xchg al,ah sti ret syncronize0 ENDP syncronize PROC NEAR mov cx,32 retry: loop tryit mov ax,0 ret ;failed completely: AX=0 tryit: call syncronize0 push ax call syncronize0 pop bx mov dx,ax sub dx,bx cmp dx,-20h jl retry cmp dx,20h jg retry add ax,bx rcr ax,1 neg ax shr ax,1 int 3 nop nop nop ret ;complete: AX=timercount for frame syncronize ENDP ;################################################################ dostimercount dw 0 setblackx PROC NEAR ret mov dx,3c8h mov al,0 out dx,al inc dx mov al,cl out dx,al mov al,ch out dx,al out dx,al mov dx,3c8h mov al,16 out dx,al inc dx mov al,cl out dx,al mov al,ch out dx,al out dx,al mov dx,3c8h mov al,32 out dx,al inc dx mov al,cl out dx,al mov al,ch out dx,al out dx,al ret setblackx ENDP testbar PROC NEAR mov cx,1f1fh call setblackx mov cx,25 ppz2: loop ppz2 xor cx,cx call setblackx ret testbar ENDP bigtestbar PROC NEAR mov cx,1f1fh call setblackx mov cx,250 ppz3: loop ppz3 xor cx,cx call setblackx ret bigtestbar ENDP copper_doit PROC NEAR push si push di push bp push ds push es ;;call bigtestbar cmp cs:copper_int0flag,0 jne @@1 mov cs:copper_int0flag,1 PUSHALL call cs:copper_int0 POPALL mov cs:copper_int0flag,0 @@1: call _zpollme call u2copperint ; mov ax,cs:dostimercount ; add ax,19900 ; mov cs:dostimercount,ax ; jnc @@skipi ; pushf ; call cs:oldint8 ;@@skipi: mov ax,040h mov ds,ax inc word ptr ds:[6ch] ;advance dos timer counter (at a wrong speed) pop es pop ds pop bp pop di pop si ret copper_doit ENDP