#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 ***************************/