gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Standard C time()-replacement needs review [renamed]

#102980 - Lick - Mon Sep 18, 2006 12:27 pm

As the current standard ctime functions don't work, I've wrote a very unclean hack that does the same as time(), at least that's what it should do.

Is there anything wrong with it? Can it be optimized?

ndsx_time.h
Code:
#ifndef _NDSX_TIME_
#define _NDSX_TIME_

#define ISLEAP(y)           (!((y) % 4) && (((y) % 100) || !((y) % 400)))
#define DAY2S(dys)          u32((dys) * 86400)
#define HOURS2S(hrs)        u32((hrs) * 3600)
#define MINUTES2S(min)      u32((min) * 60)

u16 mdays[]   = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
u16 mdays_leap[] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };

#define rtc24hours ((IPC->rtc_hours > 51) ? IPC->rtc_hours-40 : IPC->rtc_hours)

u32 NDSX_time()
{
    static u32 year_shit1 = (IPC->rtc_year+30) / 4; // get number of 4-years
    static u32 year_shit2 = (IPC->rtc_year+30) % 4; // rest of 4-years (1, 2, 3 are important)
    u32 years_in_sec = year_shit1 * (31536000*3 + 31622400);
    if(year_shit2 == 1)
        years_in_sec += 31536000; // normal year
    else if(year_shit2 == 2)
        years_in_sec += 31536000 + 31622400; // normal year + leap year
    else if(year_shit2 == 3)
        years_in_sec += 31536000*2 + 31622400; // normal year * 2 + leap year

    return
        years_in_sec
        + ISLEAP(IPC->rtc_year+2000) ?
            DAY2S(mdays_leap[IPC->rtc_month-1]) : DAY2S(mdays[IPC->rtc_month-1])
        + DAY2S(IPC->rtc_day-1)
        + HOURS2S(rtc24hours)
        + MINUTES2S(IPC->rtc_minutes)
        + IPC->rtc_seconds
        ;
}


#endif


BTW, you're free to use this code in your project!
_________________
http://licklick.wordpress.com

#103514 - Lick - Fri Sep 22, 2006 3:49 pm

Okay this is the definite one. The code in my last post did not ( ) the ISLEAP part, that's why it failed.

Use it! ;)

http://lick.huuf.net/ndsx_time.h
_________________
http://licklick.wordpress.com

#103577 - !cube - Fri Sep 22, 2006 9:42 pm

Lick wrote:
Is there anything wrong with it? Can it be optimized?


Well you can change the divisions by four into bit shifts and modulus by 4 into bitwise AND atleast.

#103579 - tepples - Fri Sep 22, 2006 9:51 pm

!cube wrote:
Lick wrote:
Is there anything wrong with it? Can it be optimized?

Well you can change the divisions by four into bit shifts and modulus by 4 into bitwise AND atleast.

Are you sure that the compiler isn't already doing that at -O2?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#103580 - Lick - Fri Sep 22, 2006 9:52 pm

I'll change that..

I actually think the compiler will do it automatically, but hey, it's worth a try. Thanks! ;)

- Lick
_________________
http://licklick.wordpress.com

#103899 - knight0fdragon - Mon Sep 25, 2006 7:11 am

hey at least give me credit for helping you bastard hahaha :-p
_________________
http://www.myspace.com/knight0fdragonds

MK DS FC: Dragon 330772 075464
AC WW FC: Anthony SamsClub 1933-3433-9458
MPFH: Dragon 0215 4231 1206

#103934 - Lick - Mon Sep 25, 2006 3:08 pm

* gives cookie to knight0fdragon *

B)
_________________
http://licklick.wordpress.com

#104228 - sasq - Wed Sep 27, 2006 8:13 am

Actually, since IPC is volatile is really not a good idea to use it directly in the macros like that, its get read multiple times. This made the above code not work for me at all until I first read out the IPC info into local variables.

Also, it is C++ only becuase of the long() cast operators and the static variables (which I also don't see any reason to use).

#104237 - Lick - Wed Sep 27, 2006 10:36 am

I'm very open to any improvements, as it's only better for everyone to have the finest code available.So sasq, could I invite you to write a better version?
_________________
http://licklick.wordpress.com

#104252 - !cube - Wed Sep 27, 2006 1:32 pm

Lick wrote:
I actually think the compiler will do it automatically, but hey, it's worth a try.


I wouldn't trust a compiler to optimize anything :) Too many a time have I stumbled into the compiler "optimizing" the code to a standstill..

#104258 - kevinc - Wed Sep 27, 2006 2:58 pm

You could make mdays a const. And I agree with sasq's volatile/static suggestions.

You should rewrite your numeric constants as #defines, too. "31536000*3 + 31622400" is a bit hard to parse.


// btw: ISLEAP(x) can be simplified to:

#define ISLEAP(x) (!(x % 25 ? x & 3 : x & 15))

That way, you only use the evil modulo once.
_________________
http://akzeac.blogspot.com

#104448 - onigiri - Fri Sep 29, 2006 7:16 am

I'm really lazy and went with using the existing mktime to help me make a drop in replacement for the standard time(time_t *inTime).

Code:

time_t timeNDS(time_t *inTime) {
    time_t current_time;
    struct tm timeinfo;
 
    timeinfo.tm_year = (IPC->rtc_year)+100;
    timeinfo.tm_mon = IPC->rtc_month-1;
    timeinfo.tm_mday = IPC->rtc_day;
   
    if (IPC->rtc_hours <= 11) {
        timeinfo.tm_hour = IPC->rtc_hours;
    }
    else {
        timeinfo.tm_hour = IPC->rtc_hours-40;
    }
    timeinfo.tm_min = IPC->rtc_minutes;
    timeinfo.tm_sec = IPC->rtc_seconds;
    timeinfo.tm_isdst = -1;
 
    current_time = mktime(&timeinfo);
    return current_time;
}