Mercurial > repos > blastem
comparison vdp.c @ 39:3c69319269ef
Horizontal scroll works correctly now. In particular, the SEGA logo in Vectorman has a nice smooth wave like it should
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 09 Dec 2012 01:13:41 -0800 |
parents | 898e3d035f42 |
children | 7368a7071908 |
comparison
equal
deleted
inserted
replaced
38:898e3d035f42 | 39:3c69319269ef |
---|---|
11 #define MAP_BIT_V_FLIP 0x1000 | 11 #define MAP_BIT_V_FLIP 0x1000 |
12 | 12 |
13 #define BIT_PAL 0x8 | 13 #define BIT_PAL 0x8 |
14 #define BIT_H40 0x1 | 14 #define BIT_H40 0x1 |
15 | 15 |
16 #define SCROLL_BUFFER_SIZE 32 | |
17 #define SCROLL_BUFFER_DRAW 16 | |
18 | |
16 void init_vdp_context(vdp_context * context) | 19 void init_vdp_context(vdp_context * context) |
17 { | 20 { |
18 memset(context, 0, sizeof(context)); | 21 memset(context, 0, sizeof(context)); |
19 context->vdpmem = malloc(VRAM_SIZE); | 22 context->vdpmem = malloc(VRAM_SIZE); |
20 context->framebuf = malloc(FRAMEBUF_SIZE); | 23 context->framebuf = malloc(FRAMEBUF_SIZE); |
21 context->linebuf = malloc(LINEBUF_SIZE + 48); | 24 context->linebuf = malloc(LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2); |
22 context->tmp_buf_a = context->linebuf + LINEBUF_SIZE; | 25 context->tmp_buf_a = context->linebuf + LINEBUF_SIZE; |
23 context->tmp_buf_b = context->tmp_buf_a + 24; | 26 context->tmp_buf_b = context->tmp_buf_a + SCROLL_BUFFER_SIZE; |
24 context->sprite_draws = MAX_DRAWS; | 27 context->sprite_draws = MAX_DRAWS; |
25 } | 28 } |
26 | 29 |
27 void render_sprite_cells(vdp_context * context) | 30 void render_sprite_cells(vdp_context * context) |
28 { | 31 { |
194 uint16_t hscroll_mask; | 197 uint16_t hscroll_mask; |
195 uint16_t v_mul; | 198 uint16_t v_mul; |
196 switch(context->regs[REG_SCROLL] & 0x3) | 199 switch(context->regs[REG_SCROLL] & 0x3) |
197 { | 200 { |
198 case 0: | 201 case 0: |
199 hscroll_mask = 0xF8; | 202 hscroll_mask = 0xF0; |
200 v_mul = 64; | 203 v_mul = 64; |
201 break; | 204 break; |
202 case 0x1: | 205 case 0x1: |
203 hscroll_mask = 0x1F8; | 206 hscroll_mask = 0x3F; |
204 v_mul = 128; | 207 v_mul = 128; |
205 break; | 208 break; |
206 case 0x2: | 209 case 0x2: |
207 //TODO: Verify this behavior | 210 //TODO: Verify this behavior |
208 hscroll_mask = 0; | 211 hscroll_mask = 0; |
209 v_mul = 0; | 212 v_mul = 0; |
210 break; | 213 break; |
211 case 0x3: | 214 case 0x3: |
212 hscroll_mask = 0x3F8; | 215 hscroll_mask = 0x3F0; |
213 v_mul = 256; | 216 v_mul = 256; |
214 break; | 217 break; |
215 } | 218 } |
216 uint16_t hscroll, offset; | 219 uint16_t hscroll, offset; |
217 for (int i = 0; i < 2; i++) { | 220 for (int i = 0; i < 2; i++) { |
218 hscroll = ((column - 2 + i) * 8 - hscroll_val) & hscroll_mask; | 221 hscroll = (column - 2 + i - ((hscroll_val/8) & 0xFFFE)) & hscroll_mask; |
219 offset = address + ((vscroll * v_mul + hscroll/4) & 0x1FFF); | 222 offset = address + ((vscroll * v_mul + hscroll*2) & 0x1FFF); |
220 //printf("%s | line: %d, col: %d, x: %d, hs_mask %X, v_mul: %d, scr reg: %X, tbl addr: %X\n", (vsram_off ? "B" : "A"), line, (column-(2-i)), hscroll, hscroll_mask, v_mul, context->regs[REG_SCROLL], offset); | 223 //printf("%s | line: %d, col: %d, x: %d, hs_mask %X, scr reg: %X, tbl addr: %X\n", (vsram_off ? "B" : "A"), line, (column-2+i), hscroll, hscroll_mask, context->regs[REG_SCROLL], offset); |
221 uint16_t col_val = (context->vdpmem[offset] << 8) | context->vdpmem[offset+1]; | 224 uint16_t col_val = (context->vdpmem[offset] << 8) | context->vdpmem[offset+1]; |
222 if (i) { | 225 if (i) { |
223 context->col_2 = col_val; | 226 context->col_2 = col_val; |
224 } else { | 227 } else { |
225 context->col_1 = col_val; | 228 context->col_1 = col_val; |
262 } | 265 } |
263 } | 266 } |
264 | 267 |
265 void render_map_1(vdp_context * context) | 268 void render_map_1(vdp_context * context) |
266 { | 269 { |
267 render_map(context->col_1, context->tmp_buf_a+8, context); | 270 render_map(context->col_1, context->tmp_buf_a+SCROLL_BUFFER_DRAW, context); |
268 } | 271 } |
269 | 272 |
270 void render_map_2(vdp_context * context) | 273 void render_map_2(vdp_context * context) |
271 { | 274 { |
272 render_map(context->col_2, context->tmp_buf_a+16, context); | 275 render_map(context->col_2, context->tmp_buf_a+SCROLL_BUFFER_DRAW+8, context); |
273 } | 276 } |
274 | 277 |
275 void render_map_3(vdp_context * context) | 278 void render_map_3(vdp_context * context) |
276 { | 279 { |
277 render_map(context->col_1, context->tmp_buf_b+8, context); | 280 render_map(context->col_1, context->tmp_buf_b+SCROLL_BUFFER_DRAW, context); |
278 } | 281 } |
279 | 282 |
280 void render_map_output(uint32_t line, int32_t col, vdp_context * context) | 283 void render_map_output(uint32_t line, int32_t col, vdp_context * context) |
281 { | 284 { |
282 if (line >= 240) { | 285 if (line >= 240) { |
283 return; | 286 return; |
284 } | 287 } |
285 render_map(context->col_2, context->tmp_buf_b+16, context); | 288 render_map(context->col_2, context->tmp_buf_b+SCROLL_BUFFER_DRAW+8, context); |
286 uint16_t *dst, *end; | 289 uint16_t *dst, *end; |
287 uint8_t *sprite_buf, *plane_a, *plane_b; | 290 uint8_t *sprite_buf, *plane_a, *plane_b; |
288 if (col) | 291 if (col) |
289 { | 292 { |
290 col-=2; | 293 col-=2; |
291 dst = context->framebuf + line * 320 + col * 8; | 294 dst = context->framebuf + line * 320 + col * 8; |
292 sprite_buf = context->linebuf + col * 8; | 295 sprite_buf = context->linebuf + col * 8; |
293 plane_a = context->tmp_buf_a + 8 - (context->hscroll_a & 0x7); | 296 plane_a = context->tmp_buf_a + SCROLL_BUFFER_DRAW - (context->hscroll_a & 0xF); |
294 plane_b = context->tmp_buf_b + 8 - (context->hscroll_b & 0x7); | 297 plane_b = context->tmp_buf_b + SCROLL_BUFFER_DRAW - (context->hscroll_b & 0xF); |
295 end = dst + 16; | 298 end = dst + 16; |
296 //printf("A | tmp_buf offset: %d\n", 8 - (context->hscroll_a & 0x7)); | 299 //printf("A | tmp_buf offset: %d\n", 8 - (context->hscroll_a & 0x7)); |
297 for (; dst < end; ++plane_a, ++plane_b, ++sprite_buf, ++dst) { | 300 for (; dst < end; ++plane_a, ++plane_b, ++sprite_buf, ++dst) { |
298 uint8_t pixel; | 301 uint8_t pixel; |
299 if (*sprite_buf & BUF_BIT_PRIORITY && *sprite_buf & 0xF) { | 302 if (*sprite_buf & BUF_BIT_PRIORITY && *sprite_buf & 0xF) { |
319 //plane_a = context->tmp_buf_a + 16 - (context->hscroll_a & 0x7); | 322 //plane_a = context->tmp_buf_a + 16 - (context->hscroll_a & 0x7); |
320 //plane_b = context->tmp_buf_b + 16 - (context->hscroll_b & 0x7); | 323 //plane_b = context->tmp_buf_b + 16 - (context->hscroll_b & 0x7); |
321 //end = dst + 8; | 324 //end = dst + 8; |
322 } | 325 } |
323 | 326 |
324 uint16_t remaining = context->hscroll_a & 0x7; | 327 uint16_t remaining = context->hscroll_a & 0xF; |
325 memcpy(context->tmp_buf_a + 8 - remaining, context->tmp_buf_a + 24 - remaining, remaining); | 328 memcpy(context->tmp_buf_a + SCROLL_BUFFER_DRAW - remaining, context->tmp_buf_a + SCROLL_BUFFER_SIZE - remaining, remaining); |
326 remaining = context->hscroll_b & 0x7; | 329 remaining = context->hscroll_b & 0xF; |
327 memcpy(context->tmp_buf_b + 8 - remaining, context->tmp_buf_b + 24 - remaining, remaining); | 330 memcpy(context->tmp_buf_b + SCROLL_BUFFER_DRAW - remaining, context->tmp_buf_b + SCROLL_BUFFER_SIZE - remaining, remaining); |
328 } | 331 } |
329 | 332 |
330 #define COLUMN_RENDER_BLOCK(column, startcyc) \ | 333 #define COLUMN_RENDER_BLOCK(column, startcyc) \ |
331 case startcyc:\ | 334 case startcyc:\ |
332 read_map_scroll_a(column, line, context);\ | 335 read_map_scroll_a(column, line, context);\ |
452 } | 455 } |
453 line &= mask; | 456 line &= mask; |
454 address += line * 4; | 457 address += line * 4; |
455 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1]; | 458 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1]; |
456 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3]; | 459 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3]; |
457 //printf("%d: HScroll A: %d, HScroll B: %d\n", line, context->hscroll_a, context->hscroll_b); | 460 printf("%d: HScroll A: %d, HScroll B: %d\n", line, context->hscroll_a, context->hscroll_b); |
458 break; | 461 break; |
459 case 36: | 462 case 36: |
460 //!HSYNC high | 463 //!HSYNC high |
461 case 37: | 464 case 37: |
462 case 38: | 465 case 38: |