1
0
Fork 0

- Add midnight/next day increment

- Add date and time commands (functionality limited)

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3715
This commit is contained in:
Ralf Grillenberger 2011-06-05 18:28:00 +00:00
parent 1887b2590b
commit a5ee614503
5 changed files with 218 additions and 26 deletions

View file

@ -87,6 +87,8 @@ public:
void CMD_HELP(char * args);
void CMD_CLS(char * args);
void CMD_COPY(char * args);
void CMD_DATE(char * args);
void CMD_TIME(char * args);
void CMD_DIR(char * args);
void CMD_DELETE(char * args);
void CMD_ECHO(char * args);

View file

@ -20,7 +20,6 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "dosbox.h"
#include "bios.h"
#include "mem.h"
@ -41,6 +40,34 @@ void DOS_SetError(Bit16u code) {
dos.errorcode=code;
}
const Bit8u DOS_DATE_months[] = {
0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
static void DOS_AddDays(Bitu days) {
dos.date.day += days;
Bit8u monthlimit = DOS_DATE_months[dos.date.month];
if(dos.date.day > monthlimit) {
if((dos.date.year %4 == 0) && (dos.date.month==2)) {
// leap year
if(dos.date.day > 29) {
dos.date.month++;
dos.date.day -= 29;
}
} else {
//not leap year
dos.date.month++;
dos.date.day -= monthlimit;
}
if(dos.date.month > 12) {
// year over
dos.date.month = 1;
dos.date.year++;
}
}
}
#define DATA_TRANSFERS_TAKE_CYCLES 1
#ifdef DATA_TRANSFERS_TAKE_CYCLES
@ -373,6 +400,9 @@ static Bitu DOS_21Handler(void) {
break;
case 0x2a: /* Get System Date */
{
reg_ax=0; // get time
CALLBACK_RunRealInt(0x1a);
if(reg_al) DOS_AddDays(reg_al);
int a = (14 - dos.date.month)/12;
int y = dos.date.year - a;
int m = dos.date.month + 12*a - 2;
@ -385,28 +415,37 @@ static Bitu DOS_21Handler(void) {
case 0x2b: /* Set System Date */
if (reg_cx<1980) { reg_al=0xff;break;}
if ((reg_dh>12) || (reg_dh==0)) { reg_al=0xff;break;}
if ((reg_dl>31) || (reg_dl==0)) { reg_al=0xff;break;}
if (reg_dl==0) { reg_al=0xff;break;}
if (reg_dl>DOS_DATE_months[reg_dh]) {
if(!((reg_dh==2)&&(reg_cx%4 == 0)&&(reg_dl==29))) // february pass
{ reg_al=0xff;break; }
}
dos.date.year=reg_cx;
dos.date.month=reg_dh;
dos.date.day=reg_dl;
reg_al=0;
break;
case 0x2c: /* Get System Time */
//TODO Get time through bios calls date is fixed
{
/* Calculate how many miliseconds have passed */
Bitu ticks=5*(mem_readd(BIOS_TIMER) - time_start);
ticks = ((ticks / 59659u) << 16) + ((ticks % 59659u) << 16) / 59659u;
Bitu seconds=(ticks/100);
reg_ch=(Bit8u)(seconds/3600);
reg_cl=(Bit8u)((seconds % 3600)/60);
reg_dh=(Bit8u)(seconds % 60);
reg_dl=(Bit8u)(ticks % 100);
}
case 0x2c: { /* Get System Time */
reg_ax=0; // get time
CALLBACK_RunRealInt(0x1a);
if(reg_al) DOS_AddDays(reg_al);
Bitu time=((Bitu)reg_cx<<16)|reg_dx;
Bitu ticks=(Bitu)(5.49254945 * (double)time);
reg_dl=(Bit8u)((Bitu)ticks % 100); // 1/100 seconds
ticks/=100;
reg_dh=(Bit8u)((Bitu)ticks % 60); // seconds
ticks/=60;
reg_cl=(Bit8u)((Bitu)ticks % 60); // minutes
ticks/=60;
reg_ch=(Bit8u)((Bitu)ticks % 24); // hours
//Simulate DOS overhead for timing-sensitive games
//Robomaze 2
//Robomaze 2
overhead();
break;
}
case 0x2d: /* Set System Time */
LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Set System Time not supported");
//Check input parameters nonetheless
@ -1188,16 +1227,6 @@ public:
dos.version.major=5;
dos.version.minor=0;
/* Setup time and date */
time_t curtime;struct tm *loctime;
curtime = time (NULL);loctime = localtime (&curtime);
dos.date.day=(Bit8u)loctime->tm_mday;
dos.date.month=(Bit8u)loctime->tm_mon+1;
dos.date.year=(Bit16u)loctime->tm_year+1900;
Bit32u ticks=(Bit32u)((loctime->tm_hour*3600+loctime->tm_min*60+loctime->tm_sec)*(float)PIT_TICK_RATE/65536.0);
mem_writed(BIOS_TIMER,ticks);
}
~DOS(){
for (Bit16u i=0;i<DOS_DRIVES;i++) delete Drives[i];

View file

@ -30,6 +30,8 @@
#include "mouse.h"
#include "setup.h"
#include "serialport.h"
#include <time.h>
#include <sys/timeb.h>
/* if mem_systems 0 then size_extended is reported as the real size else
@ -311,7 +313,8 @@ static Bitu INT1A_Handler(void) {
case 0x00: /* Get System time */
{
Bit32u ticks=mem_readd(BIOS_TIMER);
reg_al=0; /* Midnight never passes :) */
reg_al=mem_readb(BIOS_24_HOURS_FLAG);
mem_writeb(BIOS_24_HOURS_FLAG,0); // reset the "flag"
reg_cx=(Bit16u)(ticks >> 16);
reg_dx=(Bit16u)(ticks & 0xffff);
break;
@ -371,9 +374,45 @@ static Bitu INT11_Handler(void) {
#ifndef DOSBOX_CLOCKSYNC
#define DOSBOX_CLOCKSYNC 0
#endif
static void BIOS_HostTimeSync() {
/* Setup time and date */
struct timeb timebuffer;
ftime(&timebuffer);
struct tm *loctime;
loctime = localtime (&timebuffer.time);
/*
loctime->tm_hour = 23;
loctime->tm_min = 59;
loctime->tm_sec = 45;
loctime->tm_mday = 28;
loctime->tm_mon = 2-1;
loctime->tm_year = 2007 - 1900;
*/
dos.date.day=(Bit8u)loctime->tm_mday;
dos.date.month=(Bit8u)loctime->tm_mon+1;
dos.date.year=(Bit16u)loctime->tm_year+1900;
Bit32u ticks=(Bit32u)(((double)(
loctime->tm_hour*3600*1000+
loctime->tm_min*60*1000+
loctime->tm_sec*1000+
timebuffer.millitm))*(((double)PIT_TICK_RATE/65536.0)/1000.0));
mem_writed(BIOS_TIMER,ticks);
}
static Bitu INT8_Handler(void) {
/* Increase the bios tick counter */
Bit32u value = mem_readd(BIOS_TIMER) + 1;
if(value >= 0x1800B0) {
// time wrap at midnight
mem_writeb(BIOS_24_HOURS_FLAG,mem_readb(BIOS_24_HOURS_FLAG)+1);
value=0;
}
#if DOSBOX_CLOCKSYNC
static bool check = false;
if((value %50)==0) {
@ -1079,6 +1118,7 @@ public:
size_extended=IO_Read(0x71);
IO_Write(0x70,0x31);
size_extended|=(IO_Read(0x71) << 8);
BIOS_HostTimeSync();
}
~BIOS(){
/* abort DAC playing */

View file

@ -464,6 +464,23 @@ void SHELL_Init() {
MSG_Add("SHELL_CMD_CHDIR_HINT","To change to different drive type \033[31m%c:\033[0m\n");
MSG_Add("SHELL_CMD_CHDIR_HINT_2","directoryname is longer than 8 characters and/or contains spaces.\nTry \033[31mcd %s\033[0m\n");
MSG_Add("SHELL_CMD_CHDIR_HINT_3","You are still on drive Z:, change to a mounted drive with \033[31mC:\033[0m.\n");
MSG_Add("SHELL_CMD_DATE_HELP","Displays or changes the internal date.\n");
MSG_Add("SHELL_CMD_DATE_ERROR","The specified date is not correct.\n");
MSG_Add("SHELL_CMD_DATE_DAYS","3SunMonTueWedThuFriSat"); // "2SoMoDiMiDoFrSa"
MSG_Add("SHELL_CMD_DATE_NOW","Current date: ");
MSG_Add("SHELL_CMD_DATE_SETHLP","Type 'date MM-DD-YYYY' to change.\n");
MSG_Add("SHELL_CMD_DATE_FORMAT","M/D/Y");
MSG_Add("SHELL_CMD_DATE_HELP_LONG","DATE [[/T] [/H] [/S] | MM-DD-YYYY]\n"\
" MM-DD-YYYY: new date to set\n"\
" /S: Permanently use host time and date as DOS time\n"\
" /F: Switch back to DOSBox internal time (opposite of /S)\n"\
" /T: Only display date\n"\
" /H: Synchronize with host\n");
MSG_Add("SHELL_CMD_TIME_HELP","Displays the internal time.\n");
MSG_Add("SHELL_CMD_TIME_NOW","Current time: ");
MSG_Add("SHELL_CMD_TIME_HELP_LONG","TIME [/T] [/H]\n"\
" /T: Display simple time\n"\
" /H: Synchronize with host\n");
MSG_Add("SHELL_CMD_MKDIR_ERROR","Unable to make: %s.\n");
MSG_Add("SHELL_CMD_RMDIR_ERROR","Unable to remove: %s.\n");
MSG_Add("SHELL_CMD_DEL_ERROR","Unable to delete: %s.\n");

View file

@ -29,6 +29,7 @@
#include <cstdlib>
#include <vector>
#include <string>
#include <time.h>
static SHELL_Cmd cmd_list[]={
{ "DIR", 0, &DOS_Shell::CMD_DIR, "SHELL_CMD_DIR_HELP"},
@ -39,6 +40,7 @@ static SHELL_Cmd cmd_list[]={
{ "CHOICE", 1, &DOS_Shell::CMD_CHOICE, "SHELL_CMD_CHOICE_HELP"},
{ "CLS", 0, &DOS_Shell::CMD_CLS, "SHELL_CMD_CLS_HELP"},
{ "COPY", 0, &DOS_Shell::CMD_COPY, "SHELL_CMD_COPY_HELP"},
{ "DATE", 0, &DOS_Shell::CMD_DATE, "SHELL_CMD_DATE_HELP"},
{ "DEL", 0, &DOS_Shell::CMD_DELETE, "SHELL_CMD_DELETE_HELP"},
{ "DELETE", 1, &DOS_Shell::CMD_DELETE, "SHELL_CMD_DELETE_HELP"},
{ "ERASE", 1, &DOS_Shell::CMD_DELETE, "SHELL_CMD_DELETE_HELP"},
@ -61,6 +63,7 @@ static SHELL_Cmd cmd_list[]={
{ "SET", 1, &DOS_Shell::CMD_SET, "SHELL_CMD_SET_HELP"},
{ "SHIFT", 1, &DOS_Shell::CMD_SHIFT, "SHELL_CMD_SHIFT_HELP"},
{ "SUBST", 1, &DOS_Shell::CMD_SUBST, "SHELL_CMD_SUBST_HELP"},
{ "TIME", 0, &DOS_Shell::CMD_TIME, "SHELL_CMD_TIME_HELP"},
{ "TYPE", 0, &DOS_Shell::CMD_TYPE, "SHELL_CMD_TYPE_HELP"},
{ "VER", 0, &DOS_Shell::CMD_VER, "SHELL_CMD_VER_HELP"},
{0,0,0,0}
@ -937,6 +940,107 @@ void DOS_Shell::CMD_CALL(char * args){
this->call=false;
}
void DOS_Shell::CMD_DATE(char * args) {
HELP("DATE");
if(ScanCMDBool(args,"h")) {
// synchronize date with host parameter
time_t curtime;
struct tm *loctime;
curtime = time (NULL);
loctime = localtime (&curtime);
reg_cx = loctime->tm_year+1900;
reg_dh = loctime->tm_mon+1;
reg_dl = loctime->tm_mday;
reg_ah=0x2b; // set system date
CALLBACK_RunRealInt(0x21);
return;
}
// check if a date was passed in command line
Bitu newday,newmonth,newyear;
if(sscanf(args,"%u-%u-%u",&newmonth,&newday,&newyear)==3) {
reg_cx = newyear;
reg_dh = newmonth;
reg_dl = newday;
reg_ah=0x2b; // set system date
CALLBACK_RunRealInt(0x21);
if(reg_al==0xff) WriteOut(MSG_Get("SHELL_CMD_DATE_ERROR"));
return;
}
// display the current date
reg_ah=0x2a; // get system date
CALLBACK_RunRealInt(0x21);
const char* datestring = MSG_Get("SHELL_CMD_DATE_DAYS");
Bit8u length;
char day[6] = {0};
if(sscanf(datestring,"%u",&length) && (length<5) && (strlen(datestring)==(length*7+1))) {
// date string appears valid
for(int i = 0; i < length; i++) day[i] = datestring[reg_al*length+1+i];
}
bool dateonly = ScanCMDBool(args,"t");
if(!dateonly) WriteOut(MSG_Get("SHELL_CMD_DATE_NOW"));
const char* formatstring = MSG_Get("SHELL_CMD_DATE_FORMAT");
if(strlen(formatstring)!=5) return;
char buffer[15] = {0};
Bitu bufferptr=0;
for(Bitu i = 0; i < 5; i++) {
if(i==1 || i==3) {
buffer[bufferptr] = formatstring[i];
bufferptr++;
} else {
if(formatstring[i]=='M') bufferptr += sprintf(buffer+bufferptr,"%02u",(Bitu)reg_dh);
if(formatstring[i]=='D') bufferptr += sprintf(buffer+bufferptr,"%02u",(Bitu)reg_dl);
if(formatstring[i]=='Y') bufferptr += sprintf(buffer+bufferptr,"%04u",(Bitu)reg_cx);
}
}
WriteOut("%s %s\n",day, buffer);
if(!dateonly) WriteOut(MSG_Get("SHELL_CMD_DATE_SETHLP"));
};
void DOS_Shell::CMD_TIME(char * args) {
HELP("TIME");
if(ScanCMDBool(args,"h")) {
// synchronize time with host parameter
time_t curtime;
struct tm *loctime;
curtime = time (NULL);
loctime = localtime (&curtime);
//reg_cx = loctime->;
//reg_dh = loctime->;
//reg_dl = loctime->;
// reg_ah=0x2d; // set system time TODO
// CALLBACK_RunRealInt(0x21);
Bit32u ticks=(Bit32u)(((double)(loctime->tm_hour*3600+
loctime->tm_min*60+
loctime->tm_sec))*18.206481481);
mem_writed(BIOS_TIMER,ticks);
return;
}
bool timeonly = ScanCMDBool(args,"t");
reg_ah=0x2c; // get system time
CALLBACK_RunRealInt(0x21);
/*
reg_dl= // 1/100 seconds
reg_dh= // seconds
reg_cl= // minutes
reg_ch= // hours
*/
if(timeonly) {
WriteOut("%2u:%02u\n",reg_ch,reg_cl);
} else {
WriteOut(MSG_Get("SHELL_CMD_TIME_NOW"));
WriteOut("%2u:%02u:%02u,%02u\n",reg_ch,reg_cl,reg_dh,reg_dl);
}
};
void DOS_Shell::CMD_SUBST (char * args) {
/* If more that one type can be substed think of something else
* E.g. make basedir member dos_drive instead of localdrive