home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD1.iso / Emulatoren / UAE061.LZH / uae-0.6.1 / cia.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  15.5 KB  |  728 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * CIA chip support
  5.   *
  6.   * Copyright 1995 Bernd Schmidt, Alessandro Bissacco
  7.   * Copyright 1996 Stefan Reinauer
  8.   */
  9.  
  10. #include "sysconfig.h"
  11. #include "sysdeps.h"
  12. #include <assert.h>
  13.  
  14. #include "config.h"
  15. #include "options.h"
  16. #include "events.h"
  17. #include "memory.h"
  18. #include "custom.h"
  19. #include "cia.h"
  20. #include "disk.h"
  21. #include "xwin.h"
  22. #include "keybuf.h"
  23. #include "gui.h"
  24.  
  25. #define DIV10 5 /* Yes, a bad identifier. */
  26.  
  27. /* battclock stuff */
  28. #define RTC_D_ADJ      8
  29. #define RTC_D_IRQ      4
  30. #define RTC_D_BUSY     2
  31. #define RTC_D_HOLD     1
  32. #define RTC_E_t1       8
  33. #define RTC_E_t0       4
  34. #define RTC_E_INTR     2
  35. #define RTC_E_MASK     1
  36. #define RTC_F_TEST     8
  37. #define RTC_F_24_12    4
  38. #define RTC_F_STOP     2
  39. #define RTC_F_RSET     1
  40.  
  41. static UBYTE clock_control_d = RTC_D_ADJ + RTC_D_HOLD;
  42. static UBYTE clock_control_e = 0;
  43. static UBYTE clock_control_f = RTC_F_24_12;
  44.  
  45. static UBYTE ciaaicr,ciaaimask,ciabicr,ciabimask;
  46. static UBYTE ciaacra,ciaacrb,ciabcra,ciabcrb;
  47. static ULONG ciaata,ciaatb,ciabta,ciabtb;
  48. static UWORD ciaala,ciaalb,ciabla,ciablb;
  49. static ULONG ciaatod,ciabtod,ciaatol,ciabtol,ciaaalarm,ciabalarm;
  50. static int ciaatodon, ciabtodon;
  51. static int ciaatlatch,ciabtlatch;
  52. static UBYTE ciaapra=0x2, /*  the led is off in the beginning */
  53. ciaaprb,ciaadra,ciaadrb,ciaasdr;
  54. static UBYTE ciabpra,ciabprb,ciabdra,ciabdrb,ciabsdr; 
  55. static int div10;
  56. static int kbstate, kback;
  57.  
  58. static int prtopen;
  59. static FILE *prttmp;
  60.  
  61. static void setclr(UBYTE *p, UBYTE val)
  62. {
  63.     if (val & 0x80) {
  64.     *p |= val & 0x7F;
  65.     } else {
  66.     *p &= ~val;
  67.     }
  68. }
  69.  
  70. static void RethinkICRA(void)
  71. {
  72.     if (ciaaimask & ciaaicr) {
  73.     ciaaicr |= 0x80;
  74.     custom_bank.wput(0xDFF09C,0x8008);
  75.     } else {
  76.     ciaaicr &= 0x7F;
  77. /*    custom_bank.wput(0xDFF09C,0x0008);*/
  78.     }
  79. }
  80.  
  81. static void RethinkICRB(void)
  82. {
  83.     if (ciabicr & 0x10) {
  84.     custom_bank.wput(0xDFF09C,0x9000);
  85.     }
  86.     if (ciabimask & ciabicr) {
  87.     ciabicr |= 0x80;
  88.     custom_bank.wput(0xDFF09C,0xA000);
  89.     } else {
  90.     ciabicr &= 0x7F;
  91. /*    custom_bank.wput(0xDFF09C,0x2000);*/
  92.     }
  93. }
  94.  
  95. static int lastdiv10;
  96.  
  97. static void CIA_update(void)
  98. {
  99.     unsigned long int ccount = cycles - eventtab[ev_cia].oldcycles + lastdiv10;
  100.     unsigned long int ciaclocks = ccount / DIV10;
  101.  
  102.     int aovfla = 0, aovflb = 0, bovfla = 0, bovflb = 0;
  103.  
  104.     lastdiv10 = div10;
  105.     div10 = ccount % DIV10;
  106.     
  107.     /* CIA A timers */
  108.     if ((ciaacra & 0x21) == 0x01) {
  109.     assert((ciaata+1) >= ciaclocks);
  110.     if ((ciaata+1) == ciaclocks) {
  111.         aovfla = 1;
  112.         if ((ciaacrb & 0x61) == 0x41) {
  113.         if (ciaatb-- == 0) aovflb = 1;        
  114.         }
  115.     }         
  116.     ciaata -= ciaclocks;
  117.     }
  118.     if ((ciaacrb & 0x61) == 0x01) {
  119.     assert((ciaatb+1) >= ciaclocks);
  120.     if ((ciaatb+1) == ciaclocks) aovflb = 1;
  121.     ciaatb -= ciaclocks;
  122.     }
  123.     
  124.     /* CIA B timers */
  125.     if ((ciabcra & 0x21) == 0x01) {
  126.     assert((ciabta+1) >= ciaclocks);
  127.     if ((ciabta+1) == ciaclocks) {
  128.         bovfla = 1;
  129.         if ((ciabcrb & 0x61) == 0x41) {
  130.         if (ciabtb-- == 0) bovflb = 1;
  131.         }
  132.     } 
  133.     ciabta -= ciaclocks;
  134.     }
  135.     if ((ciabcrb & 0x61) == 0x01) {
  136.     assert ((ciabtb+1) >= ciaclocks);
  137.     if ((ciabtb+1) == ciaclocks) bovflb = 1;
  138.     ciabtb -= ciaclocks;
  139.     }
  140.     if (aovfla) {
  141.     ciaaicr |= 1; RethinkICRA();
  142.     ciaata = ciaala;
  143.     if (ciaacra & 0x8) ciaacra &= ~1;
  144.     }
  145.     if (aovflb) {
  146.     ciaaicr |= 2; RethinkICRA();
  147.     ciaatb = ciaalb;
  148.     if (ciaacrb & 0x8) ciaacrb &= ~1;
  149.     }
  150.     if (bovfla) {
  151.     ciabicr |= 1; RethinkICRB();
  152.     ciabta = ciabla;
  153.     if (ciabcra & 0x8) ciabcra &= ~1;
  154.     }
  155.     if (bovflb) {
  156.     ciabicr |= 2; RethinkICRB();
  157.     ciabtb = ciablb;
  158.     if (ciabcrb & 0x8) ciabcrb &= ~1;
  159.     }
  160. }
  161.  
  162. static void CIA_calctimers(void)
  163. {
  164.     int ciaatimea = -1, ciaatimeb = -1, ciabtimea = -1, ciabtimeb = -1;
  165.  
  166.     eventtab[ev_cia].oldcycles = cycles;
  167.     
  168.     if ((ciaacra & 0x21) == 0x01) {
  169.     ciaatimea = (DIV10-div10) + DIV10*ciaata;    
  170.     }
  171.     if ((ciaacrb & 0x61) == 0x41) {
  172.     /* Timer B will not get any pulses if Timer A is off. */
  173.     if (ciaatimea >= 0) {
  174.         /* If Timer A is in one-shot mode, and Timer B needs more than
  175.          * one pulse, it will not underflow. */
  176.         if (ciaatb == 0 || (ciaacra & 0x8) == 0) {
  177.         /* Otherwise, we can determine the time of the underflow. */
  178.         ciaatimeb = ciaatimea + ciaala * DIV10 * ciaatb;
  179.         }
  180.     }
  181.     }
  182.     if ((ciaacrb & 0x61) == 0x01) {
  183.     ciaatimeb = (DIV10-div10) + DIV10*ciaatb;
  184.     }
  185.  
  186.     if ((ciabcra & 0x21) == 0x01) {
  187.     ciabtimea = (DIV10-div10) + DIV10*ciabta;    
  188.     }
  189.     if ((ciabcrb & 0x61) == 0x41) {
  190.     /* Timer B will not get any pulses if Timer A is off. */
  191.     if (ciabtimea >= 0) {
  192.         /* If Timer A is in one-shot mode, and Timer B needs more than
  193.          * one pulse, it will not underflow. */
  194.         if (ciabtb == 0 || (ciabcra & 0x8) == 0) {
  195.         /* Otherwise, we can determine the time of the underflow. */
  196.         ciabtimeb = ciabtimea + ciabla * DIV10 * ciabtb;
  197.         }
  198.     }
  199.     }
  200.     if ((ciabcrb & 0x61) == 0x01) {
  201.     ciabtimeb = (DIV10-div10) + DIV10*ciabtb;
  202.     }
  203.     eventtab[ev_cia].active = (ciaatimea != -1 || ciaatimeb != -1
  204.                    || ciabtimea != -1 || ciabtimeb != -1);
  205.     if (eventtab[ev_cia].active) {
  206.     unsigned long int ciatime = ~0L;
  207.     if (ciaatimea != -1) ciatime = ciaatimea;
  208.     if (ciaatimeb != -1 && ciaatimeb < ciatime) ciatime = ciaatimeb;
  209.     if (ciabtimea != -1 && ciabtimea < ciatime) ciatime = ciabtimea;
  210.     if (ciabtimeb != -1 && ciabtimeb < ciatime) ciatime = ciabtimeb;
  211.     eventtab[ev_cia].evtime = ciatime;
  212.     }
  213.     events_schedule();
  214. }
  215.  
  216. void CIA_handler(void)
  217. {
  218.     CIA_update();
  219.     CIA_calctimers();
  220. }
  221.  
  222. void diskindex_handler(void)
  223. {
  224.     eventtab[ev_diskindex].oldcycles = cycles;
  225. /*    printf(".\n");*/
  226.     ciabicr |= 0x10;
  227.     RethinkICRB();
  228. }
  229.  
  230. void CIA_hsync_handler(void)
  231. {
  232.     static int keytime = 0;
  233.  
  234.     if (ciabtodon)
  235.     ciabtod++;
  236.     ciabtod &= 0xFFFFFF;
  237.  
  238.     if (ciabtod == ciabalarm) {
  239.     ciabicr |= 4; RethinkICRB();
  240.     }
  241.     if (keys_available() && kback && (++keytime & 15) == 0) {
  242.     switch(kbstate) {
  243.      case 0:
  244.         ciaasdr = (BYTE)~0xFB; /* aaarghh... stupid compiler */
  245.         kbstate++;
  246.         break;
  247.      case 1:
  248.         kbstate++;
  249.         ciaasdr = (BYTE)~0xFD;
  250.         break;
  251.      case 2:
  252.         ciaasdr = ~get_next_key();
  253.         break;
  254.     }
  255.     ciaaicr |= 8; RethinkICRA();
  256.     }
  257. }
  258.  
  259. void CIA_vsync_handler()
  260. {    
  261.     if (ciaatodon) 
  262.     ciaatod++;
  263.     ciaatod &= 0xFFFFFF;
  264.     if (ciaatod == ciaaalarm) {
  265.     ciaaicr |= 4; RethinkICRA();
  266.     }
  267. }
  268.  
  269. static UBYTE ReadCIAA(UWORD addr)
  270. {
  271.     UBYTE tmp;
  272.     
  273.     switch(addr & 0xf){
  274.      case 0: 
  275.     tmp = (DISK_status() & 0x3C);
  276.     if (!buttonstate[0]) tmp |= 0x40;
  277.     if (!joy0button) tmp |= 0x80;
  278.     return tmp;
  279.      case 1:
  280.     return ciaaprb;
  281.      case 2:
  282.     return ciaadra;
  283.      case 3:
  284.     return ciaadrb;
  285.      case 4:
  286.     return ciaata & 0xff;
  287.      case 5:
  288.     return ciaata >> 8;
  289.      case 6:
  290.     return ciaatb & 0xff;
  291.      case 7:
  292.     return ciaatb >> 8;
  293.      case 8:
  294.     if (ciaatlatch) {
  295.         ciaatlatch = 0;
  296.         return ciaatol & 0xff;
  297.     } else return ciaatod & 0xff;
  298.      case 9:
  299.     if (ciaatlatch) return (ciaatol >> 8) & 0xff;
  300.     else return (ciaatod >> 8) & 0xff;
  301.      case 10:
  302.     ciaatlatch = 1; ciaatol = ciaatod; /* ??? only if not already latched? */
  303.     return (ciaatol >> 16) & 0xff;
  304.      case 12:
  305.     return ciaasdr;
  306.      case 13:
  307.     tmp = ciaaicr; ciaaicr = 0; RethinkICRA(); return tmp;
  308.      case 14:
  309.     return ciaacra;
  310.      case 15:
  311.     return ciaacrb;
  312.     }
  313.     return 0;
  314. }
  315.  
  316. static UBYTE ReadCIAB(UWORD addr)
  317. {
  318.     UBYTE tmp;
  319.     
  320.     switch(addr & 0xf){
  321.      case 0: 
  322.     return ciabpra;
  323.      case 1:
  324.     return ciabprb;
  325.      case 2:
  326.     return ciabdra;
  327.      case 3:
  328.     return ciabdrb;
  329.      case 4:
  330.     return ciabta & 0xff;
  331.      case 5:
  332.     return ciabta >> 8;
  333.      case 6:
  334.     return ciabtb & 0xff;
  335.      case 7:
  336.     return ciabtb >> 8;
  337.      case 8:
  338.     if (ciabtlatch) {
  339.         ciabtlatch = 0;
  340.         return ciabtol & 0xff;
  341.     } else return ciabtod & 0xff;
  342.      case 9:
  343.     if (ciabtlatch) return (ciabtol >> 8) & 0xff;
  344.     else return (ciabtod >> 8) & 0xff;
  345.      case 10:
  346.     ciabtlatch = 1; ciabtol = ciabtod;
  347.     return (ciabtol >> 16) & 0xff;
  348.      case 12:
  349.     return ciabsdr;
  350.      case 13:
  351.     tmp = ciabicr; ciabicr = 0; RethinkICRB();
  352.     return tmp;
  353.      case 14:
  354.     return ciabcra;
  355.      case 15:
  356.     return ciabcrb;
  357.     }
  358.     return 0;
  359. }
  360.  
  361. static void WriteCIAA(UWORD addr,UBYTE val)
  362. {
  363.     int oldled;
  364.     switch(addr & 0xf){
  365.      case 0:
  366.     oldled = ciaapra & 2;
  367.     ciaapra = (ciaapra & ~0x3) | (val & 0x3); LED(ciaapra & 0x2);
  368.     if ((ciaapra & 2) != oldled)
  369.         gui_led (0, !(ciaapra & 2));
  370.     break;
  371.      case 1:
  372.     ciaaprb = val;
  373.     if (prtopen==1) {
  374.         fprintf (prttmp,"%c",val);
  375.         if (val==0x04) {
  376. #if defined(__unix) && !defined(__bebox__) && !defined(__DOS__)
  377.         pclose (prttmp);
  378. #else
  379.         fclose (prttmp);
  380. #endif
  381.         prtopen = 0;
  382.         }
  383.         } else {
  384. #if defined(__unix) && !defined(__bebox__) && !defined(__DOS__)
  385.             prttmp=(FILE *)popen ((char *)prtname,"w");
  386. #else
  387.             prttmp=(FILE *)fopen ((char *)prtname,"wb");
  388. #endif
  389.         if (prttmp != NULL) {
  390.         prtopen = 1;
  391.         fprintf (prttmp,"%c",val);
  392.         }
  393.         }
  394.     ciaaicr |= 0x10;
  395.     break;
  396.      case 2:
  397.     ciaadra = val; break;
  398.      case 3:
  399.     ciaadrb = val; break;
  400.      case 4:
  401.     CIA_update();
  402.     ciaala = (ciaala & 0xff00) | val;
  403.     CIA_calctimers();
  404.     break;
  405.      case 5:
  406.     CIA_update();
  407.     ciaala = (ciaala & 0xff) | (val << 8);
  408.     if ((ciaacra & 1) == 0)
  409.         ciaata = ciaala;
  410.     if (ciaacra & 8) { 
  411.         ciaata = ciaala; 
  412.         ciaacra |= 1; 
  413.     }
  414.     CIA_calctimers();
  415.     break;
  416.      case 6:
  417.     CIA_update();
  418.     ciaalb = (ciaalb & 0xff00) | val;
  419.     CIA_calctimers();
  420.     break;
  421.      case 7:
  422.     CIA_update();
  423.     ciaalb = (ciaalb & 0xff) | (val << 8);
  424.     if ((ciaacrb & 1) == 0)
  425.         ciaatb = ciaalb;
  426.     if (ciaacrb & 8) { 
  427.         ciaatb = ciaalb;
  428.         ciaacrb |= 1; 
  429.     }
  430.     CIA_calctimers();
  431.     break;
  432.      case 8:
  433.     if (ciaacrb & 0x80){
  434.         ciaaalarm = (ciaaalarm & ~0xff) | val;
  435.     } else {
  436.         ciaatod = (ciaatod & ~0xff) | val;
  437.         ciaatodon = 1;
  438.     }
  439.     break;
  440.      case 9:
  441.     if (ciaacrb & 0x80){
  442.         ciaaalarm = (ciaaalarm & ~0xff00) | (val << 8);
  443.     } else {
  444.         ciaatod = (ciaatod & ~0xff00) | (val << 8);
  445.         ciaatodon = 0;
  446.     }
  447.     break;
  448.      case 10:
  449.     if (ciaacrb & 0x80){
  450.         ciaaalarm = (ciaaalarm & ~0xff0000) | (val << 16);
  451.     } else {
  452.         ciaatod = (ciaatod & ~0xff0000) | (val << 16);
  453.         ciaatodon = 0;
  454.     }
  455.     break;
  456.      case 12:
  457.     ciaasdr = val; break;
  458.      case 13:
  459.     setclr(&ciaaimask,val); break; /* ??? call RethinkICR() ? */
  460.      case 14:
  461.     CIA_update();
  462.     ciaacra = val;
  463.     if (ciaacra & 0x10){
  464.         ciaacra &= ~0x10;
  465.         ciaata = ciaala;
  466.     }
  467.     if (ciaacra & 0x40) {
  468.         kback = 1;
  469.     }
  470.     CIA_calctimers();
  471.     break;
  472.      case 15:
  473.     CIA_update();
  474.     ciaacrb = val; 
  475.     if (ciaacrb & 0x10){
  476.         ciaacrb &= ~0x10;
  477.         ciaatb = ciaalb;
  478.     }
  479.     CIA_calctimers();
  480.     break;
  481.     }
  482. }
  483.  
  484. static void WriteCIAB(UWORD addr,UBYTE val)
  485. {
  486.     switch(addr & 0xf){
  487.      case 0:
  488.     ciabpra = (ciabpra & ~0x3) | (val & 0x3); break;
  489.      case 1:
  490.     ciabprb = val; DISK_select(val); break;
  491.      case 2:
  492.     ciabdra = val; break;
  493.      case 3:
  494.     ciabdrb = val; break;
  495.      case 4:
  496.     CIA_update();
  497.     ciabla = (ciabla & 0xff00) | val;
  498.     CIA_calctimers();
  499.     break;
  500.      case 5:
  501.     CIA_update();
  502.     ciabla = (ciabla & 0xff) | (val << 8);
  503.     if ((ciabcra & 1) == 0) 
  504.         ciabta = ciabla;
  505.     if (ciabcra & 8) {
  506.         ciabta = ciabla; 
  507.         ciabcra |= 1; 
  508.     } 
  509.     CIA_calctimers();
  510.     break;
  511.      case 6:
  512.     CIA_update();
  513.     ciablb = (ciablb & 0xff00) | val;
  514.     CIA_calctimers();
  515.     break;
  516.      case 7:
  517.     CIA_update();
  518.     ciablb = (ciablb & 0xff) | (val << 8);
  519.     if ((ciabcrb & 1) == 0)
  520.         ciabtb = ciablb;
  521.     if (ciabcrb & 8) {
  522.         ciabtb = ciablb;
  523.         ciabcrb |= 1;
  524.     }
  525.     CIA_calctimers();
  526.     break;
  527.      case 8:
  528.     if (ciabcrb & 0x80){
  529.         ciabalarm = (ciabalarm & ~0xff) | val;
  530.     } else {
  531.         ciabtod = (ciabtod & ~0xff) | val;
  532.         ciabtodon = 1;
  533.     }
  534.     break;
  535.      case 9:
  536.     if (ciabcrb & 0x80){
  537.         ciabalarm = (ciabalarm & ~0xff00) | (val << 8);
  538.     } else {
  539.         ciabtod = (ciabtod & ~0xff00) | (val << 8);
  540.         ciabtodon = 0;
  541.     }
  542.     break;
  543.      case 10:
  544.     if (ciabcrb & 0x80){
  545.         ciabalarm = (ciabalarm & ~0xff0000) | (val << 16);
  546.     } else {
  547.         ciabtod = (ciabtod & ~0xff0000) | (val << 16);
  548.         ciabtodon = 0;
  549.     }
  550.     break;
  551.      case 12:
  552.     ciabsdr = val; 
  553.     break;
  554.      case 13:
  555.     setclr(&ciabimask,val); 
  556.     break;
  557.      case 14:
  558.     CIA_update();
  559.     ciabcra = val;
  560.     if (ciabcra & 0x10){
  561.         ciabcra &= ~0x10;
  562.         ciabta = ciabla;
  563.     }
  564.     CIA_calctimers();
  565.     break;
  566.      case 15:
  567.     CIA_update();
  568.     ciabcrb = val; 
  569.     if (ciabcrb & 0x10){
  570.         ciabcrb &= ~0x10;
  571.         ciabtb = ciablb;
  572.     }
  573.     CIA_calctimers();
  574.     break;
  575.     }
  576. }
  577.  
  578. void CIA_reset(void)
  579. {
  580.     kback = 1;
  581.     kbstate = 0;
  582.     
  583.     ciaatlatch = ciabtlatch = 0;
  584.     ciaatod = ciabtod = 0; ciaatodon = ciabtodon = 0;
  585.     ciaaicr = ciabicr = ciaaimask = ciabimask = 0;
  586.     ciaacra = ciaacrb = ciabcra = ciabcrb = 0x4; /* outmode = toggle; */
  587.     div10 = 0;
  588.     lastdiv10 = 0;
  589.     CIA_calctimers();
  590.  
  591.     ciabpra = 0x04;
  592. }
  593.  
  594. void dumpcia(void)
  595. {
  596.     printf("A: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx, TB: %04lx\n",
  597.        (int)ciaacra, (int)ciaacrb, (int)ciaaimask, ciaatod, 
  598.        ciaatlatch ? " latched" : "", ciaata, ciaatb);
  599.     printf("B: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx, TB: %04lx\n",
  600.        (int)ciabcra, (int)ciabcrb, (int)ciabimask, ciabtod, 
  601.        ciabtlatch ? " latched" : "", ciabta, ciabtb);
  602. }
  603.  
  604. /* CIA memory access */
  605.  
  606. static ULONG cia_lget(CPTR) REGPARAM;
  607. static UWORD cia_wget(CPTR) REGPARAM;
  608. static UBYTE cia_bget(CPTR) REGPARAM;
  609. static void  cia_lput(CPTR, ULONG) REGPARAM;
  610. static void  cia_wput(CPTR, UWORD) REGPARAM;
  611. static void  cia_bput(CPTR, UBYTE) REGPARAM;
  612.  
  613. addrbank cia_bank = {
  614.     cia_lget, cia_wget, cia_bget,
  615.     cia_lput, cia_wput, cia_bput,
  616.     default_xlate, default_check
  617. };
  618.  
  619. ULONG cia_lget(CPTR addr)
  620. {
  621.     return cia_bget(addr+3);
  622. }
  623.  
  624. UWORD cia_wget(CPTR addr)
  625. {
  626.     return cia_bget(addr+1);
  627. }
  628.  
  629. UBYTE cia_bget(CPTR addr)
  630. {
  631.     if ((addr & 0x3001) == 0x2001)
  632.         return ReadCIAA((addr & 0xF00) >> 8);
  633.     if ((addr & 0x3001) == 0x1000)
  634.         return ReadCIAB((addr & 0xF00) >> 8);
  635.     return 0;
  636. }
  637.  
  638. void cia_lput(CPTR addr, ULONG value)
  639. {
  640.     cia_bput(addr+3,value); /* FIXME ? */
  641. }
  642.  
  643. void cia_wput(CPTR addr, UWORD value)
  644. {
  645.     cia_bput(addr+1,value);
  646. }
  647.  
  648. void cia_bput(CPTR addr, UBYTE value)
  649. {
  650.     if ((addr & 0x3001) == 0x2001)
  651.         WriteCIAA((addr & 0xF00) >> 8,value);
  652.     if ((addr & 0x3001) == 0x1000)
  653.         WriteCIAB((addr & 0xF00) >> 8,value);
  654. }
  655.  
  656. /* battclock memory access */
  657.  
  658. static ULONG clock_lget(CPTR) REGPARAM;
  659. static UWORD clock_wget(CPTR) REGPARAM;
  660. static UBYTE clock_bget(CPTR) REGPARAM;
  661. static void  clock_lput(CPTR, ULONG) REGPARAM;
  662. static void  clock_wput(CPTR, UWORD) REGPARAM;
  663. static void  clock_bput(CPTR, UBYTE) REGPARAM;
  664.  
  665. addrbank clock_bank = {
  666.     clock_lget, clock_wget, clock_bget,
  667.     clock_lput, clock_wput, clock_bput,
  668.     default_xlate, default_check
  669. };
  670.  
  671. ULONG clock_lget(CPTR addr)
  672. {
  673.     return clock_bget(addr+3);
  674. }
  675.  
  676. UWORD clock_wget(CPTR addr)
  677. {
  678.     return clock_bget(addr+1);
  679. }
  680.  
  681. UBYTE clock_bget(CPTR addr)
  682. {
  683.     time_t t=time(0);
  684.     struct tm *ct;
  685.     ct=localtime(&t);
  686.     switch (addr & 0x3f)
  687.     {
  688.      case 0x03: return ct->tm_sec % 10;
  689.      case 0x07: return ct->tm_sec / 10;
  690.      case 0x0b: return ct->tm_min % 10;
  691.      case 0x0f: return ct->tm_min / 10;
  692.      case 0x13: return ct->tm_hour % 10;
  693.      case 0x17: return ct->tm_hour / 10;
  694.      case 0x1b: return ct->tm_mday % 10;
  695.      case 0x1f: return ct->tm_mday / 10;
  696.      case 0x23: return (ct->tm_mon+1) % 10;
  697.      case 0x27: return (ct->tm_mon+1) / 10;
  698.      case 0x2b: return ct->tm_year % 10;
  699.      case 0x2f: return ct->tm_year / 10;
  700.  
  701.      case 0x33: return ct->tm_wday;  /*Hack by -=SR=- */
  702.      case 0x37: return clock_control_d;
  703.      case 0x3b: return clock_control_e;
  704.      case 0x3f: return clock_control_f;
  705.     }
  706.     return 0;
  707. }
  708.  
  709. void clock_lput(CPTR addr, ULONG value)
  710. {
  711.     /* No way */
  712. }
  713.  
  714. void clock_wput(CPTR addr, UWORD value)
  715. {
  716.     /* No way */
  717. }
  718.  
  719. void clock_bput(CPTR addr, UBYTE value)
  720. {
  721.     switch (addr & 0x3f)
  722.     {
  723.      case 0x37: clock_control_d=value; break;
  724.      case 0x3b: clock_control_e=value; break;
  725.      case 0x3f: clock_control_f=value; break;
  726.     }
  727. }
  728.