Metropoli BBS
VIEWER: datetime.cpp MODE: TEXT (CP437)
#if KUVAUS  /* Kari Rinne 13-Jul-1991 */

    DateTime.exe

    Lukee Hyundai PC/XT 16T reaaliaikakellon ja asettaa DOS 5.0 ajan.
    Laitteen mukana toimitettu DOS 3.21 oli valmistajan virittämä.

    Aika luetaan ja asetetaan RTC-piirin porteista. Porttiosoitteet
    ja kirjoitettavat arvot on saatu vanhoja DOS tiedostoja tutkimalla.
    Maahantuojan huolto ei edes ymmärtänyt mistä on kysymys, kun
    kysyin kuinka koneen kello saadaan aikaan päivityksen jälkeen!!

    Ohjelma on kirjoitettu alunperin C-kielellä, mutta korjattu niin
    että se kääntyy varoituksetta Microsotf C++ (7.0) kääntäjällä.

    Ohjelma ei ole muistiinladattava, vaan sitä käytettään autoexec.bat
    tiedostossa lukemaan aika paristovarmennetusta kellosta. Samalla
    ohjelmalla voidaan aika myös asettaa komentoriviltä.
    Ohjelma antaa apua /? ta /help valinnoilla.


#endif

#include <dos.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>

//#include <kri.h>
//  Määrityksi ed. tiedostosta
    #define SOURCE_ID(_nimi) static const char __kr__[] = "***** " _nimi " : Kari Rinne, "__DATE__ " " __TIME__ "  *****"
    typedef int bool;
    #define FALSE 0
    #define TRUE  !FALSE
    typedef const char * VIESTI;
    typedef char * pchar;
    typedef struct _argSt
    {
	VIESTI lippu;
	int    earvo;
	VIESTI selitys;
    } argSt;
    extern int	    usage( pchar argv[], argSt ast[] );
    extern bool     isFlag( VIESTI flag, VIESTI * argv );
    extern int	    tarkarg( VIESTI flag, argSt ast[], VIESTI * extflag );
//

#define KELLO(_no)  (0xE0+(_no))	// piirin perusosoite
#define SETDATE     0x2B		// DOS keskeytyksiä
#define SETTIME     0x2D

typedef struct _datetime
{
    short v,   kk,  pv,
	  h,   m,   s,	 ss;

} datetime;

static short otayksi( short port );
static void  asetayksi( short port, short value );
static void  get_time( datetime * dt );
static void  get_date( datetime * dt );
static void  set_time( datetime * dt );
static void  set_date( datetime * dt );
static void  set_date_time( datetime * dt );
static bool  set_date_time_dos( datetime * dt );
static void  showtime( datetime * dt );




SOURCE_ID( "DATETIME.EXE" );

extern int main( int argc, pchar argv[] )
{
    enum eAflag { ARG_0, ARG_d, ARG_t, ARG_s, ARG_help };
    static argSt liput[] =
    {
	"",	 ARG_0,    "[optiot]",
	"/d",	 ARG_d,    "<pp.kk.vv>",
	"/t",	 ARG_t,    "<tt.mm.ss>",
	"/s",	 ARG_s,    "ei näytetä aikaa",
	"/help", ARG_help, "näytä tämä teksti",
	"/?",	 ARG_help, "\""
			   "\nAjan asetus Hyundai PC/XT:llä."
			   "\nIlman optioita ajan asetus paristovarmennetusta kellosta.",
	NULL,	 ARG_0,    NULL,
    };
    static datetime dts = { 0 };
    short	    i;
    VIESTI	    ext;
    VIESTI	    tim    = NULL,
		    date   = NULL;
    bool	    showdt = TRUE;

    for( i = 1; i < argc; i++ )
    {
	switch( tarkarg( argv[ i ], liput, &ext ) )
	{
	    case ARG_d	:
		date = ext;
		break;
	    case ARG_t	    :
		tim = ext;
		break;
	    case ARG_s	    :
		showdt = FALSE;
		break;
	    case ARG_help   :
		usage( argv, liput );
		return 0;
		break;
	    case ARG_0	    :
		return usage( argv, liput );
		break;
	}
    }

    get_date( &dts );
    get_time( &dts );

    if( date != NULL )
    {
	char dump;
	if( sscanf( date, "%d%c%d%c%d", &dts.pv, &dump, &dts.kk, &dump, &dts.v ) != 5 )
	    return usage( argv, liput );
	if( dts.v > 2000 )	    /* kannattaisi ostaa uusi kone */
	    return usage( argv, liput );
	if( dts.v < 100 )
	    dts.v += 1900;
    }

    if( tim != NULL )
    {
	char dump;
	if( sscanf( tim, "%d%c%d%c%d", &dts.h, &dump, &dts.m, &dump, &dts.s ) != 5 )
	    return usage( argv, liput );
    }

    if( set_date_time_dos( &dts ) == TRUE )
    {
	showtime( &dts );
	return usage( argv, liput );
    }
    set_date_time( &dts );

    if( showdt == TRUE )
	showtime( &dts );

    return 0;
}

static short otayksi( short port )
{
    //	Luetaan arvo peräkkäisistä porteista.
    //
    short arvo = (short)( _inp( port ) & 0x0F );
    return (short) ( ( _inp( port + 1 ) & 0x0F ) * 10 + arvo );
}

static void asetayksi( short port, short value )
{
    //	Kirjoitetaan arvo peräkkäisiin portteihin.
    //
    div_t bcd_values = div( value, 10 );
    _outp( port,     bcd_values.quot );
    _outp( port - 1, bcd_values.rem  );
}

static void get_time( datetime * dt )
{
    //	Aloita
    //
    _outp( KELLO( 0x0D ), 0 );

    dt->ss = 0;
    dt->s  = otayksi( KELLO( 0x00 ) );
    dt->m  = otayksi( KELLO( 0x02 ) );
    dt->h  = otayksi( KELLO( 0x04 ) );

    //	Valmis.
    //
    _outp( KELLO( 0x0D ), 8 );
}

static void get_date( datetime * dt )
{
    //	Aloita.
    //
    _outp( KELLO( 0x0D ), 0 );

    dt->pv = otayksi( KELLO( 0x07 ) );
    dt->kk = otayksi( KELLO( 0x09 ) );
    dt->v  = (short) ( otayksi( KELLO( 0x0B ) ) + 1900 );

    //	Valmis.
    //
    _outp( KELLO( 0x0D ), 8 );

#if 0 /* vaihda konetta, on jo aika */
    if( _inp( KELLO( 0x0D ) ) & 0x80 == 0 )
	dt->v += 100;	   /* 19xx + 100 = 20xx */
#endif
}

static void set_date_time( datetime * dt )
{
    //	startset
    //
    _outp( KELLO( 0x0E ), 0 );
    _outp( KELLO( 0x0E ), 0 );
    _outp( KELLO( 0x0D ), 1 );
    _outp( KELLO( 0x0A ), 1 );
    _outp( KELLO( 0x0B ), 0 );
    _outp( KELLO( 0x0D ), 0 );
    _outp( KELLO( 0x0F ), 2 );

    set_date( dt );
    set_time( dt );

    //	endset
    _outp( KELLO( 0x0D ), 8 );
}

static void set_date( datetime * dt )
{
    asetayksi( KELLO( 0x0C ), (short) ( dt->v - 1900 ) );
    asetayksi( KELLO( 0x0A ), dt->kk );
    asetayksi( KELLO( 0x08 ), dt->pv );
}

static void set_time( datetime * dt )
{
    asetayksi( KELLO( 0x05 ), dt->h );
    asetayksi( KELLO( 0x03 ), dt->m );
    asetayksi( KELLO( 0x01 ), dt->s );
}

//  Aseta DOS oikeaan aikaan.
//
static bool set_date_time_dos( datetime * dt )
{
    union _REGS r;

    r.h.ah = SETDATE;
    r.x.cx = dt->v;
    r.h.dh = ( char ) dt->kk;
    r.h.dl = ( char ) dt->pv;
    _intdos( &r, &r );
    if( r.h.al != 0 )
    {
	printf( "Virheellinen päivämäärä\n" );
	return TRUE;
    }

    r.h.ah = SETTIME;
    r.h.ch = ( char ) dt->h;
    r.h.cl = ( char ) dt->m;
    r.h.dh = ( char ) dt->s;
    r.h.dl = ( char ) dt->ss;
    _intdos( &r, &r );
    if( r.h.al != 0 )
    {
	printf( "Virheellinen aika\n" );
	return TRUE;
    }
    return FALSE;
}

static void showtime( datetime * dt )
{
    printf( "%02d.%02d.%d kello %02d.%02d.%02d,%02d\n",
	     dt->pv, dt->kk, dt->v, dt->h,  dt->m,  dt->s,  dt->ss );
}

// Muutama funktio kirjastosta


#include <string.h>

extern int usage( pchar argv[], argSt ast[] )
{
    VIESTI pN = argv[ 0 ];

    int i = strlen( pN );
    for( pN += i ; i > 0 && strchr( "\\:/", *( --pN ) ) == NULL ; )
	i--;
    ast[ 0 ].lippu = argv[ 0 ] + i;

    for( i = 0 ; ast[ i ].lippu != NULL ; )
    {
	VIESTI p ;
	if( ( p = ast[ i ].selitys ) == NULL )
	    p = "" ;
	printf( "%-14s%s\n", ast[ i ].lippu, p );
    }
    return -1;
}

extern int tarkarg( VIESTI arg, argSt ast[], VIESTI * endarg )
{
    int    i,
	   len;
    VIESTI p,
	   tmp = NULL;

    *endarg = arg;

    /*	Tarkasta ensin onko argumentti lippu.
     */
    if( *arg != '/' && *arg != '-' )
	return ast[ 0 ].earvo;

    arg++;

    /*	Tarkista liput.
     */
    for( i = 1; ( p = ast[ i ].lippu ) != NULL; i++ )
    {
	/*  Laske lipun pituus, koska argumentilla voi olla lisäosa,
	 *  esim. /oTEMPFILE.TMP .
	 */
	if( ( len = strlen( p ) ) == 0 )
	    return ast[ 0 ].earvo;	       /* virhe */

	/*  Verrataan lipun alkumerkin jälkeen.
	 */
	len--;
	p++;
	if( _strnicmp( arg, p, len ) == 0 )
	{
	    /*	Tarkista lisäosa.
	     */
	    p = arg + len;
	    *endarg = ( *p != '\0' ) ? p : NULL;
	    return ast[ i ].earvo;
	}
    }

    /*	Ei löytynyt vastaavaa lippua.
     */
    return ast[ 0 ].earvo;
}

/****************************	TIEDOSTON LOPPU    ***************************/
[ RETURN TO DIRECTORY ]