comparison blastem.c @ 153:42c031184e8a

Implement access to Z80 RAM
author Mike Pavone <pavone@retrodev.com>
date Fri, 04 Jan 2013 21:47:09 -0800
parents 139e5dcd6aa3
children a2ab895d9708
comparison
equal deleted inserted replaced
152:79958b95526f 153:42c031184e8a
7 #include <stdio.h> 7 #include <stdio.h>
8 #include <stdlib.h> 8 #include <stdlib.h>
9 9
10 #define CARTRIDGE_WORDS 0x200000 10 #define CARTRIDGE_WORDS 0x200000
11 #define RAM_WORDS 32 * 1024 11 #define RAM_WORDS 32 * 1024
12 #define Z80_RAM_BYTES 8 * 1024
12 #define MCLKS_PER_68K 7 13 #define MCLKS_PER_68K 7
13 //TODO: Figure out the exact value for this 14 //TODO: Figure out the exact value for this
14 #define MCLKS_PER_FRAME (MCLKS_LINE*262) 15 #define MCLKS_PER_FRAME (MCLKS_LINE*262)
15 #define CYCLE_NEVER 0xFFFFFFFF 16 #define CYCLE_NEVER 0xFFFFFFFF
16 17
17 uint16_t cart[CARTRIDGE_WORDS]; 18 uint16_t cart[CARTRIDGE_WORDS];
18 uint16_t ram[RAM_WORDS]; 19 uint16_t ram[RAM_WORDS];
20 uint8_t z80_ram[Z80_RAM_BYTES];
19 21
20 io_port gamepad_1; 22 io_port gamepad_1;
21 io_port gamepad_2; 23 io_port gamepad_2;
22 24
23 #ifndef MIN 25 #ifndef MIN
273 }*/ 275 }*/
274 } 276 }
275 277
276 m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value) 278 m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value)
277 { 279 {
278 if (location < 0x100) { 280 if (location < 0x10000) {
279 switch(location/2) 281 if (busack_cycle > context->current_cycle) {
280 { 282 busack = new_busack;
281 case 0x1: 283 busack_cycle = CYCLE_NEVER;
282 io_data_write(&gamepad_1, context, value); 284 }
283 break; 285 if (!(busack || reset)) {
284 case 0x2: 286 location &= 0x7FFF;
285 io_data_write(&gamepad_2, context, value); 287 if (location < 0x4000) {
286 break; 288 z80_ram[location & 0x1FFF] = value;
287 case 0x3://PORT C Data 289 }
288 break; 290 }
289 case 0x4: 291 } else {
290 gamepad_1.control = value; 292 location &= 0x1FFF;
291 break; 293 if (location < 0x100) {
292 case 0x5: 294 switch(location/2)
293 gamepad_2.control = value; 295 {
294 break; 296 case 0x1:
295 } 297 io_data_write(&gamepad_1, context, value);
296 } else { 298 break;
297 if (location == 0x1100) { 299 case 0x2:
298 if (busack_cycle > context->current_cycle) { 300 io_data_write(&gamepad_2, context, value);
299 busack = new_busack; 301 break;
300 busack_cycle = CYCLE_NEVER; 302 case 0x3://PORT C Data
301 } 303 break;
302 if (value & 1) { 304 case 0x4:
303 busreq = 1; 305 gamepad_1.control = value;
304 if(!reset) { 306 break;
305 busack_cycle = context->current_cycle + Z80_ACK_DELAY; 307 case 0x5:
306 new_busack = 0; 308 gamepad_2.control = value;
307 } 309 break;
308 } else { 310 }
309 busreq = 0; 311 } else {
310 busack_cycle = CYCLE_NEVER; 312 if (location == 0x1100) {
311 busack = 1; 313 if (busack_cycle > context->current_cycle) {
312 } 314 busack = new_busack;
313 } else if (location == 0x1200) { 315 busack_cycle = CYCLE_NEVER;
314 if (value & 1) { 316 }
315 if (reset && busreq) { 317 if (value & 1) {
316 new_busack = 0; 318 busreq = 1;
317 busack_cycle = context->current_cycle + Z80_ACK_DELAY; 319 if(!reset) {
318 } 320 busack_cycle = context->current_cycle + Z80_ACK_DELAY;
319 reset = 0; 321 new_busack = 0;
320 } else { 322 }
321 reset = 1; 323 } else {
324 busreq = 0;
325 busack_cycle = CYCLE_NEVER;
326 busack = 1;
327 }
328 } else if (location == 0x1200) {
329 if (value & 1) {
330 if (reset && busreq) {
331 new_busack = 0;
332 busack_cycle = context->current_cycle + Z80_ACK_DELAY;
333 }
334 reset = 0;
335 } else {
336 reset = 1;
337 }
322 } 338 }
323 } 339 }
324 } 340 }
325 return context; 341 return context;
326 } 342 }
327 343
328 m68k_context * io_write_w(uint32_t location, m68k_context * context, uint16_t value) 344 m68k_context * io_write_w(uint32_t location, m68k_context * context, uint16_t value)
329 { 345 {
330 if (location < 0x100) { 346 if (location < 0x10000) {
331 switch(location/2) 347 if (busack_cycle > context->current_cycle) {
332 { 348 busack = new_busack;
333 case 0x1: 349 busack_cycle = CYCLE_NEVER;
334 io_data_write(&gamepad_1, context, value); 350 }
335 break; 351 if (!(busack || reset)) {
336 case 0x2: 352 location &= 0x7FFF;
337 io_data_write(&gamepad_2, context, value); 353 if (location < 0x4000) {
338 break; 354 z80_ram[location & 0x1FFE] = value >> 8;
339 case 0x3://PORT C Data 355 }
340 break; 356 }
341 case 0x4: 357 } else {
342 gamepad_1.control = value; 358 location &= 0x1FFF;
343 break; 359 if (location < 0x100) {
344 case 0x5: 360 switch(location/2)
345 gamepad_2.control = value; 361 {
346 break; 362 case 0x1:
347 } 363 io_data_write(&gamepad_1, context, value);
348 } else { 364 break;
349 //printf("IO Write of %X to %X @ %d\n", value, location, context->current_cycle); 365 case 0x2:
350 if (location == 0x1100) { 366 io_data_write(&gamepad_2, context, value);
351 if (busack_cycle > context->current_cycle) { 367 break;
352 busack = new_busack; 368 case 0x3://PORT C Data
353 busack_cycle = CYCLE_NEVER; 369 break;
354 } 370 case 0x4:
355 if (value & 0x100) { 371 gamepad_1.control = value;
356 busreq = 1; 372 break;
357 if(!reset) { 373 case 0x5:
358 busack_cycle = context->current_cycle + Z80_ACK_DELAY; 374 gamepad_2.control = value;
359 new_busack = 0; 375 break;
360 } 376 }
361 } else { 377 } else {
362 busreq = 0; 378 //printf("IO Write of %X to %X @ %d\n", value, location, context->current_cycle);
363 busack_cycle = CYCLE_NEVER; 379 if (location == 0x1100) {
364 busack = 1; 380 if (busack_cycle > context->current_cycle) {
365 } 381 busack = new_busack;
366 } else if (location == 0x1200) { 382 busack_cycle = CYCLE_NEVER;
367 if (value & 0x100) { 383 }
368 if (reset && busreq) { 384 if (value & 0x100) {
369 new_busack = 0; 385 busreq = 1;
370 busack_cycle = context->current_cycle + Z80_ACK_DELAY; 386 if(!reset) {
371 } 387 busack_cycle = context->current_cycle + Z80_ACK_DELAY;
372 reset = 0; 388 new_busack = 0;
373 } else { 389 }
374 reset = 1; 390 } else {
391 busreq = 0;
392 busack_cycle = CYCLE_NEVER;
393 busack = 1;
394 }
395 } else if (location == 0x1200) {
396 if (value & 0x100) {
397 if (reset && busreq) {
398 new_busack = 0;
399 busack_cycle = context->current_cycle + Z80_ACK_DELAY;
400 }
401 reset = 0;
402 } else {
403 reset = 1;
404 }
375 } 405 }
376 } 406 }
377 } 407 }
378 return context; 408 return context;
379 } 409 }
384 #define NO_DISK 0x20 414 #define NO_DISK 0x20
385 uint8_t version_reg = NO_DISK | USA; 415 uint8_t version_reg = NO_DISK | USA;
386 416
387 m68k_context * io_read(uint32_t location, m68k_context * context) 417 m68k_context * io_read(uint32_t location, m68k_context * context)
388 { 418 {
389 if (location < 0x100) { 419 if (location < 0x10000) {
390 switch(location/2) 420 if (busack_cycle > context->current_cycle) {
391 { 421 busack = new_busack;
392 case 0x0: 422 busack_cycle = CYCLE_NEVER;
393 //version bits should be 0 for now since we're not emulating TMSS 423 }
394 //Not sure about the other bits 424 if (!(busack || reset)) {
395 context->value = version_reg; 425 location &= 0x7FFF;
396 break; 426 if (location < 0x4000) {
397 case 0x1: 427 context->value = z80_ram[location & 0x1FFF];
398 io_data_read(&gamepad_1, context); 428 } else {
399 break; 429 context->value = 0xFF;
400 case 0x2: 430 }
401 io_data_read(&gamepad_2, context); 431 } else {
402 break; 432 context->value = 0xFF;
403 case 0x3://PORT C Data 433 }
404 break; 434 } else {
405 case 0x4: 435 location &= 0x1FFF;
406 context->value = gamepad_1.control; 436 if (location < 0x100) {
407 break; 437 switch(location/2)
408 case 0x5: 438 {
409 context->value = gamepad_2.control; 439 case 0x0:
410 break; 440 //version bits should be 0 for now since we're not emulating TMSS
411 } 441 //Not sure about the other bits
412 } else { 442 context->value = version_reg;
413 if (location == 0x1100) { 443 break;
414 if (busack_cycle > context->current_cycle) { 444 case 0x1:
415 busack = new_busack; 445 io_data_read(&gamepad_1, context);
416 busack_cycle = CYCLE_NEVER; 446 break;
417 } 447 case 0x2:
418 context->value = reset || busack; 448 io_data_read(&gamepad_2, context);
419 //printf("Byte read of BUSREQ returned %d @ %d (reset: %d, busack: %d)\n", context->value, context->current_cycle, reset, busack); 449 break;
420 } else if (location == 0x1200) { 450 case 0x3://PORT C Data
421 context->value = !reset; 451 break;
422 } else { 452 case 0x4:
423 printf("Byte read of unknown IO location: %X\n", location); 453 context->value = gamepad_1.control;
454 break;
455 case 0x5:
456 context->value = gamepad_2.control;
457 break;
458 }
459 } else {
460 if (location == 0x1100) {
461 if (busack_cycle > context->current_cycle) {
462 busack = new_busack;
463 busack_cycle = CYCLE_NEVER;
464 }
465 context->value = reset || busack;
466 //printf("Byte read of BUSREQ returned %d @ %d (reset: %d, busack: %d)\n", context->value, context->current_cycle, reset, busack);
467 } else if (location == 0x1200) {
468 context->value = !reset;
469 } else {
470 printf("Byte read of unknown IO location: %X\n", location);
471 }
424 } 472 }
425 } 473 }
426 return context; 474 return context;
427 } 475 }
428 476
429 m68k_context * io_read_w(uint32_t location, m68k_context * context) 477 m68k_context * io_read_w(uint32_t location, m68k_context * context)
430 { 478 {
431 if (location < 0x100) { 479 if (location < 0x10000) {
432 switch(location/2) 480 if (busack_cycle > context->current_cycle) {
433 { 481 busack = new_busack;
434 case 0x0: 482 busack_cycle = CYCLE_NEVER;
435 //version bits should be 0 for now since we're not emulating TMSS 483 }
436 //Not sure about the other bits 484 if (!(busack || reset)) {
437 context->value = 0; 485 location &= 0x7FFF;
438 break; 486 if (location < 0x4000) {
439 case 0x1: 487 context->value = z80_ram[location & 0x1FFE];
440 io_data_read(&gamepad_1, context); 488 context->value |= context->value << 8;
441 break; 489 } else {
442 case 0x2: 490 context->value = 0xFFFF;
443 io_data_read(&gamepad_2, context); 491 }
444 break; 492 } else {
445 case 0x3://PORT C Data 493 context->value = 0xFFFF;
446 break; 494 }
447 case 0x4: 495 } else {
448 context->value = gamepad_1.control; 496 location &= 0x1FFF;
449 break; 497 if (location < 0x100) {
450 case 0x5: 498 switch(location/2)
451 context->value = gamepad_2.control; 499 {
452 break; 500 case 0x0:
453 case 0x6: 501 //version bits should be 0 for now since we're not emulating TMSS
454 //PORT C Control 502 //Not sure about the other bits
455 context->value = 0; 503 context->value = 0;
456 break; 504 break;
457 } 505 case 0x1:
458 context->value = context->value | (context->value << 8); 506 io_data_read(&gamepad_1, context);
459 //printf("Word read to %X returned %d\n", location, context->value); 507 break;
460 } else { 508 case 0x2:
461 if (location == 0x1100) { 509 io_data_read(&gamepad_2, context);
462 if (busack_cycle > context->current_cycle) { 510 break;
463 busack = new_busack; 511 case 0x3://PORT C Data
464 busack_cycle = CYCLE_NEVER; 512 break;
465 } 513 case 0x4:
466 context->value = (reset || busack) << 8; 514 context->value = gamepad_1.control;
467 //printf("Word read of BUSREQ returned %d\n", context->value); 515 break;
468 } else if (location == 0x1200) { 516 case 0x5:
469 context->value = (!reset) << 8; 517 context->value = gamepad_2.control;
470 } else { 518 break;
471 printf("Word read of unknown IO location: %X\n", location); 519 case 0x6:
520 //PORT C Control
521 context->value = 0;
522 break;
523 }
524 context->value = context->value | (context->value << 8);
525 //printf("Word read to %X returned %d\n", location, context->value);
526 } else {
527 if (location == 0x1100) {
528 if (busack_cycle > context->current_cycle) {
529 busack = new_busack;
530 busack_cycle = CYCLE_NEVER;
531 }
532 context->value = (reset || busack) << 8;
533 //printf("Word read of BUSREQ returned %d\n", context->value);
534 } else if (location == 0x1200) {
535 context->value = (!reset) << 8;
536 } else {
537 printf("Word read of unknown IO location: %X\n", location);
538 }
472 } 539 }
473 } 540 }
474 return context; 541 return context;
475 } 542 }
476 543