Implement game pad and timer
This commit is contained in:
		
							parent
							
								
									37b9a94338
								
							
						
					
					
						commit
						e9f5437c1f
					
				
							
								
								
									
										75
									
								
								core/bus.c
								
								
								
								
							
							
						
						
									
										75
									
								
								core/bus.c
								
								
								
								
							| 
						 | 
					@ -16,6 +16,13 @@ static const uint32_t TYPE_MASKS[] = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**************************** Forward references *****************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void vipRead (VB *, uint32_t, int, int32_t *);
 | 
				
			||||||
 | 
					static void vipWrite(VB *, uint32_t, int, int32_t, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*************************** Sub-Module Functions ****************************/
 | 
					/*************************** Sub-Module Functions ****************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Read a typed value from a buffer in host memory */
 | 
					/* Read a typed value from a buffer in host memory */
 | 
				
			||||||
| 
						 | 
					@ -76,14 +83,62 @@ static void busWriteBuffer(uint8_t *data, int type, int32_t value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Read a value from miscellaneous hardware I/O */
 | 
				
			||||||
 | 
					static int32_t busReadMisc(VB *sim, uint8_t address, int type) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Unmapped */
 | 
				
			||||||
 | 
					    switch (type) {
 | 
				
			||||||
 | 
					        case VB_S8 : case VB_U8 : if (address & 3) return 0; break;
 | 
				
			||||||
 | 
					        case VB_S16: case VB_U16: if (address & 1) return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Access by register */
 | 
				
			||||||
 | 
					    switch (address >> 2 & 15) {
 | 
				
			||||||
 | 
					        case 0x00>>2: break; /* CCR */
 | 
				
			||||||
 | 
					        case 0x04>>2: break; /* CCSR */
 | 
				
			||||||
 | 
					        case 0x08>>2: break; /* CDTR */
 | 
				
			||||||
 | 
					        case 0x0C>>2: break; /* CDRR */
 | 
				
			||||||
 | 
					        case 0x10>>2: return sim->pad.sdlr;                /* SDLR */
 | 
				
			||||||
 | 
					        case 0x14>>2: return sim->pad.sdhr;                /* SDHR */
 | 
				
			||||||
 | 
					        case 0x18>>2: return sim->tmr.counter      & 0xFF; /* TLR */
 | 
				
			||||||
 | 
					        case 0x1C>>2: return sim->tmr.counter >> 8 & 0xFF; /* THR */
 | 
				
			||||||
 | 
					        case 0x20>>2: return tmrReadControl(sim);          /* TCR */
 | 
				
			||||||
 | 
					        case 0x24>>2: return sim->wcr;                     /* WCR */
 | 
				
			||||||
 | 
					        case 0x28>>2: return padReadControl(sim);          /* SCR */
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Unmapped */
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Write a value to miscellaneous hardware I/O */
 | 
				
			||||||
 | 
					static void busWriteMisc(VB *sim, uint8_t address, int type, int32_t value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Unmapped */
 | 
				
			||||||
 | 
					    switch (type) {
 | 
				
			||||||
 | 
					        case VB_S8 : case VB_U8 : if (address & 3) return; break;
 | 
				
			||||||
 | 
					        case VB_S16: case VB_U16: if (address & 1) return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Access by register */
 | 
				
			||||||
 | 
					    switch (address >> 2 & 15) {
 | 
				
			||||||
 | 
					        case 0x00>>2: break; /* CCR */
 | 
				
			||||||
 | 
					        case 0x04>>2: break; /* CCSR */
 | 
				
			||||||
 | 
					        case 0x08>>2: break; /* CDTR */
 | 
				
			||||||
 | 
					        case 0x0C>>2: break; /* CDRR */
 | 
				
			||||||
 | 
					        case 0x18>>2: tmrWriteLow    (sim, value); break; /* TLR */
 | 
				
			||||||
 | 
					        case 0x1C>>2: tmrWriteHigh   (sim, value); break; /* THR */
 | 
				
			||||||
 | 
					        case 0x20>>2: tmrWriteControl(sim, value); break; /* TCR */
 | 
				
			||||||
 | 
					        case 0x24>>2: sim->wcr = value & 3;        break; /* WCR */
 | 
				
			||||||
 | 
					        case 0x28>>2: padWriteControl(sim, value); break; /* SCR */
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/***************************** Library Functions *****************************/
 | 
					/***************************** Library Functions *****************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Forward references */
 | 
					 | 
				
			||||||
static void vipRead (VB *, uint32_t, int, int32_t *);
 | 
					 | 
				
			||||||
static void vipWrite(VB *, uint32_t, int, int32_t, int);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Read a typed value from the simulation bus */
 | 
					/* Read a typed value from the simulation bus */
 | 
				
			||||||
static void busRead(VB *sim, uint32_t address, int type, int32_t *value) {
 | 
					static void busRead(VB *sim, uint32_t address, int type, int32_t *value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,7 +154,11 @@ static void busRead(VB *sim, uint32_t address, int type, int32_t *value) {
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case 1: break; /* VSU */
 | 
					        case 1: break; /* VSU */
 | 
				
			||||||
        case 2: break; /* Misc. I/O */
 | 
					
 | 
				
			||||||
 | 
					        case 2: /* Misc. I/O */
 | 
				
			||||||
 | 
					            *value = busReadMisc(sim, address, type);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case 3: break; /* Unmapped */
 | 
					        case 3: break; /* Unmapped */
 | 
				
			||||||
        case 4: break; /* Game Pak expansion */
 | 
					        case 4: break; /* Game Pak expansion */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -139,7 +198,11 @@ static void busWrite(VB*sim,uint32_t address,int type,int32_t value,int debug){
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case 1: break; /* VSU */
 | 
					        case 1: break; /* VSU */
 | 
				
			||||||
        case 2: break; /* Misc. I/O */
 | 
					
 | 
				
			||||||
 | 
					        case 2: /* Misc. I/O */
 | 
				
			||||||
 | 
					            busWriteMisc(sim, address, type, value);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case 3: break; /* Unmapped */
 | 
					        case 3: break; /* Unmapped */
 | 
				
			||||||
        case 4: break; /* Game Pak expansion */
 | 
					        case 4: break; /* Game Pak expansion */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										14
									
								
								core/cpu.c
								
								
								
								
							
							
						
						
									
										14
									
								
								core/cpu.c
								
								
								
								
							| 
						 | 
					@ -1825,8 +1825,18 @@ static void cpuReset(VB *sim) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Determine how many clocks are guaranteed to process */
 | 
					/* Determine how many clocks are guaranteed to process */
 | 
				
			||||||
static uint32_t cpuUntil(VB *sim, uint32_t clocks) {
 | 
					static uint32_t cpuUntil(VB *sim, uint32_t clocks) {
 | 
				
			||||||
    return sim->cpu.halt || sim->cpu.clocks > clocks ?
 | 
					
 | 
				
			||||||
        clocks : sim->cpu.clocks;
 | 
					    /* Halting */
 | 
				
			||||||
 | 
					    if (sim->cpu.halt) {
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					            sim->cpu.operation == CPU_HALTING                      &&
 | 
				
			||||||
 | 
					            !(sim->cpu.psw.id | sim->cpu.psw.ep | sim->cpu.psw.np) &&
 | 
				
			||||||
 | 
					            IRQ_LEVELS[sim->cpu.irq] < sim->cpu.psw.i
 | 
				
			||||||
 | 
					        ? 0 : clocks;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Not halting */
 | 
				
			||||||
 | 
					    return sim->cpu.clocks > clocks ? clocks : sim->cpu.clocks;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* VBAPI */
 | 
					#endif /* VBAPI */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,117 @@
 | 
				
			||||||
 | 
					/* This file is included into vb.c and cannot be compiled on its own. */
 | 
				
			||||||
 | 
					#ifdef VBAPI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************** Library Functions *****************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Process component */
 | 
				
			||||||
 | 
					static int padEmulate(VB *sim, uint32_t clocks) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* No hardware read in progress */
 | 
				
			||||||
 | 
					    if (sim->pad.si_stat == 0)
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Hardware read completes after time to process */
 | 
				
			||||||
 | 
					    if (sim->pad.si_stat > clocks) {
 | 
				
			||||||
 | 
					        sim->pad.si_stat -= clocks;
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Complete hardware read */
 | 
				
			||||||
 | 
					    sim->pad.si_stat = 0;
 | 
				
			||||||
 | 
					    sim->pad.sdlr    = sim->pad.keys;
 | 
				
			||||||
 | 
					    sim->pad.sdhr    = sim->pad.keys >> 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Raise game pad interrupt */
 | 
				
			||||||
 | 
					    if (
 | 
				
			||||||
 | 
					        !sim->pad.k_int_inh           &&
 | 
				
			||||||
 | 
					        (sim->pad.keys & 0xFFF0) != 0 &&
 | 
				
			||||||
 | 
					        (sim->pad.keys & 0x000E) == 0
 | 
				
			||||||
 | 
					    ) sim->cpu.irq |= 0x0001;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Read a value from SCR */
 | 
				
			||||||
 | 
					static int32_t padReadControl(VB *sim) {
 | 
				
			||||||
 | 
					    return 0x4C |
 | 
				
			||||||
 | 
					        sim->pad.k_int_inh << 7 |
 | 
				
			||||||
 | 
					        sim->pad.para_si   << 5 |
 | 
				
			||||||
 | 
					        sim->pad.soft_ck   << 4 |
 | 
				
			||||||
 | 
					        !!sim->pad.si_stat << 1 |
 | 
				
			||||||
 | 
					        sim->pad.s_abt_dis
 | 
				
			||||||
 | 
					    ;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Simulate a hardware reset */
 | 
				
			||||||
 | 
					static void padReset(VB *sim) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Normal */
 | 
				
			||||||
 | 
					    sim->pad.k_int_inh = 0;
 | 
				
			||||||
 | 
					    sim->pad.para_si   = 0;
 | 
				
			||||||
 | 
					    sim->pad.s_abt_dis = 0;
 | 
				
			||||||
 | 
					    sim->pad.sdhr      = 0x00;
 | 
				
			||||||
 | 
					    sim->pad.sdlr      = 0x00;
 | 
				
			||||||
 | 
					    sim->pad.si_stat   = 0;
 | 
				
			||||||
 | 
					    sim->pad.soft_ck   = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Other */
 | 
				
			||||||
 | 
					    sim->pad.step = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Write a value to SCR */
 | 
				
			||||||
 | 
					static void padWriteControl(VB *sim, uint8_t value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Acknowledge and disable interrupt */
 | 
				
			||||||
 | 
					    sim->pad.k_int_inh = value >> 7 & 1;
 | 
				
			||||||
 | 
					    if (sim->pad.k_int_inh)
 | 
				
			||||||
 | 
					        sim->cpu.irq &= ~0x0001;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Enable or disable hardware reads */
 | 
				
			||||||
 | 
					    sim->pad.s_abt_dis = value & 1;
 | 
				
			||||||
 | 
					    if (sim->pad.s_abt_dis)
 | 
				
			||||||
 | 
					        sim->pad.si_stat = 0; /* Abort hardware read */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Initiate a hardware read */
 | 
				
			||||||
 | 
					    if (
 | 
				
			||||||
 | 
					        (value & 0x04)        && /* HW-SI */
 | 
				
			||||||
 | 
					        sim->pad.si_stat == 0 && /* No hardware read underway */
 | 
				
			||||||
 | 
					        !sim->pad.s_abt_dis      /* Hardware reads enabled */
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					        sim->pad.si_stat = 10240; /* 512us */
 | 
				
			||||||
 | 
					        sim->pad.step    = 0;     /* Abort software read */
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Reset the read operation */
 | 
				
			||||||
 | 
					    sim->pad.para_si = value >> 5 & 1;
 | 
				
			||||||
 | 
					    if (
 | 
				
			||||||
 | 
					        sim->pad.para_si &&
 | 
				
			||||||
 | 
					        sim->pad.si_stat == 0 /* No hardware read underway */
 | 
				
			||||||
 | 
					    ) sim->pad.step = 32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Signal a bit for a software read */
 | 
				
			||||||
 | 
					    sim->pad.soft_ck = value >> 4 & 1;
 | 
				
			||||||
 | 
					    if (
 | 
				
			||||||
 | 
					        sim->pad.step != 0 && /* Software read is underway */
 | 
				
			||||||
 | 
					        !sim->pad.para_si  && /* Not resetting software read */
 | 
				
			||||||
 | 
					        ((sim->pad.soft_ck ^ sim->pad.step) & 1) == 1 /* Advance */
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					        sim->pad.step--;
 | 
				
			||||||
 | 
					        if (sim->pad.step == 0) {
 | 
				
			||||||
 | 
					            sim->pad.sdlr = sim->pad.keys;
 | 
				
			||||||
 | 
					            sim->pad.sdhr = sim->pad.keys >> 8;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Determine how many clocks are guaranteed to process */
 | 
				
			||||||
 | 
					static uint32_t padUntil(VB *sim, uint32_t clocks) {
 | 
				
			||||||
 | 
					    return sim->pad.si_stat != 0 && sim->pad.si_stat < clocks ?
 | 
				
			||||||
 | 
					        sim->pad.si_stat : clocks;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* VBAPI */
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,130 @@
 | 
				
			||||||
 | 
					/* This file is included into vb.c and cannot be compiled on its own. */
 | 
				
			||||||
 | 
					#ifdef VBAPI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************** Module Functions ******************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Update the counter to a new value */
 | 
				
			||||||
 | 
					static void tmrUpdate(VB *sim, uint16_t value) {
 | 
				
			||||||
 | 
					    if (value == 0 && sim->tmr.counter != 0) {
 | 
				
			||||||
 | 
					        if (sim->tmr.t_enb)
 | 
				
			||||||
 | 
					            sim->tmr.z_stat = 1;
 | 
				
			||||||
 | 
					        if (sim->tmr.tim_z_int)
 | 
				
			||||||
 | 
					            sim->cpu.irq |= 0x0002;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    sim->tmr.counter = value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************** Library Functions *****************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Process component */
 | 
				
			||||||
 | 
					static int tmrEmulate(VB *sim, uint32_t clocks) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Timer is disabled */
 | 
				
			||||||
 | 
					    if (!sim->tmr.t_enb)
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Process all clocks */
 | 
				
			||||||
 | 
					    for (;;) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Next tick is after time to process */
 | 
				
			||||||
 | 
					        if (sim->tmr.clocks > clocks) {
 | 
				
			||||||
 | 
					            sim->tmr.clocks -= clocks;
 | 
				
			||||||
 | 
					            sim->tmr.until  -= clocks;
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Advance forward the component's number of clocks */
 | 
				
			||||||
 | 
					        clocks         -= sim->tmr.clocks;
 | 
				
			||||||
 | 
					        sim->tmr.until -= sim->tmr.clocks;
 | 
				
			||||||
 | 
					        sim->tmr.clocks = sim->tmr.t_clk_sel ? 400 : 2000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Advance to the next counter value */
 | 
				
			||||||
 | 
					        tmrUpdate(sim, sim->tmr.counter == 0 ?
 | 
				
			||||||
 | 
					            sim->tmr.reload : sim->tmr.counter - 1);
 | 
				
			||||||
 | 
					        if (sim->tmr.counter == 0)
 | 
				
			||||||
 | 
					            sim->tmr.until = sim->tmr.clocks * ((uint32_t)sim->tmr.reload + 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Read a value from TCR */
 | 
				
			||||||
 | 
					static int32_t tmrReadControl(VB *sim) {
 | 
				
			||||||
 | 
					    return 0xE4 |
 | 
				
			||||||
 | 
					        sim->tmr.t_clk_sel << 4 |
 | 
				
			||||||
 | 
					        sim->tmr.tim_z_int << 3 |
 | 
				
			||||||
 | 
					        sim->tmr.z_stat    << 1 |
 | 
				
			||||||
 | 
					        sim->tmr.t_enb
 | 
				
			||||||
 | 
					    ;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Simulate a hardware reset */
 | 
				
			||||||
 | 
					static void tmrReset(VB *sim) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Normal */
 | 
				
			||||||
 | 
					    sim->tmr.t_enb     = 0;
 | 
				
			||||||
 | 
					    sim->tmr.t_clk_sel = 0;
 | 
				
			||||||
 | 
					    sim->tmr.tim_z_int = 0;
 | 
				
			||||||
 | 
					    sim->tmr.z_stat    = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Other */
 | 
				
			||||||
 | 
					    sim->tmr.counter = 0xFFFF;
 | 
				
			||||||
 | 
					    sim->tmr.reload  = 0x0000;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Determine how many clocks are guaranteed to process */
 | 
				
			||||||
 | 
					static uint32_t tmrUntil(VB *sim, uint32_t clocks) {
 | 
				
			||||||
 | 
					    return sim->tmr.t_enb && sim->tmr.until < clocks ?
 | 
				
			||||||
 | 
					        sim->tmr.until : clocks;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Write a value to TCR */
 | 
				
			||||||
 | 
					static void tmrWriteControl(VB *sim, uint8_t value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Clear interrupt status */
 | 
				
			||||||
 | 
					    if (
 | 
				
			||||||
 | 
					        (value & 0x04) && /* Z-Stat-Clr */
 | 
				
			||||||
 | 
					        (
 | 
				
			||||||
 | 
					            sim->tmr.counter != 0 ||
 | 
				
			||||||
 | 
					            !sim->tmr.t_enb
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					        sim->tmr.z_stat = sim->tmr.counter != 0;
 | 
				
			||||||
 | 
					        sim->cpu.irq   &= ~0x0002;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Parse fields */
 | 
				
			||||||
 | 
					    sim->tmr.t_clk_sel = value >> 4 & 1;
 | 
				
			||||||
 | 
					    sim->tmr.tim_z_int = value >> 3 & 1;
 | 
				
			||||||
 | 
					    sim->tmr.t_enb     = value      & 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* The interrupt is disabled */
 | 
				
			||||||
 | 
					    if (!sim->tmr.tim_z_int)
 | 
				
			||||||
 | 
					        sim->cpu.irq &= ~0x0002;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Configure countdowns */
 | 
				
			||||||
 | 
					    sim->tmr.clocks = sim->tmr.t_clk_sel ? 400 : 2000;
 | 
				
			||||||
 | 
					    sim->tmr.until  = sim->tmr.clocks * (sim->tmr.counter == 0 ?
 | 
				
			||||||
 | 
					        (uint32_t) sim->tmr.reload + 1 : sim->tmr.counter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* TODO: Will Z-Stat raise an interrupt when Tim-Z-Int is set? */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Write to the high data register */
 | 
				
			||||||
 | 
					static void tmrWriteHigh(VB *sim, uint8_t value) {
 | 
				
			||||||
 | 
					    sim->tmr.reload = (uint16_t) value << 8 | (sim->tmr.reload & 0x00FF);
 | 
				
			||||||
 | 
					    tmrUpdate(sim, sim->tmr.reload);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Write to the low data register */
 | 
				
			||||||
 | 
					static void tmrWriteLow(VB *sim, uint8_t value) {
 | 
				
			||||||
 | 
					    sim->tmr.reload = (sim->tmr.reload & 0xFF00) | value;
 | 
				
			||||||
 | 
					    tmrUpdate(sim, sim->tmr.reload);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* VBAPI */
 | 
				
			||||||
							
								
								
									
										57
									
								
								core/vb.c
								
								
								
								
							
							
						
						
									
										57
									
								
								core/vb.c
								
								
								
								
							| 
						 | 
					@ -90,6 +90,39 @@ struct VB {
 | 
				
			||||||
        int      step;      /* Operation sub-task ID */
 | 
					        int      step;      /* Operation sub-task ID */
 | 
				
			||||||
    } cpu;
 | 
					    } cpu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Game pad */
 | 
				
			||||||
 | 
					    struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Hardware state */
 | 
				
			||||||
 | 
					        uint8_t  k_int_inh; /* Interrupt acknowledge/disable */
 | 
				
			||||||
 | 
					        uint8_t  para_si;   /* Read reset signal */
 | 
				
			||||||
 | 
					        uint8_t  s_abt_dis; /* Abort hardware read */
 | 
				
			||||||
 | 
					        uint8_t  sdhr;      /* High key bits */
 | 
				
			||||||
 | 
					        uint8_t  sdlr;      /* Low key bits */
 | 
				
			||||||
 | 
					        uint32_t si_stat;   /* Hardware read in progress */
 | 
				
			||||||
 | 
					        uint8_t  soft_ck;   /* Controller communication signal */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Simulation state */
 | 
				
			||||||
 | 
					        uint8_t keys; /* Next input bits */
 | 
				
			||||||
 | 
					        int     step; /* Software read processing phase */
 | 
				
			||||||
 | 
					    } pad;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Timer */
 | 
				
			||||||
 | 
					    struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Hardware state */
 | 
				
			||||||
 | 
					        uint8_t t_clk_sel; /* Counter tick duration */
 | 
				
			||||||
 | 
					        uint8_t t_enb;     /* Enable timer */
 | 
				
			||||||
 | 
					        uint8_t tim_z_int; /* Enable interrupt */
 | 
				
			||||||
 | 
					        uint8_t z_stat;    /* Zero status */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Simulation state */
 | 
				
			||||||
 | 
					        uint32_t clocks;  /* Master clocks to wait */
 | 
				
			||||||
 | 
					        uint16_t counter; /* Current counter value */
 | 
				
			||||||
 | 
					        uint16_t reload;  /* Reload counter value */
 | 
				
			||||||
 | 
					        uint32_t until;   /* Clocks until interrupt condition */
 | 
				
			||||||
 | 
					    } tmr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* VIP */
 | 
					    /* VIP */
 | 
				
			||||||
    struct {
 | 
					    struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -168,6 +201,7 @@ struct VB {
 | 
				
			||||||
    } vip;
 | 
					    } vip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Other state */
 | 
					    /* Other state */
 | 
				
			||||||
 | 
					    uint8_t wcr;           /* Wait controller state */
 | 
				
			||||||
    uint8_t wram[0x10000]; /* System RAM */
 | 
					    uint8_t wram[0x10000]; /* System RAM */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Application data */
 | 
					    /* Application data */
 | 
				
			||||||
| 
						 | 
					@ -199,6 +233,8 @@ static int32_t SignExtend(int32_t value, int32_t bits) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/******************************** Sub-Modules ********************************/
 | 
					/******************************** Sub-Modules ********************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "game-pad.c"
 | 
				
			||||||
 | 
					#include "timer.c"
 | 
				
			||||||
#include "bus.c"
 | 
					#include "bus.c"
 | 
				
			||||||
#include "cpu.c"
 | 
					#include "cpu.c"
 | 
				
			||||||
#include "vip.c"
 | 
					#include "vip.c"
 | 
				
			||||||
| 
						 | 
					@ -211,7 +247,9 @@ static int32_t SignExtend(int32_t value, int32_t bits) {
 | 
				
			||||||
static int sysEmulate(VB *sim, uint32_t clocks) {
 | 
					static int sysEmulate(VB *sim, uint32_t clocks) {
 | 
				
			||||||
    return
 | 
					    return
 | 
				
			||||||
        cpuEmulate(sim, clocks) |
 | 
					        cpuEmulate(sim, clocks) |
 | 
				
			||||||
        vipEmulate(sim, clocks)
 | 
					        vipEmulate(sim, clocks) |
 | 
				
			||||||
 | 
					        padEmulate(sim, clocks) |
 | 
				
			||||||
 | 
					        tmrEmulate(sim, clocks)
 | 
				
			||||||
    ;
 | 
					    ;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -219,6 +257,8 @@ static int sysEmulate(VB *sim, uint32_t clocks) {
 | 
				
			||||||
static uint32_t sysUntil(VB *sim, uint32_t clocks) {
 | 
					static uint32_t sysUntil(VB *sim, uint32_t clocks) {
 | 
				
			||||||
    clocks = cpuUntil(sim, clocks);
 | 
					    clocks = cpuUntil(sim, clocks);
 | 
				
			||||||
    clocks = vipUntil(sim, clocks);
 | 
					    clocks = vipUntil(sim, clocks);
 | 
				
			||||||
 | 
					    clocks = padUntil(sim, clocks);
 | 
				
			||||||
 | 
					    clocks = tmrUntil(sim, clocks);
 | 
				
			||||||
    return clocks;
 | 
					    return clocks;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -295,6 +335,11 @@ VBAPI vbOnFrame vbGetFrameCallback(VB *sim) {
 | 
				
			||||||
    return sim->onFrame;
 | 
					    return sim->onFrame;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Retrieve the current game pad key state */
 | 
				
			||||||
 | 
					VBAPI uint16_t vbGetKeys(VB *sim) {
 | 
				
			||||||
 | 
					    return sim->pad.keys;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Retrieve the most recent frame image pixels */
 | 
					/* Retrieve the most recent frame image pixels */
 | 
				
			||||||
VBAPI void vbGetPixels(VB *sim, void *left, int leftStrideX, int leftStrideY,
 | 
					VBAPI void vbGetPixels(VB *sim, void *left, int leftStrideX, int leftStrideY,
 | 
				
			||||||
    void *right, int rightStrideX, int rightStrideY) {
 | 
					    void *right, int rightStrideX, int rightStrideY) {
 | 
				
			||||||
| 
						 | 
					@ -391,6 +436,9 @@ VBAPI int32_t vbRead(VB *sim, uint32_t address, int type) {
 | 
				
			||||||
VBAPI VB* vbReset(VB *sim) {
 | 
					VBAPI VB* vbReset(VB *sim) {
 | 
				
			||||||
    int x; /* Iterator */
 | 
					    int x; /* Iterator */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Wait controller */
 | 
				
			||||||
 | 
					    sim->wcr = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* WRAM (the hardware does not do this) */
 | 
					    /* WRAM (the hardware does not do this) */
 | 
				
			||||||
    for (x = 0; x < 0x10000; x++)
 | 
					    for (x = 0; x < 0x10000; x++)
 | 
				
			||||||
        sim->wram[x] = 0x00;
 | 
					        sim->wram[x] = 0x00;
 | 
				
			||||||
| 
						 | 
					@ -398,6 +446,8 @@ VBAPI VB* vbReset(VB *sim) {
 | 
				
			||||||
    /* Components */
 | 
					    /* Components */
 | 
				
			||||||
    cpuReset(sim);
 | 
					    cpuReset(sim);
 | 
				
			||||||
    vipReset(sim);
 | 
					    vipReset(sim);
 | 
				
			||||||
 | 
					    padReset(sim);
 | 
				
			||||||
 | 
					    tmrReset(sim);
 | 
				
			||||||
    return sim;
 | 
					    return sim;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -451,6 +501,11 @@ VBAPI vbOnFrame vbSetFrameCallback(VB *sim, vbOnFrame callback) {
 | 
				
			||||||
    return prev;
 | 
					    return prev;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Specify new game pad keys */
 | 
				
			||||||
 | 
					VBAPI uint16_t vbSetKeys(VB *sim, uint16_t keys) {
 | 
				
			||||||
 | 
					    return sim->pad.keys = keys;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Specify a new value for the program counter */
 | 
					/* Specify a new value for the program counter */
 | 
				
			||||||
VBAPI uint32_t vbSetProgramCounter(VB *sim, uint32_t value) {
 | 
					VBAPI uint32_t vbSetProgramCounter(VB *sim, uint32_t value) {
 | 
				
			||||||
    sim->cpu.operation = CPU_FETCH;
 | 
					    sim->cpu.operation = CPU_FETCH;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -107,6 +107,7 @@ VBAPI vbOnException vbGetExceptionCallback(VB *sim);
 | 
				
			||||||
VBAPI vbOnExecute   vbGetExecuteCallback  (VB *sim);
 | 
					VBAPI vbOnExecute   vbGetExecuteCallback  (VB *sim);
 | 
				
			||||||
VBAPI vbOnFetch     vbGetFetchCallback    (VB *sim);
 | 
					VBAPI vbOnFetch     vbGetFetchCallback    (VB *sim);
 | 
				
			||||||
VBAPI vbOnFrame     vbGetFrameCallback    (VB *sim);
 | 
					VBAPI vbOnFrame     vbGetFrameCallback    (VB *sim);
 | 
				
			||||||
 | 
					VBAPI uint16_t      vbGetKeys             (VB *sim);
 | 
				
			||||||
VBAPI void          vbGetPixels           (VB *sim, void *left, int leftStrideX, int leftStrideY, void *right, int rightStrideX, int rightStrideY);
 | 
					VBAPI void          vbGetPixels           (VB *sim, void *left, int leftStrideX, int leftStrideY, void *right, int rightStrideX, int rightStrideY);
 | 
				
			||||||
VBAPI uint32_t      vbGetProgramCounter   (VB *sim);
 | 
					VBAPI uint32_t      vbGetProgramCounter   (VB *sim);
 | 
				
			||||||
VBAPI int32_t       vbGetProgramRegister  (VB *sim, int index);
 | 
					VBAPI int32_t       vbGetProgramRegister  (VB *sim, int index);
 | 
				
			||||||
| 
						 | 
					@ -123,6 +124,7 @@ VBAPI vbOnException vbSetExceptionCallback(VB *sim, vbOnException callback);
 | 
				
			||||||
VBAPI vbOnExecute   vbSetExecuteCallback  (VB *sim, vbOnExecute callback);
 | 
					VBAPI vbOnExecute   vbSetExecuteCallback  (VB *sim, vbOnExecute callback);
 | 
				
			||||||
VBAPI vbOnFetch     vbSetFetchCallback    (VB *sim, vbOnFetch callback);
 | 
					VBAPI vbOnFetch     vbSetFetchCallback    (VB *sim, vbOnFetch callback);
 | 
				
			||||||
VBAPI vbOnFrame     vbSetFrameCallback    (VB *sim, vbOnFrame callback);
 | 
					VBAPI vbOnFrame     vbSetFrameCallback    (VB *sim, vbOnFrame callback);
 | 
				
			||||||
 | 
					VBAPI uint16_t      vbSetKeys             (VB *sim, uint16_t keys);
 | 
				
			||||||
VBAPI uint32_t      vbSetProgramCounter   (VB *sim, uint32_t value);
 | 
					VBAPI uint32_t      vbSetProgramCounter   (VB *sim, uint32_t value);
 | 
				
			||||||
VBAPI int32_t       vbSetProgramRegister  (VB *sim, int index, int32_t value);
 | 
					VBAPI int32_t       vbSetProgramRegister  (VB *sim, int index, int32_t value);
 | 
				
			||||||
VBAPI vbOnRead      vbSetReadCallback     (VB *sim, vbOnRead callback);
 | 
					VBAPI vbOnRead      vbSetReadCallback     (VB *sim, vbOnRead callback);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue