Exemple #1
0
void gb_run()
{
	
#ifdef PROFILE
	prof_enter(PF_GB_RUN);
#endif

	//if (rom_get_loaded()){
		if (g_regs.LCDC&0x80){ // LCDC 起動時
			g_regs.LY=(g_regs.LY+1)%154;

			g_regs.STAT&=0xF8;
			if (g_regs.LYC==g_regs.LY){
				g_regs.STAT|=4;
				if (g_regs.STAT&0x40)
					cpu_irq(INT_LCDC);
			}
			if (g_regs.LY==0){
				renderer_refresh();
				if (now_frame>=skip){
					//pgFillvram(0);

					render_screen(vframe);
					now_frame=0;
				}
				else
					now_frame++;
				lcd_clear_win_count();
//				skip=skip_buf;
			}
			if (g_regs.LY>=144){ // VBlank 期間中
				g_regs.STAT|=1;
				if (g_regs.LY==144){
					cpu_exec(72);
					cpu_irq(INT_VBLANK);
					if (g_regs.STAT&0x10)
						cpu_irq(INT_LCDC);
					cpu_exec(456-80);
				}
				else if (g_regs.LY==153){
					cpu_exec(80);
					g_regs.LY=0;
					cpu_exec(456-80); // 前のラインのかなり早目から0になるようだ。
					g_regs.LY=153;
				}
				else
					cpu_exec(456);
			}
			else{ // VBlank 期間外
				g_regs.STAT|=2;
				if (g_regs.STAT&0x20)
					cpu_irq(INT_LCDC);
				cpu_exec(80); // state=2
				g_regs.STAT|=3;
				cpu_exec(169); // state=3

				if (dma_executing){ // HBlank DMA
					if (b_dma_first){
						dma_dest_bank=vram_bank;
						if (dma_src<0x4000)
							dma_src_bank=get_rom();
						else if (dma_src<0x8000)
							dma_src_bank=mbc_get_rom();
						else if (dma_src>=0xA000&&dma_src<0xC000)
							dma_src_bank=mbc_get_sram()-0xA000;
						else if (dma_src>=0xC000&&dma_src<0xD000)
							dma_src_bank=ram-0xC000;
						else if (dma_src>=0xD000&&dma_src<0xE000)
							dma_src_bank=ram_bank-0xD000;
						else dma_src_bank=NULL;
						b_dma_first=false;
					}
					memcpy(dma_dest_bank+(dma_dest&0x1ff0),dma_src_bank+dma_src,16);
//					fprintf(cpu_file,"%03d : dma exec %04X -> %04X rest %d\n",g_regs.LY,cpu_dma_src,cpu_dma_dest,cpu_dma_rest);

					dma_src+=16;
					dma_src&=0xfff0;
					dma_dest+=16;

					dma_dest&=0xfff0;
					dma_rest--;
					if (!dma_rest)
						dma_executing=false;

//					cpu_total_clock+=207*(cpu_speed?2:1);
//					cpu_sys_clock+=207*(cpu_speed?2:1);
//					cpu_div_clock+=207*(cpu_speed?2:1);
//					g_regs.STAT|=3;

					if (now_frame>=skip && !sgb_mask)
						lcd_render(vframe,g_regs.LY);

					g_regs.STAT&=0xfc;
					cpu_exec(207); // state=3
				}
				else{
/*					if (lcd_get_sprite_count()){
						if (lcd_get_sprite_count()>=10){
							cpu_exec(129);
							if ((g_regs.STAT&0x08))
								cpu_irq(INT_LCDC);
							g_regs.STAT&=0xfc;
							if (now_frame>=skip)
								lcd_render(vframe,g_regs.LY);
							cpu_exec(78); // state=0
						}
						else{
							cpu_exec(129*lcd_get_sprite_count()/10);
							if ((g_regs.STAT&0x08))
								cpu_irq(INT_LCDC);
							g_regs.STAT&=0xfc;
							if (now_frame>=skip)
								lcd_render(vframe,g_regs.LY);
							cpu_exec(207-(129*lcd_get_sprite_count()/10)); // state=0
						}
					}
					else{
*/						g_regs.STAT&=0xfc;
						if (now_frame>=skip && !sgb_mask)
							lcd_render(vframe,g_regs.LY);
						if ((g_regs.STAT&0x08))
							cpu_irq(INT_LCDC);
						cpu_exec(207); // state=0
//					}
				}
			}
		}
		else{ // LCDC 停止時
			g_regs.LY=0;
//			g_regs.LY=(g_regs.LY+1)%154;
			re_render++;
			if (re_render>=154){
				gb_fill_vframe(0xff);
				
				renderer_refresh();
				if (now_frame>=skip){
					//pgFillvram(0);
					
					render_screen(vframe);
					now_frame=0;
				}
				else
					now_frame++;
				lcd_clear_win_count();
				re_render=0;
			}
			g_regs.STAT&=0xF8;
			cpu_exec(456);
		}
	//}
	
#ifdef PROFILE
	prof_out();
#endif
}
$$ macro definitions

/* interp -- main loop of the interpreter */
void interp(value *sp0) {
     register value *cp = sp0[CP].p;
     uchar *pc = cp[CP_CODE].x;
     register uchar *pc0 = NULL;
     register value *sp = sp0;
     register uchar ir = 0;
#ifdef PROFILE
     register counter ticks = 0;
#endif
     register value *fp = NULL;
     value *base = sp0;
#ifdef TRACE
     proc thisproc = NULL;
#endif

#ifdef JTABLE
     /* Save time by using gcc's label array feature */
     static void *jtable[256] = {
$$ jump table
     };
#endif

#ifdef JTABLE
/* Each action ends with an indexed jump to the next */
#define ACTION(op) lbl_ ## op:
#define ALSO(op)
#define DEFAULT
#define NEXT       goto *jtable[ir = *(pc0 = pc)]
#else
/* Actions are just cases in a big switch */
#define ACTION(op) case K_ ## op:
#define ALSO(op)   case K_ ## op:
#define DEFAULT    default:
#define NEXT       break
#endif

     level++;
     do_find_proc;

#ifdef PROFILE
     prof_enter(cp, 0, PROF_CALL);
#endif

     frame();

#ifdef JTABLE
     NEXT;
#else
     while (TRUE) {
#ifdef TRACE
          if (dflag > 1) {
               int i;
               printf("pc=%s+%d(%p) sp=%p fp=%p cp=%p",
                      thisproc->p_name, pc - cp[1].x, pc, sp, fp, cp);
               fflush(stdout);
               for (i = 0; i < 8; i++) printf(" %x", sp[i].i);
               printf("\n");
               printf("%6d: %s\n", pc-imem, fmt_inst(pc));
               fflush(stdout);
          }
#endif

#ifdef DEBUG
          if (sp > (value *) ((uchar *) fp - cp[CP_FRAME].i))
               panic("*value stack underflow");
#endif

#ifdef PROFILE
          ticks++;
#endif

          switch (ir = *(pc0 = pc)) {
#endif

$$ action routines

          ACTION(ILLEGAL)
          DEFAULT
               panic("*illegal instruction %d", ir);
#ifndef JTABLE
          }
     }
#endif
}