Annotation of generator/main/event.c, revision 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.