Implement VIP, fix interrupts
This commit is contained in:
		
							parent
							
								
									3c2c9bb938
								
							
						
					
					
						commit
						37b9a94338
					
				| 
						 | 
					@ -376,7 +376,7 @@ static uint32_t cpuSetSystemRegister(VB*sim,
 | 
				
			||||||
        case VB_FEPSW: return sim->cpu.fepsw = value & 0x000FF3FF;
 | 
					        case VB_FEPSW: return sim->cpu.fepsw = value & 0x000FF3FF;
 | 
				
			||||||
        case VB_PIR  : return 0x00005346;
 | 
					        case VB_PIR  : return 0x00005346;
 | 
				
			||||||
        case VB_PSW  :
 | 
					        case VB_PSW  :
 | 
				
			||||||
            sim->cpu.psw.i   = value >> 16 & 0xF;
 | 
					            sim->cpu.psw.i   = value >> 16 & 15;
 | 
				
			||||||
            sim->cpu.psw.np  = value >> 15 & 1;
 | 
					            sim->cpu.psw.np  = value >> 15 & 1;
 | 
				
			||||||
            sim->cpu.psw.ep  = value >> 14 & 1;
 | 
					            sim->cpu.psw.ep  = value >> 14 & 1;
 | 
				
			||||||
            sim->cpu.psw.ae  = value >> 13 & 1;
 | 
					            sim->cpu.psw.ae  = value >> 13 & 1;
 | 
				
			||||||
| 
						 | 
					@ -414,7 +414,7 @@ static int cpuIRQ(VB *sim) {
 | 
				
			||||||
    if (sim->cpu.psw.id | sim->cpu.psw.ep | sim->cpu.psw.np)
 | 
					    if (sim->cpu.psw.id | sim->cpu.psw.ep | sim->cpu.psw.np)
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    level = IRQ_LEVELS[sim->cpu.irq];
 | 
					    level = IRQ_LEVELS[sim->cpu.irq];
 | 
				
			||||||
    if (level == -1 || level > sim->cpu.psw.i)
 | 
					    if (level < sim->cpu.psw.i)
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    cpuThrow(sim, 0xFE00 | level << 4);
 | 
					    cpuThrow(sim, 0xFE00 | level << 4);
 | 
				
			||||||
    return 1;
 | 
					    return 1;
 | 
				
			||||||
| 
						 | 
					@ -476,6 +476,9 @@ static int cpuException(VB *sim) {
 | 
				
			||||||
    /* Regular exception */
 | 
					    /* Regular exception */
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* All exceptions */
 | 
				
			||||||
 | 
					        sim->cpu.eipsw = cpuGetSystemRegister(sim, VB_PSW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Interrupts only */
 | 
					        /* Interrupts only */
 | 
				
			||||||
        if ((cause & 0xFF00) == 0xFE00) {
 | 
					        if ((cause & 0xFF00) == 0xFE00) {
 | 
				
			||||||
            sim->cpu.psw.i = (cause >> 4 & 7) + 1;
 | 
					            sim->cpu.psw.i = (cause >> 4 & 7) + 1;
 | 
				
			||||||
| 
						 | 
					@ -487,7 +490,6 @@ static int cpuException(VB *sim) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* All exceptions */
 | 
					        /* All exceptions */
 | 
				
			||||||
        sim->cpu.ecr.eicc = cause;
 | 
					        sim->cpu.ecr.eicc = cause;
 | 
				
			||||||
        sim->cpu.eipsw    = cpuGetSystemRegister(sim, VB_PSW);
 | 
					 | 
				
			||||||
        sim->cpu.eipc     = sim->cpu.pc;
 | 
					        sim->cpu.eipc     = sim->cpu.pc;
 | 
				
			||||||
        sim->cpu.psw.ep   = 1;
 | 
					        sim->cpu.psw.ep   = 1;
 | 
				
			||||||
        sim->cpu.nextPC   = 0xFFFF0000 |
 | 
					        sim->cpu.nextPC   = 0xFFFF0000 |
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										14
									
								
								core/vb.c
								
								
								
								
							
							
						
						
									
										14
									
								
								core/vb.c
								
								
								
								
							| 
						 | 
					@ -8,6 +8,9 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*********************************** Types ***********************************/
 | 
					/*********************************** Types ***********************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Output image */
 | 
				
			||||||
 | 
					typedef uint8_t Pixels[2][384*224];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Simulation state */
 | 
					/* Simulation state */
 | 
				
			||||||
struct VB {
 | 
					struct VB {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -126,6 +129,7 @@ struct VB {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Pixel processor */
 | 
					        /* Pixel processor */
 | 
				
			||||||
        struct {
 | 
					        struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* Hardware state */
 | 
					            /* Hardware state */
 | 
				
			||||||
            uint8_t  f0bsy;    /* Drawing into frame buffer 0 */
 | 
					            uint8_t  f0bsy;    /* Drawing into frame buffer 0 */
 | 
				
			||||||
            uint8_t  f1bsy;    /* Drawing into frame buffer 1 */
 | 
					            uint8_t  f1bsy;    /* Drawing into frame buffer 1 */
 | 
				
			||||||
| 
						 | 
					@ -137,7 +141,9 @@ struct VB {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* Simulation state */
 | 
					            /* Simulation state */
 | 
				
			||||||
            uint32_t clocks;   /* Master clocks to wait */
 | 
					            uint32_t clocks;   /* Master clocks to wait */
 | 
				
			||||||
 | 
					            int      column;   /* Current horizontal output position */
 | 
				
			||||||
            int      frame;    /* FRMCYC counter */
 | 
					            int      frame;    /* FRMCYC counter */
 | 
				
			||||||
 | 
					            int32_t  halfword; /* Current output halfword offset */
 | 
				
			||||||
            int      step;     /* Processing phase */
 | 
					            int      step;     /* Processing phase */
 | 
				
			||||||
            uint32_t until;    /* Clocks until interrupt condition */
 | 
					            uint32_t until;    /* Clocks until interrupt condition */
 | 
				
			||||||
        } xp;
 | 
					        } xp;
 | 
				
			||||||
| 
						 | 
					@ -152,8 +158,10 @@ struct VB {
 | 
				
			||||||
        uint8_t  jplt[4][4]; /* Object palettes */
 | 
					        uint8_t  jplt[4][4]; /* Object palettes */
 | 
				
			||||||
        uint16_t spt[4];     /* Object control */
 | 
					        uint16_t spt[4];     /* Object control */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Output frame buffers [buffer index][0=left, 1=right][pixel index] */
 | 
					        /* Rendering shadow memory */
 | 
				
			||||||
        uint8_t frames[2][2][384*224];
 | 
					        uint16_t halfwords[384*28]; /* Output timing by 1x8 halfword */
 | 
				
			||||||
 | 
					        Pixels   output[2];         /* Output images, row-major */
 | 
				
			||||||
 | 
					        Pixels   shadow;            /* Drawing shadow image, column-major */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Other state */
 | 
					        /* Other state */
 | 
				
			||||||
        uint8_t ram[0x40000]; /* Video memory */
 | 
					        uint8_t ram[0x40000]; /* Video memory */
 | 
				
			||||||
| 
						 | 
					@ -319,7 +327,7 @@ VBAPI void vbGetPixels(VB *sim, void *left, int leftStrideX, int leftStrideY,
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Transfer pixels to the destination */
 | 
					        /* Transfer pixels to the destination */
 | 
				
			||||||
        src = sim->vip.frames[sim->vip.dp.buffer][i];
 | 
					        src = sim->vip.output[sim->vip.dp.buffer ^ 1][i];
 | 
				
			||||||
        for (y = 0; y < 224; y++, dest += yStride)
 | 
					        for (y = 0; y < 224; y++, dest += yStride)
 | 
				
			||||||
        for (x = offset = 0; x < 384; x++, offset += xStride)
 | 
					        for (x = offset = 0; x < 384; x++, offset += xStride)
 | 
				
			||||||
            dest[offset] = *src++;
 | 
					            dest[offset] = *src++;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										523
									
								
								core/vip.c
								
								
								
								
							
							
						
						
									
										523
									
								
								core/vip.c
								
								
								
								
							| 
						 | 
					@ -8,10 +8,47 @@
 | 
				
			||||||
/* Compute how many clocks are in some number of milliseconds */
 | 
					/* Compute how many clocks are in some number of milliseconds */
 | 
				
			||||||
#define vipClocksMs(x) x * 20000
 | 
					#define vipClocksMs(x) x * 20000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Read a world line parameter value */
 | 
				
			||||||
 | 
					#define vipParam(x) busReadBuffer(&sim->vip.ram[x], VB_U16)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******************************** Lookup Data ********************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* BG map arrangement by world background dimensions */
 | 
				
			||||||
 | 
					static const uint8_t BG_TEMPLATES[][64] = {
 | 
				
			||||||
 | 
					    { 0 },                                              /* 1x1 */
 | 
				
			||||||
 | 
					    { 0, 1 },                                           /* 1x2 */
 | 
				
			||||||
 | 
					    { 0, 1, 2, 3 },                                     /* 1x4 */
 | 
				
			||||||
 | 
					    { 0, 1, 2, 3, 4, 5, 6, 7 },                         /* 1x8 */
 | 
				
			||||||
 | 
					    { 0, 1 },                                           /* 2x1 */
 | 
				
			||||||
 | 
					    { 0, 1, 2, 3 },                                     /* 2x2 */
 | 
				
			||||||
 | 
					    { 0, 1, 2, 3, 4, 5, 6, 7 },                         /* 2x4 */
 | 
				
			||||||
 | 
					    { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7 }, /* 2x8 */
 | 
				
			||||||
 | 
					    { 0, 1, 2, 3 },                                     /* 4x1 */
 | 
				
			||||||
 | 
					    { 0, 1, 2, 3, 4, 5, 6, 7 },                         /* 4x2 */
 | 
				
			||||||
 | 
					    { 0, 1, 0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 6, 7 }, /* 4x4 */
 | 
				
			||||||
 | 
					    { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,   /* 4x8 */
 | 
				
			||||||
 | 
					      4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7 },
 | 
				
			||||||
 | 
					    { 0, 1, 2, 3, 4, 5, 6, 7 },                         /* 8x1 */
 | 
				
			||||||
 | 
					    { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7 }, /* 8x2 */
 | 
				
			||||||
 | 
					    { 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3,   /* 8x4 */
 | 
				
			||||||
 | 
					      4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7 },
 | 
				
			||||||
 | 
					    { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,   /* 8x8 */
 | 
				
			||||||
 | 
					      2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
 | 
				
			||||||
 | 
					      4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
 | 
				
			||||||
 | 
					      6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7 }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/***************************** Module Functions ******************************/
 | 
					/***************************** Module Functions ******************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Retrieve a pointer to character data in host memory */
 | 
				
			||||||
 | 
					static uint8_t* vipCharacter(VB *sim, uint32_t c) {
 | 
				
			||||||
 | 
					    return &sim->vip.ram[0x06000 | (c << 6 & 0x18000) | (c << 4 & 0x01FF0)];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Read a palette */
 | 
					/* Read a palette */
 | 
				
			||||||
static int32_t vipReadPalette(uint8_t *entries) {
 | 
					static int32_t vipReadPalette(uint8_t *entries) {
 | 
				
			||||||
    return entries[3] << 6 | entries[2] << 4 | entries[1] << 2;
 | 
					    return entries[3] << 6 | entries[2] << 4 | entries[1] << 2;
 | 
				
			||||||
| 
						 | 
					@ -36,8 +73,8 @@ static void vipWritePalette(uint8_t *entries, int32_t mask, int32_t value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Read a typed value from an I/O register */
 | 
					/* Read a typed value from an I/O register */
 | 
				
			||||||
static int32_t vipReadIO(VB *sim, uint32_t address, int type) {
 | 
					static int32_t vipReadIO(VB *sim, uint32_t address, int type) {
 | 
				
			||||||
    int32_t mask;  /* Byte access mask */
 | 
					    int32_t mask = 0; /* Byte access mask */
 | 
				
			||||||
    int32_t value; /* Return value */
 | 
					    int32_t value;    /* Return value */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Adjustments by type */
 | 
					    /* Adjustments by type */
 | 
				
			||||||
    switch (type) {
 | 
					    switch (type) {
 | 
				
			||||||
| 
						 | 
					@ -211,7 +248,7 @@ static void vipWriteIO(
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 0x5F804>>1: /* INTCLR */
 | 
					        case 0x5F804>>1: /* INTCLR */
 | 
				
			||||||
            sim->vip.intpnd &= ~value;
 | 
					            sim->vip.intpnd &= ~value;
 | 
				
			||||||
            if (sim->vip.intpnd == 0)
 | 
					            if ((sim->vip.intpnd & sim->vip.intenb) == 0)
 | 
				
			||||||
                sim->cpu.irq &= ~0x0010;
 | 
					                sim->cpu.irq &= ~0x0010;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -223,7 +260,16 @@ static void vipWriteIO(
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if ((mask & 0x00FF) == 0) {
 | 
					            if ((mask & 0x00FF) == 0) {
 | 
				
			||||||
                sim->vip.dp.disp  = value >>  1 & 1;
 | 
					                sim->vip.dp.disp  = value >>  1 & 1;
 | 
				
			||||||
                /* if (value & 1) {} TODO: DPRST */
 | 
					
 | 
				
			||||||
 | 
					                /* DPRST */
 | 
				
			||||||
 | 
					                if (value & 1) {
 | 
				
			||||||
 | 
					                    sim->vip.intenb &= ~0x801F;
 | 
				
			||||||
 | 
					                    sim->vip.intpnd &= ~0x801F;
 | 
				
			||||||
 | 
					                    if ((sim->vip.intpnd & sim->vip.intenb) == 0)
 | 
				
			||||||
 | 
					                        sim->cpu.irq &= ~0x0010;
 | 
				
			||||||
 | 
					                    /* TODO: Research exact operation */
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -256,7 +302,16 @@ static void vipWriteIO(
 | 
				
			||||||
                sim->vip.xp.sbcmp = value >> 8 & 31;
 | 
					                sim->vip.xp.sbcmp = value >> 8 & 31;
 | 
				
			||||||
            if ((mask & 0x00FF) == 0) {
 | 
					            if ((mask & 0x00FF) == 0) {
 | 
				
			||||||
                sim->vip.xp.xpen  = value >> 1 &  1;
 | 
					                sim->vip.xp.xpen  = value >> 1 &  1;
 | 
				
			||||||
                /* if (value & 1) TODO: XPRST */
 | 
					
 | 
				
			||||||
 | 
					                /* XPRST */
 | 
				
			||||||
 | 
					                if (value & 1) {
 | 
				
			||||||
 | 
					                    sim->vip.intenb &= ~0xE000;
 | 
				
			||||||
 | 
					                    sim->vip.intpnd &= ~0xE000;
 | 
				
			||||||
 | 
					                    if ((sim->vip.intpnd & sim->vip.intenb) == 0)
 | 
				
			||||||
 | 
					                        sim->cpu.irq &= ~0x0010;
 | 
				
			||||||
 | 
					                    /* TODO: Research exact operation */
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -350,7 +405,7 @@ static void vipTransferColumn(VB *sim, int32_t eye) {
 | 
				
			||||||
    int      y, z; /* Iterators */
 | 
					    int      y, z; /* Iterators */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Select destination address in host memory */
 | 
					    /* Select destination address in host memory */
 | 
				
			||||||
    dest = &sim->vip.frames
 | 
					    dest = &sim->vip.output
 | 
				
			||||||
        [sim->vip.dp.buffer][eye][sim->vip.dp.column];
 | 
					        [sim->vip.dp.buffer][eye][sim->vip.dp.column];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Output is disabled */
 | 
					    /* Output is disabled */
 | 
				
			||||||
| 
						 | 
					@ -407,23 +462,26 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
 | 
				
			||||||
                vipThrow(sim, 0x0010); /* FRAMESTART */
 | 
					                vipThrow(sim, 0x0010); /* FRAMESTART */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                /* Game frame */
 | 
					                /* Game frame */
 | 
				
			||||||
                if (sim->vip.xp.frame >= sim->vip.frmcyc) {
 | 
					                if (sim->vip.xp.xpen) {
 | 
				
			||||||
                    sim->vip.xp.frame = 0;
 | 
					                    if (sim->vip.xp.frame >= sim->vip.frmcyc) {
 | 
				
			||||||
 | 
					                        sim->vip.xp.frame = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    /* Initiate drawing procedure */
 | 
					                        /* Initiate drawing procedure */
 | 
				
			||||||
                    if (sim->vip.xp.step == 0) {
 | 
					                        if (sim->vip.xp.step == 0) {
 | 
				
			||||||
                        sim->vip.xp.overtime = 0;
 | 
					                            sim->vip.dp.buffer  ^= 1;
 | 
				
			||||||
                        sim->vip.xp.step     = 1;
 | 
					                            sim->vip.xp.overtime = 0;
 | 
				
			||||||
                        vipThrow(sim, 0x0008); /* GAMESTART */
 | 
					                            sim->vip.xp.step     = 1;
 | 
				
			||||||
                    }
 | 
					                            vipThrow(sim, 0x0008); /* GAMESTART */
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    /* Drawing procedure has run into overtime */
 | 
					                        /* Drawing procedure has run into overtime */
 | 
				
			||||||
                    else {
 | 
					                        else {
 | 
				
			||||||
                        sim->vip.xp.overtime = 1;
 | 
					                            sim->vip.xp.overtime = 1;
 | 
				
			||||||
                        vipThrow(sim, 0x8000); /* TIMEERR */
 | 
					                            vipThrow(sim, 0x8000); /* TIMEERR */
 | 
				
			||||||
                    }
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                } else sim->vip.xp.frame++;
 | 
					                    } else sim->vip.xp.frame++;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -518,9 +576,375 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/****************************** Pixel Processor ******************************/
 | 
					/****************************** Pixel Processor ******************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Draw every world into a group of 8 rows of pixels */
 | 
					/* Draw an object group into shadow memory */
 | 
				
			||||||
static void vipDrawWorlds(VB *sim) {
 | 
					static void vipDrawObjects(VB *sim, int group) {
 | 
				
			||||||
    (void) sim;
 | 
					    uint8_t *dest;       /* Pointer to object position in shadow memory */
 | 
				
			||||||
 | 
					    int      fx;         /* Output horizontal position */
 | 
				
			||||||
 | 
					    int      fy;         /* Output vertical position */
 | 
				
			||||||
 | 
					    uint8_t *obj;        /* Pointer to object attributes in host memory */
 | 
				
			||||||
 | 
					    int32_t  ox;         /* Eye horizontal position */
 | 
				
			||||||
 | 
					    int      pixel;      /* Character input pixel */
 | 
				
			||||||
 | 
					    int      start;      /* Index of first object in group */
 | 
				
			||||||
 | 
					    int      stop;       /* Index of last object in group */
 | 
				
			||||||
 | 
					    int      sx;         /* Input horizontal position */
 | 
				
			||||||
 | 
					    int      sy;         /* Input vertical position */
 | 
				
			||||||
 | 
					    int32_t  top;        /* Window boundary */
 | 
				
			||||||
 | 
					    int      i, o, x, y; /* Iterators */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Object attributes */
 | 
				
			||||||
 | 
					    uint32_t attr1;      /* Attribute bits */
 | 
				
			||||||
 | 
					    uint32_t attr2;      /* Attribute bits */
 | 
				
			||||||
 | 
					    int      jhflp;      /* Is flipped horizontally */
 | 
				
			||||||
 | 
					    int32_t  jp;         /* Stereo parallax */
 | 
				
			||||||
 | 
					    int      jvflp;      /* Is flipped vetically */
 | 
				
			||||||
 | 
					    int32_t  jx;         /* Base horizontal position */
 | 
				
			||||||
 | 
					    int32_t  jy;         /* Vertical position */
 | 
				
			||||||
 | 
					    uint8_t *plt;        /* Palette */
 | 
				
			||||||
 | 
					    uint8_t *src;        /* Pointer to character source data in host memory */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Process all objects in the group */
 | 
				
			||||||
 | 
					    start = group == 0 ? 0 : (sim->vip.spt[group - 1] + 1) & 1023;
 | 
				
			||||||
 | 
					    stop  = sim->vip.spt[group];
 | 
				
			||||||
 | 
					    top   = (int32_t) sim->vip.xp.sbcount << 3;
 | 
				
			||||||
 | 
					    for (o = stop;; o = (o - 1) & 1023) {
 | 
				
			||||||
 | 
					        obj = &sim->vip.ram[0x3E000 | o << 3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Validate object is enabled */
 | 
				
			||||||
 | 
					        attr1 = busReadBuffer(obj + 2, VB_U16);
 | 
				
			||||||
 | 
					        if ((attr1 & 0xC000) == 0) /* JLON, JRON */
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Validate Y position */
 | 
				
			||||||
 | 
					        jy = (int8_t) obj[4];
 | 
				
			||||||
 | 
					        if (jy < 7)
 | 
				
			||||||
 | 
					            jy &= 0xFF;
 | 
				
			||||||
 | 
					        if (jy < top - 7 || jy > 223)
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Parse attributes */
 | 
				
			||||||
 | 
					        jx    = SignExtend(busReadBuffer(obj, VB_U16), 10);
 | 
				
			||||||
 | 
					        jp    = SignExtend(attr1, 10);
 | 
				
			||||||
 | 
					        attr2 = busReadBuffer(obj + 6, VB_U16);
 | 
				
			||||||
 | 
					        jhflp = attr2 >> 13 & 1;
 | 
				
			||||||
 | 
					        jvflp = attr2 >> 12 & 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Locate palette and character state in host memory */
 | 
				
			||||||
 | 
					        plt = sim->vip.jplt[attr2 >> 14];
 | 
				
			||||||
 | 
					        src = vipCharacter(sim, attr2); 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Draw the character */
 | 
				
			||||||
 | 
					        for (i = 0; i < 2; i++) {
 | 
				
			||||||
 | 
					            if ((attr1 >> (15 - i) & 1) == 0) /* J*ON */
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            ox   = jx - (i == 0 ? jp : -jp);
 | 
				
			||||||
 | 
					            dest = &sim->vip.shadow[i][ox * 224 + jy];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Draw all columns */
 | 
				
			||||||
 | 
					            for (x = 0; x < 8; x++, dest += 224) {
 | 
				
			||||||
 | 
					                fx = ox + x;
 | 
				
			||||||
 | 
					                if (fx < 0 || fx > 383)
 | 
				
			||||||
 | 
					                    continue;
 | 
				
			||||||
 | 
					                sx = jhflp ? 7 - x : x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Draw all rows */
 | 
				
			||||||
 | 
					                for (y = 0; y < 8; y++) {
 | 
				
			||||||
 | 
					                    fy = jy + y;
 | 
				
			||||||
 | 
					                    if (fy < top || fy > 223)
 | 
				
			||||||
 | 
					                        continue;
 | 
				
			||||||
 | 
					                    sy    = jvflp ? 7 - y : y;
 | 
				
			||||||
 | 
					                    pixel = src[sy << 1 | sx >> 2] >> ((sx & 3) << 1) & 3;
 | 
				
			||||||
 | 
					                    if (pixel != 0)
 | 
				
			||||||
 | 
					                        dest[y] = plt[pixel]; /* TODO: Research clocks */
 | 
				
			||||||
 | 
					                } /* x */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            } /* y */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        } /* i */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* All objects have been drawn */
 | 
				
			||||||
 | 
					        if (o == start)
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Draw a background world into shadow memory */
 | 
				
			||||||
 | 
					static void vipDrawWorld(VB *sim, uint8_t *world, uint16_t attr) {
 | 
				
			||||||
 | 
					    uint8_t *bg;      /* Background arrangement */
 | 
				
			||||||
 | 
					    uint16_t bgAttr;  /* BG map cell attributes */
 | 
				
			||||||
 | 
					    int32_t  bgh;     /* Height of background in BG maps, minus 1 */
 | 
				
			||||||
 | 
					    int32_t  bgw;     /* Width of background in BG maps, minus 1 */
 | 
				
			||||||
 | 
					    int32_t  bottom;  /* Window bottom edge position */
 | 
				
			||||||
 | 
					    int32_t  bp;      /* Eye BG map source parallax */
 | 
				
			||||||
 | 
					    int32_t  bx;      /* BG horizontal map source position */
 | 
				
			||||||
 | 
					    int32_t  by;      /* BG vertical map source position */
 | 
				
			||||||
 | 
					    uint8_t *cell;    /* Pointer to BG map cell in host memory */
 | 
				
			||||||
 | 
					    uint8_t *chr;     /* Pointer to character data in host memory */
 | 
				
			||||||
 | 
					    int32_t  cx;      /* BG cell/character horizontal pixel source position */
 | 
				
			||||||
 | 
					    int32_t  cy;      /* BG cell/character vertical pixel source position */
 | 
				
			||||||
 | 
					    uint8_t *dest;    /* Pointer to output in shadow memory */
 | 
				
			||||||
 | 
					    int32_t  left;    /* Window left edge position */
 | 
				
			||||||
 | 
					    uint32_t param;   /* Current line parameter address */
 | 
				
			||||||
 | 
					    int8_t   pixel;   /* Character pixel value */
 | 
				
			||||||
 | 
					    int32_t  right;   /* Window right edge position */
 | 
				
			||||||
 | 
					    int32_t  top;     /* Window top edge position */
 | 
				
			||||||
 | 
					    int32_t  wx;      /* Eye horizontal position */
 | 
				
			||||||
 | 
					    int32_t  i, x, y; /* Iterators */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* World attributes */
 | 
				
			||||||
 | 
					    int32_t  base;       /* BG map base index */
 | 
				
			||||||
 | 
					    int      bgm;        /* BG mode */
 | 
				
			||||||
 | 
					    int32_t  dx;         /* Affine per-pixel X delta */
 | 
				
			||||||
 | 
					    int32_t  dy;         /* Affine per-pixel Y delta */
 | 
				
			||||||
 | 
					    int16_t  gp;         /* Window stereo parallax */
 | 
				
			||||||
 | 
					    int16_t  gx;         /* Window base horizontal position */
 | 
				
			||||||
 | 
					    int16_t  gy;         /* Window vertical position */
 | 
				
			||||||
 | 
					    int16_t  h;          /* Window height */
 | 
				
			||||||
 | 
					    int16_t  hofst;      /* H-bias shift */
 | 
				
			||||||
 | 
					    int32_t  mp;         /* BG map source stereo parallax */
 | 
				
			||||||
 | 
					    int32_t  mx = 0;     /* BG map horizontal source */
 | 
				
			||||||
 | 
					    int32_t  my = 0;     /* BG map vertical source */
 | 
				
			||||||
 | 
					    int32_t  scx;        /* Background width shift amount */
 | 
				
			||||||
 | 
					    int32_t  scy;        /* Background height shift amount */
 | 
				
			||||||
 | 
					    uint8_t *over;       /* Pointer to overplane "cell" in host memory */
 | 
				
			||||||
 | 
					    uint32_t params = 0; /* Base address of line parameters */
 | 
				
			||||||
 | 
					    int16_t  w;          /* Window width */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Validate the world isn't below the frame */
 | 
				
			||||||
 | 
					    gy = busReadBuffer(world + 6, VB_S16);
 | 
				
			||||||
 | 
					    if (gy > 223)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Validate the world isn't above the frame, and height is positive */
 | 
				
			||||||
 | 
					    bgm = attr >> 12 & 3;
 | 
				
			||||||
 | 
					    y   = bgm == 2 ? 0 : 8;
 | 
				
			||||||
 | 
					    h   = busReadBuffer(world + 16, VB_S16) + 1;
 | 
				
			||||||
 | 
					    if (h < y)
 | 
				
			||||||
 | 
					        h = y;
 | 
				
			||||||
 | 
					    if (h == 0)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    bottom = gy + h - 1;
 | 
				
			||||||
 | 
					    top    = (int32_t) sim->vip.xp.sbcount << 3;
 | 
				
			||||||
 | 
					    if (bottom < top)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    if (bottom > 223)
 | 
				
			||||||
 | 
					        bottom = 223;
 | 
				
			||||||
 | 
					    if (top < gy)
 | 
				
			||||||
 | 
					        top = gy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Validate width is positive */
 | 
				
			||||||
 | 
					    w = SignExtend(busReadBuffer(world + 14, VB_U16), bgm == 2 ? 10 : 13) + 1;
 | 
				
			||||||
 | 
					    if (w < 1)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Parse attributes */
 | 
				
			||||||
 | 
					    bg   = (uint8_t *) BG_TEMPLATES[attr >> 8 & 15];
 | 
				
			||||||
 | 
					    gx   = SignExtend(busReadBuffer(world + 2, VB_U16), 10);
 | 
				
			||||||
 | 
					    gp   = SignExtend(busReadBuffer(world + 4, VB_U16), 10);
 | 
				
			||||||
 | 
					    over = (attr & 0x0080) ? world + 20 : NULL;
 | 
				
			||||||
 | 
					    scx  = attr >> 10 & 3;
 | 
				
			||||||
 | 
					    scy  = attr >>  8 & 3;
 | 
				
			||||||
 | 
					    bgw  = (1 << scx) - 1;
 | 
				
			||||||
 | 
					    bgh  = (1 << scy) - 1;
 | 
				
			||||||
 | 
					    base = attr & 15 & ~((1 << (scx + scy < 3 ? scx + scy : 3)) - 1);
 | 
				
			||||||
 | 
					    if (bgm != 2) {
 | 
				
			||||||
 | 
					        mx = SignExtend(busReadBuffer(world +  8, VB_U16), 13);
 | 
				
			||||||
 | 
					        mp = SignExtend(busReadBuffer(world + 10, VB_U16), 15);
 | 
				
			||||||
 | 
					        my = SignExtend(busReadBuffer(world + 12, VB_U16), 13);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (bgm != 0) {
 | 
				
			||||||
 | 
					        params = 0x20000 + (top - gy) * (bgm == 1 ? 4 : 16) +
 | 
				
			||||||
 | 
					            ((uint32_t) busReadBuffer(world + 18, VB_U16) << 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else hofst = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Draw the world */
 | 
				
			||||||
 | 
					    for (i = 0; i < 2; i++) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Validate world is enabled */
 | 
				
			||||||
 | 
					        if ((attr & (int32_t) 0x8000 >> i) == 0) /* LON, RON */
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Validate the world isn't right of frame */
 | 
				
			||||||
 | 
					        wx = gx - (i == 0 ? gp : -gp);
 | 
				
			||||||
 | 
					        if (wx > 383)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        left = wx < 0 ? 0 : wx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Validate the world isn't left of frame */
 | 
				
			||||||
 | 
					        right = wx + w - 1;
 | 
				
			||||||
 | 
					        if (right < 0)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        if (right > 383)
 | 
				
			||||||
 | 
					            right = 383;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* BG source parallax */
 | 
				
			||||||
 | 
					        if (bgm != 2)
 | 
				
			||||||
 | 
					            bp = i == 0 ? -mp : mp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Draw all rows */
 | 
				
			||||||
 | 
					        for (y = top, param = params; y <= bottom; y++) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Parse line parameters */
 | 
				
			||||||
 | 
					            switch (bgm) {
 | 
				
			||||||
 | 
					                case 1: /* H-bias */
 | 
				
			||||||
 | 
					                    hofst  = SignExtend(vipParam(param | i << 1), 13);
 | 
				
			||||||
 | 
					                    param += 4;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case 2: /* Affine */
 | 
				
			||||||
 | 
					                    dx =  (int32_t) (int16_t) vipParam(param | 6) << 7;
 | 
				
			||||||
 | 
					                    dy =  (int32_t) (int16_t) vipParam(param | 8) << 7;
 | 
				
			||||||
 | 
					                    mp =  (int32_t) (int16_t) vipParam(param | 2);
 | 
				
			||||||
 | 
					                    mx = ((int32_t) (int16_t) vipParam(param    ) << 13) +
 | 
				
			||||||
 | 
					                        dx * (left - ((mp < 0) ^ i ? mp : 0));
 | 
				
			||||||
 | 
					                    my = ((int32_t) (int16_t) vipParam(param | 4) << 13) +
 | 
				
			||||||
 | 
					                        dy * (left - ((mp < 0) ^ i ? mp : 0));
 | 
				
			||||||
 | 
					                    param += 16;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Select output in shadow memory */
 | 
				
			||||||
 | 
					            dest = &sim->vip.shadow[i][left * 224 + y];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Draw all columns */
 | 
				
			||||||
 | 
					            for (x = left; x <= right; x++, dest += 224) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Locate the pixel in the background */
 | 
				
			||||||
 | 
					                if (bgm != 2) { /* Normal, H-bias */
 | 
				
			||||||
 | 
					                    cx  = x - wx + mx + bp + hofst;
 | 
				
			||||||
 | 
					                    cy  = y - gy + my;
 | 
				
			||||||
 | 
					                } else { /* Affine */
 | 
				
			||||||
 | 
					                    cx  = (int16_t) (mx >> 16);
 | 
				
			||||||
 | 
					                    cy  = (int16_t) (my >> 16);
 | 
				
			||||||
 | 
					                    mx += dx;
 | 
				
			||||||
 | 
					                    my += dy;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Locate the BG map in the background */
 | 
				
			||||||
 | 
					                bx   = SignExtend(cx >> 9, 23);
 | 
				
			||||||
 | 
					                by   = SignExtend(cy >> 9, 23);
 | 
				
			||||||
 | 
					                cell = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* BG map is out of bounds */
 | 
				
			||||||
 | 
					                if (bx < 0 || bx > bgw || by < 0 || by > bgh) {
 | 
				
			||||||
 | 
					                    if (over == NULL) {
 | 
				
			||||||
 | 
					                        bx &= bgw;
 | 
				
			||||||
 | 
					                        by &= bgh;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else cell = over;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Locate the cell in the BG map */
 | 
				
			||||||
 | 
					                if (cell == NULL) {
 | 
				
			||||||
 | 
					                    cell = &sim->vip.ram[
 | 
				
			||||||
 | 
					                        0x20000                           |
 | 
				
			||||||
 | 
					                        (base + bg[by << scx | bx]) << 13 |
 | 
				
			||||||
 | 
					                        (cy << 4 & 0x1F80)                |
 | 
				
			||||||
 | 
					                        (cx >> 2 & 0x007E)
 | 
				
			||||||
 | 
					                    ];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Extract the pixel from the character */
 | 
				
			||||||
 | 
					                bgAttr = busReadBuffer(cell, VB_U16);
 | 
				
			||||||
 | 
					                chr    = vipCharacter(sim, bgAttr);
 | 
				
			||||||
 | 
					                cx     = (bgAttr & 0x2000 ? 7 - cx : cx) & 7;
 | 
				
			||||||
 | 
					                cy     = (bgAttr & 0x1000 ? 7 - cy : cy) & 7;
 | 
				
			||||||
 | 
					                pixel  = chr[cy << 1 | cx >> 2] >> ((cx & 3) << 1) & 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Write the pixel into shadow memory */
 | 
				
			||||||
 | 
					                if (pixel != 0)
 | 
				
			||||||
 | 
					                    *dest = sim->vip.gplt[bgAttr >> 14 & 3][pixel];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            } /* x */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        } /* y */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } /* i */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Draw the current graphics configuration into shadow memory */
 | 
				
			||||||
 | 
					static void vipRender(VB *sim) {
 | 
				
			||||||
 | 
					    uint16_t  attr;   /* World attribute bits */
 | 
				
			||||||
 | 
					    int       group;  /* Next object group index */
 | 
				
			||||||
 | 
					    uint16_t *timing; /* Column timing in host memory */
 | 
				
			||||||
 | 
					    uint8_t  *world;  /* World attribute source in host memory */
 | 
				
			||||||
 | 
					    int32_t   x, y;   /* Iterators */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Erase all pixels */
 | 
				
			||||||
 | 
					    for (x = 0; x < 384*224; x += 224)
 | 
				
			||||||
 | 
					    for (y = (int32_t) sim->vip.xp.sbcount << 3; y < 224; y++)
 | 
				
			||||||
 | 
					        sim->vip.shadow[0][x + y] = sim->vip.shadow[1][x + y] = sim->vip.bkcol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Process all worlds */
 | 
				
			||||||
 | 
					    group = 3;
 | 
				
			||||||
 | 
					    world = &sim->vip.ram[0x3DBE0]; /* World 31 */
 | 
				
			||||||
 | 
					    for (x = 31; x >= 0; x--, world -= 32) {
 | 
				
			||||||
 | 
					        attr = busReadBuffer(world, VB_U16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Non-graphical world */
 | 
				
			||||||
 | 
					        if (attr & 0x0020) /* END */
 | 
				
			||||||
 | 
					            break;    /* Control world */
 | 
				
			||||||
 | 
					        if ((attr & 0xC000) == 0) /* LON, RON */
 | 
				
			||||||
 | 
					            continue; /* Dummy world */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Object world */
 | 
				
			||||||
 | 
					        if ((attr >> 12 & 3) == 3) {
 | 
				
			||||||
 | 
					            vipDrawObjects(sim, group);
 | 
				
			||||||
 | 
					            group = (group - 1) & 3;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Background world */
 | 
				
			||||||
 | 
					        else if (attr & 0xC000) /* LON, RON */
 | 
				
			||||||
 | 
					            vipDrawWorld(sim, world, attr);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					      Supply filler timings for each group of 8 rows of pixels
 | 
				
			||||||
 | 
					        Using 2.8ms experimental measurement for empty frame
 | 
				
			||||||
 | 
					        = 125 clocks every 24 halfwords
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    timing = &sim->vip.halfwords[(uint32_t) sim->vip.xp.sbcount * 384];
 | 
				
			||||||
 | 
					    x      = sim->vip.xp.column;
 | 
				
			||||||
 | 
					    for (y = sim->vip.xp.sbcount; y < 28; y++, x = 0)
 | 
				
			||||||
 | 
					    for (; x < 384; x++, timing++)
 | 
				
			||||||
 | 
					        *timing = 5 + ((uint32_t) 0x210884 >> x % 24 & 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Transfer one halfword from shadow pixel memory to the frame buffer */
 | 
				
			||||||
 | 
					static void vipTransferHalfword(VB *sim) {
 | 
				
			||||||
 | 
					    uint32_t bits0;  /* Upper 4 pixels from shadow memory */
 | 
				
			||||||
 | 
					    uint32_t bits1;  /* Lower 4 pixels from shadow memory */
 | 
				
			||||||
 | 
					    uint8_t *dest;   /* Pointer to frame buffer data in host memory */
 | 
				
			||||||
 | 
					    uint32_t offset; /* Position of halfword in shadow memory */
 | 
				
			||||||
 | 
					    uint8_t *src;    /* Pointer to pixel data in host memory */
 | 
				
			||||||
 | 
					    int      i;      /* Iterator */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Determine the output address in frame buffer memory */
 | 
				
			||||||
 | 
					    dest = &sim->vip.ram[
 | 
				
			||||||
 | 
					        (uint32_t) (sim->vip.dp.buffer ^ 1) << 15 |
 | 
				
			||||||
 | 
					        (uint32_t)  sim->vip.xp.column      <<  6 |
 | 
				
			||||||
 | 
					        (uint32_t)  sim->vip.xp.sbcount     <<  1
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Transfer halfwords to each eye's frame buffer */
 | 
				
			||||||
 | 
					    offset = (uint32_t) sim->vip.xp.column * 224 +
 | 
				
			||||||
 | 
					        ((uint32_t) sim->vip.xp.sbcount << 3);
 | 
				
			||||||
 | 
					    for (i = 0; i < 2; i++, dest += 0x10000) {
 | 
				
			||||||
 | 
					        src   = &sim->vip.shadow[i][offset];
 | 
				
			||||||
 | 
					        bits0 = busReadBuffer(src    , VB_S32);
 | 
				
			||||||
 | 
					        bits1 = busReadBuffer(src + 4, VB_S32);
 | 
				
			||||||
 | 
					        busWriteBuffer(dest, VB_U16,
 | 
				
			||||||
 | 
					            (bits0       & 0x0003) |
 | 
				
			||||||
 | 
					            (bits0 >>  6 & 0x000C) |
 | 
				
			||||||
 | 
					            (bits0 >> 12 & 0x0030) |
 | 
				
			||||||
 | 
					            (bits0 >> 18 & 0x00C0) |
 | 
				
			||||||
 | 
					            (bits1 <<  8 & 0x0300) |
 | 
				
			||||||
 | 
					            (bits1 <<  2 & 0x0C00) |
 | 
				
			||||||
 | 
					            (bits1 >>  4 & 0x3000) |
 | 
				
			||||||
 | 
					            (bits1 >> 10 & 0xC000)
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Process sub-component */
 | 
					/* Process sub-component */
 | 
				
			||||||
| 
						 | 
					@ -544,29 +968,49 @@ static void vipEmulateDrawing(VB *sim, uint32_t clocks) {
 | 
				
			||||||
        /* Processing by operation phase */
 | 
					        /* Processing by operation phase */
 | 
				
			||||||
        switch (sim->vip.xp.step) {
 | 
					        switch (sim->vip.xp.step) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            case 1: /* Initialize */
 | 
					            case 1: /* Initialization */
 | 
				
			||||||
                sim->vip.xp.sbcount = 0;
 | 
					                sim->vip.xp.halfword = 0;
 | 
				
			||||||
 | 
					                sim->vip.xp.sbcount  = 0;
 | 
				
			||||||
 | 
					                if (sim->vip.dp.buffer == 0)
 | 
				
			||||||
 | 
					                     sim->vip.xp.f1bsy = 1;
 | 
				
			||||||
 | 
					                else sim->vip.xp.f0bsy = 1;
 | 
				
			||||||
 | 
					                vipRender(sim);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                /* Fallthrough */
 | 
					                /* Fallthrough */
 | 
				
			||||||
            case 2: /* Transition to a new row of halfwords */
 | 
					            case 2: /* Begin drawing halfwords */
 | 
				
			||||||
                sim->vip.xp.sbout = 2240; /* 112us */
 | 
					                sim->vip.xp.column = 0;
 | 
				
			||||||
                sim->vip.xp.step  = 3;
 | 
					                sim->vip.xp.sbout  = 2240; /* 112us */
 | 
				
			||||||
 | 
					                sim->vip.xp.step   = 3;
 | 
				
			||||||
 | 
					                sim->vip.xp.until  = 2000; /* 100us */
 | 
				
			||||||
                if (sim->vip.xp.sbcount == sim->vip.xp.sbcmp)
 | 
					                if (sim->vip.xp.sbcount == sim->vip.xp.sbcmp)
 | 
				
			||||||
                    vipThrow(sim, 0x2000); /* SBHIT */
 | 
					                    vipThrow(sim, 0x2000); /* SBHIT */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Fallthrough */
 | 
				
			||||||
 | 
					            case 3: /* Draw one halfword */
 | 
				
			||||||
 | 
					                vipTransferHalfword(sim);
 | 
				
			||||||
 | 
					                sim->vip.xp.clocks = sim->vip.halfwords[sim->vip.xp.halfword];
 | 
				
			||||||
 | 
					                sim->vip.xp.column  ++;
 | 
				
			||||||
 | 
					                sim->vip.xp.halfword++;
 | 
				
			||||||
 | 
					                if (sim->vip.xp.column < 384)
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                /* Transition to a new line of halfwords */
 | 
				
			||||||
 | 
					                sim->vip.xp.sbcount++;
 | 
				
			||||||
 | 
					                sim->vip.xp.step = sim->vip.xp.sbcount == 28 ? 4 : 2;
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            case 3: /* Draw halfwords */
 | 
					            case 4: /* Drawing complete */
 | 
				
			||||||
                vipDrawWorlds(sim);
 | 
					 | 
				
			||||||
                sim->vip.xp.until = 2000; /* 100us */
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            case 4: /* Finalize */
 | 
					 | 
				
			||||||
                sim->vip.xp.step = 0;
 | 
					                sim->vip.xp.step = 0;
 | 
				
			||||||
 | 
					                if (sim->vip.dp.buffer == 0)
 | 
				
			||||||
 | 
					                     sim->vip.xp.f1bsy = 0;
 | 
				
			||||||
 | 
					                else sim->vip.xp.f0bsy = 0;
 | 
				
			||||||
                vipThrow(sim, 0x4000); /* XPEND */
 | 
					                vipThrow(sim, 0x4000); /* XPEND */
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return; /* Unreachable */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -578,12 +1022,13 @@ static int vipEmulate(VB *sim, uint32_t clocks) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Process sub-components */
 | 
					    /* Process sub-components */
 | 
				
			||||||
    int brk = vipEmulateDisplay(sim, clocks);
 | 
					    int brk = vipEmulateDisplay(sim, clocks);
 | 
				
			||||||
    vipEmulateDrawing(sim, clocks);
 | 
					    if (sim->vip.xp.step != 0)
 | 
				
			||||||
 | 
					        vipEmulateDrawing(sim, clocks);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Process SBOUT */
 | 
					    /* Process SBOUT */
 | 
				
			||||||
    if (sim->vip.xp.sbout != 0) {
 | 
					    if (sim->vip.xp.sbout != 0) {
 | 
				
			||||||
        if (sim->vip.xp.sbout <= clocks) {
 | 
					        if (sim->vip.xp.sbout <= clocks) {
 | 
				
			||||||
            sim->vip.xp.sbout  = 0;
 | 
					            sim->vip.xp.sbout = 0;
 | 
				
			||||||
        } else sim->vip.xp.sbout -= clocks;
 | 
					        } else sim->vip.xp.sbout -= clocks;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -609,7 +1054,7 @@ static void vipRead(VB *sim, uint32_t address, int type, int32_t *value) {
 | 
				
			||||||
        *value = vipReadIO(sim, address, type);
 | 
					        *value = vipReadIO(sim, address, type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Unmapped */
 | 
					    /* Unmapped */
 | 
				
			||||||
    if (address < 0x78000)
 | 
					    else if (address < 0x78000)
 | 
				
			||||||
        *value = 0;
 | 
					        *value = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Mirrors of character memory */
 | 
					    /* Mirrors of character memory */
 | 
				
			||||||
| 
						 | 
					@ -655,7 +1100,7 @@ static void vipReset(VB *sim) {
 | 
				
			||||||
    sim->vip.dp.lock    = 0;
 | 
					    sim->vip.dp.lock    = 0;
 | 
				
			||||||
    sim->vip.dp.r0bsy   = 0;
 | 
					    sim->vip.dp.r0bsy   = 0;
 | 
				
			||||||
    sim->vip.dp.r1bsy   = 0;
 | 
					    sim->vip.dp.r1bsy   = 0;
 | 
				
			||||||
    sim->vip.dp.scanrdy = 0;
 | 
					    sim->vip.dp.scanrdy = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Pixel processor extra (the hardware does not do this) */
 | 
					    /* Pixel processor extra (the hardware does not do this) */
 | 
				
			||||||
    sim->vip.xp.f0bsy    = 0;
 | 
					    sim->vip.xp.f0bsy    = 0;
 | 
				
			||||||
| 
						 | 
					@ -682,6 +1127,8 @@ static void vipReset(VB *sim) {
 | 
				
			||||||
static uint32_t vipUntil(VB *sim, uint32_t clocks) {
 | 
					static uint32_t vipUntil(VB *sim, uint32_t clocks) {
 | 
				
			||||||
    if (clocks > sim->vip.dp.until)
 | 
					    if (clocks > sim->vip.dp.until)
 | 
				
			||||||
        clocks = sim->vip.dp.until;
 | 
					        clocks = sim->vip.dp.until;
 | 
				
			||||||
 | 
					    if (sim->vip.xp.step != 0 && clocks > sim->vip.xp.until)
 | 
				
			||||||
 | 
					        clocks = sim->vip.xp.until;
 | 
				
			||||||
    return clocks;
 | 
					    return clocks;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										16
									
								
								makefile
								
								
								
								
							
							
						
						
									
										16
									
								
								makefile
								
								
								
								
							| 
						 | 
					@ -20,21 +20,21 @@ clean:
 | 
				
			||||||
.PHONY: core
 | 
					.PHONY: core
 | 
				
			||||||
core:
 | 
					core:
 | 
				
			||||||
#	GCC generic
 | 
					#	GCC generic
 | 
				
			||||||
	@gcc core/vb.c -I core -c -o /dev/null \
 | 
						@gcc core/vb.c -I core -c -o /dev/null -O3 \
 | 
				
			||||||
        -Werror -std=c90 -Wall -Wextra -Wpedantic
 | 
					        -Werror -std=c90 -Wall -Wextra -Wpedantic -fno-strict-aliasing
 | 
				
			||||||
#	GCC compilation control
 | 
					#	GCC compilation control
 | 
				
			||||||
	@gcc core/vb.c -I core -c -o /dev/null \
 | 
						@gcc core/vb.c -I core -c -o /dev/null -O3 \
 | 
				
			||||||
        -Werror -std=c90 -Wall -Wextra -Wpedantic \
 | 
					        -Werror -std=c90 -Wall -Wextra -Wpedantic -fno-strict-aliasing \
 | 
				
			||||||
        -D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC \
 | 
					        -D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC \
 | 
				
			||||||
        -D VB_DIRECT_EXCEPTION=textException -D VB_DIRECT_EXECUTE=textExecute \
 | 
					        -D VB_DIRECT_EXCEPTION=textException -D VB_DIRECT_EXECUTE=textExecute \
 | 
				
			||||||
        -D VB_DIRECT_FETCH=testFetch -D VB_DIRECT_FRAME=testFrame \
 | 
					        -D VB_DIRECT_FETCH=testFetch -D VB_DIRECT_FRAME=testFrame \
 | 
				
			||||||
        -D VB_DIRECT_WRITE=testWrite -D VB_DIRECT_READ=testRead
 | 
					        -D VB_DIRECT_WRITE=testWrite -D VB_DIRECT_READ=testRead
 | 
				
			||||||
#	Clang generic
 | 
					#	Clang generic
 | 
				
			||||||
	@emcc core/vb.c -I core -c -o /dev/null \
 | 
						@emcc core/vb.c -I core -c -o /dev/null -O3 \
 | 
				
			||||||
        -Werror -std=c90 -Wall -Wextra -Wpedantic
 | 
					        -Werror -std=c90 -Wall -Wextra -Wpedantic -fno-strict-aliasing
 | 
				
			||||||
#	Clang compilation control
 | 
					#	Clang compilation control
 | 
				
			||||||
	@emcc core/vb.c -I core -c -o /dev/null \
 | 
						@emcc core/vb.c -I core -c -o /dev/null -O3 \
 | 
				
			||||||
        -Werror -std=c90 -Wall -Wextra -Wpedantic \
 | 
					        -Werror -std=c90 -Wall -Wextra -Wpedantic -fno-strict-aliasing \
 | 
				
			||||||
        -D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC \
 | 
					        -D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC \
 | 
				
			||||||
        -D VB_DIRECT_EXCEPTION=textException -D VB_DIRECT_EXECUTE=textExecute \
 | 
					        -D VB_DIRECT_EXCEPTION=textException -D VB_DIRECT_EXECUTE=textExecute \
 | 
				
			||||||
        -D VB_DIRECT_FETCH=testFetch -D VB_DIRECT_FRAME=testFrame \
 | 
					        -D VB_DIRECT_FETCH=testFetch -D VB_DIRECT_FRAME=testFrame \
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue