home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / RTC.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-05-13  |  6.4 KB  |  221 lines

  1. // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
  2. // Copyright (C) 1999-2003 Forgotten
  3. // Copyright (C) 2004 Forgotten and the VBA development team
  4.  
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 2, or(at your option)
  8. // any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software Foundation,
  17. // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18.  
  19. #include "System.h"
  20. #include "GBA.h"
  21. #include "Globals.h"
  22. #include "Port.h"
  23. #include "Util.h"
  24. #include "NLS.h"
  25.  
  26. #include <time.h>
  27. #include <memory.h>
  28.  
  29. enum RTCSTATE { IDLE, COMMAND, DATA, READDATA };
  30.  
  31. typedef struct {
  32.   u8 byte0;
  33.   u8 byte1;
  34.   u8 byte2;
  35.   u8 command;
  36.   int dataLen;
  37.   int bits;
  38.   RTCSTATE state;
  39.   u8 data[12];
  40.   // reserved variables for future
  41.   u8 reserved[12];
  42.   bool reserved2;
  43.   u32 reserved3;
  44. } RTCCLOCKDATA;
  45.  
  46. static RTCCLOCKDATA rtcClockData;
  47. static bool rtcEnabled = false;
  48.  
  49. void rtcEnable(bool e)
  50. {
  51.   rtcEnabled = e;
  52. }
  53.  
  54. bool rtcIsEnabled()
  55. {
  56.   return rtcEnabled;
  57. }
  58.  
  59. u16 rtcRead(u32 address)
  60. {
  61.   if(rtcEnabled) {
  62.     if(address == 0x80000c8)
  63.       return rtcClockData.byte2;
  64.     else if(address == 0x80000c6)
  65.       return rtcClockData.byte1;
  66.     else if(address == 0x80000c4) {
  67.       return rtcClockData.byte0;
  68.     }
  69.   }
  70.   
  71.   return READ16LE((&rom[address & 0x1FFFFFE]));
  72. }
  73.  
  74. static u8 toBCD(u8 value)
  75. {
  76.   value = value % 100;
  77.   int l = value % 10;
  78.   int h = value / 10;
  79.   return h * 16 + l;
  80. }
  81.  
  82. bool rtcWrite(u32 address, u16 value)
  83. {
  84.   if(!rtcEnabled)
  85.     return false;
  86.   
  87.   if(address == 0x80000c8) {
  88.     rtcClockData.byte2 = (u8)value; // enable ?
  89.   } else if(address == 0x80000c6) {
  90.     rtcClockData.byte1 = (u8)value; // read/write
  91.   } else if(address == 0x80000c4) {
  92.     if(rtcClockData.byte2 & 1) {
  93.       if(rtcClockData.state == IDLE && rtcClockData.byte0 == 1 && value == 5) {
  94.           rtcClockData.state = COMMAND;
  95.           rtcClockData.bits = 0;
  96.           rtcClockData.command = 0;
  97.       } else if(!(rtcClockData.byte0 & 1) && (value & 1)) { // bit transfer
  98.         rtcClockData.byte0 = (u8)value;        
  99.         switch(rtcClockData.state) {
  100.         case COMMAND:
  101.           rtcClockData.command |= ((value & 2) >> 1) << (7-rtcClockData.bits);
  102.           rtcClockData.bits++;
  103.           if(rtcClockData.bits == 8) {
  104.             rtcClockData.bits = 0;
  105.             switch(rtcClockData.command) {
  106.             case 0x60:
  107.               // not sure what this command does but it doesn't take parameters
  108.               // maybe it is a reset or stop
  109.               rtcClockData.state = IDLE;
  110.               rtcClockData.bits = 0;
  111.               break;
  112.             case 0x62:
  113.               // this sets the control state but not sure what those values are
  114.               rtcClockData.state = READDATA;
  115.               rtcClockData.dataLen = 1;
  116.               break;
  117.             case 0x63:
  118.               rtcClockData.dataLen = 1;
  119.               rtcClockData.data[0] = 0x40;
  120.               rtcClockData.state = DATA;
  121.               break;
  122.             case 0x65:
  123.               {
  124.                 struct tm *newtime;
  125.                 time_t long_time;
  126.  
  127.                 time( &long_time );                /* Get time as long integer. */
  128.                 newtime = localtime( &long_time ); /* Convert to local time. */
  129.                 
  130.                 rtcClockData.dataLen = 7;
  131.                 rtcClockData.data[0] = toBCD(newtime->tm_year);
  132.                 rtcClockData.data[1] = toBCD(newtime->tm_mon+1);
  133.                 rtcClockData.data[2] = toBCD(newtime->tm_mday);
  134.                 rtcClockData.data[3] = 0;
  135.                 rtcClockData.data[4] = toBCD(newtime->tm_hour);
  136.                 rtcClockData.data[5] = toBCD(newtime->tm_min);
  137.                 rtcClockData.data[6] = toBCD(newtime->tm_sec);
  138.                 rtcClockData.state = DATA;
  139.               }
  140.               break;              
  141.             case 0x67:
  142.               {
  143.                 struct tm *newtime;
  144.                 time_t long_time;
  145.  
  146.                 time( &long_time );                /* Get time as long integer. */
  147.                 newtime = localtime( &long_time ); /* Convert to local time. */
  148.                 
  149.                 rtcClockData.dataLen = 3;
  150.                 rtcClockData.data[0] = toBCD(newtime->tm_hour);
  151.                 rtcClockData.data[1] = toBCD(newtime->tm_min);
  152.                 rtcClockData.data[2] = toBCD(newtime->tm_sec);
  153.                 rtcClockData.state = DATA;
  154.               }
  155.               break;
  156.             default:
  157.               systemMessage(0, N_("Unknown RTC command %02x"), rtcClockData.command);
  158.               rtcClockData.state = IDLE;
  159.               break;
  160.             }
  161.           }
  162.           break;
  163.         case DATA:
  164.           if(rtcClockData.byte1 & 2) {
  165.           } else {
  166.             rtcClockData.byte0 = (rtcClockData.byte0 & ~2) |
  167.               ((rtcClockData.data[rtcClockData.bits >> 3] >>
  168.                 (rtcClockData.bits & 7)) & 1)*2;
  169.             rtcClockData.bits++;
  170.             if(rtcClockData.bits == 8*rtcClockData.dataLen) {
  171.               rtcClockData.bits = 0;
  172.               rtcClockData.state = IDLE;
  173.             }
  174.           }
  175.           break;
  176.         case READDATA:
  177.           if(!(rtcClockData.byte1 & 2)) {
  178.           } else {
  179.             rtcClockData.data[rtcClockData.bits >> 3] =
  180.               (rtcClockData.data[rtcClockData.bits >> 3] >> 1) |
  181.               ((value << 6) & 128);
  182.             rtcClockData.bits++;
  183.             if(rtcClockData.bits == 8*rtcClockData.dataLen) {
  184.               rtcClockData.bits = 0;
  185.               rtcClockData.state = IDLE;
  186.             }
  187.           }
  188.           break;
  189.         default:
  190.           break;
  191.         }
  192.       } else
  193.         rtcClockData.byte0 = (u8)value;
  194.     }
  195.   }
  196.   return true;
  197. }
  198.  
  199. void rtcReset()
  200. {
  201.   memset(&rtcClockData, 0, sizeof(rtcClockData));
  202.   
  203.   rtcClockData.byte0 = 0;
  204.   rtcClockData.byte1 = 0;
  205.   rtcClockData.byte2 = 0;
  206.   rtcClockData.command = 0;
  207.   rtcClockData.dataLen = 0;
  208.   rtcClockData.bits = 0;
  209.   rtcClockData.state = IDLE;
  210. }
  211.  
  212. void rtcSaveGame(gzFile gzFile)
  213. {
  214.   utilGzWrite(gzFile, &rtcClockData, sizeof(rtcClockData));
  215. }
  216.  
  217. void rtcReadGame(gzFile gzFile)
  218. {
  219.   utilGzRead(gzFile, &rtcClockData, sizeof(rtcClockData));
  220. }
  221.