Annotation of generator/main/event.c, revision 1.1.1.1

1.1       root        1: /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */
                      2: 
                      3: #include "generator.h"
                      4: #include "vdp.h"
                      5: #include "cpu68k.h"
                      6: #include "cpuz80.h"
                      7: #include "reg68k.h"
                      8: #include "ui.h"
                      9: #include "gensound.h"
                     10: 
                     11: #include "snprintf.h"
                     12: 
                     13: /* time for next event - update vdp_event - return when to call again */
                     14: 
                     15: inline void event_nextevent(void)
                     16: {
                     17:   /* call this when it *is* time for the next event as dictated by vdp_event,
                     18:      so we switch on it and update vdp_event at the same time */
                     19: 
                     20:   switch(vdp_event++) {
                     21:   case 0:
                     22: EVENT_NEWLINE:
                     23:     LOG_DEBUG1(("%08X due %08X, %d A: %d (cd=%d)",
                     24:                 cpu68k_clocks, vdp_event_start,
                     25:                 vdp_line - vdp_visstartline, vdp_reg[10],
                     26:                 vdp_hskip_countdown));
                     27:     if (vdp_line == (vdp_visstartline-1)) {
                     28:       vdp_vblank = 0;
                     29:     }
                     30:     if ((vdp_nextevent = vdp_event_vint - cpu68k_clocks) > 0)
                     31:       break;
                     32:     vdp_event++;
                     33:   case 1:
                     34:     LOG_DEBUG1(("%08X due %08X, %d B: %d (cd=%d)",
                     35:                 cpu68k_clocks, vdp_event_vint,
                     36:                 vdp_line - vdp_visstartline, vdp_reg[10],
                     37:                 vdp_hskip_countdown));
                     38:     if (vdp_line == vdp_visendline) {
                     39:       vdp_vblank = 1;
                     40:       vdp_vsync = 1;
                     41:       if (vdp_reg[1] & 1<<5)
                     42:         reg68k_external_autovector(6); /* vertical interrupt */
                     43:     }
                     44:     if ((vdp_nextevent = vdp_event_hint - cpu68k_clocks) > 0)
                     45:       break;
                     46:     vdp_event++;
                     47:   case 2:
                     48:     LOG_DEBUG1(("%08X due %08X, %d C: %d (cd=%d)",
                     49:                 cpu68k_clocks, vdp_event_hint,
                     50:                 vdp_line - vdp_visstartline, vdp_reg[10],
                     51:                 vdp_hskip_countdown));
                     52:     if (vdp_line >= vdp_visstartline && vdp_line < vdp_visendline)
                     53:       vdp_hblank = 1;
                     54:     if (vdp_line == (vdp_visstartline-1) || (vdp_line > vdp_visendline)) {
                     55:       vdp_hskip_countdown = vdp_reg[10];
                     56:       LOG_DEBUG1(("H counter reset to %d", vdp_hskip_countdown));
                     57:     }
                     58:     if (vdp_reg[0] & 1<<4) {
                     59:       LOG_DEBUG1(("pre = %d", vdp_hskip_countdown));
                     60:       if (vdp_hskip_countdown-- == 0) {
                     61:         LOG_DEBUG1(("in = %d", vdp_hskip_countdown));
                     62:         /* re-initialise counter */
                     63:         vdp_hskip_countdown = vdp_reg[10];
                     64:         LOG_DEBUG1(("H counter looped to %d", vdp_hskip_countdown));
                     65:         if (vdp_line >= vdp_visstartline-1 && vdp_line < vdp_visendline-1)
                     66:           reg68k_external_autovector(4); /* horizontal interrupt */
                     67:         /* since this game is obviously timing sensitive, we sacrifice
                     68:            executing the right number of 68k clocks this frame in order
                     69:            to accurately do the moments following H-Int */
                     70:         cpu68k_clocks = vdp_event_hint;
                     71:       }
                     72:       LOG_DEBUG1(("post = %d", vdp_hskip_countdown));
                     73:     }
                     74:     /* the 68k should be frozen for 68k ram to vram copies, so we need
                     75:        to eat CPU cyles immediately - implement this at the same time
                     76:        as re-working this event loop */
                     77:     if (vdp_dmabytes) {
                     78:       vdp_dmabytes-= (vdp_vblank || !(vdp_reg[1] & 1<<6)) /* blank mode ? */
                     79:         ? ((vdp_reg[12] & 1) ? 205 : 167) : ((vdp_reg[12] & 1) ? 18 : 16);
                     80:       if (vdp_dmabytes <= 0) {
                     81:         vdp_dmabytes = 0;
                     82:         vdp_dmabusy = 0;
                     83:       }
                     84:     }
                     85:     if ((vdp_nextevent = vdp_event_hdisplay - cpu68k_clocks) > 0)
                     86:       break;
                     87:     vdp_event++;
                     88:   case 3:
                     89:     LOG_DEBUG1(("%08X due %08X, %d D: %d (cd=%d)",
                     90:                 cpu68k_clocks, vdp_event_hdisplay,
                     91:                 vdp_line - vdp_visstartline, vdp_reg[10],
                     92:                 vdp_hskip_countdown));
                     93:     if (vdp_line >= vdp_visstartline-1 && vdp_line < vdp_visendline-1)
                     94:       ui_line(vdp_line - vdp_visstartline + 1);
                     95:     if ((vdp_nextevent = vdp_event_end - cpu68k_clocks) > 0)
                     96:       break;
                     97:     /* vdp_event++; - not required, we set vdp_event to 0 below */
                     98:   case 4:
                     99:     /* end of line, do sound, platform stuff */
                    100:     LOG_DEBUG1(("%08X due %08X, %d E: %d (cd=%d)",
                    101:                 cpu68k_clocks, vdp_event_end,
                    102:                 vdp_line-vdp_visstartline, vdp_reg[10],
                    103:                 vdp_hskip_countdown));
                    104:     if (vdp_line >= vdp_visstartline && vdp_line < vdp_visendline)
                    105:       vdp_hblank = 0;
                    106:     cpuz80_sync();
                    107:     sound_process();
                    108:     vdp_line++;
                    109:     if (vdp_line == vdp_visendline)
                    110:       cpuz80_interrupt();
                    111:     if (vdp_line == vdp_totlines) {
                    112:       ui_endfield();
                    113:       sound_endfield();
                    114:       vdp_endfield();
                    115:       cpuz80_endfield();
                    116:       cpu68k_endfield();
                    117:       cpu68k_frames++;
                    118:     }
                    119:     vdp_event_start+= vdp_clksperline_68k;
                    120:     vdp_event_vint+= vdp_clksperline_68k;
                    121:     vdp_event_hint+= vdp_clksperline_68k;
                    122:     vdp_event_hdisplay+= vdp_clksperline_68k;
                    123:     vdp_event_end+= vdp_clksperline_68k;
                    124:     vdp_event = 1;
                    125:     goto EVENT_NEWLINE;
                    126:   } /* switch */
                    127: }
                    128: 
                    129: /*** event_doframe - execute until the end of the current frame ***/
                    130: 
                    131: void event_doframe(void)
                    132: {
                    133:   unsigned int startframe = cpu68k_frames;
                    134: 
                    135:   do {
                    136:     while (vdp_nextevent > 0)
                    137:       vdp_nextevent = -reg68k_external_execute(vdp_nextevent);
                    138:     event_nextevent();
                    139:   } while (startframe == cpu68k_frames);
                    140: 
                    141: }
                    142: 
                    143: /*** event_step - execute one instruction with no caching ***/
                    144: 
                    145: void event_dostep(void)
                    146: {
                    147:   /* execute one instruction and subtract from vdp_nextevent those cycles */
                    148:   vdp_nextevent-= reg68k_external_step();
                    149:   /* if negative or 0, i.e. we have done all the cycles we need to this event,
                    150:      call event_nextevent! */
                    151:   while (vdp_nextevent <= 0)
                    152:     event_nextevent();
                    153: }
                    154: 
                    155: /*** event_freeze_clocks - freeze 68k for given clock cycles ***/
                    156: 
                    157: /* NB: this routine is called by event_freeze which is called by
                    158:    vdp routines.  This could all happen IN THE MIDDLE OF A BLOCK at which
                    159:    point cpu68k_clocks will have been updated but vdp_nextevent will not! 
                    160:    therefore we must at this point work out what vdp_nextevent should be
                    161:    at the current moment in time, add on the clocks, wind forward time and
                    162:    then subtract the clocks that will be added later */
                    163: 
                    164: void event_freeze_clocks(unsigned int clocks)
                    165: {
                    166:   int old_nextevent = vdp_nextevent;
                    167:   int missed = 0;
                    168: 
                    169:   /* first - fix vdp_nextevent to be correct for right now, due to block
                    170:      marking delay */
                    171: 
                    172:   /* find out how many clocks vdp_nextevent has missed */
                    173:   /* modify vdp_nextevent to reflect the real state as of now */
                    174: 
                    175:   switch (vdp_event) {
                    176:   case 0:
                    177:     missed = vdp_nextevent - (vdp_event_start - cpu68k_clocks);
                    178:     vdp_nextevent-= missed;
                    179:     break;
                    180:   case 1:
                    181:     missed = vdp_nextevent - (vdp_event_vint - cpu68k_clocks);
                    182:     vdp_nextevent-= missed;
                    183:     break;
                    184:   case 2:
                    185:     missed = vdp_nextevent - (vdp_event_hint - cpu68k_clocks);
                    186:     vdp_nextevent-= missed;
                    187:     break;
                    188:   case 3:
                    189:     missed = vdp_nextevent - (vdp_event_hdisplay - cpu68k_clocks);
                    190:     vdp_nextevent-= missed;
                    191:     break;
                    192:   case 4:
                    193:     missed = vdp_nextevent - (vdp_event_end - cpu68k_clocks);
                    194:     vdp_nextevent-= missed;
                    195:     break;
                    196:   default:
                    197:     printf("assertion failed: bad vdp_event in event_freeze_clocks: %d\n",
                    198:            vdp_event);
                    199:   }
                    200: 
                    201:   /* move cpu68k_clocks and vdp_nextevent forward in time */
                    202: 
                    203:   cpu68k_clocks+= clocks;
                    204:   vdp_nextevent-= clocks;
                    205: 
                    206:   /* now catch up events */
                    207: 
                    208:   while (vdp_nextevent <= 0)
                    209:     event_nextevent();
                    210: 
                    211:   /* and then un-adjust vdp_nextevent, as the block marking code will update
                    212:      this later */
                    213: 
                    214:   vdp_nextevent+= missed;
                    215: }
                    216: 
                    217: /*** event_freeze - freeze 68k for given VDP byte transfer ***/
                    218: 
                    219: void event_freeze(unsigned int bytes)
                    220: {
                    221:   int wide = vdp_reg[12] & 1;
                    222:   int clocks, possible;
                    223:   double percent_possible;
                    224:   int togo = (int)bytes;
                    225: 
                    226:   cpu68k_frozen = 1; /* prohibit interrupts since PC is not known in the
                    227:                         middle of a 68k block due to register mappings */
                    228: 
                    229:   while (togo > 0) {
                    230:     /* clocks will be negative if we're in the middle of a cpu block */
                    231:     clocks = vdp_event_end - cpu68k_clocks;
                    232:     if (clocks < 0)
                    233:       clocks = 0;
                    234:     percent_possible = clocks/vdp_clksperline_68k;
                    235:     if (vdp_reg[1] & 1<<6 && !vdp_vblank) {
                    236:       /* vdp active */
                    237:       possible = (unsigned int)(percent_possible*(wide ? 18 : 16));
                    238:     } else {
                    239:       /* vdp inactive */
                    240:       possible = (unsigned int)(percent_possible*(wide ? 205 : 167));
                    241:     }
                    242:     if (togo >= possible) {
                    243:       event_freeze_clocks(clocks);
                    244:       togo-= possible;
                    245:     } else {
                    246:       event_freeze_clocks(((double)togo/possible)*clocks);
                    247:       togo = 0;
                    248:     }
                    249:   }
                    250:   cpu68k_frozen = 0;
                    251: }

unix.superglobalmegacorp.com

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