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: