Implement communication port
This commit is contained in:
		
							parent
							
								
									da001e02cd
								
							
						
					
					
						commit
						e828d99da1
					
				
							
								
								
									
										33
									
								
								core/bus.c
								
								
								
								
							
							
						
						
									
										33
									
								
								core/bus.c
								
								
								
								
							| 
						 | 
					@ -95,17 +95,17 @@ static int32_t busReadMisc(VB *sim, uint8_t address, int type) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Access by register */
 | 
					    /* Access by register */
 | 
				
			||||||
    switch (address >> 2 & 15) {
 | 
					    switch (address >> 2 & 15) {
 | 
				
			||||||
        case 0x00>>2: break; /* CCR */
 | 
					        case 0x00>>2: return extReadCCR(sim);                      /* CCR */
 | 
				
			||||||
        case 0x04>>2: break; /* CCSR */
 | 
					        case 0x04>>2: return extReadCCSR(sim);                     /* CCSR */
 | 
				
			||||||
        case 0x08>>2: break; /* CDTR */
 | 
					        case 0x08>>2: return sim->ext.cdtr;                        /* CDTR */
 | 
				
			||||||
        case 0x0C>>2: break; /* CDRR */
 | 
					        case 0x0C>>2: return sim->ext.cdrr;                        /* CDRR */
 | 
				
			||||||
        case 0x10>>2: return sim->pad.sdlr;                /* SDLR */
 | 
					        case 0x10>>2: return sim->pad.sdlr;                        /* SDLR */
 | 
				
			||||||
        case 0x14>>2: return sim->pad.sdhr;                /* SDHR */
 | 
					        case 0x14>>2: return sim->pad.sdhr;                        /* SDHR */
 | 
				
			||||||
        case 0x18>>2: return sim->tmr.counter      & 0xFF; /* TLR */
 | 
					        case 0x18>>2: return sim->tmr.counter      & 0xFF;         /* TLR */
 | 
				
			||||||
        case 0x1C>>2: return sim->tmr.counter >> 8 & 0xFF; /* THR */
 | 
					        case 0x1C>>2: return sim->tmr.counter >> 8 & 0xFF;         /* THR */
 | 
				
			||||||
        case 0x20>>2: return tmrReadControl(sim);          /* TCR */
 | 
					        case 0x20>>2: return tmrReadControl(sim);                  /* TCR */
 | 
				
			||||||
        case 0x24>>2: return sim->wcr;                     /* WCR */
 | 
					        case 0x28>>2: return padReadControl(sim);                  /* SCR */
 | 
				
			||||||
        case 0x28>>2: return padReadControl(sim);          /* SCR */
 | 
					        case 0x24>>2: return sim->wcr.exp1w << 1 | sim->wcr.rom1w; /* WCR */
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Unmapped */
 | 
					    /* Unmapped */
 | 
				
			||||||
| 
						 | 
					@ -123,15 +123,16 @@ static void busWriteMisc(VB *sim, uint8_t address, int type, int32_t value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Access by register */
 | 
					    /* Access by register */
 | 
				
			||||||
    switch (address >> 2 & 15) {
 | 
					    switch (address >> 2 & 15) {
 | 
				
			||||||
        case 0x00>>2: break; /* CCR */
 | 
					        case 0x00>>2: extWriteCCR (sim, value);    break; /* CCR */
 | 
				
			||||||
        case 0x04>>2: break; /* CCSR */
 | 
					        case 0x04>>2: extWriteCCSR(sim, value);    break; /* CCSR */
 | 
				
			||||||
        case 0x08>>2: break; /* CDTR */
 | 
					        case 0x08>>2: sim->ext.cdtr = value;       break; /* CDTR */
 | 
				
			||||||
        case 0x0C>>2: break; /* CDRR */
 | 
					 | 
				
			||||||
        case 0x18>>2: tmrWriteLow    (sim, value); break; /* TLR */
 | 
					        case 0x18>>2: tmrWriteLow    (sim, value); break; /* TLR */
 | 
				
			||||||
        case 0x1C>>2: tmrWriteHigh   (sim, value); break; /* THR */
 | 
					        case 0x1C>>2: tmrWriteHigh   (sim, value); break; /* THR */
 | 
				
			||||||
        case 0x20>>2: tmrWriteControl(sim, value); break; /* TCR */
 | 
					        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 */
 | 
					        case 0x28>>2: padWriteControl(sim, value); break; /* SCR */
 | 
				
			||||||
 | 
					        case 0x24>>2:                                     /* WCR */
 | 
				
			||||||
 | 
					            sim->wcr.exp1w = value >> 1 & 1;
 | 
				
			||||||
 | 
					            sim->wcr.rom1w = value      & 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,162 @@
 | 
				
			||||||
 | 
					/* This file is included into vb.c and cannot be compiled on its own. */
 | 
				
			||||||
 | 
					#ifdef VBAPI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************** Callback Handlers *****************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Prepare to handle an exception */
 | 
				
			||||||
 | 
					#ifndef VB_DIRECT_LINK
 | 
				
			||||||
 | 
					    #define VB_ON_LINK sim1->onLink
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    extern int VB_DIRECT_LINK(VB *, VB *, uint8_t *, uint8_t *);
 | 
				
			||||||
 | 
					    #define VB_ON_LINK VB_DIRECT_LINK
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					static int extOnLink(VB *sim1, VB *sim2, uint8_t *value1, uint8_t *value2) {
 | 
				
			||||||
 | 
					    return sim1->onLink != NULL && VB_ON_LINK(sim1, sim2, value1, value2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#undef VB_ON_LINK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***************************** Library Functions *****************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Process component */
 | 
				
			||||||
 | 
					static int extEmulate(VB *sim, uint32_t clocks) {
 | 
				
			||||||
 | 
					    VB     *peer;      /* Communication peer */
 | 
				
			||||||
 | 
					    VB     *sims[2];   /* Communication peers */
 | 
				
			||||||
 | 
					    uint8_t values[2]; /* Transmission values */
 | 
				
			||||||
 | 
					    int     x;         /* Iterator */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Communication will not occur */
 | 
				
			||||||
 | 
					    if (!sim->ext.c_stat || sim->ext.c_clk_sel)
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Communication completes after time to process */
 | 
				
			||||||
 | 
					    if (sim->ext.clocks > clocks) {
 | 
				
			||||||
 | 
					        sim->ext.clocks -= clocks;
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Exchange transmission data */
 | 
				
			||||||
 | 
					    sims  [0] = sim;
 | 
				
			||||||
 | 
					    sims  [1] = sim->peer;
 | 
				
			||||||
 | 
					    values[0] = sim->ext.cdtr;
 | 
				
			||||||
 | 
					    values[1] = sim->peer == NULL ? 0 : sim->peer->ext.cdtr;
 | 
				
			||||||
 | 
					    if (extOnLink(sim, sim->peer, &values[0], &values[1]))
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Update state */
 | 
				
			||||||
 | 
					    for (x = 0; x < 2; x++) {
 | 
				
			||||||
 | 
					        sim  = sims[x];
 | 
				
			||||||
 | 
					        peer = sims[x ^ 1];
 | 
				
			||||||
 | 
					        if (sim  == NULL)
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        if (peer == NULL)
 | 
				
			||||||
 | 
					            peer = sim;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Registers */
 | 
				
			||||||
 | 
					        sim->ext.cdrr    = values[x ^ 1];
 | 
				
			||||||
 | 
					        sim->ext.c_irq  |= !sim->ext.c_int_inh;
 | 
				
			||||||
 | 
					        sim->ext.c_stat  = 0;
 | 
				
			||||||
 | 
					        sim->ext.cc_rd   = sim->ext.cc_wr  & peer->ext.cc_wr;
 | 
				
			||||||
 | 
					        sim->ext.cc_smp  = sim->ext.cc_sig & peer->ext.cc_sig & sim->ext.cc_rd;
 | 
				
			||||||
 | 
					        sim->ext.cc_irq |= !sim->ext.cc_int_inh &&
 | 
				
			||||||
 | 
					            sim->ext.cc_smp == sim->ext.cc_int_lev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Interrupt */
 | 
				
			||||||
 | 
					        if (sim->ext.c_irq | sim->ext.cc_irq)
 | 
				
			||||||
 | 
					            sim->cpu.irq |= 0x0008;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Read a value from CCR */
 | 
				
			||||||
 | 
					static int32_t extReadCCR(VB *sim) {
 | 
				
			||||||
 | 
					    return 0x6D |
 | 
				
			||||||
 | 
					        sim->ext.c_int_inh << 7 |
 | 
				
			||||||
 | 
					        sim->ext.c_clk_sel << 4 |
 | 
				
			||||||
 | 
					        sim->ext.c_stat    << 1
 | 
				
			||||||
 | 
					    ;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Read a value from CCSR */
 | 
				
			||||||
 | 
					static int32_t extReadCCSR(VB *sim) {
 | 
				
			||||||
 | 
					    return 0x60 |
 | 
				
			||||||
 | 
					        sim->ext.cc_int_inh << 7 |
 | 
				
			||||||
 | 
					        sim->ext.cc_int_lev << 4 |
 | 
				
			||||||
 | 
					        sim->ext.cc_sig     << 3 |
 | 
				
			||||||
 | 
					        sim->ext.cc_smp     << 2 |
 | 
				
			||||||
 | 
					        sim->ext.cc_wr      << 1 |
 | 
				
			||||||
 | 
					        sim->ext.cc_rd
 | 
				
			||||||
 | 
					    ;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Simulate a hardware reset */
 | 
				
			||||||
 | 
					static void extReset(VB *sim) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Normal */
 | 
				
			||||||
 | 
					    sim->ext.c_clk_sel  = 0;
 | 
				
			||||||
 | 
					    sim->ext.c_int_inh  = 0;
 | 
				
			||||||
 | 
					    sim->ext.c_stat     = 0;
 | 
				
			||||||
 | 
					    sim->ext.cc_int_inh = 1;
 | 
				
			||||||
 | 
					    sim->ext.cc_int_lev = 1;
 | 
				
			||||||
 | 
					    sim->ext.cc_sig     = 1;
 | 
				
			||||||
 | 
					    sim->ext.cc_wr      = 1;
 | 
				
			||||||
 | 
					    sim->ext.cdrr       = 0x00;
 | 
				
			||||||
 | 
					    sim->ext.cdtr       = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Other */
 | 
				
			||||||
 | 
					    sim->ext.c_irq  = 0;
 | 
				
			||||||
 | 
					    sim->ext.cc_irq = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Determine how many clocks are guaranteed to process */
 | 
				
			||||||
 | 
					static uint32_t extUntil(VB *sim, uint32_t clocks) {
 | 
				
			||||||
 | 
					    return !sim->ext.c_stat || sim->ext.c_clk_sel || clocks < sim->ext.clocks ?
 | 
				
			||||||
 | 
					        clocks : sim->ext.clocks;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Write a value to CCR */
 | 
				
			||||||
 | 
					static void extWriteCCR(VB *sim, uint8_t value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Configure state */
 | 
				
			||||||
 | 
					    sim->ext.c_int_inh = value >> 7 & 1;
 | 
				
			||||||
 | 
					    sim->ext.c_clk_sel = value >> 4 & 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Acknowledge interrupt */
 | 
				
			||||||
 | 
					    if (sim->ext.c_int_inh) {
 | 
				
			||||||
 | 
					        sim->ext.c_irq = 0;
 | 
				
			||||||
 | 
					        if (!sim->ext.cc_irq)
 | 
				
			||||||
 | 
					            sim->cpu.irq &= ~0x0008;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Do not initiate a communication */
 | 
				
			||||||
 | 
					    if (sim->ext.c_stat || (value & 0x04) == 0) /* C-Start */
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Initiate a communication */
 | 
				
			||||||
 | 
					    sim->ext.c_stat = 1;
 | 
				
			||||||
 | 
					    sim->ext.clocks = 3200; /* 160us */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Write a value to CCSR */
 | 
				
			||||||
 | 
					static void extWriteCCSR(VB *sim, uint8_t value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Configure state */
 | 
				
			||||||
 | 
					    sim->ext.cc_int_inh = value >> 7 & 1;
 | 
				
			||||||
 | 
					    sim->ext.cc_int_lev = value >> 4 & 1;
 | 
				
			||||||
 | 
					    sim->ext.cc_sig     = value >> 3 & 1;
 | 
				
			||||||
 | 
					    sim->ext.cc_wr      = value >> 1 & 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Acknowledge interrupt */
 | 
				
			||||||
 | 
					    if (!sim->ext.cc_int_inh)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    sim->ext.cc_irq = 0;
 | 
				
			||||||
 | 
					    if (!sim->ext.c_irq)
 | 
				
			||||||
 | 
					        sim->cpu.irq &= ~0x0008;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* VBAPI */
 | 
				
			||||||
| 
						 | 
					@ -9,12 +9,12 @@
 | 
				
			||||||
static void padEmulate(VB *sim, uint32_t clocks) {
 | 
					static void padEmulate(VB *sim, uint32_t clocks) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* No hardware read in progress */
 | 
					    /* No hardware read in progress */
 | 
				
			||||||
    if (sim->pad.si_stat == 0)
 | 
					    if (!sim->pad.si_stat)
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Hardware read completes after time to process */
 | 
					    /* Hardware read completes after time to process */
 | 
				
			||||||
    if (sim->pad.si_stat > clocks) {
 | 
					    if (sim->pad.clocks > clocks) {
 | 
				
			||||||
        sim->pad.si_stat -= clocks;
 | 
					        sim->pad.clocks -= clocks;
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,7 +38,7 @@ static int32_t padReadControl(VB *sim) {
 | 
				
			||||||
        sim->pad.k_int_inh << 7 |
 | 
					        sim->pad.k_int_inh << 7 |
 | 
				
			||||||
        sim->pad.para_si   << 5 |
 | 
					        sim->pad.para_si   << 5 |
 | 
				
			||||||
        sim->pad.soft_ck   << 4 |
 | 
					        sim->pad.soft_ck   << 4 |
 | 
				
			||||||
        !!sim->pad.si_stat << 1 |
 | 
					        sim->pad.si_stat   << 1 |
 | 
				
			||||||
        sim->pad.s_abt_dis
 | 
					        sim->pad.s_abt_dis
 | 
				
			||||||
    ;
 | 
					    ;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -78,7 +78,8 @@ static void padWriteControl(VB *sim, uint8_t value) {
 | 
				
			||||||
        sim->pad.si_stat == 0 && /* No hardware read underway */
 | 
					        sim->pad.si_stat == 0 && /* No hardware read underway */
 | 
				
			||||||
        !sim->pad.s_abt_dis      /* Hardware reads enabled */
 | 
					        !sim->pad.s_abt_dis      /* Hardware reads enabled */
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        sim->pad.si_stat = 10240; /* 512us */
 | 
					        sim->pad.clocks  = 10240; /* 512us */
 | 
				
			||||||
 | 
					        sim->pad.si_stat = 1;
 | 
				
			||||||
        sim->pad.step    = 0;     /* Abort software read */
 | 
					        sim->pad.step    = 0;     /* Abort software read */
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,7 +87,7 @@ static void padWriteControl(VB *sim, uint8_t value) {
 | 
				
			||||||
    sim->pad.para_si = value >> 5 & 1;
 | 
					    sim->pad.para_si = value >> 5 & 1;
 | 
				
			||||||
    if (
 | 
					    if (
 | 
				
			||||||
        sim->pad.para_si &&
 | 
					        sim->pad.para_si &&
 | 
				
			||||||
        sim->pad.si_stat == 0 /* No hardware read underway */
 | 
					        !sim->pad.si_stat /* No hardware read underway */
 | 
				
			||||||
    ) sim->pad.step = 32;
 | 
					    ) sim->pad.step = 32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Signal a bit for a software read */
 | 
					    /* Signal a bit for a software read */
 | 
				
			||||||
| 
						 | 
					@ -107,8 +108,8 @@ static void padWriteControl(VB *sim, uint8_t value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Determine how many clocks are guaranteed to process */
 | 
					/* Determine how many clocks are guaranteed to process */
 | 
				
			||||||
static uint32_t padUntil(VB *sim, uint32_t clocks) {
 | 
					static uint32_t padUntil(VB *sim, uint32_t clocks) {
 | 
				
			||||||
    return sim->pad.si_stat != 0 && sim->pad.si_stat < clocks ?
 | 
					    return sim->pad.si_stat && sim->pad.clocks < clocks ?
 | 
				
			||||||
        sim->pad.si_stat : clocks;
 | 
					        sim->pad.clocks : clocks;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										73
									
								
								core/vb.c
								
								
								
								
							
							
						
						
									
										73
									
								
								core/vb.c
								
								
								
								
							| 
						 | 
					@ -146,6 +146,28 @@ struct VB {
 | 
				
			||||||
        int      step;      /* Operation sub-task ID */
 | 
					        int      step;      /* Operation sub-task ID */
 | 
				
			||||||
    } cpu;
 | 
					    } cpu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Communication port */
 | 
				
			||||||
 | 
					    struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Register state */
 | 
				
			||||||
 | 
					        uint8_t c_clk_sel;  /* Transmission clock source */
 | 
				
			||||||
 | 
					        uint8_t c_int_inh;  /* Interrupt acknowledge/disable */
 | 
				
			||||||
 | 
					        uint8_t c_stat;     /* Communication is underway */
 | 
				
			||||||
 | 
					        uint8_t cc_int_inh; /* Interrupt acknowledge/disable */
 | 
				
			||||||
 | 
					        uint8_t cc_int_lev; /* Interrupt condition */
 | 
				
			||||||
 | 
					        uint8_t cc_rd;      /* Manual read */
 | 
				
			||||||
 | 
					        uint8_t cc_sig;     /* Automatic write */
 | 
				
			||||||
 | 
					        uint8_t cc_smp;     /* Automatic read */
 | 
				
			||||||
 | 
					        uint8_t cc_wr;      /* Manual write */
 | 
				
			||||||
 | 
					        uint8_t cdrr;       /* Data received */
 | 
				
			||||||
 | 
					        uint8_t cdtr;       /* Data to transmit */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Other state */
 | 
				
			||||||
 | 
					        int8_t   c_irq;  /* COM interrupt request */
 | 
				
			||||||
 | 
					        int8_t   cc_irq; /* COMCNT interrupt request */
 | 
				
			||||||
 | 
					        uint32_t clocks; /* Master clocks to wait */
 | 
				
			||||||
 | 
					    } ext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Game pad */
 | 
					    /* Game pad */
 | 
				
			||||||
    struct {
 | 
					    struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -159,8 +181,9 @@ struct VB {
 | 
				
			||||||
        uint8_t  soft_ck;   /* Controller communication signal */
 | 
					        uint8_t  soft_ck;   /* Controller communication signal */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Other state */
 | 
					        /* Other state */
 | 
				
			||||||
        uint16_t keys; /* Next input bits */
 | 
					        uint32_t clocks; /* Master clocks to wait */
 | 
				
			||||||
        int      step; /* Software read processing phase */
 | 
					        uint16_t keys;   /* Next input bits */
 | 
				
			||||||
 | 
					        int      step;   /* Software read processing phase */
 | 
				
			||||||
    } pad;
 | 
					    } pad;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Timer */
 | 
					    /* Timer */
 | 
				
			||||||
| 
						 | 
					@ -310,6 +333,12 @@ struct VB {
 | 
				
			||||||
        int      sample; /* Output sample index, period 417 */
 | 
					        int      sample; /* Output sample index, period 417 */
 | 
				
			||||||
    } vsu;
 | 
					    } vsu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Wait controller */
 | 
				
			||||||
 | 
					    struct {
 | 
				
			||||||
 | 
					        uint8_t exp1w; /* Cartridge expansion 1-wait */
 | 
				
			||||||
 | 
					        uint8_t rom1w; /* Cartridge ROM 1-wait */
 | 
				
			||||||
 | 
					    } wcr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Pseudo-halt */
 | 
					    /* Pseudo-halt */
 | 
				
			||||||
    struct {
 | 
					    struct {
 | 
				
			||||||
        uint32_t address;   /* Monitor address */
 | 
					        uint32_t address;   /* Monitor address */
 | 
				
			||||||
| 
						 | 
					@ -335,7 +364,6 @@ struct VB {
 | 
				
			||||||
    } ph;
 | 
					    } ph;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* 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 */
 | 
				
			||||||
| 
						 | 
					@ -343,9 +371,11 @@ struct VB {
 | 
				
			||||||
    vbOnExecute   onExecute;   /* CPU instruction execute */
 | 
					    vbOnExecute   onExecute;   /* CPU instruction execute */
 | 
				
			||||||
    vbOnFetch     onFetch;     /* CPU instruction fetch */
 | 
					    vbOnFetch     onFetch;     /* CPU instruction fetch */
 | 
				
			||||||
    vbOnFrame     onFrame;     /* VIP frame ready */
 | 
					    vbOnFrame     onFrame;     /* VIP frame ready */
 | 
				
			||||||
 | 
					    vbOnLink      onLink;      /* Communication transfer */
 | 
				
			||||||
    vbOnRead      onRead;      /* CPU instruction read */
 | 
					    vbOnRead      onRead;      /* CPU instruction read */
 | 
				
			||||||
    vbOnSamples   onSamples;   /* VSU samples full */
 | 
					    vbOnSamples   onSamples;   /* VSU samples full */
 | 
				
			||||||
    vbOnWrite     onWrite;     /* CPU instruction write */
 | 
					    vbOnWrite     onWrite;     /* CPU instruction write */
 | 
				
			||||||
 | 
					    VB           *peer;        /* Communication peer */
 | 
				
			||||||
    void         *tag;         /* User data */
 | 
					    void         *tag;         /* User data */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -368,6 +398,7 @@ static int32_t SignExtend(int32_t value, int32_t bits) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/******************************** Sub-Modules ********************************/
 | 
					/******************************** Sub-Modules ********************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "ext.c"
 | 
				
			||||||
#include "game-pad.c"
 | 
					#include "game-pad.c"
 | 
				
			||||||
#include "timer.c"
 | 
					#include "timer.c"
 | 
				
			||||||
#include "bus.c"
 | 
					#include "bus.c"
 | 
				
			||||||
| 
						 | 
					@ -391,7 +422,8 @@ static int sysEmulate(VB *sim, uint32_t clocks) {
 | 
				
			||||||
    ;
 | 
					    ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Process all components */
 | 
					    /* Process all components */
 | 
				
			||||||
    if (!never) ret  = cpuEmulate(sim, clocks);
 | 
					    if (!never){ret  = cpuEmulate(sim, clocks);}
 | 
				
			||||||
 | 
					                ret |= extEmulate(sim, clocks);
 | 
				
			||||||
                       padEmulate(sim, clocks);
 | 
					                       padEmulate(sim, clocks);
 | 
				
			||||||
                       tmrEmulate(sim, clocks);
 | 
					                       tmrEmulate(sim, clocks);
 | 
				
			||||||
                       vsuEmulate(sim, clocks);
 | 
					                       vsuEmulate(sim, clocks);
 | 
				
			||||||
| 
						 | 
					@ -403,6 +435,7 @@ static int sysEmulate(VB *sim, uint32_t clocks) {
 | 
				
			||||||
/* Determine how many clocks are guaranteed to process */
 | 
					/* Determine how many clocks are guaranteed to process */
 | 
				
			||||||
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 = extUntil(sim, clocks);
 | 
				
			||||||
    clocks = padUntil(sim, clocks);
 | 
					    clocks = padUntil(sim, clocks);
 | 
				
			||||||
    clocks = tmrUntil(sim, clocks);
 | 
					    clocks = tmrUntil(sim, clocks);
 | 
				
			||||||
    clocks = vipUntil(sim, clocks);
 | 
					    clocks = vipUntil(sim, clocks);
 | 
				
			||||||
| 
						 | 
					@ -487,6 +520,11 @@ VBAPI uint16_t vbGetKeys(VB *sim) {
 | 
				
			||||||
    return sim->pad.keys;
 | 
					    return sim->pad.keys;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Retrieve the current link callback handler */
 | 
				
			||||||
 | 
					VBAPI vbOnLink vbGetLinkCallback(VB *sim) {
 | 
				
			||||||
 | 
					    return sim->onLink;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Retrieve a core option value */
 | 
					/* Retrieve a core option value */
 | 
				
			||||||
VBAPI int vbGetOption(VB *sim, int key) {
 | 
					VBAPI int vbGetOption(VB *sim, int key) {
 | 
				
			||||||
    switch (key) {
 | 
					    switch (key) {
 | 
				
			||||||
| 
						 | 
					@ -495,6 +533,11 @@ VBAPI int vbGetOption(VB *sim, int key) {
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Retrieve the communication peer */
 | 
				
			||||||
 | 
					VBAPI VB* vbGetPeer(VB *sim) {
 | 
				
			||||||
 | 
					    return sim->peer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* 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) {
 | 
				
			||||||
| 
						 | 
					@ -594,9 +637,11 @@ VBAPI VB* vbInit(VB *sim) {
 | 
				
			||||||
    sim->onExecute       = NULL;
 | 
					    sim->onExecute       = NULL;
 | 
				
			||||||
    sim->onFetch         = NULL;
 | 
					    sim->onFetch         = NULL;
 | 
				
			||||||
    sim->onFrame         = NULL;
 | 
					    sim->onFrame         = NULL;
 | 
				
			||||||
 | 
					    sim->onLink          = NULL;
 | 
				
			||||||
    sim->onRead          = NULL;
 | 
					    sim->onRead          = NULL;
 | 
				
			||||||
    sim->onSamples       = NULL;
 | 
					    sim->onSamples       = NULL;
 | 
				
			||||||
    sim->onWrite         = NULL;
 | 
					    sim->onWrite         = NULL;
 | 
				
			||||||
 | 
					    sim->peer            = NULL;
 | 
				
			||||||
    sim->ph.enabled      = 0;
 | 
					    sim->ph.enabled      = 0;
 | 
				
			||||||
    vbReset(sim);
 | 
					    vbReset(sim);
 | 
				
			||||||
    return sim;
 | 
					    return sim;
 | 
				
			||||||
| 
						 | 
					@ -616,7 +661,8 @@ VBAPI VB* vbReset(VB *sim) {
 | 
				
			||||||
    int x; /* Iterator */
 | 
					    int x; /* Iterator */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Wait controller */
 | 
					    /* Wait controller */
 | 
				
			||||||
    sim->wcr = 0x00;
 | 
					    sim->wcr.exp1w = 0;
 | 
				
			||||||
 | 
					    sim->wcr.rom1w = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* 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++)
 | 
				
			||||||
| 
						 | 
					@ -624,6 +670,7 @@ VBAPI VB* vbReset(VB *sim) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Components */
 | 
					    /* Components */
 | 
				
			||||||
    cpuReset(sim);
 | 
					    cpuReset(sim);
 | 
				
			||||||
 | 
					    extReset(sim);
 | 
				
			||||||
    padReset(sim);
 | 
					    padReset(sim);
 | 
				
			||||||
    tmrReset(sim);
 | 
					    tmrReset(sim);
 | 
				
			||||||
    vipReset(sim);
 | 
					    vipReset(sim);
 | 
				
			||||||
| 
						 | 
					@ -689,6 +736,13 @@ VBAPI uint16_t vbSetKeys(VB *sim, uint16_t keys) {
 | 
				
			||||||
    return sim->pad.keys = keys;
 | 
					    return sim->pad.keys = keys;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Specify a new link callback handler */
 | 
				
			||||||
 | 
					VBAPI vbOnLink vbSetLinkCallback(VB *sim, vbOnLink callback) {
 | 
				
			||||||
 | 
					    vbOnLink prev = sim->onLink;
 | 
				
			||||||
 | 
					    sim->onLink = callback;
 | 
				
			||||||
 | 
					    return prev;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Specify a new core option value */
 | 
					/* Specify a new core option value */
 | 
				
			||||||
VBAPI int vbSetOption(VB *sim, int key, int value) {
 | 
					VBAPI int vbSetOption(VB *sim, int key, int value) {
 | 
				
			||||||
    switch (key) {
 | 
					    switch (key) {
 | 
				
			||||||
| 
						 | 
					@ -706,6 +760,15 @@ VBAPI int vbSetOption(VB *sim, int key, int value) {
 | 
				
			||||||
    return value;
 | 
					    return value;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Specify a new communication peer */
 | 
				
			||||||
 | 
					VBAPI VB* vbSetPeer(VB *sim, VB *peer) {
 | 
				
			||||||
 | 
					    VB *prev  = sim->peer;
 | 
				
			||||||
 | 
					    sim->peer = peer;
 | 
				
			||||||
 | 
					    if (peer != prev && prev != NULL)
 | 
				
			||||||
 | 
					        prev->peer = NULL;
 | 
				
			||||||
 | 
					    return prev;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* 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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,7 @@ extern "C" {
 | 
				
			||||||
  VB_DIRECT_EXECUTE
 | 
					  VB_DIRECT_EXECUTE
 | 
				
			||||||
  VB_DIRECT_FETCH
 | 
					  VB_DIRECT_FETCH
 | 
				
			||||||
  VB_DIRECT_FRAME
 | 
					  VB_DIRECT_FRAME
 | 
				
			||||||
 | 
					  VB_DIRECT_LINK
 | 
				
			||||||
  VB_DIRECT_READ
 | 
					  VB_DIRECT_READ
 | 
				
			||||||
  VB_DIRECT_SAMPLES
 | 
					  VB_DIRECT_SAMPLES
 | 
				
			||||||
  VB_DIRECT_WRITE
 | 
					  VB_DIRECT_WRITE
 | 
				
			||||||
| 
						 | 
					@ -94,6 +95,7 @@ typedef int  (*vbOnException)(VB *sim, uint16_t *cause);
 | 
				
			||||||
typedef int  (*vbOnExecute  )(VB *sim, uint32_t address, const uint16_t *code, int length);
 | 
					typedef int  (*vbOnExecute  )(VB *sim, uint32_t address, const uint16_t *code, int length);
 | 
				
			||||||
typedef int  (*vbOnFetch    )(VB *sim, int fetch, uint32_t address, int32_t *value, uint32_t *cycles);
 | 
					typedef int  (*vbOnFetch    )(VB *sim, int fetch, uint32_t address, int32_t *value, uint32_t *cycles);
 | 
				
			||||||
typedef int  (*vbOnFrame    )(VB *sim);
 | 
					typedef int  (*vbOnFrame    )(VB *sim);
 | 
				
			||||||
 | 
					typedef int  (*vbOnLink     )(VB *sim1, VB *sim2, uint8_t *value1, uint8_t *value2);
 | 
				
			||||||
typedef int  (*vbOnRead     )(VB *sim, uint32_t address, int type, int32_t *value, uint32_t *cycles);
 | 
					typedef int  (*vbOnRead     )(VB *sim, uint32_t address, int type, int32_t *value, uint32_t *cycles);
 | 
				
			||||||
typedef void (*vbOnSamples  )(VB *sim, int16_t *buffer, uint32_t capacity);
 | 
					typedef void (*vbOnSamples  )(VB *sim, int16_t *buffer, uint32_t capacity);
 | 
				
			||||||
typedef int  (*vbOnWrite    )(VB *sim, uint32_t address, int type, int32_t *value, uint32_t *cycles, int *cancel);
 | 
					typedef int  (*vbOnWrite    )(VB *sim, uint32_t address, int type, int32_t *value, uint32_t *cycles, int *cancel);
 | 
				
			||||||
| 
						 | 
					@ -113,7 +115,9 @@ 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 uint16_t      vbGetKeys             (VB *sim);
 | 
				
			||||||
 | 
					VBAPI vbOnLink      vbGetLinkCallback     (VB *sim);
 | 
				
			||||||
VBAPI int           vbGetOption           (VB *sim, int key);
 | 
					VBAPI int           vbGetOption           (VB *sim, int key);
 | 
				
			||||||
 | 
					VBAPI VB*           vbGetPeer             (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);
 | 
				
			||||||
| 
						 | 
					@ -132,6 +136,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 vbOnLink      vbSetLinkCallback     (VB *sim, vbOnLink callback);
 | 
				
			||||||
VBAPI uint16_t      vbSetKeys             (VB *sim, uint16_t keys);
 | 
					VBAPI uint16_t      vbSetKeys             (VB *sim, uint16_t keys);
 | 
				
			||||||
VBAPI int           vbSetOption           (VB *sim, int key, int value);
 | 
					VBAPI int           vbSetOption           (VB *sim, int key, int value);
 | 
				
			||||||
VBAPI uint32_t      vbSetProgramCounter   (VB *sim, uint32_t value);
 | 
					VBAPI uint32_t      vbSetProgramCounter   (VB *sim, uint32_t value);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue