Establish drawing procedure
This commit is contained in:
		
							parent
							
								
									7a8cf8952a
								
							
						
					
					
						commit
						3c2c9bb938
					
				
							
								
								
									
										11
									
								
								core/vb.c
								
								
								
								
							
							
						
						
									
										11
									
								
								core/vb.c
								
								
								
								
							| 
						 | 
				
			
			@ -126,13 +126,20 @@ struct VB {
 | 
			
		|||
 | 
			
		||||
        /* Pixel processor */
 | 
			
		||||
        struct {
 | 
			
		||||
            /* Hardware state */
 | 
			
		||||
            uint8_t  f0bsy;    /* Drawing into frame buffer 0 */
 | 
			
		||||
            uint8_t  f1bsy;    /* Drawing into frame buffer 1 */
 | 
			
		||||
            uint8_t  overtime; /* Drawing extends into display interval */
 | 
			
		||||
            uint8_t  sbcmp;    /* Vertical output position compare */
 | 
			
		||||
            uint8_t  sbcount;  /* Current vertical output position */
 | 
			
		||||
            uint8_t sbout;    /* Drawing specified vertical output position */
 | 
			
		||||
            uint32_t sbout;    /* Drawing specified vertical output position */
 | 
			
		||||
            uint8_t  xpen;     /* Drawing enabled */
 | 
			
		||||
 | 
			
		||||
            /* Simulation state */
 | 
			
		||||
            uint32_t clocks;   /* Master clocks to wait */
 | 
			
		||||
            int      frame;    /* FRMCYC counter */
 | 
			
		||||
            int      step;     /* Processing phase */
 | 
			
		||||
            uint32_t until;    /* Clocks until interrupt condition */
 | 
			
		||||
        } xp;
 | 
			
		||||
 | 
			
		||||
        /* Control state */
 | 
			
		||||
| 
						 | 
				
			
			@ -146,7 +153,7 @@ struct VB {
 | 
			
		|||
        uint16_t spt[4];     /* Object control */
 | 
			
		||||
 | 
			
		||||
        /* Output frame buffers [buffer index][0=left, 1=right][pixel index] */
 | 
			
		||||
        uint8_t frames[2][2][384 * 224];
 | 
			
		||||
        uint8_t frames[2][2][384*224];
 | 
			
		||||
 | 
			
		||||
        /* Other state */
 | 
			
		||||
        uint8_t ram[0x40000]; /* Video memory */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										234
									
								
								core/vip.c
								
								
								
								
							
							
						
						
									
										234
									
								
								core/vip.c
								
								
								
								
							| 
						 | 
				
			
			@ -12,23 +12,6 @@
 | 
			
		|||
 | 
			
		||||
/***************************** Module Functions ******************************/
 | 
			
		||||
 | 
			
		||||
/* Precompute brightness values for image output */
 | 
			
		||||
static void vipComputeBrightness(VB *sim) {
 | 
			
		||||
    int32_t brt[4]; /* Working output */
 | 
			
		||||
    int32_t repeat; /* Multiplier from column table */
 | 
			
		||||
    int     x;      /* Iterator */
 | 
			
		||||
 | 
			
		||||
    /* Compute brightness from hardware state */
 | 
			
		||||
    repeat = (int32_t) sim->vip.ram[sim->vip.dp.cta + 1] + 1;
 | 
			
		||||
    brt[1] = repeat * sim->vip.brtRest[0];
 | 
			
		||||
    brt[2] = repeat * sim->vip.brtRest[1];
 | 
			
		||||
    brt[3] = repeat * sim->vip.brtRest[2] + brt[2] + brt[1];
 | 
			
		||||
 | 
			
		||||
    /* Scale brightness values to 0..255 */
 | 
			
		||||
    for (x = 1; x < 4; x++)
 | 
			
		||||
        sim->vip.dp.brt[x] = ((brt[x] > 127 ? 127 : brt[x]) * 510 + 127) / 254;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Read a palette */
 | 
			
		||||
static int32_t vipReadPalette(uint8_t *entries) {
 | 
			
		||||
    return entries[3] << 6 | entries[2] << 4 | entries[1] << 2;
 | 
			
		||||
| 
						 | 
				
			
			@ -42,42 +25,6 @@ static void vipThrow(VB *sim, uint16_t cause) {
 | 
			
		|||
    sim->cpu.irq    |= 0x0010;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Transfer one column of frame buffer pixels to output */
 | 
			
		||||
static void vipTransferColumn(VB *sim, int32_t eye) {
 | 
			
		||||
    int32_t  bits; /* Pixel bits from frame buffer */
 | 
			
		||||
    uint8_t *dest; /* Host frame image output */
 | 
			
		||||
    uint8_t *src;  /* Simulation frame buffer input */
 | 
			
		||||
    int      y, z; /* Iterators */
 | 
			
		||||
 | 
			
		||||
    /* Select destination address in host memory */
 | 
			
		||||
    dest = &sim->vip.frames
 | 
			
		||||
        [sim->vip.dp.buffer][eye][sim->vip.dp.column];
 | 
			
		||||
 | 
			
		||||
    /* Output is disabled */
 | 
			
		||||
    if ((sim->vip.dp.disp & sim->vip.dp.synce) == 0) {
 | 
			
		||||
        for (z = 0; z < 0x15000; z += 4) {
 | 
			
		||||
            busWriteBuffer(dest, VB_S32, 0);
 | 
			
		||||
            dest += 4;
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Select source address in host memory */
 | 
			
		||||
    src = &sim->vip.ram[
 | 
			
		||||
        eye                << 16 |
 | 
			
		||||
        sim->vip.dp.buffer << 15 |
 | 
			
		||||
        sim->vip.dp.column <<  6
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    /* Transfer all rows as words */
 | 
			
		||||
    for (y = 0; y < 224; y += 4) {
 | 
			
		||||
        bits = busReadBuffer(src, VB_S32);
 | 
			
		||||
        for (z = 0; z < 1536; z += 384, bits >>= 2)
 | 
			
		||||
            dest[z] = sim->vip.dp.brt[bits & 3];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Write a palette */
 | 
			
		||||
static void vipWritePalette(uint8_t *entries, int32_t mask, int32_t value) {
 | 
			
		||||
    if (mask & 0x00FF)
 | 
			
		||||
| 
						 | 
				
			
			@ -157,7 +104,7 @@ static int32_t vipReadIO(VB *sim, uint32_t address, int type) {
 | 
			
		|||
 | 
			
		||||
        case 0x5F840>>1: /* XPSTTS */
 | 
			
		||||
            value =
 | 
			
		||||
                (int32_t) sim->vip.xp.sbout    << 15 |
 | 
			
		||||
                (int32_t) !!sim->vip.xp.sbout  << 15 |
 | 
			
		||||
                (int32_t) sim->vip.xp.sbcount  <<  8 |
 | 
			
		||||
                (int32_t) sim->vip.xp.overtime <<  4 |
 | 
			
		||||
                (int32_t) sim->vip.xp.f1bsy    <<  3 |
 | 
			
		||||
| 
						 | 
				
			
			@ -378,6 +325,59 @@ static int vipOnFrame(VB *sim) {
 | 
			
		|||
 | 
			
		||||
/***************************** Display Processor *****************************/
 | 
			
		||||
 | 
			
		||||
/* Precompute brightness values for image output */
 | 
			
		||||
static void vipComputeBrightness(VB *sim) {
 | 
			
		||||
    int32_t brt[4]; /* Working output */
 | 
			
		||||
    int32_t repeat; /* Multiplier from column table */
 | 
			
		||||
    int     x;      /* Iterator */
 | 
			
		||||
 | 
			
		||||
    /* Compute brightness from hardware state */
 | 
			
		||||
    repeat = (int32_t) sim->vip.ram[sim->vip.dp.cta + 1] + 1;
 | 
			
		||||
    brt[1] = repeat * sim->vip.brtRest[0];
 | 
			
		||||
    brt[2] = repeat * sim->vip.brtRest[1];
 | 
			
		||||
    brt[3] = repeat * sim->vip.brtRest[2] + brt[2] + brt[1];
 | 
			
		||||
 | 
			
		||||
    /* Scale brightness values to 0..255 */
 | 
			
		||||
    for (x = 1; x < 4; x++)
 | 
			
		||||
        sim->vip.dp.brt[x] = ((brt[x] > 127 ? 127 : brt[x]) * 510 + 127) / 254;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Transfer one column of frame buffer pixels to output */
 | 
			
		||||
static void vipTransferColumn(VB *sim, int32_t eye) {
 | 
			
		||||
    int32_t  bits; /* Pixel bits from frame buffer */
 | 
			
		||||
    uint8_t *dest; /* Host frame image output */
 | 
			
		||||
    uint8_t *src;  /* Simulation frame buffer input */
 | 
			
		||||
    int      y, z; /* Iterators */
 | 
			
		||||
 | 
			
		||||
    /* Select destination address in host memory */
 | 
			
		||||
    dest = &sim->vip.frames
 | 
			
		||||
        [sim->vip.dp.buffer][eye][sim->vip.dp.column];
 | 
			
		||||
 | 
			
		||||
    /* Output is disabled */
 | 
			
		||||
    if ((sim->vip.dp.disp & sim->vip.dp.synce) == 0) {
 | 
			
		||||
        for (z = 0; z < 0x15000; z += 4) {
 | 
			
		||||
            busWriteBuffer(dest, VB_S32, 0);
 | 
			
		||||
            dest += 4;
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Select source address in host memory */
 | 
			
		||||
    src = &sim->vip.ram[
 | 
			
		||||
        eye                << 16 |
 | 
			
		||||
        sim->vip.dp.buffer << 15 |
 | 
			
		||||
        sim->vip.dp.column <<  6
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    /* Transfer all rows as words */
 | 
			
		||||
    for (y = 0; y < 224; y += 16, src += 4) {
 | 
			
		||||
        bits = busReadBuffer(src, VB_S32);
 | 
			
		||||
        for (z = 0; z < 16; bits >>= 2, z++, dest += 384)
 | 
			
		||||
            *dest = sim->vip.dp.brt[bits & 3];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Process sub-component */
 | 
			
		||||
static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -405,8 +405,26 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
 | 
			
		|||
                sim->vip.dp.step   = 1;
 | 
			
		||||
                sim->vip.dp.until  = vipClocksMs(8);
 | 
			
		||||
                vipThrow(sim, 0x0010); /* FRAMESTART */
 | 
			
		||||
                /* TODO: Initiate drawing, throw GAMESTART */
 | 
			
		||||
                /* ELSE: Set OVERTIME, throw TIMEERR */
 | 
			
		||||
 | 
			
		||||
                /* Game frame */
 | 
			
		||||
                if (sim->vip.xp.frame >= sim->vip.frmcyc) {
 | 
			
		||||
                    sim->vip.xp.frame = 0;
 | 
			
		||||
 | 
			
		||||
                    /* Initiate drawing procedure */
 | 
			
		||||
                    if (sim->vip.xp.step == 0) {
 | 
			
		||||
                        sim->vip.xp.overtime = 0;
 | 
			
		||||
                        sim->vip.xp.step     = 1;
 | 
			
		||||
                        vipThrow(sim, 0x0008); /* GAMESTART */
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    /* Drawing procedure has run into overtime */
 | 
			
		||||
                    else {
 | 
			
		||||
                        sim->vip.xp.overtime = 1;
 | 
			
		||||
                        vipThrow(sim, 0x8000); /* TIMEERR */
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                } else sim->vip.xp.frame++;
 | 
			
		||||
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            /* 0ms-3ms - Idle */
 | 
			
		||||
| 
						 | 
				
			
			@ -500,10 +518,55 @@ static int vipEmulateDisplay(VB *sim, uint32_t clocks) {
 | 
			
		|||
 | 
			
		||||
/****************************** Pixel Processor ******************************/
 | 
			
		||||
 | 
			
		||||
/* Draw every world into a group of 8 rows of pixels */
 | 
			
		||||
static void vipDrawWorlds(VB *sim) {
 | 
			
		||||
    (void) sim;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Process sub-component */
 | 
			
		||||
static void vipEmulateDrawing(VB *sim, uint32_t clocks) {
 | 
			
		||||
    (void) sim;
 | 
			
		||||
    (void) clocks;
 | 
			
		||||
 | 
			
		||||
    /* Process all clocks */
 | 
			
		||||
    for (;;) {
 | 
			
		||||
 | 
			
		||||
        /* The next event is after the time remaining */
 | 
			
		||||
        if (sim->vip.xp.clocks > clocks) {
 | 
			
		||||
            sim->vip.xp.clocks -= clocks;
 | 
			
		||||
            sim->vip.xp.until  -= clocks;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Advance forward the component's number of clocks */
 | 
			
		||||
        clocks            -= sim->vip.xp.clocks;
 | 
			
		||||
        sim->vip.xp.until -= sim->vip.xp.clocks;
 | 
			
		||||
        sim->vip.xp.clocks = 0;
 | 
			
		||||
 | 
			
		||||
        /* Processing by operation phase */
 | 
			
		||||
        switch (sim->vip.xp.step) {
 | 
			
		||||
 | 
			
		||||
            case 1: /* Initialize */
 | 
			
		||||
                sim->vip.xp.sbcount = 0;
 | 
			
		||||
 | 
			
		||||
                /* Fallthrough */
 | 
			
		||||
            case 2: /* Transition to a new row of halfwords */
 | 
			
		||||
                sim->vip.xp.sbout = 2240; /* 112us */
 | 
			
		||||
                sim->vip.xp.step  = 3;
 | 
			
		||||
                if (sim->vip.xp.sbcount == sim->vip.xp.sbcmp)
 | 
			
		||||
                    vipThrow(sim, 0x2000); /* SBHIT */
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case 3: /* Draw halfwords */
 | 
			
		||||
                vipDrawWorlds(sim);
 | 
			
		||||
                sim->vip.xp.until = 2000; /* 100us */
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
            case 4: /* Finalize */
 | 
			
		||||
                sim->vip.xp.step = 0;
 | 
			
		||||
                vipThrow(sim, 0x4000); /* XPEND */
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -512,8 +575,18 @@ static void vipEmulateDrawing(VB *sim, uint32_t clocks) {
 | 
			
		|||
 | 
			
		||||
/* Process component */
 | 
			
		||||
static int vipEmulate(VB *sim, uint32_t clocks) {
 | 
			
		||||
 | 
			
		||||
    /* Process sub-components */
 | 
			
		||||
    int brk = vipEmulateDisplay(sim, clocks);
 | 
			
		||||
    vipEmulateDrawing(sim, clocks);
 | 
			
		||||
 | 
			
		||||
    /* Process SBOUT */
 | 
			
		||||
    if (sim->vip.xp.sbout != 0) {
 | 
			
		||||
        if (sim->vip.xp.sbout <= clocks) {
 | 
			
		||||
            sim->vip.xp.sbout  = 0;
 | 
			
		||||
        } else sim->vip.xp.sbout -= clocks;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return brk;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -552,33 +625,20 @@ static void vipReset(VB *sim) {
 | 
			
		|||
    int x, y; /* Iterators */
 | 
			
		||||
 | 
			
		||||
    /* Normal */
 | 
			
		||||
    sim->vip.intenb   = 0x0000;
 | 
			
		||||
    sim->vip.dp.disp  = 0;
 | 
			
		||||
    sim->vip.dp.re    = 0;
 | 
			
		||||
    sim->vip.dp.synce = 0;
 | 
			
		||||
    sim->vip.intenb   = 0x0000;
 | 
			
		||||
    sim->vip.xp.xpen  = 0;
 | 
			
		||||
 | 
			
		||||
    /* Extra (the hardware does not do this) */
 | 
			
		||||
    for (x = 0; x < 0x80000; x++)
 | 
			
		||||
        sim->vip.ram[x] = 0;
 | 
			
		||||
    sim->vip.bkcol     = 0;
 | 
			
		||||
    sim->vip.cta.cta_l = 0xFA;
 | 
			
		||||
    sim->vip.cta.cta_r = 0xFA;
 | 
			
		||||
    sim->vip.frmcyc    = 0;
 | 
			
		||||
    sim->vip.intpnd    = 0x0000;
 | 
			
		||||
    sim->vip.dp.fclk     = 0;
 | 
			
		||||
    sim->vip.dp.l0bsy    = 0;
 | 
			
		||||
    sim->vip.dp.l1bsy    = 0;
 | 
			
		||||
    sim->vip.dp.lock     = 0;
 | 
			
		||||
    sim->vip.dp.r0bsy    = 0;
 | 
			
		||||
    sim->vip.dp.r1bsy    = 0;
 | 
			
		||||
    sim->vip.dp.scanrdy  = 0;
 | 
			
		||||
    sim->vip.xp.f0bsy    = 0;
 | 
			
		||||
    sim->vip.xp.f1bsy    = 0;
 | 
			
		||||
    sim->vip.xp.overtime = 0;
 | 
			
		||||
    sim->vip.xp.sbcmp    = 0;
 | 
			
		||||
    sim->vip.xp.sbcount  = 0;
 | 
			
		||||
    sim->vip.xp.sbout    = 0;
 | 
			
		||||
    for (x = 0; x < 0x40000; x++)
 | 
			
		||||
        sim->vip.ram[x] = 0;
 | 
			
		||||
    for (x = 0; x < 4; x++) {
 | 
			
		||||
        sim->vip.brtRest[x] = 0;
 | 
			
		||||
        sim->vip.spt    [x] = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -588,10 +648,34 @@ static void vipReset(VB *sim) {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Other */
 | 
			
		||||
    /* Display processor extra (the hardware does not do this) */
 | 
			
		||||
    sim->vip.dp.fclk    = 0;
 | 
			
		||||
    sim->vip.dp.l0bsy   = 0;
 | 
			
		||||
    sim->vip.dp.l1bsy   = 0;
 | 
			
		||||
    sim->vip.dp.lock    = 0;
 | 
			
		||||
    sim->vip.dp.r0bsy   = 0;
 | 
			
		||||
    sim->vip.dp.r1bsy   = 0;
 | 
			
		||||
    sim->vip.dp.scanrdy = 0;
 | 
			
		||||
 | 
			
		||||
    /* Pixel processor extra (the hardware does not do this) */
 | 
			
		||||
    sim->vip.xp.f0bsy    = 0;
 | 
			
		||||
    sim->vip.xp.f1bsy    = 0;
 | 
			
		||||
    sim->vip.xp.overtime = 0;
 | 
			
		||||
    sim->vip.xp.sbcmp    = 0;
 | 
			
		||||
    sim->vip.xp.sbcount  = 0;
 | 
			
		||||
    sim->vip.xp.sbout    = 0;
 | 
			
		||||
 | 
			
		||||
    /* Display processor other */
 | 
			
		||||
    sim->vip.dp.brt[0] = 0;
 | 
			
		||||
    sim->vip.dp.buffer = 0; /* TODO: Hardware might actually do this */
 | 
			
		||||
    sim->vip.dp.clocks = 0;
 | 
			
		||||
    sim->vip.dp.step   = 0;
 | 
			
		||||
    sim->vip.dp.until  = 0;
 | 
			
		||||
 | 
			
		||||
    /* Pixel processor other */
 | 
			
		||||
    sim->vip.xp.clocks = 0;
 | 
			
		||||
    sim->vip.xp.step   = 0;
 | 
			
		||||
    sim->vip.xp.until  = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Determine how many clocks are guaranteed to process */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										8
									
								
								makefile
								
								
								
								
							
							
						
						
									
										8
									
								
								makefile
								
								
								
								
							| 
						 | 
				
			
			@ -27,8 +27,8 @@ core:
 | 
			
		|||
        -Werror -std=c90 -Wall -Wextra -Wpedantic \
 | 
			
		||||
        -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_FETCH=testFetch -D VB_DIRECT_READ=testRead \
 | 
			
		||||
        -D VB_DIRECT_WRITE=testWrite
 | 
			
		||||
        -D VB_DIRECT_FETCH=testFetch -D VB_DIRECT_FRAME=testFrame \
 | 
			
		||||
        -D VB_DIRECT_WRITE=testWrite -D VB_DIRECT_READ=testRead
 | 
			
		||||
#	Clang generic
 | 
			
		||||
	@emcc core/vb.c -I core -c -o /dev/null \
 | 
			
		||||
        -Werror -std=c90 -Wall -Wextra -Wpedantic
 | 
			
		||||
| 
						 | 
				
			
			@ -37,8 +37,8 @@ core:
 | 
			
		|||
        -Werror -std=c90 -Wall -Wextra -Wpedantic \
 | 
			
		||||
        -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_FETCH=testFetch -D VB_DIRECT_READ=testRead \
 | 
			
		||||
        -D VB_DIRECT_WRITE=testWrite
 | 
			
		||||
        -D VB_DIRECT_FETCH=testFetch -D VB_DIRECT_FRAME=testFrame \
 | 
			
		||||
        -D VB_DIRECT_WRITE=testWrite -D VB_DIRECT_READ=testRead
 | 
			
		||||
 | 
			
		||||
.PHONY: wasm
 | 
			
		||||
wasm:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue