Annotation of uae/src/cia.c, revision 1.1.1.10

1.1.1.3   root        1:  /*
1.1       root        2:   * UAE - The Un*x Amiga Emulator
1.1.1.3   root        3:   *
1.1       root        4:   * CIA chip support
                      5:   *
                      6:   * Copyright 1995 Bernd Schmidt, Alessandro Bissacco
1.1.1.3   root        7:   * Copyright 1996, 1997 Stefan Reinauer, Christian Schmitt
1.1       root        8:   */
                      9: 
                     10: #include "sysconfig.h"
                     11: #include "sysdeps.h"
                     12: #include <assert.h>
                     13: 
                     14: #include "config.h"
                     15: #include "options.h"
1.1.1.3   root       16: #include "threaddep/penguin.h"
1.1       root       17: #include "events.h"
                     18: #include "memory.h"
                     19: #include "custom.h"
                     20: #include "cia.h"
1.1.1.3   root       21: #include "serial.h"
1.1       root       22: #include "disk.h"
                     23: #include "xwin.h"
                     24: #include "keybuf.h"
                     25: #include "gui.h"
                     26: 
1.1.1.10! root       27: #define DIV10 (5*CYCLE_UNIT) /* Yes, a bad identifier. */
1.1       root       28: 
                     29: /* battclock stuff */
                     30: #define RTC_D_ADJ      8
                     31: #define RTC_D_IRQ      4
                     32: #define RTC_D_BUSY     2
                     33: #define RTC_D_HOLD     1
                     34: #define RTC_E_t1       8
                     35: #define RTC_E_t0       4
                     36: #define RTC_E_INTR     2
                     37: #define RTC_E_MASK     1
                     38: #define RTC_F_TEST     8
                     39: #define RTC_F_24_12    4
                     40: #define RTC_F_STOP     2
                     41: #define RTC_F_RSET     1
                     42: 
1.1.1.3   root       43: static unsigned int clock_control_d = RTC_D_ADJ + RTC_D_HOLD;
                     44: static unsigned int clock_control_e = 0;
                     45: static unsigned int clock_control_f = RTC_F_24_12;
                     46: 
                     47: unsigned int ciaaicr,ciaaimask,ciabicr,ciabimask;
                     48: unsigned int ciaacra,ciaacrb,ciabcra,ciabcrb;
1.1.1.10! root       49: 
        !            50: /* Values of the CIA timers.  */
1.1.1.3   root       51: unsigned long ciaata,ciaatb,ciabta,ciabtb;
1.1.1.10! root       52: /* Computed by compute_passed_time.  */
        !            53: unsigned long ciaata_passed, ciaatb_passed, ciabta_passed, ciabtb_passed;
        !            54: 
1.1.1.3   root       55: unsigned long ciaatod,ciabtod,ciaatol,ciabtol,ciaaalarm,ciabalarm;
1.1.1.2   root       56: int ciaatlatch,ciabtlatch;
1.1.1.3   root       57: 
                     58: unsigned int ciabpra;
                     59: 
                     60: unsigned int gui_ledstate;
                     61: 
                     62: static unsigned long ciaala,ciaalb,ciabla,ciablb;
                     63: static int ciaatodon, ciabtodon;
                     64: static unsigned int ciaapra,ciaaprb,ciaadra,ciaadrb,ciaasdr;
                     65: static unsigned int ciabprb,ciabdra,ciabdrb,ciabsdr;
1.1       root       66: static int div10;
1.1.1.2   root       67: static int kbstate, kback, ciaasdr_unread = 0;
1.1       root       68: 
                     69: static int prtopen;
                     70: static FILE *prttmp;
                     71: 
1.1.1.10! root       72: static void setclr (unsigned int *p, unsigned int val)
1.1       root       73: {
                     74:     if (val & 0x80) {
                     75:        *p |= val & 0x7F;
                     76:     } else {
                     77:        *p &= ~val;
                     78:     }
                     79: }
                     80: 
1.1.1.10! root       81: static void RethinkICRA (void)
1.1       root       82: {
                     83:     if (ciaaimask & ciaaicr) {
                     84:        ciaaicr |= 0x80;
                     85:        custom_bank.wput(0xDFF09C,0x8008);
                     86:     } else {
                     87:        ciaaicr &= 0x7F;
                     88: /*     custom_bank.wput(0xDFF09C,0x0008);*/
                     89:     }
                     90: }
                     91: 
1.1.1.10! root       92: static void RethinkICRB (void)
1.1       root       93: {
                     94: #if 0 /* ??? What's this then? */
                     95:     if (ciabicr & 0x10) {
                     96:        custom_bank.wput(0xDFF09C,0x9000);
                     97:     }
                     98: #endif
                     99:     if (ciabimask & ciabicr) {
                    100:        ciabicr |= 0x80;
                    101:        custom_bank.wput(0xDFF09C,0xA000);
                    102:     } else {
                    103:        ciabicr &= 0x7F;
                    104: /*     custom_bank.wput(0xDFF09C,0x2000);*/
                    105:     }
                    106: }
                    107: 
1.1.1.10! root      108: /* Figure out how many CIA timer cycles have passed for each timer since the
        !           109:    last call of CIA_calctimers.  */
