0,0 → 1,430 |
; drawing code for aclock |
; |
; Copyright (c) 2003 Thomas Mathys |
; killer@vantage.ch |
; |
; This program is free software; you can redistribute it and/or modify |
; it under the terms of the GNU General Public License as published by |
; the Free Software Foundation; either version 2 of the License, or |
; (at your option) any later version. |
; |
; This program is distributed in the hope that it will be useful, |
; but WITHOUT ANY WARRANTY; without even the implied warranty of |
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
; GNU General Public License for more details. |
; |
; You should have received a copy of the GNU General Public License |
; along with this program; if not, write to the Free Software |
; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
; |
%ifndef _DRAW_INC |
%define _DRAW_INC |
|
|
TMR1_FACTOR dd 0.45 |
TMR2_FACTOR dd 0.426315789 |
SECR_FACTOR dd 0.378947368 |
MINR_FACTOR dd 0.355263158 |
HOURR_FACTOR dd 0.189473684 |
DATE_FACTOR dd 0.1 |
|
|
monthNames: |
db "Jan" |
db "Feb" |
db "Mar" |
db "Apr" |
db "May" |
db "Jun" |
db "Jul" |
db "Aug" |
db "Sep" |
db "Oct" |
db "Nov" |
db "Dec" |
|
|
;******************************************************************** |
; draws the clock |
; input : nothing |
; output : nothing |
; destroys : nothing |
;******************************************************************** |
drawClock: |
%push drawClock_context |
%stacksize flat |
%assign %$localsize 0 |
|
%local i:dword, \ |
TMR1X:dword, \ |
TMR1Y:dword, \ |
TMR2X:dword, \ |
TMR2Y:dword, \ |
SECRX:dword, \ |
SECRY:dword, \ |
MINRX:dword, \ |
MINRY:dword, \ |
HOURRX:dword, \ |
HOURRY:dword, \ |
workwidth:dword, \ |
workheight:dword, \ |
foo:dword |
|
enter %$localsize,0 |
pushad |
pushfd |
|
; get window dimensions |
mov eax,MOS_SC_GETPROCESSINFO |
mov ebx,procInfo |
mov ecx,-1 |
int 0x40 |
|
; calculate work area size (width/height = ecx/edx) |
; if the work area is too small (maybe the window is shaded) |
; we don't draw anything. |
mov eax,MOS_SC_WINDOWPROPERTIES |
mov ebx,4 ; get skin height (eax) |
int 0x40 |
mov ecx,[procInfo + MOS_PROCESSINFO.wndWidth] |
sub ecx,MOS_WND_SKIN_BORDER_LEFT+MOS_WND_SKIN_BORDER_RIGHT |
mov edx,[procInfo + MOS_PROCESSINFO.wndHeight] |
sub edx,eax |
sub edx,MOS_WND_SKIN_BORDER_BOTTOM |
cmp ecx,0 ; width too small ? |
jle .bye |
cmp edx,0 ; height too small ? |
jnle .continue |
.bye: |
jmp .byebye |
.continue: |
mov [workwidth],ecx ; save for later (for fpu) |
mov [workheight],edx |
|
; calculate center of clock (x/y = esi/edi) |
mov esi,[procInfo + MOS_PROCESSINFO.wndWidth] |
shr esi,1 |
mov edi,[procInfo + MOS_PROCESSINFO.wndHeight] |
sub edi,MOS_WND_SKIN_BORDER_BOTTOM |
sub edi,eax |
shr edi,1 |
add edi,eax |
|
; clear work area |
pushad |
mov ebx,(MOS_WND_SKIN_BORDER_LEFT)*0x10000 ; x start |
or ebx,ecx ; width |
mov ecx,eax ; y start |
shl ecx,16 ; (=skin height) |
or ecx,edx ; height |
mov edx,[wndColors + MOS_WNDCOLORS.work] |
mov eax,MOS_SC_DRAWBAR |
int 0x40 |
popad |
|
; calculate second hand radii |
fild dword [workwidth] |
fmul dword [SECR_FACTOR] |
fstp dword [SECRX] |
fild dword [workheight] |
fmul dword [SECR_FACTOR] |
fstp dword [SECRY] |
|
; calculate minute hand radii |
fild dword [workwidth] |
fmul dword [MINR_FACTOR] |
fstp dword [MINRX] |
fild dword [workheight] |
fmul dword [MINR_FACTOR] |
fstp dword [MINRY] |
|
; calculate hour hand radii |
fild dword [workwidth] |
fmul dword [HOURR_FACTOR] |
fstp dword [HOURRX] |
fild dword [workheight] |
fmul dword [HOURR_FACTOR] |
fstp dword [HOURRY] |
|
; calculate tick mark radii |
fild dword [workwidth] |
fmul dword [TMR1_FACTOR] |
fstp dword [TMR1X] |
fild dword [workheight] |
fmul dword [TMR1_FACTOR] |
fstp dword [TMR1Y] |
fild dword [workwidth] |
fmul dword [TMR2_FACTOR] |
fstp dword [TMR2X] |
fild dword [workheight] |
fmul dword [TMR2_FACTOR] |
fstp dword [TMR2Y] |
|
; get system clock (edx) |
mov eax,MOS_SC_GETSYSCLOCK |
int 0x40 |
mov edx,eax |
|
; draw second hand |
push edx |
mov eax,edx |
shr eax,16 |
call bcdbin |
mov ecx,eax ; save seconds for later |
push ecx |
push eax |
fpush32 0.104719755 ; 2*pi/60 |
push dword [SECRX] |
push dword [SECRY] |
push esi |
push edi |
call getHandCoords |
mov eax,MOS_SC_DRAWLINE |
shl ebx,16 |
or ebx,esi |
shl ecx,16 |
or ecx,edi |
mov edx,[wndColors + MOS_WNDCOLORS.workText] |
int 0x40 |
pop ecx |
pop edx |
|
; draw minute hand |
push edx |
mov eax,edx |
shr eax,8 |
call bcdbin |
mov edx,60 |
mul edx |
add eax,ecx |
mov ecx,eax ; save for later |
push ecx |
push eax |
fpush32 0.001745329 ; 2*pi/60/60 |
push dword [MINRX] |
push dword [MINRY] |
push esi |
push edi |
call getHandCoords |
mov eax,MOS_SC_DRAWLINE |
shl ebx,16 |
or ebx,esi |
shl ecx,16 |
or ecx,edi |
mov edx,[wndColors + MOS_WNDCOLORS.workText] |
int 0x40 |
pop ecx |
pop edx |
|
; draw hour hand |
push edx |
mov eax,edx |
call bcdbin |
cmp eax,11 ; % 12 (just to be sure) |
jnae .hoursok |
sub eax,12 |
.hoursok: |
mov edx,60*60 |
mul edx |
add eax,ecx |
push eax |
fpush32 0.000145444 ; 2*pi/60/60/12 |
push dword [HOURRX] |
push dword [HOURRY] |
push esi |
push edi |
call getHandCoords |
mov eax,MOS_SC_DRAWLINE |
shl ebx,16 |
or ebx,esi |
shl ecx,16 |
or ecx,edi |
mov edx,[wndColors + MOS_WNDCOLORS.workText] |
int 0x40 |
pop edx |
|
; draw tick marks |
mov dword [i],11 ; draw 12 marks |
.drawtickmarks: |
push dword [i] ; calculate start point |
fpush32 0.523598776 ; 2*pi/12 |
push dword [TMR1X] |
push dword [TMR1Y] |
push esi |
push edi |
call getHandCoords |
mov eax,ebx ; save in eax and edx |
mov edx,ecx |
push dword [i] |
fpush32 0.523598776 ; 2*pi/12 |
push dword [TMR2X] |
push dword [TMR2Y] |
push esi |
push edi |
call getHandCoords |
shl eax,16 |
shl edx,16 |
or ebx,eax ; ebx = x start and end |
or ecx,edx ; ecx = y start and end |
mov edx,[wndColors + MOS_WNDCOLORS.workText] |
mov eax,MOS_SC_DRAWLINE |
int 0x40 |
dec dword [i] |
jns .drawtickmarks |
|
%define DATE_WIDTH 48 |
|
; calculate text start position |
mov eax,[procInfo+MOS_PROCESSINFO.wndWidth] |
sub eax,DATE_WIDTH ; x = (wndwidth-textwidth)/2 |
shr eax,1 ; eax = x |
fild dword [workheight] ; y = DATE_FACTOR*workheight... |
fmul dword [DATE_FACTOR] |
mov [foo],edi ; ... + y_clockcenter |
fiadd dword [foo] |
fistp dword [foo] |
mov ebx,[foo] ; ebx = y |
|
; draw text at all ? |
cmp dword [workwidth],DATE_WIDTH ; text too wide ? |
jb .goodbye |
mov ecx,ebx ; text too high ? |
add ecx,10-1 |
mov edx,[procInfo+MOS_PROCESSINFO.wndHeight] |
sub edx,MOS_WND_SKIN_BORDER_BOTTOM |
cmp ecx,edx |
jnae .yousuck |
.goodbye: |
jmp .bye |
.yousuck: |
|
|
; ebx = (x << 16) | y |
shl eax,16 |
or ebx,eax |
|
; get date (edi) |
mov eax,MOS_SC_GETDATE |
int 0x40 |
mov edi,eax |
|
; display month |
mov eax,edi ; get month |
shr eax,8 |
call bcdbin |
; ebx contains already position |
mov ecx,[wndColors+MOS_WNDCOLORS.workText] |
lea edx,[monthNames-3+eax*2+eax]; -3 because eax = 1..12 =] |
mov esi,3 ; text length |
mov eax,MOS_SC_WRITETEXT |
int 0x40 |
|
; display date |
add ebx,MOS_DWORD(3*6+3,0) |
mov eax,edi ; get date |
shr eax,16 |
call bcdbin |
mov edx,ebx ; position must be in edx |
mov ebx,0x00020000 ; number, display two digits |
mov ecx,eax ; number to display |
mov esi,[wndColors+MOS_WNDCOLORS.workText] |
mov eax,MOS_SC_WRITENUMBER |
int 0x40 |
|
; display year. the way we avoid the y2k bug is even |
; simpler, yet much better than in the last version: |
; now we simply display the last two digits and let the |
; user decide wether it's the year 1903 or 2003 =] |
add edx,MOS_DWORD(2*6+3,0) |
mov eax,edi ; get year |
call bcdbin |
mov ebx,0x00020000 ; number, display two digits |
mov ecx,eax ; number to display |
; edx contains already position |
mov esi,[wndColors+MOS_WNDCOLORS.workText] |
mov eax,MOS_SC_WRITENUMBER |
int 0x40 |
|
.byebye: |
popfd |
popad |
leave |
ret |
%pop |
|
|
;********************************************************** |
; bcdbin |
; converts a 8 bit bcd number into a 32 bit binary number |
; |
; in al = 8 bit bcd number |
; out eax = 32 bit binary number |
; destroys dl,flags |
;********************************************************** |
bcdbin: |
push edx |
pushfd |
mov dl,al ; save bcd number |
shr al,4 ; convert upper nibble |
mov ah,10 |
mul ah |
and dl,15 ; add lower nibble |
add al,dl |
and eax,255 ; ! |
popfd |
pop edx |
ret |
|
|
;******************************************************************** |
; getHandCoords |
; calculates the end point of a hand |
; |
; input (on stack, push from top to bottom): |
; ANGLE angle (integer) |
; DEG2RAD conversion factor for ANGLE (32 bit real) |
; RADIUSX x radius (32 bit real) |
; RADIUSY y radius (32 bit real) |
; CENTERX x center of the clock (integer) |
; CENTERY y center of the clock (integer) |
; |
; output: |
; ebx x coordinate in bits 0..15, bits 16..31 are zero |
; ecx y coordinate in bits 0..15, bits 16..31 are zero |
; |
; destroys: |
; nothing |
;******************************************************************** |
getHandCoords: |
|
ANGLE equ 28 |
DEG2RAD equ 24 |
RADIUSX equ 20 |
RADIUSY equ 16 |
CENTERX equ 12 |
CENTERY equ 8 |
|
enter 0,0 |
pushfd |
|
fild dword [ebp+ANGLE] ; get angle |
fmul dword [ebp+DEG2RAD] ; convert to radians |
fsincos |
fmul dword [ebp+RADIUSY] ; -y * radius + clockcy |
fchs |
fiadd dword [ebp+CENTERY] |
fistp dword [ebp+CENTERY] |
fmul dword [ebp+RADIUSX] ; x * radius + clockcx |
fiadd dword [ebp+CENTERX] |
fistp dword [ebp+CENTERX] |
|
mov ebx,[ebp+CENTERX] |
mov ecx,[ebp+CENTERY] |
|
popfd |
leave |
ret 4*6 |
|
|
%endif |
|
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |