comparison jaguar.c @ 1097:faa3a4617f62

Get Jaguar video interrupt working
author Michael Pavone <pavone@retrodev.com>
date Sat, 05 Nov 2016 00:23:11 -0700
parents 1dba006bad47
children 653558f6fa7a
comparison
equal deleted inserted replaced
1096:1ab30d427db8 1097:faa3a4617f62
1 #include <stdint.h> 1 #include <stdint.h>
2 #include <stdio.h> 2 #include <stdio.h>
3 #include <stddef.h> 3 #include <stddef.h>
4 #include <stdlib.h> 4 #include <stdlib.h>
5 #include "m68k_core.h" 5 #include "m68k_core.h"
6 #include "68kinst.h"
6 #include "jaguar.h" 7 #include "jaguar.h"
7 #include "util.h" 8 #include "util.h"
8 #include "debug.h" 9 #include "debug.h"
9 #include "config.h" 10 #include "config.h"
10 #include "render.h" 11 #include "render.h"
56 57
57 void handle_mouse_moved(int mouse, uint16_t x, uint16_t y, int16_t deltax, int16_t deltay) 58 void handle_mouse_moved(int mouse, uint16_t x, uint16_t y, int16_t deltax, int16_t deltay)
58 { 59 {
59 } 60 }
60 61
62 void jag_update_m68k_int(jaguar_context *system)
63 {
64 m68k_context *m68k = system->m68k;
65 if (m68k->sync_cycle - m68k->current_cycle > system->max_cycles) {
66 m68k->sync_cycle = m68k->current_cycle + system->max_cycles;
67 }
68 //TODO: Support other interrupt sources
69 if (!system->cpu_int_control || (m68k->status & 0x7)) {
70 m68k->int_cycle = CYCLE_NEVER;
71 } else if(system->cpu_int_control & system->video->cpu_int_pending) {
72 m68k->int_cycle = m68k->current_cycle;
73 //supposedly all interrupts on the jaguar are "level 0" autovector interrupts
74 //which I assume means they're abusing the "spurious interrupt" vector
75 m68k->int_num = VECTOR_USER0 - VECTOR_SPURIOUS_INTERRUPT;
76 } else {
77 m68k->int_cycle = jag_next_vid_interrupt(system->video);
78 m68k->int_num = VECTOR_USER0 - VECTOR_SPURIOUS_INTERRUPT;
79 }
80
81 if (m68k->int_cycle > m68k->current_cycle && m68k->int_pending == INT_PENDING_SR_CHANGE) {
82 m68k->int_pending = INT_PENDING_NONE;
83 }
84
85 m68k->target_cycle = m68k->int_cycle < m68k->sync_cycle ? m68k->int_cycle : m68k->sync_cycle;
86 if (m68k->should_return) {
87 m68k->target_cycle = m68k->current_cycle;
88 } else if (m68k->target_cycle < m68k->current_cycle) {
89 //Changes to SR can result in an interrupt cycle that's in the past
90 //This can cause issues with the implementation of STOP though
91 m68k->target_cycle = m68k->current_cycle;
92 }
93 }
61 94
62 void rom0_write_16(uint32_t address, jaguar_context *system, uint16_t value) 95 void rom0_write_16(uint32_t address, jaguar_context *system, uint16_t value)
63 { 96 {
64 //TODO: Use write_latch and write_pending to turn two 16-bit writes into a 32-bit one 97 //TODO: Use write_latch and write_pending to turn two 16-bit writes into a 32-bit one
65 //Documentation heavily suggests that writes to most registers should be 32-bits wide 98 //Documentation heavily suggests that writes to most registers should be 32-bits wide
109 system->memcon1 = value; 142 system->memcon1 = value;
110 break; 143 break;
111 case 2: 144 case 2:
112 system->memcon2 = value; 145 system->memcon2 = value;
113 break; 146 break;
147 case 0xE0:
148 printf("INT1 write: %X\n", value);
149 system->cpu_int_control = value & 0x1F;
150 system->video->cpu_int_pending &= ~(value >> 8);
151 //TODO: apply mask to int pending fields on other components once they are implemented
152 break;
153 case 0xE2:
154 //no real handling of bus conflicts presently, so this doesn't really need to do anything yet
155 printf("INT2 write: %X\n", value);
156 break;
114 default: 157 default:
115 jag_video_reg_write(system->video, address, value); 158 jag_video_reg_write(system->video, address, value);
159 jag_update_m68k_int(system);
116 break; 160 break;
117 } 161 }
118 } else if (address < 0x100800) { 162 } else if (address < 0x100800) {
119 //CLUT 163 //CLUT
120 address = address >> 1 & 255; 164 address = address >> 1 & 255;
142 //GPU/Blitter registers 186 //GPU/Blitter registers
143 if (address < 0x102200) { 187 if (address < 0x102200) {
144 fprintf(stderr, "Unhandled write to GPU registers %X: %X\n", address, value); 188 fprintf(stderr, "Unhandled write to GPU registers %X: %X\n", address, value);
145 if (address == 0x102116 && (value & 1)) { 189 if (address == 0x102116 && (value & 1)) {
146 FILE *f = fopen("gpu.bin", "wb"); 190 FILE *f = fopen("gpu.bin", "wb");
147 fwrite(system->gpu_local, 1, sizeof(system->gpu_local), f); 191 uint8_t buf[4];
192 for (int i = 0; i < GPU_RAM_BYTES/sizeof(uint32_t); i++)
193 {
194 buf[0] = system->gpu_local[i] >> 24;
195 buf[1] = system->gpu_local[i] >> 16;
196 buf[2] = system->gpu_local[i] >> 8;
197 buf[3] = system->gpu_local[i];
198 fwrite(buf, 1, sizeof(buf), f);
199 }
148 fclose(f); 200 fclose(f);
149 } 201 }
150 } else { 202 } else {
151 fprintf(stderr, "Unhandled write to Blitter registers %X: %X\n", address, value); 203 fprintf(stderr, "Unhandled write to Blitter registers %X: %X\n", address, value);
152 } 204 }
153 } 205 }
154 } else if (address < 0x11A100) { 206 } else if (address < 0x11A100) {
155 if (address < 0x110000) { 207 if (address < 0x110000) {
156 //GPU Local RAM 208 //GPU Local RAM
157 uint32_t offset = address >> 2 & (GPU_RAM_BYTES / sizeof(uint32_t) - 1); 209 uint32_t offset = address >> 2 & (GPU_RAM_BYTES / sizeof(uint32_t) - 1);
158 uint32_t value32 = value; 210 uint32_t value32 = value;
159 if (address & 2) { 211 if (address & 2) {
160 system->gpu_local[offset] &= 0xFFFF0000; 212 system->gpu_local[offset] &= 0xFFFF0000;
161 } else { 213 } else {
162 system->gpu_local[offset] &= 0x0000FFFF; 214 system->gpu_local[offset] &= 0x0000FFFF;
199 } 251 }
200 if (address < 0x103000) { 252 if (address < 0x103000) {
201 if (address < 0x101000) { 253 if (address < 0x101000) {
202 if (address < 0x100400) { 254 if (address < 0x100400) {
203 //Video mode / Memory control registers 255 //Video mode / Memory control registers
204 fprintf(stderr, "Unhandled read from video mode/memory control registers - %X\n", address); 256 switch (address & 0x3FE)
257 {
258 case 0xE0:
259 puts("INT1 read");
260 //TODO: Bitwise or with cpu_int_pending fields from other components once implemented
261 return system->video->cpu_int_pending;
262 break;
263 default:
264 fprintf(stderr, "Unhandled read from video mode/memory control registers - %X\n", address);
265 }
205 } else if (address < 0x100800) { 266 } else if (address < 0x100800) {
206 //CLUT 267 //CLUT
207 address = address >> 1 & 255; 268 address = address >> 1 & 255;
208 return system->video->clut[address]; 269 return system->video->clut[address];
209 } else { 270 } else {
375 436
376 m68k_context * sync_components(m68k_context * context, uint32_t address) 437 m68k_context * sync_components(m68k_context * context, uint32_t address)
377 { 438 {
378 jaguar_context *system = context->system; 439 jaguar_context *system = context->system;
379 jag_video_run(system->video, context->current_cycle); 440 jag_video_run(system->video, context->current_cycle);
441 jag_update_m68k_int(system);
380 if (context->current_cycle > 0x10000000) { 442 if (context->current_cycle > 0x10000000) {
381 context->current_cycle -= 0x10000000; 443 context->current_cycle -= 0x10000000;
382 system->video->cycles -= 0x10000000; 444 system->video->cycles -= 0x10000000;
383 } 445 }
446 if (context->int_ack) {
447 context->int_ack = 0;
448 //hack until 68K core more properly supports non-autovector interrupts
449 context->status |= 1;
450 }
451 jag_update_m68k_int(system);
384 return context; 452 return context;
385 } 453 }
386 454
387 455
388 void *rom0_write_m68k(uint32_t address, void *context, uint16_t value) 456 void *rom0_write_m68k(uint32_t address, void *context, uint16_t value)
429 jaguar_context *system = calloc(1, sizeof(jaguar_context)); 497 jaguar_context *system = calloc(1, sizeof(jaguar_context));
430 system->bios = bios; 498 system->bios = bios;
431 system->bios_size = bios_size; 499 system->bios_size = bios_size;
432 system->cart = cart; 500 system->cart = cart;
433 system->cart_size = cart_size; 501 system->cart_size = cart_size;
502 //TODO: Figure out a better default for this and make it configurable
503 system->max_cycles = 3000;
434 504
435 memmap_chunk *jag_m68k_map = calloc(8, sizeof(memmap_chunk)); 505 memmap_chunk *jag_m68k_map = calloc(8, sizeof(memmap_chunk));
436 for (uint32_t start = 0, index=0; index < 8; index++, start += 0x200000) 506 for (uint32_t start = 0, index=0; index < 8; index++, start += 0x200000)
437 { 507 {
438 jag_m68k_map[index].start = start; 508 jag_m68k_map[index].start = start;
448 jag_m68k_map[index].write_8 = rom0_write_m68k_b; 518 jag_m68k_map[index].write_8 = rom0_write_m68k_b;
449 } 519 }
450 m68k_options *opts = malloc(sizeof(m68k_options)); 520 m68k_options *opts = malloc(sizeof(m68k_options));
451 init_m68k_opts(opts, jag_m68k_map, 8, 2); 521 init_m68k_opts(opts, jag_m68k_map, 8, 2);
452 system->m68k = init_68k_context(opts, handle_m68k_reset); 522 system->m68k = init_68k_context(opts, handle_m68k_reset);
523 system->m68k->sync_cycle = system->max_cycles;
453 system->m68k->system = system; 524 system->m68k->system = system;
454 system->video = jag_video_init(); 525 system->video = jag_video_init();
455 system->video->system = system; 526 system->video->system = system;
456 return system; 527 return system;
457 } 528 }