PDA

View Full Version : datetostr, sounds simple....



seiferalmasy
20-02-2007, 10:00 AM
Yeah sounds simple but something is wrong.

I press a button which contains this>>

Button1.caption:=datetostr(date);

it reports the correct date. Cool.

Then when dxdraw is initialised (DXDraw1.Initialize) the date is always reported as the day before?

There is nothing that could do this from my code....

WTF?

http://forum.builder.cz/read.php?32,1467263,1467263,quote=1 <<this guy seems to have same prob

Huehnerschaender
20-02-2007, 12:24 PM
Have you tried sysutils.datetostr(sysutils.date) to see if the correct functions are called? Maybe there is an overloaded function in your framework-units which does not work correct?

seiferalmasy
20-02-2007, 12:30 PM
That still reports yesterday also, however:

datetostr(now) does not. It gives correct date, so i guess I will use that;)

Edit:

oh this is impossible, now the button reports correct date, but when i ask the date to be put into a table, its still reports yesterday. whenh i dont call initialise, everything works normal

seiferalmasy
20-02-2007, 12:45 PM
and it gets worse. Once initialise is called, my table that stores the dates is also changed. All records display the previous day, even though the data is correct.

Ob something in sysutils is not woring right, or delphix has changed in soem way how the date is reported?

AthenaOfDelphi
20-02-2007, 01:06 PM
The problem with dates appears to be in SysUtils.dateTimeToTimestamp.

Before DX is initialised, it returns 732303 for the date 23/12/2005 (this is correct). Once DX has been initialised it returns 732302.

I've uploaded my little test program here (http://www.soft-answer.demon.co.uk/DXDateTest.rar).

The problem also affects other float to string conversions, so its not just limited to dateTimeToTimestamp. I would suggest that somewhere along the lines, DelphiX (or DirectX) is changing some processor configuration that is screwing over Delphis sysUtils.

One thing I noticed was that this only occurs if DX7 mode is requested. I'm not sure what implications it has for performance if you turn DX7 mode off, but under those conditions, the problem doesn't occur.

seiferalmasy
20-02-2007, 01:10 PM
Thanks for the input. Was this a fix also? Because I cannot open the exe file, it just stays minimized:(

I can view source though i guess;)

ahh, yes, I remember now, I added Dx7 mode again recently...and i still have 0 idea what it does anyway, so I will disable it.

Thanks!

AthenaOfDelphi
20-02-2007, 01:18 PM
Its not minimized..... I run at 1600x1200 and its at the bottom of the screen.... I forgot to set initial position.

I'm not sure whether its a fix, because as I said, I don't know how turning DX7Mode off affects performance. If it forces DX7 mode when it could operate with DX8 or DX9, then I suspect you'll get a decrease in performance by leaving it on.

AthenaOfDelphi
20-02-2007, 01:27 PM
Just had a quick read of the documentation.....

Unfortunately, if (a) I understood the docs correctly and (b) the docs are correct, then to get hardware acceleration you have to enable DX7 mode.

AthenaOfDelphi
20-02-2007, 01:34 PM
The problem also goes away if you turn off the do3D option...

So, if you have do3D AND doDirectX7Mode, the problem occurs, but you'll get hardware acceleration (providing doHardware is set). As soon as you turn off do3D or doDirectX7Mode, the problem appears to go away.

seiferalmasy
20-02-2007, 01:42 PM
So to clarify if i have do3d and do hardware I will still get hardware acceleration. And DoDX7 doesn't have much effect on anything?

I mean, it all seems same to me on and off, on slow machines and on my own (did tests on 5 computers)

And thanks alot for the info

AthenaOfDelphi
20-02-2007, 01:46 PM
Like I said... according to the documentation, to get hardware acceleration, you need do3D, doDirectX7Mode, doHardware.



If HardwareSwitch Then
&#123;hardware&#125;
Begin
if NOT &#40;doDirectX7Mode in DXDraw.Options&#41; then
DXDraw.Options &#58;= DXDraw.Options + &#91;doDirectX7Mode&#93;;
if NOT &#40;doHardware in DXDraw.Options&#41; then
DXDraw.Options &#58;= DXDraw.Options + &#91;doHardware&#93;;
if NOT &#40;do3D in DXDraw.Options&#41; then
DXDraw.Options &#58;= DXDraw.Options + &#91;do3D&#93;;
if doSystemMemory in DXDraw.Options then
DXDraw.Options &#58;= DXDraw.Options - &#91;doSystemMemory&#93;;
End


Thats just a snippet from the documentation.

Whether its changed for unDelphiX 1.0.7 I don't know.

