# HG changeset patch # User Michael Pavone # Date 1661235676 25200 # Node ID dc4268a778bca5792fb0d7bb69a0af3b4ba48597 # Parent 9826d50061a0307d7066a968ab6b5d24814eeda7 Implement Mode 4 sprite zooming diff -r 9826d50061a0 -r dc4268a778bc vdp.c --- a/vdp.c Mon Aug 22 22:59:42 2022 -0700 +++ b/vdp.c Mon Aug 22 23:21:16 2022 -0700 @@ -392,6 +392,10 @@ static void render_sprite_cells_mode4(vdp_context * context) { if (context->sprite_index >= context->sprite_draws) { + uint8_t zoom = context->type != VDP_GENESIS && (context->regs[REG_MODE_2] & BIT_SPRITE_ZM); + if (context->type == VDP_SMS && context->sprite_index < 4) { + zoom = 0; + } sprite_draw * d = context->sprite_draw_list + context->sprite_index; uint32_t pixels = planar_to_chunky[context->fetch_tmp[0]] << 1; pixels |= planar_to_chunky[context->fetch_tmp[1]]; @@ -411,6 +415,19 @@ } else { context->linebuf[x] = pixels >> i & 0xF; } + if (zoom) { + x++; + if (context->linebuf[x] && (pixels >> i & 0xF)) { + if ( + ((context->regs[REG_MODE_1] & BIT_SPRITE_8PX) && x > 8) + || ((!(context->regs[REG_MODE_1] & BIT_SPRITE_8PX)) && x < 256) + ) { + context->flags2 |= FLAG2_SPRITE_COLLIDE; + } + } else { + context->linebuf[x] = pixels >> i & 0xF; + } + } } context->sprite_index--; } @@ -683,12 +700,20 @@ uint32_t sat_address = mode4_address_map[(context->regs[REG_SAT] << 7 & 0x3F00) + context->sprite_index]; uint32_t y = context->vdpmem[sat_address+1]; uint32_t size = (context->regs[REG_MODE_2] & BIT_SPRITE_SZ) ? 16 : 8; + uint32_t ysize = size; + uint8_t zoom = context->type != VDP_GENESIS && (context->regs[REG_MODE_2] & BIT_SPRITE_ZM); + if (context->type == VDP_SMS && context->slot_counter <= 4) { + zoom = 0; + } + if (zoom) { + ysize *= 2; + } if (y == 0xd0) { context->sprite_index = MAX_SPRITES_FRAME_H32; return; } else { - if (y <= line && line < (y + size)) { + if (y <= line && line < (y + ysize)) { if (!context->slot_counter) { context->sprite_index = MAX_SPRITES_FRAME_H32; context->flags |= FLAG_DOT_OFLOW; @@ -707,7 +732,7 @@ context->sprite_index = MAX_SPRITES_FRAME_H32; return; } else { - if (y <= line && line < (y + size)) { + if (y <= line && line < (y + ysize)) { if (!context->slot_counter) { context->sprite_index = MAX_SPRITES_FRAME_H32; context->flags |= FLAG_DOT_OFLOW; @@ -788,11 +813,19 @@ uint32_t address = (context->regs[REG_SAT] << 7 & 0x3F00) + 0x80 + context->sprite_info_list[context->cur_slot].index * 2; address = mode4_address_map[address]; --context->sprite_draws; + uint8_t zoom = context->type != VDP_GENESIS && (context->regs[REG_MODE_2] & BIT_SPRITE_ZM); + if (context->type == VDP_SMS && context->sprite_draws < 4) { + zoom = 0; + } uint32_t tile_address = context->vdpmem[address] * 32 + (context->regs[REG_STILE_BASE] << 11 & 0x2000); if (context->regs[REG_MODE_2] & BIT_SPRITE_SZ) { tile_address &= ~32; } - tile_address += (context->vcounter - context->sprite_info_list[context->cur_slot].y)* 4; + uint16_t y_diff = context->vcounter - context->sprite_info_list[context->cur_slot].y; + if (zoom) { + y_diff >>= 1; + } + tile_address += y_diff * 4; context->sprite_draw_list[context->sprite_draws].x_pos = context->vdpmem[address + 1]; context->sprite_draw_list[context->sprite_draws].address = tile_address; context->cur_slot--; diff -r 9826d50061a0 -r dc4268a778bc vdp.h --- a/vdp.h Mon Aug 22 22:59:42 2022 -0700 +++ b/vdp.h Mon Aug 22 23:21:16 2022 -0700 @@ -116,6 +116,7 @@ #define BIT_PAL 0x08 #define BIT_MODE_5 0x04 #define BIT_SPRITE_SZ 0x02 +#define BIT_SPRITE_ZM 0x01 //Mode reg 3 #define BIT_EINT_EN 0x08