Annotation of generator/src/reg68k.c, revision 1.1.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.