src/mess/drivers/psion.c
| r8751 | r8752 | |
| 30 | 30 | UINT8 id; |
| 31 | 31 | UINT8 len; |
| 32 | 32 | UINT16 counter; |
| 33 | UINT8 page; |
| 33 | 34 | UINT8* data; |
| 34 | 35 | }; |
| 35 | 36 | |
| r8751 | r8752 | |
| 287 | 288 | } |
| 288 | 289 | } |
| 289 | 290 | |
| 291 | struct datapack *get_active_slot(running_machine *machine, UINT8 data) |
| 292 | { |
| 293 | switch(data & 0x70) |
| 294 | { |
| 295 | case 0x60: |
| 296 | return &psion.pack1; |
| 297 | case 0x50: |
| 298 | return &psion.pack2; |
| 299 | } |
| 300 | |
| 301 | return NULL; |
| 302 | } |
| 303 | |
| 290 | 304 | void datapack_w(running_machine *machine, UINT8 data) |
| 291 | 305 | { |
| 292 | 306 | //TODO |
| r8751 | r8752 | |
| 294 | 308 | |
| 295 | 309 | UINT8 datapack_r(running_machine *machine) |
| 296 | 310 | { |
| 297 | | if (!(psion.port6 & 0x80)) |
| 298 | | { |
| 299 | | if (!(psion.port6 & 0x10) && psion.pack1.len > 0) |
| 300 | | return psion.pack1.data[psion.pack1.counter]; |
| 301 | | else if (!(psion.port6 & 0x20) && psion.pack2.len > 0) |
| 302 | | return psion.pack2.data[psion.pack2.counter]; |
| 303 | | } |
| 311 | struct datapack *pack = get_active_slot(machine, psion.port6); |
| 304 | 312 | |
| 313 | if (pack != NULL && pack->len > 0 && !(psion.port6 & 0x80)) |
| 314 | { |
| 315 | UINT32 pack_addr = pack->counter + ((pack->id & 0x04) ? 0x100 * pack->page : 0); |
| 316 | |
| 317 | if (pack_addr < pack->len * 0x2000) |
| 318 | return pack->data[pack_addr]; |
| 319 | } |
| 320 | |
| 305 | 321 | return 0; |
| 306 | 322 | } |
| 307 | 323 | |
| r8751 | r8752 | |
| 319 | 335 | case 0x08: |
| 320 | 336 | psion.tcsr_value = data; |
| 321 | 337 | break; |
| 338 | case 0x15: |
| 339 | /* read-only */ |
| 340 | break; |
| 322 | 341 | case 0x16: |
| 323 | 342 | psion.port6_ddr = data; |
| 324 | 343 | break; |
| r8751 | r8752 | |
| 336 | 355 | */ |
| 337 | 356 | if (psion.port6_ddr == 0xff) |
| 338 | 357 | { |
| 339 | | if ((psion.port6 & 0x01) != (data & 0x01)) |
| 340 | | { |
| 341 | | if (!(data & 0x10)) |
| 342 | | psion.pack1.counter++; |
| 343 | | else if (!(data & 0x20)) |
| 344 | | psion.pack2.counter++; |
| 358 | struct datapack *pack = get_active_slot(space->machine, data); |
| 345 | 359 | |
| 346 | | if (psion.pack1.counter >= psion.pack1.len * 0x2000) |
| 347 | | psion.pack1.counter -= 0x2000; |
| 348 | | } |
| 360 | if (pack != NULL) |
| 361 | { |
| 362 | if ((psion.port6 & 0x01) != (data & 0x01)) |
| 363 | { |
| 364 | pack->counter++; |
| 349 | 365 | |
| 350 | | if (psion.port6 & 0x02) |
| 351 | | { |
| 352 | | if (!(data & 0x10)) |
| 353 | | psion.pack1.counter = 0; |
| 354 | | else if (!(data & 0x20)) |
| 355 | | psion.pack2.counter = 0; |
| 356 | | } |
| 366 | if (pack->counter >= ((pack->id & 0x04) ? 0x100 : (pack->len * 0x2000))) |
| 367 | pack->counter = 0; |
| 368 | } |
| 357 | 369 | |
| 370 | if ((psion.port6 & 0x04) && !(data & 0x04)) |
| 371 | { |
| 372 | pack->page++; |
| 373 | |
| 374 | if (pack->page >= (pack->len * 0x2000) / 0x100) |
| 375 | pack->page = 0; |
| 376 | } |
| 377 | |
| 378 | if (psion.port6 & 0x02) |
| 379 | { |
| 380 | pack->counter = 0; |
| 381 | pack->page = 0; |
| 382 | } |
| 383 | } |
| 384 | |
| 358 | 385 | psion.port6 = data; |
| 359 | 386 | } |
| 360 | 387 | break; |
| r8751 | r8752 | |
| 581 | 608 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D [)]") PORT_CODE(KEYCODE_D) |
| 582 | 609 | INPUT_PORTS_END |
| 583 | 610 | |
| 584 | | static DEVICE_IMAGE_LOAD( psion_pack1 ) |
| 611 | int datapack_load(device_image_interface &image, struct datapack &pack) |
| 585 | 612 | { |
| 586 | 613 | running_machine *machine = image.device().machine; |
| 587 | 614 | char opk_head[6]; |
| 615 | UINT8 pack_id, pack_len; |
| 588 | 616 | |
| 589 | 617 | image.fread(opk_head, 6); |
| 590 | | image.fread(&psion.pack1.id, 1); |
| 591 | | image.fread(&psion.pack1.len, 1); |
| 618 | image.fread(&pack_id, 1); |
| 619 | image.fread(&pack_len, 1); |
| 592 | 620 | |
| 593 | | if(strcmp(opk_head, "OPK") || psion.pack1.len * 0x2000 < image.length() - 6) |
| 621 | if(strcmp(opk_head, "OPK") || pack_len * 0x2000 < image.length() - 6) |
| 594 | 622 | return IMAGE_INIT_FAIL; |
| 595 | 623 | |
| 624 | pack.id = pack_id; |
| 625 | pack.len = pack_len; |
| 596 | 626 | image.fseek(6, SEEK_SET); |
| 597 | | psion.pack1.data = auto_alloc_array(machine, UINT8, psion.pack1.len * 0x2000); |
| 598 | | memset(psion.pack1.data, 0xff, psion.pack1.len * 0x2000); |
| 599 | | image.fread(psion.pack1.data, image.length() - 6); |
| 627 | pack.data = auto_alloc_array(machine, UINT8, pack.len * 0x2000); |
| 628 | memset(pack.data, 0xff, pack.len * 0x2000); |
| 629 | image.fread(pack.data, image.length() - 6); |
| 600 | 630 | |
| 601 | 631 | return IMAGE_INIT_PASS; |
| 602 | 632 | } |
| 603 | 633 | |
| 634 | static DEVICE_IMAGE_LOAD( psion_pack1 ) |
| 635 | { |
| 636 | return datapack_load(image, psion.pack1); |
| 637 | } |
| 638 | |
| 604 | 639 | static DEVICE_IMAGE_UNLOAD( psion_pack1 ) |
| 605 | 640 | { |
| 606 | 641 | auto_free(image.device().machine, psion.pack1.data); |
| 607 | 642 | memset(&psion.pack1, 0, sizeof(psion.pack1)); |
| 608 | 643 | } |
| 609 | 644 | |
| 645 | static DEVICE_IMAGE_LOAD( psion_pack2 ) |
| 646 | { |
| 647 | return datapack_load(image, psion.pack2); |
| 648 | } |
| 649 | |
| 650 | static DEVICE_IMAGE_UNLOAD( psion_pack2 ) |
| 651 | { |
| 652 | auto_free(image.device().machine, psion.pack2.data); |
| 653 | memset(&psion.pack2, 0, sizeof(psion.pack2)); |
| 654 | } |
| 655 | |
| 610 | 656 | static MACHINE_START(psion) |
| 611 | 657 | { |
| 612 | 658 | if (!strcmp(machine->gamedrv->name, "psionlam")) |
| r8751 | r8752 | |
| 819 | 865 | MDRV_CARTSLOT_NOT_MANDATORY |
| 820 | 866 | MDRV_CARTSLOT_LOAD(psion_pack1) |
| 821 | 867 | MDRV_CARTSLOT_UNLOAD(psion_pack1) |
| 868 | |
| 869 | /* Datapack slot 2 */ |
| 870 | MDRV_CARTSLOT_ADD("pack2") |
| 871 | MDRV_CARTSLOT_EXTENSION_LIST("opk") |
| 872 | MDRV_CARTSLOT_NOT_MANDATORY |
| 873 | MDRV_CARTSLOT_LOAD(psion_pack2) |
| 874 | MDRV_CARTSLOT_UNLOAD(psion_pack2) |
| 822 | 875 | MACHINE_DRIVER_END |
| 823 | 876 | |
| 824 | 877 | /* basic configuration for 2 lines display */ |