AthenaOfDelphi
20-02-2007, 01:51 PM
Updated the archive containing the sample so the form should be positioned centrally on the screen.

seiferalmasy
20-02-2007, 01:56 PM
Well that's bad. i don't wanna use dx7/Hw mode if it ruins the dates:( maybe another job for jaro

AthenaOfDelphi
20-02-2007, 03:42 PM
I guess the question is are dates crucial? Losing hardware acceleration might be a real pain in the ass.

Anyhow, I've been tinkering, and I've made some interesting discoveries. I created local copies of some of the crucial routines. The majority of them appear to work correctly. The problem appears to be in converting TDateTime to TTimeStamp.

So... with much tinkering, I have a possible solution...

Basically, I've created versions of the key routines that only work on Integers and it appears to work (even when pushing in float date using trunc() that would break the standard routines).


function intDateTimeToTimestamp(DateTime:integer):TTimestam p;
var
temp : cardinal;
begin
temp:=dateTime*86400;
result.date:=DateDelta+(temp div 86400);
result.time:=temp-result.date;
end;

procedure LocalDivMod(Dividend: Integer; Divisor: Word;
var Result, Remainder: Word);
asm
PUSH EBX
MOV EBX,EDX
MOV EDX,EAX
SHR EDX,16
DIV BX
MOV EBX,Remainder
MOV [ECX],AX
MOV [EBX],DX
POP EBX
end;

function LocalIsLeapYear(Year: Word): Boolean;
begin
Result := (Year mod 4 = 0) and ((Year mod 100 <> 0) or (Year mod 400 = 0));
end;

const
LocalMonthDays: array [Boolean] of TDayTable =
((31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31));

procedure intDecodeDate(Date: Integer; var Year, Month, Day, DOW: Word);
const
D1 = 365;
D4 = D1 * 4 + 1;
D100 = D4 * 25 - 1;
D400 = D100 * 4 + 1;
var
Y, M, D, I: Word;
T: Integer;
DayTable: PDayTable;
begin
T := IntDateTimeToTimestamp(date).date;
if T <0>= D400 do
begin
Dec(T, D400);
Inc(Y, 400);
end;
LocalDivMod(T, D100, I, D);
if I = 4 then
begin
Dec(I);
Inc(D, D100);
end;
Inc(Y, I * 100);
LocalDivMod(D, D4, I, D);
Inc(Y, I * 4);
LocalDivMod(D, D1, I, D);
if I = 4 then
begin
Dec(I);
Inc(D, D1);
end;
Inc(Y, I);
DayTable := @LocalMonthDays[LocalIsLeapYear(Y)];
M := 1;
while True do
begin
I := DayTable^[M];
if D < I then Break;
Dec(D, I);
Inc(M);
end;
Year := Y;
Month := M;
Day := D + 1;
end;
end;


The only real requirements for this are that if you are using TDateTime values, you pass them into the routine using trunc(datetime).

I can't guarantee that this is going to work with every date because the original DateTimeToTimestamp routine is written in assembler and my x86 is VERY poor, so whilst it works (using my test data) it may not be correct for other dates. There is some kind of conditional negation I think in the routine... I don't have that, so certain date ranges could go bang.

But, these routine do appear to work in my test bed.

I think the reason is because (from what I can tell) once you call the intDecodeDate routine, there are no floating point instructions such as FMul which are present in the orginal versions.

I'm guessing from this that somewhere along the lines, unDelphiX or DirectX changes some flags or settings in the FPU that breaks standard routines.

Anyhow.... hope this helps.

As a side note... if someone in the know could possibly explain why this problem is occuring, I'm sure seiferalmasy would appreciate it, because I know I would :-)

seiferalmasy
20-02-2007, 04:15 PM
well, thats nice:) and you are right...i do want to know why, and i want it fixed :lol:

Legolas
20-02-2007, 04:23 PM
Maybe could help disabling optimization before the asm function and reenabling it after with {$O-} and {$O+}.
I'm wondering about registers used too. In free pascal you can tell to compiler the registers used, so it will preserve them, though I'm not sure about delphi:

procedure foo (value: longint); assembler;
asm
mov ebx, eax
...
...
end ['ebx'];


:think:

AthenaOfDelphi
20-02-2007, 05:16 PM
Its a very strange issue... not that it affects me (at the moment), but it got me thinking. As soon as you enable DirectX, even the most basic of operations on the variables report strange values....

For example, floatToStr(myVar) (myVar contains 1.0) will report 1 before, and then 0.9999999something or other after DirectX has been initialised with TDXDraw.initialize.