comparison blastem.c @ 288:a8ee7934a1f8

Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
author Mike Pavone <pavone@retrodev.com>
date Sun, 05 May 2013 22:56:42 -0700
parents 9ee64039ddeb
children 1cc0850ab6bc
comparison
equal deleted inserted replaced
287:fb840e0a48cd 288:a8ee7934a1f8
163 } 163 }
164 164
165 m68k_context * sync_components(m68k_context * context, uint32_t address) 165 m68k_context * sync_components(m68k_context * context, uint32_t address)
166 { 166 {
167 //TODO: Handle sync targets smaller than a single frame 167 //TODO: Handle sync targets smaller than a single frame
168 vdp_context * v_context = context->video_context; 168 genesis_context * gen = context->system;
169 z80_context * z_context = context->next_cpu; 169 vdp_context * v_context = gen->vdp;
170 z80_context * z_context = gen->z80;
170 uint32_t mclks = context->current_cycle * MCLKS_PER_68K; 171 uint32_t mclks = context->current_cycle * MCLKS_PER_68K;
171 sync_z80(z_context, mclks); 172 sync_z80(z_context, mclks);
172 if (mclks >= MCLKS_PER_FRAME) { 173 if (mclks >= MCLKS_PER_FRAME) {
174 ym_run(gen->ym, context->current_cycle);
175 gen->ym->current_cycle -= MCLKS_PER_FRAME/MCLKS_PER_68K;
173 //printf("reached frame end | 68K Cycles: %d, MCLK Cycles: %d\n", context->current_cycle, mclks); 176 //printf("reached frame end | 68K Cycles: %d, MCLK Cycles: %d\n", context->current_cycle, mclks);
174 vdp_run_context(v_context, MCLKS_PER_FRAME); 177 vdp_run_context(v_context, MCLKS_PER_FRAME);
175 if (!headless) { 178 if (!headless) {
176 break_on_sync |= wait_render_frame(v_context); 179 break_on_sync |= wait_render_frame(v_context);
177 } 180 }
352 355
353 uint32_t zram_counter = 0; 356 uint32_t zram_counter = 0;
354 357
355 m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value) 358 m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value)
356 { 359 {
360 genesis_context * gen = context->system;
357 if (location < 0x10000) { 361 if (location < 0x10000) {
358 if (busack_cycle > context->current_cycle) { 362 if (busack_cycle > context->current_cycle) {
359 busack = new_busack; 363 busack = new_busack;
360 busack_cycle = CYCLE_NEVER; 364 busack_cycle = CYCLE_NEVER;
361 } 365 }
362 if (!(busack || reset)) { 366 if (!(busack || reset)) {
363 location &= 0x7FFF; 367 location &= 0x7FFF;
364 if (location < 0x4000) { 368 if (location < 0x4000) {
365 z80_ram[location & 0x1FFF] = value; 369 z80_ram[location & 0x1FFF] = value;
366 z80_handle_code_write(location & 0x1FFF, context->next_cpu); 370 z80_handle_code_write(location & 0x1FFF, gen->z80);
371 } else if (location < 0x6000) {
372 ym_run(gen->ym, context->current_cycle);
373 if (location & 1) {
374 ym_data_write(gen->ym, value);
375 } else if(location & 2) {
376 ym_address_write_part2(gen->ym, value);
377 } else {
378 ym_address_write_part1(gen->ym, value);
379 }
367 } 380 }
368 } 381 }
369 } else { 382 } else {
370 location &= 0x1FFF; 383 location &= 0x1FFF;
371 if (location < 0x100) { 384 if (location < 0x100) {
386 gamepad_2.control = value; 399 gamepad_2.control = value;
387 break; 400 break;
388 } 401 }
389 } else { 402 } else {
390 if (location == 0x1100) { 403 if (location == 0x1100) {
391 sync_z80(context->next_cpu, context->current_cycle * MCLKS_PER_68K); 404 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K);
392 if (busack_cycle > context->current_cycle) { 405 if (busack_cycle > context->current_cycle) {
393 busack = new_busack; 406 busack = new_busack;
394 busack_cycle = CYCLE_NEVER; 407 busack_cycle = CYCLE_NEVER;
395 } 408 }
396 if (value & 1) { 409 if (value & 1) {
408 sprintf(fname, "zram-%d", zram_counter++); 421 sprintf(fname, "zram-%d", zram_counter++);
409 FILE * f = fopen(fname, "wb"); 422 FILE * f = fopen(fname, "wb");
410 fwrite(z80_ram, 1, sizeof(z80_ram), f); 423 fwrite(z80_ram, 1, sizeof(z80_ram), f);
411 fclose(f); 424 fclose(f);
412 #endif 425 #endif
413 z80_context * z_context = context->next_cpu;
414 //TODO: Add necessary delay between release of busreq and resumption of execution 426 //TODO: Add necessary delay between release of busreq and resumption of execution
415 z_context->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80; 427 gen->z80->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80;
416 } 428 }
417 busreq = 0; 429 busreq = 0;
418 busack_cycle = CYCLE_NEVER; 430 busack_cycle = CYCLE_NEVER;
419 busack = 1; 431 busack = 1;
420 } 432 }
421 } else if (location == 0x1200) { 433 } else if (location == 0x1200) {
422 sync_z80(context->next_cpu, context->current_cycle * MCLKS_PER_68K); 434 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K);
423 if (value & 1) { 435 if (value & 1) {
424 if (reset && busreq) { 436 if (reset && busreq) {
425 new_busack = 0; 437 new_busack = 0;
426 busack_cycle = context->current_cycle + Z80_ACK_DELAY; 438 busack_cycle = context->current_cycle + Z80_ACK_DELAY;
427 } 439 }
428 //TODO: Deal with the scenario in which reset is not asserted long enough 440 //TODO: Deal with the scenario in which reset is not asserted long enough
429 if (reset) { 441 if (reset) {
430 z80_context * z_context = context->next_cpu;
431 need_reset = 1; 442 need_reset = 1;
432 //TODO: Add necessary delay between release of reset and start of execution 443 //TODO: Add necessary delay between release of reset and start of execution
433 z_context->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80; 444 gen->z80->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80;
434 } 445 }
435 reset = 0; 446 reset = 0;
436 } else { 447 } else {
437 reset = 1; 448 reset = 1;
438 } 449 }
442 return context; 453 return context;
443 } 454 }
444 455
445 m68k_context * io_write_w(uint32_t location, m68k_context * context, uint16_t value) 456 m68k_context * io_write_w(uint32_t location, m68k_context * context, uint16_t value)
446 { 457 {
458 genesis_context * gen = context->system;
447 if (location < 0x10000) { 459 if (location < 0x10000) {
448 if (busack_cycle > context->current_cycle) { 460 if (busack_cycle > context->current_cycle) {
449 busack = new_busack; 461 busack = new_busack;
450 busack_cycle = CYCLE_NEVER; 462 busack_cycle = CYCLE_NEVER;
451 } 463 }
452 if (!(busack || reset)) { 464 if (!(busack || reset)) {
453 location &= 0x7FFF; 465 location &= 0x7FFF;
454 if (location < 0x4000) { 466 if (location < 0x4000) {
455 z80_ram[location & 0x1FFE] = value >> 8; 467 z80_ram[location & 0x1FFE] = value >> 8;
456 z80_handle_code_write(location & 0x1FFE, context->next_cpu); 468 z80_handle_code_write(location & 0x1FFE, gen->z80);
469 } else if (location < 0x6000) {
470 ym_run(gen->ym, context->current_cycle);
471 if (location & 1) {
472 ym_data_write(gen->ym, value >> 8);
473 } else if(location & 2) {
474 ym_address_write_part2(gen->ym, value >> 8);
475 } else {
476 ym_address_write_part1(gen->ym, value >> 8);
477 }
457 } 478 }
458 } 479 }
459 } else { 480 } else {
460 location &= 0x1FFF; 481 location &= 0x1FFF;
461 if (location < 0x100) { 482 if (location < 0x100) {
477 break; 498 break;
478 } 499 }
479 } else { 500 } else {
480 //printf("IO Write of %X to %X @ %d\n", value, location, context->current_cycle); 501 //printf("IO Write of %X to %X @ %d\n", value, location, context->current_cycle);
481 if (location == 0x1100) { 502 if (location == 0x1100) {
482 sync_z80(context->next_cpu, context->current_cycle * MCLKS_PER_68K); 503 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K);
483 if (busack_cycle > context->current_cycle) { 504 if (busack_cycle > context->current_cycle) {
484 busack = new_busack; 505 busack = new_busack;
485 busack_cycle = CYCLE_NEVER; 506 busack_cycle = CYCLE_NEVER;
486 } 507 }
487 if (value & 0x100) { 508 if (value & 0x100) {
499 sprintf(fname, "zram-%d", zram_counter++); 520 sprintf(fname, "zram-%d", zram_counter++);
500 FILE * f = fopen(fname, "wb"); 521 FILE * f = fopen(fname, "wb");
501 fwrite(z80_ram, 1, sizeof(z80_ram), f); 522 fwrite(z80_ram, 1, sizeof(z80_ram), f);
502 fclose(f); 523 fclose(f);
503 #endif 524 #endif
504 z80_context * z_context = context->next_cpu;
505 //TODO: Add necessary delay between release of busreq and resumption of execution 525 //TODO: Add necessary delay between release of busreq and resumption of execution
506 z_context->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80; 526 gen->z80->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80;
507 } 527 }
508 busreq = 0; 528 busreq = 0;
509 busack_cycle = CYCLE_NEVER; 529 busack_cycle = CYCLE_NEVER;
510 busack = 1; 530 busack = 1;
511 } 531 }
512 } else if (location == 0x1200) { 532 } else if (location == 0x1200) {
513 sync_z80(context->next_cpu, context->current_cycle * MCLKS_PER_68K); 533 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K);
514 if (value & 0x100) { 534 if (value & 0x100) {
515 if (reset && busreq) { 535 if (reset && busreq) {
516 new_busack = 0; 536 new_busack = 0;
517 busack_cycle = context->current_cycle + Z80_ACK_DELAY; 537 busack_cycle = context->current_cycle + Z80_ACK_DELAY;
518 } 538 }
519 //TODO: Deal with the scenario in which reset is not asserted long enough 539 //TODO: Deal with the scenario in which reset is not asserted long enough
520 if (reset) { 540 if (reset) {
521 z80_context * z_context = context->next_cpu;
522 need_reset = 1; 541 need_reset = 1;
523 //TODO: Add necessary delay between release of reset and start of execution 542 //TODO: Add necessary delay between release of reset and start of execution
524 z_context->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80; 543 gen->z80->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80;
525 } 544 }
526 reset = 0; 545 reset = 0;
527 } else { 546 } else {
528 reset = 1; 547 reset = 1;
529 } 548 }
539 #define NO_DISK 0x20 558 #define NO_DISK 0x20
540 uint8_t version_reg = NO_DISK | USA; 559 uint8_t version_reg = NO_DISK | USA;
541 560
542 m68k_context * io_read(uint32_t location, m68k_context * context) 561 m68k_context * io_read(uint32_t location, m68k_context * context)
543 { 562 {
563 genesis_context *gen = context->system;
544 if (location < 0x10000) { 564 if (location < 0x10000) {
545 if (busack_cycle > context->current_cycle) { 565 if (busack_cycle > context->current_cycle) {
546 busack = new_busack; 566 busack = new_busack;
547 busack_cycle = CYCLE_NEVER; 567 busack_cycle = CYCLE_NEVER;
548 } 568 }
549 if (!(busack || reset)) { 569 if (!(busack || reset)) {
550 location &= 0x7FFF; 570 location &= 0x7FFF;
551 if (location < 0x4000) { 571 if (location < 0x4000) {
552 context->value = z80_ram[location & 0x1FFF]; 572 context->value = z80_ram[location & 0x1FFF];
573 } else if (location < 0x6000) {
574 ym_run(gen->ym, context->current_cycle);
575 context->value = ym_read_status(gen->ym);
553 } else { 576 } else {
554 context->value = 0xFF; 577 context->value = 0xFF;
555 } 578 }
556 } else { 579 } else {
557 context->value = 0xFF; 580 context->value = 0xFF;
599 return context; 622 return context;
600 } 623 }
601 624
602 m68k_context * io_read_w(uint32_t location, m68k_context * context) 625 m68k_context * io_read_w(uint32_t location, m68k_context * context)
603 { 626 {
627 genesis_context * gen = context->system;
604 if (location < 0x10000) { 628 if (location < 0x10000) {
605 if (busack_cycle > context->current_cycle) { 629 if (busack_cycle > context->current_cycle) {
606 busack = new_busack; 630 busack = new_busack;
607 busack_cycle = CYCLE_NEVER; 631 busack_cycle = CYCLE_NEVER;
608 } 632 }
609 if (!(busack || reset)) { 633 if (!(busack || reset)) {
610 location &= 0x7FFF; 634 location &= 0x7FFF;
635 uint16_t value;
611 if (location < 0x4000) { 636 if (location < 0x4000) {
612 context->value = z80_ram[location & 0x1FFE]; 637 value = z80_ram[location & 0x1FFE];
613 context->value |= context->value << 8; 638 } else if (location < 0x6000) {
639 ym_run(gen->ym, context->current_cycle);
640 value = ym_read_status(gen->ym);
614 } else { 641 } else {
615 context->value = 0xFFFF; 642 value = 0xFF;
616 } 643 }
644 context->value = value | (value << 8);
617 } else { 645 } else {
618 context->value = 0xFFFF; 646 context->value = 0xFFFF;
619 } 647 }
620 } else { 648 } else {
621 location &= 0x1FFF; 649 location &= 0x1FFF;
892 } 920 }
893 } 921 }
894 return context; 922 return context;
895 } 923 }
896 924
897 void init_run_cpu(vdp_context * vcontext, z80_context * zcontext, int debug, FILE * address_log) 925 void init_run_cpu(genesis_context * gen, int debug, FILE * address_log)
898 { 926 {
899 m68k_context context; 927 m68k_context context;
900 x86_68k_options opts; 928 x86_68k_options opts;
929 gen->m68k = &context;
901 init_x86_68k_opts(&opts); 930 init_x86_68k_opts(&opts);
902 opts.address_log = address_log; 931 opts.address_log = address_log;
903 init_68k_context(&context, opts.native_code_map, &opts); 932 init_68k_context(&context, opts.native_code_map, &opts);
904 933
905 context.video_context = vcontext; 934 context.video_context = gen->vdp;
906 context.next_cpu = zcontext; 935 context.system = gen;
907 //cartridge ROM 936 //cartridge ROM
908 context.mem_pointers[0] = cart; 937 context.mem_pointers[0] = cart;
909 context.target_cycle = context.sync_cycle = MCLKS_PER_FRAME/MCLKS_PER_68K; 938 context.target_cycle = context.sync_cycle = MCLKS_PER_FRAME/MCLKS_PER_68K;
910 //work RAM 939 //work RAM
911 context.mem_pointers[1] = ram; 940 context.mem_pointers[1] = ram;
970 } 999 }
971 vdp_context v_context; 1000 vdp_context v_context;
972 1001
973 init_vdp_context(&v_context); 1002 init_vdp_context(&v_context);
974 1003
1004 ym2612_context y_context;
1005 ym_init(&y_context);
1006
975 z80_context z_context; 1007 z80_context z_context;
976 x86_z80_options z_opts; 1008 x86_z80_options z_opts;
977 init_x86_z80_opts(&z_opts); 1009 init_x86_z80_opts(&z_opts);
978 init_z80_context(&z_context, &z_opts); 1010 init_z80_context(&z_context, &z_opts);
979 z_context.next_context = &v_context; 1011 z_context.next_context = &v_context;
980 z_context.mem_pointers[0] = z80_ram; 1012 z_context.mem_pointers[0] = z80_ram;
981 z_context.sync_cycle = z_context.target_cycle = MCLKS_PER_FRAME/MCLKS_PER_Z80; 1013 z_context.sync_cycle = z_context.target_cycle = MCLKS_PER_FRAME/MCLKS_PER_Z80;
982 z_context.int_cycle = CYCLE_NEVER; 1014 z_context.int_cycle = CYCLE_NEVER;
983 z_context.mem_pointers[1] = z_context.mem_pointers[2] = (uint8_t *)cart; 1015 z_context.mem_pointers[1] = z_context.mem_pointers[2] = (uint8_t *)cart;
984 1016
985 init_run_cpu(&v_context, &z_context, debug, address_log); 1017 genesis_context gen;
1018 gen.z80 = &z_context;
1019 gen.vdp = &v_context;
1020 gen.ym = &y_context;
1021
1022 init_run_cpu(&gen, debug, address_log);
986 return 0; 1023 return 0;
987 } 1024 }