1.1       root      110: 
1.1.1.10! root      111: static void compute_passed_time (void)
1.1       root      112: {
1.1.1.10! root      113:     unsigned long int ccount = (get_cycles () - eventtab[ev_cia].oldcycles + div10);
        !           114:     unsigned long int ciaclocks = ccount / DIV10;
        !           115: 
        !           116:     ciaata_passed = ciaatb_passed = ciabta_passed = ciabtb_passed = 0;
        !           117: 
        !           118:     /* CIA A timers */
        !           119:     if ((ciaacra & 0x21) == 0x01) {
        !           120:        assert ((ciaata+1) >= ciaclocks);
        !           121:        ciaata_passed = ciaclocks;
        !           122:     }
        !           123:     if ((ciaacrb & 0x61) == 0x01) {
        !           124:        assert ((ciaatb+1) >= ciaclocks);
        !           125:        ciaatb_passed = ciaclocks;
        !           126:     }
        !           127: 
        !           128:     /* CIA B timers */
        !           129:     if ((ciabcra & 0x21) == 0x01) {
        !           130:        assert ((ciabta+1) >= ciaclocks);
        !           131:        ciabta_passed = ciaclocks;
        !           132:     }
        !           133:     if ((ciabcrb & 0x61) == 0x01) {
        !           134:        assert ((ciabtb+1) >= ciaclocks);
        !           135:        ciabtb_passed = ciaclocks;
        !           136:     }
        !           137: }
        !           138: 
        !           139: /* Called to advance all CIA timers to the current time.  This expects that
        !           140:    one of the timer values will be modified, and CIA_calctimers will be called
        !           141:    in the same cycle.  */
        !           142: 
        !           143: static void CIA_update (void)
        !           144: {
        !           145:     unsigned long int ccount = (get_cycles () - eventtab[ev_cia].oldcycles + div10);
1.1       root      146:     unsigned long int ciaclocks = ccount / DIV10;
                    147: 
                    148:     int aovfla = 0, aovflb = 0, bovfla = 0, bovflb = 0;
                    149: 
                    150:     div10 = ccount % DIV10;
1.1.1.3   root      151: 
1.1       root      152:     /* CIA A timers */
                    153:     if ((ciaacra & 0x21) == 0x01) {
1.1.1.10! root      154:        assert ((ciaata+1) >= ciaclocks);
1.1       root      155:        if ((ciaata+1) == ciaclocks) {
                    156:            aovfla = 1;
                    157:            if ((ciaacrb & 0x61) == 0x41) {
1.1.1.3   root      158:                if (ciaatb-- == 0) aovflb = 1;
1.1       root      159:            }
1.1.1.3   root      160:        }
1.1       root      161:        ciaata -= ciaclocks;
                    162:     }
                    163:     if ((ciaacrb & 0x61) == 0x01) {
1.1.1.10! root      164:        assert ((ciaatb+1) >= ciaclocks);
1.1       root      165:        if ((ciaatb+1) == ciaclocks) aovflb = 1;
                    166:        ciaatb -= ciaclocks;
                    167:     }
1.1.1.3   root      168: 
1.1       root      169:     /* CIA B timers */
                    170:     if ((ciabcra & 0x21) == 0x01) {
1.1.1.10! root      171:        assert ((ciabta+1) >= ciaclocks);
1.1       root      172:        if ((ciabta+1) == ciaclocks) {
                    173:            bovfla = 1;
                    174:            if ((ciabcrb & 0x61) == 0x41) {
                    175:                if (ciabtb-- == 0) bovflb = 1;
                    176:            }
1.1.1.3   root      177:        }
1.1       root      178:        ciabta -= ciaclocks;
                    179:     }
                    180:     if ((ciabcrb & 0x61) == 0x01) {
                    181:        assert ((ciabtb+1) >= ciaclocks);
                    182:        if ((ciabtb+1) == ciaclocks) bovflb = 1;
                    183:        ciabtb -= ciaclocks;
                    184:     }
                    185:     if (aovfla) {
                    186:        ciaaicr |= 1; RethinkICRA();
                    187:        ciaata = ciaala;
                    188:        if (ciaacra & 0x8) ciaacra &= ~1;
                    189:     }
                    190:     if (aovflb) {
                    191:        ciaaicr |= 2; RethinkICRA();
                    192:        ciaatb = ciaalb;
                    193:        if (ciaacrb & 0x8) ciaacrb &= ~1;
                    194:     }
                    195:     if (bovfla) {
                    196:        ciabicr |= 1; RethinkICRB();
                    197:        ciabta = ciabla;
                    198:        if (ciabcra & 0x8) ciabcra &= ~1;
                    199:     }
                    200:     if (bovflb) {
                    201:        ciabicr |= 2; RethinkICRB();
                    202:        ciabtb = ciablb;
                    203:        if (ciabcrb & 0x8) ciabcrb &= ~1;
                    204:     }
                    205: }
                    206: 
1.1.1.10! root      207: /* Call this only after CIA_update has been called in the same cycle.  */
        !           208: 
        !           209: static void CIA_calctimers (void)
1.1       root      210: {
1.1.1.10! root      211:     long ciaatimea = -1, ciaatimeb = -1, ciabtimea = -1, ciabtimeb = -1;
1.1       root      212: 
1.1.1.10! root      213:     eventtab[ev_cia].oldcycles = get_cycles ();
1.1.1.3   root      214: 
1.1       root      215:     if ((ciaacra & 0x21) == 0x01) {
1.1.1.10! root      216:        ciaatimea = (DIV10 - div10) + DIV10 * ciaata;
1.1       root      217:     }
                    218:     if ((ciaacrb & 0x61) == 0x41) {
                    219:        /* Timer B will not get any pulses if Timer A is off. */
                    220:        if (ciaatimea >= 0) {
                    221:            /* If Timer A is in one-shot mode, and Timer B needs more than
                    222:             * one pulse, it will not underflow. */
                    223:            if (ciaatb == 0 || (ciaacra & 0x8) == 0) {
                    224:                /* Otherwise, we can determine the time of the underflow. */
                    225:                ciaatimeb = ciaatimea + ciaala * DIV10 * ciaatb;
                    226:            }
                    227:        }
                    228:     }
                    229:     if ((ciaacrb & 0x61) == 0x01) {
1.1.1.10! root      230:        ciaatimeb = (DIV10 - div10) + DIV10 * ciaatb;
1.1       root      231:     }
                    232: 
                    233:     if ((ciabcra & 0x21) == 0x01) {
1.1.1.10! root      234:        ciabtimea = (DIV10 - div10) + DIV10 * ciabta;
1.1       root      235:     }
                    236:     if ((ciabcrb & 0x61) == 0x41) {
                    237:        /* Timer B will not get any pulses if Timer A is off. */
                    238:        if (ciabtimea >= 0) {
                    239:            /* If Timer A is in one-shot mode, and Timer B needs more than
                    240:             * one pulse, it will not underflow. */
                    241:            if (ciabtb == 0 || (ciabcra & 0x8) == 0) {
                    242:                /* Otherwise, we can determine the time of the underflow. */
                    243:                ciabtimeb = ciabtimea + ciabla * DIV10 * ciabtb;
                    244:            }
                    245:        }
                    246:     }
                    247:     if ((ciabcrb & 0x61) == 0x01) {
1.1.1.10! root      248:        ciabtimeb = (DIV10 - div10) + DIV10 * ciabtb;
1.1       root      249:     }
                    250:     eventtab[ev_cia].active = (ciaatimea != -1 || ciaatimeb != -1
                    251:                               || ciabtimea != -1 || ciabtimeb != -1);
                    252:     if (eventtab[ev_cia].active) {
                    253:        unsigned long int ciatime = ~0L;
                    254:        if (ciaatimea != -1) ciatime = ciaatimea;
                    255:        if (ciaatimeb != -1 && ciaatimeb < ciatime) ciatime = ciaatimeb;
                    256:        if (ciabtimea != -1 && ciabtimea < ciatime) ciatime = ciabtimea;
                    257:        if (ciabtimeb != -1 && ciabtimeb < ciatime) ciatime = ciabtimeb;
1.1.1.10! root      258:        eventtab[ev_cia].evtime = ciatime + get_cycles ();
1.1       root      259:     }
                    260:     events_schedule();
                    261: }
                    262: 
1.1.1.10! root      263: void CIA_handler (void)
1.1       root      264: {
1.1.1.10! root      265:     CIA_update ();
        !           266:     CIA_calctimers ();
1.1       root      267: }
                    268: 
1.1.1.10! root      269: void cia_diskindex (void)
1.1       root      270: {
                    271:     ciabicr |= 0x10;
                    272:     RethinkICRB();
                    273: }
                    274: 
1.1.1.10! root      275: void CIA_hsync_handler (void)
1.1       root      276: {
1.1.1.3   root      277:     static unsigned int keytime = 0, sleepyhead = 0;
1.1       root      278: 
                    279:     if (ciabtodon)
                    280:        ciabtod++;
                    281:     ciabtod &= 0xFFFFFF;
                    282: 
                    283:     if (ciabtod == ciabalarm) {
                    284:        ciabicr |= 4; RethinkICRB();
                    285:     }
1.1.1.3   root      286: 
                    287:     /* check wether the serial port gets some data */
                    288:     if (doreadser)
                    289:        doreadser = SERDATS();
                    290: 
1.1       root      291:     if (keys_available() && kback && (++keytime & 15) == 0) {
1.1.1.3   root      292:        /*
1.1.1.2   root      293:         * This hack lets one possible ciaaicr cycle go by without any key
                    294:         * being read, for every cycle in which a key is pulled out of the
                    295:         * queue.  If no hack is used, a lot of key events just get lost
                    296:         * when you type fast.  With a simple hack that waits for ciaasdr
                    297:         * to be read before feeding it another, it will keep up until the
                    298:         * queue gets about 14 characters ahead and then lose events, and
                    299:         * the mouse pointer will freeze while typing is being taken in.
                    300:         * With this hack, you can type 30 or 40 characters ahead with little
                    301:         * or no lossage, and the mouse doesn't get stuck.  The tradeoff is
                    302:         * that the total slowness of typing appearing on screen is worse.
                    303:         */
1.1.1.3   root      304:        if (ciaasdr_unread == 2)
                    305:            ciaasdr_unread = 0;
                    306:        else if (ciaasdr_unread == 0) {
                    307:            switch (kbstate) {
1.1.1.2   root      308:             case 0:
1.1.1.3   root      309:                ciaasdr = (uae_s8)~0xFB; /* aaarghh... stupid compiler */
                    310:                kbstate++;
                    311:                break;
1.1.1.2   root      312:             case 1:
1.1.1.3   root      313:                kbstate++;
                    314:                ciaasdr = (uae_s8)~0xFD;
                    315:                break;
1.1.1.2   root      316:             case 2:
1.1.1.3   root      317:                ciaasdr = ~get_next_key();
                    318:                ciaasdr_unread = 1;      /* interlock to prevent lost keystrokes */
                    319:                break;
1.1.1.2   root      320:            }
                    321:            ciaaicr |= 8;
                    322:            RethinkICRA();
                    323:            sleepyhead = 0;
1.1.1.3   root      324:        } else if (!(++sleepyhead & 15))
                    325:            ciaasdr_unread = 0;          /* give up on this key event after unread for a long time */
1.1       root      326:     }
                    327: }
                    328: 
1.1.1.10! root      329: void CIA_vsync_handler ()
1.1.1.3   root      330: {
                    331:     if (ciaatodon)
1.1       root      332:        ciaatod++;
                    333:     ciaatod &= 0xFFFFFF;
                    334:     if (ciaatod == ciaaalarm) {
                    335:        ciaaicr |= 4; RethinkICRA();
                    336:     }
1.1.1.3   root      337: 
                    338:     doreadser = 1;
                    339:     serstat = -1;
                    340:     serial_flush_buffer();
1.1       root      341: }
                    342: 
1.1.1.10! root      343: static uae_u8 ReadCIAA (unsigned int addr)
1.1       root      344: {
1.1.1.3   root      345:     unsigned int tmp;
                    346: 
1.1.1.10! root      347:     compute_passed_time ();
        !           348:     
        !           349:     switch (addr & 0xf) {
1.1.1.7   root      350:     case 0:
1.1.1.3   root      351:        if (currprefs.use_serial && (serstat < 0)) /* Only read status when needed */
                    352:            serstat=serial_readstatus();                /* and only once per frame */
                    353: 
1.1       root      354:        tmp = (DISK_status() & 0x3C);
1.1.1.6   root      355:        if ((JSEM_ISMOUSE (0, &currprefs) && !buttonstate[0])
                    356:            || (!JSEM_ISMOUSE (0, &currprefs) && !(joy0button & 1)))
1.1.1.3   root      357:            tmp |= 0x40;
                    358:        if (!(joy1button & 1))
                    359:            tmp |= 0x80;
1.1       root      360:        return tmp;
1.1.1.7   root      361:     case 1:
                    362:        /* Returning 0xFF is necessary for Tie Break - otherwise its joystick
                    363:           code won't work.  */
                    364:        return prtopen ? ciaaprb : 0xFF;
                    365:     case 2:
1.1       root      366:        return ciaadra;
1.1.1.7   root      367:     case 3:
1.1       root      368:        return ciaadrb;
1.1.1.7   root      369:     case 4:
1.1.1.10! root      370:        return (ciaata - ciaata_passed) & 0xff;
1.1.1.7   root      371:     case 5:
1.1.1.10! root      372:        return (ciaata - ciaata_passed) >> 8;
1.1.1.7   root      373:     case 6:
1.1.1.10! root      374:        return (ciaatb - ciaatb_passed) & 0xff;
1.1.1.7   root      375:     case 7:
1.1.1.10! root      376:        return (ciaatb - ciaatb_passed) >> 8;
1.1.1.7   root      377:     case 8:
1.1       root      378:        if (ciaatlatch) {
                    379:            ciaatlatch = 0;
                    380:            return ciaatol & 0xff;
1.1.1.3   root      381:        } else
                    382:            return ciaatod & 0xff;
1.1.1.7   root      383:     case 9:
1.1.1.3   root      384:        if (ciaatlatch)
                    385:            return (ciaatol >> 8) & 0xff;
                    386:        else
                    387:            return (ciaatod >> 8) & 0xff;
1.1.1.7   root      388:     case 10:
1.1.1.3   root      389:        ciaatlatch = 1;
                    390:        ciaatol = ciaatod; /* ??? only if not already latched? */
1.1       root      391:        return (ciaatol >> 16) & 0xff;
1.1.1.7   root      392:     case 12:
1.1.1.3   root      393:        if (ciaasdr == 1) ciaasdr_unread = 2;
1.1       root      394:        return ciaasdr;
1.1.1.7   root      395:     case 13:
1.1       root      396:        tmp = ciaaicr; ciaaicr = 0; RethinkICRA(); return tmp;
1.1.1.7   root      397:     case 14:
1.1       root      398:        return ciaacra;
1.1.1.7   root      399:     case 15:
1.1       root      400:        return ciaacrb;
                    401:     }
                    402:     return 0;
                    403: }
                    404: 
1.1.1.10! root      405: static uae_u8 ReadCIAB (unsigned int addr)
1.1       root      406: {
1.1.1.3   root      407:     unsigned int tmp;
                    408: 
1.1.1.10! root      409:     compute_passed_time ();
        !           410: 
        !           411:     switch (addr & 0xf) {
1.1.1.7   root      412:     case 0:
1.1.1.3   root      413:        if (currprefs.use_serial && serstat < 0) /* Only read status when needed */
                    414:            serstat=serial_readstatus();         /* and only once per frame      */
1.1.1.7   root      415:        /* Returning some 1 bits is necessary for Tie Break - otherwise its joystick
                    416:           code won't work.  */
                    417:        return ciabpra | (prtopen ? 0 : 3);
                    418:     case 1:
1.1       root      419:        return ciabprb;
1.1.1.7   root      420:     case 2:
1.1       root      421:        return ciabdra;
1.1.1.7   root      422:     case 3:
1.1       root      423:        return ciabdrb;
1.1.1.7   root      424:     case 4:
1.1.1.10! root      425:        return (ciabta - ciabta_passed) & 0xff;
1.1.1.7   root      426:     case 5:
1.1.1.10! root      427:        return (ciabta - ciabta_passed) >> 8;
1.1.1.7   root      428:     case 6:
1.1.1.10! root      429:        return (ciabtb - ciabtb_passed) & 0xff;
1.1.1.7   root      430:     case 7:
1.1.1.10! root      431:        return (ciabtb - ciabtb_passed) >> 8;
1.1.1.7   root      432:     case 8:
1.1       root      433:        if (ciabtlatch) {
                    434:            ciabtlatch = 0;
                    435:            return ciabtol & 0xff;
1.1.1.3   root      436:        } else
                    437:            return ciabtod & 0xff;
1.1.1.7   root      438:     case 9:
1.1.1.3   root      439:        if (ciabtlatch)
                    440:            return (ciabtol >> 8) & 0xff;
                    441:        else
                    442:            return (ciabtod >> 8) & 0xff;
1.1.1.7   root      443:     case 10:
1.1.1.3   root      444:        ciabtlatch = 1;
                    445:        ciabtol = ciabtod;
1.1       root      446:        return (ciabtol >> 16) & 0xff;
1.1.1.7   root      447:     case 12:
1.1       root      448:        return ciabsdr;
1.1.1.7   root      449:     case 13:
1.1       root      450:        tmp = ciabicr; ciabicr = 0; RethinkICRB();
                    451:        return tmp;
1.1.1.7   root      452:     case 14:
1.1       root      453:        return ciabcra;
1.1.1.7   root      454:     case 15:
1.1       root      455:        return ciabcrb;
                    456:     }
                    457:     return 0;
                    458: }
                    459: 
1.1.1.10! root      460: static void WriteCIAA (uae_u16 addr,uae_u8 val)
1.1       root      461: {
1.1.1.3   root      462:     int oldled, oldovl;
1.1.1.10! root      463:     switch (addr & 0xf) {
1.1.1.7   root      464:     case 0:
1.1.1.3   root      465:        oldovl = ciaapra & 1;
1.1       root      466:        oldled = ciaapra & 2;
                    467:        ciaapra = (ciaapra & ~0x3) | (val & 0x3); LED(ciaapra & 0x2);
1.1.1.3   root      468:        gui_ledstate &= ~1;
                    469:        gui_ledstate |= ((~ciaapra & 2) >> 1);
1.1       root      470:        if ((ciaapra & 2) != oldled)
                    471:            gui_led (0, !(ciaapra & 2));
1.1.1.3   root      472:        if ((ciaapra & 1) != oldovl) {
                    473:            map_banks(oldovl || ersatzkickfile ? &chipmem_bank : &kickmem_bank, 0, 32);
                    474:        }
1.1       root      475:        break;
1.1.1.7   root      476:     case 1:
1.1       root      477:        ciaaprb = val;
                    478:        if (prtopen==1) {
                    479: #ifndef __DOS__
1.1.1.4   root      480:            fprintf (prttmp, "%c",val);
1.1       root      481: #else
                    482:            fputc (val, prttmp);
                    483:            fflush (prttmp);
                    484: #endif
                    485:            if (val==0x04) {
1.1.1.2   root      486: #if defined(__unix) && !defined(__BEOS__) && !defined(__DOS__)
1.1       root      487:                pclose (prttmp);
                    488: #else
                    489:                fclose (prttmp);
                    490: #endif
                    491:                prtopen = 0;
                    492:            }
1.1.1.3   root      493:        } else {
1.1.1.2   root      494: #if defined(__unix) && !defined(__BEOS__) && !defined(__DOS__)
1.1.1.6   root      495:            prttmp = (FILE *)popen ((const char *)currprefs.prtname, "w");
1.1       root      496: #else
1.1.1.6   root      497:            prttmp = (FILE *)fopen ((const char *)currprefs.prtname, "wb");
1.1       root      498: #endif
                    499:            if (prttmp != NULL) {
                    500:                prtopen = 1;
                    501: #ifndef __DOS__
                    502:                fprintf (prttmp,"%c",val);
                    503: #else
                    504:                fputc (val, prttmp);
                    505:                fflush (prttmp);
                    506: #endif
                    507:            }
1.1.1.3   root      508:        }
1.1       root      509:        ciaaicr |= 0x10;
                    510:        break;
1.1.1.7   root      511:     case 2:
1.1       root      512:        ciaadra = val; break;
1.1.1.7   root      513:     case 3:
1.1       root      514:        ciaadrb = val; break;
1.1.1.7   root      515:     case 4:
1.1.1.10! root      516:        CIA_update ();
1.1       root      517:        ciaala = (ciaala & 0xff00) | val;
1.1.1.10! root      518:        CIA_calctimers ();
1.1       root      519:        break;
1.1.1.7   root      520:     case 5:
1.1.1.10! root      521:        CIA_update ();
1.1       root      522:        ciaala = (ciaala & 0xff) | (val << 8);
                    523:        if ((ciaacra & 1) == 0)
                    524:            ciaata = ciaala;
1.1.1.3   root      525:        if (ciaacra & 8) {
                    526:            ciaata = ciaala;
                    527:            ciaacra |= 1;
1.1       root      528:        }
1.1.1.10! root      529:        CIA_calctimers ();
1.1       root      530:        break;
1.1.1.7   root      531:     case 6:
1.1.1.10! root      532:        CIA_update ();
1.1       root      533:        ciaalb = (ciaalb & 0xff00) | val;
1.1.1.10! root      534:        CIA_calctimers ();
1.1       root      535:        break;
1.1.1.7   root      536:     case 7:
1.1.1.10! root      537:        CIA_update ();
1.1       root      538:        ciaalb = (ciaalb & 0xff) | (val << 8);
                    539:        if ((ciaacrb & 1) == 0)
                    540:            ciaatb = ciaalb;
1.1.1.3   root      541:        if (ciaacrb & 8) {
1.1       root      542:            ciaatb = ciaalb;
1.1.1.3   root      543:            ciaacrb |= 1;
1.1       root      544:        }
1.1.1.10! root      545:        CIA_calctimers ();
1.1       root      546:        break;
1.1.1.7   root      547:     case 8:
1.1.1.5   root      548:        if (ciaacrb & 0x80) {
1.1       root      549:            ciaaalarm = (ciaaalarm & ~0xff) | val;
                    550:        } else {
                    551:            ciaatod = (ciaatod & ~0xff) | val;
                    552:            ciaatodon = 1;
                    553:        }
                    554:        break;
1.1.1.7   root      555:     case 9:
1.1.1.5   root      556:        if (ciaacrb & 0x80) {
1.1       root      557:            ciaaalarm = (ciaaalarm & ~0xff00) | (val << 8);
                    558:        } else {
                    559:            ciaatod = (ciaatod & ~0xff00) | (val << 8);
                    560:            ciaatodon = 0;
                    561:        }
                    562:        break;
1.1.1.7   root      563:     case 10:
1.1.1.5   root      564:        if (ciaacrb & 0x80) {
1.1       root      565:            ciaaalarm = (ciaaalarm & ~0xff0000) | (val << 16);
                    566:        } else {
                    567:            ciaatod = (ciaatod & ~0xff0000) | (val << 16);
                    568:            ciaatodon = 0;
                    569:        }
                    570:        break;
1.1.1.7   root      571:     case 12:
1.1       root      572:        ciaasdr = val; break;
1.1.1.7   root      573:     case 13:
1.1       root      574:        setclr(&ciaaimask,val); break; /* ??? call RethinkICR() ? */
1.1.1.7   root      575:     case 14:
1.1.1.10! root      576:        CIA_update ();
1.1       root      577:        ciaacra = val;
1.1.1.5   root      578:        if (ciaacra & 0x10) {
1.1       root      579:            ciaacra &= ~0x10;
                    580:            ciaata = ciaala;
                    581:        }
                    582:        if (ciaacra & 0x40) {
                    583:            kback = 1;
                    584:        }
1.1.1.10! root      585:        CIA_calctimers ();
1.1       root      586:        break;
1.1.1.7   root      587:     case 15:
1.1.1.10! root      588:        CIA_update ();
1.1.1.3   root      589:        ciaacrb = val;
1.1.1.5   root      590:        if (ciaacrb & 0x10) {
1.1       root      591:            ciaacrb &= ~0x10;
                    592:            ciaatb = ciaalb;
                    593:        }
1.1.1.10! root      594:        CIA_calctimers ();
1.1       root      595:        break;
                    596:     }
                    597: }
                    598: 
