Annotation of generator/src/reg68k.c, revision 1.1

1.1     ! root        1: /*****************************************************************************/
        !             2: /*     Generator - Sega Genesis emulation - (c) James Ponder 1997-2000       */
        !             3: /*****************************************************************************/
        !             4: /*                                                                           */
        !             5: /* reg68k.c                                                                  */
        !             6: /*                                                                           */
        !             7: /*****************************************************************************/
        !             8: 
        !             9: #include "generator.h"
        !            10: #include "registers.h"
        !            11: 
        !            12: #include <stdio.h>
        !            13: #include <string.h>
        !            14: #include <stdlib.h>
        !            15: #include <setjmp.h>
        !            16: 
        !            17: #include "mem68k.h"
        !            18: #include "cpu68k.h"
        !            19: #include "cpuz80.h"
        !            20: #include "vdp.h"
        !            21: #include "ui.h"
        !            22: #include "compile.h"
        !            23: #include "gensound.h"
        !            24: 
        !            25: /*** externed variables ***/
        !            26: 
        !            27: #if (!(defined(PROCESSOR_ARM) || defined(PROCESSOR_SPARC) \
        !            28:        || defined(PROCESSOR_INTEL)))
        !            29:   uint32 reg68k_pc;
        !            30:   uint32 *reg68k_regs;
        !            31:   t_sr reg68k_sr;
        !            32: #endif
        !            33: 
        !            34: /*** forward references ***/
        !            35: 
        !            36: inline void reg68k_checkevent(void);
        !            37: void reg68k_autovector(int avno);
        !            38: 
        !            39: static unsigned int reg68k_eventdelay;
        !            40: 
        !            41: void reg68k_step(void)
        !            42: {
        !            43:   /* PAL: 312 lines, 224 or 240 visible @ 50Hz - CPU @ 7.60Mhz */
        !            44:   /* NTSC: 262 lines, 224 visible @ 60Hz - CPU @ 7.67Mhz */
        !            45: 
        !            46:   static t_ipc ipc;
        !            47:   static t_iib *piib;
        !            48:   jmp_buf jb;
        !            49: 
        !            50:   /* !!! entering global register usage area !!! */
        !            51: 
        !            52:   if (!setjmp(jb)) {
        !            53:     if (!(piib = cpu68k_iibtable[fetchword(regs.pc)]))
        !            54:       ui_err("Invalid instruction @ %08X\n", regs.pc);
        !            55:     /* move PC and register block into global variables */
        !            56:     reg68k_pc = regs.pc;
        !            57:     reg68k_regs = regs.regs;
        !            58:     reg68k_sr = regs.sr;
        !            59: 
        !            60:     cpu68k_ipc(reg68k_pc,
        !            61:               mem68k_memptr[(reg68k_pc>>12) & 0xfff](reg68k_pc & 0xFFFFFF),
        !            62:               piib, &ipc);
        !            63:     cpu68k_functable[fetchword(reg68k_pc)*2+1](&ipc);
        !            64:     cpu68k_clocks+= piib->clocks;
        !            65:     reg68k_checkevent();
        !            66:     /* restore global registers back to permanent storage */
        !            67:     regs.pc = reg68k_pc;
        !            68:     regs.sr = reg68k_sr;
        !            69:     longjmp(jb, 1);
        !            70:   }
        !            71: }
        !            72: 
        !            73: inline void reg68k_checkevent(void)
        !            74: {
        !            75:   switch(vdp_event) {
        !            76:   case 0:
        !            77:     if (cpu68k_clocks >= vdp_event_start) {
        !            78:       vdp_event_startofcurrentline = vdp_event_start;
        !            79:       LOG_USER(("%08X due %08X, %d A: %d (cd=%d)",
        !            80:                cpu68k_clocks, vdp_event_start, vdp_line, vdp_reg[10],
        !            81:                vdp_hskip_countdown));
        !            82:       vdp_event++;
        !            83:       vdp_event_start+= vdp_clksperline_68k;
        !            84:       cpuz80_sync();
        !            85:       if (vdp_line == 0) {
        !            86:        vdp_vblank = 0;
        !            87:        vdp_hskip_countdown = vdp_reg[10];
        !            88:        ui_line(0);
        !            89:       }
        !            90:       if (vdp_line < vdp_vislines)
        !            91:        ui_line(vdp_line);
        !            92:     }
        !            93:     break;
        !            94:   case 1:
        !            95:     if (cpu68k_clocks >= vdp_event_vint) {
        !            96:       LOG_USER(("%08X due %08X, %d B: %d (cd=%d)",
        !            97:                cpu68k_clocks, vdp_event_vint, vdp_line, vdp_reg[10],
        !            98:                vdp_hskip_countdown));
        !            99:       vdp_event++;
        !           100:       vdp_event_vint+= vdp_clksperline_68k;
        !           101:       if (vdp_line == vdp_vislines) {
        !           102:        vdp_vblank = 1;
        !           103:        vdp_vsync = 1;
        !           104:        if (vdp_reg[1] & 1<<5)
        !           105:          reg68k_autovector(6); /* vertical interrupt */
        !           106:       }
        !           107:     }
        !           108:     break;
        !           109:   case 2:
        !           110:     if (cpu68k_clocks >= vdp_event_hint) {
        !           111:       LOG_USER(("%08X due %08X, %d C: %d (cd=%d)",
        !           112:                cpu68k_clocks, vdp_event_hint, vdp_line, vdp_reg[10],
        !           113:                vdp_hskip_countdown));
        !           114:       /* delay hdisplay if hint is delayed */
        !           115:       vdp_event++;
        !           116:       vdp_event_hint+= vdp_clksperline_68k;
        !           117:       cpuz80_sync();
        !           118:       /* if (vdp_line < vdp_vislines) */
        !           119:        vdp_hblank = 1;
        !           120:       if (vdp_reg[0] & 1<<4) {
        !           121:        if (vdp_hskip_countdown-- == 0) {
        !           122:          /* re-initialise counter */
        !           123:          vdp_hskip_countdown = vdp_reg[10];
        !           124:          if (vdp_line < vdp_vislines)
        !           125:            reg68k_autovector(4); /* horizontal interrupt */
        !           126:          /* since this game is obviously timing sensitive, we sacrifice
        !           127:             executing the right number of 68k clocks this frame in order
        !           128:             to accurately do the moments following H-Int */
        !           129:          cpu68k_clocks = vdp_event_hint - vdp_clksperline_68k;
        !           130:        }
        !           131:       }
        !           132:     }
        !           133:     break;
        !           134:   case 3:
        !           135:     if (cpu68k_clocks >= vdp_event_hdisplay) {
        !           136:       LOG_USER(("%08X due %08X, %d D: %d (cd=%d)",
        !           137:                cpu68k_clocks, vdp_event_hdisplay, vdp_line, vdp_reg[10],
        !           138:                vdp_hskip_countdown));
        !           139:       vdp_event_hdisplay-= reg68k_eventdelay;
        !           140:       vdp_event++;
        !           141:       vdp_event_hdisplay+= vdp_clksperline_68k;
        !           142:       cpuz80_sync();
        !           143:       /* err
        !           144:       if (vdp_line+1 < vdp_vislines)
        !           145:        ui_line(vdp_line+1);
        !           146:       */
        !           147:     }
        !           148:     break;
        !           149:   case 4:
        !           150:     if (cpu68k_clocks >= vdp_event_end) {
        !           151:       /* end of line, do sound, platform stuff */
        !           152:       LOG_USER(("%08X due %08X, %d E: %d (cd=%d)",
        !           153:                cpu68k_clocks, vdp_event_end, vdp_line, vdp_reg[10],
        !           154:                vdp_hskip_countdown));
        !           155:       vdp_event = 0;
        !           156:       vdp_event_end+= vdp_clksperline_68k;
        !           157:       /* if (vdp_line < vdp_vislines) */
        !           158:        vdp_hblank = 0;
        !           159:       cpuz80_sync();
        !           160:       sound_process();
        !           161:       vdp_line++;
        !           162:       if (vdp_line == vdp_totlines) {
        !           163:        ui_endfield();
        !           164:        sound_endfield();
        !           165:        cpuz80_interrupt();
        !           166:        vdp_endfield();
        !           167:        cpuz80_endfield();
        !           168:        cpu68k_endfield();
        !           169:        cpu68k_frames++;
        !           170:       }
        !           171:     }
        !           172:     break;
        !           173:   } /* switch */
        !           174: }
        !           175: 
        !           176: /*** reg68k_framestep - do a frame and return ***/
        !           177: 
        !           178: void reg68k_framestep(void)
        !           179: {
        !           180:   /* PAL: 312 lines, 224 or 240 visible @ 50Hz - CPU @ 7.60Mhz */
        !           181:   /* NTSC: 262 lines, 224 visible @ 60Hz - CPU @ 7.67Mhz */
        !           182: 
        !           183:   unsigned int startframe = cpu68k_frames;
        !           184:   unsigned int index, i;
        !           185:   t_ipclist *list;
        !           186:   t_ipc *ipc;
        !           187:   uint32 pc24;
        !           188:   jmp_buf jb;
        !           189:   static t_ipc step_ipc;
        !           190:   static t_iib *step_piib;
        !           191: 
        !           192:   if (!setjmp(jb)) {
        !           193:     /* move PC and register block into global variables */
        !           194:     reg68k_pc = regs.pc;
        !           195:     reg68k_regs = regs.regs;
        !           196:     reg68k_sr = regs.sr;
        !           197: 
        !           198:     do {
        !           199:       pc24 = reg68k_pc & 0xffffff;
        !           200:       if ((pc24 & 0xff0000) == 0xff0000) {
        !           201:        /* executing code from RAM, do not use compiled information */
        !           202:        do {
        !           203:          step_piib = cpu68k_iibtable[fetchword(reg68k_pc)];
        !           204:          cpu68k_ipc(reg68k_pc,
        !           205:                     mem68k_memptr[(reg68k_pc>>12) &
        !           206:                                  0xfff](reg68k_pc & 0xFFFFFF),
        !           207:                     step_piib, &step_ipc);
        !           208:          cpu68k_functable[fetchword(reg68k_pc)*2+1](&step_ipc);
        !           209:          cpu68k_clocks+= step_piib->clocks;
        !           210:        } while (!step_piib->flags.endblk);
        !           211:        list = NULL; /* stop compiler warning ;(  */
        !           212:       } else {
        !           213:        index = (pc24>>1) & (LEN_IPCLISTTABLE-1);
        !           214:        list = ipclist[index];
        !           215:        while(list && (list->pc != pc24)) {
        !           216:          list = list->next;
        !           217:        }
        !           218: #ifdef PROCESSOR_ARM
        !           219:        if (!list) {
        !           220:          list = cpu68k_makeipclist(pc24);
        !           221:          list->next = ipclist[index];
        !           222:          ipclist[index] = list;
        !           223:          list->compiled = compile_make(list);
        !           224:        }
        !           225:        list->compiled((t_ipc *)(list+1));
        !           226: #else
        !           227:        if (!list) {
        !           228:          /* LOG_USER(("Making IPC list @ %08x", pc24)); */
        !           229:          list = cpu68k_makeipclist(pc24);
        !           230:          list->next = ipclist[index];
        !           231:          ipclist[index] = list;
        !           232:        }
        !           233:        ipc = (t_ipc *)(list+1);
        !           234:        do {
        !           235:          ipc->function(ipc);
        !           236:          ipc++;
        !           237:        } while (*(int *)ipc);
        !           238: #endif
        !           239:        cpu68k_clocks+= list->clocks;
        !           240:       }
        !           241:       reg68k_checkevent();
        !           242:     } while (cpu68k_frames == startframe);
        !           243:     /* restore global registers back to permanent storage */
        !           244:     regs.pc = reg68k_pc;
        !           245:     regs.sr = reg68k_sr;
        !           246:     longjmp(jb, 1);
        !           247:   }
        !           248: }
        !           249: 
        !           250: void reg68k_autovector(int avno)
        !           251: {
        !           252:   int curlevel = (reg68k_sr.sr_int>>8) & 7;
        !           253:   uint32 tmpaddr;
        !           254: 
        !           255:   LOG_VERBOSE(("autovector %d\n", avno));
        !           256:   if (curlevel < avno || avno == 7) {
        !           257:     if (!reg68k_sr.sr_struct.s) {
        !           258:       regs.regs[15]^= regs.sp;   /* swap A7 and SP */
        !           259:       regs.sp^= regs.regs[15];
        !           260:       regs.regs[15]^= regs.sp;
        !           261:       reg68k_sr.sr_struct.s = 1;
        !           262:     }
        !           263:     regs.regs[15]-=4;
        !           264:     storelong(regs.regs[15], reg68k_pc);
        !           265:     regs.regs[15]-=2;
        !           266:     storeword(regs.regs[15], reg68k_sr.sr_int);
        !           267:     reg68k_sr.sr_struct.t = 0;
        !           268:     reg68k_sr.sr_int&= ~0x0700;
        !           269:     reg68k_sr.sr_int|= avno << 8;
        !           270:     tmpaddr = reg68k_pc;
        !           271:     reg68k_pc = fetchlong((V_AUTO+avno-1)*4);
        !           272:     LOG_DEBUG1(("AUTOVECTOR %d: %X -> %X", avno, tmpaddr, reg68k_pc));
        !           273:   }
        !           274: }
        !           275: 
        !           276: void reg68k_vector(int vno, uint32 oldpc)
        !           277: {
        !           278:   LOG_DEBUG1(("Vector %d called from %8x!", vno, regs.pc));
        !           279:   if (!reg68k_sr.sr_struct.s) {
        !           280:     regs.regs[15]^= regs.sp;   /* swap A7 and SP */
        !           281:     regs.sp^= regs.regs[15];
        !           282:     regs.regs[15]^= regs.sp;
        !           283:     reg68k_sr.sr_struct.s = 1;
        !           284:   }
        !           285:   regs.regs[15]-=4;
        !           286:   storelong(regs.regs[15], oldpc);
        !           287:   regs.regs[15]-=2;
        !           288:   storeword(regs.regs[15], reg68k_sr.sr_int);
        !           289:   reg68k_pc = fetchlong(vno*4);
        !           290:   LOG_DEBUG1(("VECTOR %d: %X -> %X\n", vno, oldpc, reg68k_pc));
        !           291: }   

unix.superglobalmegacorp.com

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