comparison vdp.c @ 1151:681e8a13b261

Fix some issues with VDP interface in Mode 4/PBC mode
author Michael Pavone <pavone@retrodev.com>
date Wed, 04 Jan 2017 22:48:00 -0800
parents 322d28e6f13c
children ddbb61be6119
comparison
equal deleted inserted replaced
1150:322d28e6f13c 1151:681e8a13b261
179 //TODO: Figure out which slots are refresh when display is off in 32-cell mode 179 //TODO: Figure out which slots are refresh when display is off in 32-cell mode
180 //These numbers are guesses based on H40 numbers 180 //These numbers are guesses based on H40 numbers
181 return slot == 243 || slot == 19 || slot == 51 || slot == 83 || slot == 115; 181 return slot == 243 || slot == 19 || slot == 51 || slot == 83 || slot == 115;
182 //The numbers below are the refresh slots during active display 182 //The numbers below are the refresh slots during active display
183 //return (slot == 29 || slot == 61 || slot == 93 || slot == 125); 183 //return (slot == 29 || slot == 61 || slot == 93 || slot == 125);
184 }
185 }
186
187 static void increment_address(vdp_context *context)
188 {
189 context->address += context->regs[REG_AUTOINC];
190 if (!(context->regs[REG_MODE_2] & BIT_MODE_5)) {
191 context->address++;
184 } 192 }
185 } 193 }
186 194
187 static void render_sprite_cells(vdp_context * context) 195 static void render_sprite_cells(vdp_context * context)
188 { 196 {
781 if (context->flags2 & FLAG2_READ_PENDING) { 789 if (context->flags2 & FLAG2_READ_PENDING) {
782 context->prefetch |= context->vdpmem[context->address | 1]; 790 context->prefetch |= context->vdpmem[context->address | 1];
783 context->flags |= FLAG_READ_FETCHED; 791 context->flags |= FLAG_READ_FETCHED;
784 context->flags2 &= ~FLAG2_READ_PENDING; 792 context->flags2 &= ~FLAG2_READ_PENDING;
785 //Should this happen after the prefetch or after the read? 793 //Should this happen after the prefetch or after the read?
786 //context->address += context->regs[REG_AUTOINC]; 794 //increment_address(context);
787 } else { 795 } else {
788 context->prefetch = context->vdpmem[context->address & 0xFFFE] << 8; 796 context->prefetch = context->vdpmem[context->address & 0xFFFE] << 8;
789 context->flags2 |= FLAG2_READ_PENDING; 797 context->flags2 |= FLAG2_READ_PENDING;
790 } 798 }
791 break; 799 break;
792 case VRAM_READ8: 800 case VRAM_READ8: {
793 context->prefetch = context->vdpmem[context->address ^ 1]; 801 uint32_t address = context->address ^ 1;
802 if (!(context->regs[REG_MODE_2] & BIT_MODE_5)) {
803 address = mode4_address_map[address & 0x3FFF];
804 }
805 context->prefetch = context->vdpmem[address];
794 context->prefetch |= context->fifo[context->fifo_write].value & 0xFF00; 806 context->prefetch |= context->fifo[context->fifo_write].value & 0xFF00;
795 context->flags |= FLAG_READ_FETCHED; 807 context->flags |= FLAG_READ_FETCHED;
796 //Should this happen after the prefetch or after the read? 808 //Should this happen after the prefetch or after the read?
797 //context->address += context->regs[REG_AUTOINC]; 809 //increment_address(context);
798 break; 810 break;
811 }
799 case CRAM_READ: 812 case CRAM_READ:
800 context->prefetch = context->cram[(context->address/2) & (CRAM_SIZE-1)] & CRAM_BITS; 813 context->prefetch = context->cram[(context->address/2) & (CRAM_SIZE-1)] & CRAM_BITS;
801 context->prefetch |= context->fifo[context->fifo_write].value & ~CRAM_BITS; 814 context->prefetch |= context->fifo[context->fifo_write].value & ~CRAM_BITS;
802 context->flags |= FLAG_READ_FETCHED; 815 context->flags |= FLAG_READ_FETCHED;
803 //Should this happen after the prefetch or after the read? 816 //Should this happen after the prefetch or after the read?
804 //context->address += context->regs[REG_AUTOINC]; 817 //increment_address(context);
805 break; 818 break;
806 case VSRAM_READ: { 819 case VSRAM_READ: {
807 uint16_t address = (context->address /2) & 63; 820 uint16_t address = (context->address /2) & 63;
808 if (address >= VSRAM_SIZE) { 821 if (address >= VSRAM_SIZE) {
809 address = 0; 822 address = 0;
810 } 823 }
811 context->prefetch = context->vsram[address] & VSRAM_BITS; 824 context->prefetch = context->vsram[address] & VSRAM_BITS;
812 context->prefetch |= context->fifo[context->fifo_write].value & VSRAM_DIRTY_BITS; 825 context->prefetch |= context->fifo[context->fifo_write].value & VSRAM_DIRTY_BITS;
813 context->flags |= FLAG_READ_FETCHED; 826 context->flags |= FLAG_READ_FETCHED;
814 //Should this happen after the prefetch or after the read? 827 //Should this happen after the prefetch or after the read?
815 //context->address += context->regs[REG_AUTOINC]; 828 //increment_address(context);
816 break; 829 break;
817 } 830 }
818 } 831 }
819 } 832 }
820 } 833 }
2161 //printf("DMA Fill Address: %X, New CD: %X\n", context->address, context->cd); 2174 //printf("DMA Fill Address: %X, New CD: %X\n", context->address, context->cd);
2162 } 2175 }
2163 } 2176 }
2164 } else { 2177 } else {
2165 uint8_t mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5; 2178 uint8_t mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5;
2179 context->address = (context->address &0xC000) | (value & 0x3FFF);
2180 //Genesis Plus GX doesn't clear out the mode bits in Mode 4, but instead
2181 //ignores the uppper mode bits when it comes to reads/writes
2182 //testing on hardware is needed to determine which is truly correct
2183 context->cd = (mode_5 ? context->cd &0x3C : 0) | (value >> 14);
2166 if ((value & 0xC000) == 0x8000) { 2184 if ((value & 0xC000) == 0x8000) {
2167 //Register write 2185 //Register write
2168 uint8_t reg = (value >> 8) & 0x1F; 2186 uint8_t reg = (value >> 8) & 0x1F;
2169 if (reg < (mode_5 ? VDP_REGS : 0xB)) { 2187 if (reg < (mode_5 ? VDP_REGS : 0xB)) {
2170 //printf("register %d set to %X\n", reg, value & 0xFF); 2188 //printf("register %d set to %X\n", reg, value & 0xFF);
2182 context->double_res = (value & (BIT_INTERLACE | BIT_DOUBLE_RES)) == (BIT_INTERLACE | BIT_DOUBLE_RES); 2200 context->double_res = (value & (BIT_INTERLACE | BIT_DOUBLE_RES)) == (BIT_INTERLACE | BIT_DOUBLE_RES);
2183 if (!context->double_res) { 2201 if (!context->double_res) {
2184 context->flags2 &= ~FLAG2_EVEN_FIELD; 2202 context->flags2 &= ~FLAG2_EVEN_FIELD;
2185 } 2203 }
2186 } 2204 }
2187 context->cd &= 0x3C;
2188 } 2205 }
2189 } else if (mode_5) { 2206 } else if (mode_5) {
2190 context->flags |= FLAG_PENDING; 2207 context->flags |= FLAG_PENDING;
2191 context->address = (context->address &0xC000) | (value & 0x3FFF);
2192 context->cd = (context->cd &0x3C) | (value >> 14);
2193 //Should these be taken care of here or after the second write? 2208 //Should these be taken care of here or after the second write?
2194 //context->flags &= ~FLAG_READ_FETCHED; 2209 //context->flags &= ~FLAG_READ_FETCHED;
2195 //context->flags2 &= ~FLAG2_READ_PENDING; 2210 //context->flags2 &= ~FLAG2_READ_PENDING;
2196 } else { 2211 } else {
2197 context->address = value & 0x3FFF;
2198 context->cd = value >> 14;
2199 context->flags &= ~FLAG_READ_FETCHED; 2212 context->flags &= ~FLAG_READ_FETCHED;
2200 context->flags2 &= ~FLAG2_READ_PENDING; 2213 context->flags2 &= ~FLAG2_READ_PENDING;
2201 } 2214 }
2202 } 2215 }
2203 return 0; 2216 return 0;
2208 if (context->flags2 & FLAG2_BYTE_PENDING) { 2221 if (context->flags2 & FLAG2_BYTE_PENDING) {
2209 uint16_t full_val = value << 8 | context->pending_byte; 2222 uint16_t full_val = value << 8 | context->pending_byte;
2210 context->flags2 &= ~FLAG2_BYTE_PENDING; 2223 context->flags2 &= ~FLAG2_BYTE_PENDING;
2211 //TODO: Deal with fact that Vbus->VDP DMA doesn't do anything in PBC mode 2224 //TODO: Deal with fact that Vbus->VDP DMA doesn't do anything in PBC mode
2212 vdp_control_port_write(context, full_val); 2225 vdp_control_port_write(context, full_val);
2226 if (context->cd == VRAM_READ) {
2227 context->cd = VRAM_READ8;
2228 }
2213 } else { 2229 } else {
2214 context->pending_byte = value; 2230 context->pending_byte = value;
2215 context->flags2 |= FLAG2_BYTE_PENDING; 2231 context->flags2 |= FLAG2_BYTE_PENDING;
2216 } 2232 }
2217 } 2233 }
2245 cur->partial = 0; 2261 cur->partial = 0;
2246 if (context->fifo_read < 0) { 2262 if (context->fifo_read < 0) {
2247 context->fifo_read = context->fifo_write; 2263 context->fifo_read = context->fifo_write;
2248 } 2264 }
2249 context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1); 2265 context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1);
2250 context->address += context->regs[REG_AUTOINC]; 2266 increment_address(context);
2267 return 0;
2268 }
2269
2270 void vdp_data_port_write_pbc(vdp_context * context, uint8_t value)
2271 {
2272 if (context->flags & FLAG_PENDING) {
2273 context->flags &= ~FLAG_PENDING;
2274 context->flags2 &= ~FLAG2_BYTE_PENDING;
2275 //Should these be cleared here?
2276 context->flags &= ~FLAG_READ_FETCHED;
2277 context->flags2 &= ~FLAG2_READ_PENDING;
2278 }
2279 /*if (context->fifo_cur == context->fifo_end) {
2280 printf("FIFO full, waiting for space before next write at cycle %X\n", context->cycles);
2281 }*/
2282 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) {
2283 context->flags &= ~FLAG_DMA_RUN;
2284 }
2285 while (context->fifo_write == context->fifo_read) {
2286 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
2287 }
2288 fifo_entry * cur = context->fifo + context->fifo_write;
2289 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY;
2290 cur->address = context->address;
2291 cur->value = value;
2292 cur->cd = context->cd | 1;
2293 cur->partial = 1;
2294 if (context->fifo_read < 0) {
2295 context->fifo_read = context->fifo_write;
2296 }
2297 context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1);
2298 increment_address(context);
2299 }
2300
2301 void vdp_test_port_write(vdp_context * context, uint16_t value)
2302 {
2303 //TODO: implement test register
2304 }
2305
2306 uint16_t vdp_control_port_read(vdp_context * context)
2307 {
2308 context->flags &= ~FLAG_PENDING;
2309 context->flags2 &= ~FLAG2_BYTE_PENDING;
2310 //Bits 15-10 are not fixed like Charles MacDonald's doc suggests, but instead open bus values that reflect 68K prefetch
2311 uint16_t value = context->system->get_open_bus_value(context->system) & 0xFC00;
2312 if (context->fifo_read < 0) {
2313 value |= 0x200;
2314 }
2315 if (context->fifo_read == context->fifo_write) {
2316 value |= 0x100;
2317 }
2318 if (context->flags2 & FLAG2_VINT_PENDING) {
2319 value |= 0x80;
2320 }
2321 if (context->flags & FLAG_DOT_OFLOW) {
2322 value |= 0x40;
2323 }
2324 if (context->flags2 & FLAG2_SPRITE_COLLIDE) {
2325 value |= 0x20;
2326 context->flags2 &= ~FLAG2_SPRITE_COLLIDE;
2327 }
2328 if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && !(context->flags2 & FLAG2_EVEN_FIELD)) {
2329 value |= 0x10;
2330 }
2331 uint32_t line= context->vcounter;
2332 uint32_t slot = context->hslot;
2333 uint32_t inactive_start = (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START);
2251 if (!(context->regs[REG_MODE_2] & BIT_MODE_5)) { 2334 if (!(context->regs[REG_MODE_2] & BIT_MODE_5)) {
2252 context->address++; 2335 inactive_start = MODE4_INACTIVE_START;
2253 } 2336 }
2254 return 0; 2337 if ((line >= inactive_start && line < 0x1FF) || !(context->regs[REG_MODE_2] & BIT_DISP_EN)) {
2255 } 2338 value |= 0x8;
2256 2339 }
2257 void vdp_data_port_write_pbc(vdp_context * context, uint8_t value) 2340 if (context->regs[REG_MODE_4] & BIT_H40) {
2341 if (slot < HBLANK_END_H40 || slot > HBLANK_START_H40) {
2342 value |= 0x4;
2343 }
2344 } else {
2345 if (slot < HBLANK_END_H32 || slot > HBLANK_START_H32) {
2346 value |= 0x4;
2347 }
2348 }
2349 if (context->cd & 0x20) {
2350 value |= 0x2;
2351 }
2352 if (context->flags2 & FLAG2_REGION_PAL) {
2353 value |= 0x1;
2354 }
2355 //printf("status read at cycle %d returned %X\n", context->cycles, value);
2356 return value;
2357 }
2358
2359 uint16_t vdp_data_port_read(vdp_context * context)
2258 { 2360 {
2259 if (context->flags & FLAG_PENDING) { 2361 if (context->flags & FLAG_PENDING) {
2260 context->flags &= ~FLAG_PENDING; 2362 context->flags &= ~FLAG_PENDING;
2261 //Should these be cleared here? 2363 //Should these be cleared here?
2262 context->flags &= ~FLAG_READ_FETCHED; 2364 context->flags &= ~FLAG_READ_FETCHED;
2263 context->flags2 &= ~FLAG2_READ_PENDING; 2365 context->flags2 &= ~FLAG2_READ_PENDING;
2264 } 2366 }
2265 /*if (context->fifo_cur == context->fifo_end) { 2367 if (context->cd & 1) {
2266 printf("FIFO full, waiting for space before next write at cycle %X\n", context->cycles); 2368 warning("Read from VDP data port while writes are configured, CPU is now frozen. VDP Address: %X, CD: %X\n", context->address, context->cd);
2267 }*/ 2369 }
2268 if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) { 2370 while (!(context->flags & FLAG_READ_FETCHED)) {
2269 context->flags &= ~FLAG_DMA_RUN;
2270 }
2271 while (context->fifo_write == context->fifo_read) {
2272 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)); 2371 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
2273 } 2372 }
2274 fifo_entry * cur = context->fifo + context->fifo_write; 2373 context->flags &= ~FLAG_READ_FETCHED;
2275 cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY; 2374 //Should this happen after the prefetch or after the read?
2276 cur->address = context->address; 2375 increment_address(context);
2277 cur->value = value; 2376 return context->prefetch;
2278 cur->cd = context->cd; 2377 }
2279 cur->partial = 1; 2378
2280 if (context->fifo_read < 0) { 2379 uint8_t vdp_data_port_read_pbc(vdp_context * context)
2281 context->fifo_read = context->fifo_write;
2282 }
2283 context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1);
2284 context->address += context->regs[REG_AUTOINC];
2285 if (!(context->regs[REG_MODE_2] & BIT_MODE_5)) {
2286 context->address++;
2287 }
2288 }
2289
2290 void vdp_test_port_write(vdp_context * context, uint16_t value)
2291 {
2292 //TODO: implement test register
2293 }
2294
2295 uint16_t vdp_control_port_read(vdp_context * context)
2296 {
2297 context->flags &= ~FLAG_PENDING;
2298 //Bits 15-10 are not fixed like Charles MacDonald's doc suggests, but instead open bus values that reflect 68K prefetch
2299 uint16_t value = context->system->get_open_bus_value(context->system) & 0xFC00;
2300 if (context->fifo_read < 0) {
2301 value |= 0x200;
2302 }
2303 if (context->fifo_read == context->fifo_write) {
2304 value |= 0x100;
2305 }
2306 if (context->flags2 & FLAG2_VINT_PENDING) {
2307 value |= 0x80;
2308 }
2309 if (context->flags & FLAG_DOT_OFLOW) {
2310 value |= 0x40;
2311 }
2312 if (context->flags2 & FLAG2_SPRITE_COLLIDE) {
2313 value |= 0x20;
2314 context->flags2 &= ~FLAG2_SPRITE_COLLIDE;
2315 }
2316 if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && !(context->flags2 & FLAG2_EVEN_FIELD)) {
2317 value |= 0x10;
2318 }
2319 uint32_t line= context->vcounter;
2320 uint32_t slot = context->hslot;
2321 uint32_t inactive_start = (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START);
2322 if (!(context->regs[REG_MODE_2] & BIT_MODE_5)) {
2323 inactive_start = MODE4_INACTIVE_START;
2324 }
2325 if ((line >= inactive_start && line < 0x1FF) || !(context->regs[REG_MODE_2] & BIT_DISP_EN)) {
2326 value |= 0x8;
2327 }
2328 if (context->regs[REG_MODE_4] & BIT_H40) {
2329 if (slot < HBLANK_END_H40 || slot > HBLANK_START_H40) {
2330 value |= 0x4;
2331 }
2332 } else {
2333 if (slot < HBLANK_END_H32 || slot > HBLANK_START_H32) {
2334 value |= 0x4;
2335 }
2336 }
2337 if (context->cd & 0x20) {
2338 value |= 0x2;
2339 }
2340 if (context->flags2 & FLAG2_REGION_PAL) {
2341 value |= 0x1;
2342 }
2343 //printf("status read at cycle %d returned %X\n", context->cycles, value);
2344 return value;
2345 }
2346
2347 uint16_t vdp_data_port_read(vdp_context * context)
2348 { 2380 {
2349 if (context->flags & FLAG_PENDING) { 2381 if (context->flags & FLAG_PENDING) {
2350 context->flags &= ~FLAG_PENDING; 2382 context->flags &= ~FLAG_PENDING;
2351 //Should these be cleared here? 2383 context->flags2 &= ~FLAG2_BYTE_PENDING;
2384
2385 }
2386 if (context->flags & FLAG_READ_FETCHED) {
2352 context->flags &= ~FLAG_READ_FETCHED; 2387 context->flags &= ~FLAG_READ_FETCHED;
2353 context->flags2 &= ~FLAG2_READ_PENDING; 2388 //Should this happen after the prefetch or after the read?
2354 } 2389 increment_address(context);
2355 if (context->cd & 1) { 2390 }
2356 warning("Read from VDP data port while writes are configured, CPU is now frozen. VDP Address: %X, CD: %X\n", context->address, context->cd); 2391 context->cd &= ~1;
2357 } 2392 if (context->cd == VRAM_READ) {
2358 while (!(context->flags & FLAG_READ_FETCHED)) { 2393 context->cd = VRAM_READ8;
2359 vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)); 2394 }
2360 }
2361 context->flags &= ~FLAG_READ_FETCHED;
2362 //Should this happen after the prefetch or after the read?
2363 context->address += context->regs[REG_AUTOINC];
2364 return context->prefetch;
2365 }
2366
2367 uint8_t vdp_data_port_read_pbc(vdp_context * context)
2368 {
2369 if (context->flags & FLAG_PENDING) {
2370 context->flags &= ~FLAG_PENDING;
2371 //Should these be cleared here?
2372 context->flags &= ~FLAG_READ_FETCHED;
2373 context->flags2 &= ~FLAG2_READ_PENDING;
2374 }
2375 context->flags &= ~FLAG_READ_FETCHED;
2376 //Should this happen after the prefetch or after the read?
2377 context->address += context->regs[REG_AUTOINC];
2378 return context->prefetch; 2395 return context->prefetch;
2379 } 2396 }
2380 2397
2381 uint16_t vdp_hv_counter_read(vdp_context * context) 2398 uint16_t vdp_hv_counter_read(vdp_context * context)
2382 { 2399 {