1.1.1.10! root      599: static void WriteCIAB (uae_u16 addr,uae_u8 val)
1.1       root      600: {
1.1.1.3   root      601:     int oldval;
1.1.1.10! root      602:     switch (addr & 0xf) {
1.1.1.7   root      603:     case 0:
1.1.1.3   root      604:        if (currprefs.use_serial) {
1.1.1.7   root      605:            oldval = ciabpra;
                    606:            ciabpra  = serial_writestatus(oldval,val);
1.1.1.3   root      607:        } else
1.1.1.7   root      608:            ciabpra  = val;
1.1.1.3   root      609:        break;
1.1.1.7   root      610:     case 1:
1.1       root      611:        ciabprb = val; DISK_select(val); break;
1.1.1.7   root      612:     case 2:
1.1       root      613:        ciabdra = val; break;
1.1.1.7   root      614:     case 3:
1.1       root      615:        ciabdrb = val; break;
1.1.1.7   root      616:     case 4:
1.1.1.10! root      617:        CIA_update ();
1.1       root      618:        ciabla = (ciabla & 0xff00) | val;
1.1.1.10! root      619:        CIA_calctimers ();
1.1       root      620:        break;
1.1.1.7   root      621:     case 5:
1.1.1.10! root      622:        CIA_update ();
1.1       root      623:        ciabla = (ciabla & 0xff) | (val << 8);
1.1.1.3   root      624:        if ((ciabcra & 1) == 0)
1.1       root      625:            ciabta = ciabla;
                    626:        if (ciabcra & 8) {
1.1.1.3   root      627:            ciabta = ciabla;
                    628:            ciabcra |= 1;
                    629:        }
1.1.1.10! root      630:        CIA_calctimers ();
1.1       root      631:        break;
1.1.1.7   root      632:     case 6:
1.1.1.10! root      633:        CIA_update ();
1.1       root      634:        ciablb = (ciablb & 0xff00) | val;
1.1.1.10! root      635:        CIA_calctimers ();
1.1       root      636:        break;
1.1.1.7   root      637:     case 7:
1.1.1.10! root      638:        CIA_update ();
1.1       root      639:        ciablb = (ciablb & 0xff) | (val << 8);
                    640:        if ((ciabcrb & 1) == 0)
                    641:            ciabtb = ciablb;
                    642:        if (ciabcrb & 8) {
                    643:            ciabtb = ciablb;
                    644:            ciabcrb |= 1;
                    645:        }
1.1.1.10! root      646:        CIA_calctimers ();
1.1       root      647:        break;
1.1.1.7   root      648:     case 8:
1.1.1.5   root      649:        if (ciabcrb & 0x80) {
1.1       root      650:            ciabalarm = (ciabalarm & ~0xff) | val;
                    651:        } else {
                    652:            ciabtod = (ciabtod & ~0xff) | val;
                    653:            ciabtodon = 1;
                    654:        }
                    655:        break;
1.1.1.7   root      656:     case 9:
1.1.1.5   root      657:        if (ciabcrb & 0x80) {
1.1       root      658:            ciabalarm = (ciabalarm & ~0xff00) | (val << 8);
                    659:        } else {
                    660:            ciabtod = (ciabtod & ~0xff00) | (val << 8);
                    661:            ciabtodon = 0;
                    662:        }
                    663:        break;
1.1.1.7   root      664:     case 10:
1.1.1.5   root      665:        if (ciabcrb & 0x80) {
1.1       root      666:            ciabalarm = (ciabalarm & ~0xff0000) | (val << 16);
                    667:        } else {
                    668:            ciabtod = (ciabtod & ~0xff0000) | (val << 16);
                    669:            ciabtodon = 0;
                    670:        }
                    671:        break;
1.1.1.7   root      672:     case 12:
1.1.1.3   root      673:        ciabsdr = val;
1.1       root      674:        break;
1.1.1.7   root      675:     case 13:
1.1.1.3   root      676:        setclr(&ciabimask,val);
1.1       root      677:        break;
1.1.1.7   root      678:     case 14:
1.1.1.10! root      679:        CIA_update ();
1.1       root      680:        ciabcra = val;
1.1.1.5   root      681:        if (ciabcra & 0x10) {
1.1       root      682:            ciabcra &= ~0x10;
                    683:            ciabta = ciabla;
                    684:        }
1.1.1.10! root      685:        CIA_calctimers ();
1.1       root      686:        break;
1.1.1.7   root      687:     case 15:
1.1.1.10! root      688:        CIA_update ();
1.1.1.3   root      689:        ciabcrb = val;
1.1.1.5   root      690:        if (ciabcrb & 0x10) {
1.1       root      691:            ciabcrb &= ~0x10;
                    692:            ciabtb = ciablb;
                    693:        }
1.1.1.10! root      694:        CIA_calctimers ();
1.1       root      695:        break;
                    696:     }
                    697: }
                    698: 
1.1.1.10! root      699: void CIA_reset (void)
1.1       root      700: {
                    701:     kback = 1;
                    702:     kbstate = 0;
1.1.1.3   root      703: 
1.1       root      704:     ciaatlatch = ciabtlatch = 0;
1.1.1.3   root      705:     ciaapra = 3;
1.1       root      706:     ciaatod = ciabtod = 0; ciaatodon = ciabtodon = 0;
                    707:     ciaaicr = ciabicr = ciaaimask = ciabimask = 0;
                    708:     ciaacra = ciaacrb = ciabcra = ciabcrb = 0x4; /* outmode = toggle; */
                    709:     ciaala = ciaalb = ciabla = ciablb = ciaata = ciaatb = ciabta = ciabtb = 0xFFFF;
                    710:     div10 = 0;
1.1.1.10! root      711:     CIA_calctimers ();
1.1.1.2   root      712:     ciabpra = 0x8C;
1.1.1.3   root      713:     if (! ersatzkickfile)
1.1.1.10! root      714:        map_banks (&kickmem_bank, 0, 32);
1.1.1.3   root      715: 
1.1.1.10! root      716:     if (currprefs.use_serial)
        !           717:       serial_dtr_off(); /* Drop DTR at reset */
1.1       root      718: }
                    719: 
1.1.1.10! root      720: void dumpcia (void)
1.1       root      721: {
                    722:     printf("A: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx, TB: %04lx\n",
1.1.1.3   root      723:           (int)ciaacra, (int)ciaacrb, (int)ciaaimask, ciaatod,
1.1       root      724:           ciaatlatch ? " latched" : "", ciaata, ciaatb);
                    725:     printf("B: CRA: %02x, CRB: %02x, IMASK: %02x, TOD: %08lx %7s TA: %04lx, TB: %04lx\n",
1.1.1.3   root      726:           (int)ciabcra, (int)ciabcrb, (int)ciabimask, ciabtod,
1.1       root      727:           ciabtlatch ? " latched" : "", ciabta, ciabtb);
                    728: }
                    729: 
                    730: /* CIA memory access */
                    731: 
1.1.1.3   root      732: static uae_u32 cia_lget (uaecptr) REGPARAM;
                    733: static uae_u32 cia_wget (uaecptr) REGPARAM;
                    734: static uae_u32 cia_bget (uaecptr) REGPARAM;
                    735: static void cia_lput (uaecptr, uae_u32) REGPARAM;
                    736: static void cia_wput (uaecptr, uae_u32) REGPARAM;
                    737: static void cia_bput (uaecptr, uae_u32) REGPARAM;
1.1       root      738: 
                    739: addrbank cia_bank = {
                    740:     cia_lget, cia_wget, cia_bget,
                    741:     cia_lput, cia_wput, cia_bput,
                    742:     default_xlate, default_check
                    743: };
                    744: 
1.1.1.3   root      745: uae_u32 REGPARAM2 cia_lget (uaecptr addr)
1.1       root      746: {
1.1.1.9   root      747:     special_mem |= S_READ;
                    748:     return cia_bget (addr + 3);
1.1       root      749: }
                    750: 
1.1.1.3   root      751: uae_u32 REGPARAM2 cia_wget (uaecptr addr)
1.1       root      752: {
1.1.1.9   root      753:     special_mem |= S_READ;
                    754:     return cia_bget (addr + 1);
1.1       root      755: }
                    756: 
1.1.1.3   root      757: uae_u32 REGPARAM2 cia_bget (uaecptr addr)
1.1       root      758: {
1.1.1.9   root      759:     special_mem |= S_READ;
1.1       root      760:     if ((addr & 0x3001) == 0x2001)
1.1.1.3   root      761:        return ReadCIAA((addr & 0xF00) >> 8);
1.1       root      762:     if ((addr & 0x3001) == 0x1000)
1.1.1.3   root      763:        return ReadCIAB((addr & 0xF00) >> 8);
1.1       root      764:     return 0;
                    765: }
                    766: 
1.1.1.3   root      767: void REGPARAM2 cia_lput (uaecptr addr, uae_u32 value)
1.1       root      768: {
1.1.1.9   root      769:     special_mem |= S_WRITE;
                    770:     cia_bput (addr + 3, value); /* FIXME ? */
1.1       root      771: }
                    772: 
1.1.1.3   root      773: void REGPARAM2 cia_wput (uaecptr addr, uae_u32 value)
1.1       root      774: {
1.1.1.9   root      775:     special_mem |= S_WRITE;
                    776:     cia_bput (addr + 1, value);
1.1       root      777: }
                    778: 
1.1.1.3   root      779: void REGPARAM2 cia_bput (uaecptr addr, uae_u32 value)
1.1       root      780: {
1.1.1.9   root      781:     special_mem |= S_WRITE;
1.1       root      782:     if ((addr & 0x3001) == 0x2001)
1.1.1.9   root      783:        WriteCIAA ((addr & 0xF00) >> 8, value);
1.1       root      784:     if ((addr & 0x3001) == 0x1000)
1.1.1.9   root      785:        WriteCIAB ((addr & 0xF00) >> 8, value);
1.1       root      786: }
                    787: 
                    788: /* battclock memory access */
                    789: 
1.1.1.3   root      790: static uae_u32 clock_lget (uaecptr) REGPARAM;
                    791: static uae_u32 clock_wget (uaecptr) REGPARAM;
                    792: static uae_u32 clock_bget (uaecptr) REGPARAM;
                    793: static void clock_lput (uaecptr, uae_u32) REGPARAM;
                    794: static void clock_wput (uaecptr, uae_u32) REGPARAM;
                    795: static void clock_bput (uaecptr, uae_u32) REGPARAM;
1.1       root      796: 
                    797: addrbank clock_bank = {
                    798:     clock_lget, clock_wget, clock_bget,
                    799:     clock_lput, clock_wput, clock_bput,
                    800:     default_xlate, default_check
                    801: };
                    802: 
1.1.1.3   root      803: uae_u32 REGPARAM2 clock_lget (uaecptr addr)
1.1       root      804: {
1.1.1.9   root      805:     special_mem |= S_READ;
                    806:     return clock_bget (addr + 3);
1.1       root      807: }
                    808: 
1.1.1.3   root      809: uae_u32 REGPARAM2 clock_wget (uaecptr addr)
1.1       root      810: {
1.1.1.9   root      811:     special_mem |= S_READ;
                    812:     return clock_bget (addr + 1);
1.1       root      813: }
                    814: 
1.1.1.3   root      815: uae_u32 REGPARAM2 clock_bget (uaecptr addr)
1.1       root      816: {
1.1.1.9   root      817:     time_t t = time(0);
1.1       root      818:     struct tm *ct;
1.1.1.9   root      819: 
                    820:     ct = localtime (&t);
                    821:     special_mem |= S_READ;
                    822: 
1.1.1.7   root      823:     switch (addr & 0x3f) {
                    824:     case 0x03: return ct->tm_sec % 10;
                    825:     case 0x07: return ct->tm_sec / 10;
                    826:     case 0x0b: return ct->tm_min % 10;
                    827:     case 0x0f: return ct->tm_min / 10;
                    828:     case 0x13: return ct->tm_hour % 10;
                    829:     case 0x17: return ct->tm_hour / 10;
                    830:     case 0x1b: return ct->tm_mday % 10;
                    831:     case 0x1f: return ct->tm_mday / 10;
                    832:     case 0x23: return (ct->tm_mon+1) % 10;
                    833:     case 0x27: return (ct->tm_mon+1) / 10;
                    834:     case 0x2b: return ct->tm_year % 10;
                    835:     case 0x2f: return ct->tm_year / 10;
                    836: 
                    837:     case 0x33: return ct->tm_wday;  /*Hack by -=SR=- */
                    838:     case 0x37: return clock_control_d;
                    839:     case 0x3b: return clock_control_e;
                    840:     case 0x3f: return clock_control_f;
1.1       root      841:     }
                    842:     return 0;
                    843: }
                    844: 
1.1.1.3   root      845: void REGPARAM2 clock_lput (uaecptr addr, uae_u32 value)
1.1       root      846: {
1.1.1.9   root      847:     special_mem |= S_WRITE;
1.1       root      848:     /* No way */
                    849: }
                    850: 
1.1.1.3   root      851: void REGPARAM2 clock_wput (uaecptr addr, uae_u32 value)
1.1       root      852: {
1.1.1.9   root      853:     special_mem |= S_WRITE;
1.1       root      854:     /* No way */
                    855: }
                    856: 
1.1.1.3   root      857: void REGPARAM2 clock_bput (uaecptr addr, uae_u32 value)
1.1       root      858: {
1.1.1.9   root      859:     special_mem |= S_WRITE;
1.1.1.7   root      860:     switch (addr & 0x3f) {
1.1.1.9   root      861:     case 0x37: clock_control_d = value; break;
                    862:     case 0x3b: clock_control_e = value; break;
                    863:     case 0x3f: clock_control_f = value; break;
1.1       root      864:     }
                    865: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.