| Previous | 15994 Revisions | Next |
| r8807 Thursday 19th August, 2010 at 14:40:07 UTC by Miodrag Milanović |
|---|
| Sync with MAME |
| [src/emu] | addrmap.c addrmap.h delegate.c* delegate.h* devcpu.c devintrf.h dimemory.c dimemory.h emu.h emu.mak emucore.h machine.c machine.h memconv.h memory.c memory.h |
| [src/emu/audio] | generic.c |
| [src/emu/cpu] | drcbec.c drcbex64.c drcbex86.c drcfe.c |
| [src/emu/cpu/adsp2100] | 2100dasm.c adsp2100.c |
| [src/emu/cpu/alph8201] | alph8201.c |
| [src/emu/cpu/am29000] | am29000.c am29ops.h |
| [src/emu/cpu/apexc] | apexc.c |
| [src/emu/cpu/arm] | arm.c |
| [src/emu/cpu/arm7] | arm7.c arm7core.c arm7core.h |
| [src/emu/cpu/asap] | asap.c |
| [src/emu/cpu/avr8] | avr8.c |
| [src/emu/cpu/ccpu] | ccpu.c |
| [src/emu/cpu/cdp1802] | cdp1802.c |
| [src/emu/cpu/cop400] | cop400.c |
| [src/emu/cpu/cp1610] | cp1610.c |
| [src/emu/cpu/cubeqcpu] | cubeqcpu.c |
| [src/emu/cpu/dsp32] | dsp32.c |
| [src/emu/cpu/dsp56k] | dsp56k.c dsp56k.h dsp56ops.c dsp56pcu.c |
| [src/emu/cpu/e132xs] | e132xs.c e132xs.h |
| [src/emu/cpu/esrip] | esrip.c |
| [src/emu/cpu/f8] | f8.c |
| [src/emu/cpu/g65816] | g65816cm.h |
| [src/emu/cpu/h6280] | h6280.h h6280ops.h |
| [src/emu/cpu/h83002] | h8_16.c h8_8.c h8periph.c h8priv.h |
| [src/emu/cpu/hd6309] | hd6309.c |
| [src/emu/cpu/i386] | i386priv.h |
| [src/emu/cpu/i4004] | i4004.c |
| [src/emu/cpu/i8008] | i8008.c |
| [src/emu/cpu/i8085] | i8085.c i8085cpu.h |
| [src/emu/cpu/i86] | i286.c i86.c i86mem.c i86mem.h i86priv.h |
| [src/emu/cpu/i860] | i860.h i860dec.c |
| [src/emu/cpu/i960] | i960.c |
| [src/emu/cpu/jaguar] | jaguar.c |
| [src/emu/cpu/konami] | konami.c |
| [src/emu/cpu/lh5801] | 5801tbl.c lh5801.c |
| [src/emu/cpu/lr35902] | lr35902.c |
| [src/emu/cpu/m37710] | m37710.c m37710cm.h |
| [src/emu/cpu/m6502] | m4510.c m6502.c m6509.c m65ce02.c minc4510.h mincce02.h ops02.h ops09.h tdeco16.c |
| [src/emu/cpu/m6800] | m6800.c |
| [src/emu/cpu/m68000] | m68kcpu.c m68kcpu.h m68kmmu.h |
| [src/emu/cpu/m6805] | m6805.c |
| [src/emu/cpu/m6809] | m6809.c |
| [src/emu/cpu/mb86233] | mb86233.c |
| [src/emu/cpu/mb88xx] | mb88xx.c |
| [src/emu/cpu/mc68hc11] | mc68hc11.c |
| [src/emu/cpu/mcs48] | mcs48.c |
| [src/emu/cpu/mcs51] | mcs51.c |
| [src/emu/cpu/minx] | minx.c |
| [src/emu/cpu/mips] | mips3com.c mips3com.h psx.c r3000.c |
| [src/emu/cpu/mn10200] | mn10200.c |
| [src/emu/cpu/nec] | nec.c necmodrm.h necpriv.h |
| [src/emu/cpu/pdp1] | pdp1.c tx0.c |
| [src/emu/cpu/pic16c5x] | pic16c5x.c |
| [src/emu/cpu/pic16c62x] | pic16c62x.c |
| [src/emu/cpu/powerpc] | ppc.c ppc403.c ppc_mem.c ppccom.c ppccom.h |
| [src/emu/cpu/rsp] | rsp.c rsp.h |
| [src/emu/cpu/s2650] | s2650.c |
| [src/emu/cpu/saturn] | satops.c saturn.c |
| [src/emu/cpu/sc61860] | sc61860.c scops.c |
| [src/emu/cpu/scmp] | scmp.c |
| [src/emu/cpu/se3208] | se3208.c |
| [src/emu/cpu/sh2] | sh2.c sh2comn.c sh2comn.h sh2drc.c |
| [src/emu/cpu/sh4] | sh4.c sh4comn.c sh4comn.h |
| [src/emu/cpu/sharc] | sharc.c sharcmem.c |
| [src/emu/cpu/sm8500] | sm8500.c sm8500.h sm8500d.c sm85ops.h |
| [src/emu/cpu/spc700] | spc700.c |
| [src/emu/cpu/ssem] | ssem.c |
| [src/emu/cpu/ssp1601] | ssp1601.c |
| [src/emu/cpu/superfx] | superfx.c |
| [src/emu/cpu/t11] | t11.c |
| [src/emu/cpu/tlcs90] | tlcs90.c |
| [src/emu/cpu/tlcs900] | tlcs900.c |
| [src/emu/cpu/tms0980] | tms0980.c |
| [src/emu/cpu/tms32010] | tms32010.c |
| [src/emu/cpu/tms32025] | tms32025.c |
| [src/emu/cpu/tms32031] | tms32031.c |
| [src/emu/cpu/tms32051] | tms32051.c |
| [src/emu/cpu/tms34010] | 34010gfx.c 34010ops.h tms34010.c tms34010.h |
| [src/emu/cpu/tms57002] | tms57002.c |
| [src/emu/cpu/tms7000] | tms7000.c |
| [src/emu/cpu/tms9900] | 99xxcore.h |
| [src/emu/cpu/unsp] | unsp.c unsp.h |
| [src/emu/cpu/upd7810] | upd7810.c |
| [src/emu/cpu/v30mz] | v30mz.c v30mz.h |
| [src/emu/cpu/v60] | v60.c v60mem.c |
| [src/emu/cpu/v810] | v810.c |
| [src/emu/cpu/z180] | z180.c z180ops.h |
| [src/emu/cpu/z8] | z8.c z8ops.c |
| [src/emu/cpu/z80] | z80.c |
| [src/emu/cpu/z8000] | z8000.c |
| [src/emu/debug] | debugcmd.c debugcmd.h debugcmt.c debugcpu.c debugcpu.h dvdisasm.c dvdisasm.h dvmemory.c dvmemory.h |
| [src/emu/machine] | at28c16.c eeprom.c generic.c i2cmem.c idectrl.c latch8.c tmp68301.c tmp68301.h |
| [src/emu/sound] | bsmt2000.c k053260.c msm5232.c namco.c nes_apu.c nes_defs.h okim6295.c okim6295.h s2636.c* s2636.h* scsp.c sound.mak vlm5030.c vrender0.c ymf278b.c |
| [src/emu/video] | mc6845.c mc6845.h pc_vga.c s2636.c s2636.h tlc34076.c tlc34076.h tms34061.c tms34061.h tms9927.c tms9927.h vector.c vector.h |
| [src/mame/includes] | atari.h neogeo.h |
| [src/mame/machine] | amiga.c archimds.c atari.c cubocd32.c cx4fn.c cx4oam.c dc.c kabuki.c n64.c neoboot.c neoprot.c pcshare.c scudsp.c scudsp.h snes.c snes7110.c snescx4.c snesrtc.c snessdd1.c |
| [src/mame/video] | astrocde.c atari.c dc.c gtia.c gtia.h jaguar.c neogeo.c ppu2c0x.c ppu2c0x.h psx.c snes.c vdc.c |
| [src/mess/audio] | svision.c vp550.c vp550.h vp595.c vp595.h |
| [src/mess/devices] | ti99_peb.c z80bin.c |
| [src/mess/drivers] | a2600.c a7000.c abc80x.c apexc.c apricot.c aquarius.c atarist.c atm.c atom.c avigo.c bw12.c camplynx.c cosmicos.c crvision.c elf.c elwro800.c enterp.c exp85.c fk1.c fm7.c fmtowns.c gba.c gp32.c ip22.c kyocera.c lc80.c lynx.c mc10.c mc1000.c mikromik.c mpf1.c multi8.c nanos.c nc.c newbrain.c ng_aes.c osi.c p8k.c palm.c pasopia.c pc6001.c pc8001.c pc8401a.c pc98.c pce220.c pcw.c pcw16.c pentagon.c prestige.c prof80.c psion.c psx.c px4.c px8.c ql.c qx10.c rx78.c samcoupe.c saturn.c scorpion.c sg1000.c spc1000.c specpls3.c spectrum.c supracan.c tandy2k.c ti89.c tiki100.c timex.c tmc600.c trs80m2.c tvc.c v1050.c vc4000.c vcs80.c vectrex.c vg5k.c vic20.c victor9k.c vii.c vip.c vt520.c vtech1.c x1.c x68k.c xerox820.c xor100.c |
| [src/mess/formats] | cbm_snqk.c comx35_comx.c m65_snqk.c spec_snqk.c trs_cmd.c |
| [src/mess/includes] | fmtowns.h samcoupe.h |
| [src/mess/machine] | 990_hd.c 990_tap.c 99_usbsm.c a7800.c aim65.c amigacd.c amigafdc.c amstrad.c apple1.c apple2.c apple2gs.c apple3.c at.c ataricrt.c b2m.c bbc.c bebox.c c128.c c1551.c c16.c c64.c c65.c cgenie.c coco.c comx35.c conkort.c dgn_beta.c exidy.c galaxy.c gb.c hd63450.c hec2hrp.c hp48.c i82439tx.c jupiter.c kaypro.c kc.c lisa.c llc.c lviv.c mac.c mbee.c microtan.c mpc105.c msx_slot.c mtx.c mz700.c nascom1.c nes.c nes_pcb.c oric.c orion.c osborne1.c partner.c pc.c pc1350.c pc8801.c pdp1.c pecom.c pk8020.c pmd85.c pokemini.c poly88.c pp01.c primo.c radio86.c rmnimbus.c samcoupe.c sms.c snescart.c special.c sym1.c tf20.c thomson.c ti85.c ti99_4x.c trs80.c upd71071.c vector06.c vectrex.c vic1112.c wswan.c z80ne.c zx.c |
| [src/mess/video] | 911_vdt.c a7800.c ac1.c apple3.c atarist.c dai.c galaxy.c gb.c hd61830.c homelab.c hp48.c irisha.c kramermc.c mz80.c newbrain.c oric.c pc_aga.c pc_cga.c pc_ega.c pc_mda.c pc_vga_mess.c ti85.c upd7220.c |
| r8806 | r8807 | |
|---|---|---|
| 312 | 312 | return 0; |
| 313 | 313 | } |
| 314 | 314 | |
| 315 | void dsp_prg_ctrl( | |
| 315 | void dsp_prg_ctrl( | |
| 316 | 316 | { |
| 317 | 317 | if(LEF) dsp_reg.pc = (data & 0xff); |
| 318 | 318 | if(EXF) dsp_execute_program(space); |
| r8806 | r8807 | |
| 590 | 590 | } |
| 591 | 591 | |
| 592 | 592 | |
| 593 | static void dsp_dma( | |
| 593 | static void dsp_dma( | |
| 594 | 594 | { |
| 595 | 595 | UINT8 hold = (opcode & 0x4000) >> 14; |
| 596 | 596 | UINT32 add = (opcode & 0x38000) >> 15; |
| r8806 | r8807 | |
| 649 | 649 | |
| 650 | 650 | if ( source >= 0x06000000 && source <= 0x060fffff ) |
| 651 | 651 | { |
| 652 | data = | |
| 652 | data = space->r | |
| 653 | 653 | } |
| 654 | 654 | else |
| 655 | 655 | { |
| r8806 | r8807 | |
| 687 | 687 | #endif |
| 688 | 688 | for ( counter = 0; counter < transfer_cnt; counter++ ) |
| 689 | 689 | { |
| 690 | | |
| 690 | space-> | |
| 691 | 691 | dest += add; |
| 692 | 692 | } |
| 693 | 693 | |
| r8806 | r8807 | |
| 786 | 786 | } |
| 787 | 787 | #endif |
| 788 | 788 | |
| 789 | void dsp_execute_program( | |
| 789 | void dsp_execute_program( | |
| 790 | 790 | { |
| 791 | 791 | UINT32 cycles_run = 0; |
| 792 | 792 | UINT8 cont = 1; |
| r8806 | r8807 | |
|---|---|---|
| 469 | 469 | timer_adjust_oneshot( akiko.dma_timer, ATTOTIME_IN_USEC( CD_SECTOR_TIME / akiko.cdrom_speed ), 0 ); |
| 470 | 470 | } |
| 471 | 471 | |
| 472 | static void akiko_setup_response( | |
| 472 | static void akiko_setup_response( | |
| 473 | 473 | { |
| 474 | 474 | int resp_addr = akiko.cdrom_address[1]; |
| 475 | 475 | UINT8 resp_csum = 0xff; |
| r8806 | r8807 | |
| 488 | 488 | |
| 489 | 489 | for( i = 0; i < len; i++ ) |
| 490 | 490 | { |
| 491 | | |
| 491 | space-> | |
| 492 | 492 | } |
| 493 | 493 | |
| 494 | 494 | akiko.cdrom_cmd_resp = (akiko.cdrom_cmd_resp+len) & 0xff; |
| r8806 | r8807 | |
| 516 | 516 | |
| 517 | 517 | if ( param == 0x05 ) |
| 518 | 518 | { |
| 519 | | |
| 519 | | |
| 520 | 520 | if (LOG_AKIKO_CD) logerror( "AKIKO: Completing Command %d\n", param ); |
| 521 | 521 | |
| 522 | 522 | resp[0] = 0x06; |
| r8806 | r8807 | |
| 538 | 538 | } |
| 539 | 539 | } |
| 540 | 540 | |
| 541 | static void akiko_update_cdrom( | |
| 541 | static void akiko_update_cdrom( | |
| 542 | 542 | { |
| 543 | 543 | UINT8 resp[32], cmdbuf[32]; |
| 544 | 544 | |
| r8806 | r8807 | |
| 548 | 548 | while ( akiko.cdrom_cmd_start != akiko.cdrom_cmd_end ) |
| 549 | 549 | { |
| 550 | 550 | UINT32 cmd_addr = akiko.cdrom_address[1] + 0x200 + akiko.cdrom_cmd_start; |
| 551 | int cmd = | |
| 551 | int cmd = space->r | |
| 552 | 552 | |
| 553 | 553 | memset( resp, 0, sizeof( resp ) ); |
| 554 | 554 | resp[0] = cmd; |
| r8806 | r8807 | |
| 590 | 590 | |
| 591 | 591 | for( i = 0; i < 13; i++ ) |
| 592 | 592 | { |
| 593 | cmdbuf[i] = | |
| 593 | cmdbuf[i] = space->r | |
| 594 | 594 | cmd_addr &= 0xffffff00; |
| 595 | 595 | cmd_addr += ( akiko.cdrom_cmd_start + i + 1 ) & 0xff; |
| 596 | 596 | } |
| r8806 | r8807 | |
|---|---|---|
| 1 | 1 | /*SCU DSP stuff*/ |
| 2 | 2 | |
| 3 | extern void dsp_prg_ctrl( | |
| 3 | extern void dsp_prg_ctrl( | |
| 4 | 4 | extern void dsp_prg_data(UINT32 data); |
| 5 | 5 | extern void dsp_ram_addr_ctrl(UINT32 data); |
| 6 | 6 | extern void dsp_ram_addr_w(UINT32 data); |
| 7 | 7 | extern UINT32 dsp_ram_addr_r(void); |
| 8 | extern void dsp_execute_program( | |
| 8 | extern void dsp_execute_program( | |
| 9 | 9 |
| r8806 | r8807 | |
|---|---|---|
| 767 | 767 | } |
| 768 | 768 | |
| 769 | 769 | static void spc7110_mmio_write(running_machine *machine, UINT32 addr, UINT8 data); |
| 770 | static UINT8 spc7110_mmio_read( | |
| 770 | static UINT8 spc7110_mmio_read( | |
| 771 | 771 | static void spc7110_update_time(running_machine *machine, UINT8 offset); |
| 772 | 772 | |
| 773 | 773 | enum RTC_State |
| r8806 | r8807 | |
| 1066 | 1066 | } |
| 1067 | 1067 | } |
| 1068 | 1068 | |
| 1069 | static UINT8 spc7110_mmio_read( | |
| 1069 | static UINT8 spc7110_mmio_read( | |
| 1070 | 1070 | { |
| 1071 | 1071 | running_machine *machine = space->machine; |
| 1072 | 1072 | UINT8 *ROM = memory_region(machine, "cart"); |
| r8806 | r8807 | |
| 1639 | 1639 | } |
| 1640 | 1640 | } |
| 1641 | 1641 | |
| 1642 | static UINT8 spc7110_bank7_read( | |
| 1642 | static UINT8 spc7110_bank7_read( | |
| 1643 | 1643 | { |
| 1644 | 1644 | UINT8 *ROM = memory_region(space->machine, "cart"); |
| 1645 | 1645 | UINT32 addr = offset & 0x0fffff; |
| r8806 | r8807 | |
|---|---|---|
| 569 | 569 | snes_sdd1.buffer.ready = 0; |
| 570 | 570 | } |
| 571 | 571 | |
| 572 | static UINT8 sdd1_mmio_read( | |
| 572 | static UINT8 sdd1_mmio_read( | |
| 573 | 573 | { |
| 574 | 574 | addr &= 0xffff; |
| 575 | 575 | |
| r8806 | r8807 | |
| 593 | 593 | return snes_open_bus_r(space, 0); |
| 594 | 594 | } |
| 595 | 595 | |
| 596 | static void sdd1_mmio_write( | |
| 596 | static void sdd1_mmio_write( | |
| 597 | 597 | { |
| 598 | 598 | addr &= 0xffff; |
| 599 | 599 |
| r8806 | r8807 | |
|---|---|---|
| 314 | 314 | } |
| 315 | 315 | |
| 316 | 316 | |
| 317 | static UINT8 console_read( | |
| 317 | static UINT8 console_read( | |
| 318 | 318 | { |
| 319 | 319 | return input_port_read(space->machine, "console"); |
| 320 | 320 | } |
| 321 | 321 | |
| 322 | 322 | |
| 323 | static void console_write( | |
| 323 | static void console_write( | |
| 324 | 324 | { |
| 325 | 325 | running_device *dac = space->machine->device("dac"); |
| 326 | 326 | if (data & 0x08) |
| r8806 | r8807 | |
|---|---|---|
| 101 | 101 | UINT8 Color; |
| 102 | 102 | INT32 i; |
| 103 | 103 | |
| 104 | address_space *space = machine->device<cpu_device>("maincpu")->space(AS_PROGRAM); | |
| 104 | 105 | for(i = cx4.ram[0x0295]; i > 0; i--, line += 5) |
| 105 | 106 | { |
| 106 | if(memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), line) == 0xff && | |
| 107 | memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), line + 1) == 0xff) | |
| 107 | if(space->read_byte(line) == 0xff && | |
| 108 | space->read_byte(line + 1) == 0xff) | |
| 108 | 109 | { |
| 109 | 110 | INT32 tmp = line - 5; |
| 110 | while(memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), tmp + 2) == 0xff && | |
| 111 | memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), tmp + 3) == 0xff && | |
| 111 | while(space->read_byte(tmp + 2) == 0xff && | |
| 112 | space->read_byte(tmp + 3) == 0xff && | |
| 112 | 113 | (tmp + 2) >= 0) |
| 113 | 114 | { |
| 114 | 115 | tmp -= 5; |
| 115 | 116 | } |
| 116 | 117 | point1 = (CX4_read(0x1f82) << 16) | |
| 117 | (memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), tmp + 2) << 8) | | |
| 118 | memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), tmp + 3); | |
| 118 | (space->read_byte(tmp + 2) << 8) | | |
| 119 | space->read_byte(tmp + 3); | |
| 119 | 120 | } |
| 120 | 121 | else |
| 121 | 122 | { |
| 122 | 123 | point1 = (CX4_read(0x1f82) << 16) | |
| 123 | (memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), line) << 8) | | |
| 124 | memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), line + 1); | |
| 124 | (space->read_byte(line) << 8) | | |
| 125 | space->read_byte(line + 1); | |
| 125 | 126 | } |
| 126 | 127 | point2 = (CX4_read(0x1f82) << 16) | |
| 127 | (memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), line + 2) << 8) | | |
| 128 | memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), line + 3); | |
| 128 | (space->read_byte(line + 2) << 8) | | |
| 129 | space->read_byte(line + 3); | |
| 129 | 130 | |
| 130 | X1=(memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), point1 + 0) << 8) | | |
| 131 | memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), point1 + 1); | |
| 132 | Y1=(memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), point1 + 2) << 8) | | |
| 133 | memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), point1 + 3); | |
| 134 | Z1=(memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), point1 + 4) << 8) | | |
| 135 | memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), point1 + 5); | |
| 136 | X2=(memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), point2 + 0) << 8) | | |
| 137 | memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), point2 + 1); | |
| 138 | Y2=(memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), point2 + 2) << 8) | | |
| 139 | memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), point2 + 3); | |
| 140 | Z2=(memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), point2 + 4) << 8) | | |
| 141 | memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), point2 + 5); | |
| 142 | Color = memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), line + 4); | |
| 131 | X1=(space->read_byte(point1 + 0) << 8) | | |
| 132 | space->read_byte(point1 + 1); | |
| 133 | Y1=(space->read_byte(point1 + 2) << 8) | | |
| 134 | space->read_byte(point1 + 3); | |
| 135 | Z1=(space->read_byte(point1 + 4) << 8) | | |
| 136 | space->read_byte(point1 + 5); | |
| 137 | X2=(space->read_byte(point2 + 0) << 8) | | |
| 138 | space->read_byte(point2 + 1); | |
| 139 | Y2=(space->read_byte(point2 + 2) << 8) | | |
| 140 | space->read_byte(point2 + 3); | |
| 141 | Z2=(space->read_byte(point2 + 4) << 8) | | |
| 142 | space->read_byte(point2 + 5); | |
| 143 | Color = space->read_byte(line + 4); | |
| 143 | 144 | CX4_C4DrawLine(X1, Y1, Z1, X2, Y2, Z2, Color); |
| 144 | 145 | } |
| 145 | 146 | } |
| r8806 | r8807 | |
|---|---|---|
| 139 | 139 | |
| 140 | 140 | static UINT16 kof10thExtraRAMB[0x01000]; |
| 141 | 141 | |
| 142 | static void kof10thBankswitch( | |
| 142 | static void kof10thBankswitch( | |
| 143 | 143 | { |
| 144 | 144 | UINT32 bank = 0x100000 + ((nBank & 7) << 20); |
| 145 | 145 | if (bank >= 0x700000) |
| r8806 | r8807 | |
|---|---|---|
| 161 | 161 | |
| 162 | 162 | static void mitchell_decode(running_machine *machine, int swap_key1,int swap_key2,int addr_key,int xor_key) |
| 163 | 163 | { |
| 164 | | |
| 164 | | |
| 165 | 165 | UINT8 *rom = memory_region(machine, "maincpu"); |
| 166 | 166 | UINT8 *decrypt = auto_alloc_array(machine, UINT8, memory_region_length(machine, "maincpu")); |
| 167 | 167 | int numbanks = (memory_region_length(machine, "maincpu") - 0x10000) / 0x4000; |
| r8806 | r8807 | |
| 202 | 202 | |
| 203 | 203 | static void cps1_decode(running_machine *machine,int swap_key1,int swap_key2,int addr_key,int xor_key) |
| 204 | 204 | { |
| 205 | | |
| 205 | | |
| 206 | 206 | UINT8 *decrypt = auto_alloc_array(machine, UINT8, 0x8000); |
| 207 | 207 | UINT8 *rom = memory_region(machine, "audiocpu"); |
| 208 | 208 |
| r8806 | r8807 | |
|---|---|---|
| 229 | 229 | dc_update_interrupt_status(machine); |
| 230 | 230 | } |
| 231 | 231 | |
| 232 | static void wave_dma_execute( | |
| 232 | static void wave_dma_execute( | |
| 233 | 233 | { |
| 234 | 234 | UINT32 src,dst,size; |
| 235 | 235 | dst = wave_dma.aica_addr; |
| r8806 | r8807 | |
| 243 | 243 | { |
| 244 | 244 | for(;size<wave_dma.size;size+=4) |
| 245 | 245 | { |
| 246 | | |
| 246 | space-> | |
| 247 | 247 | src+=4; |
| 248 | 248 | dst+=4; |
| 249 | 249 | } |
| r8806 | r8807 | |
| 252 | 252 | { |
| 253 | 253 | for(;size<wave_dma.size;size+=4) |
| 254 | 254 | { |
| 255 | | |
| 255 | space-> | |
| 256 | 256 | src+=4; |
| 257 | 257 | dst+=4; |
| 258 | 258 | } |
| r8806 | r8807 | |
| 268 | 268 | timer_set(space->machine, ATTOTIME_IN_USEC(300), NULL, 0, aica_dma_irq); |
| 269 | 269 | } |
| 270 | 270 | |
| 271 | static void pvr_dma_execute( | |
| 271 | static void pvr_dma_execute( | |
| 272 | 272 | { |
| 273 | 273 | UINT32 src,dst,size; |
| 274 | 274 | dst = pvr_dma.pvr_addr; |
| r8806 | r8807 | |
| 287 | 287 | { |
| 288 | 288 | for(;size<pvr_dma.size;size+=4) |
| 289 | 289 | { |
| 290 | | |
| 290 | space-> | |
| 291 | 291 | src+=4; |
| 292 | 292 | dst+=4; |
| 293 | 293 | } |
| r8806 | r8807 | |
| 296 | 296 | { |
| 297 | 297 | for(;size<pvr_dma.size;size+=4) |
| 298 | 298 | { |
| 299 | | |
| 299 | space-> | |
| 300 | 300 | src+=4; |
| 301 | 301 | dst+=4; |
| 302 | 302 | } |
| r8806 | r8807 | |
| 416 | 416 | { |
| 417 | 417 | if((dc_sysctrl_regs[SB_G2DTNRM] & dc_sysctrl_regs[SB_ISTNRM]) || (dc_sysctrl_regs[SB_G2DTEXT] & dc_sysctrl_regs[SB_ISTEXT])) |
| 418 | 418 | { |
| 419 | | |
| 419 | | |
| 420 | 420 | |
| 421 | 421 | printf("Wave DMA HW trigger\n"); |
| 422 | 422 | wave_dma_execute(space); |
| r8806 | r8807 | |
| 428 | 428 | { |
| 429 | 429 | if((dc_sysctrl_regs[SB_PDTNRM] & dc_sysctrl_regs[SB_ISTNRM]) || (dc_sysctrl_regs[SB_PDTEXT] & dc_sysctrl_regs[SB_ISTEXT])) |
| 430 | 430 | { |
| 431 | | |
| 431 | | |
| 432 | 432 | |
| 433 | 433 | printf("PVR-DMA HW trigger\n"); |
| 434 | 434 | pvr_dma_execute(space); |
| r8806 | r8807 | |
|---|---|---|
| 1303 | 1303 | { |
| 1304 | 1304 | for (i=0; i < dma_length; i++) |
| 1305 | 1305 | { |
| 1306 | UINT8 b = memory_read_byte(space, pi_dram_addr); | |
| 1307 | memory_write_byte(space, pi_cart_addr & 0x1fffffff, b); | |
| 1306 | UINT8 b = space->read_byte(pi_dram_addr); | |
| 1307 | space->write_byte(pi_cart_addr & 0x1fffffff, b); | |
| 1308 | 1308 | pi_cart_addr += 1; |
| 1309 | 1309 | pi_dram_addr += 1; |
| 1310 | 1310 | } |
| r8806 | r8807 | |
| 1331 | 1331 | { |
| 1332 | 1332 | for (i=0; i < dma_length; i++) |
| 1333 | 1333 | { |
| 1334 | /*UINT32 d = memory_read_dword(space, pi_cart_addr); | |
| 1335 | memory_write_dword(space, pi_dram_addr, d); | |
| 1334 | /*UINT32 d = space->read_dword(pi_cart_addr); | |
| 1335 | space->write_dword(pi_dram_addr, d); | |
| 1336 | 1336 | pi_cart_addr += 4; |
| 1337 | 1337 | pi_dram_addr += 4;*/ |
| 1338 | 1338 | |
| 1339 | UINT8 b = memory_read_byte(space, pi_cart_addr); | |
| 1340 | memory_write_byte(space, pi_dram_addr & 0x1fffffff, b); | |
| 1339 | UINT8 b = space->read_byte(pi_cart_addr); | |
| 1340 | space->write_byte(pi_dram_addr & 0x1fffffff, b); | |
| 1341 | 1341 | pi_cart_addr += 1; |
| 1342 | 1342 | pi_dram_addr += 1; |
| 1343 | 1343 | } |
| r8806 | r8807 | |
| 1347 | 1347 | if (pi_first_dma) |
| 1348 | 1348 | { |
| 1349 | 1349 | // TODO: CIC-6105 has different address... |
| 1350 | memory_write_dword(space, 0x00000318, 0x400000); | |
| 1351 | memory_write_dword(space, 0x000003f0, 0x800000); | |
| 1350 | space->write_dword(0x00000318, 0x400000); | |
| 1351 | space->write_dword(0x000003f0, 0x800000); | |
| 1352 | 1352 | pi_first_dma = 0; |
| 1353 | 1353 | } |
| 1354 | 1354 | |
| r8806 | r8807 | |
| 1965 | 1965 | READ32_HANDLER( n64_pif_ram_r ) |
| 1966 | 1966 | { |
| 1967 | 1967 | /*mame_printf_debug( "pif_ram_r: %08X, %08X = %08X\n", offset << 2, mem_mask, ( ( pif_ram[offset*4+0] << 24 ) | ( pif_ram[offset*4+1] << 16 ) | ( pif_ram[offset*4+2] << 8 ) | ( pif_ram[offset*4+3] << 0 ) ) & mem_mask );*/ |
| 1968 | if(!space->debugger_access) | |
| 1968 | if(!space->debugger_access()) | |
| 1969 | 1969 | { |
| 1970 | 1970 | if( offset == ( 0x24 / 4 ) ) |
| 1971 | 1971 | { |
| r8806 | r8807 | |
|---|---|---|
| 109 | 109 | return (sum + 1) % 7; // 1900-01-01 was a Monday |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | static UINT8 srtc_read( | |
| 112 | static UINT8 srtc_read( | |
| 113 | 113 | { |
| 114 | 114 | addr &= 0xffff; |
| 115 | 115 |
| r8806 | r8807 | |
|---|---|---|
| 108 | 108 | count = (cx4.reg[0x43]) | (cx4.reg[0x44] << 8); |
| 109 | 109 | dest = (cx4.reg[0x45]) | (cx4.reg[0x46] << 8); |
| 110 | 110 | |
| 111 | address_space *space = machine->device<cpu_device>("maincpu")->space(AS_PROGRAM); | |
| 111 | 112 | for(i=0;i<count;i++) |
| 112 | 113 | { |
| 113 | CX4_write(machine, dest++, | |
| 114 | CX4_write(machine, dest++, space->r | |
| 114 | 115 | } |
| 115 | 116 | } |
| 116 | 117 |
| r8806 | r8807 | |
|---|---|---|
| 26 | 26 | /* -- Globals -- */ |
| 27 | 27 | UINT8 *snes_ram = NULL; /* 65816 ram */ |
| 28 | 28 | |
| 29 | static void snes_dma(const address_space *space, UINT8 channels); | |
| 30 | static void snes_hdma_init(const address_space *space); | |
| 31 | static void snes_hdma(const address_space *space); | |
| 29 | static void snes_dma(address_space *space, UINT8 channels); | |
| 30 | static void snes_hdma_init(address_space *space); | |
| 31 | static void snes_hdma(address_space *space); | |
| 32 | 32 | |
| 33 | 33 | static READ8_HANDLER(snes_io_dma_r); |
| 34 | 34 | static WRITE8_HANDLER(snes_io_dma_w); |
| r8806 | r8807 | |
| 88 | 88 | { |
| 89 | 89 | snes_state *state = machine->driver_data<snes_state>(); |
| 90 | 90 | // make sure we're in the 65816's context since we're messing with the OAM and stuff |
| 91 | | |
| 91 | | |
| 92 | 92 | |
| 93 | 93 | if (!(snes_ppu.screen_disabled)) //Reset OAM address, byuu says it happens at H=10 |
| 94 | 94 | { |
| 95 | memory_write_byte(space, OAMADDL, snes_ppu.oam.saved_address_low); /* Reset oam address */ | |
| 96 | memory_write_byte(space, OAMADDH, snes_ppu.oam.saved_address_high); | |
| 95 | space->write_byte(OAMADDL, snes_ppu.oam.saved_address_low); /* Reset oam address */ | |
| 96 | space->write_byte(OAMADDH, snes_ppu.oam.saved_address_high); | |
| 97 | 97 | snes_ppu.oam.first_sprite = snes_ppu.oam.priority_rotation ? (snes_ppu.oam.address >> 1) & 127 : 0; |
| 98 | 98 | } |
| 99 | 99 | } |
| r8806 | r8807 | |
| 101 | 101 | static TIMER_CALLBACK( snes_reset_hdma ) |
| 102 | 102 | { |
| 103 | 103 | snes_state *state = machine->driver_data<snes_state>(); |
| 104 | | |
| 104 | | |
| 105 | 105 | snes_hdma_init(cpu0space); |
| 106 | 106 | } |
| 107 | 107 | |
| 108 | 108 | static TIMER_CALLBACK( snes_update_io ) |
| 109 | 109 | { |
| 110 | 110 | snes_state *state = machine->driver_data<snes_state>(); |
| 111 | | |
| 111 | | |
| 112 | 112 | state->io_read(cpu0space->machine); |
| 113 | 113 | snes_ram[HVBJOY] &= 0xfe; /* Clear busy bit */ |
| 114 | 114 | |
| r8806 | r8807 | |
| 186 | 186 | // hdma reset happens at scanline 0, H=~6 |
| 187 | 187 | if (snes_ppu.beam.current_vert == 0) |
| 188 | 188 | { |
| 189 | | |
| 189 | | |
| 190 | 190 | snes_hdma_init(cpu0space); |
| 191 | 191 | } |
| 192 | 192 | |
| r8806 | r8807 | |
| 210 | 210 | static TIMER_CALLBACK( snes_hblank_tick ) |
| 211 | 211 | { |
| 212 | 212 | snes_state *state = machine->driver_data<snes_state>(); |
| 213 | | |
| 213 | | |
| 214 | 214 | int nextscan; |
| 215 | 215 | |
| 216 | 216 | snes_ppu.beam.current_vert = machine->primary_screen->vpos(); |
| r8806 | r8807 | |
| 296 | 296 | return 0xff; |
| 297 | 297 | |
| 298 | 298 | recurse = 1; |
| 299 | result = | |
| 299 | result = space->r | |
| 300 | 300 | recurse = 0; |
| 301 | 301 | return result; |
| 302 | 302 | } |
| r8806 | r8807 | |
| 476 | 476 | switch (offset) |
| 477 | 477 | { |
| 478 | 478 | case WMDATA: /* Data to read from WRAM */ |
| 479 | value = | |
| 479 | value = space->r | |
| 480 | 480 | state->wram_address &= 0x1ffff; |
| 481 | 481 | return value; |
| 482 | 482 | case OLDJOY1: /* Data for old NES controllers (JOYSER1) */ |
| r8806 | r8807 | |
| 625 | 625 | switch (offset) |
| 626 | 626 | { |
| 627 | 627 | case WMDATA: /* Data to write to WRAM */ |
| 628 | | |
| 628 | space-> | |
| 629 | 629 | state->wram_address &= 0x1ffff; |
| 630 | 630 | return; |
| 631 | 631 | case WMADDL: /* Address to read/write to wram (low) */ |
| r8806 | r8807 | |
| 914 | 914 | UINT16 address = offset & 0xffff; |
| 915 | 915 | |
| 916 | 916 | if (address < 0x2000) /* Mirror of Low RAM */ |
| 917 | value = | |
| 917 | value = space->r | |
| 918 | 918 | else if (address < 0x6000) /* I/O */ |
| 919 | 919 | { |
| 920 | 920 | if (state->cart[0].mode == SNES_MODE_BSX && address >= 0x5000) |
| r8806 | r8807 | |
| 957 | 957 | else |
| 958 | 958 | value = snes_ram[offset]; |
| 959 | 959 | |
| 960 | if(!space->debugger_access) | |
| 960 | if(!space->debugger_access()) | |
| 961 | 961 | cpu_adjust_icount(space->cpu, -snes_bank_0x00_0x3f_cycles(space->machine, offset)); |
| 962 | 962 | |
| 963 | 963 | return value; |
| r8806 | r8807 | |
| 971 | 971 | UINT16 address = offset & 0xffff; |
| 972 | 972 | |
| 973 | 973 | if (address < 0x2000) /* Mirror of Low RAM */ |
| 974 | value = | |
| 974 | value = space->r | |
| 975 | 975 | else if (address < 0x6000) /* I/O */ |
| 976 | 976 | { |
| 977 | 977 | if (state->cart[0].mode == SNES_MODE_BSX && address >= 0x5000) |
| r8806 | r8807 | |
| 1020 | 1020 | else |
| 1021 | 1021 | value = snes_ram[0x300000 + offset]; |
| 1022 | 1022 | |
| 1023 | if(!space->debugger_access) | |
| 1023 | if(!space->debugger_access()) | |
| 1024 | 1024 | cpu_adjust_icount(space->cpu, -snes_bank_0x00_0x3f_cycles(space->machine, offset)); |
| 1025 | 1025 | |
| 1026 | 1026 | return value; |
| r8806 | r8807 | |
| 1061 | 1061 | else /* Mode 21 & 25 + SuperFX games */ |
| 1062 | 1062 | value = snes_ram[0x400000 + offset]; |
| 1063 | 1063 | |
| 1064 | if(!space->debugger_access) | |
| 1064 | if(!space->debugger_access()) | |
| 1065 | 1065 | cpu_adjust_icount(space->cpu, -8); |
| 1066 | 1066 | |
| 1067 | 1067 | return value; |
| r8806 | r8807 | |
| 1099 | 1099 | else if (state->cart[0].mode & 0x0a) /* Mode 21 & 25 */ |
| 1100 | 1100 | value = snes_ram[0x600000 + offset]; |
| 1101 | 1101 | |
| 1102 | if(!space->debugger_access) | |
| 1102 | if(!space->debugger_access()) | |
| 1103 | 1103 | cpu_adjust_icount(space->cpu, -8); |
| 1104 | 1104 | |
| 1105 | 1105 | return value; |
| r8806 | r8807 | |
| 1135 | 1135 | else |
| 1136 | 1136 | value = snes_ram[0x700000 + offset]; |
| 1137 | 1137 | |
| 1138 | if(!space->debugger_access) | |
| 1138 | if(!space->debugger_access()) | |
| 1139 | 1139 | cpu_adjust_icount(space->cpu, -8); |
| 1140 | 1140 | |
| 1141 | 1141 | return value; |
| r8806 | r8807 | |
| 1149 | 1149 | UINT16 address = offset & 0xffff; |
| 1150 | 1150 | |
| 1151 | 1151 | if (state->has_addon_chip == HAS_SUPERFX) |
| 1152 | value = | |
| 1152 | value = space->r | |
| 1153 | 1153 | else if (address < 0x8000) |
| 1154 | 1154 | { |
| 1155 | 1155 | if (state->cart[0].mode != SNES_MODE_25) |
| 1156 | value = | |
| 1156 | value = space->r | |
| 1157 | 1157 | else if ((state->has_addon_chip == HAS_CX4) && (address >= 0x6000)) |
| 1158 | 1158 | value = CX4_read(address - 0x6000); |
| 1159 | 1159 | else /* Mode 25 has SRAM not mirrored from lower banks */ |
| 1160 | 1160 | { |
| 1161 | 1161 | if (address < 0x6000) |
| 1162 | value = | |
| 1162 | value = space->r | |
| 1163 | 1163 | else if ((offset >= 0x300000) && (state->cart[0].sram > 0)) |
| 1164 | 1164 | { |
| 1165 | 1165 | // int mask = state->cart[0].sram - 1; /* Limit SRAM size to what's actually present */ |
| r8806 | r8807 | |
| 1183 | 1183 | else |
| 1184 | 1184 | value = snes_ram[0x800000 + offset]; |
| 1185 | 1185 | |
| 1186 | if(!space->debugger_access) | |
| 1186 | if(!space->debugger_access()) | |
| 1187 | 1187 | cpu_adjust_icount(space->cpu, -snes_bank_0x80_0xbf_cycles(space->machine, offset)); |
| 1188 | 1188 | |
| 1189 | 1189 | return value; |
| r8806 | r8807 | |
| 1229 | 1229 | else if ((state->cart[0].mode & 5) && !(state->has_addon_chip == HAS_SUPERFX)) /* Mode 20 & 22 */ |
| 1230 | 1230 | { |
| 1231 | 1231 | if (address < 0x8000) |
| 1232 | value = | |
| 1232 | value = space->r | |
| 1233 | 1233 | else |
| 1234 | 1234 | value = snes_ram[0xc00000 + offset]; |
| 1235 | 1235 | } |
| 1236 | 1236 | else /* Mode 21 & 25 + SuperFX Games */ |
| 1237 | 1237 | value = snes_ram[0xc00000 + offset]; |
| 1238 | 1238 | |
| 1239 | if(!space->debugger_access) | |
| 1239 | if(!space->debugger_access()) | |
| 1240 | 1240 | cpu_adjust_icount(space->cpu, -((snes_ram[MEMSEL] & 1) ? 6 : 8)); |
| 1241 | 1241 | |
| 1242 | 1242 | return value; |
| r8806 | r8807 | |
| 1250 | 1250 | UINT16 address = offset & 0xffff; |
| 1251 | 1251 | |
| 1252 | 1252 | if (address < 0x2000) /* Mirror of Low RAM */ |
| 1253 | | |
| 1253 | space-> | |
| 1254 | 1254 | else if (address < 0x6000) /* I/O */ |
| 1255 | 1255 | { |
| 1256 | 1256 | if (state->cart[0].mode == SNES_MODE_BSX && address >= 0x5000) |
| r8806 | r8807 | |
| 1290 | 1290 | else |
| 1291 | 1291 | logerror( "(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(space->cpu),offset ); |
| 1292 | 1292 | |
| 1293 | if(!space->debugger_access) | |
| 1293 | if(!space->debugger_access()) | |
| 1294 | 1294 | cpu_adjust_icount(space->cpu, -snes_bank_0x00_0x3f_cycles(space->machine, offset)); |
| 1295 | 1295 | } |
| 1296 | 1296 | |
| r8806 | r8807 | |
| 1301 | 1301 | UINT16 address = offset & 0xffff; |
| 1302 | 1302 | |
| 1303 | 1303 | if (address < 0x2000) /* Mirror of Low RAM */ |
| 1304 | | |
| 1304 | space-> | |
| 1305 | 1305 | else if (address < 0x6000) /* I/O */ |
| 1306 | 1306 | { |
| 1307 | 1307 | if (state->cart[0].mode == SNES_MODE_BSX && address >= 0x5000) |
| r8806 | r8807 | |
| 1347 | 1347 | else |
| 1348 | 1348 | logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(space->cpu),offset + 0x300000); |
| 1349 | 1349 | |
| 1350 | if(!space->debugger_access) | |
| 1350 | if(!space->debugger_access()) | |
| 1351 | 1351 | cpu_adjust_icount(space->cpu, -snes_bank_0x00_0x3f_cycles(space->machine, offset)); |
| 1352 | 1352 | } |
| 1353 | 1353 | |
| r8806 | r8807 | |
| 1373 | 1373 | else if (state->cart[0].mode & 0x0a) |
| 1374 | 1374 | logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(space->cpu),offset + 0x600000); |
| 1375 | 1375 | |
| 1376 | if(!space->debugger_access) | |
| 1376 | if(!space->debugger_access()) | |
| 1377 | 1377 | cpu_adjust_icount(space->cpu, -8); |
| 1378 | 1378 | } |
| 1379 | 1379 | |
| r8806 | r8807 | |
| 1398 | 1398 | else if (state->cart[0].mode & 0x0a) |
| 1399 | 1399 | logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(space->cpu),offset + 0x700000); |
| 1400 | 1400 | |
| 1401 | if(!space->debugger_access) | |
| 1401 | if(!space->debugger_access()) | |
| 1402 | 1402 | cpu_adjust_icount(space->cpu, -8); |
| 1403 | 1403 | } |
| 1404 | 1404 | |
| r8806 | r8807 | |
| 1410 | 1410 | UINT16 address = offset & 0xffff; |
| 1411 | 1411 | |
| 1412 | 1412 | if (state->has_addon_chip == HAS_SUPERFX) |
| 1413 | | |
| 1413 | space-> | |
| 1414 | 1414 | else if (address < 0x8000) |
| 1415 | 1415 | { |
| 1416 | 1416 | if ((state->has_addon_chip == HAS_CX4) && (address >= 0x6000)) |
| 1417 | 1417 | CX4_write(space->machine, address - 0x6000, data); |
| 1418 | 1418 | else if (state->cart[0].mode != SNES_MODE_25) |
| 1419 | | |
| 1419 | space-> | |
| 1420 | 1420 | else /* Mode 25 has SRAM not mirrored from lower banks */ |
| 1421 | 1421 | { |
| 1422 | 1422 | if (address < 0x6000) |
| 1423 | | |
| 1423 | space-> | |
| 1424 | 1424 | else if ((offset >= 0x300000) && (state->cart[0].sram > 0)) |
| 1425 | 1425 | { |
| 1426 | 1426 | // int mask = state->cart[0].sram - 1; /* Limit SRAM size to what's actually present */ |
| r8806 | r8807 | |
| 1446 | 1446 | else |
| 1447 | 1447 | logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(space->cpu),offset + 0x800000); |
| 1448 | 1448 | |
| 1449 | if(!space->debugger_access) | |
| 1449 | if(!space->debugger_access()) | |
| 1450 | 1450 | cpu_adjust_icount(space->cpu, -snes_bank_0x80_0xbf_cycles(space->machine, offset)); |
| 1451 | 1451 | } |
| 1452 | 1452 | |
| r8806 | r8807 | |
| 1486 | 1486 | else if (state->cart[0].mode & 0x0a) |
| 1487 | 1487 | logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(space->cpu),offset + 0xc00000); |
| 1488 | 1488 | |
| 1489 | if(!space->debugger_access) | |
| 1489 | if(!space->debugger_access()) | |
| 1490 | 1490 | cpu_adjust_icount(space->cpu, -((snes_ram[MEMSEL] & 1) ? 6 : 8)); |
| 1491 | 1491 | } |
| 1492 | 1492 | |
| r8806 | r8807 | |
| 1604 | 1604 | static void snes_init_ram( running_machine *machine ) |
| 1605 | 1605 | { |
| 1606 | 1606 | snes_state *state = machine->driver_data<snes_state>(); |
| 1607 | | |
| 1607 | | |
| 1608 | 1608 | int i; |
| 1609 | 1609 | |
| 1610 | 1610 | /* Init work RAM - 0x55 isn't exactly right but it's close */ |
| 1611 | 1611 | /* make sure it happens to the 65816 (CPU 0) */ |
| 1612 | 1612 | for (i = 0; i < (128*1024); i++) |
| 1613 | 1613 | { |
| 1614 | | |
| 1614 | cpu0space-> | |
| 1615 | 1615 | } |
| 1616 | 1616 | |
| 1617 | 1617 | /* Inititialize registers/variables */ |
| r8806 | r8807 | |
| 1677 | 1677 | } |
| 1678 | 1678 | |
| 1679 | 1679 | |
| 1680 | ||
| 1680 | ||
| 1681 | 1681 | { |
| 1682 | direct | |
| 1682 | direct. | |
| 1683 | 1683 | return ~0; |
| 1684 | 1684 | } |
| 1685 | 1685 | |
| 1686 | ||
| 1686 | ||
| 1687 | 1687 | { |
| 1688 | direct | |
| 1688 | direct. | |
| 1689 | 1689 | return ~0; |
| 1690 | 1690 | } |
| 1691 | 1691 | |
| r8806 | r8807 | |
| 1694 | 1694 | snes_state *state = machine->driver_data<snes_state>(); |
| 1695 | 1695 | int i; |
| 1696 | 1696 | |
| 1697 | memory_set_direct_update_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), snes_direct); | |
| 1698 | memory_set_direct_update_handler(cputag_get_address_space(machine, "soundcpu", ADDRESS_SPACE_PROGRAM), spc_direct); | |
| 1699 | ||
| 1700 | 1697 | state->maincpu = machine->device<_5a22_device>("maincpu"); |
| 1701 | 1698 | state->soundcpu = machine->device<spc700_device>("soundcpu"); |
| 1702 | 1699 | state->spc700 = machine->device<snes_sound_sound_device>("spc700"); |
| 1703 | 1700 | state->superfx = machine->device<cpu_device>("superfx"); |
| 1704 | 1701 | |
| 1702 | state->maincpu->space(AS_PROGRAM)->set_direct_update_handler(direct_update_delegate_create_static(snes_direct, *machine)); | |
| 1703 | state->soundcpu->space(AS_PROGRAM)->set_direct_update_handler(direct_update_delegate_create_static(snes_spc_direct, *machine)); | |
| 1704 | ||
| 1705 | 1705 | // power-on sets these registers like this |
| 1706 | 1706 | snes_ram[WRIO] = 0xff; |
| 1707 | 1707 | snes_ram[WRMPYA] = 0xff; |
| r8806 | r8807 | |
| 1836 | 1836 | DRIVER_INIT( snes ) |
| 1837 | 1837 | { |
| 1838 | 1838 | snes_state *state = machine->driver_data<snes_state>(); |
| 1839 | | |
| 1839 | | |
| 1840 | 1840 | UINT16 total_blocks, read_blocks; |
| 1841 | 1841 | UINT8 *rom; |
| 1842 | 1842 | |
| r8806 | r8807 | |
| 1902 | 1902 | DRIVER_INIT( snes_hirom ) |
| 1903 | 1903 | { |
| 1904 | 1904 | snes_state *state = machine->driver_data<snes_state>(); |
| 1905 | | |
| 1905 | | |
| 1906 | 1906 | UINT16 total_blocks, read_blocks; |
| 1907 | 1907 | UINT8 *rom; |
| 1908 | 1908 | |
| r8806 | r8807 | |
| 1976 | 1976 | return 1; |
| 1977 | 1977 | } |
| 1978 | 1978 | |
| 1979 | INLINE UINT8 snes_abus_read( | |
| 1979 | INLINE UINT8 snes_abus_read( | |
| 1980 | 1980 | { |
| 1981 | 1981 | if (!dma_abus_valid(abus)) |
| 1982 | 1982 | return 0; |
| 1983 | 1983 | |
| 1984 | return | |
| 1984 | return space->r | |
| 1985 | 1985 | } |
| 1986 | 1986 | |
| 1987 | INLINE void snes_dma_transfer( | |
| 1987 | INLINE void snes_dma_transfer( | |
| 1988 | 1988 | { |
| 1989 | 1989 | snes_state *state = space->machine->driver_data<snes_state>(); |
| 1990 | 1990 | |
| r8806 | r8807 | |
| 1997 | 1997 | { |
| 1998 | 1998 | //illegal WRAM->WRAM transfer (bus conflict) |
| 1999 | 1999 | //no read occurs; write does occur |
| 2000 | | |
| 2000 | space-> | |
| 2001 | 2001 | return; |
| 2002 | 2002 | } |
| 2003 | 2003 | else |
| r8806 | r8807 | |
| 2005 | 2005 | if (!dma_abus_valid(abus)) |
| 2006 | 2006 | return; |
| 2007 | 2007 | |
| 2008 | | |
| 2008 | space-> | |
| 2009 | 2009 | return; |
| 2010 | 2010 | } |
| 2011 | 2011 | } |
| r8806 | r8807 | |
| 2020 | 2020 | } |
| 2021 | 2021 | else |
| 2022 | 2022 | { |
| 2023 | | |
| 2023 | space-> | |
| 2024 | 2024 | return; |
| 2025 | 2025 | } |
| 2026 | 2026 | } |
| r8806 | r8807 | |
| 2055 | 2055 | return 1; |
| 2056 | 2056 | } |
| 2057 | 2057 | |
| 2058 | static void snes_hdma_update( | |
| 2058 | static void snes_hdma_update( | |
| 2059 | 2059 | { |
| 2060 | 2060 | snes_state *state = space->machine->driver_data<snes_state>(); |
| 2061 | 2061 | UINT32 abus = snes_get_hdma_addr(space->machine, dma); |
| r8806 | r8807 | |
| 2086 | 2086 | state->dma_channel[dma].do_transfer = 1; |
| 2087 | 2087 | } |
| 2088 | 2088 | |
| 2089 | static void snes_hdma_init( | |
| 2089 | static void snes_hdma_init( | |
| 2090 | 2090 | { |
| 2091 | 2091 | snes_state *state = space->machine->driver_data<snes_state>(); |
| 2092 | 2092 | int i; |
| r8806 | r8807 | |
| 2102 | 2102 | } |
| 2103 | 2103 | } |
| 2104 | 2104 | |
| 2105 | static void snes_hdma( | |
| 2105 | static void snes_hdma( | |
| 2106 | 2106 | { |
| 2107 | 2107 | snes_state *state = space->machine->driver_data<snes_state>(); |
| 2108 | 2108 | UINT16 bbus; |
| r8806 | r8807 | |
| 2186 | 2186 | } |
| 2187 | 2187 | } |
| 2188 | 2188 | |
| 2189 | static void snes_dma( | |
| 2189 | static void snes_dma( | |
| 2190 | 2190 | { |
| 2191 | 2191 | snes_state *state = space->machine->driver_data<snes_state>(); |
| 2192 | 2192 | int i; |
| r8806 | r8807 | |
|---|---|---|
| 293 | 293 | |
| 294 | 294 | static void amiga_m68k_reset(running_device *device) |
| 295 | 295 | { |
| 296 | | |
| 296 | | |
| 297 | 297 | |
| 298 | 298 | logerror("Executed RESET at PC=%06x\n", cpu_get_pc(space->cpu)); |
| 299 | 299 | |
| r8806 | r8807 | |
| 306 | 306 | /* set the overlay bit */ |
| 307 | 307 | if ( IS_AGA(amiga_intf) ) |
| 308 | 308 | { |
| 309 | | |
| 309 | space-> | |
| 310 | 310 | } |
| 311 | 311 | else |
| 312 | 312 | { |
| r8806 | r8807 | |
| 973 | 973 | * |
| 974 | 974 | *************************************/ |
| 975 | 975 | |
| 976 | static void blitter_setup( | |
| 976 | static void blitter_setup( | |
| 977 | 977 | { |
| 978 | 978 | int ticks, width, height, blittime; |
| 979 | 979 | |
| r8806 | r8807 | |
| 1535 | 1535 | |
| 1536 | 1536 | void amiga_serial_in_w(running_machine *machine, UINT16 data) |
| 1537 | 1537 | { |
| 1538 | | |
| 1538 | | |
| 1539 | 1539 | int mask = (CUSTOM_REG(REG_SERPER) & 0x8000) ? 0x1ff : 0xff; |
| 1540 | 1540 | |
| 1541 | 1541 | /* copy the data to the low 8 bits of SERDATR and set RBF */ |
| r8806 | r8807 | |
|---|---|---|
| 163 | 163 | offs_t page_offset = (((offs_t) dma_offset[0][dma_channel]) << 16) |
| 164 | 164 | & 0xFF0000; |
| 165 | 165 | |
| 166 | return | |
| 166 | return space->r | |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | 169 | |
| r8806 | r8807 | |
| 172 | 172 | offs_t page_offset = (((offs_t) dma_offset[0][dma_channel]) << 16) |
| 173 | 173 | & 0xFF0000; |
| 174 | 174 | |
| 175 | | |
| 175 | space-> | |
| 176 | 176 | } |
| 177 | 177 | |
| 178 | 178 | static READ8_HANDLER(dma_page_select_r) |
| r8806 | r8807 | |
|---|---|---|
| 500 | 500 | } |
| 501 | 501 | |
| 502 | 502 | |
| 503 | static void pvc_write_bankswitch( | |
| 503 | static void pvc_write_bankswitch( | |
| 504 | 504 | { |
| 505 | 505 | neogeo_state *state = space->machine->driver_data<neogeo_state>(); |
| 506 | 506 | UINT32 bankaddress; |
| r8806 | r8807 | |
|---|---|---|
| 111 | 111 | /* at about every ~4/4 USEC do a DMA transfer byte */ |
| 112 | 112 | static TIMER_CALLBACK( vidc_video_tick ) |
| 113 | 113 | { |
| 114 | | |
| 114 | | |
| 115 | 115 | static UINT8 *vram = memory_region(machine,"vram"); |
| 116 | 116 | |
| 117 | vram[vidc_vidcur] = ( | |
| 117 | vram[vidc_vidcur] = (space->r | |
| 118 | 118 | |
| 119 | 119 | vidc_vidcur++; |
| 120 | 120 | |
| r8806 | r8807 | |
| 131 | 131 | |
| 132 | 132 | static TIMER_CALLBACK( vidc_audio_tick ) |
| 133 | 133 | { |
| 134 | | |
| 134 | | |
| 135 | 135 | |
| 136 | dac_signed_data_w(space->machine->device("dac"), ( | |
| 136 | dac_signed_data_w(space->machine->device("dac"), (space->r | |
| 137 | 137 | |
| 138 | 138 | vidc_sndcur++; |
| 139 | 139 | |
| r8806 | r8807 | |
| 279 | 279 | } |
| 280 | 280 | } |
| 281 | 281 | |
| 282 | ||
| 282 | ||
| 283 | 283 | { |
| 284 | 284 | // if we're not in logical memory, MAME can do the right thing |
| 285 | 285 | if (address > 0x1ffffff) |
| r8806 | r8807 | |
| 290 | 290 | // if the boot ROM is mapped in, do some trickery to make it show up |
| 291 | 291 | if (memc_latchrom) |
| 292 | 292 | { |
| 293 | direct->bytemask = 0x1fffff; | |
| 294 | direct->bytestart = 0; | |
| 295 | direct->byteend = 0x1fffff; | |
| 296 | direct->raw = direct->decrypted = memory_region(space->machine, "maincpu"); | |
| 293 | direct.explicit_configure(0x000000, 0x1fffff, 0x1fffff, *direct.space().m_machine.region("maincpu")); | |
| 297 | 294 | } |
| 298 | 295 | else // executing from logical memory |
| 299 | 296 | { |
| 300 | UINT32 page = address / page_sizes[memc_pagesize]; | |
| 301 | ||
| 302 | direct->bytemask = page_sizes[memc_pagesize]-1; | |
| 303 | direct->bytestart = page * page_sizes[memc_pagesize]; | |
| 304 | direct->byteend = direct->bytestart + direct->bytemask; | |
| 305 | direct->raw = direct->decrypted = (UINT8 *)&archimedes_memc_physmem[(memc_pages[page] * page_sizes[memc_pagesize])>>2]; | |
| 297 | offs_t pagesize = page_sizes[memc_pagesize]; | |
| 298 | UINT32 page = address / pagesize; | |
| 299 | ||
| 300 | direct.explicit_configure(page * pagesize, page * pagesize - 1, pagesize - 1, &archimedes_memc_physmem[(memc_pages[page] * pagesize)>>2]); | |
| 306 | 301 | } |
| 307 | 302 | |
| 308 | 303 | return ~0; |
| r8806 | r8807 | |
| 310 | 305 | |
| 311 | 306 | void archimedes_driver_init(running_machine *machine) |
| 312 | 307 | { |
| 313 | memory_set_direct_update_handler( cputag_get_address_space( machine, "maincpu", ADDRESS_SPACE_PROGRAM ), a310_setopbase); | |
| 308 | address_space *space = machine->device<arm_device>("maincpu")->space(AS_PROGRAM); | |
| 309 | space->set_direct_update_handler(direct_update_delegate_create_static(a310_setopbase, *machine)); | |
| 314 | 310 | } |
| 315 | 311 | |
| 316 | 312 | static const char *const ioc_regnames[] = |
| r8806 | r8807 | |
|---|---|---|
| 44 | 44 | offset = (cx4.ram[0x626] & 3) * 2; |
| 45 | 45 | srcptr = 0x220; |
| 46 | 46 | |
| 47 | address_space *space = machine->device<cpu_device>("maincpu")->space(AS_PROGRAM); | |
| 47 | 48 | for(i = cx4.ram[0x620]; i > 0 && sprcount > 0; i--, srcptr += 16) |
| 48 | 49 | { |
| 49 | 50 | UINT32 spraddr = CX4_readl(srcptr + 7); |
| r8806 | r8807 | |
| 53 | 54 | sprname = cx4.ram[srcptr + 5]; |
| 54 | 55 | sprattr = cx4.ram[srcptr + 4] | cx4.ram[srcptr + 6]; |
| 55 | 56 | |
| 56 | if( | |
| 57 | if(space->r | |
| 57 | 58 | { |
| 58 | 59 | INT16 x, y; |
| 59 | 60 | INT32 sprcnt; |
| 60 | for(sprcnt = | |
| 61 | for(sprcnt = space->r | |
| 61 | 62 | { |
| 62 | x = (INT8) | |
| 63 | x = (INT8)space->r | |
| 63 | 64 | if(sprattr & 0x40) |
| 64 | 65 | { |
| 65 | x = -x - (( | |
| 66 | x = -x - ((space->r | |
| 66 | 67 | } |
| 67 | 68 | x += sprx; |
| 68 | 69 | if(x >= -16 && x <= 272) |
| 69 | 70 | { |
| 70 | y = (INT8) | |
| 71 | y = (INT8)space->r | |
| 71 | 72 | if(sprattr & 0x80) |
| 72 | 73 | { |
| 73 | y = -y - (( | |
| 74 | y = -y - ((space->r | |
| 74 | 75 | } |
| 75 | 76 | y += spry; |
| 76 | 77 | if(y >= -16 && y <= 224) |
| 77 | 78 | { |
| 78 | 79 | cx4.ram[oamptr ] = (UINT8)x; |
| 79 | 80 | cx4.ram[oamptr + 1] = (UINT8)y; |
| 80 | cx4.ram[oamptr + 2] = sprname + memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), spraddr + 3); | |
| 81 | cx4.ram[oamptr + 3] = sprattr ^ (memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), spraddr) & 0xc0); | |
| 81 | cx4.ram[oamptr + 2] = sprname + space->read_byte(spraddr + 3); | |
| 82 | cx4.ram[oamptr + 3] = sprattr ^ (space->read_byte(spraddr) & 0xc0); | |
| 82 | 83 | cx4.ram[oamptr2] &= ~(3 << offset); |
| 83 | 84 | if(x & 0x100) |
| 84 | 85 | { |
| 85 | 86 | cx4.ram[oamptr2] |= 1 << offset; |
| 86 | 87 | } |
| 87 | if( | |
| 88 | if(space->r | |
| 88 | 89 | { |
| 89 | 90 | cx4.ram[oamptr2] |= 2 << offset; |
| 90 | 91 | } |
| r8806 | r8807 | |
|---|---|---|
| 210 | 210 | UINT16 data[HWIDTH]; /* graphics data buffer (text through chargen) */ |
| 211 | 211 | } VIDEO; |
| 212 | 212 | |
| 213 | typedef void (*atari_renderer_func)( | |
| 213 | typedef void (*atari_renderer_func)( | |
| 214 | 214 | |
| 215 | 215 | typedef struct { |
| 216 | 216 | atari_renderer_func renderer; /* current renderer */ |
| r8806 | r8807 | |
| 259 | 259 | UINT8 *uc_g3; /* used colors for gfx GTIA 3 */ |
| 260 | 260 | } ANTIC; |
| 261 | 261 | |
| 262 | #define RDANTIC(space) memory_read_byte(space, antic.dpage+antic.doffs) | |
| 263 | #define RDVIDEO(space,o) memory_read_byte(space, antic.vpage+((antic.voffs+(o))&VOFFS)) | |
| 264 | #define RDCHGEN(space,o) memory_read_byte(space, antic.chbase+(o)) | |
| 265 | #define RDPMGFXS(space,o) memory_read_byte(space, antic.pmbase_s+(o)+(antic.scanline>>1)) | |
| 266 | #define RDPMGFXD(space,o) memory_read_byte(space, antic.pmbase_d+(o)+antic.scanline) | |
| 262 | #define RDANTIC(space) space->read_byte(antic.dpage+antic.doffs) | |
| 263 | #define RDVIDEO(space,o) space->read_byte(antic.vpage+((antic.voffs+(o))&VOFFS)) | |
| 264 | #define RDCHGEN(space,o) space->read_byte(antic.chbase+(o)) | |
| 265 | #define RDPMGFXS(space,o) space->read_byte(antic.pmbase_s+(o)+(antic.scanline>>1)) | |
| 266 | #define RDPMGFXD(space,o) space->read_byte(antic.pmbase_d+(o)+antic.scanline) | |
| 267 | 267 | |
| 268 | 268 | #define PREPARE() \ |
| 269 | 269 | UINT32 *dst = (UINT32 *)&antic.cclock[PMOFFSET] |
| r8806 | r8807 | |
| 534 | 534 | READ8_HANDLER ( atari_antic_r ); |
| 535 | 535 | WRITE8_HANDLER ( atari_antic_w ); |
| 536 | 536 | |
| 537 | #define ANTIC_RENDERER(name) void name( | |
| 537 | #define ANTIC_RENDERER(name) void name( | |
| 538 | 538 | |
| 539 | 539 | ANTIC_RENDERER( antic_mode_0_xx ); |
| 540 | 540 | ANTIC_RENDERER( antic_mode_2_32 ); |
| r8806 | r8807 | |
|---|---|---|
| 116 | 116 | /*----------- defined in drivers/neogeo.c -----------*/ |
| 117 | 117 | |
| 118 | 118 | void neogeo_set_display_position_interrupt_control(running_machine *machine, UINT16 data); |
| 119 | void neogeo_set_display_counter_msb(const address_space *space, UINT16 data); | |
| 120 | void neogeo_set_display_counter_lsb(const address_space *space, UINT16 data); | |
| 119 | void neogeo_set_display_counter_msb(address_space *space, UINT16 data); | |
| 120 | void neogeo_set_display_counter_lsb(address_space *space, UINT16 data); | |
| 121 | 121 | void neogeo_acknowledge_interrupt(running_machine *machine, UINT16 data); |
| 122 | void neogeo_set_main_cpu_bank_address( | |
| 122 | void neogeo_set_main_cpu_bank_address( | |
| 123 | 123 | READ16_HANDLER( neogeo_unmapped_r ); |
| 124 | 124 | |
| 125 | 125 |
| r8806 | r8807 | |
|---|---|---|
| 3922 | 3922 | |
| 3923 | 3923 | void psx_gpu_reset( running_machine *machine ) |
| 3924 | 3924 | { |
| 3925 | | |
| 3925 | | |
| 3926 | 3926 | |
| 3927 | 3927 | psx_gpu_w(space, 1, 0, 0xffffffff ); |
| 3928 | 3928 | } |
| r8806 | r8807 | |
|---|---|---|
| 1179 | 1179 | |
| 1180 | 1180 | static void vpc_init( running_machine *machine ) |
| 1181 | 1181 | { |
| 1182 | | |
| 1182 | | |
| 1183 | 1183 | vpc_w( space, 0, 0x11 ); |
| 1184 | 1184 | vpc_w( space, 1, 0x11 ); |
| 1185 | 1185 | vpc.window1.w = 0; |
| r8806 | r8807 | |
|---|---|---|
| 130 | 130 | static int dilatechose[64]; |
| 131 | 131 | static float wbuffer[480][640]; |
| 132 | 132 | static UINT32 debug_dip_status; |
| 133 | static void pvr_accumulationbuffer_to_framebuffer( | |
| 133 | static void pvr_accumulationbuffer_to_framebuffer( | |
| 134 | 134 | |
| 135 | 135 | UINT64 *dc_framebuffer_ram; // '32-bit access area' |
| 136 | 136 | UINT64 *dc_texture_ram; // '64-bit access area' |
| r8806 | r8807 | |
| 1123 | 1123 | { |
| 1124 | 1124 | UINT32 st[6]; |
| 1125 | 1125 | |
| 1126 | st[0]=memory_read_dword(space,(0x05000000+offsetra)); | |
| 1127 | st[1]=memory_read_dword(space,(0x05000004+offsetra)); // Opaque List Pointer | |
| 1128 | st[2]=memory_read_dword(space,(0x05000008+offsetra)); // Opaque Modifier Volume List Pointer | |
| 1129 | st[3]=memory_read_dword(space,(0x0500000c+offsetra)); // Translucent List Pointer | |
| 1130 | st[4]=memory_read_dword(space,(0x05000010+offsetra)); // Translucent Modifier Volume List Pointer | |
| 1126 | st[0]=space->read_dword((0x05000000+offsetra)); | |
| 1127 | st[1]=space->read_dword((0x05000004+offsetra)); // Opaque List Pointer | |
| 1128 | st[2]=space->read_dword((0x05000008+offsetra)); // Opaque Modifier Volume List Pointer | |
| 1129 | st[3]=space->read_dword((0x0500000c+offsetra)); // Translucent List Pointer | |
| 1130 | st[4]=space->read_dword((0x05000010+offsetra)); // Translucent Modifier Volume List Pointer | |
| 1131 | 1131 | |
| 1132 | 1132 | if (sizera == 6) |
| 1133 | 1133 | { |
| 1134 | st[5] = | |
| 1134 | st[5] = space->r | |
| 1135 | 1135 | offsetra+=0x18; |
| 1136 | 1136 | } |
| 1137 | 1137 | else |
| r8806 | r8807 | |
| 1963 | 1963 | |
| 1964 | 1964 | static void render_to_accumulation_buffer(running_machine *machine,bitmap_t *bitmap,const rectangle *cliprect) |
| 1965 | 1965 | { |
| 1966 | | |
| 1966 | | |
| 1967 | 1967 | int cs,rs,ns; |
| 1968 | 1968 | UINT32 c; |
| 1969 | 1969 | #if 0 |
| r8806 | r8807 | |
| 1980 | 1980 | |
| 1981 | 1981 | rs=state_ta.renderselect; |
| 1982 | 1982 | c=pvrta_regs[ISP_BACKGND_T]; |
| 1983 | c= | |
| 1983 | c=space->r | |
| 1984 | 1984 | bitmap_fill(bitmap,cliprect,c); |
| 1985 | 1985 | |
| 1986 | 1986 | |
| r8806 | r8807 | |
| 2033 | 2033 | |
| 2034 | 2034 | */ |
| 2035 | 2035 | |
| 2036 | static void pvr_accumulationbuffer_to_framebuffer( | |
| 2036 | static void pvr_accumulationbuffer_to_framebuffer( | |
| 2037 | 2037 | { |
| 2038 | 2038 | // the accumulation buffer is always 8888 |
| 2039 | 2039 | // |
| r8806 | r8807 | |
| 2073 | 2073 | ((((data & 0x0000fc00) >> 10)) << 5) | |
| 2074 | 2074 | ((((data & 0x00f80000) >> 19)) << 11); |
| 2075 | 2075 | |
| 2076 | | |
| 2076 | space-> | |
| 2077 | 2077 | } |
| 2078 | 2078 | } |
| 2079 | 2079 | } |
| r8806 | r8807 | |
| 2101 | 2101 | ((((data & 0x00f80000) >> 19)) << 10); |
| 2102 | 2102 | // alpha? |
| 2103 | 2103 | |
| 2104 | | |
| 2104 | space-> | |
| 2105 | 2105 | } |
| 2106 | 2106 | } |
| 2107 | 2107 | } |
| r8806 | r8807 | |
| 2125 | 2125 | ((((data & 0x0000fc00) >> 10)) << 5) | |
| 2126 | 2126 | ((((data & 0x00f80000) >> 19)) << 11); |
| 2127 | 2127 | |
| 2128 | | |
| 2128 | space-> | |
| 2129 | 2129 | } |
| 2130 | 2130 | } |
| 2131 | 2131 | } |
| r8806 | r8807 | |
| 2152 | 2152 | ((((data & 0x0000fc00) >> 10)) << 5) | |
| 2153 | 2153 | ((((data & 0x00f80000) >> 19)) << 11); |
| 2154 | 2154 | |
| 2155 | | |
| 2155 | space-> | |
| 2156 | 2156 | } |
| 2157 | 2157 | } |
| 2158 | 2158 | } |
| r8806 | r8807 | |
|---|---|---|
| 2246 | 2246 | case INIDISP: /* Initial settings for screen */ |
| 2247 | 2247 | if ((snes_ppu.screen_disabled & 0x80) && (!(data & 0x80))) //a 1->0 force blank transition causes a reset OAM address |
| 2248 | 2248 | { |
| 2249 | memory_write_byte(space, OAMADDL, snes_ppu.oam.saved_address_low); | |
| 2250 | memory_write_byte(space, OAMADDH, snes_ppu.oam.saved_address_high); | |
| 2249 | space->write_byte(OAMADDL, snes_ppu.oam.saved_address_low); | |
| 2250 | space->write_byte(OAMADDH, snes_ppu.oam.saved_address_high); | |
| 2251 | 2251 | snes_ppu.oam.first_sprite = snes_ppu.oam.priority_rotation ? (snes_ppu.oam.address >> 1) & 127 : 0; |
| 2252 | 2252 | } |
| 2253 | 2253 | snes_ppu.screen_disabled = data & 0x80; |
| r8806 | r8807 | |
|---|---|---|
| 154 | 154 | static void gtia_reset(running_machine &machine) |
| 155 | 155 | { |
| 156 | 156 | int i; |
| 157 | | |
| 157 | | |
| 158 | 158 | |
| 159 | 159 | /* reset the GTIA read/write/helper registers */ |
| 160 | 160 | for (i = 0; i < 32; i++) |
| r8806 | r8807 | |
|---|---|---|
| 16 | 16 | typedef struct _gtia_interface gtia_interface; |
| 17 | 17 | struct _gtia_interface |
| 18 | 18 | { |
| 19 | UINT8 (*console_read)(const address_space *space); | |
| 20 | void (*console_write)(const address_space *space, UINT8 data); | |
| 19 | UINT8 (*console_read)(address_space *space); | |
| 20 | void (*console_write)(address_space *space, UINT8 data); | |
| 21 | 21 | }; |
| 22 | 22 | |
| 23 | 23 |
| r8806 | r8807 | |
|---|---|---|
| 493 | 493 | |
| 494 | 494 | static UINT8 *get_jaguar_memory(running_machine *machine, UINT32 offset) |
| 495 | 495 | { |
| 496 | | |
| 496 | | |
| 497 | 497 | return (UINT8 *)memory_get_read_ptr(space, offset); |
| 498 | 498 | } |
| 499 | 499 |
| r8806 | r8807 | |
|---|---|---|
| 727 | 727 | /* OR/XOR */ |
| 728 | 728 | if (funcgen_control & 0x30) |
| 729 | 729 | { |
| 730 | UINT8 olddata = | |
| 730 | UINT8 olddata = space->r | |
| 731 | 731 | |
| 732 | 732 | /* compute any intercepts */ |
| 733 | 733 | funcgen_intercept &= 0x0f; |
| r8806 | r8807 | |
| 748 | 748 | } |
| 749 | 749 | |
| 750 | 750 | /* write the result */ |
| 751 | | |
| 751 | space-> | |
| 752 | 752 | } |
| 753 | 753 | |
| 754 | 754 | |
| r8806 | r8807 | |
| 788 | 788 | } |
| 789 | 789 | |
| 790 | 790 | |
| 791 | static void execute_blit( | |
| 791 | static void execute_blit( | |
| 792 | 792 | { |
| 793 | 793 | /* |
| 794 | 794 | pattern_source = counter set U7/U16/U25/U34 |
| r8806 | r8807 | |
| 842 | 842 | if (curwidth == 0 && (pattern_mode & 0x08) != 0) |
| 843 | 843 | busdata = 0; |
| 844 | 844 | else |
| 845 | busdata = | |
| 845 | busdata = space->r | |
| 846 | 846 | |
| 847 | 847 | /* increment the appropriate address */ |
| 848 | 848 | if ((pattern_mode & 0x01) == 0) |
| r8806 | r8807 | |
| 854 | 854 | |
| 855 | 855 | /* address is selected between source/dest based on mode.d0 */ |
| 856 | 856 | busaddr = ((pattern_mode & 0x01) != 0) ? pattern_source : pattern_dest; |
| 857 | | |
| 857 | space-> | |
| 858 | 858 | |
| 859 | 859 | /* increment the appropriate address */ |
| 860 | 860 | if ((pattern_mode & 0x01) == 0) |
| r8806 | r8807 | |
|---|---|---|
| 1174 | 1174 | *****************************************************************************/ |
| 1175 | 1175 | static TIMER_CALLBACK( antic_scanline_render ) |
| 1176 | 1176 | { |
| 1177 | | |
| 1177 | | |
| 1178 | 1178 | |
| 1179 | 1179 | VIDEO *video = antic.video[antic.scanline]; |
| 1180 | 1180 | LOG((" @cycle #%3d render mode $%X lines to go #%d\n", cycle(machine), (antic.cmd & 0x0f), antic.modelines)); |
| r8806 | r8807 | |
| 1244 | 1244 | **************************************************************/ |
| 1245 | 1245 | if( new_cmd & ANTIC_LMS ) |
| 1246 | 1246 | { |
| 1247 | | |
| 1247 | | |
| 1248 | 1248 | int addr = RDANTIC(space); |
| 1249 | 1249 | antic.doffs = (antic.doffs + 1) & DOFFS; |
| 1250 | 1250 | addr += 256 * RDANTIC(space); |
| r8806 | r8807 | |
| 1269 | 1269 | *****************************************************************************/ |
| 1270 | 1270 | static void antic_scanline_dma(running_machine *machine, int param) |
| 1271 | 1271 | { |
| 1272 | | |
| 1272 | | |
| 1273 | 1273 | LOG((" @cycle #%3d DMA fetch\n", cycle(machine))); |
| 1274 | 1274 | if (antic.scanline == VBL_END) |
| 1275 | 1275 | antic.r.nmist &= ~VBL_NMI; |
| r8806 | r8807 | |
|---|---|---|
| 909 | 909 | { |
| 910 | 910 | start_sprite_line_timer(machine); |
| 911 | 911 | start_auto_animation_timer(machine); |
| 912 | optimize_sprite_data(machine); | |
| 913 | 912 | } |
| 914 | 913 | |
| 915 | 914 |
| r8806 | r8807 | |
|---|---|---|
| 76 | 76 | typedef struct _ppu2c0x_state ppu2c0x_state; |
| 77 | 77 | struct _ppu2c0x_state |
| 78 | 78 | { |
| 79 | | |
| 79 | | |
| 80 | 80 | bitmap_t *bitmap; /* target bitmap */ |
| 81 | 81 | UINT8 *spriteram; /* sprite ram */ |
| 82 | 82 | pen_t *colortable; /* color table modified at run time */ |
| r8806 | r8807 | |
| 426 | 426 | pos = ((index1 & 0x380) >> 4) | ((index1 & 0x1f) >> 2); |
| 427 | 427 | page = (index1 & 0x0c00) >> 10; |
| 428 | 428 | address = 0x3c0 + pos; |
| 429 | color_byte = | |
| 429 | color_byte = | |
| 430 | 430 | |
| 431 | 431 | /* figure out which bits in the color table to use */ |
| 432 | 432 | color_bits = ((index1 & 0x40) >> 4) + (index1 & 0x02); |
| 433 | 433 | |
| 434 | 434 | // page2 is the output of the nametable read (this section is the FIRST read per tile!) |
| 435 | 435 | address = index1 & 0x3ff; |
| 436 | page2 = | |
| 436 | page2 = | |
| 437 | 437 | |
| 438 | 438 | // 27/12/2002 |
| 439 | 439 | if (ppu_latch) |
| r8806 | r8807 | |
| 451 | 451 | // plus something that accounts for y |
| 452 | 452 | address += scroll_y_fine; |
| 453 | 453 | |
| 454 | plane1 = memory_read_byte(ppu2c0x->space, (address & 0x1fff)); | |
| 455 | plane2 = memory_read_byte(ppu2c0x->space, (address + 8) & 0x1fff); | |
| 454 | plane1 = ppu2c0x->space->read_byte((address & 0x1fff)); | |
| 455 | plane2 = ppu2c0x->space->read_byte((address + 8) & 0x1fff); | |
| 456 | 456 | |
| 457 | 457 | /* render the pixel */ |
| 458 | 458 | for (i = 0; i < 8; i++) |
| r8806 | r8807 | |
| 598 | 598 | if (size == 8) |
| 599 | 599 | index1 += ((sprite_page == 0) ? 0 : 0x1000); |
| 600 | 600 | |
| 601 | plane1 = memory_read_byte(ppu2c0x->space, (index1 + sprite_line + 0) & 0x1fff); | |
| 602 | plane2 = memory_read_byte(ppu2c0x->space, (index1 + sprite_line + 8) & 0x1fff); | |
| 601 | plane1 = ppu2c0x->space->read_byte((index1 + sprite_line + 0) & 0x1fff); | |
| 602 | plane2 = ppu2c0x->space->read_byte((index1 + sprite_line + 8) & 0x1fff); | |
| 603 | 603 | |
| 604 | 604 | /* if there are more than 8 sprites on this line, set the flag */ |
| 605 | 605 | if (sprite_count == 8) |
| r8806 | r8807 | |
| 996 | 996 | |
| 997 | 997 | if (ppu2c0x->videomem_addr >= 0x3f00) |
| 998 | 998 | { |
| 999 | ppu2c0x->data_latch = | |
| 999 | ppu2c0x->data_latch = | |
| 1000 | 1000 | // buffer the mirrored NT data |
| 1001 | ppu2c0x->buffered_data = | |
| 1001 | ppu2c0x->buffered_data = | |
| 1002 | 1002 | } |
| 1003 | 1003 | else |
| 1004 | 1004 | { |
| 1005 | 1005 | ppu2c0x->data_latch = ppu2c0x->buffered_data; |
| 1006 | ppu2c0x->buffered_data = | |
| 1006 | ppu2c0x->buffered_data = | |
| 1007 | 1007 | } |
| 1008 | 1008 | |
| 1009 | 1009 | ppu2c0x->videomem_addr += ppu2c0x->add; |
| r8806 | r8807 | |
| 1153 | 1153 | if (tempAddr < 0x2000) |
| 1154 | 1154 | { |
| 1155 | 1155 | /* store the data */ |
| 1156 | | |
| 1156 | | |
| 1157 | 1157 | } |
| 1158 | 1158 | |
| 1159 | 1159 | else |
| 1160 | 1160 | { |
| 1161 | | |
| 1161 | | |
| 1162 | 1162 | } |
| 1163 | 1163 | /* increment the address */ |
| 1164 | 1164 | ppu2c0x->videomem_addr += ppu2c0x->add; |
| r8806 | r8807 | |
| 1179 | 1179 | * |
| 1180 | 1180 | *************************************/ |
| 1181 | 1181 | |
| 1182 | void ppu2c0x_spriteram_dma( | |
| 1182 | void ppu2c0x_spriteram_dma( | |
| 1183 | 1183 | { |
| 1184 | 1184 | int i; |
| 1185 | 1185 | int address = page << 8; |
| 1186 | 1186 | |
| 1187 | 1187 | for (i = 0; i < SPRITERAM_SIZE; i++) |
| 1188 | 1188 | { |
| 1189 | UINT8 spriteData = memory_read_byte(space, address + i); | |
| 1190 | memory_write_byte(space, 0x2004, spriteData); | |
| 1189 | UINT8 spriteData = space->read_byte(address + i); | |
| 1190 | space->write_byte(0x2004, spriteData); | |
| 1191 | 1191 | } |
| 1192 | 1192 | |
| 1193 | 1193 | // should last 513 CPU cycles. |
| r8806 | r8807 | |
|---|---|---|
| 108 | 108 | void ppu2c0x_init_palette(running_machine *machine, int first_entry ) ATTR_NONNULL(1); |
| 109 | 109 | void ppu2c0x_init_palette_rgb(running_machine *machine, int first_entry ) ATTR_NONNULL(1); |
| 110 | 110 | |
| 111 | void ppu2c0x_spriteram_dma( | |
| 111 | void ppu2c0x_spriteram_dma( | |
| 112 | 112 | void ppu2c0x_render( running_device *device, bitmap_t *bitmap, int flipx, int flipy, int sx, int sy ) ATTR_NONNULL(1); |
| 113 | 113 | int ppu2c0x_get_pixel( running_device *device, int x, int y ) ATTR_NONNULL(1); |
| 114 | 114 | int ppu2c0x_get_colorbase( running_device *device ) ATTR_NONNULL(1); |
| r8806 | r8807 | |
|---|---|---|
| 81 | 81 | |
| 82 | 82 | symbol_table * symtable; /* global symbol table */ |
| 83 | 83 | |
| 84 | UINT8 within_instruction_hook; | |
| 85 | UINT8 vblank_occurred; | |
| 86 | UINT8 memory_modified; | |
| 87 | UINT8 debugger_access; | |
| 84 | bool within_instruction_hook; | |
| 85 | bool vblank_occurred; | |
| 86 | bool memory_modified; | |
| 87 | bool debugger_access; | |
| 88 | 88 | |
| 89 | 89 | int execution_state; |
| 90 | 90 | |
| r8806 | r8807 | |
| 112 | 112 | |
| 113 | 113 | /* expression handlers */ |
| 114 | 114 | static UINT64 expression_read_memory(void *param, const char *name, int space, UINT32 address, int size); |
| 115 | static UINT64 expression_read_program_direct( | |
| 115 | static UINT64 expression_read_program_direct( | |
| 116 | 116 | static UINT64 expression_read_memory_region(running_machine *machine, const char *rgntag, offs_t address, int size); |
| 117 | 117 | static void expression_write_memory(void *param, const char *name, int space, UINT32 address, int size, UINT64 data); |
| 118 | static void expression_write_program_direct( | |
| 118 | static void expression_write_program_direct( | |
| 119 | 119 | static void expression_write_memory_region(running_machine *machine, const char *rgntag, offs_t address, int size, UINT64 data); |
| 120 | 120 | static EXPRERR expression_validate(void *param, const char *name, int space); |
| 121 | 121 | |
| r8806 | r8807 | |
| 243 | 243 | |
| 244 | 244 | |
| 245 | 245 | /*------------------------------------------------- |
| 246 | debug_cpu_is_stopped - return | |
| 246 | debug_cpu_is_stopped - return true if the | |
| 247 | 247 | current execution state is stopped |
| 248 | 248 | -------------------------------------------------*/ |
| 249 | 249 | |
| 250 | 250 | int debug_cpu_is_stopped(running_machine *machine) |
| 251 | 251 | { |
| 252 | 252 | debugcpu_private *global = machine->debugcpu_data; |
| 253 | return (global != NULL) ? (global->execution_state == EXECUTION_STATE_STOPPED) : | |
| 253 | return (global != NULL) ? (global->execution_state == EXECUTION_STATE_STOPPED) : false; | |
| 254 | 254 | } |
| 255 | 255 | |
| 256 | 256 | |
| r8806 | r8807 | |
| 323 | 323 | address |
| 324 | 324 | -------------------------------------------------*/ |
| 325 | 325 | |
| 326 | int debug_cpu_translate( | |
| 326 | int debug_cpu_translate( | |
| 327 | 327 | { |
| 328 | 328 | device_memory_interface *memory; |
| 329 | 329 | if (space->cpu->interface(memory)) |
| 330 | return memory->translate(space->spacenum, intention, *address); | |
| 331 | return TRUE; | |
| 330 | return memory->translate(space->spacenum(), intention, *address); | |
| 331 | return true; | |
| 332 | 332 | } |
| 333 | 333 | |
| 334 | 334 | |
| r8806 | r8807 | |
| 341 | 341 | the specified memory space |
| 342 | 342 | -------------------------------------------------*/ |
| 343 | 343 | |
| 344 | UINT8 debug_read_byte( | |
| 344 | UINT8 debug_read_byte( | |
| 345 | 345 | { |
| 346 | address_space *space = const_cast<address_space *>(_space); | |
| 346 | 347 | debugcpu_private *global = space->machine->debugcpu_data; |
| 347 | 348 | UINT64 custom; |
| 348 | 349 | UINT8 result; |
| 349 | 350 | |
| 350 | 351 | /* mask against the logical byte mask */ |
| 351 | address &= space->logbytemask; | |
| 352 | address &= space->logbytemask(); | |
| 352 | 353 | |
| 353 | 354 | /* all accesses from this point on are for the debugger */ |
| 354 | | |
| 355 | space-> | |
| 355 | 356 | |
| 356 | 357 | /* translate if necessary; if not mapped, return 0xff */ |
| 357 | 358 | if (apply_translation && !debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) |
| 358 | 359 | result = 0xff; |
| 359 | 360 | |
| 360 | /* if there is a custom read handler, and it returns TRUE, use that value */ | |
| 361 | else if (device_memory(space->cpu)->read(space->spacenum, address, 1, custom)) | |
| 361 | /* if there is a custom read handler, and it returns true, use that value */ | |
| 362 | else if (device_memory(space->cpu)->read(space->spacenum(), address, 1, custom)) | |
| 362 | 363 | result = custom; |
| 363 | 364 | |
| 364 | 365 | /* otherwise, call the byte reading function for the translated address */ |
| 365 | 366 | else |
| 366 | result = | |
| 367 | result = space->r | |
| 367 | 368 | |
| 368 | 369 | /* no longer accessing via the debugger */ |
| 369 | | |
| 370 | space-> | |
| 370 | 371 | return result; |
| 371 | 372 | } |
| 372 | 373 | |
| r8806 | r8807 | |
| 376 | 377 | specified memory space |
| 377 | 378 | -------------------------------------------------*/ |
| 378 | 379 | |
| 379 | UINT16 debug_read_word( | |
| 380 | UINT16 debug_read_word( | |
| 380 | 381 | { |
| 382 | address_space *space = const_cast<address_space *>(_space); | |
| 381 | 383 | debugcpu_private *global = space->machine->debugcpu_data; |
| 382 | 384 | UINT16 result; |
| 383 | 385 | |
| 384 | 386 | /* mask against the logical byte mask */ |
| 385 | address &= space->logbytemask; | |
| 387 | address &= space->logbytemask(); | |
| 386 | 388 | |
| 387 | 389 | /* if this is misaligned read, or if there are no word readers, just read two bytes */ |
| 388 | 390 | if ((address & 1) != 0) |
| r8806 | r8807 | |
| 391 | 393 | UINT8 byte1 = debug_read_byte(space, address + 1, apply_translation); |
| 392 | 394 | |
| 393 | 395 | /* based on the endianness, the result is assembled differently */ |
| 394 | if (space->endianness == ENDIANNESS_LITTLE) | |
| 396 | if (space->endianness() == ENDIANNESS_LITTLE) | |
| 395 | 397 | result = byte0 | (byte1 << 8); |
| 396 | 398 | else |
| 397 | 399 | result = byte1 | (byte0 << 8); |
| r8806 | r8807 | |
| 403 | 405 | UINT64 custom; |
| 404 | 406 | |
| 405 | 407 | /* all accesses from this point on are for the debugger */ |
| 406 | | |
| 408 | space-> | |
| 407 | 409 | |
| 408 | 410 | /* translate if necessary; if not mapped, return 0xffff */ |
| 409 | 411 | if (apply_translation && !debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) |
| 410 | 412 | result = 0xffff; |
| 411 | 413 | |
| 412 | /* if there is a custom read handler, and it returns TRUE, use that value */ | |
| 413 | else if (device_memory(space->cpu)->read(space->spacenum, address, 2, custom)) | |
| 414 | /* if there is a custom read handler, and it returns true, use that value */ | |
| 415 | else if (device_memory(space->cpu)->read(space->spacenum(), address, 2, custom)) | |
| 414 | 416 | result = custom; |
| 415 | 417 | |
| 416 | 418 | /* otherwise, call the byte reading function for the translated address */ |
| 417 | 419 | else |
| 418 | result = | |
| 420 | result = space->r | |
| 419 | 421 | |
| 420 | 422 | /* no longer accessing via the debugger */ |
| 421 | | |
| 423 | space-> | |
| 422 | 424 | } |
| 423 | 425 | |
| 424 | 426 | return result; |
| r8806 | r8807 | |
| 430 | 432 | specified memory space |
| 431 | 433 | -------------------------------------------------*/ |
| 432 | 434 | |
| 433 | UINT32 debug_read_dword( | |
| 435 | UINT32 debug_read_dword( | |
| 434 | 436 | { |
| 437 | address_space *space = const_cast<address_space *>(_space); | |
| 435 | 438 | debugcpu_private *global = space->machine->debugcpu_data; |
| 436 | 439 | UINT32 result; |
| 437 | 440 | |
| 438 | 441 | /* mask against the logical byte mask */ |
| 439 | address &= space->logbytemask; | |
| 442 | address &= space->logbytemask(); | |
| 440 | 443 | |
| 441 | 444 | /* if this is misaligned read, or if there are no dword readers, just read two words */ |
| 442 | 445 | if ((address & 3) != 0) |
| r8806 | r8807 | |
| 445 | 448 | UINT16 word1 = debug_read_word(space, address + 2, apply_translation); |
| 446 | 449 | |
| 447 | 450 | /* based on the endianness, the result is assembled differently */ |
| 448 | if (space->endianness == ENDIANNESS_LITTLE) | |
| 451 | if (space->endianness() == ENDIANNESS_LITTLE) | |
| 449 | 452 | result = word0 | (word1 << 16); |
| 450 | 453 | else |
| 451 | 454 | result = word1 | (word0 << 16); |
| r8806 | r8807 | |
| 457 | 460 | UINT64 custom; |
| 458 | 461 | |
| 459 | 462 | /* all accesses from this point on are for the debugger */ |
| 460 | | |
| 463 | space-> | |
| 461 | 464 | |
| 462 | 465 | /* translate if necessary; if not mapped, return 0xffffffff */ |
| 463 | 466 | if (apply_translation && !debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) |
| 464 | 467 | result = 0xffffffff; |
| 465 | 468 | |
| 466 | /* if there is a custom read handler, and it returns TRUE, use that value */ | |
| 467 | else if (device_memory(space->cpu)->read(space->spacenum, address, 4, custom)) | |
| 469 | /* if there is a custom read handler, and it returns true, use that value */ | |
| 470 | else if (device_memory(space->cpu)->read(space->spacenum(), address, 4, custom)) | |
| 468 | 471 | result = custom; |
| 469 | 472 | |
| 470 | 473 | /* otherwise, call the byte reading function for the translated address */ |
| 471 | 474 | else |
| 472 | result = | |
| 475 | result = space->r | |
| 473 | 476 | |
| 474 | 477 | /* no longer accessing via the debugger */ |
| 475 | | |
| 478 | space-> | |
| 476 | 479 | } |
| 477 | 480 | |
| 478 | 481 | return result; |
| r8806 | r8807 | |
| 484 | 487 | specified memory space |
| 485 | 488 | -------------------------------------------------*/ |
| 486 | 489 | |
| 487 | UINT64 debug_read_qword( | |
| 490 | UINT64 debug_read_qword( | |
| 488 | 491 | { |
| 492 | address_space *space = const_cast<address_space *>(_space); | |
| 489 | 493 | debugcpu_private *global = space->machine->debugcpu_data; |
| 490 | 494 | UINT64 result; |
| 491 | 495 | |
| 492 | 496 | /* mask against the logical byte mask */ |
| 493 | address &= space->logbytemask; | |
| 497 | address &= space->logbytemask(); | |
| 494 | 498 | |
| 495 | 499 | /* if this is misaligned read, or if there are no qword readers, just read two dwords */ |
| 496 | 500 | if ((address & 7) != 0) |
| r8806 | r8807 | |
| 499 | 503 | UINT32 dword1 = debug_read_dword(space, address + 4, apply_translation); |
| 500 | 504 | |
| 501 | 505 | /* based on the endianness, the result is assembled differently */ |
| 502 | if (space->endianness == ENDIANNESS_LITTLE) | |
| 506 | if (space->endianness() == ENDIANNESS_LITTLE) | |
| 503 | 507 | result = dword0 | ((UINT64)dword1 << 32); |
| 504 | 508 | else |
| 505 | 509 | result = dword1 | ((UINT64)dword0 << 32); |
| r8806 | r8807 | |
| 511 | 515 | UINT64 custom; |
| 512 | 516 | |
| 513 | 517 | /* all accesses from this point on are for the debugger */ |
| 514 | | |
| 518 | space-> | |
| 515 | 519 | |
| 516 | 520 | /* translate if necessary; if not mapped, return 0xffffffffffffffff */ |
| 517 | 521 | if (apply_translation && !debug_cpu_translate(space, TRANSLATE_READ_DEBUG, &address)) |
| 518 | 522 | result = ~(UINT64)0; |
| 519 | 523 | |
| 520 | /* if there is a custom read handler, and it returns TRUE, use that value */ | |
| 521 | else if (device_memory(space->cpu)->read(space->spacenum, address, 8, custom)) | |
| 524 | /* if there is a custom read handler, and it returns true, use that value */ | |
| 525 | else if (device_memory(space->cpu)->read(space->spacenum(), address, 8, custom)) | |
| 522 | 526 | result = custom; |
| 523 | 527 | |
| 524 | 528 | /* otherwise, call the byte reading function for the translated address */ |
| 525 | 529 | else |
| 526 | result = | |
| 530 | result = space->r | |
| 527 | 531 | |
| 528 | 532 | /* no longer accessing via the debugger */ |
| 529 | | |
| 533 | space-> | |
| 530 | 534 | } |
| 531 | 535 | |
| 532 | 536 | return result; |
| r8806 | r8807 | |
| 538 | 542 | from the specified memory space |
| 539 | 543 | -------------------------------------------------*/ |
| 540 | 544 | |
| 541 | UINT64 debug_read_memory( | |
| 545 | UINT64 debug_read_memory( | |
| 542 | 546 | { |
| 543 | 547 | UINT64 result = ~(UINT64)0 >> (64 - 8*size); |
| 544 | 548 | switch (size) |
| r8806 | r8807 | |
| 557 | 561 | specified memory space |
| 558 | 562 | -------------------------------------------------*/ |
| 559 | 563 | |
| 560 | void debug_write_byte( | |
| 564 | void debug_write_byte( | |
| 561 | 565 | { |
| 566 | address_space *space = const_cast<address_space *>(_space); | |
| 562 | 567 | debugcpu_private *global = space->machine->debugcpu_data; |
| 563 | 568 | |
| 564 | 569 | /* mask against the logical byte mask */ |
| 565 | address &= space->logbytemask; | |
| 570 | address &= space->logbytemask(); | |
| 566 | 571 | |
| 567 | 572 | /* all accesses from this point on are for the debugger */ |
| 568 | | |
| 573 | space-> | |
| 569 | 574 | |
| 570 | 575 | /* translate if necessary; if not mapped, we're done */ |
| 571 | 576 | if (apply_translation && !debug_cpu_translate(space, TRANSLATE_WRITE_DEBUG, &address)) |
| 572 | 577 | ; |
| 573 | 578 | |
| 574 | /* if there is a custom write handler, and it returns TRUE, use that */ | |
| 575 | else if (device_memory(space->cpu)->write(space->spacenum, address, 1, data)) | |
| 579 | /* if there is a custom write handler, and it returns true, use that */ | |
| 580 | else if (device_memory(space->cpu)->write(space->spacenum(), address, 1, data)) | |
| 576 | 581 | ; |
| 577 | 582 | |
| 578 | 583 | /* otherwise, call the byte reading function for the translated address */ |
| 579 | 584 | else |
| 580 | | |
| 585 | space-> | |
| 581 | 586 | |
| 582 | 587 | /* no longer accessing via the debugger */ |
| 583 | memory_set_debugger_access(space, global->debugger_access = FALSE); | |
| 584 | global->memory_modified = TRUE; | |
| 588 | space->set_debugger_access(global->debugger_access = false); | |
| 589 | global->memory_modified = true; | |
| 585 | 590 | } |
| 586 | 591 | |
| 587 | 592 | |
| r8806 | r8807 | |
| 590 | 595 | specified memory space |
| 591 | 596 | -------------------------------------------------*/ |
| 592 | 597 | |
| 593 | void debug_write_word( | |
| 598 | void debug_write_word( | |
| 594 | 599 | { |
| 600 | address_space *space = const_cast<address_space *>(_space); | |
| 595 | 601 | debugcpu_private *global = space->machine->debugcpu_data; |
| 596 | 602 | |
| 597 | 603 | /* mask against the logical byte mask */ |
| 598 | address &= space->logbytemask; | |
| 604 | address &= space->logbytemask(); | |
| 599 | 605 | |
| 600 | 606 | /* if this is a misaligned write, or if there are no word writers, just read two bytes */ |
| 601 | 607 | if ((address & 1) != 0) |
| 602 | 608 | { |
| 603 | if (space->endianness == ENDIANNESS_LITTLE) | |
| 609 | if (space->endianness() == ENDIANNESS_LITTLE) | |
| 604 | 610 | { |
| 605 | 611 | debug_write_byte(space, address + 0, data >> 0, apply_translation); |
| 606 | 612 | debug_write_byte(space, address + 1, data >> 8, apply_translation); |
| r8806 | r8807 | |
| 616 | 622 | else |
| 617 | 623 | { |
| 618 | 624 | /* all accesses from this point on are for the debugger */ |
| 619 | | |
| 625 | space-> | |
| 620 | 626 | |
| 621 | 627 | /* translate if necessary; if not mapped, we're done */ |
| 622 | 628 | if (apply_translation && !debug_cpu_translate(space, TRANSLATE_WRITE_DEBUG, &address)) |
| 623 | 629 | ; |
| 624 | 630 | |
| 625 | /* if there is a custom write handler, and it returns TRUE, use that */ | |
| 626 | else if (device_memory(space->cpu)->write(space->spacenum, address, 2, data)) | |
| 631 | /* if there is a custom write handler, and it returns true, use that */ | |
| 632 | else if (device_memory(space->cpu)->write(space->spacenum(), address, 2, data)) | |
| 627 | 633 | ; |
| 628 | 634 | |
| 629 | 635 | /* otherwise, call the byte reading function for the translated address */ |
| 630 | 636 | else |
| 631 | | |
| 637 | space-> | |
| 632 | 638 | |
| 633 | 639 | /* no longer accessing via the debugger */ |
| 634 | memory_set_debugger_access(space, global->debugger_access = FALSE); | |
| 635 | global->memory_modified = TRUE; | |
| 640 | space->set_debugger_access(global->debugger_access = false); | |
| 641 | global->memory_modified = true; | |
| 636 | 642 | } |
| 637 | 643 | } |
| 638 | 644 | |
| r8806 | r8807 | |
| 642 | 648 | specified memory space |
| 643 | 649 | -------------------------------------------------*/ |
| 644 | 650 | |
| 645 | void debug_write_dword( | |
| 651 | void debug_write_dword( | |
| 646 | 652 | { |
| 653 | address_space *space = const_cast<address_space *>(_space); | |
| 647 | 654 | debugcpu_private *global = space->machine->debugcpu_data; |
| 648 | 655 | |
| 649 | 656 | /* mask against the logical byte mask */ |
| 650 | address &= space->logbytemask; | |
| 657 | address &= space->logbytemask(); | |
| 651 | 658 | |
| 652 | 659 | /* if this is a misaligned write, or if there are no dword writers, just read two words */ |
| 653 | 660 | if ((address & 3) != 0) |
| 654 | 661 | { |
| 655 | if (space->endianness == ENDIANNESS_LITTLE) | |
| 662 | if (space->endianness() == ENDIANNESS_LITTLE) | |
| 656 | 663 | { |
| 657 | 664 | debug_write_word(space, address + 0, data >> 0, apply_translation); |
| 658 | 665 | debug_write_word(space, address + 2, data >> 16, apply_translation); |
| r8806 | r8807 | |
| 668 | 675 | else |
| 669 | 676 | { |
| 670 | 677 | /* all accesses from this point on are for the debugger */ |
| 671 | | |
| 678 | space-> | |
| 672 | 679 | |
| 673 | 680 | /* translate if necessary; if not mapped, we're done */ |
| 674 | 681 | if (apply_translation && !debug_cpu_translate(space, TRANSLATE_WRITE_DEBUG, &address)) |
| 675 | 682 | ; |
| 676 | 683 | |
| 677 | /* if there is a custom write handler, and it returns TRUE, use that */ | |
| 678 | else if (device_memory(space->cpu)->write(space->spacenum, address, 4, data)) | |
| 684 | /* if there is a custom write handler, and it returns true, use that */ | |
| 685 | else if (device_memory(space->cpu)->write(space->spacenum(), address, 4, data)) | |
| 679 | 686 | ; |
| 680 | 687 | |
| 681 | 688 | /* otherwise, call the byte reading function for the translated address */ |
| 682 | 689 | else |
| 683 | | |
| 690 | space-> | |
| 684 | 691 | |
| 685 | 692 | /* no longer accessing via the debugger */ |
| 686 | memory_set_debugger_access(space, global->debugger_access = FALSE); | |
| 687 | global->memory_modified = TRUE; | |
| 693 | space->set_debugger_access(global->debugger_access = false); | |
| 694 | global->memory_modified = true; | |
| 688 | 695 | } |
| 689 | 696 | } |
| 690 | 697 | |
| r8806 | r8807 | |
| 694 | 701 | specified memory space |
| 695 | 702 | -------------------------------------------------*/ |
| 696 | 703 | |
| 697 | void debug_write_qword( | |
| 704 | void debug_write_qword( | |
| 698 | 705 | { |
| 706 | address_space *space = const_cast<address_space *>(_space); | |
| 699 | 707 | debugcpu_private *global = space->machine->debugcpu_data; |
| 700 | 708 | |
| 701 | 709 | /* mask against the logical byte mask */ |
| 702 | address &= space->logbytemask; | |
| 710 | address &= space->logbytemask(); | |
| 703 | 711 | |
| 704 | 712 | /* if this is a misaligned write, or if there are no qword writers, just read two dwords */ |
| 705 | 713 | if ((address & 7) != 0) |
| 706 | 714 | { |
| 707 | if (space->endianness == ENDIANNESS_LITTLE) | |
| 715 | if (space->endianness() == ENDIANNESS_LITTLE) | |
| 708 | 716 | { |
| 709 | 717 | debug_write_dword(space, address + 0, data >> 0, apply_translation); |
| 710 | 718 | debug_write_dword(space, address + 4, data >> 32, apply_translation); |
| r8806 | r8807 | |
| 720 | 728 | else |
| 721 | 729 | { |
| 722 | 730 | /* all accesses from this point on are for the debugger */ |
| 723 | | |
| 731 | space-> | |
| 724 | 732 | |
| 725 | 733 | /* translate if necessary; if not mapped, we're done */ |
| 726 | 734 | if (apply_translation && !debug_cpu_translate(space, TRANSLATE_WRITE_DEBUG, &address)) |
| 727 | 735 | ; |
| 728 | 736 | |
| 729 | /* if there is a custom write handler, and it returns TRUE, use that */ | |
| 730 | else if (device_memory(space->cpu)->write(space->spacenum, address, 8, data)) | |
| 737 | /* if there is a custom write handler, and it returns true, use that */ | |
| 738 | else if (device_memory(space->cpu)->write(space->spacenum(), address, 8, data)) | |
| 731 | 739 | ; |
| 732 | 740 | |
| 733 | 741 | /* otherwise, call the byte reading function for the translated address */ |
| 734 | 742 | else |
| 735 | | |
| 743 | space-> | |
| 736 | 744 | |
| 737 | 745 | /* no longer accessing via the debugger */ |
| 738 | memory_set_debugger_access(space, global->debugger_access = FALSE); | |
| 739 | global->memory_modified = TRUE; | |
| 746 | space->set_debugger_access(global->debugger_access = false); | |
| 747 | global->memory_modified = true; | |
| 740 | 748 | } |
| 741 | 749 | } |
| 742 | 750 | |
| r8806 | r8807 | |
| 746 | 754 | to the specified memory space |
| 747 | 755 | -------------------------------------------------*/ |
| 748 | 756 | |
| 749 | void debug_write_memory( | |
| 757 | void debug_write_memory( | |
| 750 | 758 | { |
| 751 | 759 | switch (size) |
| 752 | 760 | { |
| r8806 | r8807 | |
| 763 | 771 | the given offset from opcode space |
| 764 | 772 | -------------------------------------------------*/ |
| 765 | 773 | |
| 766 | UINT64 debug_read_opcode( | |
| 774 | UINT64 debug_read_opcode( | |
| 767 | 775 | { |
| 776 | address_space *space = const_cast<address_space *>(_space); | |
| 768 | 777 | UINT64 result = ~(UINT64)0 & (~(UINT64)0 >> (64 - 8*size)), result2; |
| 769 | 778 | debugcpu_private *global = space->machine->debugcpu_data; |
| 770 | 779 | |
| 771 | 780 | /* keep in logical range */ |
| 772 | address &= space->logbytemask; | |
| 781 | address &= space->logbytemask(); | |
| 773 | 782 | |
| 774 | 783 | /* return early if we got the result directly */ |
| 775 | | |
| 784 | space-> | |
| 776 | 785 | device_memory_interface *memory; |
| 777 | 786 | if (space->cpu->interface(memory) && memory->readop(address, size, result2)) |
| 778 | 787 | { |
| 779 | | |
| 788 | space-> | |
| 780 | 789 | return result2; |
| 781 | 790 | } |
| 782 | 791 | |
| 783 | 792 | /* if we're bigger than the address bus, break into smaller pieces */ |
| 784 | if (size > space->d | |
| 793 | if (size > space->data_width() / 8) | |
| 785 | 794 | { |
| 786 | 795 | int halfsize = size / 2; |
| 787 | 796 | UINT64 r0 = debug_read_opcode(space, address + 0, halfsize, arg); |
| 788 | 797 | UINT64 r1 = debug_read_opcode(space, address + halfsize, halfsize, arg); |
| 789 | 798 | |
| 790 | if (space->endianness == ENDIANNESS_LITTLE) | |
| 799 | if (space->endianness() == ENDIANNESS_LITTLE) | |
| 791 | 800 | return r0 | (r1 << (8 * halfsize)); |
| 792 | 801 | else |
| 793 | 802 | return r1 | (r0 << (8 * halfsize)); |
| r8806 | r8807 | |
| 798 | 807 | return result; |
| 799 | 808 | |
| 800 | 809 | /* keep in physical range */ |
| 801 | address &= space->bytemask; | |
| 802 | switch (space->dbits / 8 * 10 + size) | |
| 810 | address &= space->bytemask(); | |
| 811 | switch (space->data_width() / 8 * 10 + size) | |
| 803 | 812 | { |
| 804 | 813 | /* dump opcodes in bytes from a byte-sized bus */ |
| 805 | 814 | case 11: |
| r8806 | r8807 | |
| 807 | 816 | |
| 808 | 817 | /* dump opcodes in bytes from a word-sized bus */ |
| 809 | 818 | case 21: |
| 810 | address ^= (space->endianness == ENDIANNESS_LITTLE) ? BYTE_XOR_LE(0) : BYTE_XOR_BE(0); | |
| 819 | address ^= (space->endianness() == ENDIANNESS_LITTLE) ? BYTE_XOR_LE(0) : BYTE_XOR_BE(0); | |
| 811 | 820 | break; |
| 812 | 821 | |
| 813 | 822 | /* dump opcodes in words from a word-sized bus */ |
| r8806 | r8807 | |
| 816 | 825 | |
| 817 | 826 | /* dump opcodes in bytes from a dword-sized bus */ |
| 818 | 827 | case 41: |
| 819 | address ^= (space->endianness == ENDIANNESS_LITTLE) ? BYTE4_XOR_LE(0) : BYTE4_XOR_BE(0); | |
| 828 | address ^= (space->endianness() == ENDIANNESS_LITTLE) ? BYTE4_XOR_LE(0) : BYTE4_XOR_BE(0); | |
| 820 | 829 | break; |
| 821 | 830 | |
| 822 | 831 | /* dump opcodes in words from a dword-sized bus */ |
| 823 | 832 | case 42: |
| 824 | address ^= (space->endianness == ENDIANNESS_LITTLE) ? WORD_XOR_LE(0) : WORD_XOR_BE(0); | |
| 833 | address ^= (space->endianness() == ENDIANNESS_LITTLE) ? WORD_XOR_LE(0) : WORD_XOR_BE(0); | |
| 825 | 834 | break; |
| 826 | 835 | |
| 827 | 836 | /* dump opcodes in dwords from a dword-sized bus */ |
| r8806 | r8807 | |
| 830 | 839 | |
| 831 | 840 | /* dump opcodes in bytes from a qword-sized bus */ |
| 832 | 841 | case 81: |
| 833 | address ^= (space->endianness == ENDIANNESS_LITTLE) ? BYTE8_XOR_LE(0) : BYTE8_XOR_BE(0); | |
| 842 | address ^= (space->endianness() == ENDIANNESS_LITTLE) ? BYTE8_XOR_LE(0) : BYTE8_XOR_BE(0); | |
| 834 | 843 | break; |
| 835 | 844 | |
| 836 | 845 | /* dump opcodes in words from a qword-sized bus */ |
| 837 | 846 | case 82: |
| 838 | address ^= (space->endianness == ENDIANNESS_LITTLE) ? WORD2_XOR_LE(0) : WORD2_XOR_BE(0); | |
| 847 | address ^= (space->endianness() == ENDIANNESS_LITTLE) ? WORD2_XOR_LE(0) : WORD2_XOR_BE(0); | |
| 839 | 848 | break; |
| 840 | 849 | |
| 841 | 850 | /* dump opcodes in dwords from a qword-sized bus */ |
| 842 | 851 | case 84: |
| 843 | address ^= (space->endianness == ENDIANNESS_LITTLE) ? DWORD_XOR_LE(0) : DWORD_XOR_BE(0); | |
| 852 | address ^= (space->endianness() == ENDIANNESS_LITTLE) ? DWORD_XOR_LE(0) : DWORD_XOR_BE(0); | |
| 844 | 853 | break; |
| 845 | 854 | |
| 846 | 855 | /* dump opcodes in qwords from a qword-sized bus */ |
| r8806 | r8807 | |
| 848 | 857 | break; |
| 849 | 858 | |
| 850 | 859 | default: |
| 851 | fatalerror("debug_read_opcode: unknown type = %d", space->d | |
| 860 | fatalerror("debug_read_opcode: unknown type = %d", space->data_width() / 8 * 10 + size); | |
| 852 | 861 | break; |
| 853 | 862 | } |
| 854 | 863 | |
| 855 | 864 | /* turn on debugger access */ |
| 856 | 865 | if (!global->debugger_access) |
| 857 | | |
| 866 | space-> | |
| 858 | 867 | |
| 859 | 868 | /* switch off the size and handle unaligned accesses */ |
| 860 | 869 | switch (size) |
| r8806 | r8807 | |
| 868 | 877 | if ((address & 1) != 0) |
| 869 | 878 | { |
| 870 | 879 | result2 = (arg) ? memory_raw_read_word(space, (address & ~1) + 2) : memory_decrypted_read_word(space, (address & ~1) + 2); |
| 871 | if (space->endianness == ENDIANNESS_LITTLE) | |
| 880 | if (space->endianness() == ENDIANNESS_LITTLE) | |
| 872 | 881 | result = (result >> (8 * (address & 1))) | (result2 << (16 - 8 * (address & 1))); |
| 873 | 882 | else |
| 874 | 883 | result = (result << (8 * (address & 1))) | (result2 >> (16 - 8 * (address & 1))); |
| r8806 | r8807 | |
| 881 | 890 | if ((address & 3) != 0) |
| 882 | 891 | { |
| 883 | 892 | result2 = (arg) ? memory_raw_read_dword(space, (address & ~3) + 4) : memory_decrypted_read_dword(space, (address & ~3) + 4); |
| 884 | if (space->endianness == ENDIANNESS_LITTLE) | |
| 893 | if (space->endianness() == ENDIANNESS_LITTLE) | |
| 885 | 894 | result = (result >> (8 * (address & 3))) | (result2 << (32 - 8 * (address & 3))); |
| 886 | 895 | else |
| 887 | 896 | result = (result << (8 * (address & 3))) | (result2 >> (32 - 8 * (address & 3))); |
| r8806 | r8807 | |
| 894 | 903 | if ((address & 7) != 0) |
| 895 | 904 | { |
| 896 | 905 | result2 = (arg) ? memory_raw_read_qword(space, (address & ~7) + 8) : memory_decrypted_read_qword(space, (address & ~7) + 8); |
| 897 | if (space->endianness == ENDIANNESS_LITTLE) | |
| 906 | if (space->endianness() == ENDIANNESS_LITTLE) | |
| 898 | 907 | result = (result >> (8 * (address & 7))) | (result2 << (64 - 8 * (address & 7))); |
| 899 | 908 | else |
| 900 | 909 | result = (result << (8 * (address & 7))) | (result2 >> (64 - 8 * (address & 7))); |
| r8806 | r8807 | |
| 903 | 912 | } |
| 904 | 913 | |
| 905 | 914 | /* no longer accessing via the debugger */ |
| 906 | | |
| 915 | space-> | |
| 907 | 916 | return result; |
| 908 | 917 | } |
| 909 | 918 | |
| r8806 | r8807 | |
| 935 | 944 | { |
| 936 | 945 | /* just set a global flag to be consumed later */ |
| 937 | 946 | if (vblank_state) |
| 938 | device.machine->debugcpu_data->vblank_occurred = | |
| 947 | device.machine->debugcpu_data->vblank_occurred = true; | |
| 939 | 948 | } |
| 940 | 949 | |
| 941 | 950 | |
| r8806 | r8807 | |
| 1030 | 1039 | running_machine *machine = (running_machine *)param; |
| 1031 | 1040 | UINT64 result = ~(UINT64)0 >> (64 - 8*size); |
| 1032 | 1041 | device_t *device = NULL; |
| 1033 | | |
| 1042 | | |
| 1034 | 1043 | |
| 1035 | 1044 | switch (spacenum) |
| 1036 | 1045 | { |
| r8806 | r8807 | |
| 1044 | 1053 | device = debug_cpu_get_visible_cpu(machine); |
| 1045 | 1054 | space = cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL)); |
| 1046 | 1055 | if (space != NULL) |
| 1047 | result = debug_read_memory(space, | |
| 1056 | result = debug_read_memory(space, space-> | |
| 1048 | 1057 | break; |
| 1049 | 1058 | |
| 1050 | 1059 | case EXPSPACE_PROGRAM_PHYSICAL: |
| r8806 | r8807 | |
| 1057 | 1066 | device = debug_cpu_get_visible_cpu(machine); |
| 1058 | 1067 | space = cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL)); |
| 1059 | 1068 | if (space != NULL) |
| 1060 | result = debug_read_memory(space, | |
| 1069 | result = debug_read_memory(space, space-> | |
| 1061 | 1070 | break; |
| 1062 | 1071 | |
| 1063 | 1072 | case EXPSPACE_OPCODE: |
| r8806 | r8807 | |
| 1084 | 1093 | directly from an opcode or RAM pointer |
| 1085 | 1094 | -------------------------------------------------*/ |
| 1086 | 1095 | |
| 1087 | static UINT64 expression_read_program_direct( | |
| 1096 | static UINT64 expression_read_program_direct( | |
| 1088 | 1097 | { |
| 1098 | address_space *space = const_cast<address_space *>(_space); | |
| 1089 | 1099 | UINT64 result = ~(UINT64)0 >> (64 - 8*size); |
| 1090 | 1100 | |
| 1091 | 1101 | if (space != NULL) |
| r8806 | r8807 | |
| 1094 | 1104 | |
| 1095 | 1105 | /* adjust the address into a byte address, but not if being called recursively */ |
| 1096 | 1106 | if ((opcode & 2) == 0) |
| 1097 | address = | |
| 1107 | address = space-> | |
| 1098 | 1108 | |
| 1099 | 1109 | /* call ourself recursively until we are byte-sized */ |
| 1100 | 1110 | if (size > 1) |
| r8806 | r8807 | |
| 1107 | 1117 | r1 = expression_read_program_direct(space, opcode | 2, address + halfsize, halfsize); |
| 1108 | 1118 | |
| 1109 | 1119 | /* assemble based on the target endianness */ |
| 1110 | if (space->endianness == ENDIANNESS_LITTLE) | |
| 1120 | if (space->endianness() == ENDIANNESS_LITTLE) | |
| 1111 | 1121 | result = r0 | (r1 << (8 * halfsize)); |
| 1112 | 1122 | else |
| 1113 | 1123 | result = r1 | (r0 << (8 * halfsize)); |
| r8806 | r8807 | |
| 1117 | 1127 | else |
| 1118 | 1128 | { |
| 1119 | 1129 | /* lowmask specified which address bits are within the databus width */ |
| 1120 | offs_t lowmask = space->d | |
| 1130 | offs_t lowmask = space->data_width() / 8 - 1; | |
| 1121 | 1131 | |
| 1122 | 1132 | /* get the base of memory, aligned to the address minus the lowbits */ |
| 1123 | 1133 | if (opcode & 1) |
| r8806 | r8807 | |
| 1128 | 1138 | /* if we have a valid base, return the appropriate byte */ |
| 1129 | 1139 | if (base != NULL) |
| 1130 | 1140 | { |
| 1131 | if (space->endianness == ENDIANNESS_LITTLE) | |
| 1141 | if (space->endianness() == ENDIANNESS_LITTLE) | |
| 1132 | 1142 | result = base[BYTE8_XOR_LE(address) & lowmask]; |
| 1133 | 1143 | else |
| 1134 | 1144 | result = base[BYTE8_XOR_BE(address) & lowmask]; |
| r8806 | r8807 | |
| 1197 | 1207 | { |
| 1198 | 1208 | running_machine *machine = (running_machine *)param; |
| 1199 | 1209 | device_t *device = NULL; |
| 1200 | | |
| 1210 | | |
| 1201 | 1211 | |
| 1202 | 1212 | switch (spacenum) |
| 1203 | 1213 | { |
| r8806 | r8807 | |
| 1211 | 1221 | device = debug_cpu_get_visible_cpu(machine); |
| 1212 | 1222 | space = cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM + (spacenum - EXPSPACE_PROGRAM_LOGICAL)); |
| 1213 | 1223 | if (space != NULL) |
| 1214 | debug_write_memory(space, | |
| 1224 | debug_write_memory(space, space-> | |
| 1215 | 1225 | break; |
| 1216 | 1226 | |
| 1217 | 1227 | case EXPSPACE_PROGRAM_PHYSICAL: |
| r8806 | r8807 | |
| 1224 | 1234 | device = debug_cpu_get_visible_cpu(machine); |
| 1225 | 1235 | space = cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM + (spacenum - EXPSPACE_PROGRAM_PHYSICAL)); |
| 1226 | 1236 | if (space != NULL) |
| 1227 | debug_write_memory(space, | |
| 1237 | debug_write_memory(space, space-> | |
| 1228 | 1238 | break; |
| 1229 | 1239 | |
| 1230 | 1240 | case EXPSPACE_OPCODE: |
| r8806 | r8807 | |
| 1250 | 1260 | directly to an opcode or RAM pointer |
| 1251 | 1261 | -------------------------------------------------*/ |
| 1252 | 1262 | |
| 1253 | static void expression_write_program_direct( | |
| 1263 | static void expression_write_program_direct( | |
| 1254 | 1264 | { |
| 1265 | address_space *space = const_cast<address_space *>(_space); | |
| 1255 | 1266 | if (space != NULL) |
| 1256 | 1267 | { |
| 1257 | 1268 | debugcpu_private *global = space->machine->debugcpu_data; |
| r8806 | r8807 | |
| 1259 | 1270 | |
| 1260 | 1271 | /* adjust the address into a byte address, but not if being called recursively */ |
| 1261 | 1272 | if ((opcode & 2) == 0) |
| 1262 | address = | |
| 1273 | address = space-> | |
| 1263 | 1274 | |
| 1264 | 1275 | /* call ourself recursively until we are byte-sized */ |
| 1265 | 1276 | if (size > 1) |
| r8806 | r8807 | |
| 1269 | 1280 | |
| 1270 | 1281 | /* break apart based on the target endianness */ |
| 1271 | 1282 | halfmask = ~(UINT64)0 >> (64 - 8 * halfsize); |
| 1272 | if (space->endianness == ENDIANNESS_LITTLE) | |
| 1283 | if (space->endianness() == ENDIANNESS_LITTLE) | |
| 1273 | 1284 | { |
| 1274 | 1285 | r0 = data & halfmask; |
| 1275 | 1286 | r1 = (data >> (8 * halfsize)) & halfmask; |
| r8806 | r8807 | |
| 1289 | 1300 | else |
| 1290 | 1301 | { |
| 1291 | 1302 | /* lowmask specified which address bits are within the databus width */ |
| 1292 | offs_t lowmask = space->d | |
| 1303 | offs_t lowmask = space->data_width() / 8 - 1; | |
| 1293 | 1304 | |
| 1294 | 1305 | /* get the base of memory, aligned to the address minus the lowbits */ |
| 1295 | 1306 | if (opcode & 1) |
| r8806 | r8807 | |
| 1300 | 1311 | /* if we have a valid base, write the appropriate byte */ |
| 1301 | 1312 | if (base != NULL) |
| 1302 | 1313 | { |
| 1303 | if (space->endianness == ENDIANNESS_LITTLE) | |
| 1314 | if (space->endianness() == ENDIANNESS_LITTLE) | |
| 1304 | 1315 | base[BYTE8_XOR_LE(address) & lowmask] = data; |
| 1305 | 1316 | else |
| 1306 | 1317 | base[BYTE8_XOR_BE(address) & lowmask] = data; |
| 1307 | global->memory_modified = | |
| 1318 | global->memory_modified = true; | |
| 1308 | 1319 | } |
| 1309 | 1320 | } |
| 1310 | 1321 | } |
| r8806 | r8807 | |
| 1360 | 1371 | base[BYTE8_XOR_LE(address) & lowmask] = data; |
| 1361 | 1372 | else |
| 1362 | 1373 | base[BYTE8_XOR_BE(address) & lowmask] = data; |
| 1363 | global->memory_modified = | |
| 1374 | global->memory_modified = true; | |
| 1364 | 1375 | } |
| 1365 | 1376 | } |
| 1366 | 1377 | } |
| r8806 | r8807 | |
| 1678 | 1689 | // if a VBLANK occurred, check on things |
| 1679 | 1690 | if (global->vblank_occurred) |
| 1680 | 1691 | { |
| 1681 | global->vblank_occurred = | |
| 1692 | global->vblank_occurred = false; | |
| 1682 | 1693 | |
| 1683 | 1694 | // if we were waiting for a VBLANK, signal it now |
| 1684 | 1695 | if ((m_flags & DEBUG_FLAG_STOP_VBLANK) != 0) |
| r8806 | r8807 | |
| 1769 | 1780 | debugcpu_private *global = m_device.machine->debugcpu_data; |
| 1770 | 1781 | |
| 1771 | 1782 | // note that we are in the debugger code |
| 1772 | global->within_instruction_hook = | |
| 1783 | global->within_instruction_hook = true; | |
| 1773 | 1784 | |
| 1774 | 1785 | // update the history |
| 1775 | 1786 | m_pc_history[m_pc_history_index++ % HISTORY_SIZE] = curpc; |
| r8806 | r8807 | |
| 1831 | 1842 | // if we are supposed to halt, do it now |
| 1832 | 1843 | if (global->execution_state == EXECUTION_STATE_STOPPED) |
| 1833 | 1844 | { |
| 1834 | int firststop = | |
| 1845 | int firststop = true; | |
| 1835 | 1846 | |
| 1836 | 1847 | // reset any transient state |
| 1837 | 1848 | reset_transient_flags(*m_device.machine); |
| r8806 | r8807 | |
| 1845 | 1856 | debugger_refresh_display(m_device.machine); |
| 1846 | 1857 | |
| 1847 | 1858 | // wait for the debugger; during this time, disable sound output |
| 1848 | sound_mute(m_device.machine, | |
| 1859 | sound_mute(m_device.machine, true); | |
| 1849 | 1860 | while (global->execution_state == EXECUTION_STATE_STOPPED) |
| 1850 | 1861 | { |
| 1851 | 1862 | // flush any pending updates before waiting again |
| 1852 | 1863 | m_device.machine->m_debug_view->flush_osd_updates(); |
| 1853 | 1864 | |
| 1854 | 1865 | // clear the memory modified flag and wait |
| 1855 | global->memory_modified = | |
| 1866 | global->memory_modified = false; | |
| 1856 | 1867 | if (m_device.machine->debug_flags & DEBUG_FLAG_OSD_ENABLED) |
| 1857 | 1868 | osd_wait_for_debugger(&m_device, firststop); |
| 1858 | 1869 | else if (m_device.machine->debug_flags & DEBUG_FLAG_ENABLED) |
| 1859 | 1870 | debugint_wait_for_debugger(&m_device, firststop); |
| 1860 | firststop = | |
| 1871 | firststop = false; | |
| 1861 | 1872 | |
| 1862 | 1873 | // if something modified memory, update the screen |
| 1863 | 1874 | if (global->memory_modified) |
| r8806 | r8807 | |
| 1873 | 1884 | if (m_device.machine->scheduled_event_pending()) |
| 1874 | 1885 | global->execution_state = EXECUTION_STATE_RUNNING; |
| 1875 | 1886 | } |
| 1876 | sound_mute(m_device.machine, | |
| 1887 | sound_mute(m_device.machine, false); | |
| 1877 | 1888 | |
| 1878 | 1889 | // remember the last visible CPU in the debugger |
| 1879 | 1890 | global->visiblecpu = &m_device; |
| r8806 | r8807 | |
| 1884 | 1895 | prepare_for_step_overout(pc()); |
| 1885 | 1896 | |
| 1886 | 1897 | // no longer in debugger code |
| 1887 | global->within_instruction_hook = | |
| 1898 | global->within_instruction_hook = false; | |
| 1888 | 1899 | } |
| 1889 | 1900 | |
| 1890 | 1901 | |
| r8806 | r8807 | |
| 1894 | 1905 | // memory read happens |
| 1895 | 1906 | //------------------------------------------------- |
| 1896 | 1907 | |
| 1897 | void device_debug::memory_read_hook( | |
| 1908 | void device_debug::memory_read_hook( | |
| 1898 | 1909 | { |
| 1899 | 1910 | // check watchpoints |
| 1900 | 1911 | watchpoint_check(space, WATCHPOINT_READ, address, 0, mem_mask); |
| r8806 | r8807 | |
| 1911 | 1922 | // memory write happens |
| 1912 | 1923 | //------------------------------------------------- |
| 1913 | 1924 | |
| 1914 | void device_debug::memory_write_hook( | |
| 1925 | void device_debug::memory_write_hook( | |
| 1915 | 1926 | { |
| 1916 | 1927 | watchpoint_check(space, WATCHPOINT_WRITE, address, data, mem_mask); |
| 1917 | 1928 | } |
| r8806 | r8807 | |
| 1955 | 1966 | #ifdef MAME_DEBUG |
| 1956 | 1967 | if (m_memory != NULL && m_disasm != NULL) |
| 1957 | 1968 | { |
| 1958 | const address_space *space = m_memory->space(AS_PROGRAM); | |
| 1959 | int bytes = memory_address_to_byte(space, result & DASMFLAG_LENGTHMASK); | |
| 1969 | address_space *space = m_memory->space(AS_PROGRAM); | |
| 1970 | int bytes = space->address_to_byte(result & DASMFLAG_LENGTHMASK); | |
| 1960 | 1971 | assert(bytes >= m_disasm->min_opcode_bytes()); |
| 1961 | 1972 | assert(bytes <= m_disasm->max_opcode_bytes()); |
| 1962 | 1973 | (void) bytes; // appease compiler |
| r8806 | r8807 | |
| 2068 | 2079 | |
| 2069 | 2080 | assert(m_exec != NULL); |
| 2070 | 2081 | |
| 2071 | global->vblank_occurred = | |
| 2082 | global->vblank_occurred = false; | |
| 2072 | 2083 | m_flags |= DEBUG_FLAG_STOP_VBLANK; |
| 2073 | 2084 | global->execution_state = EXECUTION_STATE_RUNNING; |
| 2074 | 2085 | } |
| r8806 | r8807 | |
| 2268 | 2279 | // returning its index |
| 2269 | 2280 | //------------------------------------------------- |
| 2270 | 2281 | |
| 2271 | int device_debug::watchpoint_set( | |
| 2282 | int device_debug::watchpoint_set( | |
| 2272 | 2283 | { |
| 2273 | assert(space.spacenum < ARRAY_LENGTH(m_wplist)); | |
| 2284 | assert(space.spacenum() < ARRAY_LENGTH(m_wplist)); | |
| 2274 | 2285 | |
| 2275 | 2286 | // allocate a new one |
| 2276 | 2287 | watchpoint *wp = auto_alloc(m_device.machine, watchpoint(m_device.machine->debugcpu_data->bpindex++, space, type, address, length, condition, action)); |
| 2277 | 2288 | |
| 2278 | 2289 | // hook it into our list |
| 2279 | wp->m_next = m_wplist[space.spacenum]; | |
| 2280 | m_wplist[space.spacenum] = wp; | |
| 2290 | wp->m_next = m_wplist[space.spacenum()]; | |
| 2291 | m_wplist[space.spacenum()] = wp; | |
| 2281 | 2292 | |
| 2282 | 2293 | // update the flags and return the index |
| 2283 | 2294 | watchpoint_update_flags(wp->m_space); |
| r8806 | r8807 | |
| 2298 | 2309 | if ((*wp)->m_index == index) |
| 2299 | 2310 | { |
| 2300 | 2311 | watchpoint *deleteme = *wp; |
| 2301 | | |
| 2312 | | |
| 2302 | 2313 | *wp = deleteme->m_next; |
| 2303 | 2314 | auto_free(m_device.machine, deleteme); |
| 2304 | 2315 | watchpoint_update_flags(space); |
| r8806 | r8807 | |
| 2562 | 2573 | // watchpoint flags |
| 2563 | 2574 | //------------------------------------------------- |
| 2564 | 2575 | |
| 2565 | void device_debug::watchpoint_update_flags( | |
| 2576 | void device_debug::watchpoint_update_flags( | |
| 2566 | 2577 | { |
| 2567 | 2578 | // if hotspots are enabled, turn on all reads |
| 2568 | 2579 | bool enableread = false; |
| r8806 | r8807 | |
| 2571 | 2582 | |
| 2572 | 2583 | // see if there are any enabled breakpoints |
| 2573 | 2584 | bool enablewrite = false; |
| 2574 | for (watchpoint *wp = m_wplist[space.spacenum]; wp != NULL; wp = wp->m_next) | |
| 2585 | for (watchpoint *wp = m_wplist[space.spacenum()]; wp != NULL; wp = wp->m_next) | |
| 2575 | 2586 | if (wp->m_enabled) |
| 2576 | 2587 | { |
| 2577 | 2588 | if (wp->m_type & WATCHPOINT_READ) |
| r8806 | r8807 | |
| 2591 | 2602 | // for a given CPU and address space |
| 2592 | 2603 | //------------------------------------------------- |
| 2593 | 2604 | |
| 2594 | void device_debug::watchpoint_check( | |
| 2605 | void device_debug::watchpoint_check( | |
| 2595 | 2606 | { |
| 2596 | 2607 | debugcpu_private *global = space.machine->debugcpu_data; |
| 2597 | 2608 | |
| 2598 | 2609 | // if we're within debugger code, don't stop |
| 2599 | 2610 | if (global->within_instruction_hook || global->debugger_access) |
| 2600 | 2611 | return; |
| 2601 | global->within_instruction_hook = | |
| 2612 | global->within_instruction_hook = true; | |
| 2602 | 2613 | |
| 2603 | 2614 | // adjust address, size & value_to_write based on mem_mask. |
| 2604 | 2615 | offs_t size = 0; |
| 2605 | 2616 | if (mem_mask != 0) |
| 2606 | 2617 | { |
| 2607 | int bus_size = space.d | |
| 2618 | int bus_size = space.data_width() / 8; | |
| 2608 | 2619 | int address_offset = 0; |
| 2609 | 2620 | |
| 2610 | 2621 | while (address_offset < bus_size && (mem_mask & 0xff) == 0) |
| r8806 | r8807 | |
| 2620 | 2631 | mem_mask >>= 8; |
| 2621 | 2632 | } |
| 2622 | 2633 | |
| 2623 | if (space.endianness == ENDIANNESS_LITTLE) | |
| 2634 | if (space.endianness() == ENDIANNESS_LITTLE) | |
| 2624 | 2635 | address += address_offset; |
| 2625 | 2636 | else |
| 2626 | 2637 | address += bus_size - size - address_offset; |
| r8806 | r8807 | |
| 2632 | 2643 | global->wpdata = value_to_write; |
| 2633 | 2644 | |
| 2634 | 2645 | // see if we match |
| 2635 | for (watchpoint *wp = m_wplist[space.spacenum]; wp != NULL; wp = wp->m_next) | |
| 2646 | for (watchpoint *wp = m_wplist[space.spacenum()]; wp != NULL; wp = wp->m_next) | |
| 2636 | 2647 | if (wp->hit(type, address, size)) |
| 2637 | 2648 | { |
| 2638 | 2649 | // halt in the debugger by default |
| r8806 | r8807 | |
| 2654 | 2665 | |
| 2655 | 2666 | if (type & WATCHPOINT_WRITE) |
| 2656 | 2667 | { |
| 2657 | buffer.printf("Stopped at watchpoint %X writing %s to %08X (PC=%X)", wp->m_index, sizes[size], | |
| 2668 | buffer.printf("Stopped at watchpoint %X writing %s to %08X (PC=%X)", wp->m_index, sizes[size], space. | |
| 2658 | 2669 | if (value_to_write >> 32) |
| 2659 | 2670 | buffer.catprintf(" (data=%X%08X)", (UINT32)(value_to_write >> 32), (UINT32)value_to_write); |
| 2660 | 2671 | else |
| 2661 | 2672 | buffer.catprintf(" (data=%X)", (UINT32)value_to_write); |
| 2662 | 2673 | } |
| 2663 | 2674 | else |
| 2664 | buffer.printf("Stopped at watchpoint %X reading %s from %08X (PC=%X)", wp->m_index, sizes[size], | |
| 2675 | buffer.printf("Stopped at watchpoint %X reading %s from %08X (PC=%X)", wp->m_index, sizes[size], space. | |
| 2665 | 2676 | debug_console_printf(space.machine, "%s\n", buffer.cstr()); |
| 2666 | 2677 | space.cpu->debug()->compute_debug_flags(); |
| 2667 | 2678 | } |
| 2668 | 2679 | break; |
| 2669 | 2680 | } |
| 2670 | 2681 | |
| 2671 | global->within_instruction_hook = | |
| 2682 | global->within_instruction_hook = false; | |
| 2672 | 2683 | } |
| 2673 | 2684 | |
| 2674 | 2685 | |
| r8806 | r8807 | |
| 2677 | 2688 | // memory read access |
| 2678 | 2689 | //------------------------------------------------- |
| 2679 | 2690 | |
| 2680 | void device_debug::hotspot_check( | |
| 2691 | void device_debug::hotspot_check( | |
| 2681 | 2692 | { |
| 2682 | 2693 | offs_t curpc = pc(); |
| 2683 | 2694 | |
| r8806 | r8807 | |
| 2693 | 2704 | // if the bottom of the list is over the threshhold, print it |
| 2694 | 2705 | hotspot_entry &spot = m_hotspots[m_hotspot_count - 1]; |
| 2695 | 2706 | if (spot.m_count > m_hotspot_threshhold) |
| 2696 | debug_console_printf(space.machine, "Hotspot @ %s %08X (PC=%08X) hit %d times (fell off bottom)\n", space.name, spot.m_access, spot.m_pc, spot.m_count); | |
| 2707 | debug_console_printf(space.machine, "Hotspot @ %s %08X (PC=%08X) hit %d times (fell off bottom)\n", space.name(), spot.m_access, spot.m_pc, spot.m_count); | |
| 2697 | 2708 | |
| 2698 | 2709 | // move everything else down and insert this one at the top |
| 2699 | 2710 | memmove(&m_hotspots[1], &m_hotspots[0], sizeof(m_hotspots[0]) * (m_hotspot_count - 1)); |
| r8806 | r8807 | |
| 2728 | 2739 | assert(m_memory != NULL && m_disasm != NULL); |
| 2729 | 2740 | |
| 2730 | 2741 | // determine the adjusted PC |
| 2731 | const address_space *space = m_memory->space(AS_PROGRAM); | |
| 2732 | offs_t pcbyte = memory_address_to_byte(space, pc) & space->bytemask; | |
| 2742 | address_space *space = m_memory->space(AS_PROGRAM); | |
| 2743 | offs_t pcbyte = space->address_to_byte(pc) & space->bytemask(); | |
| 2733 | 2744 | |
| 2734 | 2745 | // fetch the bytes up to the maximum |
| 2735 | 2746 | UINT8 opbuf[64], argbuf[64]; |
| 2736 | 2747 | int maxbytes = max_opcode_bytes(); |
| 2737 | 2748 | for (int numbytes = 0; numbytes < maxbytes; numbytes++) |
| 2738 | 2749 | { |
| 2739 | opbuf[numbytes] = debug_read_opcode(space, pcbyte + numbytes, 1, FALSE); | |
| 2740 | argbuf[numbytes] = debug_read_opcode(space, pcbyte + numbytes, 1, TRUE); | |
| 2750 | opbuf[numbytes] = debug_read_opcode(space, pcbyte + numbytes, 1, false); | |
| 2751 | argbuf[numbytes] = debug_read_opcode(space, pcbyte + numbytes, 1, true); | |
| 2741 | 2752 | } |
| 2742 | 2753 | |
| 2743 | 2754 | // disassemble to our buffer |
| r8806 | r8807 | |
| 2777 | 2788 | |
| 2778 | 2789 | UINT64 device_debug::get_logunmap(void *globalref, void *ref) |
| 2779 | 2790 | { |
| 2780 | | |
| 2791 | | |
| 2781 | 2792 | return memory_get_log_unmap(space); |
| 2782 | 2793 | } |
| 2783 | 2794 | |
| r8806 | r8807 | |
| 2789 | 2800 | |
| 2790 | 2801 | void device_debug::set_logunmap(void *globalref, void *ref, UINT64 value) |
| 2791 | 2802 | { |
| 2792 | const address_space *space = reinterpret_cast<const address_space *>(ref); | |
| 2793 | memory_set_log_unmap(space, value ? 1 : 0); | |
| 2803 | address_space *space = reinterpret_cast<address_space *>(ref); | |
| 2804 | space->set_log_unmap(value ? true : false); | |
| 2794 | 2805 | } |
| 2795 | 2806 | |
| 2796 | 2807 | |
| r8806 | r8807 | |
| 2881 | 2892 | // watchpoint - constructor |
| 2882 | 2893 | //------------------------------------------------- |
| 2883 | 2894 | |
| 2884 | device_debug::watchpoint::watchpoint(int index, | |
| 2895 | device_debug::watchpoint::watchpoint(int index, | |
| 2885 | 2896 | : m_next(NULL), |
| 2886 | 2897 | m_space(space), |
| 2887 | 2898 | m_index(index), |
| 2888 | 2899 | m_enabled(true), |
| 2889 | 2900 | m_type(type), |
| 2890 | m_address(memory_address_to_byte(&space, address) & space.bytemask), | |
| 2891 | m_length(memory_address_to_byte(&space, length)), | |
| 2901 | m_address(space.address_to_byte(address) & space.bytemask()), | |
| 2902 | m_length(space.address_to_byte(length)), | |
| 2892 | 2903 | m_condition(condition), |
| 2893 | 2904 | m_action((action != NULL) ? action : "") |
| 2894 | 2905 | { |
| r8806 | r8807 | |
|---|---|---|
| 72 | 72 | // debug_view_memory_source - constructors |
| 73 | 73 | //------------------------------------------------- |
| 74 | 74 | |
| 75 | debug_view_memory_source::debug_view_memory_source(const char *name, | |
| 75 | debug_view_memory_source::debug_view_memory_source(const char *name, | |
| 76 | 76 | : debug_view_source(name, space.cpu), |
| 77 | 77 | m_space(&space), |
| 78 | 78 | m_memintf(dynamic_cast<device_memory_interface *>(space.cpu)), |
| 79 | 79 | m_base(NULL), |
| 80 | 80 | m_length(0), |
| 81 | 81 | m_offsetxor(0), |
| 82 | m_endianness(space.endianness), | |
| 83 | m_prefsize(space.dbits / 8) | |
| 82 | m_endianness(space.endianness()), | |
| 83 | m_prefsize(space.data_width() / 8) | |
| 84 | 84 | { |
| 85 | 85 | } |
| 86 | 86 | |
| r8806 | r8807 | |
| 156 | 156 | for (bool gotone = m_machine.m_devicelist.first(memintf); gotone; gotone = memintf->next(memintf)) |
| 157 | 157 | for (int spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++) |
| 158 | 158 | { |
| 159 | | |
| 159 | | |
| 160 | 160 | if (space != NULL) |
| 161 | 161 | { |
| 162 | name.printf("%s '%s' %s space memory", memintf->device().name(), memintf->device().tag(), space->name); | |
| 162 | name.printf("%s '%s' %s space memory", memintf->device().name(), memintf->device().tag(), space->name()); | |
| 163 | 163 | m_source_list.append(*auto_alloc(&m_machine, debug_view_memory_source(name, *space))); |
| 164 | 164 | } |
| 165 | 165 | } |
| r8806 | r8807 | |
| 263 | 263 | if (effrow < m_total.y) |
| 264 | 264 | { |
| 265 | 265 | offs_t addrbyte = m_byte_offset + effrow * m_bytes_per_row; |
| 266 | offs_t address = (source.m_space != NULL) ? | |
| 266 | offs_t address = (source.m_space != NULL) ? s | |
| 267 | 267 | char addrtext[20]; |
| 268 | 268 | |
| 269 | 269 | // generate the address |
| r8806 | r8807 | |
| 441 | 441 | int addrchars; |
| 442 | 442 | if (source.m_space != NULL) |
| 443 | 443 | { |
| 444 | m_maxaddr = m_no_translation ? source.m_space->bytemask : source.m_space->logbytemask; | |
| 445 | addrchars = m_no_translation ? source.m_space->addrchars : source.m_space->logaddrchars; | |
| 444 | m_maxaddr = m_no_translation ? source.m_space->bytemask() : source.m_space->logbytemask(); | |
| 445 | addrchars = m_no_translation ? source.m_space->addrchars() : source.m_space->logaddrchars(); | |
| 446 | 446 | } |
| 447 | 447 | else |
| 448 | 448 | { |
| r8806 | r8807 | |
| 457 | 457 | m_addrformat.printf("%%0%dX%*s", addrchars, 8 - addrchars, ""); |
| 458 | 458 | |
| 459 | 459 | // if we are viewing a space with a minimum chunk size, clamp the bytes per chunk |
| 460 | if (source.m_space != NULL && source.m_space->as | |
| 460 | if (source.m_space != NULL && source.m_space->byte_to_address(1) > 1) | |
| 461 | 461 | { |
| 462 | UINT32 min_bytes_per_chunk = | |
| 462 | UINT32 min_bytes_per_chunk = | |
| 463 | 463 | while (m_bytes_per_chunk < min_bytes_per_chunk) |
| 464 | 464 | { |
| 465 | 465 | m_bytes_per_chunk *= 2; |
| r8806 | r8807 | |
| 521 | 521 | const debug_view_memory_source &source = downcast<const debug_view_memory_source &>(*m_source); |
| 522 | 522 | offs_t resultbyte; |
| 523 | 523 | if (source.m_space != NULL) |
| 524 | resultbyte = | |
| 524 | resultbyte = s | |
| 525 | 525 | else |
| 526 | 526 | resultbyte = m_expression.value(); |
| 527 | 527 | |
| r8806 | r8807 | |
| 621 | 621 | { |
| 622 | 622 | offs_t dummyaddr = offs; |
| 623 | 623 | |
| 624 | bool ismapped = m_no_translation ? true : source.m_memintf->translate(source.m_space->spacenum, TRANSLATE_READ_DEBUG, dummyaddr); | |
| 624 | bool ismapped = m_no_translation ? true : source.m_memintf->translate(source.m_space->spacenum(), TRANSLATE_READ_DEBUG, dummyaddr); | |
| 625 | 625 | data = ~(UINT64)0; |
| 626 | 626 | if (ismapped) |
| 627 | 627 | { |
| r8806 | r8807 | |
|---|---|---|
| 107 | 107 | |
| 108 | 108 | public: |
| 109 | 109 | // construction/destruction |
| 110 | watchpoint(int index, | |
| 110 | watchpoint(int index, | |
| 111 | 111 | ~watchpoint(); |
| 112 | 112 | |
| 113 | 113 | // getters |
| 114 | 114 | watchpoint *next() const { return m_next; } |
| 115 | | |
| 115 | | |
| 116 | 116 | int index() const { return m_index; } |
| 117 | 117 | int type() const { return m_type; } |
| 118 | 118 | bool enabled() const { return m_enabled; } |
| r8806 | r8807 | |
| 126 | 126 | bool hit(int type, offs_t address, int size); |
| 127 | 127 | |
| 128 | 128 | watchpoint * m_next; // next in the list |
| 129 | | |
| 129 | | |
| 130 | 130 | int m_index; // user reported index |
| 131 | 131 | bool m_enabled; // enabled? |
| 132 | 132 | UINT8 m_type; // type (read/write) |
| r8806 | r8807 | |
| 146 | 146 | |
| 147 | 147 | // commonly-used pass-throughs |
| 148 | 148 | offs_t pc() const { return (m_state != NULL) ? m_state->pc() : 0; } |
| 149 | int logaddrchars(int spacenum = AS_PROGRAM) const { return (m_memory != NULL && m_memory->space(spacenum) != NULL) ? m_memory->space(spacenum)->logaddrchars : 8; } | |
| 149 | int logaddrchars(int spacenum = AS_PROGRAM) const { return (m_memory != NULL && m_memory->space(spacenum) != NULL) ? m_memory->space(spacenum)->logaddrchars() : 8; } | |
| 150 | 150 | int min_opcode_bytes() const { return (m_disasm != NULL) ? m_disasm->max_opcode_bytes() : 1; } |
| 151 | 151 | int max_opcode_bytes() const { return (m_disasm != NULL) ? m_disasm->max_opcode_bytes() : 1; } |
| 152 | 152 | |
| r8806 | r8807 | |
| 156 | 156 | void interrupt_hook(int irqline); |
| 157 | 157 | void exception_hook(int exception); |
| 158 | 158 | void instruction_hook(offs_t curpc); |
| 159 | void memory_read_hook(const address_space &space, offs_t address, UINT64 mem_mask); | |
| 160 | void memory_write_hook(const address_space &space, offs_t address, UINT64 data, UINT64 mem_mask); | |
| 159 | void memory_read_hook(address_space &space, offs_t address, UINT64 mem_mask); | |
| 160 | void memory_write_hook(address_space &space, offs_t address, UINT64 data, UINT64 mem_mask); | |
| 161 | 161 | |
| 162 | 162 | // hooks into our operations |
| 163 | 163 | void set_instruction_hook(debug_instruction_hook_func hook); |
| r8806 | r8807 | |
| 194 | 194 | |
| 195 | 195 | // watchpoints |
| 196 | 196 | watchpoint *watchpoint_first(int spacenum) const { return m_wplist[spacenum]; } |
| 197 | int watchpoint_set( | |
| 197 | int watchpoint_set( | |
| 198 | 198 | bool watchpoint_clear(int wpnum); |
| 199 | 199 | void watchpoint_clear_all(); |
| 200 | 200 | bool watchpoint_enable(int index, bool enable = true); |
| r8806 | r8807 | |
| 225 | 225 | // breakpoint and watchpoint helpers |
| 226 | 226 | void breakpoint_update_flags(); |
| 227 | 227 | void breakpoint_check(offs_t pc); |
| 228 | void watchpoint_update_flags(const address_space &space); | |
| 229 | void watchpoint_check(const address_space &space, int type, offs_t address, UINT64 value_to_write, UINT64 mem_mask); | |
| 230 | void hotspot_check(const address_space &space, offs_t address); | |
| 228 | void watchpoint_update_flags(address_space &space); | |
| 229 | void watchpoint_check(address_space &space, int type, offs_t address, UINT64 value_to_write, UINT64 mem_mask); | |
| 230 | void hotspot_check(address_space &space, offs_t address); | |
| 231 | 231 | |
| 232 | 232 | // symbol get/set callbacks |
| 233 | 233 | static UINT64 get_current_pc(void *globalref, void *ref); |
| r8806 | r8807 | |
| 304 | 304 | { |
| 305 | 305 | offs_t m_access; // access address |
| 306 | 306 | offs_t m_pc; // PC of the access |
| 307 | | |
| 307 | | |
| 308 | 308 | UINT32 m_count; // number of hits |
| 309 | 309 | }; |
| 310 | 310 | hotspot_entry * m_hotspots; // hotspot list |
| r8806 | r8807 | |
| 394 | 394 | /* ----- debugger memory accessors ----- */ |
| 395 | 395 | |
| 396 | 396 | /* return the physical address corresponding to the given logical address */ |
| 397 | int debug_cpu_translate( | |
| 397 | int debug_cpu_translate( | |
| 398 | 398 | |
| 399 | 399 | /* return a byte from the the specified memory space */ |
| 400 | UINT8 debug_read_byte( | |
| 400 | UINT8 debug_read_byte( | |
| 401 | 401 | |
| 402 | 402 | /* return a word from the the specified memory space */ |
| 403 | UINT16 debug_read_word( | |
| 403 | UINT16 debug_read_word( | |
| 404 | 404 | |
| 405 | 405 | /* return a dword from the the specified memory space */ |
| 406 | UINT32 debug_read_dword( | |
| 406 | UINT32 debug_read_dword( | |
| 407 | 407 | |
| 408 | 408 | /* return a qword from the the specified memory space */ |
| 409 | UINT64 debug_read_qword( | |
| 409 | UINT64 debug_read_qword( | |
| 410 | 410 | |
| 411 | 411 | /* return 1,2,4 or 8 bytes from the specified memory space */ |
| 412 | UINT64 debug_read_memory( | |
| 412 | UINT64 debug_read_memory( | |
| 413 | 413 | |
| 414 | 414 | /* write a byte to the specified memory space */ |
| 415 | void debug_write_byte( | |
| 415 | void debug_write_byte( | |
| 416 | 416 | |
| 417 | 417 | /* write a word to the specified memory space */ |
| 418 | void debug_write_word( | |
| 418 | void debug_write_word( | |
| 419 | 419 | |
| 420 | 420 | /* write a dword to the specified memory space */ |
| 421 | void debug_write_dword( | |
| 421 | void debug_write_dword( | |
| 422 | 422 | |
| 423 | 423 | /* write a qword to the specified memory space */ |
| 424 | void debug_write_qword( | |
| 424 | void debug_write_qword( | |
| 425 | 425 | |
| 426 | 426 | /* write 1,2,4 or 8 bytes to the specified memory space */ |
| 427 | void debug_write_memory( | |
| 427 | void debug_write_memory( | |
| 428 | 428 | |
| 429 | 429 | /* read 1,2,4 or 8 bytes at the given offset from opcode space */ |
| 430 | UINT64 debug_read_opcode( | |
| 430 | UINT64 debug_read_opcode( | |
| 431 | 431 | |
| 432 | 432 | |
| 433 | 433 | #endif |
| r8806 | r8807 | |
|---|---|---|
| 52 | 52 | { |
| 53 | 53 | friend class debug_view_memory; |
| 54 | 54 | |
| 55 | debug_view_memory_source(const char *name, | |
| 55 | debug_view_memory_source(const char *name, | |
| 56 | 56 | debug_view_memory_source(const char *name, const region_info ®ion); |
| 57 | 57 | debug_view_memory_source(const char *name, void *base, int element_size, int num_elements); |
| 58 | 58 | |
| 59 | 59 | public: |
| 60 | | |
| 60 | | |
| 61 | 61 | |
| 62 | 62 | private: |
| 63 | | |
| 63 | | |
| 64 | 64 | device_memory_interface *m_memintf; // pointer to the memory interface of the device |
| 65 | 65 | void * m_base; // pointer to memory base |
| 66 | 66 | offs_t m_length; // length of memory |
| r8806 | r8807 | |
|---|---|---|
| 161 | 161 | given address is valid for cheating |
| 162 | 162 | -------------------------------------------------*/ |
| 163 | 163 | |
| 164 | INLINE int cheat_address_is_valid( | |
| 164 | INLINE int cheat_address_is_valid( | |
| 165 | 165 | { |
| 166 | 166 | return debug_cpu_translate(space, TRANSLATE_READ, &address) && (memory_get_write_ptr(space, address) != NULL); |
| 167 | 167 | } |
| r8806 | r8807 | |
| 210 | 210 | and swapping if necessary |
| 211 | 211 | -------------------------------------------------*/ |
| 212 | 212 | |
| 213 | INLINE UINT64 cheat_read_extended(const cheat_system *cheatsys, | |
| 213 | INLINE UINT64 cheat_read_extended(const cheat_system *cheatsys, | |
| 214 | 214 | { |
| 215 | 215 | return cheat_sign_extend(cheatsys, cheat_byte_swap(cheatsys, debug_read_memory(space, address, cheatsys->width, TRUE))); |
| 216 | 216 | } |
| r8806 | r8807 | |
| 554 | 554 | address space |
| 555 | 555 | -------------------------------------------------*/ |
| 556 | 556 | |
| 557 | int debug_command_parameter_cpu_space(running_machine *machine, const char *param, int spacenum, | |
| 557 | int debug_command_parameter_cpu_space(running_machine *machine, const char *param, int spacenum, | |
| 558 | 558 | { |
| 559 | 559 | device_t *cpu; |
| 560 | 560 | |
| r8806 | r8807 | |
| 1305 | 1305 | static void execute_wpset(running_machine *machine, int ref, int params, const char *param[]) |
| 1306 | 1306 | { |
| 1307 | 1307 | parsed_expression *condition = NULL; |
| 1308 | | |
| 1308 | | |
| 1309 | 1309 | const char *action = NULL; |
| 1310 | 1310 | UINT64 address, length; |
| 1311 | 1311 | int type = 0; |
| r8806 | r8807 | |
| 1438 | 1438 | { |
| 1439 | 1439 | static const char *const types[] = { "unkn ", "read ", "write", "r/w " }; |
| 1440 | 1440 | |
| 1441 | debug_console_printf(machine, "Device '%s' %s space watchpoints:\n", device->tag(), device->debug()->watchpoint_first(spacenum)->space().name); | |
| 1441 | debug_console_printf(machine, "Device '%s' %s space watchpoints:\n", device->tag(), device->debug()->watchpoint_first(spacenum)->space().name()); | |
| 1442 | 1442 | |
| 1443 | 1443 | /* loop over the watchpoints */ |
| 1444 | 1444 | for (device_debug::watchpoint *wp = device->debug()->watchpoint_first(spacenum); wp != NULL; wp = wp->next()) |
| 1445 | 1445 | { |
| 1446 | 1446 | buffer.printf("%c%4X @ %s-%s %s", wp->enabled() ? ' ' : 'D', wp->index(), |
| 1447 | core_i64_hex_format(memory_byte_to_address(&wp->space(), wp->address()), wp->space().addrchars), | |
| 1448 | core_i64_hex_format(memory_byte_to_address_end(&wp->space(), wp->address() + wp->length()) - 1, wp->space().addrchars), | |
| 1447 | core_i64_hex_format(wp->space().byte_to_address(wp->address()), wp->space().addrchars()), | |
| 1448 | core_i64_hex_format(wp->space().byte_to_address_end(wp->address() + wp->length()) - 1, wp->space().addrchars()), | |
| 1449 | 1449 | types[wp->type() & 3]); |
| 1450 | 1450 | if (wp->condition() != NULL) |
| 1451 | 1451 | buffer.catprintf(" if %s", wp->condition()); |
| r8806 | r8807 | |
| 1511 | 1511 | static void execute_save(running_machine *machine, int ref, int params, const char *param[]) |
| 1512 | 1512 | { |
| 1513 | 1513 | UINT64 offset, endoffset, length; |
| 1514 | | |
| 1514 | | |
| 1515 | 1515 | FILE *f; |
| 1516 | 1516 | UINT64 i; |
| 1517 | 1517 | |
| r8806 | r8807 | |
| 1524 | 1524 | return; |
| 1525 | 1525 | |
| 1526 | 1526 | /* determine the addresses to write */ |
| 1527 | endoffset = memory_address_to_byte(space, offset + length - 1) & space->bytemask; | |
| 1528 | offset = memory_address_to_byte(space, offset) & space->bytemask; | |
| 1527 | endoffset = space->address_to_byte(offset + length - 1) & space->bytemask(); | |
| 1528 | offset = space->address_to_byte(offset) & space->bytemask(); | |
| 1529 | 1529 | |
| 1530 | 1530 | /* open the file */ |
| 1531 | 1531 | f = fopen(param[0], "wb"); |
| r8806 | r8807 | |
| 1555 | 1555 | static void execute_dump(running_machine *machine, int ref, int params, const char *param[]) |
| 1556 | 1556 | { |
| 1557 | 1557 | UINT64 offset, endoffset, length, width = 0, ascii = 1; |
| 1558 | | |
| 1558 | | |
| 1559 | 1559 | FILE *f = NULL; |
| 1560 | 1560 | UINT64 i, j; |
| 1561 | 1561 | |
| r8806 | r8807 | |
| 1573 | 1573 | |
| 1574 | 1574 | /* further validation */ |
| 1575 | 1575 | if (width == 0) |
| 1576 | width = space->dbits / 8; | |
| 1577 | if (width < memory_address_to_byte(space, 1)) | |
| 1578 | width = memory_address_to_byte(space, 1); | |
| 1576 | width = space->data_width() / 8; | |
| 1577 | if (width < space->address_to_byte(1)) | |
| 1578 | width = space->address_to_byte(1); | |
| 1579 | 1579 | if (width != 1 && width != 2 && width != 4 && width != 8) |
| 1580 | 1580 | { |
| 1581 | 1581 | debug_console_printf(machine, "Invalid width! (must be 1,2,4 or 8)\n"); |
| 1582 | 1582 | return; |
| 1583 | 1583 | } |
| 1584 | endoffset = memory_address_to_byte(space, offset + length - 1) & space->bytemask; | |
| 1585 | offset = memory_address_to_byte(space, offset) & space->bytemask; | |
| 1584 | endoffset = space->address_to_byte(offset + length - 1) & space->bytemask(); | |
| 1585 | offset = space->address_to_byte(offset) & space->bytemask(); | |
| 1586 | 1586 | |
| 1587 | 1587 | /* open the file */ |
| 1588 | 1588 | f = fopen(param[0], "w"); |
| r8806 | r8807 | |
| 1599 | 1599 | int outdex = 0; |
| 1600 | 1600 | |
| 1601 | 1601 | /* print the address */ |
| 1602 | outdex += sprintf(&output[outdex], "%s: ", core_i64_hex_format((UINT32) | |
| 1602 | outdex += sprintf(&output[outdex], "%s: ", core_i64_hex_format((UINT32)space-> | |
| 1603 | 1603 | |
| 1604 | 1604 | /* print the bytes */ |
| 1605 | 1605 | for (j = 0; j < 16; j += width) |
| r8806 | r8807 | |
| 1653 | 1653 | static void execute_cheatinit(running_machine *machine, int ref, int params, const char *param[]) |
| 1654 | 1654 | { |
| 1655 | 1655 | UINT64 offset, length = 0, real_length = 0; |
| 1656 | | |
| 1656 | | |
| 1657 | 1657 | UINT32 active_cheat = 0; |
| 1658 | 1658 | UINT64 curaddr; |
| 1659 | 1659 | UINT8 i, region_count = 0; |
| r8806 | r8807 | |
| 1711 | 1711 | if (params <= 1) |
| 1712 | 1712 | { |
| 1713 | 1713 | offset = 0; |
| 1714 | length = space->bytemask + 1; | |
| 1715 | for (entry = space->map->m_entrylist; entry != NULL; entry = entry->m_next) | |
| 1714 | length = space->bytemask() + 1; | |
| 1715 | for (entry = space->map()->m_entrylist.first(); entry != NULL; entry = entry->next()) | |
| 1716 | 1716 | { |
| 1717 | cheat_region[region_count].offset = memory_address_to_byte(space, entry->m_addrstart) & space->bytemask; | |
| 1718 | cheat_region[region_count].endoffset = memory_address_to_byte(space, entry->m_addrend) & space->bytemask; | |
| 1717 | cheat_region[region_count].offset = space->address_to_byte(entry->m_addrstart) & space->bytemask(); | |
| 1718 | cheat_region[region_count].endoffset = space->address_to_byte(entry->m_addrend) & space->bytemask(); | |
| 1719 | 1719 | cheat_region[region_count].share = entry->m_share; |
| 1720 | cheat_region[region_count].disabled = (entry->m_write.type == AMH_RAM) ? FALSE : TRUE; | |
| 1720 | cheat_region[region_count].disabled = (entry->m_write.m_type == AMH_RAM) ? FALSE : TRUE; | |
| 1721 | 1721 | |
| 1722 | 1722 | /* disable double share regions */ |
| 1723 | 1723 | if (entry->m_share != NULL) |
| 1724 | 1724 | for (i = 0; i < region_count; i++) |
| 1725 | 1725 | if (cheat_region[i].share != NULL) |
| 1726 | if (strcmp(cheat_region[i].share, entry->m_share)==0) | |
| 1726 | if (strcmp(cheat_region[i].share, entry->m_share) == 0) | |
| 1727 | 1727 | cheat_region[region_count].disabled = TRUE; |
| 1728 | 1728 | |
| 1729 | 1729 | region_count++; |
| r8806 | r8807 | |
| 1738 | 1738 | return; |
| 1739 | 1739 | |
| 1740 | 1740 | /* force region to the specified range */ |
| 1741 | cheat_region[region_count].offset = memory_address_to_byte(space, offset) & space->bytemask;; | |
| 1742 | cheat_region[region_count].endoffset = memory_address_to_byte(space, offset + length - 1) & space->bytemask;; | |
| 1741 | cheat_region[region_count].offset = space->address_to_byte(offset) & space->bytemask(); | |
| 1742 | cheat_region[region_count].endoffset = space->address_to_byte(offset + length - 1) & space->bytemask(); | |
| 1743 | 1743 | cheat_region[region_count].share = NULL; |
| 1744 | 1744 | cheat_region[region_count].disabled = FALSE; |
| 1745 | 1745 | region_count++; |
| r8806 | r8807 | |
| 1815 | 1815 | |
| 1816 | 1816 | static void execute_cheatnext(running_machine *machine, int ref, int params, const char *param[]) |
| 1817 | 1817 | { |
| 1818 | | |
| 1818 | | |
| 1819 | 1819 | UINT64 cheatindex; |
| 1820 | 1820 | UINT32 active_cheat = 0; |
| 1821 | 1821 | UINT8 condition; |
| r8806 | r8807 | |
| 1984 | 1984 | static void execute_cheatlist(running_machine *machine, int ref, int params, const char *param[]) |
| 1985 | 1985 | { |
| 1986 | 1986 | char spaceletter, sizeletter; |
| 1987 | | |
| 1987 | | |
| 1988 | 1988 | device_t *cpu; |
| 1989 | 1989 | UINT32 active_cheat = 0; |
| 1990 | 1990 | UINT64 cheatindex; |
| r8806 | r8807 | |
| 2000 | 2000 | if (params > 0) |
| 2001 | 2001 | f = fopen(param[0], "w"); |
| 2002 | 2002 | |
| 2003 | switch (space->spacenum) | |
| 2003 | switch (space->spacenum()) | |
| 2004 | 2004 | { |
| 2005 | 2005 | default: |
| 2006 | 2006 | case ADDRESS_SPACE_PROGRAM: spaceletter = 'p'; break; |
| r8806 | r8807 | |
| 2023 | 2023 | if (cheat.cheatmap[cheatindex].state == 1) |
| 2024 | 2024 | { |
| 2025 | 2025 | UINT64 value = cheat_byte_swap(&cheat, cheat_read_extended(&cheat, space, cheat.cheatmap[cheatindex].offset)) & sizemask; |
| 2026 | offs_t address = | |
| 2026 | offs_t address = space-> | |
| 2027 | 2027 | |
| 2028 | 2028 | if (params > 0) |
| 2029 | 2029 | { |
| 2030 | 2030 | active_cheat++; |
| 2031 | fprintf(f, " <cheat desc=\"Possibility %d : %s (%s)\">\n", active_cheat, core_i64_hex_format(address, space->logaddrchars), core_i64_hex_format(value, cheat.width * 2)); | |
| 2031 | fprintf(f, " <cheat desc=\"Possibility %d : %s (%s)\">\n", active_cheat, core_i64_hex_format(address, space->logaddrchars()), core_i64_hex_format(value, cheat.width * 2)); | |
| 2032 | 2032 | fprintf(f, " <script state=\"run\">\n"); |
| 2033 | fprintf(f, " <action>%s.p%c%c@%s=%s</action>\n", cpu->tag(), spaceletter, sizeletter, core_i64_hex_format(address, space->logaddrchars), core_i64_hex_format(cheat_byte_swap(&cheat, cheat.cheatmap[cheatindex].first_value) & sizemask, cheat.width * 2)); | |
| 2033 | fprintf(f, " <action>%s.p%c%c@%s=%s</action>\n", cpu->tag(), spaceletter, sizeletter, core_i64_hex_format(address, space->logaddrchars()), core_i64_hex_format(cheat_byte_swap(&cheat, cheat.cheatmap[cheatindex].first_value) & sizemask, cheat.width * 2)); | |
| 2034 | 2034 | fprintf(f, " </script>\n"); |
| 2035 | 2035 | fprintf(f, " </cheat>\n\n"); |
| 2036 | 2036 | } |
| 2037 | 2037 | else |
| 2038 | debug_console_printf(machine, "Address=%s Start=%s Current=%s\n", core_i64_hex_format(address, space->logaddrchars), core_i64_hex_format(cheat_byte_swap(&cheat, cheat.cheatmap[cheatindex].first_value) & sizemask, cheat.width * 2), core_i64_hex_format(value, cheat.width * 2)); | |
| 2038 | debug_console_printf(machine, "Address=%s Start=%s Current=%s\n", core_i64_hex_format(address, space->logaddrchars()), core_i64_hex_format(cheat_byte_swap(&cheat, cheat.cheatmap[cheatindex].first_value) & sizemask, cheat.width * 2), core_i64_hex_format(value, cheat.width * 2)); | |
| 2039 | 2039 | } |
| 2040 | 2040 | } |
| 2041 | 2041 | if (params > 0) |
| r8806 | r8807 | |
| 2079 | 2079 | static void execute_find(running_machine *machine, int ref, int params, const char *param[]) |
| 2080 | 2080 | { |
| 2081 | 2081 | UINT64 offset, endoffset, length; |
| 2082 | | |
| 2082 | | |
| 2083 | 2083 | UINT64 data_to_find[256]; |
| 2084 | 2084 | UINT8 data_size[256]; |
| 2085 | 2085 | int cur_data_size; |
| r8806 | r8807 | |
| 2096 | 2096 | return; |
| 2097 | 2097 | |
| 2098 | 2098 | /* further validation */ |
| 2099 | endoffset = memory_address_to_byte(space, offset + length - 1) & space->bytemask; | |
| 2100 | offset = memory_address_to_byte(space, offset) & space->bytemask; | |
| 2101 | cur_data_size = memory_address_to_byte(space, 1); | |
| 2099 | endoffset = space->address_to_byte(offset + length - 1) & space->bytemask(); | |
| 2100 | offset = space->address_to_byte(offset) & space->bytemask(); | |
| 2101 | cur_data_size = space->address_to_byte(1); | |
| 2102 | 2102 | if (cur_data_size == 0) |
| 2103 | 2103 | cur_data_size = 1; |
| 2104 | 2104 | |
| r8806 | r8807 | |
| 2161 | 2161 | if (match) |
| 2162 | 2162 | { |
| 2163 | 2163 | found++; |
| 2164 | debug_console_printf(machine, "Found at %s\n", core_i64_hex_format((UINT32) | |
| 2164 | debug_console_printf(machine, "Found at %s\n", core_i64_hex_format((UINT32)space-> | |
| 2165 | 2165 | } |
| 2166 | 2166 | } |
| 2167 | 2167 | |
| r8806 | r8807 | |
| 2179 | 2179 | { |
| 2180 | 2180 | UINT64 offset, length, bytes = 1; |
| 2181 | 2181 | int minbytes, maxbytes, byteswidth; |
| 2182 | | |
| 2182 | | |
| 2183 | 2183 | FILE *f = NULL; |
| 2184 | 2184 | int i, j; |
| 2185 | 2185 | |
| r8806 | r8807 | |
| 2215 | 2215 | /* now write the data out */ |
| 2216 | 2216 | for (i = 0; i < length; ) |
| 2217 | 2217 | { |
| 2218 | int pcbyte = | |
| 2218 | int pcbyte = space-> | |
| 2219 | 2219 | char output[200+DEBUG_COMMENT_MAX_LINE_LENGTH], disasm[200]; |
| 2220 | 2220 | const char *comment; |
| 2221 | 2221 | offs_t tempaddr; |
| r8806 | r8807 | |
| 2223 | 2223 | int numbytes = 0; |
| 2224 | 2224 | |
| 2225 | 2225 | /* print the address */ |
| 2226 | outdex += sprintf(&output[outdex], "%s: ", core_i64_hex_format((UINT32) | |
| 2226 | outdex += sprintf(&output[outdex], "%s: ", core_i64_hex_format((UINT32)space-> | |
| 2227 | 2227 | |
| 2228 | 2228 | /* make sure we can translate the address */ |
| 2229 | 2229 | tempaddr = pcbyte; |
| r8806 | r8807 | |
| 2246 | 2246 | if (bytes) |
| 2247 | 2247 | { |
| 2248 | 2248 | int startdex = outdex; |
| 2249 | numbytes = | |
| 2249 | numbytes = space-> | |
| 2250 | 2250 | for (j = 0; j < numbytes; j += minbytes) |
| 2251 | 2251 | outdex += sprintf(&output[outdex], "%s ", core_i64_hex_format(debug_read_opcode(space, pcbyte + j, minbytes, FALSE), minbytes * 2)); |
| 2252 | 2252 | if (outdex - startdex < byteswidth) |
| r8806 | r8807 | |
| 2373 | 2373 | static void execute_history(running_machine *machine, int ref, int params, const char *param[]) |
| 2374 | 2374 | { |
| 2375 | 2375 | /* validate parameters */ |
| 2376 | | |
| 2376 | | |
| 2377 | 2377 | if (!debug_command_parameter_cpu_space(machine, (params > 0) ? param[0] : NULL, ADDRESS_SPACE_PROGRAM, &space)) |
| 2378 | 2378 | return; |
| 2379 | 2379 | |
| r8806 | r8807 | |
| 2394 | 2394 | offs_t pc = debug->history_pc(-index); |
| 2395 | 2395 | |
| 2396 | 2396 | /* fetch the bytes up to the maximum */ |
| 2397 | offs_t pcbyte = | |
| 2397 | offs_t pcbyte = space-> | |
| 2398 | 2398 | UINT8 opbuf[64], argbuf[64]; |
| 2399 | 2399 | for (int numbytes = 0; numbytes < maxbytes; numbytes++) |
| 2400 | 2400 | { |
| r8806 | r8807 | |
| 2405 | 2405 | char buffer[200]; |
| 2406 | 2406 | debug->disassemble(buffer, pc, opbuf, argbuf); |
| 2407 | 2407 | |
| 2408 | debug_console_printf(machine, "%s: %s\n", core_i64_hex_format(pc, space->logaddrchars), buffer); | |
| 2408 | debug_console_printf(machine, "%s: %s\n", core_i64_hex_format(pc, space->logaddrchars()), buffer); | |
| 2409 | 2409 | } |
| 2410 | 2410 | } |
| 2411 | 2411 | |
| r8806 | r8807 | |
| 2473 | 2473 | |
| 2474 | 2474 | static void execute_map(running_machine *machine, int ref, int params, const char *param[]) |
| 2475 | 2475 | { |
| 2476 | | |
| 2476 | | |
| 2477 | 2477 | offs_t taddress; |
| 2478 | 2478 | UINT64 address; |
| 2479 | 2479 | int intention; |
| r8806 | r8807 | |
| 2490 | 2490 | for (intention = TRANSLATE_READ_DEBUG; intention <= TRANSLATE_FETCH_DEBUG; intention++) |
| 2491 | 2491 | { |
| 2492 | 2492 | static const char *const intnames[] = { "Read", "Write", "Fetch" }; |
| 2493 | taddress = | |
| 2493 | taddress = space-> | |
| 2494 | 2494 | if (debug_cpu_translate(space, intention, &taddress)) |
| 2495 | 2495 | { |
| 2496 | const char *mapname = memory_get_handler_string(space, intention == TRANSLATE_WRITE_DEBUG, taddress); | |
| 2497 | debug_console_printf(machine, "%7s: %s logical == %s physical -> %s\n", intnames[intention & 3], core_i64_hex_format(address, space->logaddrchars), core_i64_hex_format(memory_byte_to_address(space, taddress), space->addrchars), mapname); | |
| 2496 | const char *mapname = const_cast<address_space *>(space)->get_handler_string((intention == TRANSLATE_WRITE_DEBUG) ? ROW_WRITE : ROW_READ, taddress); | |
| 2497 | debug_console_printf(machine, "%7s: %s logical == %s physical -> %s\n", intnames[intention & 3], core_i64_hex_format(address, space->logaddrchars()), core_i64_hex_format(space->byte_to_address(taddress), space->addrchars()), mapname); | |
| 2498 | 2498 | } |
| 2499 | 2499 | else |
| 2500 | debug_console_printf(machine, "%7s: %s logical is unmapped\n", intnames[intention & 3], core_i64_hex_format(address, space->logaddrchars)); | |
| 2500 | debug_console_printf(machine, "%7s: %s logical is unmapped\n", intnames[intention & 3], core_i64_hex_format(address, space->logaddrchars())); | |
| 2501 | 2501 | } |
| 2502 | 2502 | } |
| 2503 | 2503 |
| r8806 | r8807 | |
|---|---|---|
| 203 | 203 | case DCH_HOME: // set the active column to the PC |
| 204 | 204 | { |
| 205 | 205 | const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source); |
| 206 | offs_t pc = | |
| 206 | offs_t pc = s | |
| 207 | 207 | |
| 208 | 208 | // figure out which row the pc is on |
| 209 | 209 | for (int curline = 0; curline < m_allocated.y; curline++) |
| r8806 | r8807 | |
| 242 | 242 | const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source); |
| 243 | 243 | |
| 244 | 244 | // compute the increment |
| 245 | int minlen = | |
| 245 | int minlen = s | |
| 246 | 246 | if (minlen == 0) minlen = 1; |
| 247 | int maxlen = | |
| 247 | int maxlen = s | |
| 248 | 248 | if (maxlen == 0) maxlen = 1; |
| 249 | 249 | |
| 250 | 250 | // start off numinstrs back |
| r8806 | r8807 | |
| 253 | 253 | curpc = 0; |
| 254 | 254 | |
| 255 | 255 | /* loop until we find what we are looking for */ |
| 256 | offs_t targetpcbyte = | |
| 256 | offs_t targetpcbyte = s | |
| 257 | 257 | offs_t fillpcbyte = targetpcbyte; |
| 258 | 258 | offs_t lastgoodpc = targetpc; |
| 259 | 259 | while (1) |
| 260 | 260 | { |
| 261 | 261 | // fill the buffer up to the target |
| 262 | offs_t curpcbyte = | |
| 262 | offs_t curpcbyte = s | |
| 263 | 263 | UINT8 opbuf[1024], argbuf[1024]; |
| 264 | 264 | while (curpcbyte < fillpcbyte) |
| 265 | 265 | { |
| r8806 | r8807 | |
| 274 | 274 | offs_t scanpc; |
| 275 | 275 | for (scanpc = curpc; scanpc < targetpc; scanpc += instlen) |
| 276 | 276 | { |
| 277 | offs_t scanpcbyte = | |
| 277 | offs_t scanpcbyte = s | |
| 278 | 278 | offs_t physpcbyte = scanpcbyte; |
| 279 | 279 | |
| 280 | 280 | // get the disassembly, but only if mapped |
| r8806 | r8807 | |
| 348 | 348 | const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source); |
| 349 | 349 | |
| 350 | 350 | // determine how many characters we need for an address and set the divider |
| 351 | m_divider1 = 1 + source.m_space->logaddrchars + 1; | |
| 351 | m_divider1 = 1 + source.m_space->logaddrchars() + 1; | |
| 352 | 352 | |
| 353 | 353 | // assume a fixed number of characters for the disassembly |
| 354 | 354 | m_divider2 = m_divider1 + 1 + m_dasm_width + 1; |
| r8806 | r8807 | |
| 358 | 358 | int maxbytes = source.m_disasmintf->max_opcode_bytes(); |
| 359 | 359 | |
| 360 | 360 | // ensure that the PC is aligned to the minimum opcode size |
| 361 | pc &= ~ | |
| 361 | pc &= ~s | |
| 362 | 362 | |
| 363 | 363 | // set the width of the third column according to display mode |
| 364 | 364 | if (m_right_column == DASM_RIGHTCOL_RAW || m_right_column == DASM_RIGHTCOL_ENCRYPTED) |
| r8806 | r8807 | |
| 390 | 390 | for (int line = 0; line < lines; line++) |
| 391 | 391 | { |
| 392 | 392 | // convert PC to a byte offset |
| 393 | offs_t pcbyte = | |
| 393 | offs_t pcbyte = s | |
| 394 | 394 | |
| 395 | 395 | // save a copy of the previous line as a backup if we're only doing one line |
| 396 | 396 | int instr = startline + line; |
| r8806 | r8807 | |
| 401 | 401 | |
| 402 | 402 | // convert back and set the address of this instruction |
| 403 | 403 | m_byteaddress[instr] = pcbyte; |
| 404 | sprintf(&destbuf[0], " %s ", core_i64_hex_format( | |
| 404 | sprintf(&destbuf[0], " %s ", core_i64_hex_format(s | |
| 405 | 405 | |
| 406 | 406 | // make sure we can translate the address, and then disassemble the result |
| 407 | 407 | char buffer[100]; |
| r8806 | r8807 | |
| 419 | 419 | } |
| 420 | 420 | |
| 421 | 421 | // disassemble the result |
| 422 | pc += numbytes = source.m_disasmintf->disassemble(buffer, pc & source.m_space->logaddrmask, opbuf, argbuf) & DASMFLAG_LENGTHMASK; | |
| 422 | pc += numbytes = source.m_disasmintf->disassemble(buffer, pc & source.m_space->logaddrmask(), opbuf, argbuf) & DASMFLAG_LENGTHMASK; | |
| 423 | 423 | } |
| 424 | 424 | else |
| 425 | 425 | strcpy(buffer, "<unmapped>"); |
| r8806 | r8807 | |
| 431 | 431 | if (m_right_column == DASM_RIGHTCOL_RAW || m_right_column == DASM_RIGHTCOL_ENCRYPTED) |
| 432 | 432 | { |
| 433 | 433 | // get the bytes |
| 434 | numbytes = | |
| 434 | numbytes = s | |
| 435 | 435 | generate_bytes(pcbyte, numbytes, minbytes, &destbuf[m_divider2], m_allocated.x - m_divider2, m_right_column == DASM_RIGHTCOL_ENCRYPTED); |
| 436 | 436 | } |
| 437 | 437 | else if (m_right_column == DASM_RIGHTCOL_COMMENTS) |
| 438 | 438 | { |
| 439 | 439 | // get and add the comment, if present |
| 440 | offs_t comment_address = | |
| 440 | offs_t comment_address = s | |
| 441 | 441 | const char *text = debug_comment_get_text(&source.m_device, comment_address, debug_comment_get_opcode_crc32(&source.m_device, comment_address)); |
| 442 | 442 | if (text != NULL) |
| 443 | 443 | sprintf(&destbuf[m_divider2], "// %.*s", m_allocated.x - m_divider2 - 1, text); |
| r8806 | r8807 | |
| 449 | 449 | } |
| 450 | 450 | |
| 451 | 451 | // update opcode base information |
| 452 | m_last_direct_decrypted = source.m_space->direct.decrypted; | |
| 453 | m_last_direct_raw = source.m_space->direct.raw; | |
| 452 | m_last_direct_decrypted = source.m_space->direct().decrypted(); | |
| 453 | m_last_direct_raw = source.m_space->direct().raw(); | |
| 454 | 454 | m_last_change_count = debug_comment_all_change_count(&m_machine); |
| 455 | 455 | |
| 456 | 456 | // now longer need to recompute |
| r8806 | r8807 | |
| 469 | 469 | const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source); |
| 470 | 470 | |
| 471 | 471 | offs_t pc = cpu_get_pc(&source.m_device); |
| 472 | offs_t pcbyte = | |
| 472 | offs_t pcbyte = s | |
| 473 | 473 | |
| 474 | 474 | // update our context; if the expression is dirty, recompute |
| 475 | 475 | if (m_expression.dirty()) |
| r8806 | r8807 | |
| 480 | 480 | UINT64 result = m_expression.value(); |
| 481 | 481 | if (result != previous) |
| 482 | 482 | { |
| 483 | offs_t resultbyte = | |
| 483 | offs_t resultbyte = s | |
| 484 | 484 | |
| 485 | 485 | // see if the new result is an address we already have |
| 486 | 486 | UINT32 row; |
| r8806 | r8807 | |
| 498 | 498 | } |
| 499 | 499 | |
| 500 | 500 | // if the opcode base has changed, rework things |
| 501 | if (source.m_space->direct.decrypted != m_last_direct_decrypted || source.m_space->direct.raw != m_last_direct_raw) | |
| 501 | if (source.m_space->direct().decrypted() != m_last_direct_decrypted || source.m_space->direct().raw() != m_last_direct_raw) | |
| 502 | 502 | m_recompute = true; |
| 503 | 503 | |
| 504 | 504 | // if the comments have changed, redo it |
| r8806 | r8807 | |
| 517 | 517 | m_topleft.x = 0; |
| 518 | 518 | |
| 519 | 519 | // recompute from where we last recomputed! |
| 520 | recompute( | |
| 520 | recompute(s | |
| 521 | 521 | } |
| 522 | 522 | else |
| 523 | 523 | { |
| r8806 | r8807 | |
| 579 | 579 | else |
| 580 | 580 | { |
| 581 | 581 | for (device_debug::breakpoint *bp = source.m_device.debug()->breakpoint_first(); bp != NULL; bp = bp->next()) |
| 582 | if (m_byteaddress[effrow] == ( | |
| 582 | if (m_byteaddress[effrow] == (s | |
| 583 | 583 | attrib = DCA_CHANGED; |
| 584 | 584 | } |
| 585 | 585 | |
| r8806 | r8807 | |
| 627 | 627 | offs_t debug_view_disasm::selected_address() |
| 628 | 628 | { |
| 629 | 629 | flush_updates(); |
| 630 | return | |
| 630 | return | |
| 631 | 631 | } |
| 632 | 632 | |
| 633 | 633 | |
| r8806 | r8807 | |
| 695 | 695 | void debug_view_disasm::set_selected_address(offs_t address) |
| 696 | 696 | { |
| 697 | 697 | const debug_view_disasm_source &source = downcast<const debug_view_disasm_source &>(*m_source); |
| 698 | offs_t byteaddress = | |
| 698 | offs_t byteaddress = s | |
| 699 | 699 | for (int line = 0; line < m_total.y; line++) |
| 700 | 700 | if (m_byteaddress[line] == byteaddress) |
| 701 | 701 | { |
| r8806 | r8807 | |
|---|---|---|
| 33 | 33 | int debug_command_parameter_cpu(running_machine *machine, const char *param, device_t **result); |
| 34 | 34 | |
| 35 | 35 | /* validates a parameter as a cpu and retrieves the given address space */ |
| 36 | int debug_command_parameter_cpu_space(running_machine *machine, const char *param, int spacenum, | |
| 36 | int debug_command_parameter_cpu_space(running_machine *machine, const char *param, int spacenum, | |
| 37 | 37 | |
| 38 | 38 | #endif |
| r8806 | r8807 | |
|---|---|---|
| 73 | 73 | public: |
| 74 | 74 | // getters |
| 75 | 75 | device_t &device() const { return m_device; } |
| 76 | | |
| 76 | | |
| 77 | 77 | |
| 78 | 78 | private: |
| 79 | 79 | // internal state |
| 80 | 80 | device_t & m_device; // underlying device |
| 81 | 81 | device_disasm_interface *m_disasmintf; // disassembly interface |
| 82 | | |
| 82 | | |
| 83 | 83 | }; |
| 84 | 84 | |
| 85 | 85 |
| r8806 | r8807 | |
|---|---|---|
| 281 | 281 | |
| 282 | 282 | UINT32 debug_comment_get_opcode_crc32(device_t *device, offs_t address) |
| 283 | 283 | { |
| 284 | | |
| 284 | | |
| 285 | 285 | int i; |
| 286 | 286 | UINT32 crc; |
| 287 | 287 | UINT8 opbuf[64], argbuf[64]; |
| r8806 | r8807 | |
| 289 | 289 | offs_t numbytes; |
| 290 | 290 | cpu_device *cpudevice = downcast<cpu_device *>(device); |
| 291 | 291 | int maxbytes = cpudevice->max_opcode_bytes(); |
| 292 | UINT32 addrmask = space->logaddrmask; | |
| 292 | UINT32 addrmask = space->logaddrmask(); | |
| 293 | 293 | |
| 294 | 294 | memset(opbuf, 0x00, sizeof(opbuf)); |
| 295 | 295 | memset(argbuf, 0x00, sizeof(argbuf)); |
| r8806 | r8807 | |
| 302 | 302 | } |
| 303 | 303 | |
| 304 | 304 | numbytes = device->debug()->disassemble(buff, address & addrmask, opbuf, argbuf) & DASMFLAG_LENGTHMASK; |
| 305 | numbytes = | |
| 305 | numbytes = space-> | |
| 306 | 306 | |
| 307 | 307 | crc = crc32(0, argbuf, numbytes); |
| 308 | 308 |
| r8806 | r8807 | |
|---|---|---|
| 85 | 85 | |
| 86 | 86 | device_irq_callback irq_callback; |
| 87 | 87 | legacy_cpu_device *device; |
| 88 | const address_space *program; | |
| 89 | const address_space *io; | |
| 88 | address_space *program; | |
| 89 | address_space *io; | |
| 90 | 90 | int icount; |
| 91 | 91 | |
| 92 | 92 | UINT32 prefix_base; /* base address of the latest prefix segment */ |
| r8806 | r8807 | |
|---|---|---|
| 74 | 74 | |
| 75 | 75 | #define DefaultBase(Seg) ((cpustate->seg_prefix && (Seg==DS || Seg==SS)) ? cpustate->prefix_base : cpustate->sregs[Seg] << 4) |
| 76 | 76 | |
| 77 | #define GetMemB(Seg,Off) ((UINT8)memory_read_byte_8le(cpustate->program, (DefaultBase(Seg)+(Off)))) | |
| 78 | #define GetMemW(Seg,Off) ((UINT16) memory_read_byte_8le(cpustate->program, (DefaultBase(Seg)+(Off))) + (memory_read_byte_8le(cpustate->program, (DefaultBase(Seg)+((Off)+1)))<<8) ) | |
| 77 | #define GetMemB(Seg,Off) ((UINT8)cpustate->program->read_byte((DefaultBase(Seg)+(Off)))) | |
| 78 | #define GetMemW(Seg,Off) ((UINT16) cpustate->program->read_byte((DefaultBase(Seg)+(Off))) + (cpustate->program->read_byte((DefaultBase(Seg)+((Off)+1)))<<8) ) | |
| 79 | 79 | |
| 80 | #define PutMemB(Seg,Off,x) { | |
| 80 | #define PutMemB(Seg,Off,x) { | |
| 81 | 81 | #define PutMemW(Seg,Off,x) { PutMemB(Seg,Off,(x)&0xff); PutMemB(Seg,(Off)+1,(BYTE)((x)>>8)); } |
| 82 | 82 | |
| 83 | 83 | /* Todo: Remove these later - plus readword could overflow */ |
| 84 | #define ReadByte(ea) ((BYTE)memory_read_byte_8le(cpustate->program, (ea))) | |
| 85 | #define ReadWord(ea) (memory_read_byte_8le(cpustate->program, (ea))+(memory_read_byte_8le(cpustate->program, ((ea)+1))<<8)) | |
| 86 | #define WriteByte(ea,val) { memory_write_byte_8le(cpustate->program, (ea),val); } | |
| 87 | #define WriteWord(ea,val) { memory_write_byte_8le(cpustate->program, (ea),(BYTE)(val)); memory_write_byte_8le(cpustate->program, ((ea)+1),(val)>>8); } | |
| 84 | #define ReadByte(ea) ((BYTE)cpustate->program->read_byte((ea))) | |
| 85 | #define ReadWord(ea) (cpustate->program->read_byte((ea))+(cpustate->program->read_byte(((ea)+1))<<8)) | |
| 86 | #define WriteByte(ea,val) { cpustate->program->write_byte((ea),val); } | |
| 87 | #define WriteWord(ea,val) { cpustate->program->write_byte((ea),(BYTE)(val)); cpustate->program->write_byte(((ea)+1),(val)>>8); } | |
| 88 | 88 | |
| 89 | #define read_port(port) memory_read_byte_8le(cpustate->io, port) | |
| 90 | #define write_port(port,val) memory_write_byte_8le(cpustate->io, port,val) | |
| 89 | #define read_port(port) cpustate->io->read_byte(port) | |
| 90 | #define write_port(port,val) cpustate->io->write_byte(port,val) | |
| 91 | 91 | |
| 92 | 92 | #define FETCH (memory_raw_read_byte(cpustate->program, (cpustate->sregs[CS]<<4)+cpustate->ip++)) |
| 93 | 93 | #define FETCHOP (memory_decrypted_read_byte(cpustate->program, (cpustate->sregs[CS]<<4)+cpustate->ip++)) |
| r8806 | r8807 | |
|---|---|---|
| 62 | 62 | UINT16 pending_interrupts; /* MB */ |
| 63 | 63 | device_irq_callback irq_callback; |
| 64 | 64 | legacy_cpu_device *device; |
| 65 | | |
| 65 | | |
| 66 | 66 | int irq_state[9]; /* KW Additional lines for HD63705 */ |
| 67 | 67 | int nmi_state; |
| 68 | 68 | } m6805_Regs; |
| r8806 | r8807 | |
| 79 | 79 | /****************************************************************************/ |
| 80 | 80 | /* Read a byte from given memory location */ |
| 81 | 81 | /****************************************************************************/ |
| 82 | #define M6805_RDMEM(Addr) ((unsigned) | |
| 82 | #define M6805_RDMEM(Addr) ((unsigned) | |
| 83 | 83 | |
| 84 | 84 | /****************************************************************************/ |
| 85 | 85 | /* Write a byte to given memory location */ |
| 86 | 86 | /****************************************************************************/ |
| 87 | #define M6805_WRMEM(Addr,Value) ( | |
| 87 | #define M6805_WRMEM(Addr,Value) ( | |
| 88 | 88 | |
| 89 | 89 | /****************************************************************************/ |
| 90 | 90 | /* M6805_RDOP() is identical to M6805_RDMEM() except it is used for reading */ |
| r8806 | r8807 | |
|---|---|---|
| 37 | 37 | |
| 38 | 38 | INLINE void lh5801_add_mem(lh5801_state *cpustate, int addr, UINT8 data) |
| 39 | 39 | { |
| 40 | int v=lh5801_add_generic(cpustate,memory_read_byte(cpustate->program,addr),data,0); | |
| 41 | memory_write_byte(cpustate->program,addr,v); | |
| 40 | int v=lh5801_add_generic(cpustate,cpustate->program->read_byte(addr),data,0); | |
| 41 | cpustate->program->write_byte(addr,v); | |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | 44 | INLINE void lh5801_adr(lh5801_state *cpustate, PAIR *reg) |
| r8806 | r8807 | |
| 97 | 97 | |
| 98 | 98 | INLINE void lh5801_and_mem(lh5801_state *cpustate, int addr, UINT8 data) |
| 99 | 99 | { |
| 100 | data&= | |
| 100 | data&= | |
| 101 | 101 | cpustate->t&=~Z; |
| 102 | 102 | if (!data) cpustate->t|=Z; |
| 103 | | |
| 103 | | |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | 106 | INLINE void lh5801_bit(lh5801_state *cpustate, UINT8 a, UINT8 b) |
| r8806 | r8807 | |
| 125 | 125 | |
| 126 | 126 | INLINE void lh5801_ora_mem(lh5801_state *cpustate, int addr, UINT8 data) |
| 127 | 127 | { |
| 128 | data|= | |
| 128 | data|= | |
| 129 | 129 | cpustate->t&=~Z; |
| 130 | 130 | if (!data) cpustate->t|=Z; |
| 131 | | |
| 131 | | |
| 132 | 132 | } |
| 133 | 133 | |
| 134 | 134 | INLINE void lh5801_lda(lh5801_state *cpustate, UINT8 data) |
| r8806 | r8807 | |
| 141 | 141 | INLINE void lh5801_lde(lh5801_state *cpustate, PAIR *reg) |
| 142 | 142 | { |
| 143 | 143 | // or z flag depends on reg |
| 144 | cpustate->a= | |
| 144 | cpustate->a= | |
| 145 | 145 | cpustate->t&=~Z; |
| 146 | 146 | if (!cpustate->a) cpustate->t|=Z; |
| 147 | 147 | } |
| 148 | 148 | |
| 149 | 149 | INLINE void lh5801_sde(lh5801_state *cpustate, PAIR *reg) |
| 150 | 150 | { |
| 151 | | |
| 151 | | |
| 152 | 152 | } |
| 153 | 153 | |
| 154 | 154 | INLINE void lh5801_lin(lh5801_state *cpustate, PAIR *reg) |
| 155 | 155 | { |
| 156 | 156 | // or z flag depends on reg |
| 157 | cpustate->a= | |
| 157 | cpustate->a= | |
| 158 | 158 | cpustate->t&=~Z; |
| 159 | 159 | if (!cpustate->a) cpustate->t|=Z; |
| 160 | 160 | } |
| 161 | 161 | |
| 162 | 162 | INLINE void lh5801_sin(lh5801_state *cpustate, PAIR *reg) |
| 163 | 163 | { |
| 164 | | |
| 164 | | |
| 165 | 165 | } |
| 166 | 166 | |
| 167 | 167 | INLINE void lh5801_dec(lh5801_state *cpustate, UINT8 *adr) |
| r8806 | r8807 | |
| 176 | 176 | |
| 177 | 177 | INLINE void lh5801_pop(lh5801_state *cpustate) |
| 178 | 178 | { |
| 179 | cpustate->a= | |
| 179 | cpustate->a= | |
| 180 | 180 | cpustate->t&=~Z; |
| 181 | 181 | if (!cpustate->a) cpustate->t|=Z; |
| 182 | 182 | } |
| 183 | 183 | |
| 184 | 184 | INLINE void lh5801_pop_word(lh5801_state *cpustate, PAIR *reg) |
| 185 | 185 | { |
| 186 | reg->b.h=memory_read_byte(cpustate->program,++S); | |
| 187 | reg->b.l=memory_read_byte(cpustate->program,++S); | |
| 186 | reg->b.h=cpustate->program->read_byte(++S); | |
| 187 | reg->b.l=cpustate->program->read_byte(++S); | |
| 188 | 188 | // z flag? |
| 189 | 189 | } |
| 190 | 190 | |
| 191 | 191 | INLINE void lh5801_rtn(lh5801_state *cpustate) |
| 192 | 192 | { |
| 193 | P=memory_read_byte(cpustate->program,++S)<<8; | |
| 194 | P|=memory_read_byte(cpustate->program,++S); | |
| 193 | P=cpustate->program->read_byte(++S)<<8; | |
| 194 | P|=cpustate->program->read_byte(++S); | |
| 195 | 195 | } |
| 196 | 196 | |
| 197 | 197 | INLINE void lh5801_rti(lh5801_state *cpustate) |
| 198 | 198 | { |
| 199 | P=memory_read_byte(cpustate->program,++S)<<8; | |
| 200 | P|=memory_read_byte(cpustate->program,++S); | |
| 201 | cpustate->t=memory_read_byte(cpustate->program,++S); | |
| 199 | P=cpustate->program->read_byte(++S)<<8; | |
| 200 | P|=cpustate->program->read_byte(++S); | |
| 201 | cpustate->t=cpustate->program->read_byte(++S); | |
| 202 | 202 | } |
| 203 | 203 | |
| 204 | 204 | INLINE void lh5801_push(lh5801_state *cpustate, UINT8 data) |
| 205 | 205 | { |
| 206 | | |
| 206 | | |
| 207 | 207 | } |
| 208 | 208 | |
| 209 | 209 | INLINE void lh5801_push_word(lh5801_state *cpustate, UINT16 data) |
| 210 | 210 | { |
| 211 | memory_write_byte(cpustate->program,S--, data&0xff); | |
| 212 | memory_write_byte(cpustate->program,S--, data>>8); | |
| 211 | cpustate->program->write_byte(S--, data&0xff); | |
| 212 | cpustate->program->write_byte(S--, data>>8); | |
| 213 | 213 | } |
| 214 | 214 | |
| 215 | 215 | INLINE void lh5801_jmp(lh5801_state *cpustate, UINT16 adr) |
| r8806 | r8807 | |
| 256 | 256 | { |
| 257 | 257 | if (doit) { |
| 258 | 258 | lh5801_push_word(cpustate,P); |
| 259 | P=memory_read_byte(cpustate->program,0xff00+nr)<<8; | |
| 260 | P|=memory_read_byte(cpustate->program,0xff00+nr+1); | |
| 259 | P=cpustate->program->read_byte(0xff00+nr)<<8; | |
| 260 | P|=cpustate->program->read_byte(0xff00+nr+1); | |
| 261 | 261 | cpustate->icount-=21-8; |
| 262 | 262 | } |
| 263 | 263 | cpustate->t&=~Z; // after the jump!? |
| r8806 | r8807 | |
| 272 | 272 | |
| 273 | 273 | INLINE void lh5801_drl(lh5801_state *cpustate, int adr) |
| 274 | 274 | { |
| 275 | UINT16 t=cpustate->a|( | |
| 275 | UINT16 t=cpustate->a|( | |
| 276 | 276 | |
| 277 | 277 | cpustate->a=t>>8; |
| 278 | | |
| 278 | | |
| 279 | 279 | } |
| 280 | 280 | |
| 281 | 281 | INLINE void lh5801_drr(lh5801_state *cpustate, int adr) |
| 282 | 282 | { |
| 283 | UINT16 t= | |
| 283 | UINT16 t= | |
| 284 | 284 | |
| 285 | 285 | cpustate->a=t; |
| 286 | | |
| 286 | | |
| 287 | 287 | } |
| 288 | 288 | |
| 289 | 289 | INLINE void lh5801_rol(lh5801_state *cpustate) |
| r8806 | r8807 | |
| 351 | 351 | |
| 352 | 352 | oper=memory_decrypted_read_byte(cpustate->program,P++); |
| 353 | 353 | switch (oper) { |
| 354 | case 0x01: lh5801_sbc(cpustate,memory_read_byte(cpustate->program,0x10000|X)); cpustate->icount-=11;break; | |
| 355 | case 0x03: lh5801_adc(cpustate,memory_read_byte(cpustate->program,0x10000|X)); cpustate->icount-=11;break; | |
| 356 | case 0x05: lh5801_lda(cpustate,memory_read_byte(cpustate->program,0x10000|X)); cpustate->icount-=10;break; | |
| 357 | case 0x07: lh5801_cpa(cpustate,cpustate->a, memory_read_byte(cpustate->program,0x10000|X)); cpustate->icount-=11;break; | |
| 354 | case 0x01: lh5801_sbc(cpustate,cpustate->program->read_byte(0x10000|X)); cpustate->icount-=11;break; | |
| 355 | case 0x03: lh5801_adc(cpustate,cpustate->program->read_byte(0x10000|X)); cpustate->icount-=11;break; | |
| 356 | case 0x05: lh5801_lda(cpustate,cpustate->program->read_byte(0x10000|X)); cpustate->icount-=10;break; | |
| 357 | case 0x07: lh5801_cpa(cpustate,cpustate->a, cpustate->program->read_byte(0x10000|X)); cpustate->icount-=11;break; | |
| 358 | 358 | case 0x08: X=X;cpustate->icount-=11;break; //!!! |
| 359 | case 0x09: lh5801_and(cpustate, | |
| 359 | case 0x09: lh5801_and(cpustate, | |
| 360 | 360 | case 0x0a: lh5801_pop_word(cpustate,&cpustate->x); cpustate->icount-=15;break; |
| 361 | case 0x0b: lh5801_ora(cpustate,memory_read_byte(cpustate->program,0x10000|X)); cpustate->icount-=11;break; | |
| 362 | case 0x0c: lh5801_dcs(cpustate,memory_read_byte(cpustate->program,0x10000|X)); cpustate->icount-=17; break; | |
| 363 | case 0x0d: lh5801_eor(cpustate,memory_read_byte(cpustate->program,0x10000|X)); cpustate->icount-=11;break; | |
| 364 | case 0x0e: memory_write_byte(cpustate->program,0x10000|X,cpustate->a); cpustate->icount-=10;break; | |
| 365 | case 0x0f: lh5801_bit(cpustate,memory_read_byte(cpustate->program,0x10000|X),cpustate->a); cpustate->icount-=11;break; | |
| 366 | case 0x11: lh5801_sbc(cpustate,memory_read_byte(cpustate->program,0x10000|Y)); cpustate->icount-=11;break; | |
| 367 | case 0x13: lh5801_adc(cpustate,memory_read_byte(cpustate->program,0x10000|Y)); cpustate->icount-=11;break; | |
| 368 | case 0x15: lh5801_lda(cpustate,memory_read_byte(cpustate->program,0x10000|Y)); cpustate->icount-=10;break; | |
| 369 | case 0x17: lh5801_cpa(cpustate,cpustate->a, memory_read_byte(cpustate->program,0x10000|Y)); cpustate->icount-=11;break; | |
| 361 | case 0x0b: lh5801_ora(cpustate,cpustate->program->read_byte(0x10000|X)); cpustate->icount-=11;break; | |
| 362 | case 0x0c: lh5801_dcs(cpustate,cpustate->program->read_byte(0x10000|X)); cpustate->icount-=17; break; | |
| 363 | case 0x0d: lh5801_eor(cpustate,cpustate->program->read_byte(0x10000|X)); cpustate->icount-=11;break; | |
| 364 | case 0x0e: cpustate->program->write_byte(0x10000|X,cpustate->a); cpustate->icount-=10;break; | |
| 365 | case 0x0f: lh5801_bit(cpustate,cpustate->program->read_byte(0x10000|X),cpustate->a); cpustate->icount-=11;break; | |
| 366 | case 0x11: lh5801_sbc(cpustate,cpustate->program->read_byte(0x10000|Y)); cpustate->icount-=11;break; | |
| 367 | case 0x13: lh5801_adc(cpustate,cpustate->program->read_byte(0x10000|Y)); cpustate->icount-=11;break; | |
| 368 | case 0x15: lh5801_lda(cpustate,cpustate->program->read_byte(0x10000|Y)); cpustate->icount-=10;break; | |
| 369 | case 0x17: lh5801_cpa(cpustate,cpustate->a, cpustate->program->read_byte(0x10000|Y)); cpustate->icount-=11;break; | |
| 370 | 370 | case 0x18: X=Y;cpustate->icount-=11;break; |
| 371 | case 0x19: lh5801_and(cpustate, | |
| 371 | case 0x19: lh5801_and(cpustate, | |
| 372 | 372 | case 0x1a: lh5801_pop_word(cpustate,&cpustate->y); cpustate->icount-=15;break; |
| 373 | case 0x1b: lh5801_ora(cpustate,memory_read_byte(cpustate->program,0x10000|Y)); cpustate->icount-=11;break; | |
| 374 | case 0x1c: lh5801_dcs(cpustate,memory_read_byte(cpustate->program,0x10000|Y)); cpustate->icount-=17; break; | |
| 375 | case 0x1d: lh5801_eor(cpustate,memory_read_byte(cpustate->program,0x10000|Y)); cpustate->icount-=11;break; | |
| 376 | case 0x1e: memory_write_byte(cpustate->program,0x10000|Y,cpustate->a); cpustate->icount-=10;break; | |
| 377 | case 0x1f: lh5801_bit(cpustate,memory_read_byte(cpustate->program,0x10000|Y),cpustate->a); cpustate->icount-=11;break; | |
| 378 | case 0x21: lh5801_sbc(cpustate,memory_read_byte(cpustate->program,0x10000|U)); cpustate->icount-=11;break; | |
| 379 | case 0x23: lh5801_adc(cpustate,memory_read_byte(cpustate->program,0x10000|U)); cpustate->icount-=11;break; | |
| 380 | case 0x25: lh5801_lda(cpustate,memory_read_byte(cpustate->program,0x10000|U)); cpustate->icount-=10;break; | |
| 381 | case 0x27: lh5801_cpa(cpustate,cpustate->a, memory_read_byte(cpustate->program,0x10000|U)); cpustate->icount-=11;break; | |
| 373 | case 0x1b: lh5801_ora(cpustate,cpustate->program->read_byte(0x10000|Y)); cpustate->icount-=11;break; | |
| 374 | case 0x1c: lh5801_dcs(cpustate,cpustate->program->read_byte(0x10000|Y)); cpustate->icount-=17; break; | |
| 375 | case 0x1d: lh5801_eor(cpustate,cpustate->program->read_byte(0x10000|Y)); cpustate->icount-=11;break; | |
| 376 | case 0x1e: cpustate->program->write_byte(0x10000|Y,cpustate->a); cpustate->icount-=10;break; | |
| 377 | case 0x1f: lh5801_bit(cpustate,cpustate->program->read_byte(0x10000|Y),cpustate->a); cpustate->icount-=11;break; | |
| 378 | case 0x21: lh5801_sbc(cpustate,cpustate->program->read_byte(0x10000|U)); cpustate->icount-=11;break; | |
| 379 | case 0x23: lh5801_adc(cpustate,cpustate->program->read_byte(0x10000|U)); cpustate->icount-=11;break; | |
| 380 | case 0x25: lh5801_lda(cpustate,cpustate->program->read_byte(0x10000|U)); cpustate->icount-=10;break; | |
| 381 | case 0x27: lh5801_cpa(cpustate,cpustate->a, cpustate->program->read_byte(0x10000|U)); cpustate->icount-=11;break; | |
| 382 | 382 | case 0x28: X=U;cpustate->icount-=11;break; |
| 383 | case 0x29: lh5801_and(cpustate, | |
| 383 | case 0x29: lh5801_and(cpustate, | |
| 384 | 384 | case 0x2a: lh5801_pop_word(cpustate,&cpustate->u); cpustate->icount-=15;break; |
| 385 | case 0x2b: lh5801_ora(cpustate,memory_read_byte(cpustate->program,0x10000|U)); cpustate->icount-=11;break; | |
| 386 | case 0x2c: lh5801_dcs(cpustate,memory_read_byte(cpustate->program,0x10000|U)); cpustate->icount-=17; break; | |
| 387 | case 0x2d: lh5801_eor(cpustate,memory_read_byte(cpustate->program,0x10000|U)); cpustate->icount-=11;break; | |
| 388 | case 0x2e: memory_write_byte(cpustate->program,0x10000|U,cpustate->a); cpustate->icount-=10;break; | |
| 389 | case 0x2f: lh5801_bit(cpustate,memory_read_byte(cpustate->program,0x10000|U),cpustate->a); cpustate->icount-=11;break; | |
| 385 | case 0x2b: lh5801_ora(cpustate,cpustate->program->read_byte(0x10000|U)); cpustate->icount-=11;break; | |
| 386 | case 0x2c: lh5801_dcs(cpustate,cpustate->program->read_byte(0x10000|U)); cpustate->icount-=17; break; | |
| 387 | case 0x2d: lh5801_eor(cpustate,cpustate->program->read_byte(0x10000|U)); cpustate->icount-=11;break; | |
| 388 | case 0x2e: cpustate->program->write_byte(0x10000|U,cpustate->a); cpustate->icount-=10;break; | |
| 389 | case 0x2f: lh5801_bit(cpustate,cpustate->program->read_byte(0x10000|U),cpustate->a); cpustate->icount-=11;break; | |
| 390 | 390 | case 0x40: lh5801_inc(cpustate,&XH);cpustate->icount-=9;break; |
| 391 | 391 | case 0x42: lh5801_dec(cpustate,&XH);cpustate->icount-=9;break; |
| 392 | 392 | case 0x48: X=S;cpustate->icount-=11;break; |
| r8806 | r8807 | |
| 394 | 394 | case 0x4a: X=X;cpustate->icount-=11;break; //!!! |
| 395 | 395 | case 0x4b: lh5801_ora_mem(cpustate,0x10000|X, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=17;break; |
| 396 | 396 | case 0x4c: cpustate->bf=0;/*off !*/ cpustate->icount-=8;break; |
| 397 | case 0x4d: lh5801_bit(cpustate, | |
| 397 | case 0x4d: lh5801_bit(cpustate, | |
| 398 | 398 | case 0x4e: S=X;cpustate->icount-=11;break; |
| 399 | 399 | case 0x4f: lh5801_add_mem(cpustate,0x10000|X, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=17;break; |
| 400 | 400 | case 0x50: lh5801_inc(cpustate,&YH);cpustate->icount-=9;break; |
| r8806 | r8807 | |
| 403 | 403 | case 0x59: lh5801_and_mem(cpustate,0x10000|Y, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=17;break; |
| 404 | 404 | case 0x5a: Y=X;cpustate->icount-=11;break; |
| 405 | 405 | case 0x5b: lh5801_ora_mem(cpustate,0x10000|Y, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=17;break; |
| 406 | case 0x5d: lh5801_bit(cpustate, | |
| 406 | case 0x5d: lh5801_bit(cpustate, | |
| 407 | 407 | case 0x5e: lh5801_jmp(cpustate,X);cpustate->icount-=11;break; // P=X |
| 408 | 408 | case 0x5f: lh5801_add_mem(cpustate,0x10000|Y, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=17;break; |
| 409 | 409 | case 0x60: lh5801_inc(cpustate,&UH);cpustate->icount-=9;break; |
| r8806 | r8807 | |
| 411 | 411 | case 0x69: lh5801_and_mem(cpustate,0x10000|U, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=17;break; |
| 412 | 412 | case 0x6a: U=X;cpustate->icount-=11;break; |
| 413 | 413 | case 0x6b: lh5801_ora_mem(cpustate,0x10000|U, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=17;break; |
| 414 | case 0x6d: lh5801_bit(cpustate, | |
| 414 | case 0x6d: lh5801_bit(cpustate, | |
| 415 | 415 | case 0x6f: lh5801_add_mem(cpustate,0x10000|U, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=17;break; |
| 416 | 416 | case 0x81: cpustate->t|=IE; /*sie !*/cpustate->icount-=8;break; |
| 417 | 417 | case 0x88: lh5801_push_word(cpustate,X); cpustate->icount-=14;break; |
| 418 | 418 | case 0x8a: lh5801_pop(cpustate); cpustate->icount-=12; break; |
| 419 | case 0x8c: lh5801_dca(cpustate, | |
| 419 | case 0x8c: lh5801_dca(cpustate, | |
| 420 | 420 | case 0x8e: /*cdv clears internal devider*/cpustate->icount-=8;break; |
| 421 | 421 | case 0x98: lh5801_push_word(cpustate,Y); cpustate->icount-=14;break; |
| 422 | case 0x9c: lh5801_dca(cpustate,memory_read_byte(cpustate->program,0x10000|Y)); cpustate->icount-=19; break; | |
| 423 | case 0xa1: lh5801_sbc(cpustate,memory_read_byte(cpustate->program,0x10000|lh5801_readop_word(cpustate))); cpustate->icount-=17;break; | |
| 424 | case 0xa3: lh5801_adc(cpustate,memory_read_byte(cpustate->program,0x10000|lh5801_readop_word(cpustate))); cpustate->icount-=17;break; | |
| 425 | case 0xa5: lh5801_lda(cpustate,memory_read_byte(cpustate->program,0x10000|lh5801_readop_word(cpustate))); cpustate->icount-=16;break; | |
| 426 | case 0xa7: lh5801_cpa(cpustate,cpustate->a, memory_read_byte(cpustate->program,0x10000|lh5801_readop_word(cpustate))); cpustate->icount-=17;break; | |
| 422 | case 0x9c: lh5801_dca(cpustate,cpustate->program->read_byte(0x10000|Y)); cpustate->icount-=19; break; | |
| 423 | case 0xa1: lh5801_sbc(cpustate,cpustate->program->read_byte(0x10000|lh5801_readop_word(cpustate))); cpustate->icount-=17;break; | |
| 424 | case 0xa3: lh5801_adc(cpustate,cpustate->program->read_byte(0x10000|lh5801_readop_word(cpustate))); cpustate->icount-=17;break; | |
| 425 | case 0xa5: lh5801_lda(cpustate,cpustate->program->read_byte(0x10000|lh5801_readop_word(cpustate))); cpustate->icount-=16;break; | |
| 426 | case 0xa7: lh5801_cpa(cpustate,cpustate->a, cpustate->program->read_byte(0x10000|lh5801_readop_word(cpustate))); cpustate->icount-=17;break; | |
| 427 | 427 | case 0xa8: lh5801_push_word(cpustate,U); cpustate->icount-=14;break; |
| 428 | case 0xa9: lh5801_and(cpustate, | |
| 428 | case 0xa9: lh5801_and(cpustate, | |
| 429 | 429 | case 0xaa: lh5801_lda(cpustate,cpustate->t); cpustate->icount-=9;break; |
| 430 | case 0xab: lh5801_ora(cpustate,memory_read_byte(cpustate->program,0x10000|lh5801_readop_word(cpustate))); cpustate->icount-=17;break; | |
| 431 | case 0xac: lh5801_dca(cpustate,memory_read_byte(cpustate->program,0x10000|U)); cpustate->icount-=19; break; | |
| 432 | case 0xad: lh5801_eor(cpustate,memory_read_byte(cpustate->program,0x10000|lh5801_readop_word(cpustate))); cpustate->icount-=17;break; | |
| 433 | case 0xae: memory_write_byte(cpustate->program,0x10000|lh5801_readop_word(cpustate),cpustate->a); cpustate->icount-=16;break; | |
| 434 | case 0xaf: lh5801_bit(cpustate,memory_read_byte(cpustate->program,0x10000|lh5801_readop_word(cpustate)),cpustate->a); cpustate->icount-=17;break; | |
| 430 | case 0xab: lh5801_ora(cpustate,cpustate->program->read_byte(0x10000|lh5801_readop_word(cpustate))); cpustate->icount-=17;break; | |
| 431 | case 0xac: lh5801_dca(cpustate,cpustate->program->read_byte(0x10000|U)); cpustate->icount-=19; break; | |
| 432 | case 0xad: lh5801_eor(cpustate,cpustate->program->read_byte(0x10000|lh5801_readop_word(cpustate))); cpustate->icount-=17;break; | |
| 433 | case 0xae: cpustate->program->write_byte(0x10000|lh5801_readop_word(cpustate),cpustate->a); cpustate->icount-=16;break; | |
| 434 | case 0xaf: lh5801_bit(cpustate,cpustate->program->read_byte(0x10000|lh5801_readop_word(cpustate)),cpustate->a); cpustate->icount-=17;break; | |
| 435 | 435 | case 0xb1: /*hlt*/cpustate->icount-=8;break; |
| 436 | 436 | case 0xba: lh5801_ita(cpustate);cpustate->icount-=9;break; |
| 437 | 437 | case 0xbe: cpustate->t&=~IE; /*rie !*/cpustate->icount-=8;break; |
| r8806 | r8807 | |
| 456 | 456 | break; |
| 457 | 457 | case 0xec: cpustate->t=cpustate->a; cpustate->icount-=9;break; |
| 458 | 458 | case 0xed: |
| 459 | adr=lh5801_readop_word(cpustate)|0x10000;lh5801_bit(cpustate, | |
| 459 | adr=lh5801_readop_word(cpustate)|0x10000;lh5801_bit(cpustate, | |
| 460 | 460 | cpustate->icount-=20;break; |
| 461 | 461 | case 0xef: |
| 462 | 462 | adr=lh5801_readop_word(cpustate)|0x10000; |
| r8806 | r8807 | |
| 476 | 476 | oper=memory_decrypted_read_byte(cpustate->program,P++); |
| 477 | 477 | switch (oper) { |
| 478 | 478 | case 0x00: lh5801_sbc(cpustate,XL); cpustate->icount-=6;break; |
| 479 | case 0x01: lh5801_sbc(cpustate, | |
| 479 | case 0x01: lh5801_sbc(cpustate, | |
| 480 | 480 | case 0x02: lh5801_adc(cpustate,XL); cpustate->icount-=6;break; |
| 481 | case 0x03: lh5801_adc(cpustate, | |
| 481 | case 0x03: lh5801_adc(cpustate, | |
| 482 | 482 | case 0x04: lh5801_lda(cpustate,XL); cpustate->icount-=5;break; |
| 483 | case 0x05: lh5801_lda(cpustate, | |
| 483 | case 0x05: lh5801_lda(cpustate, | |
| 484 | 484 | case 0x06: lh5801_cpa(cpustate,cpustate->a, XL); cpustate->icount-=6;break; |
| 485 | case 0x07: lh5801_cpa(cpustate,cpustate->a, | |
| 485 | case 0x07: lh5801_cpa(cpustate,cpustate->a, | |
| 486 | 486 | case 0x08: XH=cpustate->a; cpustate->icount-=5; break; |
| 487 | case 0x09: lh5801_and(cpustate, | |
| 487 | case 0x09: lh5801_and(cpustate, | |
| 488 | 488 | case 0x0a: XL=cpustate->a; cpustate->icount-=5; break; |
| 489 | case 0x0b: lh5801_ora(cpustate,memory_read_byte(cpustate->program,X)); cpustate->icount-=7;break; | |
| 490 | case 0x0c: lh5801_dcs(cpustate,memory_read_byte(cpustate->program,X)); cpustate->icount-=13; break; | |
| 491 | case 0x0d: lh5801_eor(cpustate,memory_read_byte(cpustate->program,X)); cpustate->icount-=7;break; | |
| 492 | case 0x0e: memory_write_byte(cpustate->program,X,cpustate->a); cpustate->icount-=6;break; | |
| 493 | case 0x0f: lh5801_bit(cpustate,memory_read_byte(cpustate->program,X),cpustate->a); cpustate->icount-=7;break; | |
| 489 | case 0x0b: lh5801_ora(cpustate,cpustate->program->read_byte(X)); cpustate->icount-=7;break; | |
| 490 | case 0x0c: lh5801_dcs(cpustate,cpustate->program->read_byte(X)); cpustate->icount-=13; break; | |
| 491 | case 0x0d: lh5801_eor(cpustate,cpustate->program->read_byte(X)); cpustate->icount-=7;break; | |
| 492 | case 0x0e: cpustate->program->write_byte(X,cpustate->a); cpustate->icount-=6;break; | |
| 493 | case 0x0f: lh5801_bit(cpustate,cpustate->program->read_byte(X),cpustate->a); cpustate->icount-=7;break; | |
| 494 | 494 | case 0x10: lh5801_sbc(cpustate,YL); cpustate->icount-=6;break; |
| 495 | case 0x11: lh5801_sbc(cpustate, | |
| 495 | case 0x11: lh5801_sbc(cpustate, | |
| 496 | 496 | case 0x12: lh5801_adc(cpustate,YL); cpustate->icount-=6;break; |
| 497 | case 0x13: lh5801_adc(cpustate, | |
| 497 | case 0x13: lh5801_adc(cpustate, | |
| 498 | 498 | case 0x14: lh5801_lda(cpustate,YL); cpustate->icount-=5;break; |
| 499 | case 0x15: lh5801_lda(cpustate, | |
| 499 | case 0x15: lh5801_lda(cpustate, | |
| 500 | 500 | case 0x16: lh5801_cpa(cpustate,cpustate->a, YL); cpustate->icount-=6;break; |
| 501 | case 0x17: lh5801_cpa(cpustate,cpustate->a, | |
| 501 | case 0x17: lh5801_cpa(cpustate,cpustate->a, | |
| 502 | 502 | case 0x18: YH=cpustate->a; cpustate->icount-=5; break; |
| 503 | case 0x19: lh5801_and(cpustate, | |
| 503 | case 0x19: lh5801_and(cpustate, | |
| 504 | 504 | case 0x1a: YL=cpustate->a; cpustate->icount-=5; break; |
| 505 | case 0x1b: lh5801_ora(cpustate,memory_read_byte(cpustate->program,Y)); cpustate->icount-=7;break; | |
| 506 | case 0x1c: lh5801_dcs(cpustate,memory_read_byte(cpustate->program,Y)); cpustate->icount-=13; break; | |
| 507 | case 0x1d: lh5801_eor(cpustate,memory_read_byte(cpustate->program,Y)); cpustate->icount-=7;break; | |
| 508 | case 0x1e: memory_write_byte(cpustate->program,Y,cpustate->a); cpustate->icount-=6;break; | |
| 509 | case 0x1f: lh5801_bit(cpustate,memory_read_byte(cpustate->program,Y),cpustate->a); cpustate->icount-=7;break; | |
| 505 | case 0x1b: lh5801_ora(cpustate,cpustate->program->read_byte(Y)); cpustate->icount-=7;break; | |
| 506 | case 0x1c: lh5801_dcs(cpustate,cpustate->program->read_byte(Y)); cpustate->icount-=13; break; | |
| 507 | case 0x1d: lh5801_eor(cpustate,cpustate->program->read_byte(Y)); cpustate->icount-=7;break; | |
| 508 | case 0x1e: cpustate->program->write_byte(Y,cpustate->a); cpustate->icount-=6;break; | |
| 509 | case 0x1f: lh5801_bit(cpustate,cpustate->program->read_byte(Y),cpustate->a); cpustate->icount-=7;break; | |
| 510 | 510 | case 0x20: lh5801_sbc(cpustate,UL); cpustate->icount-=6;break; |
| 511 | case 0x21: lh5801_sbc(cpustate, | |
| 511 | case 0x21: lh5801_sbc(cpustate, | |
| 512 | 512 | case 0x22: lh5801_adc(cpustate,UL); cpustate->icount-=6;break; |
| 513 | case 0x23: lh5801_adc(cpustate, | |
| 513 | case 0x23: lh5801_adc(cpustate, | |
| 514 | 514 | case 0x24: lh5801_lda(cpustate,UL); cpustate->icount-=5;break; |
| 515 | case 0x25: lh5801_lda(cpustate, | |
| 515 | case 0x25: lh5801_lda(cpustate, | |
| 516 | 516 | case 0x26: lh5801_cpa(cpustate,cpustate->a, UL); cpustate->icount-=6;break; |
| 517 | case 0x27: lh5801_cpa(cpustate,cpustate->a, | |
| 517 | case 0x27: lh5801_cpa(cpustate,cpustate->a, | |
| 518 | 518 | case 0x28: UH=cpustate->a; cpustate->icount-=5; break; |
| 519 | case 0x29: lh5801_and(cpustate, | |
| 519 | case 0x29: lh5801_and(cpustate, | |
| 520 | 520 | case 0x2a: UL=cpustate->a; cpustate->icount-=5; break; |
| 521 | case 0x2b: lh5801_ora(cpustate,memory_read_byte(cpustate->program,U)); cpustate->icount-=7;break; | |
| 522 | case 0x2c: lh5801_dcs(cpustate,memory_read_byte(cpustate->program,U)); cpustate->icount-=13; break; | |
| 523 | case 0x2d: lh5801_eor(cpustate,memory_read_byte(cpustate->program,U)); cpustate->icount-=7;break; | |
| 524 | case 0x2e: memory_write_byte(cpustate->program,U,cpustate->a); cpustate->icount-=6;break; | |
| 525 | case 0x2f: lh5801_bit(cpustate,memory_read_byte(cpustate->program,U),cpustate->a); cpustate->icount-=7;break; | |
| 521 | case 0x2b: lh5801_ora(cpustate,cpustate->program->read_byte(U)); cpustate->icount-=7;break; | |
| 522 | case 0x2c: lh5801_dcs(cpustate,cpustate->program->read_byte(U)); cpustate->icount-=13; break; | |
| 523 | case 0x2d: lh5801_eor(cpustate,cpustate->program->read_byte(U)); cpustate->icount-=7;break; | |
| 524 | case 0x2e: cpustate->program->write_byte(U,cpustate->a); cpustate->icount-=6;break; | |
| 525 | case 0x2f: lh5801_bit(cpustate,cpustate->program->read_byte(U),cpustate->a); cpustate->icount-=7;break; | |
| 526 | 526 | case 0x38: /*nop*/cpustate->icount-=5;break; |
| 527 | 527 | case 0x40: lh5801_inc(cpustate,&XL);cpustate->icount-=5;break; |
| 528 | 528 | case 0x41: lh5801_sin(cpustate,&cpustate->x); cpustate->icount-=6;break; |
| r8806 | r8807 | |
| 537 | 537 | case 0x4a: XL=memory_decrypted_read_byte(cpustate->program,P++);cpustate->icount-=6;break; |
| 538 | 538 | case 0x4b: lh5801_ora_mem(cpustate,X, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=13;break; |
| 539 | 539 | case 0x4c: lh5801_cpa(cpustate,XH, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=7;break; |
| 540 | case 0x4d: lh5801_bit(cpustate, | |
| 540 | case 0x4d: lh5801_bit(cpustate, | |
| 541 | 541 | case 0x4e: lh5801_cpa(cpustate,XL, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=7;break; |
| 542 | 542 | case 0x4f: lh5801_add_mem(cpustate,X, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=13;break; |
| 543 | 543 | case 0x50: lh5801_inc(cpustate,&YL);cpustate->icount-=5;break; |
| r8806 | r8807 | |
| 553 | 553 | case 0x5a: YL=memory_decrypted_read_byte(cpustate->program,P++);cpustate->icount-=6;break; |
| 554 | 554 | case 0x5b: lh5801_ora_mem(cpustate,Y, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=13;break; |
| 555 | 555 | case 0x5c: lh5801_cpa(cpustate,YH, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=7;break; |
| 556 | case 0x5d: lh5801_bit(cpustate, | |
| 556 | case 0x5d: lh5801_bit(cpustate, | |
| 557 | 557 | case 0x5e: lh5801_cpa(cpustate,YL, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=7;break; |
| 558 | 558 | case 0x5f: lh5801_add_mem(cpustate,Y, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=13;break; |
| 559 | 559 | case 0x60: lh5801_inc(cpustate,&UL);cpustate->icount-=5;break; |
| r8806 | r8807 | |
| 569 | 569 | case 0x6a: UL=memory_decrypted_read_byte(cpustate->program,P++);cpustate->icount-=6;break; |
| 570 | 570 | case 0x6b: lh5801_ora_mem(cpustate,U, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=13;break; |
| 571 | 571 | case 0x6c: lh5801_cpa(cpustate,UH, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=7;break; |
| 572 | case 0x6d: lh5801_bit(cpustate, | |
| 572 | case 0x6d: lh5801_bit(cpustate, | |
| 573 | 573 | case 0x6e: lh5801_cpa(cpustate,UL, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=7;break; |
| 574 | 574 | case 0x6f: lh5801_add_mem(cpustate,U, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=13;break; |
| 575 | 575 | case 0x80: lh5801_sbc(cpustate,XH); cpustate->icount-=6;break; |
| r8806 | r8807 | |
| 584 | 584 | case 0x89: lh5801_branch_plus(cpustate,!(cpustate->t&Z)); cpustate->icount-=8; break; |
| 585 | 585 | case 0x8a: lh5801_rti(cpustate); cpustate->icount-=14; break; |
| 586 | 586 | case 0x8b: lh5801_branch_plus(cpustate,cpustate->t&Z); cpustate->icount-=8; break; |
| 587 | case 0x8c: lh5801_dca(cpustate, | |
| 587 | case 0x8c: lh5801_dca(cpustate, | |
| 588 | 588 | case 0x8d: lh5801_branch_plus(cpustate,!(cpustate->t&V)); cpustate->icount-=8; break; |
| 589 | 589 | case 0x8e: lh5801_branch_plus(cpustate,1); cpustate->icount-=5; break; |
| 590 | 590 | case 0x8f: lh5801_branch_plus(cpustate,cpustate->t&V); cpustate->icount-=8; break; |
| r8806 | r8807 | |
| 599 | 599 | case 0x99: lh5801_branch_minus(cpustate,!(cpustate->t&Z)); cpustate->icount-=8; break; |
| 600 | 600 | case 0x9a: lh5801_rtn(cpustate); cpustate->icount-=11; break; |
| 601 | 601 | case 0x9b: lh5801_branch_minus(cpustate,cpustate->t&Z); cpustate->icount-=8; break; |
| 602 | case 0x9c: lh5801_dca(cpustate, | |
| 602 | case 0x9c: lh5801_dca(cpustate, | |
| 603 | 603 | case 0x9d: lh5801_branch_minus(cpustate,!(cpustate->t&V)); cpustate->icount-=8; break; |
| 604 | 604 | case 0x9e: lh5801_branch_minus(cpustate,1); cpustate->icount-=6; break; |
| 605 | 605 | case 0x9f: lh5801_branch_minus(cpustate,cpustate->t&V); cpustate->icount-=8; break; |
| 606 | 606 | case 0xa0: lh5801_sbc(cpustate,UH); cpustate->icount-=6;break; |
| 607 | 607 | case 0xa2: lh5801_adc(cpustate,UH); cpustate->icount-=6;break; |
| 608 | case 0xa1: lh5801_sbc(cpustate,memory_read_byte(cpustate->program,lh5801_readop_word(cpustate))); cpustate->icount-=13;break; | |
| 609 | case 0xa3: lh5801_adc(cpustate,memory_read_byte(cpustate->program,lh5801_readop_word(cpustate))); cpustate->icount-=13;break; | |
| 608 | case 0xa1: lh5801_sbc(cpustate,cpustate->program->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=13;break; | |
| 609 | case 0xa3: lh5801_adc(cpustate,cpustate->program->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=13;break; | |
| 610 | 610 | case 0xa4: lh5801_lda(cpustate,UH); cpustate->icount-=5;break; |
| 611 | case 0xa5: lh5801_lda(cpustate, | |
| 611 | case 0xa5: lh5801_lda(cpustate, | |
| 612 | 612 | case 0xa6: lh5801_cpa(cpustate,cpustate->a, UH); cpustate->icount-=6;break; |
| 613 | case 0xa7: lh5801_cpa(cpustate,cpustate->a, | |
| 613 | case 0xa7: lh5801_cpa(cpustate,cpustate->a, | |
| 614 | 614 | case 0xa8: cpustate->pv=1;/*spv!*/ cpustate->icount-=4; break; |
| 615 | case 0xa9: lh5801_and(cpustate, | |
| 615 | case 0xa9: lh5801_and(cpustate, | |
| 616 | 616 | case 0xaa: S=lh5801_readop_word(cpustate);cpustate->icount-=6;break; |
| 617 | case 0xab: lh5801_ora(cpustate,memory_read_byte(cpustate->program,lh5801_readop_word(cpustate))); cpustate->icount-=13;break; | |
| 618 | case 0xac: lh5801_dca(cpustate,memory_read_byte(cpustate->program,U)); cpustate->icount-=15; break; | |
| 619 | case 0xad: lh5801_eor(cpustate,memory_read_byte(cpustate->program,lh5801_readop_word(cpustate))); cpustate->icount-=13;break; | |
| 620 | case 0xae: memory_write_byte(cpustate->program,lh5801_readop_word(cpustate),cpustate->a); cpustate->icount-=12;break; | |
| 621 | case 0xaf: lh5801_bit(cpustate,memory_read_byte(cpustate->program,lh5801_readop_word(cpustate)),cpustate->a); cpustate->icount-=13;break; | |
| 617 | case 0xab: lh5801_ora(cpustate,cpustate->program->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=13;break; | |
| 618 | case 0xac: lh5801_dca(cpustate,cpustate->program->read_byte(U)); cpustate->icount-=15; break; | |
| 619 | case 0xad: lh5801_eor(cpustate,cpustate->program->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=13;break; | |
| 620 | case 0xae: cpustate->program->write_byte(lh5801_readop_word(cpustate),cpustate->a); cpustate->icount-=12;break; | |
| 621 | case 0xaf: lh5801_bit(cpustate,cpustate->program->read_byte(lh5801_readop_word(cpustate)),cpustate->a); cpustate->icount-=13;break; | |
| 622 | 622 | case 0xb1: lh5801_sbc(cpustate,memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=7;break; |
| 623 | 623 | case 0xb3: lh5801_adc(cpustate,memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=7;break; |
| 624 | 624 | case 0xb5: lh5801_lda(cpustate,memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=6;break; |
| r8806 | r8807 | |
| 655 | 655 | adr=lh5801_readop_word(cpustate);lh5801_ora_mem(cpustate,adr, memory_decrypted_read_byte(cpustate->program,P++)); |
| 656 | 656 | cpustate->icount-=19;break; |
| 657 | 657 | case 0xed: |
| 658 | adr=lh5801_readop_word(cpustate);lh5801_bit(cpustate, | |
| 658 | adr=lh5801_readop_word(cpustate);lh5801_bit(cpustate, | |
| 659 | 659 | cpustate->icount-=16;break; |
| 660 | 660 | case 0xef: |
| 661 | 661 | adr=lh5801_readop_word(cpustate); |
| 662 | 662 | lh5801_add_mem(cpustate,adr, memory_decrypted_read_byte(cpustate->program,P++)); cpustate->icount-=19; |
| 663 | 663 | break; |
| 664 | 664 | case 0xf1: lh5801_aex(cpustate); cpustate->icount-=6; break; |
| 665 | case 0xf5: memory_write_byte(cpustate->program,Y++, memory_read_byte(cpustate->program,X++)); cpustate->icount-=7; break; //tin | |
| 666 | case 0xf7: lh5801_cpa(cpustate,cpustate->a, memory_read_byte(cpustate->program,X++));cpustate->icount-=7; break; //cin | |
| 665 | case 0xf5: cpustate->program->write_byte(Y++, cpustate->program->read_byte(X++)); cpustate->icount-=7; break; //tin | |
| 666 | case 0xf7: lh5801_cpa(cpustate,cpustate->a, cpustate->program->read_byte(X++));cpustate->icount-=7; break; //cin | |
| 667 | 667 | case 0xf9: cpustate->t&=~C;cpustate->icount-=4;break; |
| 668 | 668 | case 0xfb: cpustate->t|=C;cpustate->icount-=4;break; |
| 669 | 669 | case 0xfd: lh5801_instruction_fd(cpustate);break; |
| r8806 | r8807 | |
|---|---|---|
| 51 | 51 | { |
| 52 | 52 | const lh5801_cpu_core *config; |
| 53 | 53 | legacy_cpu_device *device; |
| 54 | | |
| 54 | | |
| 55 | 55 | |
| 56 | 56 | PAIR s, p, u, x, y; |
| 57 | 57 | int tm; //9 bit |
| r8806 | r8807 | |
| 112 | 112 | { |
| 113 | 113 | lh5801_state *cpustate = get_safe_token(device); |
| 114 | 114 | |
| 115 | P = ( | |
| 115 | P = ( | |
| 116 | 116 | |
| 117 | 117 | cpustate->idle=0; |
| 118 | 118 | } |
| r8806 | r8807 | |
|---|---|---|
| 105 | 105 | PAIR ea; /* effective address */ |
| 106 | 106 | |
| 107 | 107 | /* Memory spaces */ |
| 108 | | |
| 108 | | |
| 109 | 109 | |
| 110 | 110 | UINT8 int_state; /* SYNC and CWAI flags */ |
| 111 | 111 | UINT8 nmi_state; |
| r8806 | r8807 | |
| 172 | 172 | /****************************************************************************/ |
| 173 | 173 | /* Read a byte from given memory location */ |
| 174 | 174 | /****************************************************************************/ |
| 175 | #define RM(Addr) ((unsigned)m | |
| 175 | #define RM(Addr) ((unsigned)m | |
| 176 | 176 | |
| 177 | 177 | /****************************************************************************/ |
| 178 | 178 | /* Write a byte to given memory location */ |
| 179 | 179 | /****************************************************************************/ |
| 180 | #define WM(Addr,Value) (m | |
| 180 | #define WM(Addr,Value) (m | |
| 181 | 181 | |
| 182 | 182 | /****************************************************************************/ |
| 183 | 183 | /* Z80_RDOP() is identical to Z80_RDMEM() except it is used for reading */ |
| r8806 | r8807 | |
|---|---|---|
| 268 | 268 | UINT8 byte_size; /* 8 or 9 bit bytes */ |
| 269 | 269 | const UINT32 *decode_table; |
| 270 | 270 | const tms0980_config *config; |
| 271 | const address_space *program; | |
| 272 | const address_space *data; | |
| 271 | address_space *program; | |
| 272 | address_space *data; | |
| 273 | 273 | }; |
| 274 | 274 | |
| 275 | 275 | |
| r8806 | r8807 | |
| 814 | 814 | /* fetch: rom address 0 */ |
| 815 | 815 | /* execute: read ram, alu input, execute br/call, k input valid */ |
| 816 | 816 | tms0980_set_cki_bus( device ); |
| 817 | cpustate->ram_data = | |
| 817 | cpustate->ram_data = | |
| 818 | 818 | cpustate->status = 1; |
| 819 | 819 | cpustate->p = 0; |
| 820 | 820 | cpustate->n = 0; |
| r8806 | r8807 | |
| 909 | 909 | } |
| 910 | 910 | if ( cpustate->decode & M_STO ) |
| 911 | 911 | { |
| 912 | | |
| 912 | | |
| 913 | 913 | } |
| 914 | 914 | if ( cpustate->decode & M_CKM ) |
| 915 | 915 | { |
| 916 | | |
| 916 | | |
| 917 | 917 | } |
| 918 | 918 | } |
| 919 | 919 | else |
| 920 | 920 | { |
| 921 | 921 | if ( cpustate->decode & F_SBIT ) |
| 922 | 922 | { |
| 923 | | |
| 923 | | |
| 924 | 924 | } |
| 925 | 925 | if ( cpustate->decode & F_RBIT ) |
| 926 | 926 | { |
| 927 | | |
| 927 | | |
| 928 | 928 | } |
| 929 | 929 | if ( cpustate->decode & F_SETR ) |
| 930 | 930 | { |
| r8806 | r8807 | |
| 1028 | 1028 | if ( cpustate->byte_size > 8 ) |
| 1029 | 1029 | { |
| 1030 | 1030 | debugger_instruction_hook( device, cpustate->rom_address << 1 ); |
| 1031 | cpustate->opcode = | |
| 1031 | cpustate->opcode = | |
| 1032 | 1032 | } |
| 1033 | 1033 | else |
| 1034 | 1034 | { |
| 1035 | 1035 | debugger_instruction_hook( device, cpustate->rom_address ); |
| 1036 | cpustate->opcode = | |
| 1036 | cpustate->opcode = | |
| 1037 | 1037 | } |
| 1038 | 1038 | tms0980_next_pc( cpustate ); |
| 1039 | 1039 | if (LOG) |
| r8806 | r8807 | |
|---|---|---|
| 23 | 23 | |
| 24 | 24 | #define H8_SP (7) |
| 25 | 25 | |
| 26 | #define h8_mem_read8(x) memory_read_byte(h8->program, x) | |
| 27 | #define h8_mem_read16(z, x) memory_read_word(h8->program, x) | |
| 28 | #define h8_mem_write8(x, y) memory_write_byte(h8->program, x, y) | |
| 29 | #define h8_mem_write16(z, x, y) memory_write_word(h8->program, x, y) | |
| 26 | #define h8_mem_read8(x) h8->program->read_byte(x) | |
| 27 | #define h8_mem_read16(z, x) h8->program->read_word(x) | |
| 28 | #define h8_mem_write8(x, y) h8->program->write_byte(x, y) | |
| 29 | #define h8_mem_write16(z, x, y) h8->program->write_word(x, y) | |
| 30 | 30 | #define h8_readop16(x, y) memory_decrypted_read_word(x->program, y) |
| 31 | 31 | |
| 32 | 32 | // timing macros |
| r8806 | r8807 | |
| 41 | 41 | |
| 42 | 42 | INLINE UINT32 h8_mem_read32(h83xx_state *h8, offs_t address) |
| 43 | 43 | { |
| 44 | UINT32 result = memory_read_word_16be(h8->program, address) << 16; | |
| 45 | return result | memory_read_word_16be(h8->program, address + 2); | |
| 44 | UINT32 result = h8->program->read_word(address) << 16; | |
| 45 | return result | h8->program->read_word(address + 2); | |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | 48 | INLINE void h8_mem_write32(h83xx_state *h8, offs_t address, UINT32 data) |
| 49 | 49 | { |
| 50 | memory_write_word_16be(h8->program, address, data >> 16); | |
| 51 | memory_write_word_16be(h8->program, address + 2, data); | |
| 50 | h8->program->write_word(address, data >> 16); | |
| 51 | h8->program->write_word(address + 2, data); | |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | 54 | static void h8_check_irqs(h83xx_state *h8); |
| r8806 | r8807 | |
|---|---|---|
| 28 | 28 | device_irq_callback irq_cb; |
| 29 | 29 | legacy_cpu_device *device; |
| 30 | 30 | |
| 31 | const address_space *program; | |
| 32 | const address_space *io; | |
| 31 | address_space *program; | |
| 32 | address_space *io; | |
| 33 | 33 | |
| 34 | 34 | // onboard peripherals stuff |
| 35 | 35 | UINT8 per_regs[256]; |
| r8806 | r8807 | |
| 45 | 45 | |
| 46 | 46 | int mode_8bit; |
| 47 | 47 | }; |
| 48 | extern h83xx_state h8; | |
| 49 | 48 | |
| 50 | 49 | INLINE h83xx_state *get_safe_token(running_device *device) |
| 51 | 50 | { |
| r8806 | r8807 | |
|---|---|---|
| 18 | 18 | |
| 19 | 19 | #define H8_SP (7) |
| 20 | 20 | |
| 21 | #define h8_mem_read8(x) memory_read_byte(h8->program, x) | |
| 22 | #define h8_mem_write8(x, y) memory_write_byte(h8->program, x, y) | |
| 21 | #define h8_mem_read8(x) h8->program->read_byte(x) | |
| 22 | #define h8_mem_write8(x, y) h8->program->write_byte(x, y) | |
| 23 | 23 | |
| 24 | 24 | // timing macros |
| 25 | 25 | #define H8_IFETCH_TIMING(x) h8->cyccnt -= (x) * 4; |
| r8806 | r8807 | |
| 36 | 36 | |
| 37 | 37 | INLINE UINT16 h8_mem_read16(h83xx_state *h8, offs_t address) |
| 38 | 38 | { |
| 39 | UINT16 result = memory_read_byte(h8->program, address)<<8; | |
| 40 | return result | memory_read_byte(h8->program, address+1); | |
| 39 | UINT16 result = h8->program->read_byte(address)<<8; | |
| 40 | return result | h8->program->read_byte(address+1); | |
| 41 | 41 | } |
| 42 | 42 | |
| 43 | 43 | INLINE UINT16 h8_readop16(h83xx_state *h8, offs_t address) |
| r8806 | r8807 | |
| 48 | 48 | |
| 49 | 49 | INLINE void h8_mem_write16(h83xx_state *h8, offs_t address, UINT16 data) |
| 50 | 50 | { |
| 51 | memory_write_byte(h8->program, address, data >> 8); | |
| 52 | memory_write_byte(h8->program, address+1, data); | |
| 51 | h8->program->write_byte(address, data >> 8); | |
| 52 | h8->program->write_byte(address+1, data); | |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | 55 | INLINE UINT32 h8_mem_read32(h83xx_state *h8, offs_t address) |
| 56 | 56 | { |
| 57 | UINT32 result = memory_read_byte(h8->program, address) << 24; | |
| 58 | result |= memory_read_byte(h8->program, address+1) << 16; | |
| 59 | result |= memory_read_byte(h8->program, address+2) << 8; | |
| 60 | result |= memory_read_byte(h8->program, address+3); | |
| 57 | UINT32 result = h8->program->read_byte(address) << 24; | |
| 58 | result |= h8->program->read_byte(address+1) << 16; | |
| 59 | result |= h8->program->read_byte(address+2) << 8; | |
| 60 | result |= h8->program->read_byte(address+3); | |
| 61 | 61 | |
| 62 | 62 | return result; |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | 65 | INLINE void h8_mem_write32(h83xx_state *h8, offs_t address, UINT32 data) |
| 66 | 66 | { |
| 67 | memory_write_byte(h8->program, address, data >> 24); | |
| 68 | memory_write_byte(h8->program, address+1, data >> 16); | |
| 69 | memory_write_byte(h8->program, address+2, data >> 8); | |
| 70 | memory_write_byte(h8->program, address+3, data); | |
| 67 | h8->program->write_byte(address, data >> 24); | |
| 68 | h8->program->write_byte(address+1, data >> 16); | |
| 69 | h8->program->write_byte(address+2, data >> 8); | |
| 70 | h8->program->write_byte(address+3, data); | |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | 73 | static void h8_check_irqs(h83xx_state *h8); |
| r8806 | r8807 | |
| 522 | 522 | switch(reg) |
| 523 | 523 | { |
| 524 | 524 | case 0x8d: // serial Rx 1 |
| 525 | val = | |
| 525 | val = h8->io->r | |
| 526 | 526 | break; |
| 527 | 527 | case 0x92: // FRC H |
| 528 | 528 | frc = h8->device->total_cycles() / divider[h8->per_regs[0x96]]; |
| r8806 | r8807 | |
| 533 | 533 | frc %= 65536; |
| 534 | 534 | return frc&0xff; |
| 535 | 535 | case 0xb2: // port 1 data |
| 536 | val = | |
| 536 | val = h8->io->r | |
| 537 | 537 | break; |
| 538 | 538 | case 0xb3: // port 2 data |
| 539 | val = | |
| 539 | val = h8->io->r | |
| 540 | 540 | break; |
| 541 | 541 | case 0xb6: // port 3 data |
| 542 | val = | |
| 542 | val = h8->io->r | |
| 543 | 543 | break; |
| 544 | 544 | case 0xb7: // port 4 data |
| 545 | val = | |
| 545 | val = h8->io->r | |
| 546 | 546 | break; |
| 547 | 547 | case 0xba: // port 5 data |
| 548 | val = | |
| 548 | val = h8->io->r | |
| 549 | 549 | break; |
| 550 | 550 | case 0xbb: // port 6 data |
| 551 | val = | |
| 551 | val = h8->io->r | |
| 552 | 552 | break; |
| 553 | 553 | case 0xbe: // port 7 data |
| 554 | val = | |
| 554 | val = h8->io->r | |
| 555 | 555 | break; |
| 556 | 556 | case 0xbf: // port 8 data |
| 557 | val = | |
| 557 | val = h8->io->r | |
| 558 | 558 | break; |
| 559 | 559 | case 0xc1: // port 9 data |
| 560 | val = | |
| 560 | val = h8->io->r | |
| 561 | 561 | break; |
| 562 | 562 | case 0xdc: // serial status |
| 563 | 563 | val = 0x87; |
| 564 | 564 | break; |
| 565 | 565 | case 0xdd: // serial Rx 0 |
| 566 | val = | |
| 566 | val = h8->io->r | |
| 567 | 567 | break; |
| 568 | 568 | case 0xe0: // ADC 0 low byte |
| 569 | val = | |
| 569 | val = h8->io->r | |
| 570 | 570 | break; |
| 571 | 571 | case 0xe1: // ADC 0 high byte |
| 572 | val = | |
| 572 | val = h8->io->r | |
| 573 | 573 | break; |
| 574 | 574 | case 0xe2: // ADC 1 low byte |
| 575 | val = | |
| 575 | val = h8->io->r | |
| 576 | 576 | break; |
| 577 | 577 | case 0xe3: // ADC 1 high byte |
| 578 | val = | |
| 578 | val = h8->io->r | |
| 579 | 579 | break; |
| 580 | 580 | case 0xe4: // ADC 2 low byte |
| 581 | val = | |
| 581 | val = h8->io->r | |
| 582 | 582 | break; |
| 583 | 583 | case 0xe5: // ADC 2 high byte |
| 584 | val = | |
| 584 | val = h8->io->r | |
| 585 | 585 | break; |
| 586 | 586 | case 0xe6: // ADC 3 low byte |
| 587 | val = | |
| 587 | val = h8->io->r | |
| 588 | 588 | break; |
| 589 | 589 | case 0xe7: // ADC 3 high byte |
| 590 | val = | |
| 590 | val = h8->io->r | |
| 591 | 591 | break; |
| 592 | 592 | case 0xe8: // ADCSR: A/D control/status |
| 593 | 593 | val = 0x80; // return conversion completed |
| r8806 | r8807 | |
| 613 | 613 | printf("%02x to flash control or external\n", data); |
| 614 | 614 | break; |
| 615 | 615 | case 0x8b: // serial Tx 1 |
| 616 | | |
| 616 | h8->io-> | |
| 617 | 617 | break; |
| 618 | 618 | case 0xb2: // port 1 data |
| 619 | | |
| 619 | h8->io-> | |
| 620 | 620 | break; |
| 621 | 621 | case 0xb3: // port 2 data |
| 622 | | |
| 622 | h8->io-> | |
| 623 | 623 | break; |
| 624 | 624 | case 0xb6: // port 3 data |
| 625 | | |
| 625 | h8->io-> | |
| 626 | 626 | break; |
| 627 | 627 | case 0xb7: // port 4 data |
| 628 | | |
| 628 | h8->io-> | |
| 629 | 629 | break; |
| 630 | 630 | case 0xba: // port 5 data |
| 631 | | |
| 631 | h8->io-> | |
| 632 | 632 | break; |
| 633 | 633 | case 0xbb: // port 6 data |
| 634 | | |
| 634 | h8->io-> | |
| 635 | 635 | break; |
| 636 | 636 | case 0xbe: // port 7 data |
| 637 | | |
| 637 | h8->io-> | |
| 638 | 638 | break; |
| 639 | 639 | case 0xbf: // port 8 data |
| 640 | | |
| 640 | h8->io-> | |
| 641 | 641 | break; |
| 642 | 642 | case 0xc1: // port 9 data |
| 643 | | |
| 643 | h8->io-> | |
| 644 | 644 | break; |
| 645 | 645 | case 0xdb: // serial Tx 0 |
| 646 | | |
| 646 | h8->io-> | |
| 647 | 647 | break; |
| 648 | 648 | |
| 649 | 649 | case 0xd8: |
| r8806 | r8807 | |
|---|---|---|
| 328 | 328 | val |= 0xc4; // transmit finished, receive ready, no errors |
| 329 | 329 | break; |
| 330 | 330 | case 0xb5: // serial port A receive |
| 331 | val = | |
| 331 | val = h8->io->r | |
| 332 | 332 | break; |
| 333 | 333 | case 0xbc: // serial port B status |
| 334 | 334 | val = h8->per_regs[reg]; |
| 335 | 335 | val |= 0xc4; // transmit finished, receive ready, no errors |
| 336 | 336 | break; |
| 337 | 337 | case 0xbd: // serial port B receive |
| 338 | val = | |
| 338 | val = h8->io->r | |
| 339 | 339 | break; |
| 340 | 340 | case 0xe0: |
| 341 | val = | |
| 341 | val = h8->io->r | |
| 342 | 342 | break; |
| 343 | 343 | case 0xe1: |
| 344 | val = | |
| 344 | val = h8->io->r | |
| 345 | 345 | break; |
| 346 | 346 | case 0xe2: |
| 347 | val = | |
| 347 | val = h8->io->r | |
| 348 | 348 | break; |
| 349 | 349 | case 0xe3: |
| 350 | val = | |
| 350 | val = h8->io->r | |
| 351 | 351 | break; |
| 352 | 352 | case 0xe4: |
| 353 | val = | |
| 353 | val = h8->io->r | |
| 354 | 354 | break; |
| 355 | 355 | case 0xe5: |
| 356 | val = | |
| 356 | val = h8->io->r | |
| 357 | 357 | break; |
| 358 | 358 | case 0xe6: |
| 359 | val = | |
| 359 | val = h8->io->r | |
| 360 | 360 | break; |
| 361 | 361 | case 0xe7: |
| 362 | val = | |
| 362 | val = h8->io->r | |
| 363 | 363 | break; |
| 364 | 364 | case 0xe8: // adc status |
| 365 | 365 | val = 0x80; |
| 366 | 366 | break; |
| 367 | 367 | case 0xc7: // port 4 data |
| 368 | val = | |
| 368 | val = h8->io->r | |
| 369 | 369 | break; |
| 370 | 370 | case 0xcb: // port 6 data |
| 371 | val = | |
| 371 | val = h8->io->r | |
| 372 | 372 | break; |
| 373 | 373 | case 0xce: // port 7 data |
| 374 | val = | |
| 374 | val = h8->io->r | |
| 375 | 375 | break; |
| 376 | 376 | case 0xcf: // port 8 data |
| 377 | val = | |
| 377 | val = h8->io->r | |
| 378 | 378 | break; |
| 379 | 379 | case 0xd2: // port 9 data |
| 380 | val = | |
| 380 | val = h8->io->r | |
| 381 | 381 | break; |
| 382 | 382 | case 0xd3: // port a data |
| 383 | val = | |
| 383 | val = h8->io->r | |
| 384 | 384 | break; |
| 385 | 385 | case 0xd6: // port b data |
| 386 | val = | |
| 386 | val = h8->io->r | |
| 387 | 387 | break; |
| 388 | 388 | case 0xf6: |
| 389 | 389 | val = h8_ISR_r(h8); |
| r8806 | r8807 | |
| 414 | 414 | switch (reg) |
| 415 | 415 | { |
| 416 | 416 | case 0xb3: // serial 0 send |
| 417 | | |
| 417 | h8->io-> | |
| 418 | 418 | h8_3002_InterruptRequest(h8, 54, 1); |
| 419 | 419 | h8_3002_InterruptRequest(h8, 55, 1); |
| 420 | 420 | break; |
| 421 | 421 | case 0xbb: // serial 1 send |
| 422 | | |
| 422 | h8->io-> | |
| 423 | 423 | h8_3002_InterruptRequest(h8, 58, 1); |
| 424 | 424 | h8_3002_InterruptRequest(h8, 59, 1); |
| 425 | 425 | break; |
| 426 | 426 | case 0xc7: |
| 427 | | |
| 427 | h8->io-> | |
| 428 | 428 | break; |
| 429 | 429 | case 0xcb: // port 6 data |
| 430 | | |
| 430 | h8->io-> | |
| 431 | 431 | break; |
| 432 | 432 | case 0xce: // port 7 data |
| 433 | | |
| 433 | h8->io-> | |
| 434 | 434 | break; |
| 435 | 435 | case 0xcf: // port 8 data |
| 436 | | |
| 436 | h8->io-> | |
| 437 | 437 | break; |
| 438 | 438 | case 0xd2: // port 9 data |
| 439 | | |
| 439 | h8->io-> | |
| 440 | 440 | break; |
| 441 | 441 | case 0xd3: // port a data |
| 442 | | |
| 442 | h8->io-> | |
| 443 | 443 | break; |
| 444 | 444 | case 0xd6: // port b data |
| 445 | | |
| 445 | h8->io-> | |
| 446 | 446 | break; |
| 447 | 447 | case 0xf6: |
| 448 | 448 | h8_ISR_w(h8, val); |
| r8806 | r8807 | |
| 624 | 624 | val |= 0xc4; // transmit finished, receive ready, no errors |
| 625 | 625 | break; |
| 626 | 626 | case 0xb5: // serial port A receive |
| 627 | val = | |
| 627 | val = h8->io->r | |
| 628 | 628 | break; |
| 629 | 629 | case 0xbc: // serial port B status |
| 630 | 630 | val = h8->per_regs[reg]; |
| 631 | 631 | val |= 0xc4; // transmit finished, receive ready, no errors |
| 632 | 632 | break; |
| 633 | 633 | case 0xbd: // serial port B receive |
| 634 | val = | |
| 634 | val = h8->io->r | |
| 635 | 635 | break; |
| 636 | 636 | case 0xe0: |
| 637 | val = | |
| 637 | val = h8->io->r | |
| 638 | 638 | break; |
| 639 | 639 | case 0xe1: |
| 640 | val = | |
| 640 | val = h8->io->r | |
| 641 | 641 | break; |
| 642 | 642 | case 0xe2: |
| 643 | val = | |
| 643 | val = h8->io->r | |
| 644 | 644 | break; |
| 645 | 645 | case 0xe3: |
| 646 | val = | |
| 646 | val = h8->io->r | |
| 647 | 647 | break; |
| 648 | 648 | case 0xe4: |
| 649 | val = | |
| 649 | val = h8->io->r | |
| 650 | 650 | break; |
| 651 | 651 | case 0xe5: |
| 652 | val = | |
| 652 | val = h8->io->r | |
| 653 | 653 | break; |
| 654 | 654 | case 0xe6: |
| 655 | val = | |
| 655 | val = h8->io->r | |
| 656 | 656 | break; |
| 657 | 657 | case 0xe7: |
| 658 | val = | |
| 658 | val = h8->io->r | |
| 659 | 659 | break; |
| 660 | 660 | case 0xe8: // adc status |
| 661 | 661 | val = 0x80; |
| 662 | 662 | break; |
| 663 | 663 | |
| 664 | 664 | case 0xd3: // port 4 data |
| 665 | val = | |
| 665 | val = h8->io->r | |
| 666 | 666 | break; |
| 667 | 667 | case 0xd5: // port 6 data |
| 668 | val = | |
| 668 | val = h8->io->r | |
| 669 | 669 | break; |
| 670 | 670 | case 0xd6: // port 7 data |
| 671 | val = | |
| 671 | val = h8->io->r | |
| 672 | 672 | break; |
| 673 | 673 | case 0xd7: // port 8 data |
| 674 | val = | |
| 674 | val = h8->io->r | |
| 675 | 675 | break; |
| 676 | 676 | case 0xd8: // port 9 data |
| 677 | val = | |
| 677 | val = h8->io->r | |
| 678 | 678 | break; |
| 679 | 679 | case 0xd9: // port a data |
| 680 | val = | |
| 680 | val = h8->io->r | |
| 681 | 681 | break; |
| 682 | 682 | case 0xda: // port b data |
| 683 | val = | |
| 683 | val = h8->io->r | |
| 684 | 684 | break; |
| 685 | 685 | default: |
| 686 | 686 | val = h8->per_regs[reg]; |
| r8806 | r8807 | |
| 710 | 710 | switch (reg) |
| 711 | 711 | { |
| 712 | 712 | case 0xb3: |
| 713 | | |
| 713 | h8->io-> | |
| 714 | 714 | break; |
| 715 | 715 | case 0xbb: |
| 716 | | |
| 716 | h8->io-> | |
| 717 | 717 | break; |
| 718 | 718 | case 0xd3: |
| 719 | | |
| 719 | h8->io-> | |
| 720 | 720 | break; |
| 721 | 721 | case 0xd5: // port 6 data |
| 722 | | |
| 722 | h8->io-> | |
| 723 | 723 | break; |
| 724 | 724 | case 0xd6: // port 7 data |
| 725 | | |
| 725 | h8->io-> | |
| 726 | 726 | break; |
| 727 | 727 | case 0xd7: // port 8 data |
| 728 | | |
| 728 | h8->io-> | |
| 729 | 729 | break; |
| 730 | 730 | case 0xd8: // port 9 data |
| 731 | | |
| 731 | h8->io-> | |
| 732 | 732 | break; |
| 733 | 733 | case 0xd9: // port a data |
| 734 | | |
| 734 | h8->io-> | |
| 735 | 735 | break; |
| 736 | 736 | case 0xda: // port b data |
| 737 | | |
| 737 | h8->io-> | |
| 738 | 738 | break; |
| 739 | 739 | } |
| 740 | 740 | } |
| r8806 | r8807 | |
|---|---|---|
| 98 | 98 | |
| 99 | 99 | INLINE UINT16 READ16(unsp_state *unsp, UINT32 address) |
| 100 | 100 | { |
| 101 | return | |
| 101 | return | |
| 102 | 102 | } |
| 103 | 103 | |
| 104 | 104 | INLINE void WRITE16(unsp_state *unsp, UINT32 address, UINT16 data) |
| 105 | 105 | { |
| 106 | | |
| 106 | | |
| 107 | 107 | } |
| 108 | 108 | |
| 109 | 109 | /*****************************************************************************/ |
| r8806 | r8807 | |
|---|---|---|
| 24 | 24 | UINT8 saved_sb; |
| 25 | 25 | |
| 26 | 26 | legacy_cpu_device *device; |
| 27 | | |
| 27 | | |
| 28 | 28 | int icount; |
| 29 | 29 | |
| 30 | 30 | unspimp_state *impstate; |
| r8806 | r8807 | |
|---|---|---|
| 88 | 88 | |
| 89 | 89 | |
| 90 | 90 | legacy_cpu_device *device; |
| 91 | const address_space *program; | |
| 92 | const address_space *data; | |
| 93 | const address_space *io; | |
| 91 | address_space *program; | |
| 92 | address_space *data; | |
| 93 | address_space *io; | |
| 94 | 94 | }; |
| 95 | 95 | |
| 96 | 96 | INLINE pic16c62x_state *get_safe_token(running_device *device) |
| r8806 | r8807 | |
| 130 | 130 | } |
| 131 | 131 | |
| 132 | 132 | #define PIC16C62x_RDOP(A) (memory_decrypted_read_word(cpustate->program, (A)<<1)) |
| 133 | #define PIC16C62x_RAM_RDMEM(A) ((UINT8)memory_read_byte_8le(cpustate->data, A)) | |
| 134 | #define PIC16C62x_RAM_WRMEM(A,V) (memory_write_byte_8le(cpustate->data, A,V)) | |
| 135 | #define PIC16C62x_In(Port) ((UINT8)memory_read_byte_8le(cpustate->io, (Port))) | |
| 136 | #define PIC16C62x_Out(Port,Value) (memory_write_byte_8le(cpustate->io, (Port),Value)) | |
| 133 | #define PIC16C62x_RAM_RDMEM(A) ((UINT8)cpustate->data->read_byte(A)) | |
| 134 | #define PIC16C62x_RAM_WRMEM(A,V) (cpustate->data->write_byte(A,V)) | |
| 135 | #define PIC16C62x_In(Port) ((UINT8)cpustate->io->read_byte((Port))) | |
| 136 | #define PIC16C62x_Out(Port,Value) (cpustate->io->write_byte((Port),Value)) | |
| 137 | 137 | /************ Read the state of the T0 Clock input signal ************/ |
| 138 | #define PIC16C62x_T0_In ( | |
| 138 | #define PIC16C62x_T0_In ( | |
| 139 | 139 | |
| 140 | 140 | #define M_RDRAM(A) (((A) == 0) ? cpustate->internalram[0] : PIC16C62x_RAM_RDMEM(A)) |
| 141 | 141 | #define M_WRTRAM(A,V) do { if ((A) == 0) cpustate->internalram[0] = (V); else PIC16C62x_RAM_WRMEM(A,V); } while (0) |
| r8806 | r8807 | |
|---|---|---|
| 956 | 956 | return; |
| 957 | 957 | } |
| 958 | 958 | |
| 959 | r = | |
| 959 | r = | |
| 960 | 960 | } |
| 961 | 961 | } |
| 962 | 962 | |
| r8806 | r8807 | |
| 1020 | 1020 | return; |
| 1021 | 1021 | } |
| 1022 | 1022 | |
| 1023 | r = | |
| 1023 | r = | |
| 1024 | 1024 | } |
| 1025 | 1025 | } |
| 1026 | 1026 | |
| r8806 | r8807 | |
| 1045 | 1045 | int cnt; |
| 1046 | 1046 | for (cnt = 0; cnt <= GET_CHC_CR; ++cnt) |
| 1047 | 1047 | { |
| 1048 | am29000->r[r] = | |
| 1048 | am29000->r[r] = | |
| 1049 | 1049 | |
| 1050 | 1050 | // SET_CHC_CR(cnt - 1); |
| 1051 | 1051 | addr += 4; |
| r8806 | r8807 | |
| 1086 | 1086 | } |
| 1087 | 1087 | } |
| 1088 | 1088 | |
| 1089 | | |
| 1089 | | |
| 1090 | 1090 | |
| 1091 | 1091 | if (!FREEZE_MODE) |
| 1092 | 1092 | { |
| r8806 | r8807 | |
| 1159 | 1159 | int cnt; |
| 1160 | 1160 | for (cnt = 0; cnt <= GET_CHC_CR; ++cnt) |
| 1161 | 1161 | { |
| 1162 | | |
| 1162 | | |
| 1163 | 1163 | |
| 1164 | 1164 | // SET_CHC_CR(cnt - 1); |
| 1165 | 1165 | addr += 4; |
| r8806 | r8807 | |
|---|---|---|
| 131 | 131 | UINT32 exec_pc; |
| 132 | 132 | UINT32 next_pc; |
| 133 | 133 | |
| 134 | const address_space *program; | |
| 135 | const address_space *data; | |
| 136 | const address_space *io; | |
| 134 | address_space *program; | |
| 135 | address_space *data; | |
| 136 | address_space *io; | |
| 137 | 137 | } am29000_state; |
| 138 | 138 | |
| 139 | 139 |
| r8806 | r8807 | |
|---|---|---|
| 44 | 44 | int icount; |
| 45 | 45 | |
| 46 | 46 | legacy_cpu_device *device; |
| 47 | const address_space *program; | |
| 48 | const address_space *data; | |
| 49 | const address_space *io; | |
| 47 | address_space *program; | |
| 48 | address_space *data; | |
| 49 | address_space *io; | |
| 50 | 50 | }; |
| 51 | 51 | |
| 52 | 52 | |
| r8806 | r8807 | |
| 64 | 64 | |
| 65 | 65 | #define READOP(C,a) (memory_decrypted_read_byte((C)->program, a)) |
| 66 | 66 | |
| 67 | #define RDMEM(C,a) (memory_read_word_16be((C)->data, (a) * 2) & 0xfff) | |
| 68 | #define WRMEM(C,a,v) (memory_write_word_16be((C)->data, (a) * 2, (v))) | |
| 67 | #define RDMEM(C,a) ((C)->data->read_word((a) * 2) & 0xfff) | |
| 68 | #define WRMEM(C,a,v) ((C)->data->write_word((a) * 2, (v))) | |
| 69 | 69 | |
| 70 | #define READPORT(C,a) (memory_read_byte_8be((C)->io, a)) | |
| 71 | #define WRITEPORT(C,a,v) (memory_write_byte_8be((C)->io, (a), (v))) | |
| 70 | #define READPORT(C,a) ((C)->io->read_byte(a)) | |
| 71 | #define WRITEPORT(C,a,v) ((C)->io->write_byte((a), (v))) | |
| 72 | 72 | |
| 73 | 73 | #define SET_A0(C) do { (C)->a0flag = (C)->A; } while (0) |
| 74 | 74 | #define SET_CMP_VAL(C,x) do { (C)->cmpacc = *(C)->acc; (C)->cmpval = (x) & 0xfff; } while (0) |
| r8806 | r8807 | |
|---|---|---|
| 535 | 535 | |
| 536 | 536 | /* Redirect memory calls */ |
| 537 | 537 | |
| 538 | typedef struct _m68k_memory_interface m68k_memory_interface; | |
| 539 | struct _m68k_memory_interface | |
| 538 | typedef proto_delegate_1param<UINT8, offs_t> m68k_read8_proto_delegate; | |
| 539 | typedef proto_delegate_1param<UINT16, offs_t> m68k_readimm16_proto_delegate; | |
| 540 | typedef proto_delegate_2param<UINT16, offs_t, UINT16> m68k_read16_proto_delegate; | |
| 541 | typedef proto_delegate_2param<UINT32, offs_t, UINT32> m68k_read32_proto_delegate; | |
| 542 | typedef proto_delegate_2param<void, offs_t, UINT8> m68k_write8_proto_delegate; | |
| 543 | typedef proto_delegate_3param<void, offs_t, UINT16, UINT16> m68k_write16_proto_delegate; | |
| 544 | typedef proto_delegate_3param<void, offs_t, UINT32, UINT32> m68k_write32_proto_delegate; | |
| 545 | ||
| 546 | typedef delegate_1param<UINT8, offs_t> m68k_read8_delegate; | |
| 547 | typedef delegate_1param<UINT16, offs_t> m68k_readimm16_delegate; | |
| 548 | typedef delegate_2param<UINT16, offs_t, UINT16> m68k_read16_delegate; | |
| 549 | typedef delegate_2param<UINT32, offs_t, UINT32> m68k_read32_delegate; | |
| 550 | typedef delegate_2param<void, offs_t, UINT8> m68k_write8_delegate; | |
| 551 | typedef delegate_3param<void, offs_t, UINT16, UINT16> m68k_write16_delegate; | |
| 552 | typedef delegate_3param<void, offs_t, UINT32, UINT32> m68k_write32_delegate; | |
| 553 | ||
| 554 | class m68k_memory_interface : public bindable_object | |
| 540 | 555 | { |
| 556 | public: | |
| 557 | void init8(address_space &space); | |
| 558 | void init16(address_space &space); | |
| 559 | void init32(address_space &space); | |
| 560 | void init32mmu(address_space &space); | |
| 561 | ||
| 541 | 562 | offs_t opcode_xor; // Address Calculation |
| 542 | UINT16 (*readimm16)(const address_space *, offs_t); // Immediate read 16 bit | |
| 543 | UINT8 (*read8)(const address_space *, offs_t); // Normal read 8 bit | |
| 544 | UINT16 (*read16)(const address_space *, offs_t); // Normal read 16 bit | |
| 545 | UINT32 (*read32)(const address_space *, offs_t); // Normal read 32 bit | |
| 546 | void (*write8)(const address_space *, offs_t, UINT8); // Write 8 bit | |
| 547 | void (*write16)(const address_space *, offs_t, UINT16); // Write 16 bit | |
| 548 | void (*write32)(const address_space *, offs_t, UINT32); // Write 32 bit | |
| 563 | m68k_readimm16_delegate readimm16; // Immediate read 16 bit | |
| 564 | m68k_read8_delegate read8; | |
| 565 | m68k_read16_delegate read16; | |
| 566 | m68k_read32_delegate read32; | |
| 567 | m68k_write8_delegate write8; | |
| 568 | m68k_write16_delegate write16; | |
| 569 | m68k_write32_delegate write32; | |
| 570 | ||
| 571 | private: | |
| 572 | UINT16 m68008_read_immediate_16(offs_t address); | |
| 573 | UINT16 read_immediate_16(offs_t address); | |
| 574 | UINT16 simple_read_immediate_16(offs_t address); | |
| 575 | UINT16 readword_d32(offs_t address, UINT16 mask); | |
| 576 | void writeword_d32(offs_t address, UINT16 data, UINT16 mask); | |
| 577 | UINT32 readlong_d32(offs_t address, UINT32 mask); | |
| 578 | void writelong_d32(offs_t address, UINT32 data, UINT32 mask); | |
| 579 | ||
| 580 | UINT8 read_byte_32_mmu(offs_t address); | |
| 581 | void write_byte_32_mmu(offs_t address, UINT8 data); | |
| 582 | UINT16 read_immediate_16_mmu(offs_t address); | |
| 583 | UINT16 readword_d32_mmu(offs_t address, UINT16 mask); | |
| 584 | void writeword_d32_mmu(offs_t address, UINT16 data, UINT16 mask); | |
| 585 | UINT32 readlong_d32_mmu(offs_t address, UINT32 mask); | |
| 586 | void writelong_d32_mmu(offs_t address, UINT32 data, UINT32 mask); | |
| 587 | ||
| 588 | address_space *m_space; | |
| 589 | direct_read_data *m_direct; | |
| 590 | m68ki_cpu_core *m_cpustate; | |
| 549 | 591 | }; |
| 550 | 592 | |
| 551 | 593 | struct _m68ki_cpu_core |
| r8806 | r8807 | |
| 628 | 670 | m68k_tas_func tas_instr_callback; /* Called when a TAS instruction is encountered, allows / disallows writeback */ |
| 629 | 671 | |
| 630 | 672 | legacy_cpu_device *device; |
| 631 | | |
| 673 | | |
| 632 | 674 | m68k_memory_interface memory; |
| 633 | 675 | offs_t encrypted_start; |
| 634 | 676 | offs_t encrypted_end; |
| r8806 | r8807 | |
| 779 | 821 | |
| 780 | 822 | INLINE unsigned int m68k_read_immediate_32(m68ki_cpu_core *m68k, unsigned int address) |
| 781 | 823 | { |
| 782 | return ( | |
| 824 | return ( | |
| 783 | 825 | } |
| 784 | 826 | |
| 785 | 827 | INLINE unsigned int m68k_read_pcrelative_8(m68ki_cpu_core *m68k, unsigned int address) |
| 786 | 828 | { |
| 787 | 829 | if (address >= m68k->encrypted_start && address < m68k->encrypted_end) |
| 788 | return (( | |
| 830 | return (( | |
| 789 | 831 | |
| 790 | return | |
| 832 | return | |
| 791 | 833 | } |
| 792 | 834 | |
| 793 | 835 | INLINE unsigned int m68k_read_pcrelative_16(m68ki_cpu_core *m68k, unsigned int address) |
| 794 | 836 | { |
| 795 | 837 | if (address >= m68k->encrypted_start && address < m68k->encrypted_end) |
| 796 | return | |
| 838 | return | |
| 797 | 839 | |
| 798 | return | |
| 840 | return | |
| 799 | 841 | } |
| 800 | 842 | |
| 801 | 843 | INLINE unsigned int m68k_read_pcrelative_32(m68ki_cpu_core *m68k, unsigned int address) |
| r8806 | r8807 | |
| 803 | 845 | if (address >= m68k->encrypted_start && address < m68k->encrypted_end) |
| 804 | 846 | return m68k_read_immediate_32(m68k, address); |
| 805 | 847 | |
| 806 | return | |
| 848 | return | |
| 807 | 849 | } |
| 808 | 850 | |
| 809 | 851 | |
| r8806 | r8807 | |
| 814 | 856 | */ |
| 815 | 857 | INLINE void m68kx_write_memory_32_pd(m68ki_cpu_core *m68k, unsigned int address, unsigned int value) |
| 816 | 858 | { |
| 817 | (m68k->memory.write16)(m68k->program, address+2, value>>16); | |
| 818 | (m68k->memory.write16)(m68k->program, address, value&0xffff); | |
| 859 | m68k->memory.write16(address+2, value>>16, 0xffff); | |
| 860 | m68k->memory.write16(address, value&0xffff, 0xffff); | |
| 819 | 861 | } |
| 820 | 862 | |
| 821 | 863 | |
| r8806 | r8807 | |
| 833 | 875 | if(REG_PC != m68k->pref_addr) |
| 834 | 876 | { |
| 835 | 877 | m68k->pref_addr = REG_PC; |
| 836 | m68k->pref_data = | |
| 878 | m68k->pref_data = | |
| 837 | 879 | } |
| 838 | 880 | result = MASK_OUT_ABOVE_16(m68k->pref_data); |
| 839 | 881 | REG_PC += 2; |
| 840 | 882 | m68k->pref_addr = REG_PC; |
| 841 | m68k->pref_data = | |
| 883 | m68k->pref_data = | |
| 842 | 884 | return result; |
| 843 | 885 | } |
| 844 | 886 | |
| r8806 | r8807 | |
| 851 | 893 | if(REG_PC != m68k->pref_addr) |
| 852 | 894 | { |
| 853 | 895 | m68k->pref_addr = REG_PC; |
| 854 | m68k->pref_data = | |
| 896 | m68k->pref_data = | |
| 855 | 897 | } |
| 856 | 898 | temp_val = MASK_OUT_ABOVE_16(m68k->pref_data); |
| 857 | 899 | REG_PC += 2; |
| 858 | 900 | m68k->pref_addr = REG_PC; |
| 859 | m68k->pref_data = | |
| 901 | m68k->pref_data = | |
| 860 | 902 | |
| 861 | 903 | temp_val = MASK_OUT_ABOVE_32((temp_val << 16) | MASK_OUT_ABOVE_16(m68k->pref_data)); |
| 862 | 904 | REG_PC += 2; |
| 863 | 905 | m68k->pref_addr = REG_PC; |
| 864 | m68k->pref_data = | |
| 906 | m68k->pref_data = | |
| 865 | 907 | |
| 866 | 908 | return temp_val; |
| 867 | 909 | } |
| r8806 | r8807 | |
| 878 | 920 | */ |
| 879 | 921 | INLINE UINT32 m68ki_read_8_fc(m68ki_cpu_core *m68k, UINT32 address, UINT32 fc) |
| 880 | 922 | { |
| 881 | return | |
| 923 | return | |
| 882 | 924 | } |
| 883 | 925 | INLINE UINT32 m68ki_read_16_fc(m68ki_cpu_core *m68k, UINT32 address, UINT32 fc) |
| 884 | 926 | { |
| r8806 | r8807 | |
| 886 | 928 | { |
| 887 | 929 | m68ki_check_address_error(m68k, address, MODE_READ, fc); |
| 888 | 930 | } |
| 889 | return | |
| 931 | return | |
| 890 | 932 | } |
| 891 | 933 | INLINE UINT32 m68ki_read_32_fc(m68ki_cpu_core *m68k, UINT32 address, UINT32 fc) |
| 892 | 934 | { |
| r8806 | r8807 | |
| 894 | 936 | { |
| 895 | 937 | m68ki_check_address_error(m68k, address, MODE_READ, fc); |
| 896 | 938 | } |
| 897 | return | |
| 939 | return | |
| 898 | 940 | } |
| 899 | 941 | |
| 900 | 942 | INLINE void m68ki_write_8_fc(m68ki_cpu_core *m68k, UINT32 address, UINT32 fc, UINT32 value) |
| 901 | 943 | { |
| 902 | | |
| 944 | | |
| 903 | 945 | } |
| 904 | 946 | INLINE void m68ki_write_16_fc(m68ki_cpu_core *m68k, UINT32 address, UINT32 fc, UINT32 value) |
| 905 | 947 | { |
| r8806 | r8807 | |
| 907 | 949 | { |
| 908 | 950 | m68ki_check_address_error(m68k, address, MODE_WRITE, fc); |
| 909 | 951 | } |
| 910 | | |
| 952 | | |
| 911 | 953 | } |
| 912 | 954 | INLINE void m68ki_write_32_fc(m68ki_cpu_core *m68k, UINT32 address, UINT32 fc, UINT32 value) |
| 913 | 955 | { |
| r8806 | r8807 | |
| 915 | 957 | { |
| 916 | 958 | m68ki_check_address_error(m68k, address, MODE_WRITE, fc); |
| 917 | 959 | } |
| 918 | | |
| 960 | | |
| 919 | 961 | } |
| 920 | 962 | |
| 921 | 963 | /* Special call to simulate undocumented 68k behavior when move.l with a |
| r8806 | r8807 | |
| 929 | 971 | { |
| 930 | 972 | m68ki_check_address_error(m68k, address, MODE_WRITE, fc); |
| 931 | 973 | } |
| 932 | (*m68k->memory.write16)(m68k->program, address+2, value>>16); | |
| 933 | (*m68k->memory.write16)(m68k->program, address, value&0xffff); | |
| 974 | m68k->memory.write16(address+2, value>>16, 0xffff); | |
| 975 | m68k->memory.write16(address, value&0xffff, 0xffff); | |
| 934 | 976 | } |
| 935 | 977 | |
| 936 | 978 | |
| r8806 | r8807 | |
| 1682 | 1724 | */ |
| 1683 | 1725 | if(m68k->run_mode == RUN_MODE_BERR_AERR_RESET) |
| 1684 | 1726 | { |
| 1685 | | |
| 1727 | | |
| 1686 | 1728 | m68k->stopped = STOP_LEVEL_HALT; |
| 1687 | 1729 | return; |
| 1688 | 1730 | } |
| r8806 | r8807 | |
|---|---|---|
| 53 | 53 | case 2: // valid 4 byte descriptors |
| 54 | 54 | tofs *= 4; |
| 55 | 55 | // logerror("PMMU: reading table A entry at %08x\n", tofs + (root_aptr & 0xfffffffc)); |
| 56 | tbl_entry = m | |
| 56 | tbl_entry = m68k->program->read_dword | |
| 57 | 57 | tamode = tbl_entry & 3; |
| 58 | 58 | // logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tamode, tofs); |
| 59 | 59 | break; |
| r8806 | r8807 | |
| 61 | 61 | case 3: // valid 8 byte descriptors |
| 62 | 62 | tofs *= 8; |
| 63 | 63 | // logerror("PMMU: reading table A entries at %08x\n", tofs + (root_aptr & 0xfffffffc)); |
| 64 | tbl_entry2 = memory_read_dword_32be(m68k->program, tofs + (root_aptr & 0xfffffffc)); | |
| 65 | tbl_entry = memory_read_dword_32be(m68k->program, tofs + (root_aptr & 0xfffffffc)+4); | |
| 64 | tbl_entry2 = m68k->program->read_dword(tofs + (root_aptr & 0xfffffffc)); | |
| 65 | tbl_entry = m68k->program->read_dword(tofs + (root_aptr & 0xfffffffc)+4); | |
| 66 | 66 | tamode = tbl_entry2 & 3; |
| 67 | 67 | // logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs); |
| 68 | 68 | break; |
| r8806 | r8807 | |
| 82 | 82 | case 2: // 4-byte table B descriptor |
| 83 | 83 | tofs *= 4; |
| 84 | 84 | // logerror("PMMU: reading table B entry at %08x\n", tofs + tptr); |
| 85 | tbl_entry = m | |
| 85 | tbl_entry = m68k->program->read_dword | |
| 86 | 86 | tbmode = tbl_entry & 3; |
| 87 | 87 | // logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs); |
| 88 | 88 | break; |
| r8806 | r8807 | |
| 90 | 90 | case 3: // 8-byte table B descriptor |
| 91 | 91 | tofs *= 8; |
| 92 | 92 | // logerror("PMMU: reading table B entries at %08x\n", tofs + tptr); |
| 93 | tbl_entry2 = memory_read_dword_32be(m68k->program, tofs + tptr); | |
| 94 | tbl_entry = memory_read_dword_32be(m68k->program, tofs + tptr + 4); | |
| 93 | tbl_entry2 = m68k->program->read_dword(tofs + tptr); | |
| 94 | tbl_entry = m68k->program->read_dword(tofs + tptr + 4); | |
| 95 | 95 | tbmode = tbl_entry2 & 3; |
| 96 | 96 | // logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs); |
| 97 | 97 | break; |
| r8806 | r8807 | |
| 121 | 121 | case 2: // 4-byte table C descriptor |
| 122 | 122 | tofs *= 4; |
| 123 | 123 | // logerror("PMMU: reading table C entry at %08x\n", tofs + tptr); |
| 124 | tbl_entry = m | |
| 124 | tbl_entry = m68k->program->read_dword | |
| 125 | 125 | tcmode = tbl_entry & 3; |
| 126 | 126 | // logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs); |
| 127 | 127 | break; |
| r8806 | r8807 | |
| 129 | 129 | case 3: // 8-byte table C descriptor |
| 130 | 130 | tofs *= 8; |
| 131 | 131 | // logerror("PMMU: reading table C entries at %08x\n", tofs + tptr); |
| 132 | tbl_entry2 = memory_read_dword_32be(m68k->program, tofs + tptr); | |
| 133 | tbl_entry = memory_read_dword_32be(m68k->program, tofs + tptr + 4); | |
| 132 | tbl_entry2 = m68k->program->read_dword(tofs + tptr); | |
| 133 | tbl_entry = m68k->program->read_dword(tofs + tptr + 4); | |
| 134 | 134 | tcmode = tbl_entry2 & 3; |
| 135 | 135 | // logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs); |
| 136 | 136 | break; |
| r8806 | r8807 | |
|---|---|---|
| 944 | 944 | * 8-bit data memory interface |
| 945 | 945 | ****************************************************************************/ |
| 946 | 946 | |
| 947 | ||
| 947 | ||
| 948 | 948 | { |
| 949 | offs_t addr = address; | |
| 950 | return (memory_decrypted_read_byte(space, addr) << 8) | (memory_decrypted_read_byte(space, addr + 1)); | |
| 949 | return (m_direct->read_decrypted_byte(address) << 8) | (m_direct->read_decrypted_byte(address + 1)); | |
| 951 | 950 | } |
| 952 | 951 | |
| 953 | /* interface for 20/22-bit address bus, 8-bit data bus (68008) */ | |
| 954 | static const m68k_memory_interface interface_d8 = | |
| 952 | void m68k_memory_interface::init8(address_space &space) | |
| 955 | 953 | { |
| 956 | 0, | |
| 957 | m68008_read_immediate_16, | |
| 958 | memory_read_byte_8be, | |
| 959 | memory_read_word_8be, | |
| 960 | memory_read_dword_8be, | |
| 961 | memory_write_byte_8be, | |
| 962 | memory_write_word_8be, | |
| 963 | memory_write_dword_8be | |
| 964 | }; | |
| 954 | m_space = &space; | |
| 955 | m_direct = &space.direct(); | |
| 956 | m_cpustate = get_safe_token(&space.device()); | |
| 957 | opcode_xor = 0; | |
| 965 | 958 | |
| 959 | readimm16 = m68k_readimm16_delegate(m68k_readimm16_proto_delegate::create_member(m68k_memory_interface, m68008_read_immediate_16), *this); | |
| 960 | read8 = m68k_read8_delegate(m68k_read8_proto_delegate::create_member(address_space, read_byte), space); | |
| 961 | read16 = m68k_read16_delegate(m68k_read16_proto_delegate::create_member(address_space, read_word), space); | |
| 962 | read32 = m68k_read32_delegate(m68k_read32_proto_delegate::create_member(address_space, read_dword), space); | |
| 963 | write8 = m68k_write8_delegate(m68k_write8_proto_delegate::create_member(address_space, write_byte), space); | |
| 964 | write16 = m68k_write16_delegate(m68k_write16_proto_delegate::create_member(address_space, write_word), space); | |
| 965 | write32 = m68k_write32_delegate(m68k_write32_proto_delegate::create_member(address_space, write_dword), space); | |
| 966 | } | |
| 967 | ||
| 966 | 968 | /**************************************************************************** |
| 967 | 969 | * 16-bit data memory interface |
| 968 | 970 | ****************************************************************************/ |
| 969 | 971 | |
| 970 | ||
| 972 | ||
| 971 | 973 | { |
| 972 | m68ki_cpu_core *m68k = get_safe_token(space->cpu); | |
| 973 | return memory_decrypted_read_word(space, (address) ^ m68k->memory.opcode_xor); | |
| 974 | return m_direct->read_decrypted_word((address) ^ opcode_xor); | |
| 974 | 975 | } |
| 975 | 976 | |
| 976 | ||
| 977 | ||
| 977 | 978 | { |
| 978 | return me | |
| 979 | return m_direct->read_decrypted_ | |
| 979 | 980 | } |
| 980 | 981 | |
| 981 | /* interface for 24-bit address bus, 16-bit data bus (68000, 68010) */ | |
| 982 | static const m68k_memory_interface interface_d16 = | |
| 982 | void m68k_memory_interface::init16(address_space &space) | |
| 983 | 983 | { |
| 984 | 0, | |
| 985 | simple_read_immediate_16, | |
| 986 | memory_read_byte_16be, | |
| 987 | memory_read_word_16be, | |
| 988 | memory_read_dword_16be, | |
| 989 | memory_write_byte_16be, | |
| 990 | memory_write_word_16be, | |
| 991 | memory_write_dword_16be | |
| 992 | }; | |
| 984 | m_space = &space; | |
| 985 | m_direct = &space.direct(); | |
| 986 | m_cpustate = get_safe_token(&space.device()); | |
| 987 | opcode_xor = 0; | |
| 988 | ||
| 989 | readimm16 = m68k_readimm16_delegate(m68k_readimm16_proto_delegate::create_member(m68k_memory_interface, simple_read_immediate_16), *this); | |
| 990 | read8 = m68k_read8_delegate(m68k_read8_proto_delegate::create_member(address_space, read_byte), space); | |
| 991 | read16 = m68k_read16_delegate(m68k_read16_proto_delegate::create_member(address_space, read_word), space); | |
| 992 | read32 = m68k_read32_delegate(m68k_read32_proto_delegate::create_member(address_space, read_dword), space); | |
| 993 | write8 = m68k_write8_delegate(m68k_write8_proto_delegate::create_member(address_space, write_byte), space); | |
| 994 | write16 = m68k_write16_delegate(m68k_write16_proto_delegate::create_member(address_space, write_word), space); | |
| 995 | write32 = m68k_write32_delegate(m68k_write32_proto_delegate::create_member(address_space, write_dword), space); | |
| 996 | } | |
| 993 | 997 | |
| 994 | 998 | /**************************************************************************** |
| 995 | 999 | * 32-bit data memory interface |
| 996 | 1000 | ****************************************************************************/ |
| 997 | 1001 | |
| 998 | 1002 | /* potentially misaligned 16-bit reads with a 32-bit data bus (and 24-bit address bus) */ |
| 999 | ||
| 1003 | ||
| 1000 | 1004 | { |
| 1001 | 1005 | UINT16 result; |
| 1002 | 1006 | |
| 1003 | 1007 | if (!(address & 1)) |
| 1004 | return memory_read_word_32be(space, address); | |
| 1005 | result = memory_read_byte_32be(space, address) << 8; | |
| 1006 | return result | memory_read_byte_32be(space, address + 1); | |
| 1008 | return m_space->read_word(address); | |
| 1009 | result = m_space->read_byte(address) << 8; | |
| 1010 | return result | m_space->read_byte(address + 1); | |
| 1007 | 1011 | } |
| 1008 | 1012 | |
| 1009 | 1013 | /* potentially misaligned 16-bit writes with a 32-bit data bus (and 24-bit address bus) */ |
| 1010 | ||
| 1014 | ||
| 1011 | 1015 | { |
| 1012 | 1016 | if (!(address & 1)) |
| 1013 | 1017 | { |
| 1014 | m | |
| 1018 | m | |
| 1015 | 1019 | return; |
| 1016 | 1020 | } |
| 1017 | memory_write_byte_32be(space, address, data >> 8); | |
| 1018 | memory_write_byte_32be(space, address + 1, data); | |
| 1021 | m_space->write_byte(address, data >> 8); | |
| 1022 | m_space->write_byte(address + 1, data); | |
| 1019 | 1023 | } |
| 1020 | 1024 | |
| 1021 | 1025 | /* potentially misaligned 32-bit reads with a 32-bit data bus (and 24-bit address bus) */ |
| 1022 | ||
| 1026 | ||
| 1023 | 1027 | { |
| 1024 | 1028 | UINT32 result; |
| 1025 | 1029 | |
| 1026 | 1030 | if (!(address & 3)) |
| 1027 | return me | |
| 1031 | return m_space->r | |
| 1028 | 1032 | else if (!(address & 1)) |
| 1029 | 1033 | { |
| 1030 | result = memory_read_word_32be(space, address) << 16; | |
| 1031 | return result | memory_read_word_32be(space, address + 2); | |
| 1034 | result = m_space->read_word(address) << 16; | |
| 1035 | return result | m_space->read_word(address + 2); | |
| 1032 | 1036 | } |
| 1033 | result = memory_read_byte_32be(space, address) << 24; | |
| 1034 | result |= memory_read_word_32be(space, address + 1) << 8; | |
| 1035 | return result | memory_read_byte_32be(space, address + 3); | |
| 1037 | result = m_space->read_byte(address) << 24; | |
| 1038 | result |= m_space->read_word(address + 1) << 8; | |
| 1039 | return result | m_space->read_byte(address + 3); | |
| 1036 | 1040 | } |
| 1037 | 1041 | |
| 1038 | 1042 | /* potentially misaligned 32-bit writes with a 32-bit data bus (and 24-bit address bus) */ |
| 1039 | ||
| 1043 | ||
| 1040 | 1044 | { |
| 1041 | 1045 | if (!(address & 3)) |
| 1042 | 1046 | { |
| 1043 | m | |
| 1047 | m | |
| 1044 | 1048 | return; |
| 1045 | 1049 | } |
| 1046 | 1050 | else if (!(address & 1)) |
| 1047 | 1051 | { |
| 1048 | memory_write_word_32be(space, address, data >> 16); | |
| 1049 | memory_write_word_32be(space, address + 2, data); | |
| 1052 | m_space->write_word(address, data >> 16); | |
| 1053 | m_space->write_word(address + 2, data); | |
| 1050 | 1054 | return; |
| 1051 | 1055 | } |
| 1052 | memory_write_byte_32be(space, address, data >> 24); | |
| 1053 | memory_write_word_32be(space, address + 1, data >> 8); | |
| 1054 | memory_write_byte_32be(space, address + 3, data); | |
| 1056 | m_space->write_byte(address, data >> 24); | |
| 1057 | m_space->write_word(address + 1, data >> 8); | |
| 1058 | m_space->write_byte(address + 3, data); | |
| 1055 | 1059 | } |
| 1056 | 1060 | |
| 1057 | 1061 | /* interface for 32-bit data bus (68EC020, 68020) */ |
| 1058 | ||
| 1062 | vo | |
| 1059 | 1063 | { |
| 1060 | WORD_XOR_BE(0), | |
| 1061 | read_immediate_16, | |
| 1062 | memory_read_byte_32be, | |
| 1063 | readword_d32, | |
| 1064 | readlong_d32, | |
| 1065 | memory_write_byte_32be, | |
| 1066 | writeword_d32, | |
| 1067 | writelong_d32 | |
| 1068 | }; | |
| 1064 | m_space = &space; | |
| 1065 | m_direct = &space.direct(); | |
| 1066 | m_cpustate = get_safe_token(&space.device()); | |
| 1067 | opcode_xor = WORD_XOR_BE(0); | |
| 1068 | ||
| 1069 | readimm16 = m68k_readimm16_delegate(m68k_readimm16_proto_delegate::create_member(m68k_memory_interface, read_immediate_16), *this); | |
| 1070 | read8 = m68k_read8_delegate(m68k_read8_proto_delegate::create_member(address_space, read_byte), space); | |
| 1071 | read16 = m68k_read16_delegate(m68k_read16_proto_delegate::create_member(m68k_memory_interface, readword_d32), *this); | |
| 1072 | read32 = m68k_read32_delegate(m68k_read32_proto_delegate::create_member(m68k_memory_interface, readlong_d32), *this); | |
| 1073 | write8 = m68k_write8_delegate(m68k_write8_proto_delegate::create_member(address_space, write_byte), space); | |
| 1074 | write16 = m68k_write16_delegate(m68k_write16_proto_delegate::create_member(m68k_memory_interface, writeword_d32), *this); | |
| 1075 | write32 = m68k_write32_delegate(m68k_write32_proto_delegate::create_member(m68k_memory_interface, writelong_d32), *this); | |
| 1076 | } | |
| 1069 | 1077 | |
| 1070 | 1078 | /* interface for 32-bit data bus with PMMU (68EC020, 68020) */ |
| 1071 | ||
| 1079 | ||
| 1072 | 1080 | { |
| 1073 | m68ki_cpu_core *m68k = get_safe_token(space->cpu); | |
| 1074 | ||
| 1075 | if (m68k->pmmu_enabled) | |
| 1081 | if (m_cpustate->pmmu_enabled) | |
| 1076 | 1082 | { |
| 1077 | address = pmmu_translate_addr(m | |
| 1083 | address = pmmu_translate_addr(m_cpustate, address); | |
| 1078 | 1084 | } |
| 1079 | 1085 | |
| 1080 | return me | |
| 1086 | return m_space->r | |
| 1081 | 1087 | } |
| 1082 | 1088 | |
| 1083 | ||
| 1089 | ||
| 1084 | 1090 | { |
| 1085 | m68ki_cpu_core *m68k = get_safe_token(space->cpu); | |
| 1086 | ||
| 1087 | if (m68k->pmmu_enabled) | |
| 1091 | if (m_cpustate->pmmu_enabled) | |
| 1088 | 1092 | { |
| 1089 | address = pmmu_translate_addr(m | |
| 1093 | address = pmmu_translate_addr(m_cpustate, address); | |
| 1090 | 1094 | } |
| 1091 | 1095 | |
| 1092 | m | |
| 1096 | m | |
| 1093 | 1097 | } |
| 1094 | 1098 | |
| 1095 | ||
| 1099 | ||
| 1096 | 1100 | { |
| 1097 | m68ki_cpu_core *m68k = get_safe_token(space->cpu); | |
| 1098 | ||
| 1099 | if (m68k->pmmu_enabled) | |
| 1101 | if (m_cpustate->pmmu_enabled) | |
| 1100 | 1102 | { |
| 1101 | address = pmmu_translate_addr(m | |
| 1103 | address = pmmu_translate_addr(m_cpustate, address); | |
| 1102 | 1104 | } |
| 1103 | 1105 | |
| 1104 | return memory_decrypted_read_word(space, (address) ^ m | |
| 1106 | return memory_decrypted_read_word(m_space, (address) ^ m_cpustate->memory.opcode_xor); | |
| 1105 | 1107 | } |
| 1106 | 1108 | |
| 1107 | 1109 | /* potentially misaligned 16-bit reads with a 32-bit data bus (and 24-bit address bus) */ |
| 1108 | ||
| 1110 | ||
| 1109 | 1111 | { |
| 1110 | m68ki_cpu_core *m68k = get_safe_token(space->cpu); | |
| 1111 | 1112 | UINT16 result; |
| 1112 | 1113 | |
| 1113 | if (m | |
| 1114 | if (m_cpustate->pmmu_enabled) | |
| 1114 | 1115 | { |
| 1115 | address = pmmu_translate_addr(m | |
| 1116 | address = pmmu_translate_addr(m_cpustate, address); | |
| 1116 | 1117 | } |
| 1117 | 1118 | |
| 1118 | 1119 | if (!(address & 1)) |
| 1119 | return memory_read_word_32be(space, address); | |
| 1120 | result = memory_read_byte_32be(space, address) << 8; | |
| 1121 | return result | memory_read_byte_32be(space, address + 1); | |
| 1120 | return m_space->read_word(address); | |
| 1121 | result = m_space->read_byte(address) << 8; | |
| 1122 | return result | m_space->read_byte(address + 1); | |
| 1122 | 1123 | } |
| 1123 | 1124 | |
| 1124 | 1125 | /* potentially misaligned 16-bit writes with a 32-bit data bus (and 24-bit address bus) */ |
| 1125 | ||
| 1126 | ||
| 1126 | 1127 | { |
| 1127 | m68ki_cpu_core *m68k = get_safe_token(space->cpu); | |
| 1128 | ||
| 1129 | if (m68k->pmmu_enabled) | |
| 1128 | if (m_cpustate->pmmu_enabled) | |
| 1130 | 1129 | { |
| 1131 | address = pmmu_translate_addr(m | |
| 1130 | address = pmmu_translate_addr(m_cpustate, address); | |
| 1132 | 1131 | } |
| 1133 | 1132 | |
| 1134 | 1133 | if (!(address & 1)) |
| 1135 | 1134 | { |
| 1136 | m | |
| 1135 | m | |
| 1137 | 1136 | return; |
| 1138 | 1137 | } |
| 1139 | memory_write_byte_32be(space, address, data >> 8); | |
| 1140 | memory_write_byte_32be(space, address + 1, data); | |
| 1138 | m_space->write_byte(address, data >> 8); | |
| 1139 | m_space->write_byte(address + 1, data); | |
| 1141 | 1140 | } |
| 1142 | 1141 | |
| 1143 | 1142 | /* potentially misaligned 32-bit reads with a 32-bit data bus (and 24-bit address bus) */ |
| 1144 | ||
| 1143 | ||
| 1145 | 1144 | { |
| 1146 | m68ki_cpu_core *m68k = get_safe_token(space->cpu); | |
| 1147 | 1145 | UINT32 result; |
| 1148 | 1146 | |
| 1149 | if (m | |
| 1147 | if (m_cpustate->pmmu_enabled) | |
| 1150 | 1148 | { |
| 1151 | address = pmmu_translate_addr(m | |
| 1149 | address = pmmu_translate_addr(m_cpustate, address); | |
| 1152 | 1150 | } |
| 1153 | 1151 | |
| 1154 | 1152 | if (!(address & 3)) |
| 1155 | return me | |
| 1153 | return m_space->r | |
| 1156 | 1154 | else if (!(address & 1)) |
| 1157 | 1155 | { |
| 1158 | result = memory_read_word_32be(space, address) << 16; | |
| 1159 | return result | memory_read_word_32be(space, address + 2); | |
| 1156 | result = m_space->read_word(address) << 16; | |
| 1157 | return result | m_space->read_word(address + 2); | |
| 1160 | 1158 | } |
| 1161 | result = memory_read_byte_32be(space, address) << 24; | |
| 1162 | result |= memory_read_word_32be(space, address + 1) << 8; | |
| 1163 | return result | memory_read_byte_32be(space, address + 3); | |
| 1159 | result = m_space->read_byte(address) << 24; | |
| 1160 | result |= m_space->read_word(address + 1) << 8; | |
| 1161 | return result | m_space->read_byte(address + 3); | |
| 1164 | 1162 | } |
| 1165 | 1163 | |
| 1166 | 1164 | /* potentially misaligned 32-bit writes with a 32-bit data bus (and 24-bit address bus) */ |
| 1167 | ||
| 1165 | ||
| 1168 | 1166 | { |
| 1169 | m68ki_cpu_core *m68k = get_safe_token(space->cpu); | |
| 1170 | ||
| 1171 | if (m68k->pmmu_enabled) | |
| 1167 | if (m_cpustate->pmmu_enabled) | |
| 1172 | 1168 | { |
| 1173 | address = pmmu_translate_addr(m | |
| 1169 | address = pmmu_translate_addr(m_cpustate, address); | |
| 1174 | 1170 | } |
| 1175 | 1171 | |
| 1176 | 1172 | if (!(address & 3)) |
| 1177 | 1173 | { |
| 1178 | m | |
| 1174 | m | |
| 1179 | 1175 | return; |
| 1180 | 1176 | } |
| 1181 | 1177 | else if (!(address & 1)) |
| 1182 | 1178 | { |
| 1183 | memory_write_word_32be(space, address, data >> 16); | |
| 1184 | memory_write_word_32be(space, address + 2, data); | |
| 1179 | m_space->write_word(address, data >> 16); | |
| 1180 | m_space->write_word(address + 2, data); | |
| 1185 | 1181 | return; |
| 1186 | 1182 | } |
| 1187 | memory_write_byte_32be(space, address, data >> 24); | |
| 1188 | memory_write_word_32be(space, address + 1, data >> 8); | |
| 1189 | memory_write_byte_32be(space, address + 3, data); | |
| 1183 | m_space->write_byte(address, data >> 24); | |
| 1184 | m_space->write_word(address + 1, data >> 8); | |
| 1185 | m_space->write_byte(address + 3, data); | |
| 1190 | 1186 | } |
| 1191 | 1187 | |
| 1192 | ||
| 1188 | vo | |
| 1193 | 1189 | { |
| 1194 | WORD_XOR_BE(0), | |
| 1195 | read_immediate_16_mmu, | |
| 1196 | read_byte_32_mmu, | |
| 1197 | readword_d32_mmu, | |
| 1198 | readlong_d32_mmu, | |
| 1199 | write_byte_32_mmu, | |
| 1200 | writeword_d32_mmu, | |
| 1201 | writelong_d32_mmu | |
| 1202 | }; | |
| 1190 | m_space = &space; | |
| 1191 | m_direct = &space.direct(); | |
| 1192 | m_cpustate = get_safe_token(&space.device()); | |
| 1193 | opcode_xor = WORD_XOR_BE(0); | |
| 1194 | ||
| 1195 | readimm16 = m68k_readimm16_delegate(m68k_readimm16_proto_delegate::create_member(m68k_memory_interface, read_immediate_16_mmu), *this); | |
| 1196 | read8 = m68k_read8_delegate(m68k_read8_proto_delegate::create_member(m68k_memory_interface, read_byte_32_mmu), *this); | |
| 1197 | read16 = m68k_read16_delegate(m68k_read16_proto_delegate::create_member(m68k_memory_interface, readword_d32_mmu), *this); | |
| 1198 | read32 = m68k_read32_delegate(m68k_read32_proto_delegate::create_member(m68k_memory_interface, readlong_d32_mmu), *this); | |
| 1199 | write8 = m68k_write8_delegate(m68k_write8_proto_delegate::create_member(m68k_memory_interface, write_byte_32_mmu), *this); | |
| 1200 | write16 = m68k_write16_delegate(m68k_write16_proto_delegate::create_member(m68k_memory_interface, writeword_d32_mmu), *this); | |
| 1201 | write32 = m68k_write32_delegate(m68k_write32_proto_delegate::create_member(m68k_memory_interface, writelong_d32_mmu), *this); | |
| 1202 | } | |
| 1203 | 1203 | |
| 1204 | 1204 | |
| 1205 | 1205 | void m68k_set_reset_callback(running_device *device, m68k_reset_func callback) |
| r8806 | r8807 | |
| 1294 | 1294 | |
| 1295 | 1295 | m68k->cpu_type = CPU_TYPE_000; |
| 1296 | 1296 | m68k->dasm_type = M68K_CPU_TYPE_68000; |
| 1297 | m68k->memory = interface_d16; | |
| 1297 | // hack alert: we use placement new to ensure we are properly initialized | |
| 1298 | // because we live in the device state which is allocated as bytes | |
| 1299 | // remove me when we have a real C++ device | |
| 1300 | new(&m68k->memory) m68k_memory_interface; | |
| 1301 | m68k->memory.init16(*m68k->program); | |
| 1298 | 1302 | m68k->sr_mask = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */ |
| 1299 | 1303 | m68k->cyc_instruction = m68ki_cycles[0]; |
| 1300 | 1304 | m68k->cyc_exception = m68ki_exception_cycle_table[0]; |
| r8806 | r8807 | |
| 1339 | 1343 | |
| 1340 | 1344 | m68k->cpu_type = CPU_TYPE_008; |
| 1341 | 1345 | m68k->dasm_type = M68K_CPU_TYPE_68008; |
| 1342 | m68k->memory = interface_d8; | |
| 1346 | // hack alert: we use placement new to ensure we are properly initialized | |
| 1347 | // because we live in the device state which is allocated as bytes | |
| 1348 | // remove me when we have a real C++ device | |
| 1349 | new(&m68k->memory) m68k_memory_interface; | |
| 1350 | m68k->memory.init8(*m68k->program); | |
| 1343 | 1351 | m68k->sr_mask = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */ |
| 1344 | 1352 | m68k->cyc_instruction = m68ki_cycles[0]; |
| 1345 | 1353 | m68k->cyc_exception = m68ki_exception_cycle_table[0]; |
| r8806 | r8807 | |
| 1388 | 1396 | |
| 1389 | 1397 | m68k->cpu_type = CPU_TYPE_010; |
| 1390 | 1398 | m68k->dasm_type = M68K_CPU_TYPE_68010; |
| 1391 | m68k->memory = interface_d16; | |
| 1399 | // hack alert: we use placement new to ensure we are properly initialized | |
| 1400 | // because we live in the device state which is allocated as bytes | |
| 1401 | // remove me when we have a real C++ device | |
| 1402 | new(&m68k->memory) m68k_memory_interface; | |
| 1403 | m68k->memory.init16(*m68k->program); | |
| 1392 | 1404 | m68k->sr_mask = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */ |
| 1393 | 1405 | m68k->cyc_instruction = m68ki_cycles[1]; |
| 1394 | 1406 | m68k->cyc_exception = m68ki_exception_cycle_table[1]; |
| r8806 | r8807 | |
| 1433 | 1445 | |
| 1434 | 1446 | m68k->cpu_type = CPU_TYPE_020; |
| 1435 | 1447 | m68k->dasm_type = M68K_CPU_TYPE_68020; |
| 1436 | m68k->memory = interface_d32; | |
| 1448 | // hack alert: we use placement new to ensure we are properly initialized | |
| 1449 | // because we live in the device state which is allocated as bytes | |
| 1450 | // remove me when we have a real C++ device | |
| 1451 | new(&m68k->memory) m68k_memory_interface; | |
| 1452 | m68k->memory.init32(*m68k->program); | |
| 1437 | 1453 | m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ |
| 1438 | 1454 | m68k->cyc_instruction = m68ki_cycles[2]; |
| 1439 | 1455 | m68k->cyc_exception = m68ki_exception_cycle_table[2]; |
| r8806 | r8807 | |
| 1481 | 1497 | CPU_INIT_CALL(m68020); |
| 1482 | 1498 | |
| 1483 | 1499 | m68k->has_pmmu = 1; |
| 1484 | m68k->memory = interface_d32_mmu; | |
| 1500 | // hack alert: we use placement new to ensure we are properly initialized | |
| 1501 | // because we live in the device state which is allocated as bytes | |
| 1502 | // remove me when we have a real C++ device | |
| 1503 | new(&m68k->memory) m68k_memory_interface; | |
| 1504 | m68k->memory.init32mmu(*m68k->program); | |
| 1485 | 1505 | } |
| 1486 | 1506 | |
| 1487 | 1507 | CPU_GET_INFO( m68020pmmu ) |
| r8806 | r8807 | |
| 1510 | 1530 | |
| 1511 | 1531 | m68k->cpu_type = CPU_TYPE_EC020; |
| 1512 | 1532 | m68k->dasm_type = M68K_CPU_TYPE_68EC020; |
| 1513 | m68k->memory = interface_d32; | |
| 1533 | // hack alert: we use placement new to ensure we are properly initialized | |
| 1534 | // because we live in the device state which is allocated as bytes | |
| 1535 | // remove me when we have a real C++ device | |
| 1536 | new(&m68k->memory) m68k_memory_interface; | |
| 1537 | m68k->memory.init32(*m68k->program); | |
| 1514 | 1538 | m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ |
| 1515 | 1539 | m68k->cyc_instruction = m68ki_cycles[2]; |
| 1516 | 1540 | m68k->cyc_exception = m68ki_exception_cycle_table[2]; |
| r8806 | r8807 | |
| 1557 | 1581 | |
| 1558 | 1582 | m68k->cpu_type = CPU_TYPE_030; |
| 1559 | 1583 | m68k->dasm_type = M68K_CPU_TYPE_68030; |
| 1560 | m68k->memory = interface_d32_mmu; | |
| 1584 | // hack alert: we use placement new to ensure we are properly initialized | |
| 1585 | // because we live in the device state which is allocated as bytes | |
| 1586 | // remove me when we have a real C++ device | |
| 1587 | new(&m68k->memory) m68k_memory_interface; | |
| 1588 | m68k->memory.init32mmu(*m68k->program); | |
| 1561 | 1589 | m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ |
| 1562 | 1590 | m68k->cyc_instruction = m68ki_cycles[3]; |
| 1563 | 1591 | m68k->cyc_exception = m68ki_exception_cycle_table[3]; |
| r8806 | r8807 | |
| 1610 | 1638 | |
| 1611 | 1639 | m68k->cpu_type = CPU_TYPE_EC030; |
| 1612 | 1640 | m68k->dasm_type = M68K_CPU_TYPE_68EC030; |
| 1613 | m68k->memory = interface_d32; | |
| 1641 | // hack alert: we use placement new to ensure we are properly initialized | |
| 1642 | // because we live in the device state which is allocated as bytes | |
| 1643 | // remove me when we have a real C++ device | |
| 1644 | new(&m68k->memory) m68k_memory_interface; | |
| 1645 | m68k->memory.init32(*m68k->program); | |
| 1614 | 1646 | m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ |
| 1615 | 1647 | m68k->cyc_instruction = m68ki_cycles[3]; |
| 1616 | 1648 | m68k->cyc_exception = m68ki_exception_cycle_table[3]; |
| r8806 | r8807 | |
| 1654 | 1686 | |
| 1655 | 1687 | m68k->cpu_type = CPU_TYPE_040; |
| 1656 | 1688 | m68k->dasm_type = M68K_CPU_TYPE_68040; |
| 1657 | m68k->memory = interface_d32_mmu; | |
| 1689 | // hack alert: we use placement new to ensure we are properly initialized | |
| 1690 | // because we live in the device state which is allocated as bytes | |
| 1691 | // remove me when we have a real C++ device | |
| 1692 | new(&m68k->memory) m68k_memory_interface; | |
| 1693 | m68k->memory.init32mmu(*m68k->program); | |
| 1658 | 1694 | m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ |
| 1659 | 1695 | m68k->cyc_instruction = m68ki_cycles[4]; |
| 1660 | 1696 | m68k->cyc_exception = m68ki_exception_cycle_table[4]; |
| r8806 | r8807 | |
| 1706 | 1742 | |
| 1707 | 1743 | m68k->cpu_type = CPU_TYPE_EC040; |
| 1708 | 1744 | m68k->dasm_type = M68K_CPU_TYPE_68EC040; |
| 1709 | m68k->memory = interface_d32; | |
| 1745 | // hack alert: we use placement new to ensure we are properly initialized | |
| 1746 | // because we live in the device state which is allocated as bytes | |
| 1747 | // remove me when we have a real C++ device | |
| 1748 | new(&m68k->memory) m68k_memory_interface; | |
| 1749 | m68k->memory.init32(*m68k->program); | |
| 1710 | 1750 | m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ |
| 1711 | 1751 | m68k->cyc_instruction = m68ki_cycles[4]; |
| 1712 | 1752 | m68k->cyc_exception = m68ki_exception_cycle_table[4]; |
| r8806 | r8807 | |
| 1750 | 1790 | |
| 1751 | 1791 | m68k->cpu_type = CPU_TYPE_LC040; |
| 1752 | 1792 | m68k->dasm_type = M68K_CPU_TYPE_68LC040; |
| 1753 | m68k->memory = interface_d32; | |
| 1793 | // hack alert: we use placement new to ensure we are properly initialized | |
| 1794 | // because we live in the device state which is allocated as bytes | |
| 1795 | // remove me when we have a real C++ device | |
| 1796 | new(&m68k->memory) m68k_memory_interface; | |
| 1797 | m68k->memory.init32(*m68k->program); | |
| 1754 | 1798 | m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ |
| 1755 | 1799 | m68k->cyc_instruction = m68ki_cycles[4]; |
| 1756 | 1800 | m68k->cyc_exception = m68ki_exception_cycle_table[4]; |
| r8806 | r8807 | |
|---|---|---|
| 22 | 22 | MEMORY I/O MACROS |
| 23 | 23 | ***************************************************************************/ |
| 24 | 24 | |
| 25 | #define TMS34010_RDMEM(T,A) ((unsigned)memory_read_byte_16le ((T)->program, A)) | |
| 26 | #define TMS34010_RDMEM_WORD(T,A) ((unsigned)memory_read_word_16le ((T)->program, A)) | |
| 25 | #define TMS34010_RDMEM(T,A) ((unsigned)(T)->program->read_byte (A)) | |
| 26 | #define TMS34010_RDMEM_WORD(T,A) ((unsigned)(T)->program->read_word (A)) | |
| 27 | 27 | INLINE UINT32 TMS34010_RDMEM_DWORD(tms34010_state *tms, offs_t A) |
| 28 | 28 | { |
| 29 | UINT32 result = memory_read_word_16le(tms->program, A); | |
| 30 | return result | (memory_read_word_16le(tms->program, A+2)<<16); | |
| 29 | UINT32 result = tms->program->read_word(A); | |
| 30 | return result | (tms->program->read_word(A+2)<<16); | |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | #define TMS34010_WRMEM(T,A,V) (memory_write_byte_16le((T)->program, A,V)) | |
| 34 | #define TMS34010_WRMEM_WORD(T,A,V) (memory_write_word_16le((T)->program, A,V)) | |
| 33 | #define TMS34010_WRMEM(T,A,V) ((T)->program->write_byte(A,V)) | |
| 34 | #define TMS34010_WRMEM_WORD(T,A,V) ((T)->program->write_word(A,V)) | |
| 35 | 35 | INLINE void TMS34010_WRMEM_DWORD(tms34010_state *tms, offs_t A,UINT32 V) |
| 36 | 36 | { |
| 37 | memory_write_word_16le(tms->program, A,V); | |
| 38 | memory_write_word_16le(tms->program, A+2,V>>16); | |
| 37 | tms->program->write_word(A,V); | |
| 38 | tms->program->write_word(A+2,V>>16); | |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | 41 |
| r8806 | r8807 | |
|---|---|---|
| 198 | 198 | int pixperclock; /* pixels per clock */ |
| 199 | 199 | void (*scanline_callback)(screen_device &screen, bitmap_t *bitmap, int scanline, const tms34010_display_params *params); |
| 200 | 200 | void (*output_int)(running_device *device, int state); /* output interrupt callback */ |
| 201 | void (*to_shiftreg)(const address_space *space, offs_t, UINT16 *); /* shift register write */ | |
| 202 | void (*from_shiftreg)(const address_space *space, offs_t, UINT16 *); /* shift register read */ | |
| 201 | void (*to_shiftreg)(address_space *space, offs_t, UINT16 *); /* shift register write */ | |
| 202 | void (*from_shiftreg)(address_space *space, offs_t, UINT16 *); /* shift register read */ | |
| 203 | 203 | }; |
| 204 | 204 | |
| 205 | 205 |
| r8806 | r8807 | |
|---|---|---|
| 63 | 63 | UINT8 executing; |
| 64 | 64 | device_irq_callback irq_callback; |
| 65 | 65 | legacy_cpu_device *device; |
| 66 | | |
| 66 | | |
| 67 | 67 | const tms34010_config *config; |
| 68 | 68 | screen_device *screen; |
| 69 | 69 | emu_timer * scantimer; |
| r8806 | r8807 | |
| 1556 | 1556 | |
| 1557 | 1557 | void tms34010_host_w(running_device *cpu, int reg, int data) |
| 1558 | 1558 | { |
| 1559 | | |
| 1559 | | |
| 1560 | 1560 | tms34010_state *tms = get_safe_token(cpu); |
| 1561 | 1561 | unsigned int addr; |
| 1562 | 1562 |
| r8806 | r8807 | |
|---|---|---|
| 201 | 201 | |
| 202 | 202 | |
| 203 | 203 | /* Shift register handling */ |
| 204 | static void | |
| 204 | static void m | |
| 205 | 205 | { |
| 206 | space->write_word(offset, data); | |
| 207 | } | |
| 208 | ||
| 209 | static UINT16 memory_r(address_space *space, offs_t offset) | |
| 210 | { | |
| 211 | return space->read_word(offset); | |
| 212 | } | |
| 213 | ||
| 214 | static void shiftreg_w(address_space *space, offs_t offset,UINT16 data) | |
| 215 | { | |
| 206 | 216 | tms34010_state *tms = get_safe_token(space->cpu); |
| 207 | 217 | if (tms->config->from_shiftreg) |
| 208 | 218 | (*tms->config->from_shiftreg)(space, (UINT32)(offset << 3) & ~15, &tms->shiftreg[0]); |
| r8806 | r8807 | |
| 210 | 220 | logerror("From ShiftReg function not set. PC = %08X\n", tms->pc); |
| 211 | 221 | } |
| 212 | 222 | |
| 213 | static UINT16 shiftreg_r( | |
| 223 | static UINT16 shiftreg_r( | |
| 214 | 224 | { |
| 215 | 225 | tms34010_state *tms = get_safe_token(space->cpu); |
| 216 | 226 | if (tms->config->to_shiftreg) |
| r8806 | r8807 | |
| 220 | 230 | return tms->shiftreg[0]; |
| 221 | 231 | } |
| 222 | 232 | |
| 223 | static UINT16 dummy_shiftreg_r( | |
| 233 | static UINT16 dummy_shiftreg_r( | |
| 224 | 234 | { |
| 225 | 235 | tms34010_state *tms = get_safe_token(space->cpu); |
| 226 | 236 | return tms->shiftreg[0]; |
| r8806 | r8807 | |
| 1028 | 1038 | if (!P_FLAG(tms)) |
| 1029 | 1039 | { |
| 1030 | 1040 | int dx, dy, x, y, /*words,*/ yreverse; |
| 1031 | void (*word_write)(const address_space *space,offs_t address,UINT16 data); | |
| 1032 | UINT16 (*word_read)(const address_space *space,offs_t address); | |
| 1041 | void (*word_write)(address_space *space,offs_t address,UINT16 data); | |
| 1042 | UINT16 (*word_read)(address_space *space,offs_t address); | |
| 1033 | 1043 | UINT32 readwrites = 0; |
| 1034 | 1044 | UINT32 saddr, daddr; |
| 1035 | 1045 | XY dstxy = { 0 }; |
| r8806 | r8807 | |
| 1042 | 1052 | } |
| 1043 | 1053 | else |
| 1044 | 1054 | { |
| 1045 | word_write = memory_write_word_16le; | |
| 1046 | word_read = memory_read_word_16le; | |
| 1055 | word_write = memory_w; | |
| 1056 | word_read = memory_r; | |
| 1047 | 1057 | } |
| 1048 | 1058 | |
| 1049 | 1059 | /* compute the starting addresses */ |
| r8806 | r8807 | |
| 1375 | 1385 | if (!P_FLAG(tms)) |
| 1376 | 1386 | { |
| 1377 | 1387 | int dx, dy, x, y, words, yreverse; |
| 1378 | void (*word_write)(const address_space *space,offs_t address,UINT16 data); | |
| 1379 | UINT16 (*word_read)(const address_space *space,offs_t address); | |
| 1388 | void (*word_write)(address_space *space,offs_t address,UINT16 data); | |
| 1389 | UINT16 (*word_read)(address_space *space,offs_t address); | |
| 1380 | 1390 | UINT32 saddr, daddr; |
| 1381 | 1391 | XY dstxy = { 0 }; |
| 1382 | 1392 | |
| r8806 | r8807 | |
| 1388 | 1398 | } |
| 1389 | 1399 | else |
| 1390 | 1400 | { |
| 1391 | word_write = memory_write_word_16le; | |
| 1392 | word_read = memory_read_word_16le; | |
| 1401 | word_write = memory_w; | |
| 1402 | word_read = memory_r; | |
| 1393 | 1403 | } |
| 1394 | 1404 | |
| 1395 | 1405 | /* compute the starting addresses */ |
| r8806 | r8807 | |
| 1640 | 1650 | if (!P_FLAG(tms)) |
| 1641 | 1651 | { |
| 1642 | 1652 | int dx, dy, x, y, words, left_partials, right_partials, full_words; |
| 1643 | void (*word_write)(const address_space *space,offs_t address,UINT16 data); | |
| 1644 | UINT16 (*word_read)(const address_space *space,offs_t address); | |
| 1653 | void (*word_write)(address_space *space,offs_t address,UINT16 data); | |
| 1654 | UINT16 (*word_read)(address_space *space,offs_t address); | |
| 1645 | 1655 | UINT32 saddr, daddr; |
| 1646 | 1656 | XY dstxy = { 0 }; |
| 1647 | 1657 | |
| r8806 | r8807 | |
| 1653 | 1663 | } |
| 1654 | 1664 | else |
| 1655 | 1665 | { |
| 1656 | word_write = memory_write_word_16le; | |
| 1657 | word_read = memory_read_word_16le; | |
| 1666 | word_write = memory_w; | |
| 1667 | word_read = memory_r; | |
| 1658 | 1668 | } |
| 1659 | 1669 | |
| 1660 | 1670 | /* compute the starting addresses */ |
| r8806 | r8807 | |
| 1854 | 1864 | if (!P_FLAG(tms)) |
| 1855 | 1865 | { |
| 1856 | 1866 | int dx, dy, x, y, words, left_partials, right_partials, full_words; |
| 1857 | void (*word_write)(const address_space *space,offs_t address,UINT16 data); | |
| 1858 | UINT16 (*word_read)(const address_space *space,offs_t address); | |
| 1867 | void (*word_write)(address_space *space,offs_t address,UINT16 data); | |
| 1868 | UINT16 (*word_read)(address_space *space,offs_t address); | |
| 1859 | 1869 | UINT32 daddr; |
| 1860 | 1870 | XY dstxy = { 0 }; |
| 1861 | 1871 | |
| r8806 | r8807 | |
| 1867 | 1877 | } |
| 1868 | 1878 | else |
| 1869 | 1879 | { |
| 1870 | word_write = memory_write_word_16le; | |
| 1871 | word_read = memory_read_word_16le; | |
| 1880 | word_write = memory_w; | |
| 1881 | word_read = memory_r; | |
| 1872 | 1882 | } |
| 1873 | 1883 | |
| 1874 | 1884 | /* compute the bounds of the operation */ |
| r8806 | r8807 | |
|---|---|---|
| 120 | 120 | tms32031_iack_func iack_w; |
| 121 | 121 | device_irq_callback irq_callback; |
| 122 | 122 | legacy_cpu_device *device; |
| 123 | | |
| 123 | | |
| 124 | 124 | }; |
| 125 | 125 | |
| 126 | 126 | INLINE tms32031_state *get_safe_token(running_device *device) |
| r8806 | r8807 | |
| 148 | 148 | |
| 149 | 149 | #define ROPCODE(T,pc) memory_decrypted_read_dword((T)->program, (pc) << 2) |
| 150 | 150 | |
| 151 | #define RMEM(T,addr) memory_read_dword_32le((T)->program, (addr) << 2) | |
| 152 | #define WMEM(T,addr,data) memory_write_dword_32le((T)->program, (addr) << 2, data) | |
| 151 | #define RMEM(T,addr) (T)->program->read_dword((addr) << 2) | |
| 152 | #define WMEM(T,addr,data) (T)->program->write_dword((addr) << 2, data) | |
| 153 | 153 | |
| 154 | 154 | |
| 155 | 155 |
| r8806 | r8807 | |
|---|---|---|
| 62 | 62 | pixelcache_t pixelcache[2]; |
| 63 | 63 | |
| 64 | 64 | legacy_cpu_device *device; |
| 65 | | |
| 65 | | |
| 66 | 66 | int icount; |
| 67 | 67 | }; |
| 68 | 68 | |
| r8806 | r8807 | |
| 179 | 179 | |
| 180 | 180 | INLINE UINT8 superfx_bus_read(superfx_state *cpustate, UINT32 addr) |
| 181 | 181 | { |
| 182 | return | |
| 182 | return | |
| 183 | 183 | } |
| 184 | 184 | |
| 185 | 185 | INLINE void superfx_bus_write(superfx_state *cpustate, UINT32 addr, UINT8 data) |
| 186 | 186 | { |
| 187 | | |
| 187 | | |
| 188 | 188 | } |
| 189 | 189 | |
| 190 | 190 | INLINE void superfx_pixelcache_flush(superfx_state *cpustate, INT32 line) |
| r8806 | r8807 | |
|---|---|---|
| 405 | 405 | switch (offset) |
| 406 | 406 | { |
| 407 | 407 | case 2: // p0 |
| 408 | return | |
| 408 | return | |
| 409 | 409 | case 3: // p1 |
| 410 | return | |
| 410 | return | |
| 411 | 411 | case 6: // p2 |
| 412 | return | |
| 412 | return | |
| 413 | 413 | case 7: // p3 |
| 414 | return | |
| 414 | return | |
| 415 | 415 | case 0xa: // p4 |
| 416 | return | |
| 416 | return | |
| 417 | 417 | case 0xb: // p5 |
| 418 | return | |
| 418 | return | |
| 419 | 419 | case 0xe: // p6 |
| 420 | return | |
| 420 | return | |
| 421 | 421 | case 0xf: // p7 |
| 422 | return | |
| 422 | return | |
| 423 | 423 | case 0x12: // p8 |
| 424 | return | |
| 424 | return | |
| 425 | 425 | |
| 426 | 426 | case 0x20: |
| 427 | return | |
| 427 | return | |
| 428 | 428 | case 0x21: |
| 429 | return | |
| 429 | return | |
| 430 | 430 | case 0x22: |
| 431 | return | |
| 431 | return | |
| 432 | 432 | case 0x23: |
| 433 | return | |
| 433 | return | |
| 434 | 434 | case 0x24: |
| 435 | return | |
| 435 | return | |
| 436 | 436 | case 0x25: |
| 437 | return | |
| 437 | return | |
| 438 | 438 | case 0x26: |
| 439 | return | |
| 439 | return | |
| 440 | 440 | case 0x27: |
| 441 | return | |
| 441 | return | |
| 442 | 442 | case 0x28: |
| 443 | return | |
| 443 | return | |
| 444 | 444 | case 0x29: |
| 445 | return | |
| 445 | return | |
| 446 | 446 | case 0x2a: |
| 447 | return | |
| 447 | return | |
| 448 | 448 | case 0x2b: |
| 449 | return | |
| 449 | return | |
| 450 | 450 | case 0x2c: |
| 451 | return | |
| 451 | return | |
| 452 | 452 | case 0x2d: |
| 453 | return | |
| 453 | return | |
| 454 | 454 | case 0x2e: |
| 455 | return | |
| 455 | return | |
| 456 | 456 | case 0x2f: |
| 457 | return | |
| 457 | return | |
| 458 | 458 | case 0x35: |
| 459 | 459 | return 0xff; // UART control |
| 460 | 460 | |
| r8806 | r8807 | |
| 472 | 472 | switch(offset) |
| 473 | 473 | { |
| 474 | 474 | case 2: // p0 |
| 475 | | |
| 475 | cpustate->io-> | |
| 476 | 476 | return; |
| 477 | 477 | case 3: // p1 |
| 478 | | |
| 478 | cpustate->io-> | |
| 479 | 479 | return; |
| 480 | 480 | case 6: // p2 |
| 481 | | |
| 481 | cpustate->io-> | |
| 482 | 482 | return; |
| 483 | 483 | case 7: // p3 |
| 484 | | |
| 484 | cpustate->io-> | |
| 485 | 485 | return; |
| 486 | 486 | case 0xa: // p4 |
| 487 | | |
| 487 | cpustate->io-> | |
| 488 | 488 | return; |
| 489 | 489 | case 0xb: // p5 |
| 490 | | |
| 490 | cpustate->io-> | |
| 491 | 491 | return; |
| 492 | 492 | case 0xe: // p6 |
| 493 | | |
| 493 | cpustate->io-> | |
| 494 | 494 | return; |
| 495 | 495 | case 0xf: // p7 |
| 496 | | |
| 496 | cpustate->io-> | |
| 497 | 497 | return; |
| 498 | 498 | case 0x12: // p8 |
| 499 | | |
| 499 | cpustate->io-> | |
| 500 | 500 | return; |
| 501 | 501 | |
| 502 | 502 | case 0x40: // count start |
| r8806 | r8807 | |
|---|---|---|
| 22 | 22 | #undef M37710_CALL_DEBUGGER |
| 23 | 23 | |
| 24 | 24 | #define M37710_CALL_DEBUGGER(x) debugger_instruction_hook(cpustate->device, x) |
| 25 | #define m37710_read_8(addr) memory_read_byte_16le(cpustate->program, addr) | |
| 26 | #define m37710_write_8(addr,data) memory_write_byte_16le(cpustate->program, addr,data) | |
| 27 | #define m37710_read_8_immediate(A) memory_read_byte_16le(cpustate->program, A) | |
| 28 | #define m37710_read_16(addr) memory_read_word_16le(cpustate->program, addr) | |
| 29 | #define m37710_write_16(addr,data) memory_write_word_16le(cpustate->program, addr,data) | |
| 25 | #define m37710_read_8(addr) cpustate->program->read_byte(addr) | |
| 26 | #define m37710_write_8(addr,data) cpustate->program->write_byte(addr,data) | |
| 27 | #define m37710_read_8_immediate(A) cpustate->program->read_byte(A) | |
| 28 | #define m37710_read_16(addr) cpustate->program->read_word(addr) | |
| 29 | #define m37710_write_16(addr,data) cpustate->program->write_word(addr,data) | |
| 30 | 30 | #define m37710_jumping(A) |
| 31 | 31 | #define m37710_branching(A) |
| 32 | 32 | |
| r8806 | r8807 | |
| 110 | 110 | uint destination; /* temp register */ |
| 111 | 111 | device_irq_callback int_ack; |
| 112 | 112 | legacy_cpu_device *device; |
| 113 | const address_space *program; | |
| 114 | const address_space *io; | |
| 113 | address_space *program; | |
| 114 | address_space *io; | |
| 115 | 115 | uint stopped; /* Sets how the CPU is stopped */ |
| 116 | 116 | void (*const *opcodes)(m37710i_cpu_struct *cpustate); /* opcodes with no prefix */ |
| 117 | 117 | void (*const *opcodes42)(m37710i_cpu_struct *cpustate); /* opcodes with 0x42 prefix */ |
| r8806 | r8807 | |
|---|---|---|
| 154 | 154 | int icount; |
| 155 | 155 | |
| 156 | 156 | /* Memory spaces */ |
| 157 | const address_space *program; | |
| 158 | const address_space *data; | |
| 159 | const address_space *io; | |
| 157 | address_space *program; | |
| 158 | address_space *data; | |
| 159 | address_space *io; | |
| 160 | 160 | |
| 161 | 161 | UINT8 feature_mask; /* processor feature flags */ |
| 162 | 162 | UINT16 int_rom_size; /* internal rom size */ |
| r8806 | r8807 | |
| 175 | 175 | ***************************************************************************/ |
| 176 | 176 | |
| 177 | 177 | /* ROM is mapped to ADDRESS_SPACE_PROGRAM */ |
| 178 | #define program_r(a) | |
| 178 | #define program_r(a) | |
| 179 | 179 | |
| 180 | 180 | /* RAM is mapped to ADDRESS_SPACE_DATA */ |
| 181 | #define ram_r(a) memory_read_byte_8le(cpustate->data, a) | |
| 182 | #define ram_w(a,V) memory_write_byte_8le(cpustate->data, a, V) | |
| 181 | #define ram_r(a) cpustate->data->read_byte(a) | |
| 182 | #define ram_w(a,V) cpustate->data->write_byte(a, V) | |
| 183 | 183 | |
| 184 | 184 | /* ports are mapped to ADDRESS_SPACE_IO */ |
| 185 | #define ext_r(a) memory_read_byte_8le(cpustate->io, a) | |
| 186 | #define ext_w(a,V) memory_write_byte_8le(cpustate->io, a, V) | |
| 187 | #define port_r(a) memory_read_byte_8le(cpustate->io, MCS48_PORT_P0 + a) | |
| 188 | #define port_w(a,V) memory_write_byte_8le(cpustate->io, MCS48_PORT_P0 + a, V) | |
| 189 | #define test_r(a) memory_read_byte_8le(cpustate->io, MCS48_PORT_T0 + a) | |
| 190 | #define test_w(a,V) memory_write_byte_8le(cpustate->io, MCS48_PORT_T0 + a, V) | |
| 191 | #define bus_r() memory_read_byte_8le(cpustate->io, MCS48_PORT_BUS) | |
| 192 | #define bus_w(V) memory_write_byte_8le(cpustate->io, MCS48_PORT_BUS, V) | |
| 193 | #define ea_r() memory_read_byte_8le(cpustate->io, MCS48_PORT_EA) | |
| 194 | #define prog_w(V) memory_write_byte_8le(cpustate->io, MCS48_PORT_PROG, V) | |
| 185 | #define ext_r(a) cpustate->io->read_byte(a) | |
| 186 | #define ext_w(a,V) cpustate->io->write_byte(a, V) | |
| 187 | #define port_r(a) cpustate->io->read_byte(MCS48_PORT_P0 + a) | |
| 188 | #define port_w(a,V) cpustate->io->write_byte(MCS48_PORT_P0 + a, V) | |
| 189 | #define test_r(a) cpustate->io->read_byte(MCS48_PORT_T0 + a) | |
| 190 | #define test_w(a,V) cpustate->io->write_byte(MCS48_PORT_T0 + a, V) | |
| 191 | #define bus_r() cpustate->io->read_byte(MCS48_PORT_BUS) | |
| 192 | #define bus_w(V) cpustate->io->write_byte(MCS48_PORT_BUS, V) | |
| 193 | #define ea_r() cpustate->io->read_byte(MCS48_PORT_EA) | |
| 194 | #define prog_w(V) cpustate->io->write_byte(MCS48_PORT_PROG, V) | |
| 195 | 195 | |
| 196 | 196 | /* r0-r7 map to memory via the regptr */ |
| 197 | 197 | #define R0 regptr[0] |
| r8806 | r8807 | |
|---|---|---|
| 153 | 153 | } |
| 154 | 154 | } |
| 155 | 155 | |
| 156 | return | |
| 156 | return | |
| 157 | 157 | } |
| 158 | 158 | |
| 159 | 159 | static void dm_write32(SHARC_REGS *cpustate, UINT32 address, UINT32 data) |
| r8806 | r8807 | |
| 198 | 198 | return; |
| 199 | 199 | } |
| 200 | 200 | |
| 201 | | |
| 201 | | |
| 202 | 202 | } |
| r8806 | r8807 | |
|---|---|---|
| 126 | 126 | |
| 127 | 127 | device_irq_callback irq_callback; |
| 128 | 128 | legacy_cpu_device *device; |
| 129 | const address_space *program; | |
| 130 | const address_space *data; | |
| 129 | address_space *program; | |
| 130 | address_space *data; | |
| 131 | 131 | void (*opcode_handler)(SHARC_REGS *cpustate); |
| 132 | 132 | int icount; |
| 133 | 133 | UINT64 opcode; |
| r8806 | r8807 | |
|---|---|---|
| 104 | 104 | |
| 105 | 105 | cd cache; |
| 106 | 106 | |
| 107 | | |
| 107 | | |
| 108 | 108 | int icount; |
| 109 | 109 | int unsupported_inst_warning; |
| 110 | 110 | } tms57002_t; |
| r8806 | r8807 | |
| 192 | 192 | s->sti = (s->sti & ~SU_MASK) | SU_PRG; |
| 193 | 193 | break; |
| 194 | 194 | case SU_PRG: |
| 195 | | |
| 195 | s->program->write_dword | |
| 196 | 196 | break; |
| 197 | 197 | } |
| 198 | 198 | } |
| r8806 | r8807 | |
| 391 | 391 | static void tms57002_xm_step_read(tms57002_t *s) |
| 392 | 392 | { |
| 393 | 393 | UINT32 adr = s->xm_adr; |
| 394 | UINT8 v = | |
| 394 | UINT8 v = s->data->r | |
| 395 | 395 | int done; |
| 396 | 396 | if(s->st0 & ST0_WORD) { |
| 397 | 397 | if(s->st0 & ST0_SEL) { |
| r8806 | r8807 | |
| 451 | 451 | done = off == 12; |
| 452 | 452 | } |
| 453 | 453 | } |
| 454 | | |
| 454 | s->data->write_byte | |
| 455 | 455 | if(done) { |
| 456 | 456 | s->sti &= ~S_WRITE; |
| 457 | 457 | s->xm_adr = 0; |
| r8806 | r8807 | |
| 986 | 986 | void tms57002_execute(tms57002_t *s) |
| 987 | 987 | { |
| 988 | 988 | while(!(s->sti & (S_IDLE | IN_PLOAD | IN_CLOAD))) { |
| 989 | UINT32 opcode = | |
| 989 | UINT32 opcode = s->program->read_dword | |
| 990 | 990 | |
| 991 | 991 | if(s->sti & (S_READ|S_WRITE)) { |
| 992 | 992 | if(s->sti & S_READ) |
| r8806 | r8807 | |
| 1245 | 1245 | |
| 1246 | 1246 | for(;;) { |
| 1247 | 1247 | short ipc; |
| 1248 | UINT32 opcode = | |
| 1248 | UINT32 opcode = s->program->read_dword | |
| 1249 | 1249 | |
| 1250 | 1250 | if((opcode & 0xfc0000) == 0xfc0000) |
| 1251 | 1251 | tms57002_decode_one(s, opcode, &cs, tms57002_decode_cat3); |
| r8806 | r8807 | |
|---|---|---|
| 140 | 140 | z80_daisy_chain daisy; |
| 141 | 141 | device_irq_callback irq_callback; |
| 142 | 142 | legacy_cpu_device *device; |
| 143 | const address_space *program; | |
| 144 | const address_space *iospace; | |
| 143 | address_space *program; | |
| 144 | address_space *iospace; | |
| 145 | 145 | UINT8 rtemp; |
| 146 | 146 | UINT32 ioltemp; |
| 147 | 147 | int icount; |
| r8806 | r8807 | |
| 839 | 839 | static UINT8 z180_readcontrol(z180_state *cpustate, offs_t port) |
| 840 | 840 | { |
| 841 | 841 | /* normal external readport */ |
| 842 | UINT8 data = | |
| 842 | UINT8 data = | |
| 843 | 843 | |
| 844 | 844 | /* remap internal I/O registers */ |
| 845 | 845 | if((port & (cpustate->IO_IOCR & 0xc0)) == (cpustate->IO_IOCR & 0xc0)) |
| r8806 | r8807 | |
| 1267 | 1267 | static void z180_writecontrol(z180_state *cpustate, offs_t port, UINT8 data) |
| 1268 | 1268 | { |
| 1269 | 1269 | /* normal external write port */ |
| 1270 | | |
| 1270 | | |
| 1271 | 1271 | |
| 1272 | 1272 | /* remap internal I/O registers */ |
| 1273 | 1273 | if((port & (cpustate->IO_IOCR & 0xc0)) == (cpustate->IO_IOCR & 0xc0)) |
| r8806 | r8807 | |
| 1642 | 1642 | switch( cpustate->IO_DMODE & (Z180_DMODE_SM | Z180_DMODE_DM) ) |
| 1643 | 1643 | { |
| 1644 | 1644 | case 0x00: /* memory SAR0+1 to memory DAR0+1 */ |
| 1645 | | |
| 1645 | | |
| 1646 | 1646 | break; |
| 1647 | 1647 | case 0x04: /* memory SAR0-1 to memory DAR0+1 */ |
| 1648 | | |
| 1648 | | |
| 1649 | 1649 | break; |
| 1650 | 1650 | case 0x08: /* memory SAR0 fixed to memory DAR0+1 */ |
| 1651 | | |
| 1651 | | |
| 1652 | 1652 | break; |
| 1653 | 1653 | case 0x0c: /* I/O SAR0 fixed to memory DAR0+1 */ |
| 1654 | 1654 | if (cpustate->iol & Z180_DREQ0) |
| 1655 | 1655 | { |
| 1656 | | |
| 1656 | | |
| 1657 | 1657 | /* edge sensitive DREQ0 ? */ |
| 1658 | 1658 | if (cpustate->IO_DCNTL & Z180_DCNTL_DIM0) |
| 1659 | 1659 | { |
| r8806 | r8807 | |
| 1663 | 1663 | } |
| 1664 | 1664 | break; |
| 1665 | 1665 | case 0x10: /* memory SAR0+1 to memory DAR0-1 */ |
| 1666 | | |
| 1666 | | |
| 1667 | 1667 | break; |
| 1668 | 1668 | case 0x14: /* memory SAR0-1 to memory DAR0-1 */ |
| 1669 | | |
| 1669 | | |
| 1670 | 1670 | break; |
| 1671 | 1671 | case 0x18: /* memory SAR0 fixed to memory DAR0-1 */ |
| 1672 | | |
| 1672 | | |
| 1673 | 1673 | break; |
| 1674 | 1674 | case 0x1c: /* I/O SAR0 fixed to memory DAR0-1 */ |
| 1675 | 1675 | if (cpustate->iol & Z180_DREQ0) |
| 1676 | 1676 | { |
| 1677 | | |
| 1677 | | |
| 1678 | 1678 | /* edge sensitive DREQ0 ? */ |
| 1679 | 1679 | if (cpustate->IO_DCNTL & Z180_DCNTL_DIM0) |
| 1680 | 1680 | { |
| r8806 | r8807 | |
| 1684 | 1684 | } |
| 1685 | 1685 | break; |
| 1686 | 1686 | case 0x20: /* memory SAR0+1 to memory DAR0 fixed */ |
| 1687 | | |
| 1687 | | |
| 1688 | 1688 | break; |
| 1689 | 1689 | case 0x24: /* memory SAR0-1 to memory DAR0 fixed */ |
| 1690 | | |
| 1690 | | |
| 1691 | 1691 | break; |
| 1692 | 1692 | case 0x28: /* reserved */ |
| 1693 | 1693 | break; |
| r8806 | r8807 | |
| 1696 | 1696 | case 0x30: /* memory SAR0+1 to I/O DAR0 fixed */ |
| 1697 | 1697 | if (cpustate->iol & Z180_DREQ0) |
| 1698 | 1698 | { |
| 1699 | OUT(cpustate, dar0, | |
| 1699 | OUT(cpustate, dar0, | |
| 1700 | 1700 | /* edge sensitive DREQ0 ? */ |
| 1701 | 1701 | if (cpustate->IO_DCNTL & Z180_DCNTL_DIM0) |
| 1702 | 1702 | { |
| r8806 | r8807 | |
| 1708 | 1708 | case 0x34: /* memory SAR0-1 to I/O DAR0 fixed */ |
| 1709 | 1709 | if (cpustate->iol & Z180_DREQ0) |
| 1710 | 1710 | { |
| 1711 | OUT(cpustate, dar0, | |
| 1711 | OUT(cpustate, dar0, | |
| 1712 | 1712 | /* edge sensitive DREQ0 ? */ |
| 1713 | 1713 | if (cpustate->IO_DCNTL & Z180_DCNTL_DIM0) |
| 1714 | 1714 | { |
| r8806 | r8807 | |
| 1776 | 1776 | switch (cpustate->IO_DCNTL & (Z180_DCNTL_DIM1 | Z180_DCNTL_DIM0)) |
| 1777 | 1777 | { |
| 1778 | 1778 | case 0x00: /* memory MAR1+1 to I/O IAR1 fixed */ |
| 1779 | | |
| 1779 | | |
| 1780 | 1780 | break; |
| 1781 | 1781 | case 0x01: /* memory MAR1-1 to I/O IAR1 fixed */ |
| 1782 | | |
| 1782 | | |
| 1783 | 1783 | break; |
| 1784 | 1784 | case 0x02: /* I/O IAR1 fixed to memory MAR1+1 */ |
| 1785 | | |
| 1785 | | |
| 1786 | 1786 | break; |
| 1787 | 1787 | case 0x03: /* I/O IAR1 fixed to memory MAR1-1 */ |
| 1788 | | |
| 1788 | | |
| 1789 | 1789 | break; |
| 1790 | 1790 | } |
| 1791 | 1791 |
| r8806 | r8807 | |
|---|---|---|
| 22 | 22 | ***************************************************************/ |
| 23 | 23 | #define IN(cs,port) \ |
| 24 | 24 | (((port ^ (cs)->IO_IOCR) & 0xffc0) == 0) ? \ |
| 25 | z180_readcontrol(cs, port) : | |
| 25 | z180_readcontrol(cs, port) : | |
| 26 | 26 | |
| 27 | 27 | /*************************************************************** |
| 28 | 28 | * Output a byte to given I/O port |
| r8806 | r8807 | |
| 30 | 30 | #define OUT(cs,port,value) \ |
| 31 | 31 | if (((port ^ (cs)->IO_IOCR) & 0xffc0) == 0) \ |
| 32 | 32 | z180_writecontrol(cs,port,value); \ |
| 33 | else | |
| 33 | else | |
| 34 | 34 | |
| 35 | 35 | /*************************************************************** |
| 36 | 36 | * MMU calculate the memory managemant lookup table |
| r8806 | r8807 | |
| 66 | 66 | /*************************************************************** |
| 67 | 67 | * Read a byte from given memory location |
| 68 | 68 | ***************************************************************/ |
| 69 | #define RM(cs,addr) | |
| 69 | #define RM(cs,addr) | |
| 70 | 70 | #ifdef UNUSED_FUNCTION |
| 71 | 71 | UINT8 z180_readmem(running_device *device, offs_t offset) |
| 72 | 72 | { |
| r8806 | r8807 | |
| 78 | 78 | /*************************************************************** |
| 79 | 79 | * Write a byte to given memory location |
| 80 | 80 | ***************************************************************/ |
| 81 | #define WM(cs,addr,value) | |
| 81 | #define WM(cs,addr,value) | |
| 82 | 82 | #ifdef UNUSED_FUNCTION |
| 83 | 83 | void z180_writemem(running_device *device, offs_t offset, UINT8 data) |
| 84 | 84 | { |
| r8806 | r8807 | |
|---|---|---|
| 55 | 55 | |
| 56 | 56 | /* CPU parameters */ |
| 57 | 57 | cpu_device * cpudevice; /* CPU device object */ |
| 58 | | |
| 58 | | |
| 59 | 59 | offs_t pageshift; /* shift to convert address to a page index */ |
| 60 | 60 | |
| 61 | 61 | /* opcode descriptor arrays */ |
| r8806 | r8807 | |
|---|---|---|
| 2 | 2 | 8-bit memory accessors |
| 3 | 3 | *****************************************************************************/ |
| 4 | 4 | |
| 5 | static UINT8 memory_read_byte(address_space *space, offs_t address) { return space->read_byte(address); } | |
| 6 | static void memory_write_byte(address_space *space, offs_t address, UINT8 data) { space->write_byte(address, data); } | |
| 7 | ||
| 5 | 8 | #ifdef I8086 |
| 9 | ||
| 10 | static UINT16 memory_read_word(address_space *space, offs_t address) { return space->read_word(address); } | |
| 11 | static void memory_write_word(address_space *space, offs_t address, UINT16 data) { space->write_word(address, data); } | |
| 12 | ||
| 6 | 13 | static void configure_memory_8bit(i8086_state *cpustate) |
| 7 | 14 | { |
| 8 | 15 | cpustate->mem.fetch_xor = 0; |
| 9 | 16 | |
| 10 | cpustate->mem.rbyte = memory_read_byte_8le; | |
| 11 | cpustate->mem.rword = memory_read_word_8le; | |
| 12 | cpustate->mem.wbyte = memory_write_byte_8le; | |
| 13 | cpustate->mem.wword = memory_write_word_8le; | |
| 17 | cpustate->mem.rbyte = memory_read_byte; | |
| 18 | cpustate->mem.rword = memory_read_word; | |
| 19 | cpustate->mem.wbyte = memory_write_byte; | |
| 20 | cpustate->mem.wword = memory_write_word; | |
| 14 | 21 | } |
| 15 | 22 | #endif |
| 16 | 23 | |
| r8806 | r8807 | |
| 19 | 26 | 16-bit memory accessors |
| 20 | 27 | *****************************************************************************/ |
| 21 | 28 | |
| 22 | static UINT16 read_word_16le( | |
| 29 | static UINT16 read_word_16le( | |
| 23 | 30 | { |
| 24 | 31 | if (!(addr & 1)) |
| 25 | return | |
| 32 | return space->r | |
| 26 | 33 | else |
| 27 | 34 | { |
| 28 | UINT16 result = memory_read_byte_16le(space, addr); | |
| 29 | return result | (memory_read_byte_16le(space, addr + 1) << 8); | |
| 35 | UINT16 result = space->read_byte(addr); | |
| 36 | return result | (space->read_byte(addr + 1) << 8); | |
| 30 | 37 | } |
| 31 | 38 | } |
| 32 | 39 | |
| 33 | static void write_word_16le( | |
| 40 | static void write_word_16le( | |
| 34 | 41 | { |
| 35 | 42 | if (!(addr & 1)) |
| 36 | | |
| 43 | space-> | |
| 37 | 44 | else |
| 38 | 45 | { |
| 39 | memory_write_byte_16le(space, addr, data); | |
| 40 | memory_write_byte_16le(space, addr + 1, data >> 8); | |
| 46 | space->write_byte(addr, data); | |
| 47 | space->write_byte(addr + 1, data >> 8); | |
| 41 | 48 | } |
| 42 | 49 | } |
| 43 | 50 | |
| r8806 | r8807 | |
| 45 | 52 | { |
| 46 | 53 | cpustate->mem.fetch_xor = BYTE_XOR_LE(0); |
| 47 | 54 | |
| 48 | cpustate->mem.rbyte = memory_read_byte | |
| 55 | cpustate->mem.rbyte = memory_read_byte | |
| 49 | 56 | cpustate->mem.rword = read_word_16le; |
| 50 | cpustate->mem.wbyte = memory_write_byte | |
| 57 | cpustate->mem.wbyte = memory_write_byte | |
| 51 | 58 | cpustate->mem.wword = write_word_16le; |
| 52 | 59 | } |
| r8806 | r8807 | |
|---|---|---|
| 60 | 60 | memory_interface mem; |
| 61 | 61 | |
| 62 | 62 | legacy_cpu_device *device; |
| 63 | const address_space *program; | |
| 64 | const address_space *io; | |
| 63 | address_space *program; | |
| 64 | address_space *io; | |
| 65 | 65 | int icount; |
| 66 | 66 | |
| 67 | 67 | unsigned prefix_base; /* base address of the latest prefix segment */ |
| r8806 | r8807 | |
|---|---|---|
| 3 | 3 | { |
| 4 | 4 | offs_t fetch_xor; |
| 5 | 5 | |
| 6 | UINT8 (*rbyte)(const address_space *, offs_t); | |
| 7 | UINT16 (*rword)(const address_space *, offs_t); | |
| 8 | void (*wbyte)(const address_space *, offs_t, UINT8); | |
| 9 | void (*wword)(const address_space *, offs_t, UINT16); | |
| 6 | UINT8 (*rbyte)(address_space *, offs_t); | |
| 7 | UINT16 (*rword)(address_space *, offs_t); | |
| 8 | void (*wbyte)(address_space *, offs_t, UINT8); | |
| 9 | void (*wword)(address_space *, offs_t, UINT16); | |
| 10 | 10 | }; |
| r8806 | r8807 | |
|---|---|---|
| 84 | 84 | |
| 85 | 85 | /************************************************************************/ |
| 86 | 86 | |
| 87 | #define read_byte(a) (*cpustate->mem.rbyte)(cpustate->program, a) | |
| 88 | #define read_word(a) (*cpustate->mem.rword)(cpustate->program, a) | |
| 89 | #define write_byte(a,d) (*cpustate->mem.wbyte)(cpustate->program, (a),(d)) | |
| 90 | #define write_word(a,d) (*cpustate->mem.wword)(cpustate->program, (a),(d)) | |
| 87 | #define read_mem_byte(a) (*cpustate->mem.rbyte)(cpustate->program, a) | |
| 88 | #define read_mem_word(a) (*cpustate->mem.rword)(cpustate->program, a) | |
| 89 | #define write_mem_byte(a,d) (*cpustate->mem.wbyte)(cpustate->program, (a),(d)) | |
| 90 | #define write_mem_word(a,d) (*cpustate->mem.wword)(cpustate->program, (a),(d)) | |
| 91 | 91 | |
| 92 | 92 | #define read_port_byte(a) (*cpustate->mem.rbyte)(cpustate->io, a) |
| 93 | 93 | #define read_port_word(a) (*cpustate->mem.rword)(cpustate->io, a) |
| r8806 | r8807 | |
| 100 | 100 | |
| 101 | 101 | #define DefaultBase(Seg) ((cpustate->seg_prefix && (Seg == DS || Seg == SS)) ? cpustate->prefix_base : cpustate->base[Seg]) |
| 102 | 102 | |
| 103 | #define GetMemB(Seg,Off) (read_byte((DefaultBase(Seg) + (Off)) & AMASK)) | |
| 104 | #define GetMemW(Seg,Off) (read_word((DefaultBase(Seg) + (Off)) & AMASK)) | |
| 105 | #define PutMemB(Seg,Off,x) write_byte((DefaultBase(Seg) + (Off)) & AMASK, (x)) | |
| 106 | #define PutMemW(Seg,Off,x) write_word((DefaultBase(Seg) + (Off)) & AMASK, (x)) | |
| 103 | #define GetMemB(Seg,Off) (read_mem_byte((DefaultBase(Seg) + (Off)) & AMASK)) | |
| 104 | #define GetMemW(Seg,Off) (read_mem_word((DefaultBase(Seg) + (Off)) & AMASK)) | |
| 105 | #define PutMemB(Seg,Off,x) write_mem_byte((DefaultBase(Seg) + (Off)) & AMASK, (x)) | |
| 106 | #define PutMemW(Seg,Off,x) write_mem_word((DefaultBase(Seg) + (Off)) & AMASK, (x)) | |
| 107 | 107 | |
| 108 | #define PEEKBYTE(ea) (read_byte((ea) & AMASK)) | |
| 109 | #define ReadByte(ea) (read_byte((ea) & AMASK)) | |
| 110 | #define ReadWord(ea) (read_word((ea) & AMASK)) | |
| 111 | #define WriteByte(ea,val) write_byte((ea) & AMASK, val); | |
| 112 | #define WriteWord(ea,val) write_word((ea) & AMASK, val); | |
| 108 | #define PEEKBYTE(ea) (read_mem_byte((ea) & AMASK)) | |
| 109 | #define ReadByte(ea) (read_mem_byte((ea) & AMASK)) | |
| 110 | #define ReadWord(ea) (read_mem_word((ea) & AMASK)) | |
| 111 | #define WriteByte(ea,val) write_mem_byte((ea) & AMASK, val); | |
| 112 | #define WriteWord(ea,val) write_mem_word((ea) & AMASK, val); | |
| 113 | 113 | |
| 114 | 114 | #define FETCH_XOR(a) ((a) ^ cpustate->mem.fetch_xor) |
| 115 | 115 | #define FETCH (memory_raw_read_byte(cpustate->program, FETCH_XOR(cpustate->pc++))) |
| r8806 | r8807 | |
|---|---|---|
| 59 | 59 | } ldtr, tr; |
| 60 | 60 | device_irq_callback irq_callback; |
| 61 | 61 | legacy_cpu_device *device; |
| 62 | const address_space *program; | |
| 63 | const address_space *io; | |
| 62 | address_space *program; | |
| 63 | address_space *io; | |
| 64 | 64 | INT32 AuxVal, OverVal, SignVal, ZeroVal, CarryVal, DirVal; /* 0 or non-0 valued flags */ |
| 65 | 65 | UINT8 ParityVal; |
| 66 | 66 | UINT8 TF, IF; /* 0 or 1 valued flags */ |
| r8806 | r8807 | |
|---|---|---|
| 98 | 98 | UINT16 *sound_data; |
| 99 | 99 | |
| 100 | 100 | legacy_cpu_device *device; |
| 101 | | |
| 101 | | |
| 102 | 102 | int icount; |
| 103 | 103 | } cquestsnd_state; |
| 104 | 104 | |
| r8806 | r8807 | |
| 139 | 139 | |
| 140 | 140 | legacy_cpu_device *device; |
| 141 | 141 | legacy_cpu_device *lindevice; |
| 142 | | |
| 142 | | |
| 143 | 143 | int icount; |
| 144 | 144 | } cquestrot_state; |
| 145 | 145 | |
| r8806 | r8807 | |
| 185 | 185 | |
| 186 | 186 | legacy_cpu_device *device; |
| 187 | 187 | legacy_cpu_device *rotdevice; |
| 188 | | |
| 188 | | |
| 189 | 189 | int icount; |
| 190 | 190 | } cquestlin_state; |
| 191 | 191 |
| r8806 | r8807 | |
|---|---|---|
| 500 | 500 | UPD7810_CONFIG config; |
| 501 | 501 | device_irq_callback irq_callback; |
| 502 | 502 | legacy_cpu_device *device; |
| 503 | const address_space *program; | |
| 504 | const address_space *io; | |
| 503 | address_space *program; | |
| 504 | address_space *io; | |
| 505 | 505 | int icount; |
| 506 | 506 | }; |
| 507 | 507 | |
| r8806 | r8807 | |
| 644 | 644 | |
| 645 | 645 | #define RDOP(O) O = memory_decrypted_read_byte(cpustate->program, PCD); PC++ |
| 646 | 646 | #define RDOPARG(A) A = memory_raw_read_byte(cpustate->program, PCD); PC++ |
| 647 | #define RM(A) memory_read_byte_8le(cpustate->program, A) | |
| 648 | #define WM(A,V) memory_write_byte_8le(cpustate->program, A,V) | |
| 647 | #define RM(A) cpustate->program->read_byte(A) | |
| 648 | #define WM(A,V) cpustate->program->write_byte(A,V) | |
| 649 | 649 | |
| 650 | 650 | #define ZHC_ADD(after,before,carry) \ |
| 651 | 651 | if (after == 0) PSW |= Z; else PSW &= ~Z; \ |
| r8806 | r8807 | |
| 686 | 686 | { |
| 687 | 687 | case UPD7810_PORTA: |
| 688 | 688 | if (cpustate->ma) // NS20031301 no need to read if the port is set as output |
| 689 | cpustate->pa_in = | |
| 689 | cpustate->pa_in = | |
| 690 | 690 | data = (cpustate->pa_in & cpustate->ma) | (cpustate->pa_out & ~cpustate->ma); |
| 691 | 691 | break; |
| 692 | 692 | case UPD7810_PORTB: |
| 693 | 693 | if (cpustate->mb) // NS20031301 no need to read if the port is set as output |
| 694 | cpustate->pb_in = | |
| 694 | cpustate->pb_in = | |
| 695 | 695 | data = (cpustate->pb_in & cpustate->mb) | (cpustate->pb_out & ~cpustate->mb); |
| 696 | 696 | break; |
| 697 | 697 | case UPD7810_PORTC: |
| 698 | 698 | if (cpustate->mc) // NS20031301 no need to read if the port is set as output |
| 699 | cpustate->pc_in = | |
| 699 | cpustate->pc_in = | |
| 700 | 700 | data = (cpustate->pc_in & cpustate->mc) | (cpustate->pc_out & ~cpustate->mc); |
| 701 | 701 | if (cpustate->mcc & 0x01) /* PC0 = TxD output */ |
| 702 | 702 | data = (data & ~0x01) | (cpustate->txd & 1 ? 0x01 : 0x00); |
| r8806 | r8807 | |
| 716 | 716 | data = (data & ~0x80) | (cpustate->co1 & 1 ? 0x80 : 0x00); |
| 717 | 717 | break; |
| 718 | 718 | case UPD7810_PORTD: |
| 719 | cpustate->pd_in = | |
| 719 | cpustate->pd_in = | |
| 720 | 720 | switch (cpustate->mm & 0x07) |
| 721 | 721 | { |
| 722 | 722 | case 0x00: /* PD input mode, PF port mode */ |
| r8806 | r8807 | |
| 731 | 731 | } |
| 732 | 732 | break; |
| 733 | 733 | case UPD7810_PORTF: |
| 734 | cpustate->pf_in = | |
| 734 | cpustate->pf_in = | |
| 735 | 735 | switch (cpustate->mm & 0x06) |
| 736 | 736 | { |
| 737 | 737 | case 0x00: /* PD input/output mode, PF port mode */ |
| r8806 | r8807 | |
| 751 | 751 | } |
| 752 | 752 | break; |
| 753 | 753 | case UPD7807_PORTT: // NS20031301 partial implementation |
| 754 | data = | |
| 754 | data = | |
| 755 | 755 | break; |
| 756 | 756 | default: |
| 757 | 757 | logerror("uPD7810 internal error: RP(cpustate) called with invalid port number\n"); |
| r8806 | r8807 | |
| 767 | 767 | cpustate->pa_out = data; |
| 768 | 768 | // data = (data & ~cpustate->ma) | (cpustate->pa_in & cpustate->ma); |
| 769 | 769 | data = (data & ~cpustate->ma) | (cpustate->ma); // NS20031401 |
| 770 | | |
| 770 | cpustate->io-> | |
| 771 | 771 | break; |
| 772 | 772 | case UPD7810_PORTB: |
| 773 | 773 | cpustate->pb_out = data; |
| 774 | 774 | // data = (data & ~cpustate->mb) | (cpustate->pb_in & cpustate->mb); |
| 775 | 775 | data = (data & ~cpustate->mb) | (cpustate->mb); // NS20031401 |
| 776 | | |
| 776 | cpustate->io-> | |
| 777 | 777 | break; |
| 778 | 778 | case UPD7810_PORTC: |
| 779 | 779 | cpustate->pc_out = data; |
| r8806 | r8807 | |
| 795 | 795 | data = (data & ~0x40) | (cpustate->co0 & 1 ? 0x40 : 0x00); |
| 796 | 796 | if (cpustate->mcc & 0x80) /* PC7 = CO1 output */ |
| 797 | 797 | data = (data & ~0x80) | (cpustate->co1 & 1 ? 0x80 : 0x00); |
| 798 | | |
| 798 | cpustate->io-> | |
| 799 | 799 | break; |
| 800 | 800 | case UPD7810_PORTD: |
| 801 | 801 | cpustate->pd_out = data; |
| r8806 | r8807 | |
| 810 | 810 | default: /* PD extension mode, PF port/extension mode */ |
| 811 | 811 | return; |
| 812 | 812 | } |
| 813 | | |
| 813 | cpustate->io-> | |
| 814 | 814 | break; |
| 815 | 815 | case UPD7810_PORTF: |
| 816 | 816 | cpustate->pf_out = data; |
| r8806 | r8807 | |
| 829 | 829 | data |= 0xff; /* what would come out for the lower bits here? */ |
| 830 | 830 | break; |
| 831 | 831 | } |
| 832 | | |
| 832 | cpustate->io-> | |
| 833 | 833 | break; |
| 834 | 834 | default: |
| 835 | 835 | logerror("uPD7810 internal error: RP(cpustate) called with invalid port number\n"); |
| r8806 | r8807 | |
|---|---|---|
| 45 | 45 | |
| 46 | 46 | INLINE UINT8 READ_BYTE(sc61860_state *cpustate, UINT16 adr) |
| 47 | 47 | { |
| 48 | return | |
| 48 | return | |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | 51 | INLINE void WRITE_BYTE(sc61860_state *cpustate, UINT16 a,UINT8 v) |
| 52 | 52 | { |
| 53 | | |
| 53 | | |
| 54 | 54 | } |
| 55 | 55 | |
| 56 | 56 | #define PUSH(v) cpustate->ram[--cpustate->r]=v |
| r8806 | r8807 | |
|---|---|---|
| 56 | 56 | struct { int t2ms, t512ms; int count;} timer; |
| 57 | 57 | |
| 58 | 58 | legacy_cpu_device *device; |
| 59 | | |
| 59 | | |
| 60 | 60 | int icount; |
| 61 | 61 | }; |
| 62 | 62 |
| r8806 | r8807 | |
|---|---|---|
| 85 | 85 | UINT8 interrupt_pending; |
| 86 | 86 | device_irq_callback irq_callback; |
| 87 | 87 | legacy_cpu_device *device; |
| 88 | | |
| 88 | | |
| 89 | 89 | int icount; |
| 90 | 90 | } minx_state; |
| 91 | 91 | |
| 92 | #define RD(offset) memory_read_byte_8be( minx->program, offset ) | |
| 93 | #define WR(offset,data) memory_write_byte_8be( minx->program, offset, data ) | |
| 92 | #define RD(offset) minx->program->read_byte( offset ) | |
| 93 | #define WR(offset,data) minx->program->write_byte( offset, data ) | |
| 94 | 94 | #define GET_MINX_PC ( ( minx->PC & 0x8000 ) ? ( minx->V << 15 ) | (minx->PC & 0x7FFF ) : minx->PC ) |
| 95 | 95 | |
| 96 | 96 | INLINE minx_state *get_safe_token(running_device *device) |
| r8806 | r8807 | |
|---|---|---|
| 3 | 3 | /****************************************************************/ |
| 4 | 4 | |
| 5 | 5 | struct cpu_info { |
| 6 | UINT8 (*mr8) (const address_space *space, offs_t address); | |
| 7 | void (*mw8) (const address_space *space, offs_t address, UINT8 data); | |
| 8 | UINT16 (*mr16)(const address_space *space, offs_t address); | |
| 9 | void (*mw16)(const address_space *space, offs_t address, UINT16 data); | |
| 10 | UINT32 (*mr32)(const address_space *space, offs_t address); | |
| 11 | void (*mw32)(const address_space *space, offs_t address, UINT32 data); | |
| 12 | UINT8 (*or8) (const address_space *space, offs_t address); | |
| 13 | UINT16 (*or16)(const address_space *space, offs_t address); | |
| 14 | UINT32 (*or32)(const address_space *space, offs_t address); | |
| 6 | UINT8 (*mr8) (address_space *space, offs_t address); | |
| 7 | void (*mw8) (address_space *space, offs_t address, UINT8 data); | |
| 8 | UINT16 (*mr16)(address_space *space, offs_t address); | |
| 9 | void (*mw16)(address_space *space, offs_t address, UINT16 data); | |
| 10 | UINT32 (*mr32)(address_space *space, offs_t address); | |
| 11 | void (*mw32)(address_space *space, offs_t address, UINT32 data); | |
| 12 | UINT8 (*or8) (address_space *space, offs_t address); | |
| 13 | UINT16 (*or16)(address_space *space, offs_t address); | |
| 14 | UINT32 (*or32)(address_space *space, offs_t address); | |
| 15 | 15 | UINT32 start_pc; |
| 16 | 16 | }; |
| 17 | 17 | |
| r8806 | r8807 | |
| 21 | 21 | /* Memory accesses for 16-bit data bus, 24-bit address bus (V60) */ |
| 22 | 22 | /*****************************************************************/ |
| 23 | 23 | |
| 24 | #define MemRead8_16 memory_read_byte_16le | |
| 25 | #define MemWrite8_16 memory_write_byte_16le | |
| 24 | static UINT8 memory_read_byte(address_space *space, offs_t address) { return space->read_byte(address); } | |
| 25 | static void memory_write_byte(address_space *space, offs_t address, UINT8 data) { space->write_byte(address, data); } | |
| 26 | 26 | |
| 27 | static UINT16 MemRead16_16(const address_space *space, offs_t address) | |
| 27 | #define MemRead8_16 memory_read_byte | |
| 28 | #define MemWrite8_16 memory_write_byte | |
| 29 | ||
| 30 | static UINT16 MemRead16_16(address_space *space, offs_t address) | |
| 28 | 31 | { |
| 29 | 32 | if (!(address & 1)) |
| 30 | return | |
| 33 | return space->r | |
| 31 | 34 | else |
| 32 | 35 | { |
| 33 | UINT16 result = memory_read_byte_16le(space, address); | |
| 34 | return result | memory_read_byte_16le(space, address + 1) << 8; | |
| 36 | UINT16 result = space->read_byte(address); | |
| 37 | return result | space->read_byte(address + 1) << 8; | |
| 35 | 38 | } |
| 36 | 39 | } |
| 37 | 40 | |
| 38 | static void MemWrite16_16( | |
| 41 | static void MemWrite16_16( | |
| 39 | 42 | { |
| 40 | 43 | if (!(address & 1)) |
| 41 | | |
| 44 | space-> | |
| 42 | 45 | else |
| 43 | 46 | { |
| 44 | memory_write_byte_16le(space, address, data); | |
| 45 | memory_write_byte_16le(space, address + 1, data >> 8); | |
| 47 | space->write_byte(address, data); | |
| 48 | space->write_byte(address + 1, data >> 8); | |
| 46 | 49 | } |
| 47 | 50 | } |
| 48 | 51 | |
| 49 | static UINT32 MemRead32_16( | |
| 52 | static UINT32 MemRead32_16( | |
| 50 | 53 | { |
| 51 | 54 | if (!(address & 1)) |
| 52 | 55 | { |
| 53 | UINT32 result = memory_read_word_16le(space, address); | |
| 54 | return result | (memory_read_word_16le(space, address + 2) << 16); | |
| 56 | UINT32 result = space->read_word(address); | |
| 57 | return result | (space->read_word(address + 2) << 16); | |
| 55 | 58 | } |
| 56 | 59 | else |
| 57 | 60 | { |
| 58 | UINT32 result = memory_read_byte_16le(space, address); | |
| 59 | result |= memory_read_word_16le(space, address + 1) << 8; | |
| 60 | return result | memory_read_byte_16le(space, address + 3) << 24; | |
| 61 | UINT32 result = space->read_byte(address); | |
| 62 | result |= space->read_word(address + 1) << 8; | |
| 63 | return result | space->read_byte(address + 3) << 24; | |
| 61 | 64 | } |
| 62 | 65 | } |
| 63 | 66 | |
| 64 | static void MemWrite32_16( | |
| 67 | static void MemWrite32_16( | |
| 65 | 68 | { |
| 66 | 69 | if (!(address & 1)) |
| 67 | 70 | { |
| 68 | memory_write_word_16le(space, address, data); | |
| 69 | memory_write_word_16le(space, address + 2, data >> 16); | |
| 71 | space->write_word(address, data); | |
| 72 | space->write_word(address + 2, data >> 16); | |
| 70 | 73 | } |
| 71 | 74 | else |
| 72 | 75 | { |
| 73 | memory_write_byte_16le(space, address, data); | |
| 74 | memory_write_word_16le(space, address + 1, data >> 8); | |
| 75 | memory_write_byte_16le(space, address + 3, data >> 24); | |
| 76 | space->write_byte(address, data); | |
| 77 | space->write_word(address + 1, data >> 8); | |
| 78 | space->write_byte(address + 3, data >> 24); | |
| 76 | 79 | } |
| 77 | 80 | } |
| 78 | 81 | |
| r8806 | r8807 | |
| 81 | 84 | /* Opcode accesses for 16-bit data bus, 24-bit address bus (V60) */ |
| 82 | 85 | /*****************************************************************/ |
| 83 | 86 | |
| 84 | static UINT8 OpRead8_16( | |
| 87 | static UINT8 OpRead8_16( | |
| 85 | 88 | { |
| 86 | 89 | return memory_decrypted_read_byte(space, BYTE_XOR_LE(address)); |
| 87 | 90 | } |
| 88 | 91 | |
| 89 | static UINT16 OpRead16_16( | |
| 92 | static UINT16 OpRead16_16( | |
| 90 | 93 | { |
| 91 | 94 | return memory_decrypted_read_byte(space, BYTE_XOR_LE(address)) | (memory_decrypted_read_byte(space, BYTE_XOR_LE(address + 1)) << 8); |
| 92 | 95 | } |
| 93 | 96 | |
| 94 | static UINT32 OpRead32_16( | |
| 97 | static UINT32 OpRead32_16( | |
| 95 | 98 | { |
| 96 | 99 | return memory_decrypted_read_byte(space, BYTE_XOR_LE(address)) | (memory_decrypted_read_byte(space, BYTE_XOR_LE(address + 1)) << 8) | |
| 97 | 100 | (memory_decrypted_read_byte(space, BYTE_XOR_LE(address + 2)) << 16) | (memory_decrypted_read_byte(space, BYTE_XOR_LE(address + 3)) << 24); |
| r8806 | r8807 | |
| 103 | 106 | /* Memory accesses for 32-bit data bus, 32-bit address bus (V70) */ |
| 104 | 107 | /*****************************************************************/ |
| 105 | 108 | |
| 106 | #define MemRead8_32 memory_read_byte_32le | |
| 107 | #define MemWrite8_32 memory_write_byte_32le | |
| 109 | #define MemRead8_32 memory_read_byte | |
| 110 | #define MemWrite8_32 memory_write_byte | |
| 108 | 111 | |
| 109 | static UINT16 MemRead16_32( | |
| 112 | static UINT16 MemRead16_32( | |
| 110 | 113 | { |
| 111 | 114 | if (!(address & 1)) |
| 112 | return | |
| 115 | return space->r | |
| 113 | 116 | else |
| 114 | 117 | { |
| 115 | UINT16 result = memory_read_byte_32le(space, address); | |
| 116 | return result | memory_read_byte_32le(space, address + 1) << 8; | |
| 118 | UINT16 result = space->read_byte(address); | |
| 119 | return result | space->read_byte(address + 1) << 8; | |
| 117 | 120 | } |
| 118 | 121 | } |
| 119 | 122 | |
| 120 | static void MemWrite16_32( | |
| 123 | static void MemWrite16_32( | |
| 121 | 124 | { |
| 122 | 125 | if (!(address & 1)) |
| 123 | | |
| 126 | space-> | |
| 124 | 127 | else |
| 125 | 128 | { |
| 126 | memory_write_byte_32le(space, address, data); | |
| 127 | memory_write_byte_32le(space, address + 1, data >> 8); | |
| 129 | space->write_byte(address, data); | |
| 130 | space->write_byte(address + 1, data >> 8); | |
| 128 | 131 | } |
| 129 | 132 | } |
| 130 | 133 | |
| 131 | static UINT32 MemRead32_32( | |
| 134 | static UINT32 MemRead32_32( | |
| 132 | 135 | { |
| 133 | 136 | if (!(address & 3)) |
| 134 | return | |
| 137 | return space->r | |
| 135 | 138 | else if (!(address & 1)) |
| 136 | 139 | { |
| 137 | UINT32 result = memory_read_word_32le(space, address); | |
| 138 | return result | (memory_read_word_32le(space, address + 2) << 16); | |
| 140 | UINT32 result = space->read_word(address); | |
| 141 | return result | (space->read_word(address + 2) << 16); | |
| 139 | 142 | } |
| 140 | 143 | else |
| 141 | 144 | { |
| 142 | UINT32 result = memory_read_byte_32le(space, address); | |
| 143 | result |= memory_read_word_32le(space, address + 1) << 8; | |
| 144 | return result | memory_read_byte_32le(space, address + 3) << 24; | |
| 145 | UINT32 result = space->read_byte(address); | |
| 146 | result |= space->read_word(address + 1) << 8; | |
| 147 | return result | space->read_byte(address + 3) << 24; | |
| 145 | 148 | } |
| 146 | 149 | } |
| 147 | 150 | |
| 148 | static void MemWrite32_32( | |
| 151 | static void MemWrite32_32( | |
| 149 | 152 | { |
| 150 | 153 | if (!(address & 3)) |
| 151 | | |
| 154 | space-> | |
| 152 | 155 | else if (!(address & 1)) |
| 153 | 156 | { |
| 154 | memory_write_word_32le(space, address, data); | |
| 155 | memory_write_word_32le(space, address + 2, data >> 16); | |
| 157 | space->write_word(address, data); | |
| 158 | space->write_word(address + 2, data >> 16); | |
| 156 | 159 | } |
| 157 | 160 | else |
| 158 | 161 | { |
| 159 | memory_write_byte_32le(space, address, data); | |
| 160 | memory_write_word_32le(space, address + 1, data >> 8); | |
| 161 | memory_write_byte_32le(space, address + 3, data >> 24); | |
| 162 | space->write_byte(address, data); | |
| 163 | space->write_word(address + 1, data >> 8); | |
| 164 | space->write_byte(address + 3, data >> 24); | |
| 162 | 165 | } |
| 163 | 166 | } |
| 164 | 167 | |
| r8806 | r8807 | |
| 168 | 171 | /* Opcode accesses for 32-bit data bus, 32-bit address bus (V60) */ |
| 169 | 172 | /*****************************************************************/ |
| 170 | 173 | |
| 171 | static UINT8 OpRead8_32( | |
| 174 | static UINT8 OpRead8_32( | |
| 172 | 175 | { |
| 173 | 176 | return memory_decrypted_read_byte(space, BYTE4_XOR_LE(address)); |
| 174 | 177 | } |
| 175 | 178 | |
| 176 | static UINT16 OpRead16_32( | |
| 179 | static UINT16 OpRead16_32( | |
| 177 | 180 | { |
| 178 | 181 | return memory_decrypted_read_byte(space, BYTE4_XOR_LE(address)) | (memory_decrypted_read_byte(space, BYTE4_XOR_LE(address + 1)) << 8); |
| 179 | 182 | } |
| 180 | 183 | |
| 181 | static UINT32 OpRead32_32( | |
| 184 | static UINT32 OpRead32_32( | |
| 182 | 185 | { |
| 183 | 186 | return memory_decrypted_read_byte(space, BYTE4_XOR_LE(address)) | (memory_decrypted_read_byte(space, BYTE4_XOR_LE(address + 1)) << 8) | |
| 184 | 187 | (memory_decrypted_read_byte(space, BYTE4_XOR_LE(address + 2)) << 16) | (memory_decrypted_read_byte(space, BYTE4_XOR_LE(address + 3)) << 24); |
| r8806 | r8807 | |
|---|---|---|
| 79 | 79 | UINT8 nmi_line; |
| 80 | 80 | device_irq_callback irq_cb; |
| 81 | 81 | legacy_cpu_device * device; |
| 82 | const address_space *program; | |
| 83 | const address_space *io; | |
| 82 | address_space *program; | |
| 83 | address_space *io; | |
| 84 | 84 | UINT32 PPC; |
| 85 | 85 | int icount; |
| 86 | 86 | int stall_io; |
| r8806 | r8807 | |
|---|---|---|
| 88 | 88 | uint ir; /* Instruction Register */ |
| 89 | 89 | device_irq_callback int_ack; |
| 90 | 90 | legacy_cpu_device *device; |
| 91 | | |
| 91 | | |
| 92 | 92 | uint stopped; /* stopped status */ |
| 93 | 93 | int ICount; |
| 94 | 94 | uint source; |
| r8806 | r8807 | |
| 247 | 247 | /* ================================= MAME ================================= */ |
| 248 | 248 | /* ======================================================================== */ |
| 249 | 249 | |
| 250 | #define spc700_read_8(addr) memory_read_byte_8le(cpustate->program,addr) | |
| 251 | #define spc700_write_8(addr,data) memory_write_byte_8le(cpustate->program,addr,data) | |
| 250 | #define spc700_read_8(addr) cpustate->program->read_byte(addr) | |
| 251 | #define spc700_write_8(addr,data) cpustate->program->write_byte(addr,data) | |
| 252 | 252 | |
| 253 | 253 | #define spc700_read_8_direct(A) spc700_read_8(A) |
| 254 | 254 | #define spc700_write_8_direct(A, V) spc700_write_8(A, V) |
| 255 | 255 | //#define spc700_read_instruction(A) memory_decrypted_read_byte(cpustate->program,A) |
| 256 | 256 | //#define spc700_read_8_immediate(A) memory_raw_read_byte(cpustate->program,A) |
| 257 | #define spc700_read_instruction(A) memory_read_byte_8le(cpustate->program,A) | |
| 258 | #define spc700_read_8_immediate(A) memory_read_byte_8le(cpustate->program,A) | |
| 257 | #define spc700_read_instruction(A) cpustate->program->read_byte(A) | |
| 258 | #define spc700_read_8_immediate(A) cpustate->program->read_byte(A) | |
| 259 | 259 | #define spc700_jumping(A) |
| 260 | 260 | #define spc700_branching(A) |
| 261 | 261 |
| r8806 | r8807 | |
|---|---|---|
| 144 | 144 | /* ... */ |
| 145 | 145 | /* P:$cffe -> Internal P:$07ff low byte */ |
| 146 | 146 | /* P:$cfff -> Internal P:$07ff high byte */ |
| 147 | UINT8 mem_value_low = memory_read_byte_16le(cpustate->program, mem_offset); /* TODO: IS THIS READING RIGHT? */ | |
| 148 | UINT8 mem_value_high = memory_read_byte_16be(cpustate->program, mem_offset); | |
| 147 | UINT8 mem_value_low = cpustate->program->read_byte(mem_offset); /* TODO: IS THIS READING RIGHT? */ | |
| 148 | UINT8 mem_value_high = cpustate->program->read_byte(mem_offset); | |
| 149 | 149 | cpustate->program_ram[i] = (mem_value_high << 8) || mem_value_low; |
| 150 | 150 | } |
| 151 | 151 | |
| r8806 | r8807 | |
| 166 | 166 | /* they need. Once they've had their fill, they turn bootstrap mode off */ |
| 167 | 167 | /* and the CPU begins execution at 0x0000; */ |
| 168 | 168 | /* HACK - Read bit 15 at 0xc000 to see if we're working with the SSIO or host interface. */ |
| 169 | if ( | |
| 169 | if ( | |
| 170 | 170 | { |
| 171 | 171 | cpustate->bootstrap_mode = BOOTSTRAP_SSIX; |
| 172 | 172 | logerror("DSP56k : Currently in (hacked) bootstrap mode - reading from SSIx.\n"); |
| r8806 | r8807 | |
|---|---|---|
| 67 | 67 | /*************************************************************************** |
| 68 | 68 | Direct Update Handler |
| 69 | 69 | ***************************************************************************/ |
| 70 | ||
| 70 | ||
| 71 | 71 | { |
| 72 | 72 | if (address >= (0x0000<<1) && address <= (0x07ff<<1)) |
| 73 | 73 | { |
| 74 | dsp56k_core* cpustate = get_safe_token(space->cpu); | |
| 75 | direct->raw = direct->decrypted = (UINT8 *)(cpustate->program_ram - (0x0000<<1)); | |
| 74 | dsp56k_core* cpustate = get_safe_token(direct.space().cpu); | |
| 75 | direct.explicit_configure(0x0000<<1, 0x07ff<<1, 0x07ff<<1, cpustate->program_ram); | |
| 76 | 76 | return ~0; |
| 77 | 77 | } |
| 78 | 78 | |
| r8806 | r8807 | |
| 237 | 237 | |
| 238 | 238 | /* Setup the direct memory handler for this CPU */ |
| 239 | 239 | /* NOTE: Be sure to grab this guy and call him if you ever install another direct_update_hander in a driver! */ |
| 240 | | |
| 240 | c | |
| 241 | 241 | } |
| 242 | 242 | |
| 243 | 243 | |
| r8806 | r8807 | |
| 290 | 290 | alu_reset(cpustate); |
| 291 | 291 | |
| 292 | 292 | /* HACK - Put a jump to 0x0000 at 0x0000 - this keeps the CPU locked to the instruction at address 0x0000 */ |
| 293 | | |
| 293 | | |
| 294 | 294 | } |
| 295 | 295 | |
| 296 | 296 |
| r8806 | r8807 | |
|---|---|---|
| 233 | 233 | int interrupt_cycles; |
| 234 | 234 | void (*output_pins_changed)(UINT32 pins); |
| 235 | 235 | legacy_cpu_device *device; |
| 236 | const address_space *program; | |
| 237 | const address_space *data; | |
| 236 | address_space *program; | |
| 237 | address_space *data; | |
| 238 | 238 | |
| 239 | 239 | UINT16 peripheral_ram[0x40]; |
| 240 | 240 | UINT16 program_ram[0x800]; |
| r8806 | r8807 | |
|---|---|---|
| 2306 | 2306 | decode_BBB_bitmask(cpustate, BITS(op2,0xe000), &iVal); |
| 2307 | 2307 | |
| 2308 | 2308 | workAddr = assemble_address_from_Pppppp_table(cpustate, BITS(op,0x0020), BITS(op,0x001f)); |
| 2309 | previousValue = | |
| 2309 | previousValue = | |
| 2310 | 2310 | workingWord = previousValue; |
| 2311 | 2311 | |
| 2312 | 2312 | switch(BITS(op2, 0x1f00)) |
| r8806 | r8807 | |
| 2372 | 2372 | decode_RR_table(cpustate, BITS(op,0x0003), &R); |
| 2373 | 2373 | |
| 2374 | 2374 | workAddr = *((UINT16*)R.addr); |
| 2375 | previousValue = | |
| 2375 | previousValue = | |
| 2376 | 2376 | workingWord = previousValue; |
| 2377 | 2377 | |
| 2378 | 2378 | switch(BITS(op2, 0x1f00)) |
| r8806 | r8807 | |
| 3280 | 3280 | if (W) |
| 3281 | 3281 | { |
| 3282 | 3282 | /* Write D */ |
| 3283 | UINT16 value = | |
| 3283 | UINT16 value = | |
| 3284 | 3284 | typed_pointer temp_src = { &value, DT_WORD }; |
| 3285 | 3285 | SetDestinationValue(temp_src, SD); |
| 3286 | 3286 | } |
| r8806 | r8807 | |
| 3322 | 3322 | if (W) |
| 3323 | 3323 | { |
| 3324 | 3324 | /* Write D */ |
| 3325 | UINT16 tempData = | |
| 3325 | UINT16 tempData = | |
| 3326 | 3326 | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 3327 | 3327 | SetDestinationValue(temp_src, SD); |
| 3328 | 3328 | } |
| r8806 | r8807 | |
| 3366 | 3366 | if (W) |
| 3367 | 3367 | { |
| 3368 | 3368 | /* Write D */ |
| 3369 | UINT16 tempData = | |
| 3369 | UINT16 tempData = | |
| 3370 | 3370 | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 3371 | 3371 | SetDestinationValue(temp_src, SD); |
| 3372 | 3372 | } |
| r8806 | r8807 | |
| 3417 | 3417 | else |
| 3418 | 3418 | { |
| 3419 | 3419 | /* 16-bit long address */ |
| 3420 | UINT16 tempD = | |
| 3420 | UINT16 tempD = | |
| 3421 | 3421 | typed_pointer tempTP = {&tempD, DT_WORD}; |
| 3422 | 3422 | SetDestinationValue(tempTP, SD); |
| 3423 | 3423 | } |
| r8806 | r8807 | |
| 3495 | 3495 | if (W) |
| 3496 | 3496 | { |
| 3497 | 3497 | /* Write D */ |
| 3498 | UINT16 tempData = | |
| 3498 | UINT16 tempData = | |
| 3499 | 3499 | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 3500 | 3500 | SetDestinationValue(temp_src, SD); |
| 3501 | 3501 | } |
| r8806 | r8807 | |
| 3558 | 3558 | { |
| 3559 | 3559 | /* Read from Program Memory */ |
| 3560 | 3560 | typed_pointer data; |
| 3561 | UINT16 ldata = | |
| 3561 | UINT16 ldata = | |
| 3562 | 3562 | |
| 3563 | 3563 | data.addr = &ldata; |
| 3564 | 3564 | data.data_type = DT_WORD; |
| r8806 | r8807 | |
| 3612 | 3612 | |
| 3613 | 3613 | if (W) |
| 3614 | 3614 | { |
| 3615 | UINT16 data = | |
| 3615 | UINT16 data = | |
| 3616 | 3616 | |
| 3617 | 3617 | typed_pointer tempTP; |
| 3618 | 3618 | tempTP.addr = &data; |
| r8806 | r8807 | |
| 3651 | 3651 | /* A little different than most W if's - opposite read and write */ |
| 3652 | 3652 | if (W) |
| 3653 | 3653 | { |
| 3654 | UINT16 data = | |
| 3654 | UINT16 data = | |
| 3655 | 3655 | |
| 3656 | 3656 | typed_pointer tempTP; |
| 3657 | 3657 | tempTP.addr = &data; |
| r8806 | r8807 | |
| 4681 | 4681 | if (W) |
| 4682 | 4682 | { |
| 4683 | 4683 | /* From X:<ea> to SD */ |
| 4684 | UINT16 data = | |
| 4684 | UINT16 data = | |
| 4685 | 4685 | |
| 4686 | 4686 | typed_pointer tempTP; |
| 4687 | 4687 | tempTP.addr = &data; |
| r8806 | r8807 | |
| 4729 | 4729 | if (W) |
| 4730 | 4730 | { |
| 4731 | 4731 | /* Write D */ |
| 4732 | UINT16 value = | |
| 4732 | UINT16 value = | |
| 4733 | 4733 | typed_pointer tempV = {&value, DT_WORD}; |
| 4734 | 4734 | SetDestinationValue(tempV, SD); |
| 4735 | 4735 | } |
| r8806 | r8807 | |
| 4757 | 4757 | if (W) |
| 4758 | 4758 | { |
| 4759 | 4759 | /* Write D */ |
| 4760 | UINT16 tempData = | |
| 4760 | UINT16 tempData = | |
| 4761 | 4761 | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 4762 | 4762 | SetDestinationValue(temp_src, SD); |
| 4763 | 4763 | } |
| r8806 | r8807 | |
| 4793 | 4793 | fatalerror("Dsp56k: Unimplemented access to external X Data Memory >= 0xffc0 in Dual X Memory Data Read."); |
| 4794 | 4794 | |
| 4795 | 4795 | /* First memmove */ |
| 4796 | srcVal1 = | |
| 4796 | srcVal1 = | |
| 4797 | 4797 | tempV.addr = &srcVal1; |
| 4798 | 4798 | tempV.data_type = DT_WORD; |
| 4799 | 4799 | SetDestinationValue(tempV, D1); |
| 4800 | 4800 | |
| 4801 | 4801 | /* Second memmove */ |
| 4802 | srcVal2 = | |
| 4802 | srcVal2 = | |
| 4803 | 4803 | tempV.addr = &srcVal2; |
| 4804 | 4804 | tempV.data_type = DT_WORD; |
| 4805 | 4805 | SetDestinationValue(tempV, D2); |
| r8806 | r8807 | |
| 4895 | 4895 | { |
| 4896 | 4896 | switch(source.data_type) |
| 4897 | 4897 | { |
| 4898 | case DT_BYTE: memory_write_word_16le(cpustate->data, destinationAddr, (UINT16)( (*((UINT8*) source.addr) & 0xff) ) ) ; break ; | |
| 4899 | case DT_WORD: memory_write_word_16le(cpustate->data, destinationAddr, (UINT16)( (*((UINT16*)source.addr) & 0xffff) ) ) ; break ; | |
| 4900 | case DT_DOUBLE_WORD: memory_write_word_16le(cpustate->data, destinationAddr, (UINT16)( (*((UINT32*)source.addr) & 0x0000ffff) ) ) ; break ; | |
| 4898 | case DT_BYTE: cpustate->data->write_word(destinationAddr, (UINT16)( (*((UINT8*) source.addr) & 0xff) ) ) ; break ; | |
| 4899 | case DT_WORD: cpustate->data->write_word(destinationAddr, (UINT16)( (*((UINT16*)source.addr) & 0xffff) ) ) ; break ; | |
| 4900 | case DT_DOUBLE_WORD: cpustate->data->write_word(destinationAddr, (UINT16)( (*((UINT32*)source.addr) & 0x0000ffff) ) ) ; break ; | |
| 4901 | 4901 | |
| 4902 | 4902 | /* !!! Is this universal ??? */ |
| 4903 | 4903 | /* !!! Forget not, yon shift-limiter !!! */ |
| 4904 | case DT_LONG_WORD: | |
| 4904 | case DT_LONG_WORD: | |
| 4905 | 4905 | } |
| 4906 | 4906 | } |
| 4907 | 4907 | |
| r8806 | r8807 | |
| 4910 | 4910 | { |
| 4911 | 4911 | switch(source.data_type) |
| 4912 | 4912 | { |
| 4913 | case DT_BYTE: memory_write_word_16le(cpustate->program, destinationAddr, (UINT16)( (*((UINT8*) source.addr) & 0xff) ) ) ; break ; | |
| 4914 | case DT_WORD: memory_write_word_16le(cpustate->program, destinationAddr, (UINT16)( (*((UINT16*)source.addr) & 0xffff) ) ) ; break ; | |
| 4915 | case DT_DOUBLE_WORD: memory_write_word_16le(cpustate->program, destinationAddr, (UINT16)( (*((UINT32*)source.addr) & 0x0000ffff) ) ) ; break ; | |
| 4913 | case DT_BYTE: cpustate->program->write_word(destinationAddr, (UINT16)( (*((UINT8*) source.addr) & 0xff) ) ) ; break ; | |
| 4914 | case DT_WORD: cpustate->program->write_word(destinationAddr, (UINT16)( (*((UINT16*)source.addr) & 0xffff) ) ) ; break ; | |
| 4915 | case DT_DOUBLE_WORD: cpustate->program->write_word(destinationAddr, (UINT16)( (*((UINT32*)source.addr) & 0x0000ffff) ) ) ; break ; | |
| 4916 | 4916 | |
| 4917 | 4917 | /* !!! Is this universal ??? */ |
| 4918 | 4918 | /* !!! Forget not, yon shift-limiter !!! */ |
| 4919 | case DT_LONG_WORD: | |
| 4919 | case DT_LONG_WORD: | |
| 4920 | 4920 | } |
| 4921 | 4921 | } |
| 4922 | 4922 |
| r8806 | r8807 | |
|---|---|---|
| 53 | 53 | int g_cycles; |
| 54 | 54 | |
| 55 | 55 | legacy_cpu_device *device; |
| 56 | const address_space *program; | |
| 57 | const address_space *io; | |
| 56 | address_space *program; | |
| 57 | address_space *io; | |
| 58 | 58 | }; |
| 59 | 59 | |
| 60 | 60 | INLINE ssp1601_state_t *get_safe_token(running_device *device) |
| r8806 | r8807 | |
| 84 | 84 | #define PPC ssp1601_state->ppc.w.h |
| 85 | 85 | |
| 86 | 86 | #define FETCH() memory_decrypted_read_word(ssp1601_state->program, rPC++ << 1) |
| 87 | #define PROGRAM_WORD(a) | |
| 87 | #define PROGRAM_WORD(a) | |
| 88 | 88 | #define GET_PPC_OFFS() PPC |
| 89 | 89 | |
| 90 | 90 | #define REG_READ(ssp1601_state,r) (((r) <= 4) ? ssp1601_state->gr[r].w.h : reg_read_handlers[r](ssp1601_state, r)) |
| r8806 | r8807 | |
| 255 | 255 | static UINT32 read_ext(ssp1601_state_t *ssp1601_state, int reg) |
| 256 | 256 | { |
| 257 | 257 | reg &= 7; |
| 258 | return | |
| 258 | return | |
| 259 | 259 | } |
| 260 | 260 | |
| 261 | 261 | static void write_ext(ssp1601_state_t *ssp1601_state, int reg, UINT32 d) |
| 262 | 262 | { |
| 263 | 263 | reg &= 7; |
| 264 | | |
| 264 | | |
| 265 | 265 | } |
| 266 | 266 | |
| 267 | 267 | // 4 |
| r8806 | r8807 | |
|---|---|---|
| 137 | 137 | PAIR ea; /* effective address */ |
| 138 | 138 | |
| 139 | 139 | /* Memory spaces */ |
| 140 | | |
| 140 | | |
| 141 | 141 | |
| 142 | 142 | UINT8 int_state; /* SYNC and CWAI flags */ |
| 143 | 143 | UINT8 nmi_state; |
| r8806 | r8807 | |
| 229 | 229 | /****************************************************************************/ |
| 230 | 230 | /* Read a byte from given memory location */ |
| 231 | 231 | /****************************************************************************/ |
| 232 | #define RM(Addr) ((unsigned)m | |
| 232 | #define RM(Addr) ((unsigned)m | |
| 233 | 233 | |
| 234 | 234 | /****************************************************************************/ |
| 235 | 235 | /* Write a byte to given memory location */ |
| 236 | 236 | /****************************************************************************/ |
| 237 | #define WM(Addr,Value) (m | |
| 237 | #define WM(Addr,Value) (m | |
| 238 | 238 | |
| 239 | 239 | /****************************************************************************/ |
| 240 | 240 | /* Z80_RDOP() is identical to Z80_RDMEM() except it is used for reading */ |
| r8806 | r8807 | |
|---|---|---|
| 32 | 32 | UINT16 irq_state, irq_mask; |
| 33 | 33 | device_irq_callback irq_callback; |
| 34 | 34 | legacy_cpu_device *device; |
| 35 | const address_space *program; | |
| 36 | const address_space *io; | |
| 35 | address_space *program; | |
| 36 | address_space *io; | |
| 37 | 37 | int icount; |
| 38 | 38 | int extra_cycles; // extra cycles for interrupts |
| 39 | 39 | UINT8 internal_registers[48]; |
| r8806 | r8807 | |
| 177 | 177 | #define R16D8( N,R,I ) cpustate->mode##N = MODE_R16D8; cpustate->r##N = R; cpustate->r##N##b = I; |
| 178 | 178 | #define R16R8( N,R,g ) cpustate->mode##N = MODE_R16R8; cpustate->r##N = R; cpustate->r##N##b = g; |
| 179 | 179 | |
| 180 | INLINE UINT8 RM8 (t90_Regs *cpustate, UINT32 a) { return | |
| 180 | INLINE UINT8 RM8 (t90_Regs *cpustate, UINT32 a) { return | |
| 181 | 181 | INLINE UINT16 RM16(t90_Regs *cpustate, UINT32 a) { return RM8(cpustate,a) | (RM8( cpustate, (a+1) & 0xffff ) << 8); } |
| 182 | 182 | |
| 183 | INLINE void WM8 (t90_Regs *cpustate, UINT32 a, UINT8 v) { | |
| 183 | INLINE void WM8 (t90_Regs *cpustate, UINT32 a, UINT8 v) { | |
| 184 | 184 | INLINE void WM16(t90_Regs *cpustate, UINT32 a, UINT16 v) { WM8(cpustate,a,v); WM8( cpustate, (a+1) & 0xffff, v >> 8); } |
| 185 | 185 | |
| 186 | INLINE UINT8 RX8 (t90_Regs *cpustate, UINT32 a, UINT32 base) { return | |
| 186 | INLINE UINT8 RX8 (t90_Regs *cpustate, UINT32 a, UINT32 base) { return | |
| 187 | 187 | INLINE UINT16 RX16(t90_Regs *cpustate, UINT32 a, UINT32 base) { return RX8(cpustate,a,base) | (RX8( cpustate, (a+1) & 0xffff, base ) << 8); } |
| 188 | 188 | |
| 189 | INLINE void WX8 (t90_Regs *cpustate, UINT32 a, UINT8 v, UINT32 base) { | |
| 189 | INLINE void WX8 (t90_Regs *cpustate, UINT32 a, UINT8 v, UINT32 base) { | |
| 190 | 190 | INLINE void WX16(t90_Regs *cpustate, UINT32 a, UINT16 v, UINT32 base) { WX8(cpustate,a,v,base); WX8( cpustate, (a+1) & 0xffff, v >> 8, base); } |
| 191 | 191 | |
| 192 | 192 | INLINE UINT8 READ8(t90_Regs *cpustate) { UINT8 b0 = RM8( cpustate, cpustate->addr++ ); cpustate->addr &= 0xffff; return b0; } |
| r8806 | r8807 | |
| 2284 | 2284 | { |
| 2285 | 2285 | t90_Regs *cpustate = get_safe_token(space->cpu); |
| 2286 | 2286 | |
| 2287 | #define RIO | |
| 2287 | #define RIO | |
| 2288 | 2288 | |
| 2289 | 2289 | UINT8 data = cpustate->internal_registers[offset]; |
| 2290 | 2290 | switch ( T90_IOBASE + offset ) |
| r8806 | r8807 | |
| 2495 | 2495 | |
| 2496 | 2496 | static WRITE8_HANDLER( t90_internal_registers_w ) |
| 2497 | 2497 | { |
| 2498 | #define WIO | |
| 2498 | #define WIO cpustate->io-> | |
| 2499 | 2499 | |
| 2500 | 2500 | t90_Regs *cpustate = get_safe_token(space->cpu); |
| 2501 | 2501 | UINT8 out_mask; |
| r8806 | r8807 | |
|---|---|---|
| 43 | 43 | int icount; |
| 44 | 44 | device_irq_callback irq_callback; |
| 45 | 45 | legacy_cpu_device *device; |
| 46 | const address_space *program; | |
| 47 | const address_space *io; | |
| 46 | address_space *program; | |
| 47 | address_space *io; | |
| 48 | 48 | }; |
| 49 | 49 | |
| 50 | 50 | INLINE s2650_regs *get_safe_token(running_device *device) |
| r8806 | r8807 | |
| 151 | 151 | * RDMEM |
| 152 | 152 | * read memory byte from addr |
| 153 | 153 | ***************************************************************/ |
| 154 | #define RDMEM(addr) | |
| 154 | #define RDMEM(addr) | |
| 155 | 155 | |
| 156 | 156 | static void s2650_set_sense(s2650_regs *s2650c, int state); |
| 157 | 157 | |
| r8806 | r8807 | |
| 161 | 161 | |
| 162 | 162 | s2650c->psu = new_val; |
| 163 | 163 | if ((new_val ^ old) & FO) |
| 164 | | |
| 164 | s2650c->io-> | |
| 165 | 165 | } |
| 166 | 166 | |
| 167 | 167 | INLINE UINT8 get_sp(s2650_regs *s2650c) |
| r8806 | r8807 | |
| 532 | 532 | * Store source register to memory addr (CC unchanged) |
| 533 | 533 | ***************************************************************/ |
| 534 | 534 | #define M_STR(address,source) \ |
| 535 | | |
| 535 | | |
| 536 | 536 | |
| 537 | 537 | /*************************************************************** |
| 538 | 538 | * M_AND |
| r8806 | r8807 | |
| 677 | 677 | ***************************************************************/ |
| 678 | 678 | #define M_SPSU() \ |
| 679 | 679 | { \ |
| 680 | R0 = ((s2650c->psu & ~PSU34) | ( | |
| 680 | R0 = ((s2650c->psu & ~PSU34) | (s2650c->io->r | |
| 681 | 681 | SET_CC(R0); \ |
| 682 | 682 | } |
| 683 | 683 | |
| r8806 | r8807 | |
| 746 | 746 | #define M_TPSU() \ |
| 747 | 747 | { \ |
| 748 | 748 | UINT8 tpsu = ARG(s2650c); \ |
| 749 | UINT8 rpsu = (s2650c->psu | ( | |
| 749 | UINT8 rpsu = (s2650c->psu | (s2650c->io->r | |
| 750 | 750 | s2650c->psl &= ~CC; \ |
| 751 | 751 | if( (rpsu & tpsu) != tpsu ) \ |
| 752 | 752 | s2650c->psl |= 0x80; \ |
| r8806 | r8807 | |
| 879 | 879 | { |
| 880 | 880 | /* OR'd with Input to allow for external connections */ |
| 881 | 881 | |
| 882 | return (((s2650c->psu & SI) ? 1 : 0) | (( | |
| 882 | return (((s2650c->psu & SI) ? 1 : 0) | ((s2650c->io->r | |
| 883 | 883 | } |
| 884 | 884 | |
| 885 | 885 | static CPU_EXECUTE( s2650 ) |
| r8806 | r8807 | |
| 1018 | 1018 | case 0x32: /* REDC,2 */ |
| 1019 | 1019 | case 0x33: /* REDC,3 */ |
| 1020 | 1020 | s2650c->icount -= 6; |
| 1021 | s2650c->reg[s2650c->r] = | |
| 1021 | s2650c->reg[s2650c->r] = s2650c->io->r | |
| 1022 | 1022 | SET_CC( s2650c->reg[s2650c->r] ); |
| 1023 | 1023 | break; |
| 1024 | 1024 | |
| r8806 | r8807 | |
| 1108 | 1108 | case 0x56: /* REDE,2 v */ |
| 1109 | 1109 | case 0x57: /* REDE,3 v */ |
| 1110 | 1110 | s2650c->icount -= 9; |
| 1111 | s2650c->reg[s2650c->r] = | |
| 1111 | s2650c->reg[s2650c->r] = s2650c->io->r | |
| 1112 | 1112 | SET_CC(s2650c->reg[s2650c->r]); |
| 1113 | 1113 | break; |
| 1114 | 1114 | |
| r8806 | r8807 | |
| 1167 | 1167 | case 0x72: /* REDD,2 */ |
| 1168 | 1168 | case 0x73: /* REDD,3 */ |
| 1169 | 1169 | s2650c->icount -= 6; |
| 1170 | s2650c->reg[s2650c->r] = | |
| 1170 | s2650c->reg[s2650c->r] = s2650c->io->r | |
| 1171 | 1171 | SET_CC(s2650c->reg[s2650c->r]); |
| 1172 | 1172 | break; |
| 1173 | 1173 | |
| r8806 | r8807 | |
| 1323 | 1323 | case 0xb2: /* WRTC,2 */ |
| 1324 | 1324 | case 0xb3: /* WRTC,3 */ |
| 1325 | 1325 | s2650c->icount -= 6; |
| 1326 | | |
| 1326 | s2650c->io-> | |
| 1327 | 1327 | break; |
| 1328 | 1328 | |
| 1329 | 1329 | case 0xb4: /* TPSU */ |
| r8806 | r8807 | |
| 1409 | 1409 | case 0xd6: /* WRTE,2 v */ |
| 1410 | 1410 | case 0xd7: /* WRTE,3 v */ |
| 1411 | 1411 | s2650c->icount -= 9; |
| 1412 | | |
| 1412 | s2650c->io-> | |
| 1413 | 1413 | break; |
| 1414 | 1414 | |
| 1415 | 1415 | case 0xd8: /* BIRR,0 (*)a */ |
| r8806 | r8807 | |
| 1467 | 1467 | case 0xf2: /* WRTD,2 */ |
| 1468 | 1468 | case 0xf3: /* WRTD,3 */ |
| 1469 | 1469 | s2650c->icount -= 6; |
| 1470 | | |
| 1470 | s2650c->io-> | |
| 1471 | 1471 | break; |
| 1472 | 1472 | |
| 1473 | 1473 | case 0xf4: /* TMI,0 v */ |
| r8806 | r8807 | |
|---|---|---|
| 27 | 27 | UINT32 pc; |
| 28 | 28 | |
| 29 | 29 | legacy_cpu_device *device; |
| 30 | const address_space *program; | |
| 31 | const address_space *io; | |
| 30 | address_space *program; | |
| 31 | address_space *io; | |
| 32 | 32 | int icount; |
| 33 | 33 | }; |
| 34 | 34 | |
| r8806 | r8807 | |
| 115 | 115 | |
| 116 | 116 | INLINE UINT8 READ_PRG_8(avr8_state *cpustate, UINT32 address) |
| 117 | 117 | { |
| 118 | return | |
| 118 | return | |
| 119 | 119 | } |
| 120 | 120 | |
| 121 | 121 | INLINE UINT16 READ_PRG_16(avr8_state *cpustate, UINT32 address) |
| 122 | 122 | { |
| 123 | return | |
| 123 | return | |
| 124 | 124 | } |
| 125 | 125 | |
| 126 | 126 | INLINE void WRITE_PRG_8(avr8_state *cpustate, UINT32 address, UINT8 data) |
| 127 | 127 | { |
| 128 | | |
| 128 | | |
| 129 | 129 | } |
| 130 | 130 | |
| 131 | 131 | INLINE void WRITE_PRG_16(avr8_state *cpustate, UINT32 address, UINT16 data) |
| 132 | 132 | { |
| 133 | | |
| 133 | | |
| 134 | 134 | } |
| 135 | 135 | |
| 136 | 136 | INLINE UINT8 READ_IO_8(avr8_state *cpustate, UINT16 address) |
| 137 | 137 | { |
| 138 | return | |
| 138 | return | |
| 139 | 139 | } |
| 140 | 140 | |
| 141 | 141 | INLINE void WRITE_IO_8(avr8_state *cpustate, UINT16 address, UINT8 data) |
| 142 | 142 | { |
| 143 | | |
| 143 | cpustate->io-> | |
| 144 | 144 | } |
| 145 | 145 | |
| 146 | 146 | INLINE void PUSH(avr8_state *cpustate, UINT8 val) |
| r8806 | r8807 | |
|---|---|---|
| 26 | 26 | { |
| 27 | 27 | const cdp1802_interface *intf; |
| 28 | 28 | |
| 29 | const address_space *program; | |
| 30 | const address_space *io; | |
| 29 | address_space *program; | |
| 30 | address_space *io; | |
| 31 | 31 | |
| 32 | 32 | devcb_resolved_write_line out_q_func; |
| 33 | 33 | devcb_resolved_read8 in_dma_func; |
| r8806 | r8807 | |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | 77 | #define OPCODE_R(addr) memory_decrypted_read_byte(cpustate->program, addr) |
| 78 | #define RAM_R(addr) memory_read_byte_8be(cpustate->program, addr) | |
| 79 | #define RAM_W(addr, data) memory_write_byte_8be(cpustate->program, addr, data) | |
| 80 | #define IO_R(addr) memory_read_byte_8be(cpustate->io, addr) | |
| 81 | #define IO_W(addr, data) memory_write_byte_8be(cpustate->io, addr, data) | |
| 78 | #define RAM_R(addr) cpustate->program->read_byte(addr) | |
| 79 | #define RAM_W(addr, data) cpustate->program->write_byte(addr, data) | |
| 80 | #define IO_R(addr) cpustate->io->read_byte(addr) | |
| 81 | #define IO_W(addr, data) cpustate->io->write_byte(addr, data) | |
| 82 | 82 | |
| 83 | 83 | #define P cpustate->p |
| 84 | 84 | #define X cpustate->x |
| r8806 | r8807 | |
|---|---|---|
| 24 | 24 | |
| 25 | 25 | device_irq_callback irq_callback; |
| 26 | 26 | legacy_cpu_device *device; |
| 27 | | |
| 27 | | |
| 28 | 28 | UINT8 IRQ; |
| 29 | 29 | UINT8 NMI; |
| 30 | 30 | |
| r8806 | r8807 | |
| 65 | 65 | return (se3208_state_t *)downcast<legacy_cpu_device *>(device)->token(); |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | INLINE UINT32 read_dword_unaligned( | |
| 68 | INLINE UINT32 read_dword_unaligned( | |
| 69 | 69 | { |
| 70 | 70 | if (address & 3) |
| 71 | return | |
| 71 | return space->r | |
| 72 | 72 | else |
| 73 | return | |
| 73 | return space->r | |
| 74 | 74 | } |
| 75 | 75 | |
| 76 | INLINE UINT16 read_word_unaligned( | |
| 76 | INLINE UINT16 read_word_unaligned( | |
| 77 | 77 | { |
| 78 | 78 | if (address & 1) |
| 79 | return | |
| 79 | return space->r | |
| 80 | 80 | else |
| 81 | return | |
| 81 | return space->r | |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | INLINE void write_dword_unaligned( | |
| 84 | INLINE void write_dword_unaligned( | |
| 85 | 85 | { |
| 86 | 86 | if (address & 3) |
| 87 | 87 | { |
| 88 | memory_write_byte_32le(space, address, data & 0xff); | |
| 89 | memory_write_byte_32le(space, address+1, (data>>8)&0xff); | |
| 90 | memory_write_byte_32le(space, address+2, (data>>16)&0xff); | |
| 91 | memory_write_byte_32le(space, address+3, (data>>24)&0xff); | |
| 88 | space->write_byte(address, data & 0xff); | |
| 89 | space->write_byte(address+1, (data>>8)&0xff); | |
| 90 | space->write_byte(address+2, (data>>16)&0xff); | |
| 91 | space->write_byte(address+3, (data>>24)&0xff); | |
| 92 | 92 | } |
| 93 | 93 | else |
| 94 | 94 | { |
| 95 | | |
| 95 | space-> | |
| 96 | 96 | } |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | INLINE void write_word_unaligned( | |
| 99 | INLINE void write_word_unaligned( | |
| 100 | 100 | { |
| 101 | 101 | if (address & 1) |
| 102 | 102 | { |
| 103 | memory_write_byte_32le(space, address, data & 0xff); | |
| 104 | memory_write_byte_32le(space, address+1, (data>>8)&0xff); | |
| 103 | space->write_byte(address, data & 0xff); | |
| 104 | space->write_byte(address+1, (data>>8)&0xff); | |
| 105 | 105 | } |
| 106 | 106 | else |
| 107 | 107 | { |
| 108 | | |
| 108 | space-> | |
| 109 | 109 | } |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | 112 | |
| 113 | 113 | INLINE UINT8 SE3208_Read8(se3208_state_t *se3208_state, UINT32 addr) |
| 114 | 114 | { |
| 115 | return | |
| 115 | return | |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | 118 | INLINE UINT16 SE3208_Read16(se3208_state_t *se3208_state, UINT32 addr) |
| r8806 | r8807 | |
| 127 | 127 | |
| 128 | 128 | INLINE void SE3208_Write8(se3208_state_t *se3208_state, UINT32 addr,UINT8 val) |
| 129 | 129 | { |
| 130 | | |
| 130 | | |
| 131 | 131 | } |
| 132 | 132 | |
| 133 | 133 | INLINE void SE3208_Write16(se3208_state_t *se3208_state, UINT32 addr,UINT16 val) |
| r8806 | r8807 | |
|---|---|---|
| 320 | 320 | |
| 321 | 321 | device_irq_callback irq_callback; |
| 322 | 322 | legacy_cpu_device *device; |
| 323 | const address_space *program; | |
| 324 | const address_space *io; | |
| 323 | address_space *program; | |
| 324 | address_space *io; | |
| 325 | 325 | UINT32 opcodexor; |
| 326 | 326 | |
| 327 | 327 | INT32 instruction_length; |
| r8806 | r8807 | |
|---|---|---|
| 42 | 42 | |
| 43 | 43 | /* Memory access */ |
| 44 | 44 | /* read byte */ |
| 45 | #define READ_B(H,addr) | |
| 45 | #define READ_B(H,addr) | |
| 46 | 46 | /* read half-word */ |
| 47 | #define READ_HW(H,addr) | |
| 47 | #define READ_HW(H,addr) | |
| 48 | 48 | /* read word */ |
| 49 | #define READ_W(H,addr) | |
| 49 | #define READ_W(H,addr) (H)->program->read_dword( | |
| 50 | 50 | |
| 51 | 51 | /* write byte */ |
| 52 | #define WRITE_B(H,addr, data) | |
| 52 | #define WRITE_B(H,addr, data) (H)->program->write_byte( | |
| 53 | 53 | /* write half-word */ |
| 54 | #define WRITE_HW(H,addr, data) | |
| 54 | #define WRITE_HW(H,addr, data) (H)->program->write_word( | |
| 55 | 55 | /* write word */ |
| 56 | #define WRITE_W(H,addr, data) | |
| 56 | #define WRITE_W(H,addr, data) (H)->program->write_dword( | |
| 57 | 57 | |
| 58 | 58 | |
| 59 | 59 | /* I/O access */ |
| 60 | 60 | /* read word */ |
| 61 | #define IO_READ_W(H,addr) | |
| 61 | #define IO_READ_W(H,addr) (H)->io->r | |
| 62 | 62 | /* write word */ |
| 63 | #define IO_WRITE_W(H,addr, data) | |
| 63 | #define IO_WRITE_W(H,addr, data) (H)->io-> | |
| 64 | 64 | |
| 65 | 65 | |
| 66 | 66 | #define READ_OP(H,addr) memory_decrypted_read_word((H)->program, (addr) ^ (H)->opcodexor) |
| r8806 | r8807 | |
|---|---|---|
| 369 | 369 | |
| 370 | 370 | /* Since i860 instructions are always stored LSB first (regardless of |
| 371 | 371 | the BE bit), we need to adjust the instruction below on MSB hosts. */ |
| 372 | w1 = | |
| 372 | w1 = | |
| 373 | 373 | #ifdef HOST_MSB |
| 374 | 374 | BYTE_REV32 (w1); |
| 375 | 375 | #endif /* HOST_MSB. */ |
| r8806 | r8807 | |
| 407 | 407 | |
| 408 | 408 | /* Get page directory entry at DTB:DIR:00. */ |
| 409 | 409 | pg_dir_entry_a = dtb | (vdir << 2); |
| 410 | pg_dir_entry = | |
| 410 | pg_dir_entry = | |
| 411 | 411 | #ifdef HOST_MSB |
| 412 | 412 | BYTE_REV32 (pg_dir_entry); |
| 413 | 413 | #endif |
| r8806 | r8807 | |
| 455 | 455 | /* Get page table entry at PFA1:PAGE:00. */ |
| 456 | 456 | pfa1 = pg_dir_entry & 0xfffff000; |
| 457 | 457 | pg_tbl_entry_a = pfa1 | (vpage << 2); |
| 458 | pg_tbl_entry = | |
| 458 | pg_tbl_entry = | |
| 459 | 459 | #ifdef HOST_MSB |
| 460 | 460 | BYTE_REV32 (pg_tbl_entry); |
| 461 | 461 | #endif |
| r8806 | r8807 | |
| 505 | 505 | BYTE_REV32 (ttpde); |
| 506 | 506 | BYTE_REV32 (ttpte); |
| 507 | 507 | #endif |
| 508 | memory_write_dword_64le(cpustate->program, pg_dir_entry_a, ttpde); | |
| 509 | memory_write_dword_64le(cpustate->program, pg_tbl_entry_a, ttpte); | |
| 508 | cpustate->program->write_dword(pg_dir_entry_a, ttpde); | |
| 509 | cpustate->program->write_dword(pg_tbl_entry_a, ttpte); | |
| 510 | 510 | |
| 511 | 511 | if (is_write && is_dataref && (pg_tbl_entry & 0x40) == 0) |
| 512 | 512 | { |
| r8806 | r8807 | |
| 567 | 567 | /* Now do the actual read. */ |
| 568 | 568 | if (size == 1) |
| 569 | 569 | { |
| 570 | UINT32 ret = | |
| 570 | UINT32 ret = | |
| 571 | 571 | return ret & 0xff; |
| 572 | 572 | } |
| 573 | 573 | else if (size == 2) |
| 574 | 574 | { |
| 575 | UINT32 ret = | |
| 575 | UINT32 ret = | |
| 576 | 576 | #ifdef HOST_MSB |
| 577 | 577 | BYTE_REV16 (ret); |
| 578 | 578 | #endif |
| r8806 | r8807 | |
| 580 | 580 | } |
| 581 | 581 | else if (size == 4) |
| 582 | 582 | { |
| 583 | UINT32 ret = | |
| 583 | UINT32 ret = | |
| 584 | 584 | #ifdef HOST_MSB |
| 585 | 585 | BYTE_REV32 (ret); |
| 586 | 586 | #endif |
| r8806 | r8807 | |
| 630 | 630 | |
| 631 | 631 | /* Now do the actual write. */ |
| 632 | 632 | if (size == 1) |
| 633 | | |
| 633 | | |
| 634 | 634 | else if (size == 2) |
| 635 | 635 | { |
| 636 | 636 | #ifdef HOST_MSB |
| 637 | 637 | BYTE_REV16 (data); |
| 638 | 638 | #endif |
| 639 | | |
| 639 | | |
| 640 | 640 | } |
| 641 | 641 | else if (size == 4) |
| 642 | 642 | { |
| 643 | 643 | #ifdef HOST_MSB |
| 644 | 644 | BYTE_REV32 (data); |
| 645 | 645 | #endif |
| 646 | | |
| 646 | | |
| 647 | 647 | } |
| 648 | 648 | else |
| 649 | 649 | assert (0); |
| r8806 | r8807 | |
| 689 | 689 | |
| 690 | 690 | if (size == 4) |
| 691 | 691 | { |
| 692 | dest[0] = memory_read_byte_64le(cpustate->program, addr+3); | |
| 693 | dest[1] = memory_read_byte_64le(cpustate->program, addr+2); | |
| 694 | dest[2] = memory_read_byte_64le(cpustate->program, addr+1); | |
| 695 | dest[3] = memory_read_byte_64le(cpustate->program, addr+0); | |
| 692 | dest[0] = cpustate->program->read_byte(addr+3); | |
| 693 | dest[1] = cpustate->program->read_byte(addr+2); | |
| 694 | dest[2] = cpustate->program->read_byte(addr+1); | |
| 695 | dest[3] = cpustate->program->read_byte(addr+0); | |
| 696 | 696 | } |
| 697 | 697 | else if (size == 8) |
| 698 | 698 | { |
| 699 | dest[0] = memory_read_byte_64le(cpustate->program, addr+7); | |
| 700 | dest[1] = memory_read_byte_64le(cpustate->program, addr+6); | |
| 701 | dest[2] = memory_read_byte_64le(cpustate->program, addr+5); | |
| 702 | dest[3] = memory_read_byte_64le(cpustate->program, addr+4); | |
| 703 | dest[4] = memory_read_byte_64le(cpustate->program, addr+3); | |
| 704 | dest[5] = memory_read_byte_64le(cpustate->program, addr+2); | |
| 705 | dest[6] = memory_read_byte_64le(cpustate->program, addr+1); | |
| 706 | dest[7] = memory_read_byte_64le(cpustate->program, addr+0); | |
| 699 | dest[0] = cpustate->program->read_byte(addr+7); | |
| 700 | dest[1] = cpustate->program->read_byte(addr+6); | |
| 701 | dest[2] = cpustate->program->read_byte(addr+5); | |
| 702 | dest[3] = cpustate->program->read_byte(addr+4); | |
| 703 | dest[4] = cpustate->program->read_byte(addr+3); | |
| 704 | dest[5] = cpustate->program->read_byte(addr+2); | |
| 705 | dest[6] = cpustate->program->read_byte(addr+1); | |
| 706 | dest[7] = cpustate->program->read_byte(addr+0); | |
| 707 | 707 | } |
| 708 | 708 | else if (size == 16) |
| 709 | 709 | { |
| 710 | 710 | int i; |
| 711 | 711 | for (i = 0; i < 16; i++) |
| 712 | 712 | { |
| 713 | dest[i] = | |
| 713 | dest[i] = | |
| 714 | 714 | } |
| 715 | 715 | } |
| 716 | 716 | } |
| r8806 | r8807 | |
| 757 | 757 | if (size == 4) |
| 758 | 758 | { |
| 759 | 759 | #if 1 |
| 760 | memory_write_byte_64le(cpustate->program, addr+3, data[0]); | |
| 761 | memory_write_byte_64le(cpustate->program, addr+2, data[1]); | |
| 762 | memory_write_byte_64le(cpustate->program, addr+1, data[2]); | |
| 763 | memory_write_byte_64le(cpustate->program, addr+0, data[3]); | |
| 760 | cpustate->program->write_byte(addr+3, data[0]); | |
| 761 | cpustate->program->write_byte(addr+2, data[1]); | |
| 762 | cpustate->program->write_byte(addr+1, data[2]); | |
| 763 | cpustate->program->write_byte(addr+0, data[3]); | |
| 764 | 764 | #else |
| 765 | 765 | UINT32 ddd = (data[3]) | (data[2] << 8) | (data[1] << 16) |(data[0] << 24); |
| 766 | | |
| 766 | | |
| 767 | 767 | #endif |
| 768 | 768 | } |
| 769 | 769 | else if (size == 8) |
| r8806 | r8807 | |
| 771 | 771 | /* Special: watch for wmask != 0xff, which means we're doing pst.d. */ |
| 772 | 772 | if (wmask == 0xff) |
| 773 | 773 | { |
| 774 | memory_write_byte_64le(cpustate->program, addr+7, data[0]); | |
| 775 | memory_write_byte_64le(cpustate->program, addr+6, data[1]); | |
| 776 | memory_write_byte_64le(cpustate->program, addr+5, data[2]); | |
| 777 | memory_write_byte_64le(cpustate->program, addr+4, data[3]); | |
| 778 | memory_write_byte_64le(cpustate->program, addr+3, data[4]); | |
| 779 | memory_write_byte_64le(cpustate->program, addr+2, data[5]); | |
| 780 | memory_write_byte_64le(cpustate->program, addr+1, data[6]); | |
| 781 | memory_write_byte_64le(cpustate->program, addr+0, data[7]); | |
| 774 | cpustate->program->write_byte(addr+7, data[0]); | |
| 775 | cpustate->program->write_byte(addr+6, data[1]); | |
| 776 | cpustate->program->write_byte(addr+5, data[2]); | |
| 777 | cpustate->program->write_byte(addr+4, data[3]); | |
| 778 | cpustate->program->write_byte(addr+3, data[4]); | |
| 779 | cpustate->program->write_byte(addr+2, data[5]); | |
| 780 | cpustate->program->write_byte(addr+1, data[6]); | |
| 781 | cpustate->program->write_byte(addr+0, data[7]); | |
| 782 | 782 | } |
| 783 | 783 | else |
| 784 | 784 | { |
| 785 | if (wmask & 0x80) memory_write_byte_64le(cpustate->program, addr+7, data[0]); | |
| 786 | if (wmask & 0x40) memory_write_byte_64le(cpustate->program, addr+6, data[1]); | |
| 787 | if (wmask & 0x20) memory_write_byte_64le(cpustate->program, addr+5, data[2]); | |
| 788 | if (wmask & 0x10) memory_write_byte_64le(cpustate->program, addr+4, data[3]); | |
| 789 | if (wmask & 0x08) memory_write_byte_64le(cpustate->program, addr+3, data[4]); | |
| 790 | if (wmask & 0x04) memory_write_byte_64le(cpustate->program, addr+2, data[5]); | |
| 791 | if (wmask & 0x02) memory_write_byte_64le(cpustate->program, addr+1, data[6]); | |
| 792 | if (wmask & 0x01) memory_write_byte_64le(cpustate->program, addr+0, data[7]); | |
| 785 | if (wmask & 0x80) cpustate->program->write_byte(addr+7, data[0]); | |
| 786 | if (wmask & 0x40) cpustate->program->write_byte(addr+6, data[1]); | |
| 787 | if (wmask & 0x20) cpustate->program->write_byte(addr+5, data[2]); | |
| 788 | if (wmask & 0x10) cpustate->program->write_byte(addr+4, data[3]); | |
| 789 | if (wmask & 0x08) cpustate->program->write_byte(addr+3, data[4]); | |
| 790 | if (wmask & 0x04) cpustate->program->write_byte(addr+2, data[5]); | |
| 791 | if (wmask & 0x02) cpustate->program->write_byte(addr+1, data[6]); | |
| 792 | if (wmask & 0x01) cpustate->program->write_byte(addr+0, data[7]); | |
| 793 | 793 | } |
| 794 | 794 | } |
| 795 | 795 | else if (size == 16) |
| r8806 | r8807 | |
| 797 | 797 | int i; |
| 798 | 798 | for (i = 0; i < 16; i++) |
| 799 | 799 | { |
| 800 | | |
| 800 | | |
| 801 | 801 | } |
| 802 | 802 | } |
| 803 | 803 | |
| r8806 | r8807 | |
| 4552 | 4552 | /* Note that we print the incoming (possibly virtual) address as the |
| 4553 | 4553 | PC rather than the translated address. */ |
| 4554 | 4554 | fprintf (stderr, " (%s) 0x%08x: ", cpustate->device->tag(), addr); |
| 4555 | insn = | |
| 4555 | insn = | |
| 4556 | 4556 | #ifdef HOST_MSB |
| 4557 | 4557 | BYTE_REV32 (insn); |
| 4558 | 4558 | #endif /* HOST_MSB. */ |
| r8806 | r8807 | |
| 4584 | 4584 | if (GET_DIRBASE_ATE ()) |
| 4585 | 4585 | phys_addr = get_address_translation (cpustate, addr, 1 /* is_dataref */, 0 /* is_write */); |
| 4586 | 4586 | |
| 4587 | b[i] = | |
| 4587 | b[i] = | |
| 4588 | 4588 | fprintf (stderr, "%02x ", b[i]); |
| 4589 | 4589 | addr++; |
| 4590 | 4590 | } |
| r8806 | r8807 | |
|---|---|---|
| 169 | 169 | * MAME-specific stuff. |
| 170 | 170 | */ |
| 171 | 171 | legacy_cpu_device *device; |
| 172 | | |
| 172 | | |
| 173 | 173 | UINT32 ppc; |
| 174 | 174 | int icount; |
| 175 | 175 |
| r8806 | r8807 | |
|---|---|---|
| 285 | 285 | legacy_cpu_device *device; |
| 286 | 286 | |
| 287 | 287 | /* Memory spaces */ |
| 288 | const address_space *program; | |
| 289 | const address_space *data; | |
| 290 | const address_space *io; | |
| 288 | address_space *program; | |
| 289 | address_space *data; | |
| 290 | address_space *io; | |
| 291 | 291 | |
| 292 | 292 | /* Serial Port TX/RX Callbacks */ |
| 293 | 293 | // TODO: Move to special port r/w |
| r8806 | r8807 | |
| 314 | 314 | #define ROP_ARG(pc) memory_raw_read_byte(mcs51_state->program, pc) |
| 315 | 315 | |
| 316 | 316 | /* Read a byte from External Code Memory (Usually Program Rom(s) Space) */ |
| 317 | #define CODEMEM_R(a) (UINT8)m | |
| 317 | #define CODEMEM_R(a) (UINT8)m | |
| 318 | 318 | |
| 319 | 319 | /* Read/Write a byte from/to External Data Memory (Usually RAM or other I/O) */ |
| 320 | #define DATAMEM_R(a) (UINT8)memory_read_byte_8le(mcs51_state->io, a) | |
| 321 | #define DATAMEM_W(a,v) memory_write_byte_8le(mcs51_state->io, a, v) | |
| 320 | #define DATAMEM_R(a) (UINT8)mcs51_state->io->read_byte(a) | |
| 321 | #define DATAMEM_W(a,v) mcs51_state->io->write_byte(a, v) | |
| 322 | 322 | |
| 323 | 323 | /* Read/Write a byte from/to the Internal RAM */ |
| 324 | 324 | |
| r8806 | r8807 | |
| 327 | 327 | |
| 328 | 328 | /* Read/Write a byte from/to the Internal RAM indirectly */ |
| 329 | 329 | /* (called from indirect addressing) */ |
| 330 | INLINE UINT8 iram_iread(mcs51_state_t *mcs51_state, offs_t a) { return (a <= mcs51_state->ram_mask) ? memory_read_byte_8le(mcs51_state->data, a) : 0xff; } | |
| 331 | INLINE void iram_iwrite(mcs51_state_t *mcs51_state, offs_t a, UINT8 d) { if (a <= mcs51_state->ram_mask) memory_write_byte_8le(mcs51_state->data, a, d); } | |
| 330 | INLINE UINT8 iram_iread(mcs51_state_t *mcs51_state, offs_t a) { return (a <= mcs51_state->ram_mask) ? mcs51_state->data->read_byte(a) : 0xff; } | |
| 331 | INLINE void iram_iwrite(mcs51_state_t *mcs51_state, offs_t a, UINT8 d) { if (a <= mcs51_state->ram_mask) mcs51_state->data->write_byte(a, d); } | |
| 332 | 332 | |
| 333 | 333 | #define IRAM_IR(a) iram_iread(mcs51_state, a) |
| 334 | 334 | #define IRAM_IW(a, d) iram_iwrite(mcs51_state, a, d) |
| r8806 | r8807 | |
| 342 | 342 | #define BIT_W(a,v) bit_address_w(mcs51_state, a, v) |
| 343 | 343 | |
| 344 | 344 | /* Input/Output a byte from given I/O port */ |
| 345 | #define IN(port) ((UINT8)memory_read_byte(mcs51_state->io, port)) | |
| 346 | #define OUT(port,value) memory_write_byte(mcs51_state->io, port,value) | |
| 345 | #define IN(port) ((UINT8)mcs51_state->io->read_byte(port)) | |
| 346 | #define OUT(port,value) mcs51_state->io->write_byte(port,value) | |
| 347 | 347 | |
| 348 | 348 | |
| 349 | 349 | /*************************************************************************** |
| r8806 | r8807 | |
| 757 | 757 | |
| 758 | 758 | INLINE UINT8 iram_read(mcs51_state_t *mcs51_state, size_t offset) |
| 759 | 759 | { |
| 760 | return (((offset) < 0x80) ? m | |
| 760 | return (((offset) < 0x80) ? m | |
| 761 | 761 | } |
| 762 | 762 | |
| 763 | 763 | INLINE void iram_write(mcs51_state_t *mcs51_state, size_t offset, UINT8 data) |
| 764 | 764 | { |
| 765 | 765 | if ((offset) < 0x80) |
| 766 | m | |
| 766 | m | |
| 767 | 767 | else |
| 768 | 768 | mcs51_state->sfr_write(mcs51_state, offset, data); |
| 769 | 769 | } |
| r8806 | r8807 | |
| 2024 | 2024 | /* no write in this case according to manual */ |
| 2025 | 2025 | return; |
| 2026 | 2026 | } |
| 2027 | m | |
| 2027 | m | |
| 2028 | 2028 | } |
| 2029 | 2029 | |
| 2030 | 2030 | static UINT8 mcs51_sfr_read(mcs51_state_t *mcs51_state, size_t offset) |
| r8806 | r8807 | |
| 2057 | 2057 | case ADDR_SBUF: |
| 2058 | 2058 | case ADDR_IE: |
| 2059 | 2059 | case ADDR_IP: |
| 2060 | return m | |
| 2060 | return m | |
| 2061 | 2061 | /* Illegal or non-implemented sfr */ |
| 2062 | 2062 | default: |
| 2063 | 2063 | LOG(("mcs51 '%s': attemping to read an invalid/non-implemented SFR address: %x at 0x%04x\n", mcs51_state->device->tag(), (UINT32)offset,PC)); |
| r8806 | r8807 | |
| 2212 | 2212 | case ADDR_RCAP2H: |
| 2213 | 2213 | case ADDR_TL2: |
| 2214 | 2214 | case ADDR_TH2: |
| 2215 | m | |
| 2215 | m | |
| 2216 | 2216 | break; |
| 2217 | 2217 | |
| 2218 | 2218 | default: |
| r8806 | r8807 | |
| 2230 | 2230 | case ADDR_RCAP2H: |
| 2231 | 2231 | case ADDR_TL2: |
| 2232 | 2232 | case ADDR_TH2: |
| 2233 | return m | |
| 2233 | return m | |
| 2234 | 2234 | default: |
| 2235 | 2235 | return mcs51_sfr_read(mcs51_state, offset); |
| 2236 | 2236 | } |
| r8806 | r8807 | |
| 2272 | 2272 | i8052_sfr_write(mcs51_state, offset, data); |
| 2273 | 2273 | return; |
| 2274 | 2274 | } |
| 2275 | m | |
| 2275 | m | |
| 2276 | 2276 | } |
| 2277 | 2277 | |
| 2278 | 2278 | static UINT8 i80c52_sfr_read(mcs51_state_t *mcs51_state, size_t offset) |
| r8806 | r8807 | |
| 2283 | 2283 | case ADDR_IPH: |
| 2284 | 2284 | case ADDR_SADDR: |
| 2285 | 2285 | case ADDR_SADEN: |
| 2286 | return m | |
| 2286 | return m | |
| 2287 | 2287 | default: |
| 2288 | 2288 | return i8052_sfr_read(mcs51_state, offset); |
| 2289 | 2289 | } |
| r8806 | r8807 | |
| 2355 | 2355 | mcs51_sfr_write(mcs51_state, offset, data); |
| 2356 | 2356 | return; |
| 2357 | 2357 | } |
| 2358 | m | |
| 2358 | m | |
| 2359 | 2359 | } |
| 2360 | 2360 | |
| 2361 | 2361 | static UINT8 ds5002fp_sfr_read(mcs51_state_t *mcs51_state, size_t offset) |
| r8806 | r8807 | |
| 2376 | 2376 | default: |
| 2377 | 2377 | return mcs51_sfr_read(mcs51_state, offset); |
| 2378 | 2378 | } |
| 2379 | return m | |
| 2379 | return m | |
| 2380 | 2380 | } |
| 2381 | 2381 | |
| 2382 | 2382 | static CPU_INIT( ds5002fp ) |
| r8806 | r8807 | |
|---|---|---|
| 228 | 228 | UINT8 irq_state; |
| 229 | 229 | device_irq_callback irq_callback; |
| 230 | 230 | legacy_cpu_device *device; |
| 231 | const address_space *program; | |
| 232 | const address_space *io; | |
| 231 | address_space *program; | |
| 232 | address_space *io; | |
| 233 | 233 | UINT32 a20_mask; |
| 234 | 234 | |
| 235 | 235 | int cpuid_max_input_value_eax; |
| r8806 | r8807 | |
| 349 | 349 | UINT32 page_entry; |
| 350 | 350 | |
| 351 | 351 | // TODO: 4MB pages |
| 352 | UINT32 page_dir = | |
| 352 | UINT32 page_dir = | |
| 353 | 353 | if (!(cpustate->cr[4] & 0x10)) { |
| 354 | page_entry = | |
| 354 | page_entry = | |
| 355 | 355 | *address = (page_entry & 0xfffff000) | offset; |
| 356 | 356 | } else { |
| 357 | 357 | if (page_dir & 0x80) |
| 358 | 358 | *address = (page_dir & 0xffc00000) | (a & 0x003fffff); |
| 359 | 359 | else { |
| 360 | page_entry = | |
| 360 | page_entry = | |
| 361 | 361 | *address = (page_entry & 0xfffff000) | offset; |
| 362 | 362 | } |
| 363 | 363 | } |
| r8806 | r8807 | |
| 461 | 461 | } |
| 462 | 462 | |
| 463 | 463 | address &= cpustate->a20_mask; |
| 464 | return | |
| 464 | return | |
| 465 | 465 | } |
| 466 | 466 | INLINE UINT16 READ16(i386_state *cpustate,UINT32 ea) |
| 467 | 467 | { |
| r8806 | r8807 | |
| 478 | 478 | } |
| 479 | 479 | |
| 480 | 480 | address &= cpustate->a20_mask; |
| 481 | value = | |
| 481 | value = | |
| 482 | 482 | } |
| 483 | 483 | return value; |
| 484 | 484 | } |
| r8806 | r8807 | |
| 499 | 499 | } |
| 500 | 500 | |
| 501 | 501 | address &= cpustate->a20_mask; |
| 502 | value = | |
| 502 | value = | |
| 503 | 503 | } |
| 504 | 504 | return value; |
| 505 | 505 | } |
| r8806 | r8807 | |
| 525 | 525 | } |
| 526 | 526 | |
| 527 | 527 | address &= cpustate->a20_mask; |
| 528 | value = (((UINT64) memory_read_dword_32le( cpustate->program, address+0 )) << 0) | | |
| 529 | (((UINT64) memory_read_dword_32le( cpustate->program, address+4 )) << 32); | |
| 528 | value = (((UINT64) cpustate->program->read_dword( address+0 )) << 0) | | |
| 529 | (((UINT64) cpustate->program->read_dword( address+4 )) << 32); | |
| 530 | 530 | } |
| 531 | 531 | return value; |
| 532 | 532 | } |
| r8806 | r8807 | |
| 541 | 541 | } |
| 542 | 542 | |
| 543 | 543 | address &= cpustate->a20_mask; |
| 544 | | |
| 544 | | |
| 545 | 545 | } |
| 546 | 546 | INLINE void WRITE16(i386_state *cpustate,UINT32 ea, UINT16 value) |
| 547 | 547 | { |
| r8806 | r8807 | |
| 557 | 557 | } |
| 558 | 558 | |
| 559 | 559 | address &= cpustate->a20_mask; |
| 560 | | |
| 560 | | |
| 561 | 561 | } |
| 562 | 562 | } |
| 563 | 563 | INLINE void WRITE32(i386_state *cpustate,UINT32 ea, UINT32 value) |
| r8806 | r8807 | |
| 576 | 576 | } |
| 577 | 577 | |
| 578 | 578 | ea &= cpustate->a20_mask; |
| 579 | | |
| 579 | | |
| 580 | 580 | } |
| 581 | 581 | } |
| 582 | 582 | |
| r8806 | r8807 | |
| 600 | 600 | } |
| 601 | 601 | |
| 602 | 602 | ea &= cpustate->a20_mask; |
| 603 | memory_write_dword_32le(cpustate->program, address+0, value & 0xffffffff); | |
| 604 | memory_write_dword_32le(cpustate->program, address+4, (value >> 32) & 0xffffffff); | |
| 603 | cpustate->program->write_dword(address+0, value & 0xffffffff); | |
| 604 | cpustate->program->write_dword(address+4, (value >> 32) & 0xffffffff); | |
| 605 | 605 | } |
| 606 | 606 | } |
| 607 | 607 | |
| r8806 | r8807 | |
| 892 | 892 | |
| 893 | 893 | /***********************************************************************************/ |
| 894 | 894 | |
| 895 | #define READPORT8(port) (memory_read_byte_32le(cpustate->io, port)) | |
| 896 | #define READPORT16(port) (memory_read_word_32le(cpustate->io, port)) | |
| 897 | #define READPORT32(port) (memory_read_dword_32le(cpustate->io, port)) | |
| 898 | #define WRITEPORT8(port, value) (memory_write_byte_32le(cpustate->io, port, value)) | |
| 899 | #define WRITEPORT16(port, value) (memory_write_word_32le(cpustate->io, port, value)) | |
| 900 | #define WRITEPORT32(port, value) (memory_write_dword_32le(cpustate->io, port, value)) | |
| 895 | #define READPORT8(port) (cpustate->io->read_byte(port)) | |
| 896 | #define READPORT16(port) (cpustate->io->read_word(port)) | |
| 897 | #define READPORT32(port) (cpustate->io->read_dword(port)) | |
| 898 | #define WRITEPORT8(port, value) (cpustate->io->write_byte(port, value)) | |
| 899 | #define WRITEPORT16(port, value) (cpustate->io->write_word(port, value)) | |
| 900 | #define WRITEPORT32(port, value) (cpustate->io->write_dword(port, value)) | |
| 901 | 901 | |
| 902 | 902 | #endif /* __I386_H__ */ |
| r8806 | r8807 | |
|---|---|---|
| 10 | 10 | |
| 11 | 11 | static const char *const mac_xop[] = { "MX0", "MX1", "AR", "MR0", "MR1", "MR2", "SR0", "SR1" }; |
| 12 | 12 | static const char *const mac_yop[] = { "MY0", "MY1", "MF", "0" }; |
| 13 | static const char *const mac_dst[] = { "MR", "MF" }; | |
| 13 | static const char *const mac_dst[] = { "MR", "MF", "NONE" }; | |
| 14 | 14 | |
| 15 | 15 | static const char *const shift_xop[] = { "SI", "??", "AR", "MR0", "MR1", "MR2", "SR0", "SR1" }; |
| 16 | 16 |
| r8806 | r8807 | |
|---|---|---|
| 263 | 263 | adsp21xx_timer_func timer_fired; |
| 264 | 264 | |
| 265 | 265 | /* memory spaces */ |
| 266 | const address_space *program; | |
| 267 | const address_space *data; | |
| 268 | const address_space *io; | |
| 266 | address_space *program; | |
| 267 | address_space *data; | |
| 268 | address_space *io; | |
| 269 | 269 | |
| 270 | 270 | } adsp2100_state; |
| 271 | 271 | |
| r8806 | r8807 | |
| 318 | 318 | |
| 319 | 319 | INLINE UINT16 RWORD_DATA(adsp2100_state *adsp, UINT32 addr) |
| 320 | 320 | { |
| 321 | return | |
| 321 | return | |
| 322 | 322 | } |
| 323 | 323 | |
| 324 | 324 | INLINE void WWORD_DATA(adsp2100_state *adsp, UINT32 addr, UINT16 data) |
| 325 | 325 | { |
| 326 | | |
| 326 | adsp->data->write_word | |
| 327 | 327 | } |
| 328 | 328 | |
| 329 | 329 | INLINE UINT16 RWORD_IO(adsp2100_state *adsp, UINT32 addr) |
| 330 | 330 | { |
| 331 | return | |
| 331 | return adsp->io->r | |
| 332 | 332 | } |
| 333 | 333 | |
| 334 | 334 | INLINE void WWORD_IO(adsp2100_state *adsp, UINT32 addr, UINT16 data) |
| 335 | 335 | { |
| 336 | | |
| 336 | adsp->io-> | |
| 337 | 337 | } |
| 338 | 338 | |
| 339 | 339 | INLINE UINT32 RWORD_PGM(adsp2100_state *adsp, UINT32 addr) |
| 340 | 340 | { |
| 341 | return | |
| 341 | return | |
| 342 | 342 | } |
| 343 | 343 | |
| 344 | 344 | INLINE void WWORD_PGM(adsp2100_state *adsp, UINT32 addr, UINT32 data) |
| 345 | 345 | { |
| 346 | | |
| 346 | adsp->program->write_dword | |
| 347 | 347 | } |
| 348 | 348 | |
| 349 | 349 | #define ROPCODE(a) memory_decrypted_read_dword((a)->program, (a)->pc << 2) |
| r8806 | r8807 | |
|---|---|---|
| 62 | 62 | device_irq_callback irq_callback; |
| 63 | 63 | UINT8 irq_state[2]; |
| 64 | 64 | legacy_cpu_device *device; |
| 65 | const address_space *program; | |
| 66 | const address_space *io; | |
| 65 | address_space *program; | |
| 66 | address_space *io; | |
| 67 | 67 | int icount; |
| 68 | 68 | |
| 69 | 69 | int ram_position; |
| r8806 | r8807 | |
| 97 | 97 | switch(reg) |
| 98 | 98 | { |
| 99 | 99 | case 0x00: /* PORTA */ |
| 100 | return | |
| 100 | return | |
| 101 | 101 | case 0x01: /* DDRA */ |
| 102 | 102 | return 0; |
| 103 | 103 | case 0x02: /* PIOC */ |
| 104 | 104 | return 0; |
| 105 | 105 | case 0x03: /* PORTC */ |
| 106 | return | |
| 106 | return | |
| 107 | 107 | case 0x04: /* PORTB */ |
| 108 | return | |
| 108 | return | |
| 109 | 109 | case 0x08: /* PORTD */ |
| 110 | return | |
| 110 | return | |
| 111 | 111 | case 0x09: /* DDRD */ |
| 112 | 112 | return 0; |
| 113 | 113 | case 0x0a: /* PORTE */ |
| 114 | return | |
| 114 | return | |
| 115 | 115 | case 0x23: |
| 116 | 116 | return cpustate->tflg1; |
| 117 | 117 | case 0x28: /* SPCR1 */ |
| r8806 | r8807 | |
| 122 | 122 | { |
| 123 | 123 | if (cpustate->adctl & 0x10) |
| 124 | 124 | { |
| 125 | return | |
| 125 | return | |
| 126 | 126 | } |
| 127 | 127 | else |
| 128 | 128 | { |
| 129 | return | |
| 129 | return | |
| 130 | 130 | } |
| 131 | 131 | } |
| 132 | 132 | case 0x32: /* ADR2 */ |
| 133 | 133 | { |
| 134 | 134 | if (cpustate->adctl & 0x10) |
| 135 | 135 | { |
| 136 | return | |
| 136 | return | |
| 137 | 137 | } |
| 138 | 138 | else |
| 139 | 139 | { |
| 140 | return | |
| 140 | return | |
| 141 | 141 | } |
| 142 | 142 | } |
| 143 | 143 | case 0x33: /* ADR3 */ |
| 144 | 144 | { |
| 145 | 145 | if (cpustate->adctl & 0x10) |
| 146 | 146 | { |
| 147 | return | |
| 147 | return | |
| 148 | 148 | } |
| 149 | 149 | else |
| 150 | 150 | { |
| 151 | return | |
| 151 | return | |
| 152 | 152 | } |
| 153 | 153 | } |
| 154 | 154 | case 0x34: /* ADR4 */ |
| 155 | 155 | { |
| 156 | 156 | if (cpustate->adctl & 0x10) |
| 157 | 157 | { |
| 158 | return | |
| 158 | return | |
| 159 | 159 | } |
| 160 | 160 | else |
| 161 | 161 | { |
| 162 | return | |
| 162 | return | |
| 163 | 163 | } |
| 164 | 164 | } |
| 165 | 165 | case 0x38: /* OPT2 */ |
| r8806 | r8807 | |
| 175 | 175 | case 0x74: /* SCSR1 */ |
| 176 | 176 | return 0x40; |
| 177 | 177 | case 0x7c: /* PORTH */ |
| 178 | return | |
| 178 | return | |
| 179 | 179 | case 0x7e: /* PORTG */ |
| 180 | return | |
| 180 | return | |
| 181 | 181 | case 0x7f: /* DDRG */ |
| 182 | 182 | return 0; |
| 183 | 183 | |
| r8806 | r8807 | |
| 186 | 186 | case 0x89: /* SPSR2 */ |
| 187 | 187 | return 0x80; |
| 188 | 188 | case 0x8a: /* SPDR2 */ |
| 189 | return | |
| 189 | return | |
| 190 | 190 | |
| 191 | 191 | case 0x8b: /* OPT4 */ |
| 192 | 192 | return 0; |
| r8806 | r8807 | |
| 203 | 203 | switch(reg) |
| 204 | 204 | { |
| 205 | 205 | case 0x00: /* PORTA */ |
| 206 | | |
| 206 | cpustate->io-> | |
| 207 | 207 | return; |
| 208 | 208 | case 0x01: /* DDRA */ |
| 209 | 209 | //mame_printf_debug("HC11: ddra = %02X\n", value); |
| 210 | 210 | return; |
| 211 | 211 | case 0x03: /* PORTC */ |
| 212 | | |
| 212 | cpustate->io-> | |
| 213 | 213 | return; |
| 214 | 214 | case 0x04: /* PORTC */ |
| 215 | | |
| 215 | cpustate->io-> | |
| 216 | 216 | return; |
| 217 | 217 | case 0x08: /* PORTD */ |
| 218 | | |
| 218 | cpustate->io-> | |
| 219 | 219 | return; |
| 220 | 220 | case 0x09: /* DDRD */ |
| 221 | 221 | //mame_printf_debug("HC11: ddrd = %02X\n", value); |
| 222 | 222 | return; |
| 223 | 223 | case 0x0a: /* PORTE */ |
| 224 | | |
| 224 | cpustate->io-> | |
| 225 | 225 | return; |
| 226 | 226 | case 0x22: /* TMSK1 */ |
| 227 | 227 | return; |
| r8806 | r8807 | |
| 271 | 271 | case 0x77: /* SCDRL */ |
| 272 | 272 | return; |
| 273 | 273 | case 0x7c: /* PORTH */ |
| 274 | | |
| 274 | cpustate->io-> | |
| 275 | 275 | return; |
| 276 | 276 | case 0x7d: /* DDRH */ |
| 277 | 277 | //mame_printf_debug("HC11: ddrh = %02X at %04X\n", value, cpustate->pc); |
| 278 | 278 | return; |
| 279 | 279 | case 0x7e: /* PORTG */ |
| 280 | | |
| 280 | cpustate->io-> | |
| 281 | 281 | return; |
| 282 | 282 | case 0x7f: /* DDRG */ |
| 283 | 283 | //mame_printf_debug("HC11: ddrg = %02X at %04X\n", value, cpustate->pc); |
| r8806 | r8807 | |
| 288 | 288 | case 0x89: /* SPSR2 */ |
| 289 | 289 | return; |
| 290 | 290 | case 0x8a: /* SPDR2 */ |
| 291 | | |
| 291 | cpustate->io-> | |
| 292 | 292 | return; |
| 293 | 293 | |
| 294 | 294 | case 0x8b: /* OPT4 */ |
| r8806 | r8807 | |
| 324 | 324 | { |
| 325 | 325 | return cpustate->internal_ram[address-cpustate->ram_position]; |
| 326 | 326 | } |
| 327 | return | |
| 327 | return | |
| 328 | 328 | } |
| 329 | 329 | |
| 330 | 330 | INLINE void WRITE8(hc11_state *cpustate, UINT32 address, UINT8 value) |
| r8806 | r8807 | |
| 339 | 339 | cpustate->internal_ram[address-cpustate->ram_position] = value; |
| 340 | 340 | return; |
| 341 | 341 | } |
| 342 | | |
| 342 | | |
| 343 | 343 | } |
| 344 | 344 | |
| 345 | 345 | INLINE UINT16 READ16(hc11_state *cpustate, UINT32 address) |
| r8806 | r8807 | |
|---|---|---|
| 185 | 185 | UINT32 ppc; |
| 186 | 186 | void (*output_pins_changed)(running_device *device, UINT32 pins); |
| 187 | 187 | legacy_cpu_device * device; |
| 188 | | |
| 188 | | |
| 189 | 189 | }; |
| 190 | 190 | |
| 191 | 191 | |
| r8806 | r8807 | |
| 217 | 217 | |
| 218 | 218 | #define ROPCODE(cs,pc) memory_decrypted_read_dword((cs)->program, pc) |
| 219 | 219 | |
| 220 | #define RBYTE(cs,addr) memory_read_byte_32le((cs)->program, addr) | |
| 221 | #define WBYTE(cs,addr,data) memory_write_byte_32le((cs)->program, (addr), data) | |
| 220 | #define RBYTE(cs,addr) (cs)->program->read_byte(addr) | |
| 221 | #define WBYTE(cs,addr,data) (cs)->program->write_byte((addr), data) | |
| 222 | 222 | |
| 223 | 223 | #if (!DETECT_MISALIGNED_MEMORY) |
| 224 | 224 | |
| 225 | #define RWORD(cs,addr) memory_read_word_32le((cs)->program, addr) | |
| 226 | #define WWORD(cs,addr,data) memory_write_word_32le((cs)->program, (addr), data) | |
| 227 | #define RLONG(cs,addr) memory_read_dword_32le((cs)->program, addr) | |
| 228 | #define WLONG(cs,addr,data) memory_write_dword_32le((cs)->program, (addr), data) | |
| 225 | #define RWORD(cs,addr) (cs)->program->read_word(addr) | |
| 226 | #define WWORD(cs,addr,data) (cs)->program->write_word((addr), data) | |
| 227 | #define RLONG(cs,addr) (cs)->program->read_dword(addr) | |
| 228 | #define WLONG(cs,addr,data) (cs)->program->write_dword((addr), data) | |
| 229 | 229 | |
| 230 | 230 | #else |
| 231 | 231 | |
| r8806 | r8807 | |
| 233 | 233 | { |
| 234 | 234 | UINT16 data; |
| 235 | 235 | if (addr & 1) fprintf(stderr, "Unaligned word read @ %06X, PC=%06X\n", addr, cpustate->PC); |
| 236 | data = | |
| 236 | data = | |
| 237 | 237 | return data; |
| 238 | 238 | } |
| 239 | 239 | |
| r8806 | r8807 | |
| 241 | 241 | { |
| 242 | 242 | UINT32 data; |
| 243 | 243 | if (addr & 3) fprintf(stderr, "Unaligned long read @ %06X, PC=%06X\n", addr, cpustate->PC); |
| 244 | data = | |
| 244 | data = | |
| 245 | 245 | return data; |
| 246 | 246 | } |
| 247 | 247 | |
| 248 | 248 | INLINE void WWORD(dsp32_state *cpustate, offs_t addr, UINT16 data) |
| 249 | 249 | { |
| 250 | 250 | if (addr & 1) fprintf(stderr, "Unaligned word write @ %06X, PC=%06X\n", addr, cpustate->PC); |
| 251 | | |
| 251 | | |
| 252 | 252 | } |
| 253 | 253 | |
| 254 | 254 | INLINE void WLONG(dsp32_state *cpustate, offs_t addr, UINT32 data) |
| 255 | 255 | { |
| 256 | 256 | if (addr & 3) fprintf(stderr, "Unaligned long write @ %06X, PC=%06X\n", addr, cpustate->PC); |
| 257 | | |
| 257 | | |
| 258 | 258 | } |
| 259 | 259 | |
| 260 | 260 | #endif |
| r8806 | r8807 | |
|---|---|---|
| 73 | 73 | int regbank; |
| 74 | 74 | device_irq_callback irqcallback; |
| 75 | 75 | legacy_cpu_device *device; |
| 76 | | |
| 76 | | |
| 77 | 77 | }; |
| 78 | 78 | |
| 79 | 79 | |
| r8806 | r8807 | |
| 195 | 195 | #define FLAG_SF 0x80 |
| 196 | 196 | |
| 197 | 197 | |
| 198 | #define RDMEM(addr) memory_read_byte_8le( cpustate->program, addr ) | |
| 199 | #define WRMEM(addr,data) memory_write_byte_8le( cpustate->program, addr, data ) | |
| 198 | #define RDMEM(addr) cpustate->program->read_byte( addr ) | |
| 199 | #define WRMEM(addr,data) cpustate->program->write_byte( addr, data ) | |
| 200 | 200 | #define RDOP() RDMEM( cpustate->pc.d ); cpustate->pc.d++ |
| 201 | 201 | #define RDMEMW(addr) ( RDMEM(addr) | ( RDMEM(addr+1) << 8 ) ) |
| 202 | 202 | #define RDMEML(addr) ( RDMEMW(addr) | ( RDMEMW(addr+2) << 16 ) ) |
| r8806 | r8807 | |
|---|---|---|
| 34 | 34 | UINT8 flags; // used for I/O only |
| 35 | 35 | |
| 36 | 36 | legacy_cpu_device *device; |
| 37 | const address_space *program; | |
| 38 | const address_space *data; | |
| 39 | const address_space *io; | |
| 37 | address_space *program; | |
| 38 | address_space *data; | |
| 39 | address_space *io; | |
| 40 | 40 | int icount; |
| 41 | 41 | int pc_pos; // PC possition in ADDR |
| 42 | 42 | int addr_mask; |
| r8806 | r8807 | |
| 73 | 73 | |
| 74 | 74 | INLINE void WPM(i4004_state *cpustate) |
| 75 | 75 | { |
| 76 | UINT8 t = (memory_read_byte_8le(cpustate->program, cpustate->RAM.d) << 4) | cpustate->A; | |
| 77 | memory_write_byte_8le(cpustate->program, (GET_PC.w.l & 0x0f00) | cpustate->RAM.d, t); | |
| 76 | UINT8 t = (cpustate->program->read_byte(cpustate->RAM.d) << 4) | cpustate->A; | |
| 77 | cpustate->program->write_byte((GET_PC.w.l & 0x0f00) | cpustate->RAM.d, t); | |
| 78 | 78 | } |
| 79 | 79 | |
| 80 | 80 | |
| r8806 | r8807 | |
| 88 | 88 | |
| 89 | 89 | INLINE UINT8 RM(i4004_state *cpustate) |
| 90 | 90 | { |
| 91 | return | |
| 91 | return | |
| 92 | 92 | } |
| 93 | 93 | |
| 94 | 94 | INLINE UINT8 RMS(i4004_state *cpustate, UINT32 a) |
| 95 | 95 | { |
| 96 | return | |
| 96 | return | |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | 99 | INLINE void WM(i4004_state *cpustate, UINT8 v) |
| 100 | 100 | { |
| 101 | UINT8 t = memory_read_byte_8le(cpustate->data, cpustate->RAM.d); | |
| 102 | memory_write_byte_8le(cpustate->data, cpustate->RAM.d, (t & 0xf0) | v); | |
| 101 | UINT8 t = cpustate->data->read_byte(cpustate->RAM.d); | |
| 102 | cpustate->data->write_byte(cpustate->RAM.d, (t & 0xf0) | v); | |
| 103 | 103 | } |
| 104 | 104 | |
| 105 | 105 | |
| 106 | 106 | INLINE void WMP(i4004_state *cpustate, UINT8 v) |
| 107 | 107 | { |
| 108 | | |
| 108 | cpustate->io-> | |
| 109 | 109 | } |
| 110 | 110 | |
| 111 | 111 | INLINE void WMS(i4004_state *cpustate, UINT32 a, UINT8 v) |
| 112 | 112 | { |
| 113 | UINT8 t = memory_read_byte_8le(cpustate->data, (cpustate->RAM.d & 0xff0) + a); | |
| 114 | memory_write_byte_8le(cpustate->data,(cpustate->RAM.d & 0xff0) + a, (t & 0x0f) | (v<<4)); | |
| 113 | UINT8 t = cpustate->data->read_byte((cpustate->RAM.d & 0xff0) + a); | |
| 114 | cpustate->data->write_byte((cpustate->RAM.d & 0xff0) + a, (t & 0x0f) | (v<<4)); | |
| 115 | 115 | } |
| 116 | 116 | |
| 117 | 117 | INLINE UINT8 RIO(i4004_state *cpustate) |
| 118 | 118 | { |
| 119 | return | |
| 119 | return | |
| 120 | 120 | } |
| 121 | 121 | |
| 122 | 122 | INLINE void WIO(i4004_state *cpustate, UINT8 v) |
| 123 | 123 | { |
| 124 | | |
| 124 | cpustate->io-> | |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | 127 | INLINE UINT8 GET_REG(i4004_state *cpustate, UINT8 num) |
| r8806 | r8807 | |
|---|---|---|
| 33 | 33 | UINT8 SR; |
| 34 | 34 | |
| 35 | 35 | legacy_cpu_device *device; |
| 36 | const address_space *program; | |
| 37 | const address_space *io; | |
| 36 | address_space *program; | |
| 37 | address_space *io; | |
| 38 | 38 | int icount; |
| 39 | 39 | |
| 40 | 40 | devcb_resolved_write8 flag_out_func; |
| r8806 | r8807 | |
| 81 | 81 | |
| 82 | 82 | INLINE UINT8 RM(scmp_state *cpustate,UINT32 a) |
| 83 | 83 | { |
| 84 | return | |
| 84 | return | |
| 85 | 85 | } |
| 86 | 86 | |
| 87 | 87 | INLINE void WM(scmp_state *cpustate,UINT32 a, UINT8 v) |
| 88 | 88 | { |
| 89 | | |
| 89 | | |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | 92 | INLINE void illegal(scmp_state *cpustate,UINT8 opcode) |
| r8806 | r8807 | |
|---|---|---|
| 277 | 277 | x86code * debug_cpu_instruction_hook;/* debugger callback */ |
| 278 | 278 | x86code * debug_log_hashjmp; /* hashjmp debugging */ |
| 279 | 279 | x86code * drcmap_get_value; /* map lookup helper */ |
| 280 | data_accessors accessors[ADDRESS_SPACES];/* memory accessors */ | |
| 281 | const address_space * space[ADDRESS_SPACES]; /* address spaces */ | |
| 280 | data_accessors accessors[ADDRESS_SPACES]; /* memory accessors */ | |
| 281 | address_space * space[ADDRESS_SPACES]; /* address spaces */ | |
| 282 | 282 | |
| 283 | 283 | UINT8 sse41; /* do we have SSE4.1 support? */ |
| 284 | 284 | UINT32 ssemode; /* saved SSE mode */ |
| r8806 | r8807 | |
| 388 | 388 | }; |
| 389 | 389 | |
| 390 | 390 | |
| 391 | ||
| 392 | 391 | /*************************************************************************** |
| 393 | 392 | TABLES |
| 394 | 393 | ***************************************************************************/ |
| r8806 | r8807 | |
| 716 | 715 | { |
| 717 | 716 | drcbe->space[spacenum] = downcast<cpu_device *>(device)->space(spacenum); |
| 718 | 717 | if (drcbe->space[spacenum] != NULL) |
| 719 | drcbe->ac | |
| 718 | drcbe->spac | |
| 720 | 719 | } |
| 721 | 720 | |
| 722 | 721 | /* build up necessary arrays */ |
| r8806 | r8807 | |
|---|---|---|
| 213 | 213 | struct _drcbe_state |
| 214 | 214 | { |
| 215 | 215 | running_device * device; /* CPU device we are associated with */ |
| 216 | | |
| 216 | | |
| 217 | 217 | drcuml_state * drcuml; /* pointer back to our owner */ |
| 218 | 218 | drccache * cache; /* pointer to the cache */ |
| 219 | 219 | drcuml_machine_state state; /* state of the machine */ |
| r8806 | r8807 | |
| 903 | 903 | break; |
| 904 | 904 | |
| 905 | 905 | case MAKE_OPCODE_SHORT(DRCUML_OP_READ1, 4, 0): /* READ dst,src1,space_BYTE */ |
| 906 | PARAM0 = | |
| 906 | PARAM0 = | |
| 907 | 907 | break; |
| 908 | 908 | |
| 909 | 909 | case MAKE_OPCODE_SHORT(DRCUML_OP_READ2, 4, 0): /* READ dst,src1,space_WORD */ |
| 910 | PARAM0 = | |
| 910 | PARAM0 = | |
| 911 | 911 | break; |
| 912 | 912 | |
| 913 | 913 | case MAKE_OPCODE_SHORT(DRCUML_OP_READ4, 4, 0): /* READ dst,src1,space_DWORD */ |
| 914 | PARAM0 = | |
| 914 | PARAM0 = | |
| 915 | 915 | break; |
| 916 | 916 | |
| 917 | 917 | case MAKE_OPCODE_SHORT(DRCUML_OP_READM2, 4, 0): /* READM dst,src1,mask,space_WORD */ |
| 918 | PARAM0 = | |
| 918 | PARAM0 = | |
| 919 | 919 | break; |
| 920 | 920 | |
| 921 | 921 | case MAKE_OPCODE_SHORT(DRCUML_OP_READM4, 4, 0): /* READM dst,src1,mask,space_DWORD */ |
| 922 | PARAM0 = | |
| 922 | PARAM0 = | |
| 923 | 923 | break; |
| 924 | 924 | |
| 925 | 925 | case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE1, 4, 0): /* WRITE dst,src1,space_BYTE */ |
| 926 | | |
| 926 | | |
| 927 | 927 | break; |
| 928 | 928 | |
| 929 | 929 | case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE2, 4, 0): /* WRITE dst,src1,space_WORD */ |
| 930 | | |
| 930 | | |
| 931 | 931 | break; |
| 932 | 932 | |
| 933 | 933 | case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE4, 4, 0): /* WRITE dst,src1,space_DWORD */ |
| 934 | | |
| 934 | | |
| 935 | 935 | break; |
| 936 | 936 | |
| 937 | 937 | case MAKE_OPCODE_SHORT(DRCUML_OP_WRITEM2, 4, 0): /* WRITEM dst,src1,mask,space_WORD */ |
| 938 | | |
| 938 | | |
| 939 | 939 | break; |
| 940 | 940 | |
| 941 | 941 | case MAKE_OPCODE_SHORT(DRCUML_OP_WRITEM4, 4, 0): /* WRITEM dst,src1,mask,space_DWORD */ |
| 942 | | |
| 942 | | |
| 943 | 943 | break; |
| 944 | 944 | |
| 945 | 945 | case MAKE_OPCODE_SHORT(DRCUML_OP_CARRY, 4, 1): /* CARRY src,bitnum */ |
| r8806 | r8807 | |
| 1482 | 1482 | break; |
| 1483 | 1483 | |
| 1484 | 1484 | case MAKE_OPCODE_SHORT(DRCUML_OP_READ1, 8, 0): /* DREAD dst,src1,space_BYTE */ |
| 1485 | DPARAM0 = | |
| 1485 | DPARAM0 = | |
| 1486 | 1486 | break; |
| 1487 | 1487 | |
| 1488 | 1488 | case MAKE_OPCODE_SHORT(DRCUML_OP_READ2, 8, 0): /* DREAD dst,src1,space_WORD */ |
| 1489 | DPARAM0 = | |
| 1489 | DPARAM0 = | |
| 1490 | 1490 | break; |
| 1491 | 1491 | |
| 1492 | 1492 | case MAKE_OPCODE_SHORT(DRCUML_OP_READ4, 8, 0): /* DREAD dst,src1,space_DWORD */ |
| 1493 | DPARAM0 = | |
| 1493 | DPARAM0 = | |
| 1494 | 1494 | break; |
| 1495 | 1495 | |
| 1496 | 1496 | case MAKE_OPCODE_SHORT(DRCUML_OP_READ8, 8, 0): /* DREAD dst,src1,space_QOWRD */ |
| 1497 | DPARAM0 = | |
| 1497 | DPARAM0 = | |
| 1498 | 1498 | break; |
| 1499 | 1499 | |
| 1500 | 1500 | case MAKE_OPCODE_SHORT(DRCUML_OP_READM2, 8, 0): /* DREADM dst,src1,mask,space_WORD */ |
| 1501 | DPARAM0 = | |
| 1501 | DPARAM0 = | |
| 1502 | 1502 | break; |
| 1503 | 1503 | |
| 1504 | 1504 | case MAKE_OPCODE_SHORT(DRCUML_OP_READM4, 8, 0): /* DREADM dst,src1,mask,space_DWORD */ |
| 1505 | DPARAM0 = | |
| 1505 | DPARAM0 = | |
| 1506 | 1506 | break; |
| 1507 | 1507 | |
| 1508 | 1508 | case MAKE_OPCODE_SHORT(DRCUML_OP_READM8, 8, 0): /* DREADM dst,src1,mask,space_QWORD */ |
| 1509 | DPARAM0 = | |
| 1509 | DPARAM0 = | |
| 1510 | 1510 | break; |
| 1511 | 1511 | |
| 1512 | 1512 | case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE1, 8, 0): /* DWRITE dst,src1,space_BYTE */ |
| 1513 | | |
| 1513 | | |
| 1514 | 1514 | break; |
| 1515 | 1515 | |
| 1516 | 1516 | case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE2, 8, 0): /* DWRITE dst,src1,space_WORD */ |
| 1517 | | |
| 1517 | | |
| 1518 | 1518 | break; |
| 1519 | 1519 | |
| 1520 | 1520 | case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE4, 8, 0): /* DWRITE dst,src1,space_DWORD */ |
| 1521 | | |
| 1521 | | |
| 1522 | 1522 | break; |
| 1523 | 1523 | |
| 1524 | 1524 | case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE8, 8, 0): /* DWRITE dst,src1,space_QWORD */ |
| 1525 | | |
| 1525 | | |
| 1526 | 1526 | break; |
| 1527 | 1527 | |
| 1528 | 1528 | case MAKE_OPCODE_SHORT(DRCUML_OP_WRITEM2, 8, 0): /* DWRITEM dst,src1,mask,space_WORD */ |
| 1529 | | |
| 1529 | | |
| 1530 | 1530 | break; |
| 1531 | 1531 | |
| 1532 | 1532 | case MAKE_OPCODE_SHORT(DRCUML_OP_WRITEM4, 8, 0): /* DWRITEM dst,src1,mask,space_DWORD */ |
| 1533 | | |
| 1533 | | |
| 1534 | 1534 | break; |
| 1535 | 1535 | |
| 1536 | 1536 | case MAKE_OPCODE_SHORT(DRCUML_OP_WRITEM8, 8, 0): /* DWRITEM dst,src1,mask,space_QWORD */ |
| 1537 | | |
| 1537 | | |
| 1538 | 1538 | break; |
| 1539 | 1539 | |
| 1540 | 1540 | case MAKE_OPCODE_SHORT(DRCUML_OP_CARRY, 8, 0): /* DCARRY src,bitnum */ |
| r8806 | r8807 | |
| 1895 | 1895 | break; |
| 1896 | 1896 | |
| 1897 | 1897 | case MAKE_OPCODE_SHORT(DRCUML_OP_FREAD, 4, 0): /* FSREAD dst,src1,space */ |
| 1898 | PARAM0 = | |
| 1898 | PARAM0 = | |
| 1899 | 1899 | break; |
| 1900 | 1900 | |
| 1901 | 1901 | case MAKE_OPCODE_SHORT(DRCUML_OP_FWRITE, 4, 0): /* FSWRITE dst,src1,space */ |
| 1902 | | |
| 1902 | | |
| 1903 | 1903 | break; |
| 1904 | 1904 | |
| 1905 | 1905 | case MAKE_OPCODE_SHORT(DRCUML_OP_FMOV, 4, 1): /* FSMOV dst,src[,c] */ |
| r8806 | r8807 | |
| 2030 | 2030 | break; |
| 2031 | 2031 | |
| 2032 | 2032 | case MAKE_OPCODE_SHORT(DRCUML_OP_FREAD, 8, 0): /* FDREAD dst,src1,space */ |
| 2033 | DPARAM0 = | |
| 2033 | DPARAM0 = | |
| 2034 | 2034 | break; |
| 2035 | 2035 | |
| 2036 | 2036 | case MAKE_OPCODE_SHORT(DRCUML_OP_FWRITE, 8, 0): /* FDWRITE dst,src1,space */ |
| 2037 | | |
| 2037 | | |
| 2038 | 2038 | break; |
| 2039 | 2039 | |
| 2040 | 2040 | case MAKE_OPCODE_SHORT(DRCUML_OP_FMOV, 8, 1): /* FDMOV dst,src[,c] */ |
| r8806 | r8807 | |
|---|---|---|
| 109 | 109 | INLINE UINT8 READ8(rsp_state *rsp, UINT32 address) |
| 110 | 110 | { |
| 111 | 111 | address = 0x04000000 | (address & 0xfff); |
| 112 | return | |
| 112 | return | |
| 113 | 113 | } |
| 114 | 114 | |
| 115 | 115 | INLINE UINT16 READ16(rsp_state *rsp, UINT32 address) |
| r8806 | r8807 | |
| 119 | 119 | if (address & 1) |
| 120 | 120 | { |
| 121 | 121 | //osd_die("RSP: READ16: unaligned %08X at %08X\n", address, rsp->ppc); |
| 122 | return (( | |
| 122 | return (( | |
| 123 | 123 | } |
| 124 | 124 | |
| 125 | return | |
| 125 | return | |
| 126 | 126 | } |
| 127 | 127 | |
| 128 | 128 | INLINE UINT32 READ32(rsp_state *rsp, UINT32 address) |
| r8806 | r8807 | |
| 132 | 132 | if (address & 3) |
| 133 | 133 | { |
| 134 | 134 | //osd_die("RSP: READ32: unaligned %08X at %08X\n", address, rsp->ppc); |
| 135 | return ((memory_read_byte_32be(rsp->program, address + 0) & 0xff) << 24) | | |
| 136 | ((memory_read_byte_32be(rsp->program, address + 1) & 0xff) << 16) | | |
| 137 | ((memory_read_byte_32be(rsp->program, address + 2) & 0xff) << 8) | | |
| 138 | ((memory_read_byte_32be(rsp->program, address + 3) & 0xff) << 0); | |
| 135 | return ((rsp->program->read_byte(address + 0) & 0xff) << 24) | | |
| 136 | ((rsp->program->read_byte(address + 1) & 0xff) << 16) | | |
| 137 | ((rsp->program->read_byte(address + 2) & 0xff) << 8) | | |
| 138 | ((rsp->program->read_byte(address + 3) & 0xff) << 0); | |
| 139 | 139 | } |
| 140 | 140 | |
| 141 | return | |
| 141 | return rsp->program->read_dword | |
| 142 | 142 | } |
| 143 | 143 | |
| 144 | 144 | INLINE void WRITE8(rsp_state *rsp, UINT32 address, UINT8 data) |
| 145 | 145 | { |
| 146 | 146 | address = 0x04000000 | (address & 0xfff); |
| 147 | | |
| 147 | rsp->program->write_byte | |
| 148 | 148 | } |
| 149 | 149 | |
| 150 | 150 | INLINE void WRITE16(rsp_state *rsp, UINT32 address, UINT16 data) |
| r8806 | r8807 | |
| 154 | 154 | if (address & 1) |
| 155 | 155 | { |
| 156 | 156 | //fatalerror("RSP: WRITE16: unaligned %08X, %04X at %08X\n", address, data, rsp->ppc); |
| 157 | memory_write_byte_32be(rsp->program, address + 0, (data >> 8) & 0xff); | |
| 158 | memory_write_byte_32be(rsp->program, address + 1, (data >> 0) & 0xff); | |
| 157 | rsp->program->write_byte(address + 0, (data >> 8) & 0xff); | |
| 158 | rsp->program->write_byte(address + 1, (data >> 0) & 0xff); | |
| 159 | 159 | return; |
| 160 | 160 | } |
| 161 | 161 | |
| 162 | | |
| 162 | rsp->program->write_word | |
| 163 | 163 | } |
| 164 | 164 | |
| 165 | 165 | INLINE void WRITE32(rsp_state *rsp, UINT32 address, UINT32 data) |
| r8806 | r8807 | |
| 169 | 169 | if (address & 3) |
| 170 | 170 | { |
| 171 | 171 | //osd_die("RSP: WRITE32: unaligned %08X, %08X at %08X\n", address, data, rsp->ppc); |
| 172 | memory_write_byte_32be(rsp->program, address + 0, (data >> 24) & 0xff); | |
| 173 | memory_write_byte_32be(rsp->program, address + 1, (data >> 16) & 0xff); | |
| 174 | memory_write_byte_32be(rsp->program, address + 2, (data >> 8) & 0xff); | |
| 175 | memory_write_byte_32be(rsp->program, address + 3, (data >> 0) & 0xff); | |
| 172 | rsp->program->write_byte(address + 0, (data >> 24) & 0xff); | |
| 173 | rsp->program->write_byte(address + 1, (data >> 16) & 0xff); | |
| 174 | rsp->program->write_byte(address + 2, (data >> 8) & 0xff); | |
| 175 | rsp->program->write_byte(address + 3, (data >> 0) & 0xff); | |
| 176 | 176 | return; |
| 177 | 177 | } |
| 178 | 178 | |
| 179 | | |
| 179 | rsp->program->write_dword | |
| 180 | 180 | } |
| 181 | 181 | |
| 182 | 182 | /*****************************************************************************/ |
| r8806 | r8807 | |
|---|---|---|
| 210 | 210 | |
| 211 | 211 | device_irq_callback irq_callback; |
| 212 | 212 | legacy_cpu_device *device; |
| 213 | | |
| 213 | | |
| 214 | 214 | int icount; |
| 215 | 215 | |
| 216 | 216 | rspimp_state* impstate; |
| r8806 | r8807 | |
|---|---|---|
| 89 | 89 | { |
| 90 | 90 | const cop400_interface *intf; |
| 91 | 91 | |
| 92 | const address_space *program; | |
| 93 | const address_space *data; | |
| 94 | const address_space *io; | |
| 92 | address_space *program; | |
| 93 | address_space *data; | |
| 94 | address_space *io; | |
| 95 | 95 | |
| 96 | 96 | UINT8 featuremask; |
| 97 | 97 | |
| r8806 | r8807 | |
| 161 | 161 | ***************************************************************************/ |
| 162 | 162 | |
| 163 | 163 | #define ROM(a) memory_decrypted_read_byte(cpustate->program, a) |
| 164 | #define RAM_R(a) memory_read_byte_8le(cpustate->data, a) | |
| 165 | #define RAM_W(a, v) memory_write_byte_8le(cpustate->data, a, v) | |
| 166 | #define IN(a) memory_read_byte_8le(cpustate->io, a) | |
| 167 | #define OUT(a, v) memory_write_byte_8le(cpustate->io, a, v) | |
| 164 | #define RAM_R(a) cpustate->data->read_byte(a) | |
| 165 | #define RAM_W(a, v) cpustate->data->write_byte(a, v) | |
| 166 | #define IN(a) cpustate->io->read_byte(a) | |
| 167 | #define OUT(a, v) cpustate->io->write_byte(a, v) | |
| 168 | 168 | |
| 169 | 169 | #define IN_G() (IN(COP400_PORT_G) & cpustate->g_mask) |
| 170 | 170 | #define IN_L() IN(COP400_PORT_L) |
| r8806 | r8807 | |
|---|---|---|
| 22 | 22 | UINT32 halt; |
| 23 | 23 | |
| 24 | 24 | legacy_cpu_device *device; |
| 25 | | |
| 25 | | |
| 26 | 26 | int icount; |
| 27 | 27 | }; |
| 28 | 28 | |
| r8806 | r8807 | |
| 67 | 67 | // the address value to get the appropriate byte index. |
| 68 | 68 | address <<= 2; |
| 69 | 69 | |
| 70 | v |= memory_read_byte(cpustate->program, address + 0) << 24; | |
| 71 | v |= memory_read_byte(cpustate->program, address + 1) << 16; | |
| 72 | v |= memory_read_byte(cpustate->program, address + 2) << 8; | |
| 73 | v |= memory_read_byte(cpustate->program, address + 3) << 0; | |
| 70 | v |= cpustate->program->read_byte(address + 0) << 24; | |
| 71 | v |= cpustate->program->read_byte(address + 1) << 16; | |
| 72 | v |= cpustate->program->read_byte(address + 2) << 8; | |
| 73 | v |= cpustate->program->read_byte(address + 3) << 0; | |
| 74 | 74 | |
| 75 | 75 | return reverse(v); |
| 76 | 76 | } |
| r8806 | r8807 | |
| 84 | 84 | // the address value to get the appropriate byte index. |
| 85 | 85 | address <<= 2; |
| 86 | 86 | |
| 87 | memory_write_byte(cpustate->program, address + 0, (v >> 24) & 0x000000ff); | |
| 88 | memory_write_byte(cpustate->program, address + 1, (v >> 16) & 0x000000ff); | |
| 89 | memory_write_byte(cpustate->program, address + 2, (v >> 8) & 0x000000ff); | |
| 90 | memory_write_byte(cpustate->program, address + 3, (v >> 0) & 0x000000ff); | |
| 87 | cpustate->program->write_byte(address + 0, (v >> 24) & 0x000000ff); | |
| 88 | cpustate->program->write_byte(address + 1, (v >> 16) & 0x000000ff); | |
| 89 | cpustate->program->write_byte(address + 2, (v >> 8) & 0x000000ff); | |
| 90 | cpustate->program->write_byte(address + 3, (v >> 0) & 0x000000ff); | |
| 91 | 91 | return; |
| 92 | 92 | } |
| 93 | 93 | |
| r8806 | r8807 | |
| 130 | 130 | { |
| 131 | 131 | for( i = 0; i < 0x80; i++ ) |
| 132 | 132 | { |
| 133 | fputc( | |
| 133 | fputc( | |
| 134 | 134 | } |
| 135 | 135 | fclose(store); |
| 136 | 136 | } |
| r8806 | r8807 | |
|---|---|---|
| 34 | 34 | UINT8 HALT; |
| 35 | 35 | UINT8 flags; // temporary I/O only |
| 36 | 36 | legacy_cpu_device *device; |
| 37 | const address_space *program; | |
| 38 | const address_space *io; | |
| 37 | address_space *program; | |
| 38 | address_space *io; | |
| 39 | 39 | int icount; |
| 40 | 40 | int pc_pos; // PC possition in ADDR |
| 41 | 41 | |
| r8806 | r8807 | |
| 91 | 91 | case 4 : retVal = cpustate->E; break; |
| 92 | 92 | case 5 : retVal = cpustate->H; break; |
| 93 | 93 | case 6 : retVal = cpustate->L; break; |
| 94 | default: retVal = | |
| 94 | default: retVal = | |
| 95 | 95 | } |
| 96 | 96 | return retVal; |
| 97 | 97 | } |
| r8806 | r8807 | |
| 106 | 106 | case 4 : cpustate->E = val; break; |
| 107 | 107 | case 5 : cpustate->H = val; break; |
| 108 | 108 | case 6 : cpustate->L = val; break; |
| 109 | default: | |
| 109 | default: | |
| 110 | 110 | } |
| 111 | 111 | } |
| 112 | 112 | |
| r8806 | r8807 | |
| 391 | 391 | if (((opcode>>4)&3)==0) { |
| 392 | 392 | // INP |
| 393 | 393 | cpustate->icount -= 8; |
| 394 | cpustate->A = | |
| 394 | cpustate->A = | |
| 395 | 395 | } else { |
| 396 | 396 | // OUT |
| 397 | 397 | cpustate->icount -= 6; |
| 398 | | |
| 398 | cpustate->io-> | |
| 399 | 399 | } |
| 400 | 400 | break; |
| 401 | 401 | } |
| r8806 | r8807 | |
|---|---|---|
| 64 | 64 | |
| 65 | 65 | #define CONDITION(x) condition_table[(x) + ((jaguar->FLAGS & 7) << 5)] |
| 66 | 66 | |
| 67 | #define READBYTE(J,a) memory_read_byte_32be((J)->program, a) | |
| 68 | #define READWORD(J,a) memory_read_word_32be((J)->program, a) | |
| 69 | #define READLONG(J,a) memory_read_dword_32be((J)->program, a) | |
| 67 | #define READBYTE(J,a) (J)->program->read_byte(a) | |
| 68 | #define READWORD(J,a) (J)->program->read_word(a) | |
| 69 | #define READLONG(J,a) (J)->program->read_dword(a) | |
| 70 | 70 | |
| 71 | #define WRITEBYTE(J,a,v) memory_write_byte_32be((J)->program, a, v) | |
| 72 | #define WRITEWORD(J,a,v) memory_write_word_32be((J)->program, a, v) | |
| 73 | #define WRITELONG(J,a,v) memory_write_dword_32be((J)->program, a, v) | |
| 71 | #define WRITEBYTE(J,a,v) (J)->program->write_byte(a, v) | |
| 72 | #define WRITEWORD(J,a,v) (J)->program->write_word(a, v) | |
| 73 | #define WRITELONG(J,a,v) (J)->program->write_dword(a, v) | |
| 74 | 74 | |
| 75 | 75 | |
| 76 | 76 | |
| r8806 | r8807 | |
| 101 | 101 | device_irq_callback irq_callback; |
| 102 | 102 | jaguar_int_func cpu_interrupt; |
| 103 | 103 | legacy_cpu_device *device; |
| 104 | | |
| 104 | | |
| 105 | 105 | }; |
| 106 | 106 | |
| 107 | 107 |
| r8806 | r8807 | |
|---|---|---|
| 188 | 188 | OP(47) { RD_DUM; ILL; } /* 2 ILL / 5 RMB4 ZPG ?? */ |
| 189 | 189 | OP(67) { |
| 190 | 190 | int tmp; RD_IMM; |
| 191 | cpustate->a= | |
| 191 | cpustate->a= | |
| 192 | 192 | |
| 193 | 193 | // logerror("%04x: VBL (0x67)\n",PCW); |
| 194 | 194 | |
| r8806 | r8807 | |
| 274 | 274 | OP(4b) { int tmp; cpustate->icount -= 1; RD_IMM; |
| 275 | 275 | //logerror("%04x: OP4B %02x\n",PCW,tmp); |
| 276 | 276 | /* TODO: Maybe it's just read I/O 0 and do a logic AND with bit 1? */ |
| 277 | cpustate->a= | |
| 277 | cpustate->a= | |
| 278 | 278 | |
| 279 | 279 | //tilt?? |
| 280 | 280 | |
| r8806 | r8807 | |
| 367 | 367 | if (DECO16_VERBOSE) |
| 368 | 368 | logerror("%04x: BANK (8F) %02x\n",PCW,tmp); |
| 369 | 369 | |
| 370 | | |
| 370 | cpustate->io-> | |
| 371 | 371 | |
| 372 | 372 | //swap bank in/out |
| 373 | 373 | } /* */ |
| r8806 | r8807 | |
|---|---|---|
| 54 | 54 | |
| 55 | 55 | #define PEEK_OP() memory_decrypted_read_byte(cpustate->space, M4510_MEM(PCW)) |
| 56 | 56 | |
| 57 | #define RDMEM(addr) memory_read_byte_8le(cpustate->space, M4510_MEM(addr)); cpustate->icount -= 1 | |
| 58 | #define WRMEM(addr,data) memory_write_byte_8le(cpustate->space, M4510_MEM(addr),data); cpustate->icount -= 1 | |
| 57 | #define RDMEM(addr) cpustate->space->read_byte(M4510_MEM(addr)); cpustate->icount -= 1 | |
| 58 | #define WRMEM(addr,data) cpustate->space->write_byte(M4510_MEM(addr),data); cpustate->icount -= 1 | |
| 59 | 59 | |
| 60 | 60 | /*************************************************************** |
| 61 | 61 | * RDOP read an opcode |
| r8806 | r8807 | |
|---|---|---|
| 65 | 65 | |
| 66 | 66 | #define PEEK_OP() memory_decrypted_read_byte(cpustate->space, PCW) |
| 67 | 67 | |
| 68 | #define RDMEM(addr) memory_read_byte_8le(cpustate->space, addr); cpustate->icount -= 1 | |
| 69 | #define WRMEM(addr,data) memory_write_byte_8le(cpustate->space, addr,data); cpustate->icount -= 1 | |
| 68 | #define RDMEM(addr) cpustate->space->read_byte(addr); cpustate->icount -= 1 | |
| 69 | #define WRMEM(addr,data) cpustate->space->write_byte(addr,data); cpustate->icount -= 1 |
| r8806 | r8807 | |
|---|---|---|
| 144 | 144 | |
| 145 | 145 | device_irq_callback irq_callback; |
| 146 | 146 | legacy_cpu_device *device; |
| 147 | | |
| 147 | | |
| 148 | 148 | int icount; |
| 149 | 149 | |
| 150 | 150 | read8_space_func rdmem_id; /* readmem callback for indexed instructions */ |
| r8806 | r8807 | |
| 182 | 182 | #define M4510 |
| 183 | 183 | #include "t65ce02.c" |
| 184 | 184 | |
| 185 | static UINT8 default_rdmem_id( | |
| 185 | static UINT8 default_rdmem_id( | |
| 186 | 186 | { |
| 187 | 187 | m4510_Regs *cpustate = get_safe_token(space->cpu); |
| 188 | return | |
| 188 | return space->r | |
| 189 | 189 | } |
| 190 | static void default_wrmem_id( | |
| 190 | static void default_wrmem_id( | |
| 191 | 191 | { |
| 192 | 192 | m4510_Regs *cpustate = get_safe_token(space->cpu); |
| 193 | | |
| 193 | space-> | |
| 194 | 194 | } |
| 195 | 195 | |
| 196 | 196 | static CPU_INIT( m4510 ) |
| r8806 | r8807 | |
|---|---|---|
| 81 | 81 | /*************************************************************** |
| 82 | 82 | * RDMEM read memory |
| 83 | 83 | ***************************************************************/ |
| 84 | #define RDMEM(addr) | |
| 84 | #define RDMEM(addr) | |
| 85 | 85 | |
| 86 | 86 | /*************************************************************** |
| 87 | 87 | * WRMEM write memory |
| 88 | 88 | ***************************************************************/ |
| 89 | #define WRMEM(addr,data) | |
| 89 | #define WRMEM(addr,data) | |
| 90 | 90 | |
| 91 | 91 | /*************************************************************** |
| 92 | 92 | * BRA branch relative |
| r8806 | r8807 | |
|---|---|---|
| 70 | 70 | |
| 71 | 71 | device_irq_callback irq_callback; |
| 72 | 72 | legacy_cpu_device *device; |
| 73 | const address_space *space; | |
| 74 | const address_space *io; | |
| 73 | address_space *space; | |
| 74 | address_space *io; | |
| 75 | 75 | int int_occured; |
| 76 | 76 | int icount; |
| 77 | 77 | |
| r8806 | r8807 | |
| 99 | 99 | return (m6502_Regs *)downcast<legacy_cpu_device *>(device)->token(); |
| 100 | 100 | } |
| 101 | 101 | |
| 102 | static UINT8 default_rdmem_id(const address_space *space, offs_t offset) { return memory_read_byte_8le(space, offset); } | |
| 103 | static void default_wdmem_id(const address_space *space, offs_t offset, UINT8 data) { memory_write_byte_8le(space, offset, data); } | |
| 102 | static UINT8 default_rdmem_id(address_space *space, offs_t offset) { return space->read_byte(offset); } | |
| 103 | static void default_wdmem_id(address_space *space, offs_t offset, UINT8 data) { space->write_byte(offset, data); } | |
| 104 | 104 | |
| 105 | 105 | /*************************************************************** |
| 106 | 106 | * include the opcode macros, functions and tables |
| r8806 | r8807 | |
|---|---|---|
| 46 | 46 | * RDMEM read memory |
| 47 | 47 | ***************************************************************/ |
| 48 | 48 | #undef RDMEM |
| 49 | #define RDMEM(addr) | |
| 49 | #define RDMEM(addr) | |
| 50 | 50 | |
| 51 | 51 | /*************************************************************** |
| 52 | 52 | * WRMEM write memory |
| 53 | 53 | ***************************************************************/ |
| 54 | 54 | #undef WRMEM |
| 55 | #define WRMEM(addr,data) | |
| 55 | #define WRMEM(addr,data) | |
| 56 | 56 | |
| 57 | 57 | /*************************************************************** |
| 58 | 58 | * push a register onto the stack |
| r8806 | r8807 | |
|---|---|---|
| 79 | 79 | UINT8 so_state; |
| 80 | 80 | device_irq_callback irq_callback; |
| 81 | 81 | legacy_cpu_device *device; |
| 82 | | |
| 82 | | |
| 83 | 83 | |
| 84 | 84 | int icount; |
| 85 | 85 | |
| r8806 | r8807 | |
| 134 | 134 | AM_RANGE(0x00001, 0x00001) AM_MIRROR(0xF0000) AM_READWRITE(m6509_read_00001, m6509_write_00001) |
| 135 | 135 | ADDRESS_MAP_END |
| 136 | 136 | |
| 137 | static UINT8 default_rdmem_id(const address_space *space, offs_t address) { return memory_read_byte_8le(space, address); } | |
| 138 | static void default_wdmem_id(const address_space *space, offs_t address, UINT8 data) { memory_write_byte_8le(space, address, data); } | |
| 137 | static UINT8 default_rdmem_id(address_space *space, offs_t address) { return space->read_byte(address); } | |
| 138 | static void default_wdmem_id(address_space *space, offs_t address, UINT8 data) { space->write_byte(address, data); } | |
| 139 | 139 | |
| 140 | 140 | static CPU_INIT( m6509 ) |
| 141 | 141 | { |
| r8806 | r8807 | |
|---|---|---|
| 76 | 76 | int icount; |
| 77 | 77 | device_irq_callback irq_callback; |
| 78 | 78 | legacy_cpu_device *device; |
| 79 | | |
| 79 | | |
| 80 | 80 | read8_space_func rdmem_id; /* readmem callback for indexed instructions */ |
| 81 | 81 | write8_space_func wrmem_id; /* writemem callback for indexed instructions */ |
| 82 | 82 | }; |
| r8806 | r8807 | |
| 94 | 94 | |
| 95 | 95 | #include "t65ce02.c" |
| 96 | 96 | |
| 97 | static UINT8 default_rdmem_id(const address_space *space, offs_t address) { return memory_read_byte_8le(space, address); } | |
| 98 | static void default_wdmem_id(const address_space *space, offs_t address, UINT8 data) { memory_write_byte_8le(space, address, data); } | |
| 97 | static UINT8 default_rdmem_id(address_space *space, offs_t address) { return space->read_byte(address); } | |
| 98 | static void default_wdmem_id(address_space *space, offs_t address, UINT8 data) { space->write_byte(address, data); } | |
| 99 | 99 | |
| 100 | 100 | static CPU_INIT( m65ce02 ) |
| 101 | 101 | { |
| r8806 | r8807 | |
|---|---|---|
| 125 | 125 | #define M_IN \ |
| 126 | 126 | cpustate->STATUS = 0x42; \ |
| 127 | 127 | cpustate->WZ.d=ARG(cpustate); \ |
| 128 | cpustate->AF.b.h= | |
| 128 | cpustate->AF.b.h= | |
| 129 | 129 | |
| 130 | 130 | #define M_OUT \ |
| 131 | 131 | cpustate->STATUS = 0x10; \ |
| 132 | 132 | cpustate->WZ.d=ARG(cpustate); \ |
| 133 | | |
| 133 | cpustate->io-> | |
| 134 | 134 | |
| 135 | 135 | /* stack */ |
| 136 | 136 | #define M_PUSH(R) { \ |
| 137 | 137 | cpustate->STATUS = 0x04; \ |
| 138 | memory_write_byte_8le(cpustate->program, --cpustate->SP.w.l, cpustate->R.b.h); \ | |
| 139 | memory_write_byte_8le(cpustate->program, --cpustate->SP.w.l, cpustate->R.b.l); \ | |
| 138 | cpustate->program->write_byte(--cpustate->SP.w.l, cpustate->R.b.h); \ | |
| 139 | cpustate->program->write_byte(--cpustate->SP.w.l, cpustate->R.b.l); \ | |
| 140 | 140 | } |
| 141 | 141 | |
| 142 | 142 | #define M_POP(R) { \ |
| 143 | 143 | cpustate->STATUS = 0x86; \ |
| 144 | cpustate->R.b.l = memory_read_byte_8le(cpustate->program, cpustate->SP.w.l++); \ | |
| 145 | cpustate->R.b.h = memory_read_byte_8le(cpustate->program, cpustate->SP.w.l++); \ | |
| 144 | cpustate->R.b.l = cpustate->program->read_byte(cpustate->SP.w.l++); \ | |
| 145 | cpustate->R.b.h = cpustate->program->read_byte(cpustate->SP.w.l++); \ | |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | 148 | /* jumps */ |
| r8806 | r8807 | |
|---|---|---|
| 184 | 184 | |
| 185 | 185 | device_irq_callback irq_callback; |
| 186 | 186 | legacy_cpu_device *device; |
| 187 | const address_space *program; | |
| 188 | const address_space *io; | |
| 187 | address_space *program; | |
| 188 | address_space *io; | |
| 189 | 189 | int icount; |
| 190 | 190 | }; |
| 191 | 191 | |
| r8806 | r8807 | |
| 374 | 374 | INLINE UINT8 RM(i8085_state *cpustate, UINT32 a) |
| 375 | 375 | { |
| 376 | 376 | set_status(cpustate, 0x82); // memory read |
| 377 | return | |
| 377 | return | |
| 378 | 378 | } |
| 379 | 379 | |
| 380 | 380 | INLINE void WM(i8085_state *cpustate, UINT32 a, UINT8 v) |
| 381 | 381 | { |
| 382 | 382 | set_status(cpustate, 0x00); // memory write |
| 383 | | |
| 383 | | |
| 384 | 384 | } |
| 385 | 385 | |
| 386 | 386 |
| r8806 | r8807 | |
|---|---|---|
| 634 | 634 | |
| 635 | 635 | for (i=0; i < length; i++) |
| 636 | 636 | { |
| 637 | | |
| 637 | ppc.program->write_byte | |
| 638 | 638 | } |
| 639 | 639 | } |
| 640 | 640 | |
| r8806 | r8807 | |
| 809 | 809 | int length = ppc.dma[ch].ct; |
| 810 | 810 | |
| 811 | 811 | for( i=0; i < length; i++ ) { |
| 812 | spu_tx_dma_ptr[i] = | |
| 812 | spu_tx_dma_ptr[i] = ppc.program->read_byte | |
| 813 | 813 | } |
| 814 | 814 | spu_tx_dma_handler(length); |
| 815 | 815 | } |
| r8806 | r8807 | |
| 906 | 906 | |
| 907 | 907 | /*********************************************************************************/ |
| 908 | 908 | |
| 909 | static UINT8 ppc403_read8( | |
| 909 | static UINT8 ppc403_read8( | |
| 910 | 910 | { |
| 911 | 911 | if(a >= 0x40000000 && a <= 0x4000000f) /* Serial Port */ |
| 912 | 912 | return ppc403_spu_r(a); |
| 913 | return | |
| 913 | return space->r | |
| 914 | 914 | } |
| 915 | 915 | |
| 916 | 916 | #define ppc403_read16 memory_read_word_32be |
| 917 | 917 | #define ppc403_read32 memory_read_dword_32be |
| 918 | 918 | |
| 919 | static void ppc403_write8( | |
| 919 | static void ppc403_write8( | |
| 920 | 920 | { |
| 921 | 921 | if( a >= 0x40000000 && a <= 0x4000000f ) /* Serial Port */ |
| 922 | 922 | { |
| 923 | 923 | ppc403_spu_w(a, d); |
| 924 | 924 | return; |
| 925 | 925 | } |
| 926 | | |
| 926 | space-> | |
| 927 | 927 | } |
| 928 | 928 | |
| 929 | 929 | #define ppc403_write16 memory_write_word_32be |
| 930 | 930 | #define ppc403_write32 memory_write_dword_32be |
| 931 | 931 | |
| 932 | static UINT16 ppc403_read16_unaligned( | |
| 932 | static UINT16 ppc403_read16_unaligned( | |
| 933 | 933 | { |
| 934 | 934 | fatalerror("ppc: Unaligned read16 %08X at %08X", a, ppc.pc); |
| 935 | 935 | return 0; |
| 936 | 936 | } |
| 937 | 937 | |
| 938 | static UINT32 ppc403_read32_unaligned( | |
| 938 | static UINT32 ppc403_read32_unaligned( | |
| 939 | 939 | { |
| 940 | 940 | fatalerror("ppc: Unaligned read32 %08X at %08X", a, ppc.pc); |
| 941 | 941 | return 0; |
| 942 | 942 | } |
| 943 | 943 | |
| 944 | static void ppc403_write16_unaligned( | |
| 944 | static void ppc403_write16_unaligned( | |
| 945 | 945 | { |
| 946 | 946 | fatalerror("ppc: Unaligned write16 %08X, %04X at %08X", a, d, ppc.pc); |
| 947 | 947 | } |
| 948 | 948 | |
| 949 | static void ppc403_write32_unaligned( | |
| 949 | static void ppc403_write32_unaligned( | |
| 950 | 950 | { |
| 951 | 951 | fatalerror("ppc: Unaligned write32 %08X, %08X at %08X", a, d, ppc.pc); |
| 952 | 952 | } |
| r8806 | r8807 | |
|---|---|---|
| 66 | 66 | |
| 67 | 67 | /***********************************************************************/ |
| 68 | 68 | |
| 69 | static UINT16 ppc_read16_unaligned( | |
| 69 | static UINT16 ppc_read16_unaligned( | |
| 70 | 70 | { |
| 71 | 71 | return ((UINT16)ppc.read8(space, a+0) << 8) | ((UINT16)ppc.read8(space, a+1) << 0); |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | static UINT32 ppc_read32_unaligned( | |
| 74 | static UINT32 ppc_read32_unaligned( | |
| 75 | 75 | { |
| 76 | 76 | return ((UINT32)ppc.read8(space, a+0) << 24) | ((UINT32)ppc.read8(space, a+1) << 16) | |
| 77 | 77 | ((UINT32)ppc.read8(space, a+2) << 8) | ((UINT32)ppc.read8(space, a+3) << 0); |
| 78 | 78 | } |
| 79 | 79 | |
| 80 | static UINT64 ppc_read64_unaligned( | |
| 80 | static UINT64 ppc_read64_unaligned( | |
| 81 | 81 | { |
| 82 | 82 | return ((UINT64)READ32(space, a+0) << 32) | (UINT64)(READ32(space, a+4)); |
| 83 | 83 | } |
| 84 | 84 | |
| 85 | static void ppc_write16_unaligned( | |
| 85 | static void ppc_write16_unaligned( | |
| 86 | 86 | { |
| 87 | 87 | ppc.write8(space, a+0, (UINT8)(d >> 8)); |
| 88 | 88 | ppc.write8(space, a+1, (UINT8)(d)); |
| 89 | 89 | } |
| 90 | 90 | |
| 91 | static void ppc_write32_unaligned( | |
| 91 | static void ppc_write32_unaligned( | |
| 92 | 92 | { |
| 93 | 93 | ppc.write8(space, a+0, (UINT8)(d >> 24)); |
| 94 | 94 | ppc.write8(space, a+1, (UINT8)(d >> 16)); |
| r8806 | r8807 | |
| 96 | 96 | ppc.write8(space, a+3, (UINT8)(d >> 0)); |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | static void ppc_write64_unaligned( | |
| 99 | static void ppc_write64_unaligned( | |
| 100 | 100 | { |
| 101 | 101 | ppc.write32(space, a+0, (UINT32)(d >> 32)); |
| 102 | 102 | ppc.write32(space, a+4, (UINT32)(d)); |
| r8806 | r8807 | |
| 306 | 306 | return success; |
| 307 | 307 | } |
| 308 | 308 | |
| 309 | static UINT8 ppc_read8_translated( | |
| 309 | static UINT8 ppc_read8_translated( | |
| 310 | 310 | { |
| 311 | 311 | ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ); |
| 312 | return | |
| 312 | return space->r | |
| 313 | 313 | } |
| 314 | 314 | |
| 315 | static UINT16 ppc_read16_translated( | |
| 315 | static UINT16 ppc_read16_translated( | |
| 316 | 316 | { |
| 317 | 317 | ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ); |
| 318 | return | |
| 318 | return space->r | |
| 319 | 319 | } |
| 320 | 320 | |
| 321 | static UINT32 ppc_read32_translated( | |
| 321 | static UINT32 ppc_read32_translated( | |
| 322 | 322 | { |
| 323 | 323 | ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ); |
| 324 | return | |
| 324 | return space->r | |
| 325 | 325 | } |
| 326 | 326 | |
| 327 | static UINT64 ppc_read64_translated( | |
| 327 | static UINT64 ppc_read64_translated( | |
| 328 | 328 | { |
| 329 | 329 | ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ); |
| 330 | return | |
| 330 | return space->r | |
| 331 | 331 | } |
| 332 | 332 | |
| 333 | static void ppc_write8_translated( | |
| 333 | static void ppc_write8_translated( | |
| 334 | 334 | { |
| 335 | 335 | ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE); |
| 336 | | |
| 336 | space-> | |
| 337 | 337 | } |
| 338 | 338 | |
| 339 | static void ppc_write16_translated( | |
| 339 | static void ppc_write16_translated( | |
| 340 | 340 | { |
| 341 | 341 | ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE); |
| 342 | | |
| 342 | space-> | |
| 343 | 343 | } |
| 344 | 344 | |
| 345 | static void ppc_write32_translated( | |
| 345 | static void ppc_write32_translated( | |
| 346 | 346 | { |
| 347 | 347 | ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE); |
| 348 | | |
| 348 | space-> | |
| 349 | 349 | } |
| 350 | 350 | |
| 351 | static void ppc_write64_translated( | |
| 351 | static void ppc_write64_translated( | |
| 352 | 352 | { |
| 353 | 353 | ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE); |
| 354 | | |
| 354 | space-> | |
| 355 | 355 | } |
| 356 | 356 | |
| 357 | 357 | #ifndef PPC_DRC |
| 358 | static UINT32 ppc_readop_translated( | |
| 358 | static UINT32 ppc_readop_translated( | |
| 359 | 359 | { |
| 360 | 360 | ppc_translate_address(&address, PPC_TRANSLATE_CODE | PPC_TRANSLATE_READ); |
| 361 | return | |
| 361 | return space->r | |
| 362 | 362 | } |
| 363 | 363 | #endif |
| 364 | 364 | |
| r8806 | r8807 | |
| 385 | 385 | { |
| 386 | 386 | switch(size) |
| 387 | 387 | { |
| 388 | case 1: *value = memory_read_byte(ppc.program, offset); break; | |
| 389 | case 2: *value = memory_read_word(ppc.program, offset); break; | |
| 390 | case 4: *value = memory_read_dword(ppc.program, offset); break; | |
| 391 | case 8: *value = memory_read_qword(ppc.program, offset); break; | |
| 388 | case 1: *value = ppc.program->read_byte(offset); break; | |
| 389 | case 2: *value = ppc.program->read_word(offset); break; | |
| 390 | case 4: *value = ppc.program->read_dword(offset); break; | |
| 391 | case 8: *value = ppc.program->read_qword(offset); break; | |
| 392 | 392 | } |
| 393 | 393 | } |
| 394 | 394 | |
| r8806 | r8807 | |
| 406 | 406 | { |
| 407 | 407 | switch(size) |
| 408 | 408 | { |
| 409 | case 1: *value = memory_read_byte(ppc.program, offset); break; | |
| 410 | case 2: *value = memory_read_word(ppc.program, offset); break; | |
| 411 | case 4: *value = memory_read_dword(ppc.program, offset); break; | |
| 412 | case 8: *value = memory_read_qword(ppc.program, offset); break; | |
| 409 | case 1: *value = ppc.program->read_byte(offset); break; | |
| 410 | case 2: *value = ppc.program->read_word(offset); break; | |
| 411 | case 4: *value = ppc.program->read_dword(offset); break; | |
| 412 | case 8: *value = ppc.program->read_qword(offset); break; | |
| 413 | 413 | } |
| 414 | 414 | } |
| 415 | 415 | |
| r8806 | r8807 | |
| 425 | 425 | { |
| 426 | 426 | switch(size) |
| 427 | 427 | { |
| 428 | case 1: memory_write_byte(ppc.program, offset, value); break; | |
| 429 | case 2: memory_write_word(ppc.program, offset, value); break; | |
| 430 | case 4: memory_write_dword(ppc.program, offset, value); break; | |
| 431 | case 8: memory_write_qword(ppc.program, offset, value); break; | |
| 428 | case 1: ppc.program->write_byte(offset, value); break; | |
| 429 | case 2: ppc.program->write_word(offset, value); break; | |
| 430 | case 4: ppc.program->write_dword(offset, value); break; | |
| 431 | case 8: ppc.program->write_qword(offset, value); break; | |
| 432 | 432 | } |
| 433 | 433 | } |
| 434 | 434 |
| r8806 | r8807 | |
|---|---|---|
| 1639 | 1639 | return FALSE; |
| 1640 | 1640 | |
| 1641 | 1641 | /* fetch the data */ |
| 1642 | *byte = | |
| 1642 | *byte = | |
| 1643 | 1643 | ppc4xx_dma_decrement_count(ppc, dmachan); |
| 1644 | 1644 | return TRUE; |
| 1645 | 1645 | } |
| r8806 | r8807 | |
| 1663 | 1663 | return FALSE; |
| 1664 | 1664 | |
| 1665 | 1665 | /* store the data */ |
| 1666 | | |
| 1666 | ppc->program->write_byte( | |
| 1667 | 1667 | ppc4xx_dma_decrement_count(ppc, dmachan); |
| 1668 | 1668 | return TRUE; |
| 1669 | 1669 | } |
| r8806 | r8807 | |
| 1716 | 1716 | case 1: |
| 1717 | 1717 | do |
| 1718 | 1718 | { |
| 1719 | | |
| 1719 | ppc->program->write_byte( | |
| 1720 | 1720 | dmaregs[DCR4XX_DMASA0] += srcinc; |
| 1721 | 1721 | dmaregs[DCR4XX_DMADA0] += destinc; |
| 1722 | 1722 | } while (!ppc4xx_dma_decrement_count(ppc, dmachan)); |
| r8806 | r8807 | |
| 1726 | 1726 | case 2: |
| 1727 | 1727 | do |
| 1728 | 1728 | { |
| 1729 | | |
| 1729 | ppc->program->write_word( | |
| 1730 | 1730 | dmaregs[DCR4XX_DMASA0] += srcinc; |
| 1731 | 1731 | dmaregs[DCR4XX_DMADA0] += destinc; |
| 1732 | 1732 | } while (!ppc4xx_dma_decrement_count(ppc, dmachan)); |
| r8806 | r8807 | |
| 1736 | 1736 | case 4: |
| 1737 | 1737 | do |
| 1738 | 1738 | { |
| 1739 | | |
| 1739 | ppc->program->write_dword( | |
| 1740 | 1740 | dmaregs[DCR4XX_DMASA0] += srcinc; |
| 1741 | 1741 | dmaregs[DCR4XX_DMADA0] += destinc; |
| 1742 | 1742 | } while (!ppc4xx_dma_decrement_count(ppc, dmachan)); |
| r8806 | r8807 | |
| 1746 | 1746 | case 16: |
| 1747 | 1747 | do |
| 1748 | 1748 | { |
| 1749 | memory_write_qword(ppc->program, dmaregs[DCR4XX_DMADA0], memory_read_qword(ppc->program, dmaregs[DCR4XX_DMASA0])); | |
| 1750 | memory_write_qword(ppc->program, dmaregs[DCR4XX_DMADA0] + 8, memory_read_qword(ppc->program, dmaregs[DCR4XX_DMASA0] + 8)); | |
| 1749 | ppc->program->write_qword(dmaregs[DCR4XX_DMADA0], ppc->program->read_qword(dmaregs[DCR4XX_DMASA0])); | |
| 1750 | ppc->program->write_qword(dmaregs[DCR4XX_DMADA0] + 8, ppc->program->read_qword(dmaregs[DCR4XX_DMASA0] + 8)); | |
| 1751 | 1751 | dmaregs[DCR4XX_DMASA0] += srcinc; |
| 1752 | 1752 | dmaregs[DCR4XX_DMADA0] += destinc; |
| 1753 | 1753 | } while (!ppc4xx_dma_decrement_count(ppc, dmachan)); |
| r8806 | r8807 | |
|---|---|---|
| 307 | 307 | |
| 308 | 308 | device_irq_callback irq_callback; |
| 309 | 309 | legacy_cpu_device *device; |
| 310 | | |
| 310 | | |
| 311 | 311 | |
| 312 | 312 | // STUFF added for the 6xx series |
| 313 | 313 | UINT32 dec, dec_frac; |
| r8806 | r8807 | |
| 330 | 330 | |
| 331 | 331 | /* PowerPC function pointers for memory accesses/exceptions */ |
| 332 | 332 | jmp_buf exception_jmpbuf; |
| 333 | UINT8 (*read8)(const address_space *space, offs_t address); | |
| 334 | UINT16 (*read16)(const address_space *space, offs_t address); | |
| 335 | UINT32 (*read32)(const address_space *space, offs_t address); | |
| 336 | UINT64 (*read64)(const address_space *space, offs_t address); | |
| 337 | void (*write8)(const address_space *space, offs_t address, UINT8 data); | |
| 338 | void (*write16)(const address_space *space, offs_t address, UINT16 data); | |
| 339 | void (*write32)(const address_space *space, offs_t address, UINT32 data); | |
| 340 | void (*write64)(const address_space *space, offs_t address, UINT64 data); | |
| 341 | UINT16 (*read16_unaligned)(const address_space *space, offs_t address); | |
| 342 | UINT32 (*read32_unaligned)(const address_space *space, offs_t address); | |
| 343 | UINT64 (*read64_unaligned)(const address_space *space, offs_t address); | |
| 344 | void (*write16_unaligned)(const address_space *space, offs_t address, UINT16 data); | |
| 345 | void (*write32_unaligned)(const address_space *space, offs_t address, UINT32 data); | |
| 346 | void (*write64_unaligned)(const address_space *space, offs_t address, UINT64 data); | |
| 333 | UINT8 (*read8)(address_space *space, offs_t address); | |
| 334 | UINT16 (*read16)(address_space *space, offs_t address); | |
| 335 | UINT32 (*read32)(address_space *space, offs_t address); | |
| 336 | UINT64 (*read64)(address_space *space, offs_t address); | |
| 337 | void (*write8)(address_space *space, offs_t address, UINT8 data); | |
| 338 | void (*write16)(address_space *space, offs_t address, UINT16 data); | |
| 339 | void (*write32)(address_space *space, offs_t address, UINT32 data); | |
| 340 | void (*write64)(address_space *space, offs_t address, UINT64 data); | |
| 341 | UINT16 (*read16_unaligned)(address_space *space, offs_t address); | |
| 342 | UINT32 (*read32_unaligned)(address_space *space, offs_t address); | |
| 343 | UINT64 (*read64_unaligned)(address_space *space, offs_t address); | |
| 344 | void (*write16_unaligned)(address_space *space, offs_t address, UINT16 data); | |
| 345 | void (*write32_unaligned)(address_space *space, offs_t address, UINT32 data); | |
| 346 | void (*write64_unaligned)(address_space *space, offs_t address, UINT64 data); | |
| 347 | 347 | |
| 348 | 348 | void (* optable19[1024])(UINT32); |
| 349 | 349 | void (* optable31[1024])(UINT32); |
| r8806 | r8807 | |
| 786 | 786 | return 0; |
| 787 | 787 | } |
| 788 | 788 | |
| 789 | static UINT8 ppc_read8_translated(const address_space *space, offs_t address); | |
| 790 | static UINT16 ppc_read16_translated(const address_space *space, offs_t address); | |
| 791 | static UINT32 ppc_read32_translated(const address_space *space, offs_t address); | |
| 792 | static UINT64 ppc_read64_translated(const address_space *space, offs_t address); | |
| 793 | static void ppc_write8_translated(const address_space *space, offs_t address, UINT8 data); | |
| 794 | static void ppc_write16_translated(const address_space *space, offs_t address, UINT16 data); | |
| 795 | static void ppc_write32_translated(const address_space *space, offs_t address, UINT32 data); | |
| 796 | static void ppc_write64_translated(const address_space *space, offs_t address, UINT64 data); | |
| 789 | static UINT8 ppc_read8_translated(address_space *space, offs_t address); | |
| 790 | static UINT16 ppc_read16_translated(address_space *space, offs_t address); | |
| 791 | static UINT32 ppc_read32_translated(address_space *space, offs_t address); | |
| 792 | static UINT64 ppc_read64_translated(address_space *space, offs_t address); | |
| 793 | static void ppc_write8_translated(address_space *space, offs_t address, UINT8 data); | |
| 794 | static void ppc_write16_translated(address_space *space, offs_t address, UINT16 data); | |
| 795 | static void ppc_write32_translated(address_space *space, offs_t address, UINT32 data); | |
| 796 | static void ppc_write64_translated(address_space *space, offs_t address, UINT64 data); | |
| 797 | 797 | |
| 798 | 798 | INLINE void ppc_set_msr(UINT32 value) |
| 799 | 799 | { |
| r8806 | r8807 | |
|---|---|---|
| 552 | 552 | /* internal stuff */ |
| 553 | 553 | device_irq_callback irq_callback; |
| 554 | 554 | legacy_cpu_device * device; |
| 555 | | |
| 555 | | |
| 556 | 556 | offs_t codexor; |
| 557 | 557 | UINT32 irq_pending; |
| 558 | 558 | UINT32 system_clock; |
| r8806 | r8807 | |
|---|---|---|
| 236 | 236 | UINT8 pendingFiq; |
| 237 | 237 | device_irq_callback irq_callback; |
| 238 | 238 | legacy_cpu_device *device; |
| 239 | | |
| 239 | | |
| 240 | 240 | endianness_t endian; |
| 241 | 241 | } ARM_REGS; |
| 242 | 242 | |
| r8806 | r8807 | |
| 263 | 263 | { |
| 264 | 264 | /* Unaligned writes are treated as normal writes */ |
| 265 | 265 | if ( cpustate->endian == ENDIANNESS_BIG ) |
| 266 | | |
| 266 | | |
| 267 | 267 | else |
| 268 | | |
| 268 | | |
| 269 | 269 | if (ARM_DEBUG_CORE && addr&3) logerror("%08x: Unaligned write %08x\n",R15,addr); |
| 270 | 270 | } |
| 271 | 271 | |
| 272 | 272 | INLINE void cpu_write8( ARM_REGS* cpustate, int addr, UINT8 data ) |
| 273 | 273 | { |
| 274 | 274 | if ( cpustate->endian == ENDIANNESS_BIG ) |
| 275 | | |
| 275 | | |
| 276 | 276 | else |
| 277 | | |
| 277 | | |
| 278 | 278 | } |
| 279 | 279 | |
| 280 | 280 | INLINE UINT32 cpu_read32( ARM_REGS* cpustate, int addr ) |
| r8806 | r8807 | |
| 282 | 282 | UINT32 result; |
| 283 | 283 | |
| 284 | 284 | if ( cpustate->endian == ENDIANNESS_BIG ) |
| 285 | result = | |
| 285 | result = | |
| 286 | 286 | else |
| 287 | result = | |
| 287 | result = | |
| 288 | 288 | |
| 289 | 289 | /* Unaligned reads rotate the word, they never combine words */ |
| 290 | 290 | if (addr&3) { |
| r8806 | r8807 | |
| 305 | 305 | INLINE UINT8 cpu_read8( ARM_REGS* cpustate, int addr ) |
| 306 | 306 | { |
| 307 | 307 | if ( cpustate->endian == ENDIANNESS_BIG ) |
| 308 | return | |
| 308 | return | |
| 309 | 309 | else |
| 310 | return | |
| 310 | return | |
| 311 | 311 | } |
| 312 | 312 | |
| 313 | 313 | INLINE UINT32 GetRegister( ARM_REGS* cpustate, int rIndex ) |
| r8806 | r8807 | |
|---|---|---|
| 66 | 66 | int ei_delay; |
| 67 | 67 | device_irq_callback irq_callback; |
| 68 | 68 | legacy_cpu_device *device; |
| 69 | | |
| 69 | | |
| 70 | 70 | int icount; |
| 71 | 71 | /* Timer stuff */ |
| 72 | 72 | lr35902_timer_fired_func timer_fired_func; |
| r8806 | r8807 | |
| 129 | 129 | /* Memory functions */ |
| 130 | 130 | /****************************************************************************/ |
| 131 | 131 | |
| 132 | #define mem_ReadByte(cs,A) ((UINT8)memory_read_byte_8le((cs)->w.program,A)) | |
| 133 | #define mem_WriteByte(cs,A,V) (memory_write_byte_8le((cs)->w.program,A,V)) | |
| 132 | #define mem_ReadByte(cs,A) ((UINT8)(cs)->w.program->read_byte(A)) | |
| 133 | #define mem_WriteByte(cs,A,V) ((cs)->w.program->write_byte(A,V)) | |
| 134 | 134 | |
| 135 | 135 | INLINE UINT16 mem_ReadWord (lr35902_state *cpustate, UINT32 address) |
| 136 | 136 | { |
| r8806 | r8807 | |
|---|---|---|
| 83 | 83 | int irq_state[2]; /* IRQ line states (NVI, VI) */ |
| 84 | 84 | device_irq_callback irq_callback; |
| 85 | 85 | legacy_cpu_device *device; |
| 86 | const address_space *program; | |
| 87 | const address_space *io; | |
| 86 | address_space *program; | |
| 87 | address_space *io; | |
| 88 | 88 | int icount; |
| 89 | 89 | }; |
| 90 | 90 | |
| r8806 | r8807 | |
| 115 | 115 | |
| 116 | 116 | INLINE UINT8 RDMEM_B(z8000_state *cpustate, UINT32 addr) |
| 117 | 117 | { |
| 118 | return | |
| 118 | return | |
| 119 | 119 | } |
| 120 | 120 | |
| 121 | 121 | INLINE UINT16 RDMEM_W(z8000_state *cpustate, UINT32 addr) |
| 122 | 122 | { |
| 123 | 123 | addr &= ~1; |
| 124 | return | |
| 124 | return | |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | 127 | INLINE UINT32 RDMEM_L(z8000_state *cpustate, UINT32 addr) |
| 128 | 128 | { |
| 129 | 129 | UINT32 result; |
| 130 | 130 | addr &= ~1; |
| 131 | result = memory_read_word_16be(cpustate->program, addr) << 16; | |
| 132 | return result + memory_read_word_16be(cpustate->program, addr + 2); | |
| 131 | result = cpustate->program->read_word(addr) << 16; | |
| 132 | return result + cpustate->program->read_word(addr + 2); | |
| 133 | 133 | } |
| 134 | 134 | |
| 135 | 135 | INLINE void WRMEM_B(z8000_state *cpustate, UINT32 addr, UINT8 value) |
| 136 | 136 | { |
| 137 | | |
| 137 | | |
| 138 | 138 | } |
| 139 | 139 | |
| 140 | 140 | INLINE void WRMEM_W(z8000_state *cpustate, UINT32 addr, UINT16 value) |
| 141 | 141 | { |
| 142 | 142 | addr &= ~1; |
| 143 | | |
| 143 | | |
| 144 | 144 | } |
| 145 | 145 | |
| 146 | 146 | INLINE void WRMEM_L(z8000_state *cpustate, UINT32 addr, UINT32 value) |
| 147 | 147 | { |
| 148 | 148 | addr &= ~1; |
| 149 | memory_write_word_16be(cpustate->program, addr, value >> 16); | |
| 150 | memory_write_word_16be(cpustate->program, (UINT16)(addr + 2), value & 0xffff); | |
| 149 | cpustate->program->write_word(addr, value >> 16); | |
| 150 | cpustate->program->write_word((UINT16)(addr + 2), value & 0xffff); | |
| 151 | 151 | } |
| 152 | 152 | |
| 153 | 153 | INLINE UINT8 RDPORT_B(z8000_state *cpustate, int mode, UINT16 addr) |
| 154 | 154 | { |
| 155 | 155 | if(mode == 0) |
| 156 | 156 | { |
| 157 | return | |
| 157 | return | |
| 158 | 158 | } |
| 159 | 159 | else |
| 160 | 160 | { |
| r8806 | r8807 | |
| 167 | 167 | { |
| 168 | 168 | if(mode == 0) |
| 169 | 169 | { |
| 170 | return memory_read_byte_8le(cpustate->io, (UINT16)(addr)) + | |
| 171 | (memory_read_byte_8le(cpustate->io, (UINT16)(addr+1)) << 8); | |
| 170 | return cpustate->io->read_byte((UINT16)(addr)) + | |
| 171 | (cpustate->io->read_byte((UINT16)(addr+1)) << 8); | |
| 172 | 172 | } |
| 173 | 173 | else |
| 174 | 174 | { |
| r8806 | r8807 | |
| 181 | 181 | { |
| 182 | 182 | if(mode == 0) |
| 183 | 183 | { |
| 184 | | |
| 184 | cpustate->io-> | |
| 185 | 185 | } |
| 186 | 186 | else |
| 187 | 187 | { |
| r8806 | r8807 | |
| 193 | 193 | { |
| 194 | 194 | if(mode == 0) |
| 195 | 195 | { |
| 196 | memory_write_byte_8le(cpustate->io, (UINT16)(addr),value & 0xff); | |
| 197 | memory_write_byte_8le(cpustate->io, (UINT16)(addr+1),(value >> 8) & 0xff); | |
| 196 | cpustate->io->write_byte((UINT16)(addr),value & 0xff); | |
| 197 | cpustate->io->write_byte((UINT16)(addr+1),(value >> 8) & 0xff); | |
| 198 | 198 | } |
| 199 | 199 | else |
| 200 | 200 | { |
| r8806 | r8807 | |
|---|---|---|
| 98 | 98 | int addr_mask; |
| 99 | 99 | |
| 100 | 100 | legacy_cpu_device *device; |
| 101 | const address_space *program; | |
| 102 | const address_space *data; | |
| 103 | const address_space *io; | |
| 101 | address_space *program; | |
| 102 | address_space *data; | |
| 103 | address_space *io; | |
| 104 | 104 | }; |
| 105 | 105 | |
| 106 | 106 | INLINE tms32010_state *get_safe_token(running_device *device) |
| r8806 | r8807 | |
| 148 | 148 | * Read the state of the BIO pin |
| 149 | 149 | */ |
| 150 | 150 | |
| 151 | #define TMS32010_BIO_In ( | |
| 151 | #define TMS32010_BIO_In ( | |
| 152 | 152 | |
| 153 | 153 | |
| 154 | 154 | /**************************************************************************** |
| 155 | 155 | * Input a word from given I/O port |
| 156 | 156 | */ |
| 157 | 157 | |
| 158 | #define TMS32010_In(Port) ( | |
| 158 | #define TMS32010_In(Port) ( | |
| 159 | 159 | |
| 160 | 160 | |
| 161 | 161 | /**************************************************************************** |
| 162 | 162 | * Output a word to given I/O port |
| 163 | 163 | */ |
| 164 | 164 | |
| 165 | #define TMS32010_Out(Port,Value) ( | |
| 165 | #define TMS32010_Out(Port,Value) (cpustate->io-> | |
| 166 | 166 | |
| 167 | 167 | |
| 168 | 168 | |
| r8806 | r8807 | |
| 170 | 170 | * Read a word from given ROM memory location |
| 171 | 171 | */ |
| 172 | 172 | |
| 173 | #define TMS32010_ROM_RDMEM(A) ( | |
| 173 | #define TMS32010_ROM_RDMEM(A) ( | |
| 174 | 174 | |
| 175 | 175 | |
| 176 | 176 | /**************************************************************************** |
| 177 | 177 | * Write a word to given ROM memory location |
| 178 | 178 | */ |
| 179 | 179 | |
| 180 | #define TMS32010_ROM_WRMEM(A,V) ( | |
| 180 | #define TMS32010_ROM_WRMEM(A,V) ( | |
| 181 | 181 | |
| 182 | 182 | |
| 183 | 183 | |
| r8806 | r8807 | |
| 185 | 185 | * Read a word from given RAM memory location |
| 186 | 186 | */ |
| 187 | 187 | |
| 188 | #define TMS32010_RAM_RDMEM(A) ( | |
| 188 | #define TMS32010_RAM_RDMEM(A) ( | |
| 189 | 189 | |
| 190 | 190 | |
| 191 | 191 | /**************************************************************************** |
| 192 | 192 | * Write a word to given RAM memory location |
| 193 | 193 | */ |
| 194 | 194 | |
| 195 | #define TMS32010_RAM_WRMEM(A,V) ( | |
| 195 | #define TMS32010_RAM_WRMEM(A,V) ( | |
| 196 | 196 | |
| 197 | 197 | |
| 198 | 198 |
| r8806 | r8807 | |
|---|---|---|
| 116 | 116 | INT8 irq_line_state[17]; |
| 117 | 117 | device_irq_callback irq_callback; |
| 118 | 118 | legacy_cpu_device *device; |
| 119 | const address_space *program; | |
| 120 | const address_space *internal; | |
| 119 | address_space *program; | |
| 120 | address_space *internal; | |
| 121 | 121 | UINT32 *m; |
| 122 | 122 | INT8 nmi_line_state; |
| 123 | 123 |
| r8806 | r8807 | |
|---|---|---|
| 151 | 151 | return sh2_internal_r(sh2->internal, (A & 0x1fc)>>2, 0xffff << (((~A) & 2)*8)) >> (((~A) & 2)*8); |
| 152 | 152 | |
| 153 | 153 | if (A >= 0xc0000000) |
| 154 | return | |
| 154 | return | |
| 155 | 155 | |
| 156 | return | |
| 156 | return | |
| 157 | 157 | } |
| 158 | 158 | |
| 159 | 159 | INLINE UINT32 RL(sh2_state *sh2, offs_t A) |
| r8806 | r8807 | |
| 162 | 162 | return sh2_internal_r(sh2->internal, (A & 0x1fc)>>2, 0xffffffff); |
| 163 | 163 | |
| 164 | 164 | if (A >= 0xc0000000) |
| 165 | return | |
| 165 | return sh2->program->read_dword | |
| 166 | 166 | |
| 167 | return | |
| 167 | return sh2->program->read_dword | |
| 168 | 168 | } |
| 169 | 169 | |
| 170 | 170 | /*------------------------------------------------- |
| r8806 | r8807 | |
| 827 | 827 | sh2->m = m; |
| 828 | 828 | memset(sh2->m, 0, 0x200); |
| 829 | 829 | |
| 830 | sh2->pc = memory_read_dword_32be(sh2->program, 0); | |
| 831 | sh2->r[15] = memory_read_dword_32be(sh2->program, 4); | |
| 830 | sh2->pc = sh2->program->read_dword(0); | |
| 831 | sh2->r[15] = sh2->program->read_dword(4); | |
| 832 | 832 | sh2->sr = I; |
| 833 | 833 | |
| 834 | 834 | sh2->internal_irq_level = -1; |
| r8806 | r8807 | |
|---|---|---|
| 30 | 30 | return sh2_internal_r(sh2->internal, (A & 0x1fc)>>2, 0xffffffff); |
| 31 | 31 | |
| 32 | 32 | if (A >= 0xc0000000) |
| 33 | return | |
| 33 | return sh2->program->read_dword | |
| 34 | 34 | |
| 35 | 35 | if (A >= 0x40000000) |
| 36 | 36 | return 0xa5a5a5a5; |
| 37 | 37 | |
| 38 | return | |
| 38 | return sh2->program->read_dword | |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | 41 | INLINE void WL(sh2_state *sh2, offs_t A, UINT32 V) |
| r8806 | r8807 | |
| 48 | 48 | |
| 49 | 49 | if (A >= 0xc0000000) |
| 50 | 50 | { |
| 51 | | |
| 51 | sh2->program->write_dword | |
| 52 | 52 | return; |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | 55 | if (A >= 0x40000000) |
| 56 | 56 | return; |
| 57 | 57 | |
| 58 | | |
| 58 | sh2->program->write_dword | |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | 61 | static void sh2_timer_resync(sh2_state *sh2) |
| r8806 | r8807 | |
| 185 | 185 | if(incd == 2) |
| 186 | 186 | dst --; |
| 187 | 187 | |
| 188 | dmadata = | |
| 188 | dmadata = | |
| 189 | 189 | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(src, dst, dmadata, size); |
| 190 | | |
| 190 | sh2->program->write_byte | |
| 191 | 191 | |
| 192 | 192 | if(incs == 1) |
| 193 | 193 | src ++; |
| r8806 | r8807 | |
| 207 | 207 | dst -= 2; |
| 208 | 208 | |
| 209 | 209 | // check: should this really be using read_word_32 / write_word_32? |
| 210 | dmadata = | |
| 210 | dmadata = | |
| 211 | 211 | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(src, dst, dmadata, size); |
| 212 | | |
| 212 | sh2->program->write_word | |
| 213 | 213 | |
| 214 | 214 | if(incs == 1) |
| 215 | 215 | src += 2; |
| r8806 | r8807 | |
| 227 | 227 | if(incd == 2) |
| 228 | 228 | dst -= 4; |
| 229 | 229 | |
| 230 | dmadata = | |
| 230 | dmadata = sh2->program->read_dword | |
| 231 | 231 | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(src, dst, dmadata, size); |
| 232 | | |
| 232 | sh2->program->write_dword | |
| 233 | 233 | |
| 234 | 234 | if(incs == 1) |
| 235 | 235 | src += 4; |
| r8806 | r8807 | |
| 247 | 247 | if(incd == 2) |
| 248 | 248 | dst -= 16; |
| 249 | 249 | |
| 250 | dmadata = | |
| 250 | dmadata = sh2->program->read_dword | |
| 251 | 251 | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(src, dst, dmadata, size); |
| 252 | | |
| 252 | sh2->program->write_dword | |
| 253 | 253 | |
| 254 | dmadata = | |
| 254 | dmadata = sh2->program->read_dword | |
| 255 | 255 | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(src, dst, dmadata, size); |
| 256 | | |
| 256 | sh2->program->write_dword | |
| 257 | 257 | |
| 258 | dmadata = | |
| 258 | dmadata = sh2->program->read_dword | |
| 259 | 259 | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(src, dst, dmadata, size); |
| 260 | | |
| 260 | sh2->program->write_dword | |
| 261 | 261 | |
| 262 | dmadata = | |
| 262 | dmadata = sh2->program->read_dword | |
| 263 | 263 | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(src, dst, dmadata, size); |
| 264 | | |
| 264 | sh2->program->write_dword | |
| 265 | 265 | |
| 266 | 266 | src += 16; |
| 267 | 267 | if(incd == 1) |
| r8806 | r8807 | |
| 702 | 702 | void sh2_common_init(sh2_state *sh2, legacy_cpu_device *device, device_irq_callback irqcallback) |
| 703 | 703 | { |
| 704 | 704 | const sh2_cpu_core *conf = (const sh2_cpu_core *)device->baseconfig().static_config(); |
| 705 | int i; | |
| 705 | 706 | |
| 706 | 707 | sh2->timer = timer_alloc(device->machine, sh2_timer_callback, sh2); |
| 707 | 708 | timer_adjust_oneshot(sh2->timer, attotime_never, 0); |
| r8806 | r8807 | |
| 731 | 732 | sh2->internal = device->space(AS_PROGRAM); |
| 732 | 733 | |
| 733 | 734 | state_save_register_device_item(device, 0, sh2->pc); |
| 734 | state_save_register_device_item(device, 0, sh2->r[15]); | |
| 735 | 735 | state_save_register_device_item(device, 0, sh2->sr); |
| 736 | 736 | state_save_register_device_item(device, 0, sh2->pr); |
| 737 | 737 | state_save_register_device_item(device, 0, sh2->gbr); |
| 738 | 738 | state_save_register_device_item(device, 0, sh2->vbr); |
| 739 | 739 | state_save_register_device_item(device, 0, sh2->mach); |
| 740 | 740 | state_save_register_device_item(device, 0, sh2->macl); |
| 741 | state_save_register_device_item(device, 0, sh2->r[ 0]); | |
| 742 | state_save_register_device_item(device, 0, sh2->r[ 1]); | |
| 743 | state_save_register_device_item(device, 0, sh2->r[ 2]); | |
| 744 | state_save_register_device_item(device, 0, sh2->r[ 3]); | |
| 745 | state_save_register_device_item(device, 0, sh2->r[ 4]); | |
| 746 | state_save_register_device_item(device, 0, sh2->r[ 5]); | |
| 747 | state_save_register_device_item(device, 0, sh2->r[ 6]); | |
| 748 | state_save_register_device_item(device, 0, sh2->r[ 7]); | |
| 749 | state_save_register_device_item(device, 0, sh2->r[ 8]); | |
| 750 | state_save_register_device_item(device, 0, sh2->r[ 9]); | |
| 751 | state_save_register_device_item(device, 0, sh2->r[10]); | |
| 752 | state_save_register_device_item(device, 0, sh2->r[11]); | |
| 753 | state_save_register_device_item(device, 0, sh2->r[12]); | |
| 754 | state_save_register_device_item(device, 0, sh2->r[13]); | |
| 755 | state_save_register_device_item(device, 0, sh2->r[14]); | |
| 741 | state_save_register_device_item_array(device, 0, sh2->r); | |
| 756 | 742 | state_save_register_device_item(device, 0, sh2->ea); |
| 743 | state_save_register_device_item(device, 0, sh2->delay); | |
| 744 | state_save_register_device_item(device, 0, sh2->cpu_off); | |
| 745 | state_save_register_device_item(device, 0, sh2->dvsr); | |
| 746 | state_save_register_device_item(device, 0, sh2->dvdnth); | |
| 747 | state_save_register_device_item(device, 0, sh2->dvdntl); | |
| 748 | state_save_register_device_item(device, 0, sh2->dvcr); | |
| 749 | state_save_register_device_item(device, 0, sh2->pending_irq); | |
| 750 | state_save_register_device_item(device, 0, sh2->test_irq); | |
| 751 | state_save_register_device_item(device, 0, sh2->pending_nmi); | |
| 752 | state_save_register_device_item(device, 0, sh2->irqline); | |
| 753 | state_save_register_device_item(device, 0, sh2->evec); | |
| 754 | state_save_register_device_item(device, 0, sh2->irqsr); | |
| 755 | state_save_register_device_item(device, 0, sh2->target); | |
| 756 | for (i = 0; i < 16; ++i) | |
| 757 | { | |
| 758 | state_save_register_device_item(device, i, sh2->irq_queue[i].irq_vector); | |
| 759 | state_save_register_device_item(device, i, sh2->irq_queue[i].irq_priority); | |
| 760 | } | |
| 761 | state_save_register_device_item(device, 0, sh2->pcfsel); | |
| 762 | state_save_register_device_item(device, 0, sh2->maxpcfsel); | |
| 763 | state_save_register_device_item_array(device, 0, sh2->pcflushes); | |
| 764 | state_save_register_device_item_array(device, 0, sh2->irq_line_state); | |
| 765 | state_save_register_device_item_pointer(device, 0, sh2->m, 0x200/4); | |
| 766 | state_save_register_device_item(device, 0, sh2->nmi_line_state); | |
| 767 | state_save_register_device_item(device, 0, sh2->frc); | |
| 768 | state_save_register_device_item(device, 0, sh2->ocra); | |
| 769 | state_save_register_device_item(device, 0, sh2->ocrb); | |
| 770 | state_save_register_device_item(device, 0, sh2->icr); | |
| 771 | state_save_register_device_item(device, 0, sh2->frc_base); | |
| 772 | state_save_register_device_item(device, 0, sh2->frt_input); | |
| 773 | state_save_register_device_item(device, 0, sh2->internal_irq_level); | |
| 774 | state_save_register_device_item(device, 0, sh2->internal_irq_vector); | |
| 775 | state_save_register_device_item(device, 0, sh2->icount); | |
| 776 | state_save_register_device_item_array(device, 0, sh2->dma_timer_active); | |
| 757 | 777 | } |
| 758 | 778 |
| r8806 | r8807 | |
|---|---|---|
| 131 | 131 | return sh2_internal_r(sh2->internal, (A & 0x1fc)>>2, 0xff << (((~A) & 3)*8)) >> (((~A) & 3)*8); |
| 132 | 132 | |
| 133 | 133 | if (A >= 0xc0000000) |
| 134 | return | |
| 134 | return | |
| 135 | 135 | |
| 136 | 136 | if (A >= 0x40000000) |
| 137 | 137 | return 0xa5; |
| 138 | 138 | |
| 139 | return | |
| 139 | return | |
| 140 | 140 | } |
| 141 | 141 | |
| 142 | 142 | INLINE UINT16 RW(sh2_state *sh2, offs_t A) |
| r8806 | r8807 | |
| 145 | 145 | return sh2_internal_r(sh2->internal, (A & 0x1fc)>>2, 0xffff << (((~A) & 2)*8)) >> (((~A) & 2)*8); |
| 146 | 146 | |
| 147 | 147 | if (A >= 0xc0000000) |
| 148 | return | |
| 148 | return | |
| 149 | 149 | |
| 150 | 150 | if (A >= 0x40000000) |
| 151 | 151 | return 0xa5a5; |
| 152 | 152 | |
| 153 | return | |
| 153 | return | |
| 154 | 154 | } |
| 155 | 155 | |
| 156 | 156 | INLINE UINT32 RL(sh2_state *sh2, offs_t A) |
| r8806 | r8807 | |
| 159 | 159 | return sh2_internal_r(sh2->internal, (A & 0x1fc)>>2, 0xffffffff); |
| 160 | 160 | |
| 161 | 161 | if (A >= 0xc0000000) |
| 162 | return | |
| 162 | return sh2->program->read_dword | |
| 163 | 163 | |
| 164 | 164 | if (A >= 0x40000000) |
| 165 | 165 | return 0xa5a5a5a5; |
| 166 | 166 | |
| 167 | return | |
| 167 | return sh2->program->read_dword | |
| 168 | 168 | } |
| 169 | 169 | |
| 170 | 170 | INLINE void WB(sh2_state *sh2, offs_t A, UINT8 V) |
| r8806 | r8807 | |
| 178 | 178 | |
| 179 | 179 | if (A >= 0xc0000000) |
| 180 | 180 | { |
| 181 | | |
| 181 | sh2->program->write_byte | |
| 182 | 182 | return; |
| 183 | 183 | } |
| 184 | 184 | |
| 185 | 185 | if (A >= 0x40000000) |
| 186 | 186 | return; |
| 187 | 187 | |
| 188 | | |
| 188 | sh2->program->write_byte | |
| 189 | 189 | } |
| 190 | 190 | |
| 191 | 191 | INLINE void WW(sh2_state *sh2, offs_t A, UINT16 V) |
| r8806 | r8807 | |
| 198 | 198 | |
| 199 | 199 | if (A >= 0xc0000000) |
| 200 | 200 | { |
| 201 | | |
| 201 | sh2->program->write_word | |
| 202 | 202 | return; |
| 203 | 203 | } |
| 204 | 204 | |
| 205 | 205 | if (A >= 0x40000000) |
| 206 | 206 | return; |
| 207 | 207 | |
| 208 | | |
| 208 | sh2->program->write_word | |
| 209 | 209 | } |
| 210 | 210 | |
| 211 | 211 | INLINE void WL(sh2_state *sh2, offs_t A, UINT32 V) |
| r8806 | r8807 | |
| 218 | 218 | |
| 219 | 219 | if (A >= 0xc0000000) |
| 220 | 220 | { |
| 221 | | |
| 221 | sh2->program->write_dword | |
| 222 | 222 | return; |
| 223 | 223 | } |
| 224 | 224 | |
| 225 | 225 | if (A >= 0x40000000) |
| 226 | 226 | return; |
| 227 | 227 | |
| 228 | | |
| 228 | sh2->program->write_dword | |
| 229 | 229 | } |
| 230 | 230 | |
| 231 | 231 | /* code cycles t-bit |
| r8806 | r8807 | |
|---|---|---|
| 41 | 41 | "iret", "jmp", "mov", "movm", "movw", "mult", "neg", "nop", "or", |
| 42 | 42 | "orw", "pop", "popw", "push", "pushw", "ret", "rl", "rlc", |
| 43 | 43 | "rr", "rrc", "sbc", "sbcw", "setc", "sll", "sra", "srl", "stop", |
| 44 | "sub", "subw", "swap", "xor", "xorw", "mov | |
| 44 | "sub", "subw", "swap", "xor", "xorw", "mov | |
| 45 | 45 | /* unknowns */ |
| 46 | 46 | "unk5A", "unk5B", |
| 47 | 47 |
| r8806 | r8807 | |
|---|---|---|
| 36 | 36 | |
| 37 | 37 | extern CPU_DISASSEMBLE( sm8500 ); |
| 38 | 38 | |
| 39 | UINT8 *sm8500_get_internal_ram(legacy_cpu_device *device); | |
| 40 | ||
| 39 | 41 | #endif /* __SM8500_H__ */ |
| r8806 | r8807 | |
|---|---|---|
| 488 | 488 | case 0x0F: /* NC */ if ( ! (cpustate->PS1 & FLAG_C) ) res = 1; break; \ |
| 489 | 489 | } |
| 490 | 490 | |
| 491 | #define PUSH8(X) cpustate->SP--; \ | |
| 492 | if ( ( cpustate->SYS & 0x40 ) == 0 ) cpustate->SP &= 0xFF; \ | |
| 491 | #define PUSH8(X) cpustate->SP = cpustate->SP - 1; \ | |
| 492 | if ( ( cpustate->SYS & 0x40 ) == 0 ) { \ | |
| 493 | cpustate->SP = cpustate->SP & 0xFF; \ | |
| 494 | } \ | |
| 493 | 495 | sm85cpu_mem_writebyte( cpustate, cpustate->SP, X ); |
| 494 | 496 | |
| 495 | 497 | #define POP8(X) X = sm85cpu_mem_readbyte( cpustate, cpustate->SP ); \ |
| 496 | cpustate->SP++; \ | |
| 497 | if ( ( cpustate->SYS & 0x40 ) == 0 ) cpustate->SP &= 0xFF; | |
| 498 | cpustate->SP = cpustate->SP + 1; \ | |
| 499 | if ( ( cpustate->SYS & 0x40 ) == 0 ) { \ | |
| 500 | cpustate->SP = cpustate->SP & 0xFF; \ | |
| 501 | } | |
| 498 | 502 | |
| 499 | 503 | case 0x00: /* CLR R - 4 cycles - Flags affected: -------- */ |
| 500 | 504 | ARG_R; |
| r8806 | r8807 | |
| 906 | 910 | break; |
| 907 | 911 | case 0x2E: /* MOV PS0,#00 - 4 cycles - Flags affected: -------- */ |
| 908 | 912 | ARG_R; |
| 909 | cpustate->PS0 = r1; | |
| 913 | cpustate->PS0 = r1; cpustate->register_base = cpustate->internal_ram + ( r1 & 0xF8 ); | |
| 910 | 914 | mycycles += 4; |
| 911 | 915 | break; |
| 912 | 916 | case 0x2F: /* BTST R,i - 6 cycles - Flags affected: -Z-0---- */ |
| r8806 | r8807 | |
| 1276 | 1280 | break; |
| 1277 | 1281 | case 0x5B: /* unk5B - 6,7,11,8,7 cycles */ |
| 1278 | 1282 | logerror( "%04X: unk%02x\n", cpustate->PC-1,op ); |
| 1279 | /* NOTE: This unknown command is used in several carts, the code below allows those carts to boot */ | |
| 1280 | ARG_iR; | |
| 1281 | r1 = r2 & 7; | |
| 1282 | res = sm85cpu_mem_readbyte( cpustate, r1 ) + 1; | |
| 1283 | sm85cpu_mem_writebyte( cpustate, r1, res ); | |
| 1283 | ARG_ad16; | |
| 1284 | 1284 | mycycles += 6; |
| 1285 | 1285 | break; |
| 1286 | 1286 | case 0x5C: /* DIV RRr,RRs - 47 cycles - Flags affected: -Z-V---- */ |
| r8806 | r8807 | |
|---|---|---|
| 7 | 7 | this cpu, and made educated guesses on the number of cycles for each instruction. |
| 8 | 8 | |
| 9 | 9 | Code by Wilbert Pol |
| 10 | ||
| 11 | ||
| 12 | There is some internal ram for the main cpu registers. They are offset by an index value. | |
| 13 | The address is (PS0 & 0xF8) + register number. It is not known what happens when PS0 >= F8. | |
| 14 | The assumption is that F8 to 107 is used, but it might wrap around instead. | |
| 15 | The registers also mirror out to main RAM, appearing at 0000 to 000F regardless of where | |
| 16 | they are internally. | |
| 17 | ||
| 18 | 10 | */ |
| 19 | 11 | |
| 20 | 12 | #include "emu.h" |
| r8806 | r8807 | |
| 35 | 27 | { |
| 36 | 28 | SM8500_CONFIG config; |
| 37 | 29 | UINT16 PC; |
| 30 | UINT8 *register_base; | |
| 38 | 31 | UINT8 IE0; |
| 39 | 32 | UINT8 IE1; |
| 40 | 33 | UINT8 IR0; |
| 41 | 34 | UINT8 IR1; |
| 35 | UINT8 P0; | |
| 36 | UINT8 P1; | |
| 37 | UINT8 P2; | |
| 38 | UINT8 P3; | |
| 42 | 39 | UINT8 SYS; |
| 43 | 40 | UINT8 CKC; |
| 44 | 41 | UINT8 clock_changed; |
| 45 | 42 | UINT16 SP; |
| 46 | 43 | UINT8 PS0; |
| 47 | 44 | UINT8 PS1; |
| 45 | UINT8 P0C; | |
| 46 | UINT8 P1C; | |
| 47 | UINT8 P2C; | |
| 48 | UINT8 P3C; | |
| 48 | 49 | UINT8 IFLAGS; |
| 49 | 50 | UINT8 CheckInterrupts; |
| 50 | 51 | int halted; |
| 51 | 52 | int icount; |
| 52 | 53 | device_irq_callback irq_callback; |
| 53 | 54 | legacy_cpu_device *device; |
| 54 | const address_space *program; | |
| 55 | UINT16 oldpc; | |
| 56 | UINT8 register_ram[0x108]; | |
| 55 | address_space *program; | |
| 56 | UINT8 internal_ram[0x500]; | |
| 57 | 57 | }; |
| 58 | 58 | |
| 59 | 59 | INLINE sm8500_state *get_safe_token(running_device *device) |
| r8806 | r8807 | |
| 67 | 67 | 0, 8, 2, 10, 4, 12, 6, 14 |
| 68 | 68 | }; |
| 69 | 69 | |
| 70 | INLINE void sm8500_get_sp( sm8500_state *cpustate ) | |
| 71 | { | |
| 72 | UINT16 data = memory_read_byte( cpustate->program, 0x1c) << 8; | |
| 73 | cpustate->SP = memory_read_byte( cpustate->program, 0x1d); | |
| 74 | if (cpustate->SYS&0x40) cpustate->SP |= data; | |
| 70 | static UINT8 sm85cpu_mem_readbyte( sm8500_state *cpustate, UINT32 offset ) { | |
| 71 | return ( offset < 0x10 ) ? cpustate->register_base[offset] : cpustate->program->read_byte( offset ); | |
| 75 | 72 | } |
| 76 | 73 | |
| 77 | static UINT8 sm85cpu_mem_readbyte( sm8500_state *cpustate, UINT32 offset ) | |
| 78 | { | |
| 79 | offset &= 0xffff; | |
| 80 | return (offset < 0x10) ? cpustate->register_ram[offset + (cpustate->PS0 & 0xF8)] | |
| 81 | : memory_read_byte( cpustate->program, offset ); | |
| 82 | } | |
| 83 | ||
| 84 | static void sm85cpu_mem_writebyte( sm8500_state *cpustate, UINT32 offset, UINT8 data ) | |
| 85 | { | |
| 86 | UINT8 i; | |
| 87 | offset &= 0xffff; | |
| 88 | if (offset < 0x10) | |
| 89 | cpustate->register_ram[offset + (cpustate->PS0 & 0xF8)] = data; | |
| 90 | ||
| 91 | memory_write_byte( cpustate->program, offset, data ); | |
| 92 | ||
| 93 | switch (offset) | |
| 94 | { | |
| 95 | case 0x10: cpustate->IE0 = data; break; | |
| 96 | case 0x11: cpustate->IE1 = data; break; | |
| 97 | case 0x12: cpustate->IR0 = data; break; | |
| 98 | case 0x13: cpustate->IR1 = data; break; | |
| 99 | case 0x19: cpustate->SYS = data; break; | |
| 100 | case 0x1a: cpustate->CKC = data; break; | |
| 101 | case 0x1c: | |
| 102 | case 0x1d: sm8500_get_sp(cpustate); break; | |
| 103 | case 0x1e: cpustate->PS0 = data; | |
| 104 | for (i = 0; i < 16; i++) // refresh register contents in debugger | |
| 105 | memory_write_byte(cpustate->program, i, sm85cpu_mem_readbyte(cpustate, i)); break; | |
| 106 | case 0x1f: cpustate->PS1 = data; break; | |
| 74 | static void sm85cpu_mem_writebyte( sm8500_state *cpustate, UINT32 offset, UINT8 data ) { | |
| 75 | if ( offset < 0x10 ) { | |
| 76 | cpustate->register_base[offset] = data; | |
| 77 | } else { | |
| 78 | cpustate->program->write_byte( offset, data ); | |
| 107 | 79 | } |
| 108 | 80 | } |
| 109 | 81 | |
| 110 | ||
| 111 | 82 | INLINE UINT16 sm85cpu_mem_readword( sm8500_state *cpustate, UINT32 address ) |
| 112 | 83 | { |
| 113 | return (sm85cpu_mem_readbyte( cpustate, address ) << 8) | (sm85cpu_mem_readbyte( cpustate, address+1 )); | |
| 84 | UINT16 value = (UINT16) sm85cpu_mem_readbyte( cpustate, address ) << 8; | |
| 85 | value |= sm85cpu_mem_readbyte( cpustate, ( address + 1 ) & 0xffff ); | |
| 86 | return value; | |
| 114 | 87 | } |
| 115 | 88 | |
| 116 | 89 | INLINE void sm85cpu_mem_writeword( sm8500_state *cpustate, UINT32 address, UINT16 value ) |
| 117 | 90 | { |
| 118 | 91 | sm85cpu_mem_writebyte( cpustate, address, value >> 8 ); |
| 119 | sm85cpu_mem_writebyte( cpustate, | |
| 92 | sm85cpu_mem_writebyte( cpustate, ( address + 1 ) & 0xffff, value & 0xff ); | |
| 120 | 93 | } |
| 121 | 94 | |
| 122 | 95 | static CPU_INIT( sm8500 ) |
| r8806 | r8807 | |
| 133 | 106 | cpustate->config.handle_dma = NULL; |
| 134 | 107 | cpustate->config.handle_timers = NULL; |
| 135 | 108 | } |
| 109 | cpustate->register_base = cpustate->internal_ram; | |
| 136 | 110 | } |
| 137 | 111 | |
| 138 | 112 | static CPU_RESET( sm8500 ) |
| r8806 | r8807 | |
| 140 | 114 | sm8500_state *cpustate = get_safe_token(device); |
| 141 | 115 | |
| 142 | 116 | cpustate->PC = 0x1020; |
| 143 | cpustate->clock_changed = 0; | |
| 117 | cpustate->IE0 = 0; | |
| 118 | cpustate->IE1 = 0; | |
| 119 | cpustate->IR0 = 0; | |
| 120 | cpustate->IR1 = 0; | |
| 121 | cpustate->P0 = 0xFF; | |
| 122 | cpustate->P1 = 0xFF; | |
| 123 | cpustate->P2 = 0xFF; | |
| 124 | cpustate->P3 = 0; | |
| 125 | cpustate->SYS = 0; | |
| 126 | cpustate->CKC = 0; cpustate->clock_changed = 0; | |
| 127 | cpustate->PS1 = 0; | |
| 128 | cpustate->register_base = cpustate->internal_ram; | |
| 144 | 129 | cpustate->halted = 0; |
| 145 | sm85cpu_mem_writeword(cpustate, 0x10, 0); // IE0, IE1 | |
| 146 | sm85cpu_mem_writeword(cpustate, 0x12, 0); // IR0, IR1 | |
| 147 | sm85cpu_mem_writeword(cpustate, 0x14, 0xffff); // P0, P1 | |
| 148 | sm85cpu_mem_writeword(cpustate, 0x16, 0xff00); // P2, P3 | |
| 149 | sm85cpu_mem_writebyte(cpustate, 0x19, 0); // SYS | |
| 150 | sm85cpu_mem_writebyte(cpustate, 0x1a, 0); // CKC | |
| 151 | sm85cpu_mem_writebyte(cpustate, 0x1f, 0); // PS1 | |
| 152 | sm85cpu_mem_writebyte(cpustate, 0x2b, 0xff); // URTT | |
| 153 | sm85cpu_mem_writebyte(cpustate, 0x2d, 0x42); // URTS | |
| 154 | sm85cpu_mem_writebyte(cpustate, 0x5f, 0x38); // WDTC | |
| 155 | 130 | } |
| 156 | 131 | |
| 157 | 132 | static CPU_EXIT( sm8500 ) |
| 158 | 133 | { |
| 159 | 134 | } |
| 160 | 135 | |
| 161 | #define PUSH_BYTE(X) cpustate->SP--; \ | |
| 162 | if ( ( cpustate->SYS & 0x40 ) == 0 ) cpustate->SP &= 0xFF; \ | |
| 136 | #define PUSH_BYTE(X) cpustate->SP = cpustate->SP - 1; \ | |
| 137 | if ( ( cpustate->SYS & 0x40 ) == 0 ) { \ | |
| 138 | cpustate->SP = cpustate->SP & 0xFF; \ | |
| 139 | } \ | |
| 163 | 140 | sm85cpu_mem_writebyte( cpustate, cpustate->SP, X ); |
| 164 | 141 | |
| 165 | 142 | INLINE void sm8500_do_interrupt(sm8500_state *cpustate, UINT16 vector) { |
| 166 | /* Get regs from ram */ | |
| 167 | sm8500_get_sp(cpustate); | |
| 168 | cpustate->SYS = memory_read_byte(cpustate->program, 0x19); | |
| 169 | cpustate->PS1 = memory_read_byte(cpustate->program, 0x1f); | |
| 170 | 143 | /* Push PC */ |
| 171 | 144 | PUSH_BYTE( cpustate->PC & 0xFF ); |
| 172 | 145 | PUSH_BYTE( cpustate->PC >> 8 ); |
| r8806 | r8807 | |
| 174 | 147 | PUSH_BYTE( cpustate->PS1 ); |
| 175 | 148 | /* Clear I flag */ |
| 176 | 149 | cpustate->PS1 &= ~ 0x01; |
| 177 | /* save regs to ram */ | |
| 178 | memory_write_byte(cpustate->program, 0x1f, cpustate->PS1); | |
| 179 | memory_write_byte(cpustate->program, 0x1d, cpustate->SP&0xFF); | |
| 180 | if (cpustate->SYS&0x40) memory_write_byte(cpustate->program, 0x1c, cpustate->SP>>8); | |
| 181 | 150 | /* Change PC to address stored at "vector" */ |
| 182 | 151 | cpustate->PC = sm85cpu_mem_readword( cpustate, vector ); |
| 183 | 152 | } |
| r8806 | r8807 | |
| 188 | 157 | while( irqline < 11 ) { |
| 189 | 158 | if ( cpustate->IFLAGS & ( 1 << irqline ) ) { |
| 190 | 159 | cpustate->halted = 0; |
| 191 | cpustate->IE0 = memory_read_byte(cpustate->program, 0x10); | |
| 192 | cpustate->IE1 = memory_read_byte(cpustate->program, 0x11); | |
| 193 | cpustate->IR0 = memory_read_byte(cpustate->program, 0x12); | |
| 194 | cpustate->IR1 = memory_read_byte(cpustate->program, 0x13); | |
| 195 | cpustate->PS0 = memory_read_byte(cpustate->program, 0x1e); | |
| 196 | cpustate->PS1 = memory_read_byte(cpustate->program, 0x1f); | |
| 197 | 160 | switch( irqline ) { |
| 198 | case | |
| 161 | case ILL_INT: | |
| 199 | 162 | sm8500_do_interrupt( cpustate, 0x101C ); |
| 200 | 163 | break; |
| 201 | case ILL_INT: | |
| 164 | case WDT_INT: | |
| 165 | sm8500_do_interrupt( cpustate, 0x101E ); | |
| 166 | break; | |
| 202 | 167 | case NMI_INT: |
| 203 | 168 | sm8500_do_interrupt( cpustate, 0x101E ); |
| 204 | 169 | break; |
| r8806 | r8807 | |
| 252 | 217 | break; |
| 253 | 218 | } |
| 254 | 219 | cpustate->IFLAGS &= ~ ( 1 << irqline ); |
| 255 | memory_write_byte(cpustate->program, 0x12, cpustate->IR0); | |
| 256 | memory_write_byte(cpustate->program, 0x13, cpustate->IR1); | |
| 257 | 220 | } |
| 258 | 221 | irqline++; |
| 259 | 222 | } |
| r8806 | r8807 | |
| 264 | 227 | { |
| 265 | 228 | sm8500_state *cpustate = get_safe_token(device); |
| 266 | 229 | UINT8 op; |
| 230 | UINT16 oldpc; | |
| 267 | 231 | int mycycles; |
| 268 | 232 | |
| 269 | 233 | do |
| r8806 | r8807 | |
| 274 | 238 | UINT32 res; |
| 275 | 239 | |
| 276 | 240 | debugger_instruction_hook(device, cpustate->PC); |
| 277 | | |
| 241 | | |
| 278 | 242 | mycycles = 0; |
| 279 | 243 | sm8500_process_interrupts(cpustate); |
| 280 | 244 | if ( !cpustate->halted ) { |
| 281 | 245 | op = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); |
| 282 | cpustate->SYS = memory_read_byte(cpustate->program, 0x19); | |
| 283 | cpustate->PS0 = memory_read_byte(cpustate->program, 0x1e); | |
| 284 | cpustate->PS1 = memory_read_byte(cpustate->program, 0x1f); | |
| 285 | sm8500_get_sp(cpustate); | |
| 286 | 246 | switch( op ) |
| 287 | 247 | { |
| 288 | 248 | #include "sm85ops.h" |
| 289 | 249 | } |
| 290 | if (cpustate->SYS&0x40) memory_write_byte(cpustate->program,0x1c,cpustate->SP>>8); | |
| 291 | memory_write_byte(cpustate->program,0x1d,cpustate->SP&0xFF); | |
| 292 | sm85cpu_mem_writebyte(cpustate,0x1e,cpustate->PS0); // need to update debugger | |
| 293 | memory_write_byte(cpustate->program,0x1f,cpustate->PS1); | |
| 294 | 250 | } else { |
| 295 | 251 | mycycles = 4; |
| 296 | 252 | if ( cpustate->config.handle_dma ) { |
| r8806 | r8807 | |
| 322 | 278 | case STATE_GENPC: |
| 323 | 279 | case SM8500_PC: return cpustate->PC; |
| 324 | 280 | case STATE_GENSP: |
| 325 | case SM8500_SP: return cpustate->SP; | |
| 326 | case SM8500_PS: return sm85cpu_mem_readword( cpustate, 0x1e ); | |
| 281 | case SM8500_SP: return ( cpustate->SYS & 0x40 ) ? cpustate->SP : cpustate->SP & 0xFF ; | |
| 282 | case SM8500_PS: return ( cpustate->PS0 << 8 ) | cpustate->PS1; | |
| 327 | 283 | case SM8500_SYS16: return cpustate->SYS; |
| 328 | 284 | case SM8500_RR0: return sm85cpu_mem_readword( cpustate, 0x00 ); |
| 329 | 285 | case SM8500_RR2: return sm85cpu_mem_readword( cpustate, 0x02 ); |
| r8806 | r8807 | |
| 333 | 289 | case SM8500_RR10: return sm85cpu_mem_readword( cpustate, 0x0A ); |
| 334 | 290 | case SM8500_RR12: return sm85cpu_mem_readword( cpustate, 0x0C ); |
| 335 | 291 | case SM8500_RR14: return sm85cpu_mem_readword( cpustate, 0x0E ); |
| 336 | case SM8500_IE0: return sm85cpu_mem_readbyte( cpustate, 0x10 ); | |
| 337 | case SM8500_IE1: return sm85cpu_mem_readbyte( cpustate, 0x11 ); | |
| 338 | case SM8500_IR0: return sm85cpu_mem_readbyte( cpustate, 0x12 ); | |
| 339 | case SM8500_IR1: return sm85cpu_mem_readbyte( cpustate, 0x13 ); | |
| 340 | case SM8500_P0: return sm85cpu_mem_readbyte( cpustate, 0x14 ); | |
| 341 | case SM8500_P1: return sm85cpu_mem_readbyte( cpustate, 0x15 ); | |
| 342 | case SM8500_P2: return sm85cpu_mem_readbyte( cpustate, 0x16 ); | |
| 343 | case SM8500_P3: return sm85cpu_mem_readbyte( cpustate, 0x17 ); | |
| 344 | case SM8500_SYS: return sm85cpu_mem_readbyte( cpustate, 0x19 ); | |
| 345 | case SM8500_CKC: return sm85cpu_mem_readbyte( cpustate, 0x1a ); | |
| 346 | case SM8500_SPH: return sm85cpu_mem_readbyte( cpustate, 0x1c ); | |
| 347 | case SM8500_SPL: return sm85cpu_mem_readbyte( cpustate, 0x1d ); | |
| 348 | case SM8500_PS0: return sm85cpu_mem_readbyte( cpustate, 0x1e ); | |
| 349 | case SM8500_PS1: return sm85cpu_mem_readbyte( cpustate, 0x1f ); | |
| 350 | case SM8500_P0C: return sm85cpu_mem_readbyte( cpustate, 0x20 ); | |
| 351 | case SM8500_P1C: return sm85cpu_mem_readbyte( cpustate, 0x21 ); | |
| 352 | case SM8500_P2C: return sm85cpu_mem_readbyte( cpustate, 0x22 ); | |
| 353 | case SM8500_P3C: return sm85cpu_mem_readbyte( cpustate, 0x23 ); | |
| 292 | case SM8500_IE0: return cpustate->IE0; | |
| 293 | case SM8500_IE1: return cpustate->IE1; | |
| 294 | case SM8500_IR0: return cpustate->IR0; | |
| 295 | case SM8500_IR1: return cpustate->IR1; | |
| 296 | case SM8500_P0: return cpustate->P0; | |
| 297 | case SM8500_P1: return cpustate->P1; | |
| 298 | case SM8500_P2: return cpustate->P2; | |
| 299 | case SM8500_P3: return cpustate->P3; | |
| 300 | case SM8500_SYS: return cpustate->SYS; | |
| 301 | case SM8500_CKC: return cpustate->CKC; | |
| 302 | case SM8500_SPH: return (cpustate->SP >> 8); | |
| 303 | case SM8500_SPL: return cpustate->SP & 0xFF; | |
| 304 | case SM8500_PS0: return cpustate->PS0; | |
| 305 | case SM8500_PS1: return cpustate->PS1; | |
| 306 | case SM8500_P0C: return cpustate->P0C; | |
| 307 | case SM8500_P1C: return cpustate->P1C; | |
| 308 | case SM8500_P2C: return cpustate->P2C; | |
| 309 | case SM8500_P3C: return cpustate->P3C; | |
| 354 | 310 | } |
| 355 | 311 | return 0; |
| 356 | 312 | } |
| r8806 | r8807 | |
| 362 | 318 | case STATE_GENPC: |
| 363 | 319 | case SM8500_PC: cpustate->PC = val; break; |
| 364 | 320 | case STATE_GENSP: |
| 365 | case SM8500_SP: cpustate->SP = val; memory_write_byte( cpustate->program, 0x1d, val&0xff); if (cpustate->SYS&0x40) memory_write_byte( cpustate->program, 0x1c, val>>8); break; | |
| 366 | case SM8500_PS: sm85cpu_mem_writeword( cpustate, 0x1e, val); break; | |
| 367 | case SM8500_SYS16: val&=0xff; sm85cpu_mem_writebyte( cpustate, 0x19, val); break; | |
| 321 | case SM8500_SP: cpustate->SP = val; break; | |
| 322 | case SM8500_PS: sm8500_set_reg( cpustate, SM8500_PS0, ( val >> 8 ) & 0xFF ); sm8500_set_reg( cpustate, SM8500_PS1, val & 0xFF ); break; | |
| 323 | case SM8500_SYS16: cpustate->SYS = val; break; | |
| 368 | 324 | case SM8500_RR0: sm85cpu_mem_writeword( cpustate, 0x00, val); break; |
| 369 | 325 | case SM8500_RR2: sm85cpu_mem_writeword( cpustate, 0x02, val); break; |
| 370 | 326 | case SM8500_RR4: sm85cpu_mem_writeword( cpustate, 0x04, val); break; |
| r8806 | r8807 | |
| 373 | 329 | case SM8500_RR10: sm85cpu_mem_writeword( cpustate, 0x0A, val); break; |
| 374 | 330 | case SM8500_RR12: sm85cpu_mem_writeword( cpustate, 0x0C, val); break; |
| 375 | 331 | case SM8500_RR14: sm85cpu_mem_writeword( cpustate, 0x0E, val); break; |
| 376 | case SM8500_IE0: sm85cpu_mem_writebyte( cpustate, 0x10, val); break; | |
| 377 | case SM8500_IE1: sm85cpu_mem_writebyte( cpustate, 0x11, val); break; | |
| 378 | case SM8500_IR0: sm85cpu_mem_writebyte( cpustate, 0x12, val); break; | |
| 379 | case SM8500_IR1: sm85cpu_mem_writebyte( cpustate, 0x13, val); break; | |
| 380 | case SM8500_P0: sm85cpu_mem_writebyte( cpustate, 0x14, val); break; | |
| 381 | case SM8500_P1: sm85cpu_mem_writebyte( cpustate, 0x15, val); break; | |
| 382 | case SM8500_P2: sm85cpu_mem_writebyte( cpustate, 0x16, val); break; | |
| 383 | case SM8500_P3: sm85cpu_mem_writebyte( cpustate, 0x17, val); break; | |
| 384 | case SM8500_SYS: sm85cpu_mem_writebyte( cpustate, 0x19, val); break; | |
| 385 | case SM8500_CKC: sm85cpu_mem_writebyte( cpustate, 0x1a, val); if ( val & 0x80 ) { cpustate->clock_changed = 1; }; break; | |
| 386 | case SM8500_SPH: sm85cpu_mem_writebyte( cpustate, 0x1c, val); break; | |
| 387 | case SM8500_SPL: sm85cpu_mem_writebyte( cpustate, 0x1d, val); break; | |
| 388 | case SM8500_PS0: sm85cpu_mem_writebyte( cpustate, 0x1e, val); break; | |
| 389 | case SM8500_PS1: sm85cpu_mem_writebyte( cpustate, 0x1f, val); break; | |
| 390 | case SM8500_P0C: sm85cpu_mem_writebyte( cpustate, 0x20, val); break; | |
| 391 | case SM8500_P1C: sm85cpu_mem_writebyte( cpustate, 0x21, val); break; | |
| 392 | case SM8500_P2C: sm85cpu_mem_writebyte( cpustate, 0x22, val); break; | |
| 393 | case SM8500_P3C: sm85cpu_mem_writebyte( cpustate, 0x23, val); break; | |
| 332 | case SM8500_IE0: cpustate->IE0 = val; break; | |
| 333 | case SM8500_IE1: cpustate->IE1 = val; break; | |
| 334 | case SM8500_IR0: cpustate->IR0 = val; break; | |
| 335 | case SM8500_IR1: cpustate->IR1 = val; break; | |
| 336 | case SM8500_P0: cpustate->P0 = val; break; | |
| 337 | case SM8500_P1: cpustate->P1 = val; break; | |
| 338 | case SM8500_P2: cpustate->P2 = val; break; | |
| 339 | case SM8500_P3: cpustate->P3 = val; break; | |
| 340 | case SM8500_SYS: cpustate->SYS = val; break; | |
| 341 | case SM8500_CKC: cpustate->CKC = val; if ( val & 0x80 ) { cpustate->clock_changed = 1; }; break; | |
| 342 | case SM8500_SPH: cpustate->SP = ( ( val & 0xFF ) << 8 ) | ( cpustate->SP & 0xFF ); break; | |
| 343 | case SM8500_SPL: cpustate->SP = ( cpustate->SP & 0xFF00 ) | ( val & 0xFF ); break; | |
| 344 | case SM8500_PS0: cpustate->PS0 = val; cpustate->register_base = cpustate->internal_ram + ( val & 0xF8 ); break; | |
| 345 | case SM8500_PS1: cpustate->PS1 = val; break; | |
| 346 | case SM8500_P0C: cpustate->P0C = val; break; | |
| 347 | case SM8500_P1C: cpustate->P1C = val; break; | |
| 348 | case SM8500_P2C: cpustate->P2C = val; break; | |
| 349 | case SM8500_P3C: cpustate->P3C = val; break; | |
| 394 | 350 | } |
| 395 | 351 | } |
| 396 | 352 | |
| 397 | 353 | static void sm8500_set_irq_line( sm8500_state *cpustate, int irqline, int state ) |
| 398 | 354 | { |
| 399 | cpustate->IR0 = memory_read_byte(cpustate->program, 0x12); | |
| 400 | cpustate->IR1 = memory_read_byte(cpustate->program, 0x13); | |
| 401 | 355 | if ( state == ASSERT_LINE ) { |
| 402 | 356 | cpustate->IFLAGS |= ( 0x01 << irqline ); |
| 403 | 357 | cpustate->CheckInterrupts = 1; |
| r8806 | r8807 | |
| 427 | 381 | cpustate->CheckInterrupts = 0; |
| 428 | 382 | } |
| 429 | 383 | } |
| 430 | memory_write_byte(cpustate->program, 0x12, cpustate->IR0); | |
| 431 | memory_write_byte(cpustate->program, 0x13, cpustate->IR1); | |
| 432 | 384 | } |
| 433 | 385 | |
| 386 | UINT8 *sm8500_get_internal_ram(legacy_cpu_device *device) | |
| 387 | { | |
| 388 | sm8500_state *cpustate = get_safe_token(device); | |
| 389 | return cpustate->internal_ram; | |
| 390 | } | |
| 391 | ||
| 434 | 392 | static CPU_SET_INFO( sm8500 ) |
| 435 | 393 | { |
| 436 | 394 | sm8500_state *cpustate = get_safe_token(device); |
| r8806 | r8807 | |
| 480 | 438 | case CPUINFO_INT_REGISTER + SM8500_P1C: |
| 481 | 439 | case CPUINFO_INT_REGISTER + SM8500_P2C: |
| 482 | 440 | case CPUINFO_INT_REGISTER + SM8500_P3C: |
| 483 | sm8500_set_reg( cpustate, state - CPUINFO_INT_REGISTER, info->i ); break; | |
| 441 | sm8500_set_reg( cpustate, state - CPUINFO_INT_REGISTER, info->i ); break; | |
| 484 | 442 | |
| 485 | 443 | } |
| 486 | 444 | } |
| r8806 | r8807 | |
| 551 | 509 | info->i = sm8500_get_reg( cpustate, state - CPUINFO_INT_REGISTER ); break; |
| 552 | 510 | case CPUINFO_INT_REGISTER + STATE_GENPC: info->i = sm8500_get_reg( cpustate, SM8500_PC ); break; |
| 553 | 511 | case CPUINFO_INT_REGISTER + STATE_GENSP: info->i = sm8500_get_reg( cpustate, SM8500_SP ); break; |
| 554 | case CPUINFO_INT_PREVIOUSPC: info->i = | |
| 512 | case CPUINFO_INT_PREVIOUSPC: info->i = 0x0000 | |
| 555 | 513 | |
| 556 | 514 | |
| 557 | 515 | case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(sm8500); break; |
| r8806 | r8807 | |
| 590 | 548 | case CPUINFO_STR_REGISTER + SM8500_PC: sprintf(info->s, "PC:%04X", cpustate->PC); break; |
| 591 | 549 | case CPUINFO_STR_REGISTER + SM8500_SP: sprintf(info->s, "SP:%04X", cpustate->SP); break; |
| 592 | 550 | case CPUINFO_STR_REGISTER + SM8500_PS: sprintf(info->s, "PS:%04X", ( cpustate->PS0 << 8 ) | cpustate->PS1 ); break; |
| 593 | case CPUINFO_STR_REGISTER + SM8500_SYS16: sprintf(info->s, "SYS:%0 | |
| 551 | case CPUINFO_STR_REGISTER + SM8500_SYS16: sprintf(info->s, "SYS:%04X", cpustate->SYS ); break; | |
| 594 | 552 | } |
| 595 | 553 | } |
| 596 | 554 |
| r8806 | r8807 | |
|---|---|---|
| 65 | 65 | int cycles; |
| 66 | 66 | |
| 67 | 67 | legacy_cpu_device *device; |
| 68 | const address_space *program; | |
| 69 | const address_space *io; | |
| 68 | address_space *program; | |
| 69 | address_space *io; | |
| 70 | 70 | }; |
| 71 | 71 | |
| 72 | 72 | static void mn10200_w(mn102_info *mn102, UINT32 adr, UINT32 data, int type); |
| r8806 | r8807 | |
| 79 | 79 | return mn10200_r(mn102, address-0xfc00, MEM_BYTE); |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | return m | |
| 82 | return m | |
| 83 | 83 | } |
| 84 | 84 | |
| 85 | 85 | INLINE UINT16 mn102_read_word(mn102_info *mn102, UINT32 address) |
| r8806 | r8807 | |
| 91 | 91 | |
| 92 | 92 | if (address & 1) |
| 93 | 93 | { |
| 94 | return m | |
| 94 | return m | |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | return m | |
| 97 | return m | |
| 98 | 98 | } |
| 99 | 99 | |
| 100 | 100 | INLINE void mn102_write_byte(mn102_info *mn102, UINT32 address, UINT8 data) |
| r8806 | r8807 | |
| 105 | 105 | return; |
| 106 | 106 | } |
| 107 | 107 | |
| 108 | m | |
| 108 | m | |
| 109 | 109 | } |
| 110 | 110 | |
| 111 | 111 | INLINE void mn102_write_word(mn102_info *mn102, UINT32 address, UINT16 data) |
| r8806 | r8807 | |
| 118 | 118 | |
| 119 | 119 | if (address & 1) |
| 120 | 120 | { |
| 121 | memory_write_byte_16le(mn102->program, address, data&0xff); | |
| 122 | memory_write_byte_16le(mn102->program, address+1, (data>>8)&0xff); | |
| 121 | mn102->program->write_byte(address, data&0xff); | |
| 122 | mn102->program->write_byte(address+1, (data>>8)&0xff); | |
| 123 | 123 | return; |
| 124 | 124 | } |
| 125 | 125 | |
| 126 | m | |
| 126 | m | |
| 127 | 127 | } |
| 128 | 128 | |
| 129 | 129 | INLINE INT32 r24u(mn102_info *mn102, offs_t adr) |
| r8806 | r8807 | |
| 2057 | 2057 | break; |
| 2058 | 2058 | |
| 2059 | 2059 | case 0x264: |
| 2060 | m | |
| 2060 | mn102->io-> | |
| 2061 | 2061 | break; |
| 2062 | 2062 | |
| 2063 | 2063 | case 0x280: case 0x290: case 0x2a0: case 0x2b0: case 0x2c0: case 0x2d0: case 0x2e0: case 0x2f0: { |
| r8806 | r8807 | |
| 2211 | 2211 | break; |
| 2212 | 2212 | |
| 2213 | 2213 | case 0x3c0: // port 0 data |
| 2214 | m | |
| 2214 | mn102->io-> | |
| 2215 | 2215 | break; |
| 2216 | 2216 | |
| 2217 | 2217 | case 0x3c2: // port 2 data |
| 2218 | m | |
| 2218 | mn102->io-> | |
| 2219 | 2219 | break; |
| 2220 | 2220 | |
| 2221 | 2221 | case 0x3c3: // port 3 data |
| 2222 | m | |
| 2222 | mn102->io-> | |
| 2223 | 2223 | break; |
| 2224 | 2224 | |
| 2225 | 2225 | case 0x3e0: // port0 ddr |
| r8806 | r8807 | |
| 2304 | 2304 | break; |
| 2305 | 2305 | |
| 2306 | 2306 | case 0x264: // port 1 data |
| 2307 | return m | |
| 2307 | return mn102->io->r | |
| 2308 | 2308 | |
| 2309 | 2309 | case 0x28c: case 0x29c: case 0x2ac: case 0x2bc: case 0x2cc: case 0x2dc: case 0x2ec: case 0x2fc: |
| 2310 | 2310 | { |
| r8806 | r8807 | |
| 2313 | 2313 | } |
| 2314 | 2314 | |
| 2315 | 2315 | case 0x3c0: // port 0 data |
| 2316 | return m | |
| 2316 | return mn102->io->r | |
| 2317 | 2317 | |
| 2318 | 2318 | case 0x3c2: // port 2 data |
| 2319 | return m | |
| 2319 | return mn102->io->r | |
| 2320 | 2320 | |
| 2321 | 2321 | case 0x3c3: // port 3 data |
| 2322 | return m | |
| 2322 | return mn102->io->r | |
| 2323 | 2323 | |
| 2324 | 2324 | default: |
| 2325 | 2325 | log_event("MN102", "internal_r %04x (%03x)", adr+0xfc00, adr); |
| r8806 | r8807 | |
|---|---|---|
| 75 | 75 | UINT8 pending_interrupt; |
| 76 | 76 | device_irq_callback irqcallback; |
| 77 | 77 | legacy_cpu_device *device; |
| 78 | const address_space *program; | |
| 79 | const address_space *data; | |
| 80 | const address_space *io; | |
| 78 | address_space *program; | |
| 79 | address_space *data; | |
| 80 | address_space *io; | |
| 81 | 81 | int icount; |
| 82 | 82 | }; |
| 83 | 83 | |
| r8806 | r8807 | |
| 100 | 100 | |
| 101 | 101 | #define READOP(a) (memory_decrypted_read_byte(cpustate->program, a)) |
| 102 | 102 | |
| 103 | #define RDMEM(a) (memory_read_byte_8be(cpustate->data, a)) | |
| 104 | #define WRMEM(a,v) (memory_write_byte_8be(cpustate->data, (a), (v))) | |
| 103 | #define RDMEM(a) (cpustate->data->read_byte(a)) | |
| 104 | #define WRMEM(a,v) (cpustate->data->write_byte((a), (v))) | |
| 105 | 105 | |
| 106 | #define READPORT(a) (memory_read_byte_8be(cpustate->io, a)) | |
| 107 | #define WRITEPORT(a,v) (memory_write_byte_8be(cpustate->io, (a), (v))) | |
| 106 | #define READPORT(a) (cpustate->io->read_byte(a)) | |
| 107 | #define WRITEPORT(a,v) (cpustate->io->write_byte((a), (v))) | |
| 108 | 108 | |
| 109 | 109 | #define TEST_ST() (cpustate->st & 1) |
| 110 | 110 | #define TEST_ZF() (cpustate->zf & 1) |
| r8806 | r8807 | |
|---|---|---|
| 126 | 126 | return sh4_internal_r(sh4->internal, ((A & 0x0fc) >> 2) | ((A & 0x1fe0000) >> 11), 0xff << ((A & 3)*8)) >> ((A & 3)*8); |
| 127 | 127 | |
| 128 | 128 | if (A >= 0xe0000000) |
| 129 | return | |
| 129 | return | |
| 130 | 130 | |
| 131 | return | |
| 131 | return | |
| 132 | 132 | } |
| 133 | 133 | |
| 134 | 134 | INLINE UINT16 RW(sh4_state *sh4, offs_t A) |
| r8806 | r8807 | |
| 137 | 137 | return sh4_internal_r(sh4->internal, ((A & 0x0fc) >> 2) | ((A & 0x1fe0000) >> 11), 0xffff << ((A & 2)*8)) >> ((A & 2)*8); |
| 138 | 138 | |
| 139 | 139 | if (A >= 0xe0000000) |
| 140 | return | |
| 140 | return | |
| 141 | 141 | |
| 142 | return | |
| 142 | return | |
| 143 | 143 | } |
| 144 | 144 | |
| 145 | 145 | INLINE UINT32 RL(sh4_state *sh4, offs_t A) |
| r8806 | r8807 | |
| 148 | 148 | return sh4_internal_r(sh4->internal, ((A & 0x0fc) >> 2) | ((A & 0x1fe0000) >> 11), 0xffffffff); |
| 149 | 149 | |
| 150 | 150 | if (A >= 0xe0000000) |
| 151 | return | |
| 151 | return sh4->program->read_dword | |
| 152 | 152 | |
| 153 | return | |
| 153 | return sh4->program->read_dword | |
| 154 | 154 | } |
| 155 | 155 | |
| 156 | 156 | INLINE void WB(sh4_state *sh4, offs_t A, UINT8 V) |
| r8806 | r8807 | |
| 164 | 164 | |
| 165 | 165 | if (A >= 0xe0000000) |
| 166 | 166 | { |
| 167 | | |
| 167 | sh4->program->write_byte | |
| 168 | 168 | return; |
| 169 | 169 | } |
| 170 | 170 | |
| 171 | | |
| 171 | sh4->program->write_byte | |
| 172 | 172 | } |
| 173 | 173 | |
| 174 | 174 | INLINE void WW(sh4_state *sh4, offs_t A, UINT16 V) |
| r8806 | r8807 | |
| 181 | 181 | |
| 182 | 182 | if (A >= 0xe0000000) |
| 183 | 183 | { |
| 184 | | |
| 184 | sh4->program->write_word | |
| 185 | 185 | return; |
| 186 | 186 | } |
| 187 | 187 | |
| 188 | | |
| 188 | sh4->program->write_word | |
| 189 | 189 | } |
| 190 | 190 | |
| 191 | 191 | INLINE void WL(sh4_state *sh4, offs_t A, UINT32 V) |
| r8806 | r8807 | |
| 198 | 198 | |
| 199 | 199 | if (A >= 0xe0000000) |
| 200 | 200 | { |
| 201 | | |
| 201 | sh4->program->write_dword | |
| 202 | 202 | return; |
| 203 | 203 | } |
| 204 | 204 | |
| 205 | 205 | /* if (A >= 0x40000000) |
| 206 | 206 | return;*/ |
| 207 | 207 | |
| 208 | | |
| 208 | sh4->program->write_dword | |
| 209 | 209 | } |
| 210 | 210 | |
| 211 | 211 | /* code cycles t-bit |
| r8806 | r8807 | |
| 2129 | 2129 | for (a = 0;a < 4;a++) |
| 2130 | 2130 | { |
| 2131 | 2131 | // shouldn't be causing a memory read, should store sq writes in registers. |
| 2132 | | |
| 2132 | sh4->program->write_qword | |
| 2133 | 2133 | addr += 8; |
| 2134 | 2134 | dest += 8; |
| 2135 | 2135 | } |
| r8806 | r8807 | |
|---|---|---|
| 63 | 63 | INT8 irq_line_state[17]; |
| 64 | 64 | device_irq_callback irq_callback; |
| 65 | 65 | legacy_cpu_device *device; |
| 66 | const address_space *internal; | |
| 67 | const address_space *program; | |
| 68 | const address_space *io; | |
| 66 | address_space *internal; | |
| 67 | address_space *program; | |
| 68 | address_space *io; | |
| 69 | 69 | UINT32 *m; |
| 70 | 70 | INT8 nmi_line_state; |
| 71 | 71 |
| r8806 | r8807 | |
|---|---|---|
| 480 | 480 | src --; |
| 481 | 481 | if(incd == 2) |
| 482 | 482 | dst --; |
| 483 | | |
| 483 | sh4->program->write_byte | |
| 484 | 484 | if(incs == 1) |
| 485 | 485 | src ++; |
| 486 | 486 | if(incd == 1) |
| r8806 | r8807 | |
| 496 | 496 | src -= 2; |
| 497 | 497 | if(incd == 2) |
| 498 | 498 | dst -= 2; |
| 499 | | |
| 499 | sh4->program->write_word | |
| 500 | 500 | if(incs == 1) |
| 501 | 501 | src += 2; |
| 502 | 502 | if(incd == 1) |
| r8806 | r8807 | |
| 512 | 512 | src -= 8; |
| 513 | 513 | if(incd == 2) |
| 514 | 514 | dst -= 8; |
| 515 | | |
| 515 | sh4->program->write_qword | |
| 516 | 516 | if(incs == 1) |
| 517 | 517 | src += 8; |
| 518 | 518 | if(incd == 1) |
| r8806 | r8807 | |
| 529 | 529 | src -= 4; |
| 530 | 530 | if(incd == 2) |
| 531 | 531 | dst -= 4; |
| 532 | | |
| 532 | sh4->program->write_dword | |
| 533 | 533 | if(incs == 1) |
| 534 | 534 | src += 4; |
| 535 | 535 | if(incd == 1) |
| r8806 | r8807 | |
| 546 | 546 | src -= 32; |
| 547 | 547 | if(incd == 2) |
| 548 | 548 | dst -= 32; |
| 549 | memory_write_qword_64le(sh4->program, dst, memory_read_qword_64le(sh4->program, src)); | |
| 550 | memory_write_qword_64le(sh4->program, dst+8, memory_read_qword_64le(sh4->program, src+8)); | |
| 551 | memory_write_qword_64le(sh4->program, dst+16, memory_read_qword_64le(sh4->program, src+16)); | |
| 552 | memory_write_qword_64le(sh4->program, dst+24, memory_read_qword_64le(sh4->program, src+24)); | |
| 549 | sh4->program->write_qword(dst, sh4->program->read_qword(src)); | |
| 550 | sh4->program->write_qword(dst+8, sh4->program->read_qword(src+8)); | |
| 551 | sh4->program->write_qword(dst+16, sh4->program->read_qword(src+16)); | |
| 552 | sh4->program->write_qword(dst+24, sh4->program->read_qword(src+24)); | |
| 553 | 553 | if(incs == 1) |
| 554 | 554 | src += 32; |
| 555 | 555 | if(incd == 1) |
| r8806 | r8807 | |
| 910 | 910 | sh4->ioport16_direction &= 0xffff; |
| 911 | 911 | sh4->ioport16_pullup = (sh4->ioport16_pullup | sh4->ioport16_direction) ^ 0xffff; |
| 912 | 912 | if (sh4->m[BCR2] & 1) |
| 913 | | |
| 913 | sh4->io-> | |
| 914 | 914 | break; |
| 915 | 915 | case PDTRA: |
| 916 | 916 | if (sh4->m[BCR2] & 1) |
| 917 | | |
| 917 | sh4->io-> | |
| 918 | 918 | break; |
| 919 | 919 | case PCTRB: |
| 920 | 920 | sh4->ioport4_pullup = 0; |
| r8806 | r8807 | |
| 926 | 926 | sh4->ioport4_direction &= 0xf; |
| 927 | 927 | sh4->ioport4_pullup = (sh4->ioport4_pullup | sh4->ioport4_direction) ^ 0xf; |
| 928 | 928 | if (sh4->m[BCR2] & 1) |
| 929 | | |
| 929 | sh4->io-> | |
| 930 | 930 | break; |
| 931 | 931 | case PDTRB: |
| 932 | 932 | if (sh4->m[BCR2] & 1) |
| 933 | | |
| 933 | sh4->io-> | |
| 934 | 934 | break; |
| 935 | 935 | |
| 936 | 936 | case SCBRR2: |
| r8806 | r8807 | |
| 981 | 981 | // I/O ports |
| 982 | 982 | case PDTRA: |
| 983 | 983 | if (sh4->m[BCR2] & 1) |
| 984 | return ( | |
| 984 | return (sh4->io->r | |
| 985 | 985 | break; |
| 986 | 986 | case PDTRB: |
| 987 | 987 | if (sh4->m[BCR2] & 1) |
| 988 | return ( | |
| 988 | return (sh4->io->r | |
| 989 | 989 | break; |
| 990 | 990 | |
| 991 | 991 | // SCIF (UART with FIFO) |
| r8806 | r8807 | |
| 1278 | 1278 | len = s->length; |
| 1279 | 1279 | p32bits = (UINT32 *)(s->buffer); |
| 1280 | 1280 | for (pos = 0;pos < len;pos++) { |
| 1281 | *p32bits = | |
| 1281 | *p32bits = sh4->program->read_dword | |
| 1282 | 1282 | p32bits++; |
| 1283 | 1283 | s->source = s->source + 4; |
| 1284 | 1284 | } |
| r8806 | r8807 | |
| 1286 | 1286 | len = s->length; |
| 1287 | 1287 | p32bits = (UINT32 *)(s->buffer); |
| 1288 | 1288 | for (pos = 0;pos < len;pos++) { |
| 1289 | | |
| 1289 | sh4->program->write_dword | |
| 1290 | 1290 | p32bits++; |
| 1291 | 1291 | s->destination = s->destination + 4; |
| 1292 | 1292 | } |
| r8806 | r8807 | |
| 1297 | 1297 | len = s->length * 4; |
| 1298 | 1298 | p32bytes = (UINT64 *)(s->buffer); |
| 1299 | 1299 | for (pos = 0;pos < len;pos++) { |
| 1300 | *p32bytes = | |
| 1300 | *p32bytes = sh4->program->read_qword | |
| 1301 | 1301 | p32bytes++; |
| 1302 | 1302 | s->destination = s->destination + 8; |
| 1303 | 1303 | } |
| r8806 | r8807 | |
| 1305 | 1305 | len = s->length * 4; |
| 1306 | 1306 | p32bytes = (UINT64 *)(s->buffer); |
| 1307 | 1307 | for (pos = 0;pos < len;pos++) { |
| 1308 | | |
| 1308 | sh4->program->write_qword | |
| 1309 | 1309 | p32bytes++; |
| 1310 | 1310 | s->destination = s->destination + 8; |
| 1311 | 1311 | } |
| r8806 | r8807 | |
|---|---|---|
| 144 | 144 | |
| 145 | 145 | device_irq_callback irq_callback; |
| 146 | 146 | legacy_cpu_device *device; |
| 147 | const address_space *program; | |
| 148 | const address_space *data; | |
| 147 | address_space *program; | |
| 148 | address_space *data; | |
| 149 | 149 | int icount; |
| 150 | 150 | }; |
| 151 | 151 | |
| r8806 | r8807 | |
| 173 | 173 | |
| 174 | 174 | INLINE UINT16 PM_READ16(tms32051_state *cpustate, UINT16 address) |
| 175 | 175 | { |
| 176 | return | |
| 176 | return | |
| 177 | 177 | } |
| 178 | 178 | |
| 179 | 179 | INLINE void PM_WRITE16(tms32051_state *cpustate, UINT16 address, UINT16 data) |
| 180 | 180 | { |
| 181 | | |
| 181 | | |
| 182 | 182 | } |
| 183 | 183 | |
| 184 | 184 | INLINE UINT16 DM_READ16(tms32051_state *cpustate, UINT16 address) |
| 185 | 185 | { |
| 186 | return | |
| 186 | return | |
| 187 | 187 | } |
| 188 | 188 | |
| 189 | 189 | INLINE void DM_WRITE16(tms32051_state *cpustate, UINT16 address, UINT16 data) |
| 190 | 190 | { |
| 191 | | |
| 191 | | |
| 192 | 192 | } |
| 193 | 193 | |
| 194 | 194 | #include "32051ops.c" |
| r8806 | r8807 | |
|---|---|---|
| 165 | 165 | /* MAME is unnecessary */ |
| 166 | 166 | #define HANDLE_HALT_LINE 0 |
| 167 | 167 | |
| 168 | #define M_RDMEM(A) memory_read_byte_8le(cpustate->program, A) | |
| 169 | #define M_WRMEM(A,V) memory_write_byte_8le(cpustate->program, A, V) | |
| 168 | #define M_RDMEM(A) cpustate->program->read_byte(A) | |
| 169 | #define M_WRMEM(A,V) cpustate->program->write_byte(A, V) | |
| 170 | 170 | #define M_RDOP(A) memory_decrypted_read_byte(cpustate->program, A) |
| 171 | 171 | #define M_RDOP_ARG(A) memory_raw_read_byte(cpustate->program, A) |
| 172 | 172 | |
| r8806 | r8807 | |
| 198 | 198 | #endif |
| 199 | 199 | |
| 200 | 200 | legacy_cpu_device *device; |
| 201 | | |
| 201 | | |
| 202 | 202 | int icount; |
| 203 | 203 | int inst_cycles; |
| 204 | 204 | }; |
| r8806 | r8807 | |
|---|---|---|
| 328 | 328 | #include "apexc.h" |
| 329 | 329 | |
| 330 | 330 | #ifndef SUPPORT_ODD_WORD_SIZES |
| 331 | #define apexc_readmem(address) memory_read_dword_32be(cpustate->program, (address)<<2) | |
| 332 | #define apexc_writemem(address, data) memory_write_dword_32be(cpustate->program, (address)<<2, (data)) | |
| 331 | #define apexc_readmem(address) cpustate->program->read_dword((address)<<2) | |
| 332 | #define apexc_writemem(address, data) cpustate->program->write_dword((address)<<2, (data)) | |
| 333 | 333 | /* eewww ! - Fortunately, there is no memory mapped I/O, so we can simulate masked write |
| 334 | 334 | without danger */ |
| 335 | 335 | #define apexc_writemem_masked(address, data, mask) \ |
| r8806 | r8807 | |
| 359 | 359 | UINT32 pc; /* address of next instruction for the disassembler */ |
| 360 | 360 | |
| 361 | 361 | legacy_cpu_device *device; |
| 362 | const address_space *program; | |
| 363 | const address_space *io; | |
| 362 | address_space *program; | |
| 363 | address_space *io; | |
| 364 | 364 | int icount; |
| 365 | 365 | }; |
| 366 | 366 | |
| r8806 | r8807 | |
| 474 | 474 | |
| 475 | 475 | static int papertape_read(apexc_state *cpustate) |
| 476 | 476 | { |
| 477 | return | |
| 477 | return | |
| 478 | 478 | } |
| 479 | 479 | |
| 480 | 480 | static void papertape_punch(apexc_state *cpustate, int data) |
| 481 | 481 | { |
| 482 | | |
| 482 | cpustate->io-> | |
| 483 | 483 | } |
| 484 | 484 | |
| 485 | 485 | /* |
| r8806 | r8807 | |
|---|---|---|
| 11 | 11 | #undef G65816_CALL_DEBUGGER |
| 12 | 12 | #define G65816_CALL_DEBUGGER(x) debugger_instruction_hook(cpustate->device, x) |
| 13 | 13 | |
| 14 | #define g65816_read_8(addr) memory_read_byte_8be(cpustate->program, addr) | |
| 15 | #define g65816_write_8(addr,data) memory_write_byte_8be(cpustate->program, addr,data) | |
| 16 | #define g65816_read_8_immediate(A) memory_read_byte_8be(cpustate->program, A) | |
| 14 | #define g65816_read_8(addr) cpustate->program->read_byte(addr) | |
| 15 | #define g65816_write_8(addr,data) cpustate->program->write_byte(addr,data) | |
| 16 | #define g65816_read_8_immediate(A) cpustate->program->read_byte(A) | |
| 17 | 17 | #define g65816_jumping(A) |
| 18 | 18 | #define g65816_branching(A) |
| 19 | 19 | |
| r8806 | r8807 | |
| 95 | 95 | uint irq_delay; /* delay 1 instruction before checking irq */ |
| 96 | 96 | device_irq_callback int_ack; /* Interrupt Acknowledge */ |
| 97 | 97 | legacy_cpu_device *device; |
| 98 | | |
| 98 | | |
| 99 | 99 | read8_space_func read_vector; /* Read vector override */ |
| 100 | 100 | uint stopped; /* Sets how the CPU is stopped */ |
| 101 | 101 | void (*const *opcodes)(g65816i_cpu_struct *cpustate); |
| r8806 | r8807 | |
|---|---|---|
| 135 | 135 | { |
| 136 | 136 | offs_t fetch_xor; |
| 137 | 137 | |
| 138 | UINT8 (*rbyte)(const address_space *, offs_t); | |
| 139 | UINT16 (*rword)(const address_space *, offs_t); | |
| 140 | void (*wbyte)(const address_space *, offs_t, UINT8); | |
| 141 | void (*wword)(const address_space *, offs_t, UINT16); | |
| 138 | UINT8 (*rbyte)(address_space *, offs_t); | |
| 139 | UINT16 (*rword)(address_space *, offs_t); | |
| 140 | void (*wbyte)(address_space *, offs_t, UINT8); | |
| 141 | void (*wword)(address_space *, offs_t, UINT16); | |
| 142 | 142 | } memory_interface; |
| 143 | 143 | |
| 144 | 144 | |
| r8806 | r8807 | |
| 162 | 162 | |
| 163 | 163 | device_irq_callback irq_callback; |
| 164 | 164 | legacy_cpu_device *device; |
| 165 | const address_space *program; | |
| 166 | const address_space *io; | |
| 165 | address_space *program; | |
| 166 | address_space *io; | |
| 167 | 167 | int icount; |
| 168 | 168 | |
| 169 | 169 | memory_interface mem; |
| r8806 | r8807 | |
| 357 | 357 | nec_state->pending_irq &= ~INT_IRQ; |
| 358 | 358 | } |
| 359 | 359 | |
| 360 | dest_off = read_word(int_num*4); | |
| 361 | dest_seg = read_word(int_num*4+2); | |
| 360 | dest_off = read_mem_word(int_num*4); | |
| 361 | dest_seg = read_mem_word(int_num*4+2); | |
| 362 | 362 | |
| 363 | 363 | PUSH(nec_state->sregs[PS]); |
| 364 | 364 | PUSH(nec_state->ip); |
| r8806 | r8807 | |
| 1138 | 1138 | 8-bit memory accessors |
| 1139 | 1139 | *****************************************************************************/ |
| 1140 | 1140 | |
| 1141 | static UINT8 memory_read_byte(address_space *space, offs_t address) { return space->read_byte(address); } | |
| 1142 | static void memory_write_byte(address_space *space, offs_t address, UINT8 data) { space->write_byte(address, data); } | |
| 1143 | static UINT16 memory_read_word(address_space *space, offs_t address) { return space->read_word(address); } | |
| 1144 | static void memory_write_word(address_space *space, offs_t address, UINT16 data) { space->write_word(address, data); } | |
| 1145 | ||
| 1146 | ||
| 1141 | 1147 | static void configure_memory_8bit(nec_state_t *nec_state) |
| 1142 | 1148 | { |
| 1143 | 1149 | nec_state->mem.fetch_xor = 0; |
| 1144 | 1150 | |
| 1145 | nec_state->mem.rbyte = memory_read_byte_8le; | |
| 1146 | nec_state->mem.rword = memory_read_word_8le; | |
| 1147 | nec_state->mem.wbyte = memory_write_byte_8le; | |
| 1148 | nec_state->mem.wword = memory_write_word_8le; | |
| 1151 | nec_state->mem.rbyte = memory_read_byte; | |
| 1152 | nec_state->mem.rword = memory_read_word; | |
| 1153 | nec_state->mem.wbyte = memory_write_byte; | |
| 1154 | nec_state->mem.wword = memory_write_word; | |
| 1149 | 1155 | } |
| 1150 | 1156 | |
| 1151 | 1157 | |
| r8806 | r8807 | |
| 1153 | 1159 | 16-bit memory accessors |
| 1154 | 1160 | *****************************************************************************/ |
| 1155 | 1161 | |
| 1156 | static UINT16 read_word_16le( | |
| 1162 | static UINT16 read_word_16le( | |
| 1157 | 1163 | { |
| 1158 | 1164 | if (!(addr & 1)) |
| 1159 | return | |
| 1165 | return space->r | |
| 1160 | 1166 | else |
| 1161 | 1167 | { |
| 1162 | UINT16 result = memory_read_byte_16le(space, addr); | |
| 1163 | return result | (memory_read_byte_16le(space, addr + 1) << 8); | |
| 1168 | UINT16 result = space->read_byte(addr); | |
| 1169 | return result | (space->read_byte(addr + 1) << 8); | |
| 1164 | 1170 | } |
| 1165 | 1171 | } |
| 1166 | 1172 | |
| 1167 | static void write_word_16le( | |
| 1173 | static void write_word_16le( | |
| 1168 | 1174 | { |
| 1169 | 1175 | if (!(addr & 1)) |
| 1170 | | |
| 1176 | space-> | |
| 1171 | 1177 | else |
| 1172 | 1178 | { |
| 1173 | memory_write_byte_16le(space, addr, data); | |
| 1174 | memory_write_byte_16le(space, addr + 1, data >> 8); | |
| 1179 | space->write_byte(addr, data); | |
| 1180 | space->write_byte(addr + 1, data >> 8); | |
| 1175 | 1181 | } |
| 1176 | 1182 | } |
| 1177 | 1183 | |
| r8806 | r8807 | |
| 1179 | 1185 | { |
| 1180 | 1186 | nec_state->mem.fetch_xor = BYTE_XOR_LE(0); |
| 1181 | 1187 | |
| 1182 | nec_state->mem.rbyte = memory_read_byte | |
| 1188 | nec_state->mem.rbyte = memory_read_byte | |
| 1183 | 1189 | nec_state->mem.rword = read_word_16le; |
| 1184 | nec_state->mem.wbyte = memory_write_byte | |
| 1190 | nec_state->mem.wbyte = memory_write_byte | |
| 1185 | 1191 | nec_state->mem.wword = write_word_16le; |
| 1186 | 1192 | } |
| 1187 | 1193 |
| r8806 | r8807 | |
|---|---|---|
| 13 | 13 | #define RegByte(ModRM) nec_state->regs.b[Mod_RM.reg.b[ModRM]] |
| 14 | 14 | |
| 15 | 15 | #define GetRMWord(ModRM) \ |
| 16 | ((ModRM) >= 0xc0 ? nec_state->regs.w[Mod_RM.RM.w[ModRM]] : ( (*GetEA[ModRM])(nec_state), read_word( EA ) )) | |
| 16 | ((ModRM) >= 0xc0 ? nec_state->regs.w[Mod_RM.RM.w[ModRM]] : ( (*GetEA[ModRM])(nec_state), read_mem_word( EA ) )) | |
| 17 | 17 | |
| 18 | 18 | #define PutbackRMWord(ModRM,val) \ |
| 19 | 19 | { \ |
| 20 | 20 | if (ModRM >= 0xc0) nec_state->regs.w[Mod_RM.RM.w[ModRM]]=val; \ |
| 21 | else write_word(EA,val); \ | |
| 21 | else write_mem_word(EA,val); \ | |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | #define GetnextRMWord read_word((EA&0xf0000)|((EA+2)&0xffff)) | |
| 24 | #define GetnextRMWord read_mem_word((EA&0xf0000)|((EA+2)&0xffff)) | |
| 25 | 25 | |
| 26 | 26 | #define PutRMWord(ModRM,val) \ |
| 27 | 27 | { \ |
| r8806 | r8807 | |
| 29 | 29 | nec_state->regs.w[Mod_RM.RM.w[ModRM]]=val; \ |
| 30 | 30 | else { \ |
| 31 | 31 | (*GetEA[ModRM])(nec_state); \ |
| 32 | write_word( EA ,val); \ | |
| 32 | write_mem_word( EA ,val); \ | |
| 33 | 33 | } \ |
| 34 | 34 | } |
| 35 | 35 | |
| r8806 | r8807 | |
| 41 | 41 | else { \ |
| 42 | 42 | (*GetEA[ModRM])(nec_state); \ |
| 43 | 43 | val = FETCHWORD(); \ |
| 44 | write_word( EA , val); \ | |
| 44 | write_mem_word( EA , val); \ | |
| 45 | 45 | } \ |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | 48 | #define GetRMByte(ModRM) \ |
| 49 | ((ModRM) >= 0xc0 ? nec_state->regs.b[Mod_RM.RM.b[ModRM]] : read_byte( (*GetEA[ModRM])(nec_state) )) | |
| 49 | ((ModRM) >= 0xc0 ? nec_state->regs.b[Mod_RM.RM.b[ModRM]] : read_mem_byte( (*GetEA[ModRM])(nec_state) )) | |
| 50 | 50 | |
| 51 | 51 | #define PutRMByte(ModRM,val) \ |
| 52 | 52 | { \ |
| 53 | 53 | if (ModRM >= 0xc0) \ |
| 54 | 54 | nec_state->regs.b[Mod_RM.RM.b[ModRM]]=val; \ |
| 55 | 55 | else \ |
| 56 | write_byte( (*GetEA[ModRM])(nec_state) ,val); \ | |
| 56 | write_mem_byte( (*GetEA[ModRM])(nec_state) ,val); \ | |
| 57 | 57 | } |
| 58 | 58 | |
| 59 | 59 | #define PutImmRMByte(ModRM) \ |
| r8806 | r8807 | |
| 62 | 62 | nec_state->regs.b[Mod_RM.RM.b[ModRM]]=FETCH(); \ |
| 63 | 63 | else { \ |
| 64 | 64 | (*GetEA[ModRM])(nec_state); \ |
| 65 | write_byte( EA , FETCH() ); \ | |
| 65 | write_mem_byte( EA , FETCH() ); \ | |
| 66 | 66 | } \ |
| 67 | 67 | } |
| 68 | 68 | |
| r8806 | r8807 | |
| 71 | 71 | if (ModRM >= 0xc0) \ |
| 72 | 72 | nec_state->regs.b[Mod_RM.RM.b[ModRM]]=val; \ |
| 73 | 73 | else \ |
| 74 | write_byte(EA,val); \ | |
| 74 | write_mem_byte(EA,val); \ | |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | 77 | #define DEF_br8 \ |
| r8806 | r8807 | |
|---|---|---|
| 80 | 80 | |
| 81 | 81 | /************************************************************************/ |
| 82 | 82 | |
| 83 | #define read_byte(a) (*nec_state->mem.rbyte)(nec_state->program, a) | |
| 84 | #define read_word(a) (*nec_state->mem.rword)(nec_state->program, a) | |
| 85 | #define write_byte(a,d) (*nec_state->mem.wbyte)(nec_state->program, (a),(d)) | |
| 86 | #define write_word(a,d) (*nec_state->mem.wword)(nec_state->program, (a),(d)) | |
| 83 | #define read_mem_byte(a) (*nec_state->mem.rbyte)(nec_state->program, a) | |
| 84 | #define read_mem_word(a) (*nec_state->mem.rword)(nec_state->program, a) | |
| 85 | #define write_mem_byte(a,d) (*nec_state->mem.wbyte)(nec_state->program, (a),(d)) | |
| 86 | #define write_mem_word(a,d) (*nec_state->mem.wword)(nec_state->program, (a),(d)) | |
| 87 | 87 | |
| 88 | 88 | #define read_port_byte(a) (*nec_state->mem.rbyte)(nec_state->io, a) |
| 89 | 89 | #define read_port_word(a) (*nec_state->mem.rword)(nec_state->io, a) |
| r8806 | r8807 | |
| 98 | 98 | |
| 99 | 99 | #define DefaultBase(Seg) ((nec_state->seg_prefix && (Seg==DS0 || Seg==SS)) ? nec_state->prefix_base : nec_state->sregs[Seg] << 4) |
| 100 | 100 | |
| 101 | #define GetMemB(Seg,Off) (read_byte(DefaultBase(Seg) + (Off))) | |
| 102 | #define GetMemW(Seg,Off) (read_word(DefaultBase(Seg) + (Off))) | |
| 101 | #define GetMemB(Seg,Off) (read_mem_byte(DefaultBase(Seg) + (Off))) | |
| 102 | #define GetMemW(Seg,Off) (read_mem_word(DefaultBase(Seg) + (Off))) | |
| 103 | 103 | |
| 104 | #define PutMemB(Seg,Off,x) { write_byte(DefaultBase(Seg) + (Off), (x)); } | |
| 105 | #define PutMemW(Seg,Off,x) { write_word(DefaultBase(Seg) + (Off), (x)); } | |
| 104 | #define PutMemB(Seg,Off,x) { write_mem_byte(DefaultBase(Seg) + (Off), (x)); } | |
| 105 | #define PutMemW(Seg,Off,x) { write_mem_word(DefaultBase(Seg) + (Off), (x)); } | |
| 106 | 106 | |
| 107 | 107 | /* prefetch timing */ |
| 108 | 108 | |
| r8806 | r8807 | |
| 112 | 112 | #define EMPTY_PREFETCH() nec_state->prefetch_reset = 1 |
| 113 | 113 | |
| 114 | 114 | |
| 115 | #define PUSH(val) { nec_state->regs.w[SP]-=2; write_word((((nec_state->sregs[SS]<<4)+nec_state->regs.w[SP])),val); } | |
| 116 | #define POP(var) { var = read_word((((nec_state->sregs[SS]<<4)+nec_state->regs.w[SP]))); nec_state->regs.w[SP]+=2; } | |
| 115 | #define PUSH(val) { nec_state->regs.w[SP]-=2; write_mem_word((((nec_state->sregs[SS]<<4)+nec_state->regs.w[SP])),val); } | |
| 116 | #define POP(var) { var = read_mem_word((((nec_state->sregs[SS]<<4)+nec_state->regs.w[SP]))); nec_state->regs.w[SP]+=2; } | |
| 117 | 117 | |
| 118 | 118 | #define GetModRM UINT32 ModRM=FETCH() |
| 119 | 119 | |
| r8806 | r8807 | |
| 221 | 221 | } \ |
| 222 | 222 | else { \ |
| 223 | 223 | (*GetEA[ModRM])(nec_state); \ |
| 224 | tmp=read_byte(EA); \ | |
| 224 | tmp=read_mem_byte(EA); \ | |
| 225 | 225 | } |
| 226 | 226 | |
| 227 | 227 | #define BITOP_WORD \ |
| r8806 | r8807 | |
| 231 | 231 | } \ |
| 232 | 232 | else { \ |
| 233 | 233 | (*GetEA[ModRM])(nec_state); \ |
| 234 | tmp=read_word(EA); \ | |
| 234 | tmp=read_mem_word(EA); \ | |
| 235 | 235 | } |
| 236 | 236 | |
| 237 | 237 | #define BIT_NOT \ |
| r8806 | r8807 | |
|---|---|---|
| 196 | 196 | mips3_flavor flavor; |
| 197 | 197 | device_irq_callback irq_callback; |
| 198 | 198 | legacy_cpu_device * device; |
| 199 | | |
| 199 | | |
| 200 | 200 | UINT32 system_clock; |
| 201 | 201 | UINT32 cpu_clock; |
| 202 | 202 | UINT64 count_zero_time; |
| r8806 | r8807 | |
|---|---|---|
| 139 | 139 | int hasfpu; |
| 140 | 140 | device_irq_callback irq_callback; |
| 141 | 141 | legacy_cpu_device *device; |
| 142 | | |
| 142 | | |
| 143 | 143 | |
| 144 | 144 | /* endian-dependent load/store */ |
| 145 | 145 | void (*lwl)(r3000_state *r3000, UINT32 op); |
| r8806 | r8807 | |
| 150 | 150 | /* memory accesses */ |
| 151 | 151 | UINT8 bigendian; |
| 152 | 152 | data_accessors cur; |
| 153 | | |
| 153 | | |
| 154 | 154 | const data_accessors *cache_hand; |
| 155 | 155 | |
| 156 | 156 | /* cache memory */ |
| r8806 | r8807 | |
| 187 | 187 | static void swl_le(r3000_state *r3000, UINT32 op); |
| 188 | 188 | static void swr_le(r3000_state *r3000, UINT32 op); |
| 189 | 189 | |
| 190 | static UINT8 readcache_be(const address_space *space, offs_t offset); | |
| 191 | static UINT16 readcache_be_word(const address_space *space, offs_t offset); | |
| 192 | static UINT32 readcache_be_dword(const address_space *space, offs_t offset); | |
| 193 | static void writecache_be(const address_space *space, offs_t offset, UINT8 data); | |
| 194 | static void writecache_be_word(const address_space *space, offs_t offset, UINT16 data); | |
| 195 | static void writecache_be_dword(const address_space *space, offs_t offset, UINT32 data); | |
| 190 | static UINT8 readcache_be(address_space *space, offs_t offset); | |
| 191 | static UINT16 readcache_be_word(address_space *space, offs_t offset); | |
| 192 | static UINT32 readcache_be_dword(address_space *space, offs_t offset); | |
| 193 | static void writecache_be(address_space *space, offs_t offset, UINT8 data); | |
| 194 | static void writecache_be_word(address_space *space, offs_t offset, UINT16 data); | |
| 195 | static void writecache_be_dword(address_space *space, offs_t offset, UINT32 data); | |
| 196 | 196 | |
| 197 | static UINT8 readcache_le(const address_space *space, offs_t offset); | |
| 198 | static UINT16 readcache_le_word(const address_space *space, offs_t offset); | |
| 199 | static UINT32 readcache_le_dword(const address_space *space, offs_t offset); | |
| 200 | static void writecache_le(const address_space *space, offs_t offset, UINT8 data); | |
| 201 | static void writecache_le_word(const address_space *space, offs_t offset, UINT16 data); | |
| 202 | static void writecache_le_dword(const address_space *space, offs_t offset, UINT32 data); | |
| 197 | static UINT8 readcache_le(address_space *space, offs_t offset); | |
| 198 | static UINT16 readcache_le_word(address_space *space, offs_t offset); | |
| 199 | static UINT32 readcache_le_dword(address_space *space, offs_t offset); | |
| 200 | static void writecache_le(address_space *space, offs_t offset, UINT8 data); | |
| 201 | static void writecache_le_word(address_space *space, offs_t offset, UINT16 data); | |
| 202 | static void writecache_le_dword(address_space *space, offs_t offset, UINT32 data); | |
| 203 | 203 | |
| 204 | 204 | |
| 205 | 205 | |
| r8806 | r8807 | |
| 319 | 319 | { |
| 320 | 320 | /* set up the endianness */ |
| 321 | 321 | r3000->bigendian = bigendian; |
| 322 | r3000->program->accessors(r3000->memory_hand); | |
| 322 | 323 | if (r3000->bigendian) |
| 323 | 324 | { |
| 324 | r3000->memory_hand = &r3000->program->accessors; | |
| 325 | 325 | r3000->cache_hand = &be_cache; |
| 326 | 326 | r3000->lwl = lwl_be; |
| 327 | 327 | r3000->lwr = lwr_be; |
| r8806 | r8807 | |
| 330 | 330 | } |
| 331 | 331 | else |
| 332 | 332 | { |
| 333 | r3000->memory_hand = &r3000->program->accessors; | |
| 334 | 333 | r3000->cache_hand = &le_cache; |
| 335 | 334 | r3000->lwl = lwl_le; |
| 336 | 335 | r3000->lwr = lwr_le; |
| r8806 | r8807 | |
| 339 | 338 | } |
| 340 | 339 | |
| 341 | 340 | /* initialize the rest of the config */ |
| 342 | r3000->cur = | |
| 341 | r3000->cur = | |
| 343 | 342 | r3000->cache = r3000->dcache; |
| 344 | 343 | r3000->cache_size = r3000->dcache_size; |
| 345 | 344 | |
| r8806 | r8807 | |
| 396 | 395 | if (val & SR_IsC) |
| 397 | 396 | r3000->cur = *r3000->cache_hand; |
| 398 | 397 | else |
| 399 | r3000->cur = | |
| 398 | r3000->cur = | |
| 400 | 399 | } |
| 401 | 400 | |
| 402 | 401 | /* handle cache switching */ |
| r8806 | r8807 | |
| 892 | 891 | CACHE I/O |
| 893 | 892 | ***************************************************************************/ |
| 894 | 893 | |
| 895 | static UINT8 readcache_be( | |
| 894 | static UINT8 readcache_be( | |
| 896 | 895 | { |
| 897 | 896 | r3000_state *r3000 = get_safe_token(space->cpu); |
| 898 | 897 | offset &= 0x1fffffff; |
| 899 | 898 | return (offset * 4 < r3000->cache_size) ? r3000->cache[BYTE4_XOR_BE(offset)] : 0xff; |
| 900 | 899 | } |
| 901 | 900 | |
| 902 | static UINT16 readcache_be_word( | |
| 901 | static UINT16 readcache_be_word( | |
| 903 | 902 | { |
| 904 | 903 | r3000_state *r3000 = get_safe_token(space->cpu); |
| 905 | 904 | offset &= 0x1fffffff; |
| 906 | 905 | return (offset * 4 < r3000->cache_size) ? *(UINT16 *)&r3000->cache[WORD_XOR_BE(offset)] : 0xffff; |
| 907 | 906 | } |
| 908 | 907 | |
| 909 | static UINT32 readcache_be_dword( | |
| 908 | static UINT32 readcache_be_dword( | |
| 910 | 909 | { |
| 911 | 910 | r3000_state *r3000 = get_safe_token(space->cpu); |
| 912 | 911 | offset &= 0x1fffffff; |
| 913 | 912 | return (offset * 4 < r3000->cache_size) ? *(UINT32 *)&r3000->cache[offset] : 0xffffffff; |
| 914 | 913 | } |
| 915 | 914 | |
| 916 | static void writecache_be( | |
| 915 | static void writecache_be( | |
| 917 | 916 | { |
| 918 | 917 | r3000_state *r3000 = get_safe_token(space->cpu); |
| 919 | 918 | offset &= 0x1fffffff; |
| 920 | 919 | if (offset * 4 < r3000->cache_size) r3000->cache[BYTE4_XOR_BE(offset)] = data; |
| 921 | 920 | } |
| 922 | 921 | |
| 923 | static void writecache_be_word( | |
| 922 | static void writecache_be_word( | |
| 924 | 923 | { |
| 925 | 924 | r3000_state *r3000 = get_safe_token(space->cpu); |
| 926 | 925 | offset &= 0x1fffffff; |
| 927 | 926 | if (offset * 4 < r3000->cache_size) *(UINT16 *)&r3000->cache[WORD_XOR_BE(offset)] = data; |
| 928 | 927 | } |
| 929 | 928 | |
| 930 | static void writecache_be_dword( | |
| 929 | static void writecache_be_dword( | |
| 931 | 930 | { |
| 932 | 931 | r3000_state *r3000 = get_safe_token(space->cpu); |
| 933 | 932 | offset &= 0x1fffffff; |
| 934 | 933 | if (offset * 4 < r3000->cache_size) *(UINT32 *)&r3000->cache[offset] = data; |
| 935 | 934 | } |
| 936 | 935 | |
| 937 | static UINT8 readcache_le( | |
| 936 | static UINT8 readcache_le( | |
| 938 | 937 | { |
| 939 | 938 | r3000_state *r3000 = get_safe_token(space->cpu); |
| 940 | 939 | offset &= 0x1fffffff; |
| 941 | 940 | return (offset * 4 < r3000->cache_size) ? r3000->cache[BYTE4_XOR_LE(offset)] : 0xff; |
| 942 | 941 | } |
| 943 | 942 | |
| 944 | static UINT16 readcache_le_word( | |
| 943 | static UINT16 readcache_le_word( | |
| 945 | 944 | { |
| 946 | 945 | r3000_state *r3000 = get_safe_token(space->cpu); |
| 947 | 946 | offset &= 0x1fffffff; |
| 948 | 947 | return (offset * 4 < r3000->cache_size) ? *(UINT16 *)&r3000->cache[WORD_XOR_LE(offset)] : 0xffff; |
| 949 | 948 | } |
| 950 | 949 | |
| 951 | static UINT32 readcache_le_dword( | |
| 950 | static UINT32 readcache_le_dword( | |
| 952 | 951 | { |
| 953 | 952 | r3000_state *r3000 = get_safe_token(space->cpu); |
| 954 | 953 | offset &= 0x1fffffff; |
| 955 | 954 | return (offset * 4 < r3000->cache_size) ? *(UINT32 *)&r3000->cache[offset] : 0xffffffff; |
| 956 | 955 | } |
| 957 | 956 | |
| 958 | static void writecache_le( | |
| 957 | static void writecache_le( | |
| 959 | 958 | { |
| 960 | 959 | r3000_state *r3000 = get_safe_token(space->cpu); |
| 961 | 960 | offset &= 0x1fffffff; |
| 962 | 961 | if (offset * 4 < r3000->cache_size) r3000->cache[BYTE4_XOR_LE(offset)] = data; |
| 963 | 962 | } |
| 964 | 963 | |
| 965 | static void writecache_le_word( | |
| 964 | static void writecache_le_word( | |
| 966 | 965 | { |
| 967 | 966 | r3000_state *r3000 = get_safe_token(space->cpu); |
| 968 | 967 | offset &= 0x1fffffff; |
| 969 | 968 | if (offset * 4 < r3000->cache_size) *(UINT16 *)&r3000->cache[WORD_XOR_LE(offset)] = data; |
| 970 | 969 | } |
| 971 | 970 | |
| 972 | static void writecache_le_dword( | |
| 971 | static void writecache_le_dword( | |
| 973 | 972 | { |
| 974 | 973 | r3000_state *r3000 = get_safe_token(space->cpu); |
| 975 | 974 | offset &= 0x1fffffff; |
| r8806 | r8807 | |
|---|---|---|
| 186 | 186 | UINT32 multiplier_operand2; |
| 187 | 187 | device_irq_callback irq_callback; |
| 188 | 188 | legacy_cpu_device *device; |
| 189 | | |
| 189 | | |
| 190 | 190 | int bus_attached; |
| 191 | 191 | UINT32 bad_byte_address_mask; |
| 192 | 192 | UINT32 bad_half_address_mask; |
| r8806 | r8807 | |
| 335 | 335 | { |
| 336 | 336 | if( psxcpu->bus_attached ) |
| 337 | 337 | { |
| 338 | return | |
| 338 | return | |
| 339 | 339 | } |
| 340 | 340 | else |
| 341 | 341 | { |
| r8806 | r8807 | |
| 347 | 347 | { |
| 348 | 348 | if( psxcpu->bus_attached ) |
| 349 | 349 | { |
| 350 | return | |
| 350 | return | |
| 351 | 351 | } |
| 352 | 352 | else |
| 353 | 353 | { |
| r8806 | r8807 | |
| 359 | 359 | { |
| 360 | 360 | if( psxcpu->bus_attached ) |
| 361 | 361 | { |
| 362 | return | |
| 362 | return | |
| 363 | 363 | } |
| 364 | 364 | else |
| 365 | 365 | { |
| r8806 | r8807 | |
| 371 | 371 | { |
| 372 | 372 | if( psxcpu->bus_attached ) |
| 373 | 373 | { |
| 374 | return | |
| 374 | return | |
| 375 | 375 | } |
| 376 | 376 | else |
| 377 | 377 | { |
| r8806 | r8807 | |
| 383 | 383 | { |
| 384 | 384 | if( psxcpu->bus_attached ) |
| 385 | 385 | { |
| 386 | | |
| 386 | | |
| 387 | 387 | } |
| 388 | 388 | else |
| 389 | 389 | { |
| r8806 | r8807 | |
| 395 | 395 | { |
| 396 | 396 | if( psxcpu->bus_attached ) |
| 397 | 397 | { |
| 398 | | |
| 398 | | |
| 399 | 399 | } |
| 400 | 400 | else |
| 401 | 401 | { |
| r8806 | r8807 | |
| 1300 | 1300 | psxcpu->berr = 1; |
| 1301 | 1301 | } |
| 1302 | 1302 | |
| 1303 | static void mips_update_scratchpad( | |
| 1303 | static void mips_update_scratchpad( | |
| 1304 | 1304 | { |
| 1305 | 1305 | psxcpu_state *psxcpu = get_safe_token(space->cpu); |
| 1306 | 1306 | |
| r8806 | r8807 | |
| 1797 | 1797 | } |
| 1798 | 1798 | } |
| 1799 | 1799 | |
| 1800 | data = | |
| 1800 | data = | |
| 1801 | 1801 | } |
| 1802 | 1802 | break; |
| 1803 | 1803 | |
| r8806 | r8807 | |
| 2959 | 2959 | { |
| 2960 | 2960 | /* if a mtc/ctc precedes then this will get the value moved (which cop1 register is irrelevant). */ |
| 2961 | 2961 | /* if a mfc/cfc follows then it will get the same value as this one. */ |
| 2962 | return | |
| 2962 | return | |
| 2963 | 2963 | } |
| 2964 | 2964 | |
| 2965 | 2965 | static void setcp1dr( psxcpu_state *psxcpu, int reg, UINT32 value ) |
| r8806 | r8807 | |
| 2970 | 2970 | { |
| 2971 | 2971 | /* if a mtc/ctc precedes then this will get the value moved (which cop1 register is irrelevant). */ |
| 2972 | 2972 | /* if a mfc/cfc follows then it will get the same value as this one. */ |
| 2973 | return | |
| 2973 | return | |
| 2974 | 2974 | } |
| 2975 | 2975 | |
| 2976 | 2976 | static void setcp1cr( psxcpu_state *psxcpu, int reg, UINT32 value ) |
| r8806 | r8807 | |
| 2983 | 2983 | /* if you have mtc/ctc with an mfc/cfc directly afterwards then you get the value that was moved. */ |
| 2984 | 2984 | /* if you have an lwc with an mfc/cfc somewhere after it then you get the value that is loaded */ |
| 2985 | 2985 | /* otherwise you get the next opcode. which register you transfer to or from is irrelevant. */ |
| 2986 | return | |
| 2986 | return | |
| 2987 | 2987 | } |
| 2988 | 2988 | |
| 2989 | 2989 | static void setcp3dr( psxcpu_state *psxcpu, int reg, UINT32 value ) |
| r8806 | r8807 | |
| 2995 | 2995 | /* if you have mtc/ctc with an mfc/cfc directly afterwards then you get the value that was moved. */ |
| 2996 | 2996 | /* if you have an lwc with an mfc/cfc somewhere after it then you get the value that is loaded */ |
| 2997 | 2997 | /* otherwise you get the next opcode. which register you transfer to or from is irrelevant. */ |
| 2998 | return | |
| 2998 | return | |
| 2999 | 2999 | } |
| 3000 | 3000 | |
| 3001 | 3001 | static void setcp3cr( psxcpu_state *psxcpu, int reg, UINT32 value ) |
| r8806 | r8807 | |
|---|---|---|
| 98 | 98 | } |
| 99 | 99 | |
| 100 | 100 | /* set up the endianness */ |
| 101 | mips-> | |
| 101 | mips-> | |
| 102 | 102 | |
| 103 | 103 | /* allocate the virtual TLB */ |
| 104 | 104 | mips->vtlb = vtlb_alloc(device, ADDRESS_SPACE_PROGRAM, 2 * mips->tlbentries + 2, 0); |
| r8806 | r8807 | |
|---|---|---|
| 52 | 52 | |
| 53 | 53 | /* Static variables */ |
| 54 | 54 | |
| 55 | #define RM(Addr) ((unsigned)memory_read_byte_8be(cpustate->program, Addr)) | |
| 56 | #define WM(Addr,Value) (memory_write_byte_8be(cpustate->program, Addr, Value)) | |
| 55 | #define RM(Addr) ((unsigned)cpustate->program->read_byte(Addr)) | |
| 56 | #define WM(Addr,Value) (cpustate->program->write_byte(Addr, Value)) | |
| 57 | 57 | |
| 58 | 58 | #define IMMBYTE(b) b = ((unsigned)memory_raw_read_byte(cpustate->program, pPC)); pPC++ |
| 59 | 59 | #define SIMMBYTE(b) b = ((signed)memory_raw_read_byte(cpustate->program, pPC)); pPC++ |
| r8806 | r8807 | |
| 74 | 74 | UINT8 pf[0x100]; /* Perpherial file */ |
| 75 | 75 | device_irq_callback irq_callback; |
| 76 | 76 | legacy_cpu_device *device; |
| 77 | const address_space *program; | |
| 78 | const address_space *io; | |
| 77 | address_space *program; | |
| 78 | address_space *io; | |
| 79 | 79 | int icount; |
| 80 | 80 | int div_by_16_trigger; |
| 81 | 81 | int cycles_per_INT2; |
| r8806 | r8807 | |
| 599 | 599 | break; |
| 600 | 600 | |
| 601 | 601 | case 0x06: /* Port B write */ |
| 602 | | |
| 602 | cpustate->io-> | |
| 603 | 603 | cpustate->pf[ 0x06 ] = data; |
| 604 | 604 | break; |
| 605 | 605 | |
| 606 | 606 | case 0x08: /* Port C write */ |
| 607 | 607 | temp1 = data & cpustate->pf[ 0x09 ]; /* Mask off input bits */ |
| 608 | | |
| 608 | cpustate->io-> | |
| 609 | 609 | cpustate->pf[ 0x08 ] = temp1; |
| 610 | 610 | break; |
| 611 | 611 | |
| 612 | 612 | case 0x0a: /* Port D write */ |
| 613 | 613 | temp1 = data & cpustate->pf[ 0x0b ]; /* Mask off input bits */ |
| 614 | | |
| 614 | cpustate->io-> | |
| 615 | 615 | cpustate->pf[ 0x0a ] = temp1; |
| 616 | 616 | break; |
| 617 | 617 | |
| r8806 | r8807 | |
| 647 | 647 | break; |
| 648 | 648 | |
| 649 | 649 | case 0x04: /* Port A read */ |
| 650 | result = | |
| 650 | result = | |
| 651 | 651 | break; |
| 652 | 652 | |
| 653 | 653 | |
| r8806 | r8807 | |
| 658 | 658 | |
| 659 | 659 | case 0x08: /* Port C read */ |
| 660 | 660 | temp1 = cpustate->pf[ 0x08 ] & cpustate->pf[ 0x09 ]; /* Get previous output bits */ |
| 661 | temp2 = | |
| 661 | temp2 = | |
| 662 | 662 | temp3 = temp2 & (~cpustate->pf[ 0x09 ]); /* Mask off output bits */ |
| 663 | 663 | result = temp1 | temp3; /* OR together */ |
| 664 | 664 | break; |
| 665 | 665 | |
| 666 | 666 | case 0x0a: /* Port D read */ |
| 667 | 667 | temp1 = cpustate->pf[ 0x0a ] & cpustate->pf[ 0x0b ]; /* Get previous output bits */ |
| 668 | temp2 = | |
| 668 | temp2 = | |
| 669 | 669 | temp3 = temp2 & (~cpustate->pf[ 0x0b ]); /* Mask off output bits */ |
| 670 | 670 | result = temp1 | temp3; /* OR together */ |
| 671 | 671 | break; |
| r8806 | r8807 | |
|---|---|---|
| 54 | 54 | UINT16 irq_vector; |
| 55 | 55 | device_irq_callback irq_callback; |
| 56 | 56 | legacy_cpu_device *device; |
| 57 | const address_space *program; | |
| 58 | const address_space *iospace; | |
| 57 | address_space *program; | |
| 58 | address_space *iospace; | |
| 59 | 59 | int icount; |
| 60 | 60 | UINT8 r[64]; /* scratchpad RAM */ |
| 61 | 61 | int irq_request; |
| r8806 | r8807 | |
| 145 | 145 | * the memory location addressed by DC0; then all devices increment |
| 146 | 146 | * DC0. |
| 147 | 147 | */ |
| 148 | cpustate->dbus = | |
| 148 | cpustate->dbus = | |
| 149 | 149 | cpustate->dc0 += 1; |
| 150 | 150 | cpustate->icount -= cL; |
| 151 | 151 | } |
| r8806 | r8807 | |
| 176 | 176 | * Store the data bus contents into the memory location pointed |
| 177 | 177 | * to by DC0; increment DC0. |
| 178 | 178 | */ |
| 179 | | |
| 179 | | |
| 180 | 180 | cpustate->dc0 += 1; |
| 181 | 181 | cpustate->icount -= cL; |
| 182 | 182 | } |
| r8806 | r8807 | |
| 412 | 412 | * register was addressed; the device containing the addressed port |
| 413 | 413 | * must place the contents of the data bus into the address port. |
| 414 | 414 | */ |
| 415 | | |
| 415 | | |
| 416 | 416 | cpustate->icount -= cL; |
| 417 | 417 | } |
| 418 | 418 | |
| r8806 | r8807 | |
| 425 | 425 | * contents of timer and interrupt control registers cannot be read |
| 426 | 426 | * back onto the data bus). |
| 427 | 427 | */ |
| 428 | cpustate->dbus = | |
| 428 | cpustate->dbus = | |
| 429 | 429 | cpustate->icount -= cL; |
| 430 | 430 | } |
| 431 | 431 | |
| r8806 | r8807 | |
| 1267 | 1267 | { |
| 1268 | 1268 | ROMC_1C(cpustate, cS); |
| 1269 | 1269 | CLR_OZCS; |
| 1270 | cpustate->a = | |
| 1270 | cpustate->a = | |
| 1271 | 1271 | SET_SZ(cpustate->a); |
| 1272 | 1272 | } |
| 1273 | 1273 | |
| r8806 | r8807 | |
| 1292 | 1292 | static void f8_outs_0(f8_Regs *cpustate, int n) |
| 1293 | 1293 | { |
| 1294 | 1294 | ROMC_1C(cpustate, cS); |
| 1295 | | |
| 1295 | | |
| 1296 | 1296 | } |
| 1297 | 1297 | |
| 1298 | 1298 | /*************************************************** |
| r8806 | r8807 | |
|---|---|---|
| 150 | 150 | UINT32 ea; |
| 151 | 151 | device_irq_callback irq_callback; |
| 152 | 152 | legacy_cpu_device *device; |
| 153 | const address_space *program; | |
| 154 | const address_space *io; | |
| 153 | address_space *program; | |
| 154 | address_space *io; | |
| 155 | 155 | int icount; |
| 156 | 156 | z80_daisy_chain daisy; |
| 157 | 157 | UINT8 rtemp; |
| r8806 | r8807 | |
| 595 | 595 | /*************************************************************** |
| 596 | 596 | * Input a byte from given I/O port |
| 597 | 597 | ***************************************************************/ |
| 598 | #define IN(Z,port) | |
| 598 | #define IN(Z,port) (Z)->io->r | |
| 599 | 599 | |
| 600 | 600 | /*************************************************************** |
| 601 | 601 | * Output a byte to given I/O port |
| 602 | 602 | ***************************************************************/ |
| 603 | #define OUT(Z,port,value) | |
| 603 | #define OUT(Z,port,value) (Z)->io-> | |
| 604 | 604 | |
| 605 | 605 | /*************************************************************** |
| 606 | 606 | * Read a byte from given memory location |
| 607 | 607 | ***************************************************************/ |
| 608 | #define RM(Z,addr) | |
| 608 | #define RM(Z,addr) | |
| 609 | 609 | |
| 610 | 610 | /*************************************************************** |
| 611 | 611 | * Read a word from given memory location |
| r8806 | r8807 | |
| 619 | 619 | /*************************************************************** |
| 620 | 620 | * Write a byte to given memory location |
| 621 | 621 | ***************************************************************/ |
| 622 | #define WM(Z,addr,value) | |
| 622 | #define WM(Z,addr,value) (Z)->program->write_byte | |
| 623 | 623 | |
| 624 | 624 | /*************************************************************** |
| 625 | 625 | * Write a word to given memory location |
| r8806 | r8807 | |
|---|---|---|
| 110 | 110 | UINT8 *lbrm; |
| 111 | 111 | |
| 112 | 112 | legacy_cpu_device *device; |
| 113 | | |
| 113 | | |
| 114 | 114 | int icount; |
| 115 | 115 | |
| 116 | 116 | read16_device_func fdt_r; |
| r8806 | r8807 | |
|---|---|---|
| 86 | 86 | UINT8 irq_state; |
| 87 | 87 | int icount; |
| 88 | 88 | device_irq_callback irq_callback; |
| 89 | | |
| 89 | | |
| 90 | 90 | legacy_cpu_device *device; |
| 91 | 91 | |
| 92 | 92 | /* src2val table, registers are at the end */ |
| r8806 | r8807 | |
| 287 | 287 | INLINE UINT8 READBYTE(asap_state *asap, offs_t address) |
| 288 | 288 | { |
| 289 | 289 | /* no alignment issues with bytes */ |
| 290 | return | |
| 290 | return | |
| 291 | 291 | } |
| 292 | 292 | |
| 293 | 293 | INLINE UINT16 READWORD(asap_state *asap, offs_t address) |
| 294 | 294 | { |
| 295 | 295 | /* aligned reads are easy */ |
| 296 | 296 | if (!(address & 1)) |
| 297 | return | |
| 297 | return | |
| 298 | 298 | |
| 299 | 299 | /* misaligned reads are tricky */ |
| 300 | return | |
| 300 | return | |
| 301 | 301 | } |
| 302 | 302 | |
| 303 | 303 | INLINE UINT32 READLONG(asap_state *asap, offs_t address) |
| 304 | 304 | { |
| 305 | 305 | /* aligned reads are easy */ |
| 306 | 306 | if (!(address & 3)) |
| 307 | return | |
| 307 | return | |
| 308 | 308 | |
| 309 | 309 | /* misaligned reads are tricky */ |
| 310 | return | |
| 310 | return | |
| 311 | 311 | } |
| 312 | 312 | |
| 313 | 313 | INLINE void WRITEBYTE(asap_state *asap, offs_t address, UINT8 data) |
| 314 | 314 | { |
| 315 | 315 | /* no alignment issues with bytes */ |
| 316 | | |
| 316 | | |
| 317 | 317 | } |
| 318 | 318 | |
| 319 | 319 | INLINE void WRITEWORD(asap_state *asap, offs_t address, UINT16 data) |
| r8806 | r8807 | |
| 321 | 321 | /* aligned writes are easy */ |
| 322 | 322 | if (!(address & 1)) |
| 323 | 323 | { |
| 324 | | |
| 324 | | |
| 325 | 325 | return; |
| 326 | 326 | } |
| 327 | 327 | |
| 328 | 328 | /* misaligned writes are tricky */ |
| 329 | 329 | if (!(address & 2)) |
| 330 | 330 | { |
| 331 | memory_write_byte_32le(asap->program, address + 1, data); | |
| 332 | memory_write_byte_32le(asap->program, address + 2, data >> 8); | |
| 331 | asap->program->write_byte(address + 1, data); | |
| 332 | asap->program->write_byte(address + 2, data >> 8); | |
| 333 | 333 | } |
| 334 | 334 | else |
| 335 | | |
| 335 | | |
| 336 | 336 | } |
| 337 | 337 | |
| 338 | 338 | INLINE void WRITELONG(asap_state *asap, offs_t address, UINT32 data) |
| r8806 | r8807 | |
| 340 | 340 | /* aligned writes are easy */ |
| 341 | 341 | if (!(address & 3)) |
| 342 | 342 | { |
| 343 | | |
| 343 | asap->program->write_dword | |
| 344 | 344 | return; |
| 345 | 345 | } |
| 346 | 346 | |
| r8806 | r8807 | |
| 348 | 348 | switch (address & 3) |
| 349 | 349 | { |
| 350 | 350 | case 1: |
| 351 | memory_write_byte_32le(asap->program, address, data); | |
| 352 | memory_write_word_32le(asap->program, address + 1, data >> 8); | |
| 351 | asap->program->write_byte(address, data); | |
| 352 | asap->program->write_word(address + 1, data >> 8); | |
| 353 | 353 | break; |
| 354 | 354 | case 2: |
| 355 | | |
| 355 | | |
| 356 | 356 | break; |
| 357 | 357 | case 3: |
| 358 | | |
| 358 | | |
| 359 | 359 | break; |
| 360 | 360 | } |
| 361 | 361 | } |
| r8806 | r8807 | |
|---|---|---|
| 437 | 437 | retreive the value on IC0-IC3 (non-standard behaviour) */ |
| 438 | 438 | device_irq_callback irq_callback; |
| 439 | 439 | legacy_cpu_device *device; |
| 440 | const address_space *program; | |
| 441 | const address_space *io; | |
| 440 | address_space *program; | |
| 441 | address_space *io; | |
| 442 | 442 | int icount; |
| 443 | 443 | |
| 444 | 444 | UINT8 IDLE; /* nonzero if processor is IDLE - i.e waiting for interrupt while writing |
| r8806 | r8807 | |
| 529 | 529 | READ16_HANDLER(ti990_10_internal_r) |
| 530 | 530 | { |
| 531 | 531 | //return cpustate->ROM[offset]; |
| 532 | return | |
| 532 | return space->r | |
| 533 | 533 | } |
| 534 | 534 | |
| 535 | 535 | #endif |
| r8806 | r8807 | |
| 579 | 579 | { /* intercept TPCS and CPU ROM */ |
| 580 | 580 | if (addr < 0xfc00) |
| 581 | 581 | /* TPCS */ |
| 582 | return | |
| 582 | return | |
| 583 | 583 | else |
| 584 | 584 | /* CPU ROM */ |
| 585 | return | |
| 585 | return | |
| 586 | 586 | } |
| 587 | 587 | else if (! cpustate->mapping_on) |
| 588 | 588 | { |
| 589 | return | |
| 589 | return | |
| 590 | 590 | } |
| 591 | 591 | else |
| 592 | 592 | { |
| r8806 | r8807 | |
| 607 | 607 | cpustate->error_interrupt_register |= EIR_MAPERR; |
| 608 | 608 | cpustate->write_inhibit = 1; |
| 609 | 609 | } |
| 610 | return | |
| 610 | return | |
| 611 | 611 | } |
| 612 | 612 | if ((! (cpustate->error_interrupt_register & EIR_MAPERR)) && ! (cpustate->diaglat)) |
| 613 | 613 | cpustate->mapper_address_latch = cpustate->map_files[map_file].bias[map_index]+addr; |
| 614 | 614 | if ((cpustate->latch_control[map_index]) && (! cpustate->reset_maperr)) |
| 615 | 615 | cpustate->diaglat = 1; |
| 616 | return | |
| 616 | return | |
| 617 | 617 | } |
| 618 | 618 | } |
| 619 | 619 | |
| r8806 | r8807 | |
| 624 | 624 | { /* intercept TPCS and CPU ROM */ |
| 625 | 625 | if (addr < 0xfc00) |
| 626 | 626 | /* TPCS */ |
| 627 | | |
| 627 | | |
| 628 | 628 | else |
| 629 | 629 | /* CPU ROM */ |
| 630 | | |
| 630 | | |
| 631 | 631 | } |
| 632 | 632 | else if (! cpustate->mapping_on) |
| 633 | 633 | { |
| 634 | | |
| 634 | | |
| 635 | 635 | } |
| 636 | 636 | else |
| 637 | 637 | { |
| r8806 | r8807 | |
| 653 | 653 | cpustate->write_inhibit = 1; |
| 654 | 654 | } |
| 655 | 655 | if (cpustate->write_inhibit) |
| 656 | (void) | |
| 656 | (void) | |
| 657 | 657 | else |
| 658 | | |
| 658 | | |
| 659 | 659 | return; |
| 660 | 660 | } |
| 661 | 661 | if ((! (cpustate->error_interrupt_register & EIR_MAPERR)) && ! (cpustate->diaglat)) |
| 662 | 662 | cpustate->mapper_address_latch = cpustate->map_files[map_file].bias[map_index]+addr; |
| 663 | 663 | if ((cpustate->latch_control[map_index]) && (! cpustate->reset_maperr)) |
| 664 | 664 | cpustate->diaglat = 1; |
| 665 | | |
| 665 | | |
| 666 | 666 | } |
| 667 | 667 | } |
| 668 | 668 | |
| r8806 | r8807 | |
| 673 | 673 | { /* intercept TPCS and CPU ROM */ |
| 674 | 674 | if (addr < 0xfc00) |
| 675 | 675 | /* TPCS */ |
| 676 | return | |
| 676 | return | |
| 677 | 677 | else |
| 678 | 678 | /* CPU ROM */ |
| 679 | return | |
| 679 | return | |
| 680 | 680 | } |
| 681 | 681 | else if (! cpustate->mapping_on) |
| 682 | 682 | { |
| 683 | return | |
| 683 | return | |
| 684 | 684 | } |
| 685 | 685 | else |
| 686 | 686 | { |
| r8806 | r8807 | |
| 701 | 701 | cpustate->error_interrupt_register |= EIR_MAPERR; |
| 702 | 702 | cpustate->write_inhibit = 1; |
| 703 | 703 | } |
| 704 | return | |
| 704 | return | |
| 705 | 705 | } |
| 706 | 706 | if ((! (cpustate->error_interrupt_register & EIR_MAPERR)) && ! (cpustate->diaglat)) |
| 707 | 707 | cpustate->mapper_address_latch = cpustate->map_files[map_file].bias[map_index]+addr; |
| 708 | 708 | if ((cpustate->latch_control[map_index]) && (! cpustate->reset_maperr)) |
| 709 | 709 | cpustate->diaglat = 1; |
| 710 | return | |
| 710 | return | |
| 711 | 711 | } |
| 712 | 712 | } |
| 713 | 713 | |
| r8806 | r8807 | |
| 718 | 718 | { /* intercept TPCS and CPU ROM */ |
| 719 | 719 | if (addr < 0xfc00) |
| 720 | 720 | /* TPCS */ |
| 721 | | |
| 721 | | |
| 722 | 722 | else |
| 723 | 723 | /* CPU ROM */ |
| 724 | | |
| 724 | | |
| 725 | 725 | } |
| 726 | 726 | else if (! cpustate->mapping_on) |
| 727 | 727 | { |
| 728 | | |
| 728 | | |
| 729 | 729 | } |
| 730 | 730 | else |
| 731 | 731 | { |
| r8806 | r8807 | |
| 747 | 747 | cpustate->write_inhibit = 1; |
| 748 | 748 | } |
| 749 | 749 | if (cpustate->write_inhibit) |
| 750 | (void) | |
| 750 | (void) | |
| 751 | 751 | else |
| 752 | | |
| 752 | | |
| 753 | 753 | return; |
| 754 | 754 | } |
| 755 | 755 | if ((! (cpustate->error_interrupt_register & EIR_MAPERR)) && ! (cpustate->diaglat)) |
| 756 | 756 | cpustate->mapper_address_latch = cpustate->map_files[map_file].bias[map_index]+addr; |
| 757 | 757 | if ((cpustate->latch_control[map_index]) && (! cpustate->reset_maperr)) |
| 758 | 758 | cpustate->diaglat = 1; |
| 759 | | |
| 759 | | |
| 760 | 760 | } |
| 761 | 761 | } |
| 762 | 762 | |
| r8806 | r8807 | |
| 767 | 767 | remember this when writing memory handlers.*/ |
| 768 | 768 | /*This does not apply to tms9995 and tms99xxx, but does apply to tms9980 (see below).*/ |
| 769 | 769 | |
| 770 | #define readword(cs, addr) memory_read_word_16be((cs)->program, addr) | |
| 771 | #define writeword(cs, addr,data) memory_write_word_16be((cs)->program, (addr), (data)) | |
| 770 | #define readword(cs, addr) (cs)->program->read_word(addr) | |
| 771 | #define writeword(cs, addr,data) (cs)->program->write_word((addr), (data)) | |
| 772 | 772 | |
| 773 | #define readbyte(cs, addr) memory_read_byte_16be((cs)->program, addr) | |
| 774 | #define writebyte(cs, addr,data) memory_write_byte_16be((cs)->program, (addr),(data)) | |
| 773 | #define readbyte(cs, addr) (cs)->program->read_byte(addr) | |
| 774 | #define writebyte(cs, addr,data) (cs)->program->write_byte((addr),(data)) | |
| 775 | 775 | |
| 776 | 776 | #elif (TMS99XX_MODEL == TMS9980_ID) |
| 777 | 777 | /*8-bit data bus, 14-bit address*/ |
| r8806 | r8807 | |
| 784 | 784 | int val; |
| 785 | 785 | |
| 786 | 786 | cpustate->icount -= 2; |
| 787 | val = memory_read_byte_8be(cpustate->program, addr); | |
| 788 | return (val << 8) | memory_read_byte_8be(cpustate->program, addr+1); | |
| 787 | val = cpustate->program->read_byte(addr); | |
| 788 | return (val << 8) | cpustate->program->read_byte(addr+1); | |
| 789 | 789 | } |
| 790 | #define writeword(cs, addr,data) { (cs)->icount -= 2; | |
| 790 | #define writeword(cs, addr,data) { (cs)->icount -= 2; (cs)->program->write_byte | |
| 791 | 791 | |
| 792 | 792 | #if 0 |
| 793 | #define readbyte(cs, addr) ((cs)->icount -= 2, memory_read_byte_8be((cs)->program, addr)) | |
| 794 | #define writebyte(cs, addr,data) { (cs)->icount -= 2; memory_write_byte_8be((cs)->program, (addr),(data)); } | |
| 793 | #define readbyte(cs, addr) ((cs)->icount -= 2, (cs)->program->read_byte(addr)) | |
| 794 | #define writebyte(cs, addr,data) { (cs)->icount -= 2; (cs)->program->write_byte((addr),(data)); } | |
| 795 | 795 | #else |
| 796 | 796 | /*This is how it really works*/ |
| 797 | 797 | /*Note that every writebyte must match a readbyte (which is indeed the case)*/ |
| r8806 | r8807 | |
| 801 | 801 | cpustate->icount -= 2; |
| 802 | 802 | if (addr & 1) |
| 803 | 803 | { |
| 804 | cpustate->extra_byte = memory_read_byte_8be(cpustate->program, addr-1); | |
| 805 | return memory_read_byte_8be(cpustate->program, addr); | |
| 804 | cpustate->extra_byte = cpustate->program->read_byte(addr-1); | |
| 805 | return cpustate->program->read_byte(addr); | |
| 806 | 806 | } |
| 807 | 807 | else |
| 808 | 808 | { |
| 809 | int val = memory_read_byte_8be(cpustate->program, addr); | |
| 810 | cpustate->extra_byte = memory_read_byte_8be(cpustate->program, addr+1); | |
| 809 | int val = cpustate->program->read_byte(addr); | |
| 810 | cpustate->extra_byte = cpustate->program->read_byte(addr+1); | |
| 811 | 811 | return val; |
| 812 | 812 | } |
| 813 | 813 | } |
| r8806 | r8807 | |
| 816 | 816 | cpustate->icount -= 2; |
| 817 | 817 | if (addr & 1) |
| 818 | 818 | { |
| 819 | memory_write_byte_8be(cpustate->program, addr-1, cpustate->extra_byte); | |
| 820 | memory_write_byte_8be(cpustate->program, addr, data); | |
| 819 | cpustate->program->write_byte(addr-1, cpustate->extra_byte); | |
| 820 | cpustate->program->write_byte(addr, data); | |
| 821 | 821 | } |
| 822 | 822 | else |
| 823 | 823 | { |
| 824 | memory_write_byte_8be(cpustate->program, addr, data); | |
| 825 | memory_write_byte_8be(cpustate->program, addr+1, cpustate->extra_byte); | |
| 824 | cpustate->program->write_byte(addr, data); | |
| 825 | cpustate->program->write_byte(addr+1, cpustate->extra_byte); | |
| 826 | 826 | } |
| 827 | 827 | } |
| 828 | 828 | #endif |
| r8806 | r8807 | |
| 841 | 841 | else |
| 842 | 842 | { |
| 843 | 843 | cpustate->icount -= 2; |
| 844 | return ( | |
| 844 | return ( | |
| 845 | 845 | } |
| 846 | 846 | } |
| 847 | 847 | static void writeword(tms99xx_state *cpustate, int addr, int data) |
| r8806 | r8807 | |
| 852 | 852 | else if (!(addr < 0x2000)) |
| 853 | 853 | { |
| 854 | 854 | cpustate->icount -= 2; |
| 855 | memory_write_byte_8be(cpustate->program, addr, data >> 8); | |
| 856 | memory_write_byte_8be(cpustate->program, addr + 1, data & 0xff); | |
| 855 | cpustate->program->write_byte(addr, data >> 8); | |
| 856 | cpustate->program->write_byte(addr + 1, data & 0xff); | |
| 857 | 857 | } |
| 858 | 858 | } |
| 859 | 859 | |
| r8806 | r8807 | |
| 870 | 870 | cpustate->icount -= 2; |
| 871 | 871 | if (addr & 1) |
| 872 | 872 | { |
| 873 | cpustate->extra_byte = memory_read_byte_8be(cpustate->program, addr-1); | |
| 874 | return memory_read_byte_8be(cpustate->program, addr); | |
| 873 | cpustate->extra_byte = cpustate->program->read_byte(addr-1); | |
| 874 | return cpustate->program->read_byte(addr); | |
| 875 | 875 | } |
| 876 | 876 | else |
| 877 | 877 | { |
| 878 | int val = memory_read_byte_8be(cpustate->program, addr); | |
| 879 | cpustate->extra_byte = memory_read_byte_8be(cpustate->program, addr+1); | |
| 878 | int val = cpustate->program->read_byte(addr); | |
| 879 | cpustate->extra_byte = cpustate->program->read_byte(addr+1); | |
| 880 | 880 | return val; |
| 881 | 881 | } |
| 882 | 882 | } |
| r8806 | r8807 | |
| 891 | 891 | cpustate->icount -= 2; |
| 892 | 892 | if (addr & 1) |
| 893 | 893 | { |
| 894 | memory_write_byte_8be(cpustate->program, addr-1, cpustate->extra_byte); | |
| 895 | memory_write_byte_8be(cpustate->program, addr, data); | |
| 894 | cpustate->program->write_byte(addr-1, cpustate->extra_byte); | |
| 895 | cpustate->program->write_byte(addr, data); | |
| 896 | 896 | } |
| 897 | 897 | else |
| 898 | 898 | { |
| 899 | memory_write_byte_8be(cpustate->program, addr, data); | |
| 900 | memory_write_byte_8be(cpustate->program, addr+1, cpustate->extra_byte); | |
| 899 | cpustate->program->write_byte(addr, data); | |
| 900 | cpustate->program->write_byte(addr+1, cpustate->extra_byte); | |
| 901 | 901 | } |
| 902 | 902 | } |
| 903 | 903 | } |
| r8806 | r8807 | |
| 914 | 914 | { |
| 915 | 915 | int reply; |
| 916 | 916 | cpustate->icount -= cpustate->memory_wait_states_word; |
| 917 | reply = memory_read_byte_8be(cpustate->program, addr); | |
| 918 | return (reply << 8) | memory_read_byte_8be(cpustate->program, addr + 1); | |
| 917 | reply = cpustate->program->read_byte(addr); | |
| 918 | return (reply << 8) | cpustate->program->read_byte(addr + 1); | |
| 919 | 919 | } |
| 920 | 920 | else if (addr < 0xf0fc) |
| 921 | 921 | { |
| r8806 | r8807 | |
| 925 | 925 | { |
| 926 | 926 | int reply; |
| 927 | 927 | cpustate->icount -= cpustate->memory_wait_states_word; |
| 928 | reply = memory_read_byte_8be(cpustate->program, addr); | |
| 929 | return (reply << 8) | memory_read_byte_8be(cpustate->program, addr + 1); | |
| 928 | reply = cpustate->program->read_byte(addr); | |
| 929 | return (reply << 8) | cpustate->program->read_byte(addr + 1); | |
| 930 | 930 | } |
| 931 | 931 | else if (addr < 0xfffc) |
| 932 | 932 | { |
| r8806 | r8807 | |
| 949 | 949 | if ((addr < 0xf000) || (cpustate->is_mp9537)) |
| 950 | 950 | { |
| 951 | 951 | cpustate->icount -= cpustate->memory_wait_states_word; |
| 952 | memory_write_byte_8be(cpustate->program, addr, data >> 8); | |
| 953 | memory_write_byte_8be(cpustate->program, addr + 1, data & 0xff); | |
| 952 | cpustate->program->write_byte(addr, data >> 8); | |
| 953 | cpustate->program->write_byte(addr + 1, data & 0xff); | |
| 954 | 954 | } |
| 955 | 955 | else if (addr < 0xf0fc) |
| 956 | 956 | { |
| r8806 | r8807 | |
| 959 | 959 | else if (addr < 0xfffa) |
| 960 | 960 | { |
| 961 | 961 | cpustate->icount -= cpustate->memory_wait_states_word; |
| 962 | memory_write_byte_8be(cpustate->program, addr, data >> 8); | |
| 963 | memory_write_byte_8be(cpustate->program, addr + 1, data & 0xff); | |
| 962 | cpustate->program->write_byte(addr, data >> 8); | |
| 963 | cpustate->program->write_byte(addr + 1, data & 0xff); | |
| 964 | 964 | } |
| 965 | 965 | else if (addr < 0xfffc) |
| 966 | 966 | { |
| r8806 | r8807 | |
| 979 | 979 | if ((addr < 0xf000) || (cpustate->is_mp9537)) |
| 980 | 980 | { |
| 981 | 981 | cpustate->icount -= cpustate->memory_wait_states_byte; |
| 982 | return | |
| 982 | return | |
| 983 | 983 | } |
| 984 | 984 | else if (addr < 0xf0fc) |
| 985 | 985 | { |
| r8806 | r8807 | |
| 988 | 988 | else if (addr < 0xfffa) |
| 989 | 989 | { |
| 990 | 990 | cpustate->icount -= cpustate->memory_wait_states_byte; |
| 991 | return | |
| 991 | return | |
| 992 | 992 | } |
| 993 | 993 | else if (addr < 0xfffc) |
| 994 | 994 | { |
| r8806 | r8807 | |
| 1018 | 1018 | if ((addr < 0xf000) || (cpustate->is_mp9537)) |
| 1019 | 1019 | { |
| 1020 | 1020 | cpustate->icount -= cpustate->memory_wait_states_byte; |
| 1021 | | |
| 1021 | | |
| 1022 | 1022 | } |
| 1023 | 1023 | else if (addr < 0xf0fc) |
| 1024 | 1024 | { |
| r8806 | r8807 | |
| 1027 | 1027 | else if (addr < 0xfffa) |
| 1028 | 1028 | { |
| 1029 | 1029 | cpustate->icount -= cpustate->memory_wait_states_byte; |
| 1030 | | |
| 1030 | | |
| 1031 | 1031 | } |
| 1032 | 1032 | else if (addr < 0xfffc) |
| 1033 | 1033 | { |
| r8806 | r8807 | |
| 1999 | 1999 | CRU_PRIVILEGE_VIOLATION = -1 |
| 2000 | 2000 | } cru_error_code; |
| 2001 | 2001 | |
| 2002 | #define WRITEPORT(cs, port, data) | |
| 2002 | #define WRITEPORT(cs, port, data) (cs)->io-> | |
| 2003 | 2003 | |
| 2004 | 2004 | #if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID) |
| 2005 | 2005 | /* on tms9940, we have to handle internal CRU ports */ |
| r8806 | r8807 | |
| 2218 | 2218 | read at the same address. This seems to be impossible to emulate efficiently, so, if you need |
| 2219 | 2219 | to emulate this, you're in trouble. |
| 2220 | 2220 | */ |
| 2221 | #define READPORT(cs, port) | |
| 2221 | #define READPORT(cs, port) (cs)->io->r | |
| 2222 | 2222 | |
| 2223 | 2223 | |
| 2224 | 2224 | #if (TMS99XX_MODEL == TMS9940_ID) || (TMS99XX_MODEL == TMS9985_ID) |
| r8806 | r8807 | |
| 2429 | 2429 | |
| 2430 | 2430 | for (i=0; i<3; i++) |
| 2431 | 2431 | { |
| 2432 | cpustate->map_files[dst_file].L[i] = | |
| 2432 | cpustate->map_files[dst_file].L[i] = | |
| 2433 | 2433 | cpustate->map_files[dst_file].limit[i] = (cpustate->map_files[dst_file].L[i] ^ 0xffe0) | 0x001f; |
| 2434 | 2434 | cpustate->mapper_address_latch = (cpustate->mapper_address_latch+2) & 0x1fffff; |
| 2435 | cpustate->map_files[dst_file].B[i] = | |
| 2435 | cpustate->map_files[dst_file].B[i] = | |
| 2436 | 2436 | cpustate->map_files[dst_file].bias[i] = ((unsigned int) cpustate->map_files[dst_file].B[i]) << 5; |
| 2437 | 2437 | cpustate->mapper_address_latch = (cpustate->mapper_address_latch+2) & 0x1fffff; |
| 2438 | 2438 | } |
| r8806 | r8807 | |
|---|---|---|
| 35 | 35 | |
| 36 | 36 | device_irq_callback irq_cb; |
| 37 | 37 | legacy_cpu_device *device; |
| 38 | | |
| 38 | | |
| 39 | 39 | |
| 40 | 40 | int icount; |
| 41 | 41 | }; |
| r8806 | r8807 | |
| 52 | 52 | INLINE UINT32 i960_read_dword_unaligned(i960_state_t *i960, UINT32 address) |
| 53 | 53 | { |
| 54 | 54 | if (address & 3) |
| 55 | return | |
| 55 | return | |
| 56 | 56 | else |
| 57 | return | |
| 57 | return | |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | 60 | INLINE UINT16 i960_read_word_unaligned(i960_state_t *i960, UINT32 address) |
| 61 | 61 | { |
| 62 | 62 | if (address & 1) |
| 63 | return | |
| 63 | return | |
| 64 | 64 | else |
| 65 | return | |
| 65 | return | |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | 68 | INLINE void i960_write_dword_unaligned(i960_state_t *i960, UINT32 address, UINT32 data) |
| 69 | 69 | { |
| 70 | 70 | if (address & 3) |
| 71 | 71 | { |
| 72 | memory_write_byte_32le(i960->program, address, data & 0xff); | |
| 73 | memory_write_byte_32le(i960->program, address+1, (data>>8)&0xff); | |
| 74 | memory_write_byte_32le(i960->program, address+2, (data>>16)&0xff); | |
| 75 | memory_write_byte_32le(i960->program, address+3, (data>>24)&0xff); | |
| 72 | i960->program->write_byte(address, data & 0xff); | |
| 73 | i960->program->write_byte(address+1, (data>>8)&0xff); | |
| 74 | i960->program->write_byte(address+2, (data>>16)&0xff); | |
| 75 | i960->program->write_byte(address+3, (data>>24)&0xff); | |
| 76 | 76 | } |
| 77 | 77 | else |
| 78 | 78 | { |
| 79 | | |
| 79 | i960->program->write_dword | |
| 80 | 80 | } |
| 81 | 81 | } |
| 82 | 82 | |
| r8806 | r8807 | |
| 84 | 84 | { |
| 85 | 85 | if (address & 1) |
| 86 | 86 | { |
| 87 | memory_write_byte_32le(i960->program, address, data & 0xff); | |
| 88 | memory_write_byte_32le(i960->program, address+1, (data>>8)&0xff); | |
| 87 | i960->program->write_byte(address, data & 0xff); | |
| 88 | i960->program->write_byte(address+1, (data>>8)&0xff); | |
| 89 | 89 | } |
| 90 | 90 | else |
| 91 | 91 | { |
| 92 | | |
| 92 | | |
| 93 | 93 | } |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | 96 | INLINE void send_iac(i960_state_t *i960, UINT32 adr) |
| 97 | 97 | { |
| 98 | 98 | UINT32 iac[4]; |
| 99 | iac[0] = memory_read_dword_32le(i960->program, adr); | |
| 100 | iac[1] = memory_read_dword_32le(i960->program, adr+4); | |
| 101 | iac[2] = memory_read_dword_32le(i960->program, adr+8); | |
| 102 | iac[3] = memory_read_dword_32le(i960->program, adr+12); | |
| 99 | iac[0] = i960->program->read_dword(adr); | |
| 100 | iac[1] = i960->program->read_dword(adr+4); | |
| 101 | iac[2] = i960->program->read_dword(adr+8); | |
| 102 | iac[3] = i960->program->read_dword(adr+12); | |
| 103 | 103 | |
| 104 | 104 | switch(iac[0]>>24) { |
| 105 | 105 | case 0x93: // reinit |
| r8806 | r8807 | |
| 415 | 415 | // interrupt dispatch |
| 416 | 416 | static void take_interrupt(i960_state_t *i960, int vector, int lvl) |
| 417 | 417 | { |
| 418 | int int_tab = memory_read_dword_32le(i960->program, i960->PRCB+20); // interrupt table | |
| 419 | int int_SP = memory_read_dword_32le(i960->program, i960->PRCB+24); // interrupt stack | |
| 418 | int int_tab = i960->program->read_dword(i960->PRCB+20); // interrupt table | |
| 419 | int int_SP = i960->program->read_dword(i960->PRCB+24); // interrupt stack | |
| 420 | 420 | int SP; |
| 421 | 421 | UINT32 IRQV; |
| 422 | 422 | |
| 423 | IRQV = | |
| 423 | IRQV = | |
| 424 | 424 | |
| 425 | 425 | // start the process |
| 426 | 426 | if(!(i960->PC & 0x2000)) // if this is a nested interrupt, don't re-get int_SP |
| r8806 | r8807 | |
| 438 | 438 | do_call(i960, IRQV, 7, SP); |
| 439 | 439 | |
| 440 | 440 | // save the processor state |
| 441 | memory_write_dword_32le(i960->program, i960->r[I960_FP]-16, i960->PC); | |
| 442 | memory_write_dword_32le(i960->program, i960->r[I960_FP]-12, i960->AC); | |
| 441 | i960->program->write_dword(i960->r[I960_FP]-16, i960->PC); | |
| 442 | i960->program->write_dword(i960->r[I960_FP]-12, i960->AC); | |
| 443 | 443 | // store the vector |
| 444 | | |
| 444 | i960->program->write_dword | |
| 445 | 445 | |
| 446 | 446 | i960->PC &= ~0x1f00; // clear priority, state, trace-fault pending, and trace enable |
| 447 | 447 | i960->PC |= (lvl<<16); // set CPU level to current IRQ level |
| r8806 | r8807 | |
| 450 | 450 | |
| 451 | 451 | static void check_irqs(i960_state_t *i960) |
| 452 | 452 | { |
| 453 | int int_tab = | |
| 453 | int int_tab = | |
| 454 | 454 | int cpu_pri = (i960->PC>>16)&0x1f; |
| 455 | 455 | int pending_pri; |
| 456 | 456 | int lvl, irq, take = -1; |
| 457 | 457 | int vword; |
| 458 | 458 | static const UINT32 lvlmask[4] = { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }; |
| 459 | 459 | |
| 460 | pending_pri = | |
| 460 | pending_pri = | |
| 461 | 461 | |
| 462 | 462 | if ((i960->immediate_irq) && ((cpu_pri < i960->immediate_pri) || (i960->immediate_pri == 31))) |
| 463 | 463 | { |
| r8806 | r8807 | |
| 475 | 475 | wordl = (lvl % 4) * 8; |
| 476 | 476 | wordh = (wordl + 8) - 1; |
| 477 | 477 | |
| 478 | vword = | |
| 478 | vword = | |
| 479 | 479 | |
| 480 | 480 | // take the first vector we find for this level |
| 481 | 481 | for (irq = wordh; irq >= wordl; irq--) { |
| 482 | 482 | if(vword & (1 << irq)) { |
| 483 | 483 | // clear pending bit |
| 484 | 484 | vword &= ~(1 << irq); |
| 485 | | |
| 485 | i960->program->write_dword | |
| 486 | 486 | take = irq; |
| 487 | 487 | break; |
| 488 | 488 | } |
| r8806 | r8807 | |
| 494 | 494 | |
| 495 | 495 | // try to recover... |
| 496 | 496 | pending_pri &= ~(1 << lvl); |
| 497 | | |
| 497 | i960->program->write_dword | |
| 498 | 498 | return; |
| 499 | 499 | } |
| 500 | 500 | |
| 501 | 501 | // if no vectors are waiting for this level, clear the level bit |
| 502 | 502 | if(!(vword & lvlmask[lvl % 4])) { |
| 503 | 503 | pending_pri &= ~(1 << lvl); |
| 504 | | |
| 504 | i960->program->write_dword | |
| 505 | 505 | } |
| 506 | 506 | |
| 507 | 507 | take += ((lvl/4) * 32); |
| r8806 | r8807 | |
| 530 | 530 | // flush the current register set to the current frame |
| 531 | 531 | FP = i960->r[I960_FP] & ~0x3f; |
| 532 | 532 | for (i = 0; i < 16; i++) { |
| 533 | | |
| 533 | i960->program->write_dword | |
| 534 | 534 | } |
| 535 | 535 | } |
| 536 | 536 | else // a cache entry is available, use it |
| r8806 | r8807 | |
| 569 | 569 | { |
| 570 | 570 | int i; |
| 571 | 571 | for(i=0; i<0x10; i++) |
| 572 | i960->r[i] = | |
| 572 | i960->r[i] = | |
| 573 | 573 | |
| 574 | 574 | if (i960->rcache_pos < 0) |
| 575 | 575 | { |
| r8806 | r8807 | |
| 595 | 595 | break; |
| 596 | 596 | |
| 597 | 597 | case 7: |
| 598 | x = memory_read_dword(i960->program, i960->r[I960_FP]-16); | |
| 599 | y = memory_read_dword(i960->program, i960->r[I960_FP]-12); | |
| 598 | x = i960->program->read_dword(i960->r[I960_FP]-16); | |
| 599 | y = i960->program->read_dword(i960->r[I960_FP]-12); | |
| 600 | 600 | do_ret_0(i960); |
| 601 | 601 | i960->AC = y; |
| 602 | 602 | // #### test supervisor |
| r8806 | r8807 | |
| 1235 | 1235 | t2 = get_2_ri(i960, opcode); |
| 1236 | 1236 | // interrupt control register |
| 1237 | 1237 | if(t1 == 0xff000004) |
| 1238 | i960->ICR = | |
| 1238 | i960->ICR = | |
| 1239 | 1239 | else |
| 1240 | | |
| 1240 | i960->program->write_dword | |
| 1241 | 1241 | i960->AC = (i960->AC & ~7) | 2; |
| 1242 | 1242 | break; |
| 1243 | 1243 | |
| r8806 | r8807 | |
| 1248 | 1248 | if(t1 == 0xff000010) |
| 1249 | 1249 | send_iac(i960, t2); |
| 1250 | 1250 | else { |
| 1251 | memory_write_dword_32le(i960->program, t1, memory_read_dword_32le(i960->program, t2)); | |
| 1252 | memory_write_dword_32le(i960->program, t1+4, memory_read_dword_32le(i960->program, t2+4)); | |
| 1253 | memory_write_dword_32le(i960->program, t1+8, memory_read_dword_32le(i960->program, t2+8)); | |
| 1254 | memory_write_dword_32le(i960->program, t1+12, memory_read_dword_32le(i960->program, t2+12)); | |
| 1251 | i960->program->write_dword(t1, i960->program->read_dword(t2)); | |
| 1252 | i960->program->write_dword(t1+4, i960->program->read_dword(t2+4)); | |
| 1253 | i960->program->write_dword(t1+8, i960->program->read_dword(t2+8)); | |
| 1254 | i960->program->write_dword(t1+12, i960->program->read_dword(t2+12)); | |
| 1255 | 1255 | } |
| 1256 | 1256 | i960->AC = (i960->AC & ~7) | 2; |
| 1257 | 1257 | break; |
| r8806 | r8807 | |
| 1352 | 1352 | |
| 1353 | 1353 | for (i = 0; i < 0x10; i++) |
| 1354 | 1354 | { |
| 1355 | | |
| 1355 | i960->program->write_dword | |
| 1356 | 1356 | } |
| 1357 | 1357 | } |
| 1358 | 1358 | i960->rcache_pos = 0; |
| r8806 | r8807 | |
| 1792 | 1792 | |
| 1793 | 1793 | case 0x80: // ldob |
| 1794 | 1794 | i960->icount -= 4; |
| 1795 | i960->r[(opcode>>19)&0x1f] = | |
| 1795 | i960->r[(opcode>>19)&0x1f] = | |
| 1796 | 1796 | break; |
| 1797 | 1797 | |
| 1798 | 1798 | case 0x82: // stob |
| 1799 | 1799 | i960->icount -= 2; |
| 1800 | | |
| 1800 | | |
| 1801 | 1801 | break; |
| 1802 | 1802 | |
| 1803 | 1803 | case 0x84: // bx |
| r8806 | r8807 | |
| 1928 | 1928 | |
| 1929 | 1929 | case 0xc0: // ldib |
| 1930 | 1930 | i960->icount -= 4; |
| 1931 | i960->r[(opcode>>19)&0x1f] = (INT8) | |
| 1931 | i960->r[(opcode>>19)&0x1f] = (INT8) | |
| 1932 | 1932 | break; |
| 1933 | 1933 | |
| 1934 | 1934 | case 0xc2: // stib |
| 1935 | 1935 | i960->icount -= 2; |
| 1936 | | |
| 1936 | | |
| 1937 | 1937 | break; |
| 1938 | 1938 | |
| 1939 | 1939 | case 0xc8: // ldis |
| r8806 | r8807 | |
| 1973 | 1973 | |
| 1974 | 1974 | static void set_irq_line(i960_state_t *i960, int irqline, int state) |
| 1975 | 1975 | { |
| 1976 | int int_tab = | |
| 1976 | int int_tab = | |
| 1977 | 1977 | int cpu_pri = (i960->PC>>16)&0x1f; |
| 1978 | 1978 | int vector =0; |
| 1979 | 1979 | int priority; |
| r8806 | r8807 | |
| 2022 | 2022 | else |
| 2023 | 2023 | { |
| 2024 | 2024 | // store the interrupt in the "pending" table |
| 2025 | pend = | |
| 2025 | pend = | |
| 2026 | 2026 | pend |= (1 << priority); |
| 2027 | | |
| 2027 | i960->program->write_dword | |
| 2028 | 2028 | |
| 2029 | 2029 | // now bitfield-ize the vector |
| 2030 | 2030 | word = ((vector / 32) * 4) + 4; |
| 2031 | 2031 | wordofs = vector % 32; |
| 2032 | pend = | |
| 2032 | pend = | |
| 2033 | 2033 | pend |= (1 << wordofs); |
| 2034 | | |
| 2034 | i960->program->write_dword | |
| 2035 | 2035 | } |
| 2036 | 2036 | |
| 2037 | 2037 | // and ack it to the core now that it's queued |
| r8806 | r8807 | |
| 2085 | 2085 | { |
| 2086 | 2086 | i960_state_t *i960 = get_safe_token(device); |
| 2087 | 2087 | |
| 2088 | i960->SAT = memory_read_dword_32le(i960->program, 0); | |
| 2089 | i960->PRCB = memory_read_dword_32le(i960->program, 4); | |
| 2090 | i960->IP = memory_read_dword_32le(i960->program, 12); | |
| 2088 | i960->SAT = i960->program->read_dword(0); | |
| 2089 | i960->PRCB = i960->program->read_dword(4); | |
| 2090 | i960->IP = i960->program->read_dword(12); | |
| 2091 | 2091 | i960->PC = 0x001f2002; |
| 2092 | 2092 | i960->AC = 0; |
| 2093 | 2093 | i960->ICR = 0xff000000; |
| r8806 | r8807 | |
| 2097 | 2097 | memset(i960->r, 0, sizeof(i960->r)); |
| 2098 | 2098 | memset(i960->rcache, 0, sizeof(i960->rcache)); |
| 2099 | 2099 | |
| 2100 | i960->r[I960_FP] = | |
| 2100 | i960->r[I960_FP] = | |
| 2101 | 2101 | i960->r[I960_SP] = i960->r[I960_FP] + 64; |
| 2102 | 2102 | i960->rcache_pos = 0; |
| 2103 | 2103 | } |
| r8806 | r8807 | |
|---|---|---|
| 31 | 31 | UINT8 nmi_line; |
| 32 | 32 | device_irq_callback irq_cb; |
| 33 | 33 | legacy_cpu_device *device; |
| 34 | const address_space *program; | |
| 35 | const address_space *io; | |
| 34 | address_space *program; | |
| 35 | address_space *io; | |
| 36 | 36 | UINT32 PPC; |
| 37 | 37 | int icount; |
| 38 | 38 | }; |
| r8806 | r8807 | |
| 109 | 109 | #define SET_NP(val) (cpustate->PSW = (cpustate->PSW & ~0x00020000) | ((val) << 17)) |
| 110 | 110 | #define SET_AE(val) (cpustate->PSW = (cpustate->PSW & ~0x00040000) | ((val) << 18)) |
| 111 | 111 | |
| 112 | #define R_B(cs, addr) (memory_read_byte_32le((cs)->program, addr)) | |
| 113 | #define R_H(cs, addr) (memory_read_word_32le((cs)->program, addr)) | |
| 114 | #define R_W(cs, addr) (memory_read_dword_32le((cs)->program, addr)) | |
| 112 | #define R_B(cs, addr) ((cs)->program->read_byte(addr)) | |
| 113 | #define R_H(cs, addr) ((cs)->program->read_word(addr)) | |
| 114 | #define R_W(cs, addr) ((cs)->program->read_dword(addr)) | |
| 115 | 115 | |
| 116 | 116 | |
| 117 | #define W_B(cs, addr, val) (memory_write_byte_32le((cs)->program, addr,val)) | |
| 118 | #define W_H(cs, addr, val) (memory_write_word_32le((cs)->program, addr,val)) | |
| 119 | #define W_W(cs, addr, val) (memory_write_dword_32le((cs)->program, addr,val)) | |
| 117 | #define W_B(cs, addr, val) ((cs)->program->write_byte(addr,val)) | |
| 118 | #define W_H(cs, addr, val) ((cs)->program->write_word(addr,val)) | |
| 119 | #define W_W(cs, addr, val) ((cs)->program->write_dword(addr,val)) | |
| 120 | 120 | |
| 121 | 121 | |
| 122 | #define RIO_B(cs, addr) (memory_read_byte_32le((cs)->io, addr)) | |
| 123 | #define RIO_H(cs, addr) (memory_read_word_32le((cs)->io, addr)) | |
| 124 | #define RIO_W(cs, addr) (memory_read_dword_32le((cs)->io, addr)) | |
| 122 | #define RIO_B(cs, addr) ((cs)->io->read_byte(addr)) | |
| 123 | #define RIO_H(cs, addr) ((cs)->io->read_word(addr)) | |
| 124 | #define RIO_W(cs, addr) ((cs)->io->read_dword(addr)) | |
| 125 | 125 | |
| 126 | 126 | |
| 127 | #define WIO_B(cs, addr, val) (memory_write_byte_32le((cs)->io, addr,val)) | |
| 128 | #define WIO_H(cs, addr, val) (memory_write_word_32le((cs)->io, addr,val)) | |
| 129 | #define WIO_W(cs, addr, val) (memory_write_dword_32le((cs)->io, addr,val)) | |
| 127 | #define WIO_B(cs, addr, val) ((cs)->io->write_byte(addr,val)) | |
| 128 | #define WIO_H(cs, addr, val) ((cs)->io->write_word(addr,val)) | |
| 129 | #define WIO_W(cs, addr, val) ((cs)->io->write_dword(addr,val)) | |
| 130 | 130 | |
| 131 | 131 | #define R_OP(cs, addr) (memory_decrypted_read_word((cs)->program, addr)) |
| 132 | 132 |
| r8806 | r8807 | |
|---|---|---|
| 127 | 127 | |
| 128 | 128 | #define SET_PC(x) do { cpustate->PC = (x); } while (0) |
| 129 | 129 | |
| 130 | #define P_IN(A) (memory_read_word_16be(cpustate->io, (A)<<1)) | |
| 131 | #define P_OUT(A,V) (memory_write_word_16be(cpustate->io, ((A)<<1),(V))) | |
| 132 | #define S_IN(A) (memory_read_word_16be(cpustate->io, (A)<<1)) | |
| 133 | #define S_OUT(A,V) (memory_write_word_16be(cpustate->io, ((A)<<1),(V))) | |
| 130 | #define P_IN(A) (cpustate->io->read_word((A)<<1)) | |
| 131 | #define P_OUT(A,V) (cpustate->io->write_word(((A)<<1),(V))) | |
| 132 | #define S_IN(A) (cpustate->io->read_word((A)<<1)) | |
| 133 | #define S_OUT(A,V) (cpustate->io->write_word(((A)<<1),(V))) | |
| 134 | 134 | |
| 135 | 135 | #define M_RDOP(A) ((cpustate->pgmmap[(A) >> 7]) ? (cpustate->pgmmap[(A) >> 7][(A) & 0x7f]) : memory_decrypted_read_word(cpustate->program, (A)<<1)) |
| 136 | 136 | #define M_RDOP_ARG(A) ((cpustate->pgmmap[(A) >> 7]) ? (cpustate->pgmmap[(A) >> 7][(A) & 0x7f]) : memory_decrypted_read_word(cpustate->program, (A)<<1)) |
| r8806 | r8807 | |
| 174 | 174 | int waiting_for_serial_frame; |
| 175 | 175 | |
| 176 | 176 | legacy_cpu_device *device; |
| 177 | const address_space *program; | |
| 178 | const address_space *data; | |
| 179 | const address_space *io; | |
| 177 | address_space *program; | |
| 178 | address_space *data; | |
| 179 | address_space *io; | |
| 180 | 180 | |
| 181 | 181 | UINT16 *pgmmap[0x200]; |
| 182 | 182 | UINT16 *datamap[0x200]; |
| r8806 | r8807 | |
| 324 | 324 | addr &= 0xffff; |
| 325 | 325 | ram = cpustate->pgmmap[addr >> 7]; |
| 326 | 326 | if (ram) return ram[addr & 0x7f]; |
| 327 | return | |
| 327 | return | |
| 328 | 328 | } |
| 329 | 329 | |
| 330 | 330 | INLINE void M_WRTROM(tms32025_state *cpustate, offs_t addr, UINT16 data) |
| r8806 | r8807 | |
| 333 | 333 | addr &= 0xffff; |
| 334 | 334 | ram = cpustate->pgmmap[addr >> 7]; |
| 335 | 335 | if (ram) { ram[addr & 0x7f] = data; } |
| 336 | else | |
| 336 | else | |
| 337 | 337 | } |
| 338 | 338 | |
| 339 | 339 | INLINE UINT16 M_RDRAM(tms32025_state *cpustate, offs_t addr) |
| r8806 | r8807 | |
| 342 | 342 | addr &= 0xffff; |
| 343 | 343 | ram = cpustate->datamap[addr >> 7]; |
| 344 | 344 | if (ram) return ram[addr & 0x7f]; |
| 345 | return | |
| 345 | return | |
| 346 | 346 | } |
| 347 | 347 | |
| 348 | 348 | INLINE void M_WRTRAM(tms32025_state *cpustate, offs_t addr, UINT16 data) |
| r8806 | r8807 | |
| 359 | 359 | cpustate->IFR |= 0x20; |
| 360 | 360 | } |
| 361 | 361 | } |
| 362 | else | |
| 362 | else | |
| 363 | 363 | } |
| 364 | 364 | |
| 365 | 365 |
| r8806 | r8807 | |
|---|---|---|
| 159 | 159 | typedef struct _z8_state z8_state; |
| 160 | 160 | struct _z8_state |
| 161 | 161 | { |
| 162 | const address_space *program; | |
| 163 | const address_space *data; | |
| 164 | const address_space *io; | |
| 162 | address_space *program; | |
| 163 | address_space *data; | |
| 164 | address_space *io; | |
| 165 | 165 | |
| 166 | 166 | /* registers */ |
| 167 | 167 | UINT16 pc; /* program counter */ |
| r8806 | r8807 | |
| 233 | 233 | |
| 234 | 234 | if (!(P3M & Z8_P3M_P0_STROBED)) |
| 235 | 235 | { |
| 236 | if (mask) cpustate->input[offset] = | |
| 236 | if (mask) cpustate->input[offset] = | |
| 237 | 237 | } |
| 238 | 238 | |
| 239 | 239 | data |= cpustate->input[offset] & mask; |
| r8806 | r8807 | |
| 249 | 249 | |
| 250 | 250 | if ((P3M & Z8_P3M_P33_P34_MASK) != Z8_P3M_P33_P34_DAV1_RDY1) |
| 251 | 251 | { |
| 252 | if (mask) cpustate->input[offset] = | |
| 252 | if (mask) cpustate->input[offset] = | |
| 253 | 253 | } |
| 254 | 254 | |
| 255 | 255 | data |= cpustate->input[offset] & mask; |
| r8806 | r8807 | |
| 260 | 260 | |
| 261 | 261 | if (!(P3M & Z8_P3M_P2_STROBED)) |
| 262 | 262 | { |
| 263 | if (mask) cpustate->input[offset] = | |
| 263 | if (mask) cpustate->input[offset] = | |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | 266 | data = (cpustate->input[offset] & mask) | (cpustate->output[offset] & ~mask); |
| r8806 | r8807 | |
| 273 | 273 | mask = 0x0f; |
| 274 | 274 | } |
| 275 | 275 | |
| 276 | if (mask) cpustate->input[offset] = | |
| 276 | if (mask) cpustate->input[offset] = | |
| 277 | 277 | |
| 278 | 278 | data = (cpustate->input[offset] & mask) | (cpustate->output[offset] & ~mask); |
| 279 | 279 | break; |
| r8806 | r8807 | |
| 318 | 318 | cpustate->output[offset] = data; |
| 319 | 319 | if ((P01M & Z8_P01M_P0L_MODE_MASK) == Z8_P01M_P0L_MODE_OUTPUT) mask |= 0x0f; |
| 320 | 320 | if ((P01M & Z8_P01M_P0H_MODE_MASK) == Z8_P01M_P0H_MODE_OUTPUT) mask |= 0xf0; |
| 321 | if (mask) | |
| 321 | if (mask) cpustate->io-> | |
| 322 | 322 | break; |
| 323 | 323 | |
| 324 | 324 | case Z8_REGISTER_P1: |
| 325 | 325 | cpustate->output[offset] = data; |
| 326 | 326 | if ((P01M & Z8_P01M_P1_MODE_MASK) == Z8_P01M_P1_MODE_OUTPUT) mask = 0xff; |
| 327 | if (mask) | |
| 327 | if (mask) cpustate->io-> | |
| 328 | 328 | break; |
| 329 | 329 | |
| 330 | 330 | case Z8_REGISTER_P2: |
| 331 | 331 | cpustate->output[offset] = data; |
| 332 | 332 | mask = cpustate->r[Z8_REGISTER_P2M] ^ 0xff; |
| 333 | if (mask) | |
| 333 | if (mask) cpustate->io-> | |
| 334 | 334 | break; |
| 335 | 335 | |
| 336 | 336 | case Z8_REGISTER_P3: |
| r8806 | r8807 | |
| 342 | 342 | mask = 0xf0; |
| 343 | 343 | } |
| 344 | 344 | |
| 345 | if (mask) | |
| 345 | if (mask) cpustate->io-> | |
| 346 | 346 | break; |
| 347 | 347 | |
| 348 | 348 | case Z8_REGISTER_SIO: |
| r8806 | r8807 | |
| 436 | 436 | register_pair_write(cpustate, Z8_REGISTER_SPH, sp); |
| 437 | 437 | |
| 438 | 438 | /* @SP <- src */ |
| 439 | | |
| 439 | | |
| 440 | 440 | } |
| 441 | 441 | } |
| 442 | 442 | |
| r8806 | r8807 | |
| 458 | 458 | register_pair_write(cpustate, Z8_REGISTER_SPH, sp); |
| 459 | 459 | |
| 460 | 460 | /* @SP <- src */ |
| 461 | | |
| 461 | | |
| 462 | 462 | } |
| 463 | 463 | } |
| 464 | 464 | |
| r8806 | r8807 | |
| 480 | 480 | register_pair_write(cpustate, Z8_REGISTER_SPH, sp); |
| 481 | 481 | |
| 482 | 482 | /* @SP <- src */ |
| 483 | return | |
| 483 | return | |
| 484 | 484 | } |
| 485 | 485 | } |
| 486 | 486 | |
| r8806 | r8807 | |
| 502 | 502 | register_pair_write(cpustate, Z8_REGISTER_SPH, sp); |
| 503 | 503 | |
| 504 | 504 | /* @SP <- src */ |
| 505 | return | |
| 505 | return | |
| 506 | 506 | } |
| 507 | 507 | } |
| 508 | 508 | |
| r8806 | r8807 | |
| 694 | 694 | debugger_instruction_hook(device, cpustate->pc); |
| 695 | 695 | |
| 696 | 696 | /* TODO: sample interrupts */ |
| 697 | cpustate->input[3] = | |
| 697 | cpustate->input[3] = | |
| 698 | 698 | |
| 699 | 699 | /* fetch opcode */ |
| 700 | 700 | opcode = fetch(cpustate); |
| r8806 | r8807 | |
|---|---|---|
| 140 | 140 | INSTRUCTION( ld_R1_IM ) { mode_R1_IM(load) } |
| 141 | 141 | INSTRUCTION( ld_IR1_IM ) { mode_IR1_IM(load) } |
| 142 | 142 | |
| 143 | static void load_from_memory(z8_state *cpustate, | |
| 143 | static void load_from_memory(z8_state *cpustate, | |
| 144 | 144 | { |
| 145 | 145 | UINT8 operands = fetch(cpustate); |
| 146 | 146 | UINT8 dst = get_working_register(cpustate, operands >> 4); |
| r8806 | r8807 | |
| 152 | 152 | register_write(cpustate, dst, data); |
| 153 | 153 | } |
| 154 | 154 | |
| 155 | static void load_to_memory(z8_state *cpustate, | |
| 155 | static void load_to_memory(z8_state *cpustate, | |
| 156 | 156 | { |
| 157 | 157 | UINT8 operands = fetch(cpustate); |
| 158 | 158 | UINT8 src = get_working_register(cpustate, operands >> 4); |
| r8806 | r8807 | |
| 161 | 161 | UINT16 address = register_pair_read(cpustate, dst); |
| 162 | 162 | UINT8 data = register_read(cpustate, src); |
| 163 | 163 | |
| 164 | | |
| 164 | | |
| 165 | 165 | } |
| 166 | 166 | |
| 167 | static void load_from_memory_autoinc(z8_state *cpustate, | |
| 167 | static void load_from_memory_autoinc(z8_state *cpustate, | |
| 168 | 168 | { |
| 169 | 169 | UINT8 operands = fetch(cpustate); |
| 170 | 170 | UINT8 dst = get_working_register(cpustate, operands >> 4); |
| r8806 | r8807 | |
| 180 | 180 | register_pair_write(cpustate, src, address + 1); |
| 181 | 181 | } |
| 182 | 182 | |
| 183 | static void load_to_memory_autoinc(z8_state *cpustate, | |
| 183 | static void load_to_memory_autoinc(z8_state *cpustate, | |
| 184 | 184 | { |
| 185 | 185 | UINT8 operands = fetch(cpustate); |
| 186 | 186 | UINT8 src = get_working_register(cpustate, operands >> 4); |
| r8806 | r8807 | |
| 190 | 190 | UINT16 address = register_pair_read(cpustate, dst); |
| 191 | 191 | UINT8 data = register_read(cpustate, real_src); |
| 192 | 192 | |
| 193 | | |
| 193 | | |
| 194 | 194 | |
| 195 | 195 | register_pair_write(cpustate, dst, address + 1); |
| 196 | 196 | register_write(cpustate, src, real_src + 1); |
| r8806 | r8807 | |
|---|---|---|
| 98 | 98 | |
| 99 | 99 | |
| 100 | 100 | legacy_cpu_device *device; |
| 101 | const address_space *program; | |
| 102 | const address_space *data; | |
| 103 | const address_space *io; | |
| 101 | address_space *program; | |
| 102 | address_space *data; | |
| 103 | address_space *io; | |
| 104 | 104 | }; |
| 105 | 105 | |
| 106 | 106 | INLINE pic16c5x_state *get_safe_token(running_device *device) |
| r8806 | r8807 | |
| 133 | 133 | |
| 134 | 134 | |
| 135 | 135 | #define PIC16C5x_RDOP(A) (memory_decrypted_read_word(cpustate->program, (A)<<1)) |
| 136 | #define PIC16C5x_RAM_RDMEM(A) ((UINT8)memory_read_byte_8le(cpustate->data, A)) | |
| 137 | #define PIC16C5x_RAM_WRMEM(A,V) (memory_write_byte_8le(cpustate->data, A,V)) | |
| 138 | #define PIC16C5x_In(Port) ((UINT8)memory_read_byte_8le(cpustate->io, (Port))) | |
| 139 | #define PIC16C5x_Out(Port,Value) (memory_write_byte_8le(cpustate->io, (Port),Value)) | |
| 136 | #define PIC16C5x_RAM_RDMEM(A) ((UINT8)cpustate->data->read_byte(A)) | |
| 137 | #define PIC16C5x_RAM_WRMEM(A,V) (cpustate->data->write_byte(A,V)) | |
| 138 | #define PIC16C5x_In(Port) ((UINT8)cpustate->io->read_byte((Port))) | |
| 139 | #define PIC16C5x_Out(Port,Value) (cpustate->io->write_byte((Port),Value)) | |
| 140 | 140 | /************ Read the state of the T0 Clock input signal ************/ |
| 141 | #define PIC16C5x_T0_In ( | |
| 141 | #define PIC16C5x_T0_In ( | |
| 142 | 142 | |
| 143 | 143 | #define M_RDRAM(A) (((A) < 8) ? cpustate->internalram[A] : PIC16C5x_RAM_RDMEM(A)) |
| 144 | 144 | #define M_WRTRAM(A,V) do { if ((A) < 8) cpustate->internalram[A] = (V); else PIC16C5x_RAM_WRMEM(A,V); } while (0) |
| r8806 | r8807 | |
|---|---|---|
| 343 | 343 | #define LOG_EXTRA 0 |
| 344 | 344 | #define LOG_IOT_EXTRA 0 |
| 345 | 345 | |
| 346 | #define READ_PDP_18BIT(A) ((signed)memory_read_dword_32be(cpustate->program, (A)<<2)) | |
| 347 | #define WRITE_PDP_18BIT(A,V) (memory_write_dword_32be(cpustate->program, (A)<<2,(V))) | |
| 346 | #define READ_PDP_18BIT(A) ((signed)cpustate->program->read_dword((A)<<2)) | |
| 347 | #define WRITE_PDP_18BIT(A,V) (cpustate->program->write_dword((A)<<2,(V))) | |
| 348 | 348 | |
| 349 | 349 | |
| 350 | 350 | /* PDP1 Registers */ |
| r8806 | r8807 | |
| 418 | 418 | int type_20_sbs; |
| 419 | 419 | |
| 420 | 420 | legacy_cpu_device *device; |
| 421 | | |
| 421 | | |
| 422 | 422 | int icount; |
| 423 | 423 | }; |
| 424 | 424 |
| r8806 | r8807 | |
|---|---|---|
| 65 | 65 | int icount; |
| 66 | 66 | |
| 67 | 67 | legacy_cpu_device *device; |
| 68 | | |
| 68 | | |
| 69 | 69 | }; |
| 70 | 70 | |
| 71 | 71 | INLINE tx0_state *get_safe_token(running_device *device) |
| r8806 | r8807 | |
| 76 | 76 | return (tx0_state *)downcast<legacy_cpu_device *>(device)->token(); |
| 77 | 77 | } |
| 78 | 78 | |
| 79 | #define READ_TX0_18BIT(A) ((signed)memory_read_dword_32be(cpustate->program, (A)<<2)) | |
| 80 | #define WRITE_TX0_18BIT(A,V) (memory_write_dword_32be(cpustate->program, (A)<<2,(V))) | |
| 79 | #define READ_TX0_18BIT(A) ((signed)cpustate->program->read_dword((A)<<2)) | |
| 80 | #define WRITE_TX0_18BIT(A,V) (cpustate->program->write_dword((A)<<2,(V))) | |
| 81 | 81 | |
| 82 | 82 | |
| 83 | 83 | #define io_handler_rim 3 |
| r8806 | r8807 | |
|---|---|---|
| 51 | 51 | UINT32 extport[0x30]; |
| 52 | 52 | |
| 53 | 53 | legacy_cpu_device *device; |
| 54 | | |
| 54 | | |
| 55 | 55 | int icount; |
| 56 | 56 | |
| 57 | 57 | /* FIFO */ |
| r8806 | r8807 | |
| 96 | 96 | #define GETREPCNT() cpustate->repcnt |
| 97 | 97 | |
| 98 | 98 | #define ROPCODE(a) memory_decrypted_read_dword(cpustate->program, a<<2) |
| 99 | #define RDMEM(a) memory_read_dword_32le(cpustate->program, (a<<2)) | |
| 100 | #define WRMEM(a,v) memory_write_dword_32le(cpustate->program, (a<<2), v) | |
| 99 | #define RDMEM(a) cpustate->program->read_dword((a<<2)) | |
| 100 | #define WRMEM(a,v) cpustate->program->write_dword((a<<2), v) | |
| 101 | 101 | |
| 102 | 102 | /*************************************************************************** |
| 103 | 103 | Initialization and Shutdown |
| r8806 | r8807 | |
|---|---|---|
| 34 | 34 | int icount; |
| 35 | 35 | device_irq_callback irq_callback; |
| 36 | 36 | legacy_cpu_device * device; |
| 37 | | |
| 37 | | |
| 38 | 38 | }; |
| 39 | 39 | |
| 40 | 40 | |
| r8806 | r8807 | |
| 82 | 82 | |
| 83 | 83 | INLINE int RBYTE(t11_state *cpustate, int addr) |
| 84 | 84 | { |
| 85 | return | |
| 85 | return | |
| 86 | 86 | } |
| 87 | 87 | |
| 88 | 88 | |
| 89 | 89 | INLINE void WBYTE(t11_state *cpustate, int addr, int data) |
| 90 | 90 | { |
| 91 | | |
| 91 | | |
| 92 | 92 | } |
| 93 | 93 | |
| 94 | 94 | |
| 95 | 95 | INLINE int RWORD(t11_state *cpustate, int addr) |
| 96 | 96 | { |
| 97 | return | |
| 97 | return | |
| 98 | 98 | } |
| 99 | 99 | |
| 100 | 100 | |
| 101 | 101 | INLINE void WWORD(t11_state *cpustate, int addr, int data) |
| 102 | 102 | { |
| 103 | | |
| 103 | | |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | 106 |
| r8806 | r8807 | |
|---|---|---|
| 136 | 136 | |
| 137 | 137 | addr &= ~3; |
| 138 | 138 | if ( cpustate->endian == ENDIANNESS_BIG ) |
| 139 | | |
| 139 | | |
| 140 | 140 | else |
| 141 | | |
| 141 | | |
| 142 | 142 | } |
| 143 | 143 | |
| 144 | 144 | |
| r8806 | r8807 | |
| 151 | 151 | |
| 152 | 152 | addr &= ~1; |
| 153 | 153 | if ( cpustate->endian == ENDIANNESS_BIG ) |
| 154 | | |
| 154 | | |
| 155 | 155 | else |
| 156 | | |
| 156 | | |
| 157 | 157 | } |
| 158 | 158 | |
| 159 | 159 | INLINE void arm7_cpu_write8(arm_state *cpustate, UINT32 addr, UINT8 data) |
| r8806 | r8807 | |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | 166 | if ( cpustate->endian == ENDIANNESS_BIG ) |
| 167 | | |
| 167 | | |
| 168 | 168 | else |
| 169 | | |
| 169 | | |
| 170 | 170 | } |
| 171 | 171 | |
| 172 | 172 | INLINE UINT32 arm7_cpu_read32(arm_state *cpustate, offs_t addr) |
| r8806 | r8807 | |
| 181 | 181 | if (addr & 3) |
| 182 | 182 | { |
| 183 | 183 | if ( cpustate->endian == ENDIANNESS_BIG ) |
| 184 | result = | |
| 184 | result = | |
| 185 | 185 | else |
| 186 | result = | |
| 186 | result = | |
| 187 | 187 | result = (result >> (8 * (addr & 3))) | (result << (32 - (8 * (addr & 3)))); |
| 188 | 188 | } |
| 189 | 189 | else |
| 190 | 190 | { |
| 191 | 191 | if ( cpustate->endian == ENDIANNESS_BIG ) |
| 192 | result = | |
| 192 | result = | |
| 193 | 193 | else |
| 194 | result = | |
| 194 | result = | |
| 195 | 195 | } |
| 196 | 196 | |
| 197 | 197 | return result; |
| r8806 | r8807 | |
| 207 | 207 | } |
| 208 | 208 | |
| 209 | 209 | if ( cpustate->endian == ENDIANNESS_BIG ) |
| 210 | result = | |
| 210 | result = | |
| 211 | 211 | else |
| 212 | result = | |
| 212 | result = | |
| 213 | 213 | |
| 214 | 214 | if (addr & 1) |
| 215 | 215 | { |
| r8806 | r8807 | |
| 228 | 228 | |
| 229 | 229 | // Handle through normal 8 bit handler (for 32 bit cpu) |
| 230 | 230 | if ( cpustate->endian == ENDIANNESS_BIG ) |
| 231 | return | |
| 231 | return | |
| 232 | 232 | else |
| 233 | return | |
| 233 | return | |
| 234 | 234 | } |
| 235 | 235 | |
| 236 | 236 | /*************** |
| r8806 | r8807 | |
|---|---|---|
| 163 | 163 | endianness_t endian; \ |
| 164 | 164 | device_irq_callback irq_callback; \ |
| 165 | 165 | legacy_cpu_device *device; \ |
| 166 | | |
| 166 | | |
| 167 | 167 | |
| 168 | 168 | |
| 169 | 169 | /* CPU state struct */ |
| r8806 | r8807 | |
|---|---|---|
| 104 | 104 | INLINE UINT32 arm7_tlb_get_first_level_descriptor( arm_state *cpustate, UINT32 vaddr ) |
| 105 | 105 | { |
| 106 | 106 | UINT32 entry_paddr = ( COPRO_TLB_BASE & COPRO_TLB_BASE_MASK ) | ( ( vaddr & COPRO_TLB_VADDR_FLTI_MASK ) >> COPRO_TLB_VADDR_FLTI_MASK_SHIFT ); |
| 107 | return | |
| 107 | return | |
| 108 | 108 | } |
| 109 | 109 | |
| 110 | 110 | INLINE UINT32 arm7_tlb_get_second_level_descriptor( arm_state *cpustate, UINT32 granularity, UINT32 first_desc, UINT32 vaddr ) |
| r8806 | r8807 | |
| 125 | 125 | break; |
| 126 | 126 | } |
| 127 | 127 | |
| 128 | return | |
| 128 | return | |
| 129 | 129 | } |
| 130 | 130 | |
| 131 | 131 | INLINE UINT32 arm7_tlb_translate(arm_state *cpustate, UINT32 vaddr) |
| r8806 | r8807 | |
| 550 | 550 | case CPUINFO_STR_REGISTER + ARM7_FR12: sprintf(info->s, "FR12:%08x", ARM7REG(eR12_FIQ) ); break; |
| 551 | 551 | case CPUINFO_STR_REGISTER + ARM7_FR13: sprintf(info->s, "FR13:%08x", ARM7REG(eR13_FIQ) ); break; |
| 552 | 552 | case CPUINFO_STR_REGISTER + ARM7_FR14: sprintf(info->s, "FR14:%08x", ARM7REG(eR14_FIQ) ); break; |
| 553 | case CPUINFO_STR_REGISTER + ARM7_FSPSR: sprintf(info->s, "F | |
| 553 | case CPUINFO_STR_REGISTER + ARM7_FSPSR: sprintf(info->s, "F | |
| 554 | 554 | |
| 555 | 555 | /* IRQ Mode Shadowed Registers */ |
| 556 | 556 | case CPUINFO_STR_REGISTER + ARM7_IR13: sprintf(info->s, "IR13:%08x", ARM7REG(eR13_IRQ) ); break; |
| 557 | 557 | case CPUINFO_STR_REGISTER + ARM7_IR14: sprintf(info->s, "IR14:%08x", ARM7REG(eR14_IRQ) ); break; |
| 558 | case CPUINFO_STR_REGISTER + ARM7_ISPSR: sprintf(info->s, " | |
| 558 | case CPUINFO_STR_REGISTER + ARM7_ISPSR: sprintf(info->s, "I | |
| 559 | 559 | |
| 560 | 560 | /* Supervisor Mode Shadowed Registers */ |
| 561 | 561 | case CPUINFO_STR_REGISTER + ARM7_SR13: sprintf(info->s, "SR13:%08x", ARM7REG(eR13_SVC) ); break; |
| 562 | 562 | case CPUINFO_STR_REGISTER + ARM7_SR14: sprintf(info->s, "SR14:%08x", ARM7REG(eR14_SVC) ); break; |
| 563 | case CPUINFO_STR_REGISTER + ARM7_SSPSR: sprintf(info->s, "S | |
| 563 | case CPUINFO_STR_REGISTER + ARM7_SSPSR: sprintf(info->s, "S | |
| 564 | 564 | |
| 565 | 565 | /* Abort Mode Shadowed Registers */ |
| 566 | 566 | case CPUINFO_STR_REGISTER + ARM7_AR13: sprintf(info->s, "AR13:%08x", ARM7REG(eR13_ABT) ); break; |
| 567 | 567 | case CPUINFO_STR_REGISTER + ARM7_AR14: sprintf(info->s, "AR14:%08x", ARM7REG(eR14_ABT) ); break; |
| 568 | case CPUINFO_STR_REGISTER + ARM7_ASPSR: sprintf(info->s, "A | |
| 568 | case CPUINFO_STR_REGISTER + ARM7_ASPSR: sprintf(info->s, "A | |
| 569 | 569 | |
| 570 | 570 | /* Undefined Mode Shadowed Registers */ |
| 571 | 571 | case CPUINFO_STR_REGISTER + ARM7_UR13: sprintf(info->s, "UR13:%08x", ARM7REG(eR13_UND) ); break; |
| 572 | 572 | case CPUINFO_STR_REGISTER + ARM7_UR14: sprintf(info->s, "UR14:%08x", ARM7REG(eR14_UND) ); break; |
| 573 | case CPUINFO_STR_REGISTER + ARM7_USPSR: sprintf(info->s, "U | |
| 573 | case CPUINFO_STR_REGISTER + ARM7_USPSR: sprintf(info->s, "U | |
| 574 | 574 | } |
| 575 | 575 | } |
| 576 | 576 |
| r8806 | r8807 | |
|---|---|---|
| 178 | 178 | UINT32 * last_upper_addr; /* address where we last stored an upper register */ |
| 179 | 179 | double fptemp; /* temporary storage for floating point */ |
| 180 | 180 | |
| 181 | const address_space * space[ADDRESS_SPACES]; /* address spaces */ | |
| 181 | data_accessors accessors[ADDRESS_SPACES]; /* memory accessors */ | |
| 182 | address_space * space[ADDRESS_SPACES]; /* address spaces */ | |
| 182 | 183 | |
| 183 | 184 | UINT8 sse3; /* do we have SSE3 support? */ |
| 184 | 185 | UINT16 fpumode; /* saved FPU mode */ |
| r8806 | r8807 | |
| 629 | 630 | drcbe->drcuml = drcuml; |
| 630 | 631 | drcbe->cache = cache; |
| 631 | 632 | |
| 632 | /* get address spaces */ | |
| 633 | /* get address spaces and accessors */ | |
| 633 | 634 | for (spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++) |
| 635 | { | |
| 634 | 636 | drcbe->space[spacenum] = downcast<cpu_device *>(device)->space(spacenum); |
| 637 | if (drcbe->space[spacenum] != NULL) | |
| 638 | drcbe->space[spacenum]->accessors(drcbe->accessors[spacenum]); | |
| 639 | } | |
| 635 | 640 | |
| 636 | 641 | /* allocate hash tables */ |
| 637 | 642 | drcbe->hash = drchash_alloc(cache, modes, addrbits, ignorebits); |
| r8806 | r8807 | |
| 4262 | 4267 | emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (UINT32)drcbe->space[spacesizep.value / 16]);// mov [esp],space |
| 4263 | 4268 | if ((spacesizep.value & 3) == DRCUML_SIZE_BYTE) |
| 4264 | 4269 | { |
| 4265 | emit_call(&dst, (x86code *)drcbe-> | |
| 4270 | emit_call(&dst, (x86code *)drcbe-> | |
| 4266 | 4271 | // call read_byte |
| 4267 | 4272 | emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al |
| 4268 | 4273 | } |
| 4269 | 4274 | else if ((spacesizep.value & 3) == DRCUML_SIZE_WORD) |
| 4270 | 4275 | { |
| 4271 | emit_call(&dst, (x86code *)drcbe-> | |
| 4276 | emit_call(&dst, (x86code *)drcbe-> | |
| 4272 | 4277 | // call read_word |
| 4273 | 4278 | emit_movzx_r32_r16(&dst, dstreg, REG_AX); // movzx dstreg,ax |
| 4274 | 4279 | } |
| 4275 | 4280 | else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD) |
| 4276 | 4281 | { |
| 4277 | emit_call(&dst, (x86code *)drcbe-> | |
| 4282 | emit_call(&dst, (x86code *)drcbe-> | |
| 4278 | 4283 | // call read_dword |
| 4279 | 4284 | emit_mov_r32_r32(&dst, dstreg, REG_EAX); // mov dstreg,eax |
| 4280 | 4285 | } |
| 4281 | 4286 | else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD) |
| 4282 | 4287 | { |
| 4283 | emit_call(&dst, (x86code *)drcbe-> | |
| 4288 | emit_call(&dst, (x86code *)drcbe-> | |
| 4284 | 4289 | // call read_qword |
| 4285 | 4290 | emit_mov_r32_r32(&dst, dstreg, REG_EAX); // mov dstreg,eax |
| 4286 | 4291 | } |
| r8806 | r8807 | |
| 4342 | 4347 | emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (UINT32)drcbe->space[spacesizep.value / 16]);// mov [esp],space |
| 4343 | 4348 | if ((spacesizep.value & 3) == DRCUML_SIZE_WORD) |
| 4344 | 4349 | { |
| 4345 | emit_call(&dst, (x86code *)drcbe-> | |
| 4350 | emit_call(&dst, (x86code *)drcbe-> | |
| 4346 | 4351 | // call read_word_masked |
| 4347 | 4352 | emit_movzx_r32_r16(&dst, dstreg, REG_AX); // movzx dstreg,ax |
| 4348 | 4353 | } |
| 4349 | 4354 | else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD) |
| 4350 | 4355 | { |
| 4351 | emit_call(&dst, (x86code *)drcbe-> | |
| 4356 | emit_call(&dst, (x86code *)drcbe-> | |
| 4352 | 4357 | // call read_dword_masked |
| 4353 | 4358 | emit_mov_r32_r32(&dst, dstreg, REG_EAX); // mov dstreg,eax |
| 4354 | 4359 | } |
| 4355 | 4360 | else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD) |
| 4356 | 4361 | { |
| 4357 | emit_call(&dst, (x86code *)drcbe-> | |
| 4362 | emit_call(&dst, (x86code *)drcbe-> | |
| 4358 | 4363 | // call read_qword_masked |
| 4359 | 4364 | emit_mov_r32_r32(&dst, dstreg, REG_EAX); // mov dstreg,eax |
| 4360 | 4365 | } |
| r8806 | r8807 | |
| 4411 | 4416 | emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 4), &addrp); // mov [esp+4],addrp |
| 4412 | 4417 | emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (UINT32)drcbe->space[spacesizep.value / 16]);// mov [esp],space |
| 4413 | 4418 | if ((spacesizep.value & 3) == DRCUML_SIZE_BYTE) |
| 4414 | emit_call(&dst, (x86code *)drcbe-> | |
| 4419 | emit_call(&dst, (x86code *)drcbe-> | |
| 4415 | 4420 | // call write_byte |
| 4416 | 4421 | else if ((spacesizep.value & 3) == DRCUML_SIZE_WORD) |
| 4417 | emit_call(&dst, (x86code *)drcbe-> | |
| 4422 | emit_call(&dst, (x86code *)drcbe-> | |
| 4418 | 4423 | // call write_word |
| 4419 | 4424 | else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD) |
| 4420 | emit_call(&dst, (x86code *)drcbe-> | |
| 4425 | emit_call(&dst, (x86code *)drcbe-> | |
| 4421 | 4426 | // call write_dword |
| 4422 | 4427 | else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD) |
| 4423 | emit_call(&dst, (x86code *)drcbe-> | |
| 4428 | emit_call(&dst, (x86code *)drcbe-> | |
| 4424 | 4429 | // call write_qword |
| 4425 | 4430 | return dst; |
| 4426 | 4431 | } |
| r8806 | r8807 | |
| 4456 | 4461 | emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 4), &addrp); // mov [esp+4],addrp |
| 4457 | 4462 | emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (UINT32)drcbe->space[spacesizep.value / 16]);// mov [esp],space |
| 4458 | 4463 | if ((spacesizep.value & 3) == DRCUML_SIZE_WORD) |
| 4459 | emit_call(&dst, (x86code *)drcbe-> | |
| 4464 | emit_call(&dst, (x86code *)drcbe-> | |
| 4460 | 4465 | // call write_word_masked |
| 4461 | 4466 | else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD) |
| 4462 | emit_call(&dst, (x86code *)drcbe-> | |
| 4467 | emit_call(&dst, (x86code *)drcbe-> | |
| 4463 | 4468 | // call write_dword_masked |
| 4464 | 4469 | else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD) |
| 4465 | emit_call(&dst, (x86code *)drcbe-> | |
| 4470 | emit_call(&dst, (x86code *)drcbe-> | |
| 4466 | 4471 | // call write_qword_masked |
| 4467 | 4472 | return dst; |
| 4468 | 4473 | } |
| r8806 | r8807 | |
| 6411 | 6416 | emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 4), &addrp); // mov [esp+4],addrp |
| 6412 | 6417 | emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (UINT32)drcbe->space[spacep.value]); // mov [esp],space |
| 6413 | 6418 | if (inst->size == 4) |
| 6414 | emit_call(&dst, (x86code *)drcbe-> | |
| 6419 | emit_call(&dst, (x86code *)drcbe-> | |
| 6415 | 6420 | else if (inst->size == 8) |
| 6416 | emit_call(&dst, (x86code *)drcbe-> | |
| 6421 | emit_call(&dst, (x86code *)drcbe-> | |
| 6417 | 6422 | |
| 6418 | 6423 | /* store result */ |
| 6419 | 6424 | if (inst->size == 4) |
| r8806 | r8807 | |
| 6449 | 6454 | emit_mov_m32_p32(drcbe, &dst, MBD(REG_ESP, 4), &addrp); // mov [esp+4],addrp |
| 6450 | 6455 | emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (UINT32)drcbe->space[spacep.value]); // mov [esp],space |
| 6451 | 6456 | if (inst->size == 4) |
| 6452 | emit_call(&dst, (x86code *)drcbe-> | |
| 6457 | emit_call(&dst, (x86code *)drcbe-> | |
| 6453 | 6458 | else if (inst->size == 8) |
| 6454 | emit_call(&dst, (x86code *)drcbe-> | |
| 6459 | emit_call(&dst, (x86code *)drcbe-> | |
| 6455 | 6460 | |
| 6456 | 6461 | return dst; |
| 6457 | 6462 | } |
| r8806 | r8807 | |
|---|---|---|
| 125 | 125 | ***************************************************************/ |
| 126 | 126 | INLINE UINT8 RDMEM(h6280_Regs* cpustate, offs_t addr) { |
| 127 | 127 | CHECK_VDC_VCE_PENALTY(addr); |
| 128 | return | |
| 128 | return | |
| 129 | 129 | } |
| 130 | 130 | |
| 131 | 131 | /*************************************************************** |
| r8806 | r8807 | |
| 133 | 133 | ***************************************************************/ |
| 134 | 134 | INLINE void WRMEM(h6280_Regs* cpustate, offs_t addr, UINT8 data) { |
| 135 | 135 | CHECK_VDC_VCE_PENALTY(addr); |
| 136 | | |
| 136 | | |
| 137 | 137 | } |
| 138 | 138 | |
| 139 | 139 | /*************************************************************** |
| 140 | 140 | * RDMEMZ read memory - zero page |
| 141 | 141 | ***************************************************************/ |
| 142 | 142 | #define RDMEMZ(addr) \ |
| 143 | | |
| 143 | | |
| 144 | 144 | |
| 145 | 145 | /*************************************************************** |
| 146 | 146 | * WRMEMZ write memory - zero page |
| 147 | 147 | ***************************************************************/ |
| 148 | 148 | #define WRMEMZ(addr,data) \ |
| 149 | | |
| 149 | | |
| 150 | 150 | |
| 151 | 151 | /*************************************************************** |
| 152 | 152 | * RDMEMW read word from memory |
| 153 | 153 | ***************************************************************/ |
| 154 | 154 | #define RDMEMW(addr) \ |
| 155 | memory_read_byte_8le(cpustate->program, TRANSLATED(addr)) \ | |
| 156 | | ( memory_read_byte_8le(cpustate->program, TRANSLATED(addr+1)) << 8 ) | |
| 155 | cpustate->program->read_byte(TRANSLATED(addr)) \ | |
| 156 | | ( cpustate->program->read_byte(TRANSLATED(addr+1)) << 8 ) | |
| 157 | 157 | |
| 158 | 158 | /*************************************************************** |
| 159 | 159 | * RDZPWORD read a word from a zero page address |
| 160 | 160 | ***************************************************************/ |
| 161 | 161 | #define RDZPWORD(addr) \ |
| 162 | 162 | ((addr&0xff)==0xff) ? \ |
| 163 | memory_read_byte_8le(cpustate->program, (cpustate->mmr[1] << 13) | ((addr)&0x1fff)) \ | |
| 164 | +(memory_read_byte_8le(cpustate->program, (cpustate->mmr[1] << 13) | ((addr-0xff)&0x1fff))<<8) : \ | |
| 165 | memory_read_byte_8le(cpustate->program, (cpustate->mmr[1] << 13) | ((addr)&0x1fff)) \ | |
| 166 | +(memory_read_byte_8le(cpustate->program, (cpustate->mmr[1] << 13) | ((addr+1)&0x1fff))<<8) | |
| 163 | cpustate->program->read_byte((cpustate->mmr[1] << 13) | ((addr)&0x1fff)) \ | |
| 164 | +(cpustate->program->read_byte((cpustate->mmr[1] << 13) | ((addr-0xff)&0x1fff))<<8) : \ | |
| 165 | cpustate->program->read_byte((cpustate->mmr[1] << 13) | ((addr)&0x1fff)) \ | |
| 166 | +(cpustate->program->read_byte((cpustate->mmr[1] << 13) | ((addr+1)&0x1fff))<<8) | |
| 167 | 167 | |
| 168 | 168 | |
| 169 | 169 | /*************************************************************** |
| 170 | 170 | * push a register onto the stack |
| 171 | 171 | ***************************************************************/ |
| 172 | #define PUSH(Rg) | |
| 172 | #define PUSH(Rg) | |
| 173 | 173 | |
| 174 | 174 | /*************************************************************** |
| 175 | 175 | * pull a register from the stack |
| 176 | 176 | ***************************************************************/ |
| 177 | #define PULL(Rg) S++; Rg = | |
| 177 | #define PULL(Rg) S++; Rg = | |
| 178 | 178 | |
| 179 | 179 | /*************************************************************** |
| 180 | 180 | * RDOP read an opcode |
| r8806 | r8807 | |
| 1111 | 1111 | ***************************************************************/ |
| 1112 | 1112 | #define ST0 \ |
| 1113 | 1113 | CLEAR_T; \ |
| 1114 | | |
| 1114 | cpustate->io-> | |
| 1115 | 1115 | |
| 1116 | 1116 | /* 6280 ******************************************************** |
| 1117 | 1117 | * ST1 Store at hardware address 2 |
| 1118 | 1118 | ***************************************************************/ |
| 1119 | 1119 | #define ST1 \ |
| 1120 | 1120 | CLEAR_T; \ |
| 1121 | | |
| 1121 | cpustate->io-> | |
| 1122 | 1122 | |
| 1123 | 1123 | /* 6280 ******************************************************** |
| 1124 | 1124 | * ST2 Store at hardware address 3 |
| 1125 | 1125 | ***************************************************************/ |
| 1126 | 1126 | #define ST2 \ |
| 1127 | 1127 | CLEAR_T; \ |
| 1128 | | |
| 1128 | cpustate->io-> | |
| 1129 | 1129 | |
| 1130 | 1130 | /* 6280 ******************************************************** |
| 1131 | 1131 | * STA Store accumulator |
| r8806 | r8807 | |
|---|---|---|
| 62 | 62 | UINT8 irq_pending; |
| 63 | 63 | device_irq_callback irq_callback; |
| 64 | 64 | legacy_cpu_device *device; |
| 65 | const address_space *program; | |
| 66 | const address_space *io; | |
| 65 | address_space *program; | |
| 66 | address_space *io; | |
| 67 | 67 | |
| 68 | 68 | #if LAZY_FLAGS |
| 69 | 69 | INT32 NZ; /* last value (lazy N and Z flag) */ |
| r8806 | r8807 | |
|---|---|---|
| 116 | 116 | legacy_cpu_device *device; |
| 117 | 117 | |
| 118 | 118 | /* Memory spaces */ |
| 119 | const address_space *program; | |
| 120 | const address_space *data; | |
| 121 | const address_space *io; | |
| 119 | address_space *program; | |
| 120 | address_space *data; | |
| 121 | address_space *io; | |
| 122 | 122 | |
| 123 | 123 | void (* const * insn)(m6800_state *); /* instruction table */ |
| 124 | 124 | const UINT8 *cycles; /* clock cycle of instruction table */ |
| r8806 | r8807 | |
| 206 | 206 | /****************************************************************************/ |
| 207 | 207 | /* Read a byte from given memory location */ |
| 208 | 208 | /****************************************************************************/ |
| 209 | #define RM(Addr) ((unsigned) | |
| 209 | #define RM(Addr) ((unsigned) | |
| 210 | 210 | |
| 211 | 211 | /****************************************************************************/ |
| 212 | 212 | /* Write a byte to given memory location */ |
| 213 | 213 | /****************************************************************************/ |
| 214 | #define WM(Addr,Value) ( | |
| 214 | #define WM(Addr,Value) ( | |
| 215 | 215 | |
| 216 | 216 | /****************************************************************************/ |
| 217 | 217 | /* M6800_RDOP() is identical to M6800_RDMEM() except it is used for reading */ |
| r8806 | r8807 | |
| 675 | 675 | cpustate->port2_data = (cpustate->port2_data & 0xef) | (value << 4); |
| 676 | 676 | |
| 677 | 677 | if(cpustate->port2_ddr == 0xff) |
| 678 | | |
| 678 | cpustate->io-> | |
| 679 | 679 | else |
| 680 | memory_write_byte_8be(cpustate->io, M6803_PORT2,(cpustate->port2_data & cpustate->port2_ddr) | |
| 681 | | (memory_read_byte_8be(cpustate->io, M6803_PORT2) & (cpustate->port2_ddr ^ 0xff))); | |
| 680 | cpustate->io->write_byte(M6803_PORT2,(cpustate->port2_data & cpustate->port2_ddr) | |
| 681 | | (cpustate->io->read_byte(M6803_PORT2) & (cpustate->port2_ddr ^ 0xff))); | |
| 682 | 682 | } |
| 683 | 683 | |
| 684 | 684 | static int m6800_rx(m6800_state *cpustate) |
| 685 | 685 | { |
| 686 | return ( | |
| 686 | return ( | |
| 687 | 687 | } |
| 688 | 688 | |
| 689 | 689 | static TIMER_CALLBACK(m6800_tx_tick) |
| r8806 | r8807 | |
| 2360 | 2360 | case 0x01: |
| 2361 | 2361 | return cpustate->port2_ddr; |
| 2362 | 2362 | case 0x02: |
| 2363 | return ( | |
| 2363 | return ( | |
| 2364 | 2364 | | (cpustate->port1_data & cpustate->port1_ddr); |
| 2365 | 2365 | case 0x03: |
| 2366 | return ( | |
| 2366 | return ( | |
| 2367 | 2367 | | (cpustate->port2_data & cpustate->port2_ddr); |
| 2368 | 2368 | case 0x04: |
| 2369 | 2369 | return cpustate->port3_ddr; |
| 2370 | 2370 | case 0x05: |
| 2371 | 2371 | return cpustate->port4_ddr; |
| 2372 | 2372 | case 0x06: |
| 2373 | return ( | |
| 2373 | return ( | |
| 2374 | 2374 | | (cpustate->port3_data & cpustate->port3_ddr); |
| 2375 | 2375 | case 0x07: |
| 2376 | return ( | |
| 2376 | return ( | |
| 2377 | 2377 | | (cpustate->port4_data & cpustate->port4_ddr); |
| 2378 | 2378 | case 0x08: |
| 2379 | 2379 | cpustate->pending_tcsr = 0; |
| r8806 | r8807 | |
| 2458 | 2458 | { |
| 2459 | 2459 | cpustate->port1_ddr = data; |
| 2460 | 2460 | if(cpustate->port1_ddr == 0xff) |
| 2461 | | |
| 2461 | cpustate->io-> | |
| 2462 | 2462 | else |
| 2463 | memory_write_byte_8be(cpustate->io, M6803_PORT1,(cpustate->port1_data & cpustate->port1_ddr) | |
| 2464 | | (memory_read_byte_8be(cpustate->io, M6803_PORT1) & (cpustate->port1_ddr ^ 0xff))); | |
| 2463 | cpustate->io->write_byte(M6803_PORT1,(cpustate->port1_data & cpustate->port1_ddr) | |
| 2464 | | (cpustate->io->read_byte(M6803_PORT1) & (cpustate->port1_ddr ^ 0xff))); | |
| 2465 | 2465 | } |
| 2466 | 2466 | break; |
| 2467 | 2467 | case 0x01: |
| r8806 | r8807 | |
| 2469 | 2469 | { |
| 2470 | 2470 | cpustate->port2_ddr = data; |
| 2471 | 2471 | if(cpustate->port2_ddr == 0xff) |
| 2472 | | |
| 2472 | cpustate->io-> | |
| 2473 | 2473 | else |
| 2474 | memory_write_byte_8be(cpustate->io, M6803_PORT2,(cpustate->port2_data & cpustate->port2_ddr) | |
| 2475 | | (memory_read_byte_8be(cpustate->io, M6803_PORT2) & (cpustate->port2_ddr ^ 0xff))); | |
| 2474 | cpustate->io->write_byte(M6803_PORT2,(cpustate->port2_data & cpustate->port2_ddr) | |
| 2475 | | (cpustate->io->read_byte(M6803_PORT2) & (cpustate->port2_ddr ^ 0xff))); | |
| 2476 | 2476 | |
| 2477 | 2477 | if (cpustate->port2_ddr & 2) |
| 2478 | 2478 | logerror("CPU '%s' PC %04x: warning - port 2 bit 1 set as output (OLVL) - not supported\n",space->cpu->tag(),cpu_get_pc(space->cpu)); |
| r8806 | r8807 | |
| 2481 | 2481 | case 0x02: |
| 2482 | 2482 | cpustate->port1_data = data; |
| 2483 | 2483 | if(cpustate->port1_ddr == 0xff) |
| 2484 | | |
| 2484 | cpustate->io-> | |
| 2485 | 2485 | else |
| 2486 | memory_write_byte_8be(cpustate->io, M6803_PORT1,(cpustate->port1_data & cpustate->port1_ddr) | |
| 2487 | | (memory_read_byte_8be(cpustate->io, M6803_PORT1) & (cpustate->port1_ddr ^ 0xff))); | |
| 2486 | cpustate->io->write_byte(M6803_PORT1,(cpustate->port1_data & cpustate->port1_ddr) | |
| 2487 | | (cpustate->io->read_byte(M6803_PORT1) & (cpustate->port1_ddr ^ 0xff))); | |
| 2488 | 2488 | break; |
| 2489 | 2489 | case 0x03: |
| 2490 | 2490 | if (cpustate->trcsr & M6800_TRCSR_TE) |
| r8806 | r8807 | |
| 2496 | 2496 | cpustate->port2_data = data; |
| 2497 | 2497 | } |
| 2498 | 2498 | if(cpustate->port2_ddr == 0xff) |
| 2499 | | |
| 2499 | cpustate->io-> | |
| 2500 | 2500 | else |
| 2501 | memory_write_byte_8be(cpustate->io, M6803_PORT2,(cpustate->port2_data & cpustate->port2_ddr) | |
| 2502 | | (memory_read_byte_8be(cpustate->io, M6803_PORT2) & (cpustate->port2_ddr ^ 0xff))); | |
| 2501 | cpustate->io->write_byte(M6803_PORT2,(cpustate->port2_data & cpustate->port2_ddr) | |
| 2502 | | (cpustate->io->read_byte(M6803_PORT2) & (cpustate->port2_ddr ^ 0xff))); | |
| 2503 | 2503 | break; |
| 2504 | 2504 | case 0x04: |
| 2505 | 2505 | if (cpustate->port3_ddr != data) |
| 2506 | 2506 | { |
| 2507 | 2507 | cpustate->port3_ddr = data; |
| 2508 | 2508 | if(cpustate->port3_ddr == 0xff) |
| 2509 | | |
| 2509 | cpustate->io-> | |
| 2510 | 2510 | else |
| 2511 | memory_write_byte_8be(cpustate->io, M6803_PORT3,(cpustate->port3_data & cpustate->port3_ddr) | |
| 2512 | | (memory_read_byte_8be(cpustate->io, M6803_PORT3) & (cpustate->port3_ddr ^ 0xff))); | |
| 2511 | cpustate->io->write_byte(M6803_PORT3,(cpustate->port3_data & cpustate->port3_ddr) | |
| 2512 | | (cpustate->io->read_byte(M6803_PORT3) & (cpustate->port3_ddr ^ 0xff))); | |
| 2513 | 2513 | } |
| 2514 | 2514 | break; |
| 2515 | 2515 | case 0x05: |
| r8806 | r8807 | |
| 2517 | 2517 | { |
| 2518 | 2518 | cpustate->port4_ddr = data; |
| 2519 | 2519 | if(cpustate->port4_ddr == 0xff) |
| 2520 | | |
| 2520 | cpustate->io-> | |
| 2521 | 2521 | else |
| 2522 | memory_write_byte_8be(cpustate->io, M6803_PORT4,(cpustate->port4_data & cpustate->port4_ddr) | |
| 2523 | | (memory_read_byte_8be(cpustate->io, M6803_PORT4) & (cpustate->port4_ddr ^ 0xff))); | |
| 2522 | cpustate->io->write_byte(M6803_PORT4,(cpustate->port4_data & cpustate->port4_ddr) | |
| 2523 | | (cpustate->io->read_byte(M6803_PORT4) & (cpustate->port4_ddr ^ 0xff))); | |
| 2524 | 2524 | } |
| 2525 | 2525 | break; |
| 2526 | 2526 | case 0x06: |
| 2527 | 2527 | cpustate->port3_data = data; |
| 2528 | 2528 | if(cpustate->port3_ddr == 0xff) |
| 2529 | | |
| 2529 | cpustate->io-> | |
| 2530 | 2530 | else |
| 2531 | memory_write_byte_8be(cpustate->io, M6803_PORT3,(cpustate->port3_data & cpustate->port3_ddr) | |
| 2532 | | (memory_read_byte_8be(cpustate->io, M6803_PORT3) & (cpustate->port3_ddr ^ 0xff))); | |
| 2531 | cpustate->io->write_byte(M6803_PORT3,(cpustate->port3_data & cpustate->port3_ddr) | |
| 2532 | | (cpustate->io->read_byte(M6803_PORT3) & (cpustate->port3_ddr ^ 0xff))); | |
| 2533 | 2533 | break; |
| 2534 | 2534 | case 0x07: |
| 2535 | 2535 | cpustate->port4_data = data; |
| 2536 | 2536 | if(cpustate->port4_ddr == 0xff) |
| 2537 | | |
| 2537 | cpustate->io-> | |
| 2538 | 2538 | else |
| 2539 | memory_write_byte_8be(cpustate->io, M6803_PORT4,(cpustate->port4_data & cpustate->port4_ddr) | |
| 2540 | | (memory_read_byte_8be(cpustate->io, M6803_PORT4) & (cpustate->port4_ddr ^ 0xff))); | |
| 2539 | cpustate->io->write_byte(M6803_PORT4,(cpustate->port4_data & cpustate->port4_ddr) | |
| 2540 | | (cpustate->io->read_byte(M6803_PORT4) & (cpustate->port4_ddr ^ 0xff))); | |
| 2541 | 2541 | break; |
| 2542 | 2542 | case 0x08: |
| 2543 | 2543 | cpustate->tcsr = data; |
| r8806 | r8807 | |
|---|---|---|
| 47 | 47 | int intrm_pending; |
| 48 | 48 | int mask_interrupts; |
| 49 | 49 | legacy_cpu_device *device; |
| 50 | | |
| 50 | | |
| 51 | 51 | int icount; |
| 52 | 52 | }; |
| 53 | 53 | |
| r8806 | r8807 | |
| 58 | 58 | return (cp1610_state *)downcast<legacy_cpu_device *>(device)->token(); |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | #define cp1610_readop(A) memory_read_word_16be(cpustate->program, (A)<<1) | |
| 62 | #define cp1610_readmem16(A) memory_read_word_16be(cpustate->program, (A)<<1) | |
| 63 | #define cp1610_writemem16(A,B) memory_write_word_16be(cpustate->program, (A)<<1,B) | |
| 61 | #define cp1610_readop(A) cpustate->program->read_word((A)<<1) | |
| 62 | #define cp1610_readmem16(A) cpustate->program->read_word((A)<<1) | |
| 63 | #define cp1610_writemem16(A,B) cpustate->program->write_word((A)<<1,B) | |
| 64 | 64 | |
| 65 | 65 | /* clear all flags */ |
| 66 | 66 | #define CLR_SZOC \ |
| r8806 | r8807 | |
|---|---|---|
| 78 | 78 | { |
| 79 | 79 | UINT8 data; |
| 80 | 80 | cpustate->icount-=3; |
| 81 | data= | |
| 81 | data= | |
| 82 | 82 | saturn_assert(data<0x10); |
| 83 | 83 | if (cpustate->config&&cpustate->config->crc) cpustate->config->crc(cpustate->device, adr&0xfffff, data); |
| 84 | 84 | return data; |
| r8806 | r8807 | |
| 108 | 108 | { |
| 109 | 109 | cpustate->icount-=3; |
| 110 | 110 | saturn_assert(nib<0x10); |
| 111 | | |
| 111 | | |
| 112 | 112 | } |
| 113 | 113 | |
| 114 | 114 | #define BEGIN_B 0 |
| r8806 | r8807 | |
|---|---|---|
| 83 | 83 | int monitor_in; |
| 84 | 84 | device_irq_callback irq_callback; |
| 85 | 85 | legacy_cpu_device *device; |
| 86 | | |
| 86 | | |
| 87 | 87 | int icount; |
| 88 | 88 | }; |
| 89 | 89 |
| r8806 | r8807 | |
|---|---|---|
| 62 | 62 | UINT8 nmi_pending; |
| 63 | 63 | int icount; |
| 64 | 64 | legacy_cpu_device *device; |
| 65 | | |
| 65 | | |
| 66 | 66 | konami_set_lines_func setlines_callback; |
| 67 | 67 | }; |
| 68 | 68 | |
| r8806 | r8807 | |
| 118 | 118 | #define KONAMI_SYNC 16 /* set when SYNC is waiting for an interrupt */ |
| 119 | 119 | #define KONAMI_LDS 32 /* set when LDS occured at least once */ |
| 120 | 120 | |
| 121 | #define RM(cs,Addr) memory_read_byte_8be((cs)->program, Addr) | |
| 122 | #define WM(cs,Addr,Value) memory_write_byte_8be((cs)->program, Addr,Value) | |
| 121 | #define RM(cs,Addr) (cs)->program->read_byte(Addr) | |
| 122 | #define WM(cs,Addr,Value) (cs)->program->write_byte(Addr,Value) | |
| 123 | 123 | #define ROP(cs,Addr) memory_decrypted_read_byte((cs)->program, Addr) |
| 124 | 124 | #define ROP_ARG(cs,Addr) memory_raw_read_byte((cs)->program, Addr) |
| 125 | 125 |
| r8806 | r8807 | |
|---|---|---|
| 56 | 56 | static void recompute_parameters(tms9927_state *tms, int postload); |
| 57 | 57 | |
| 58 | 58 | |
| 59 | tms9927_interface tms9927_null_interface = { 0 }; | |
| 59 | const tms9927_interface tms9927_null_interface = { 0 }; | |
| 60 | 60 | |
| 61 | 61 | |
| 62 | 62 | /* makes sure that the passed in device is the right type */ |
| r8806 | r8807 | |
|---|---|---|
| 596 | 596 | |
| 597 | 597 | static void vga_cpu_interface(running_machine *machine) |
| 598 | 598 | { |
| 599 | | |
| 599 | | |
| 600 | 600 | static int sequencer, gc; |
| 601 | 601 | read8_space_func read_handler; |
| 602 | 602 | write8_space_func write_handler; |
| r8806 | r8807 | |
| 1220 | 1220 | void pc_vga_init(running_machine *machine, const struct pc_vga_interface *vga_intf, const struct pc_svga_interface *svga_intf) |
| 1221 | 1221 | { |
| 1222 | 1222 | int i, j, k, mask, buswidth; |
| 1223 | | |
| 1223 | | |
| 1224 | 1224 | |
| 1225 | 1225 | memset(&vga, 0, sizeof(vga)); |
| 1226 | 1226 |
| r8806 | r8807 | |
|---|---|---|
| 164 | 164 | * |
| 165 | 165 | *************************************/ |
| 166 | 166 | |
| 167 | static void register_w( | |
| 167 | static void register_w( | |
| 168 | 168 | { |
| 169 | 169 | int scanline; |
| 170 | 170 | int regnum = offset >> 2; |
| r8806 | r8807 | |
| 235 | 235 | * |
| 236 | 236 | *************************************/ |
| 237 | 237 | |
| 238 | static UINT8 register_r( | |
| 238 | static UINT8 register_r( | |
| 239 | 239 | { |
| 240 | 240 | int regnum = offset >> 2; |
| 241 | 241 | UINT16 result; |
| r8806 | r8807 | |
| 357 | 357 | } |
| 358 | 358 | |
| 359 | 359 | |
| 360 | static void xypixel_w( | |
| 360 | static void xypixel_w( | |
| 361 | 361 | { |
| 362 | 362 | /* determine the offset, then adjust it */ |
| 363 | 363 | offs_t pixeloffs = tms34061.regs[TMS34061_XYADDRESS]; |
| r8806 | r8807 | |
| 377 | 377 | } |
| 378 | 378 | |
| 379 | 379 | |
| 380 | static UINT8 xypixel_r( | |
| 380 | static UINT8 xypixel_r( | |
| 381 | 381 | { |
| 382 | 382 | /* determine the offset, then adjust it */ |
| 383 | 383 | offs_t pixeloffs = tms34061.regs[TMS34061_XYADDRESS]; |
| r8806 | r8807 | |
| 402 | 402 | * |
| 403 | 403 | *************************************/ |
| 404 | 404 | |
| 405 | void tms34061_w( | |
| 405 | void tms34061_w( | |
| 406 | 406 | { |
| 407 | 407 | offs_t offs; |
| 408 | 408 | |
| r8806 | r8807 | |
| 464 | 464 | } |
| 465 | 465 | |
| 466 | 466 | |
| 467 | UINT8 tms34061_r( | |
| 467 | UINT8 tms34061_r( | |
| 468 | 468 | { |
| 469 | 469 | int result = 0; |
| 470 | 470 | offs_t offs; |
| r8806 | r8807 | |
|---|---|---|
| 39 | 39 | const char *selfload_region; /* name of the region with self-load data */ |
| 40 | 40 | }; |
| 41 | 41 | |
| 42 | extern tms9927_interface tms9927_null_interface; | |
| 42 | extern const tms9927_interface tms9927_null_interface; | |
| 43 | 43 | |
| 44 | 44 | |
| 45 | 45 | /* basic read/write handlers */ |
| r8806 | r8807 | |
|---|---|---|
| 59 | 59 | void tms34061_start(running_machine *machine, const struct tms34061_interface *interface); |
| 60 | 60 | |
| 61 | 61 | /* reads/writes to the 34061 */ |
| 62 | UINT8 tms34061_r(const address_space *space, int col, int row, int func); | |
| 63 | void tms34061_w(const address_space *space, int col, int row, int func, UINT8 data); | |
| 62 | UINT8 tms34061_r(address_space *space, int col, int row, int func); | |
| 63 | void tms34061_w(address_space *space, int col, int row, int func, UINT8 data); | |
| 64 | 64 | |
| 65 | 65 | /* latch settings */ |
| 66 | 66 | READ8_HANDLER( tms34061_latch_r ); |
| r8806 | r8807 | |
|---|---|---|
| 10 | 10 | #include "emu.h" |
| 11 | 11 | #include "tlc34076.h" |
| 12 | 12 | |
| 13 | static UINT8 local_paletteram[0x300]; | |
| 14 | static UINT8 regs[0x10]; | |
| 15 | static UINT8 palettedata[3]; | |
| 16 | static UINT8 writeindex, readindex; | |
| 17 | static UINT8 dacbits; | |
| 18 | ||
| 19 | static rgb_t pens[0x100]; | |
| 20 | ||
| 21 | 13 | #define PALETTE_WRITE_ADDR 0x00 |
| 22 | 14 | #define PALETTE_DATA 0x01 |
| 23 | 15 | #define PIXEL_READ_MASK 0x02 |
| r8806 | r8807 | |
| 30 | 22 | #define TEST_REGISTER 0x0e |
| 31 | 23 | #define RESET_STATE 0x0f |
| 32 | 24 | |
| 25 | typedef struct _tlc34076_state tlc34076_state; | |
| 26 | struct _tlc34076_state | |
| 27 | { | |
| 28 | UINT8 local_paletteram[0x300]; | |
| 29 | UINT8 regs[0x10]; | |
| 30 | UINT8 palettedata[3]; | |
| 31 | UINT8 writeindex; | |
| 32 | UINT8 readindex; | |
| 33 | UINT8 dacbits; | |
| 33 | 34 | |
| 35 | rgb_t pens[0x100]; | |
| 36 | }; | |
| 34 | 37 | |
| 38 | ||
| 35 | 39 | /************************************* |
| 36 | 40 | * |
| 41 | * Inline functions | |
| 42 | * | |
| 43 | *************************************/ | |
| 44 | ||
| 45 | INLINE tlc34076_state *get_safe_token( running_device *device ) | |
| 46 | { | |
| 47 | assert(device != NULL); | |
| 48 | assert(device->type() == TLC34076); | |
| 49 | ||
| 50 | return (tlc34076_state *)downcast<legacy_device_base *>(device)->token(); | |
| 51 | } | |
| 52 | ||
| 53 | /************************************* | |
| 54 | * | |
| 37 | 55 | * Retrieve Current Palette |
| 38 | 56 | * |
| 39 | 57 | *************************************/ |
| 40 | 58 | |
| 41 | const pen_t *tlc34076_get_pens(v | |
| 59 | const pen_t *tlc34076_get_pens(running_dev | |
| 42 | 60 | { |
| 61 | tlc34076_state *state = get_safe_token(device); | |
| 43 | 62 | offs_t i; |
| 44 | 63 | |
| 45 | 64 | for (i = 0; i < 0x100; i++) |
| 46 | 65 | { |
| 47 | 66 | int r, g, b; |
| 48 | 67 | |
| 49 | if ((i & regs[PIXEL_READ_MASK]) == i) | |
| 68 | if ((i & state->regs[PIXEL_READ_MASK]) == i) | |
| 50 | 69 | { |
| 51 | r = local_paletteram[3 * i + 0]; | |
| 52 | g = local_paletteram[3 * i + 1]; | |
| 53 | b = local_paletteram[3 * i + 2]; | |
| 70 | r = state->local_paletteram[3 * i + 0]; | |
| 71 | g = state->local_paletteram[3 * i + 1]; | |
| 72 | b = state->local_paletteram[3 * i + 2]; | |
| 54 | 73 | |
| 55 | if (dacbits == 6) | |
| 74 | if (state->dacbits == 6) | |
| 56 | 75 | { |
| 57 | 76 | r = pal6bit(r); |
| 58 | 77 | g = pal6bit(g); |
| r8806 | r8807 | |
| 66 | 85 | b = 0; |
| 67 | 86 | } |
| 68 | 87 | |
| 69 | pens[i] = MAKE_RGB(r, g, b); | |
| 88 | state->pens[i] = MAKE_RGB(r, g, b); | |
| 70 | 89 | } |
| 71 | 90 | |
| 72 | return pens; | |
| 91 | return state->pens; | |
| 73 | 92 | } |
| 74 | 93 | |
| 75 | 94 | |
| r8806 | r8807 | |
| 80 | 99 | * |
| 81 | 100 | *************************************/ |
| 82 | 101 | |
| 83 | ||
| 102 | static DEVICE_RESET( tlc34076 | |
| 84 | 103 | { |
| 85 | | |
| 104 | | |
| 86 | 105 | |
| 87 | dacbits = dacwidth; | |
| 88 | ||
| 89 | 106 | /* reset the registers */ |
| 90 | regs[PIXEL_READ_MASK] = 0xff; | |
| 91 | regs[GENERAL_CONTROL] = 0x03; | |
| 92 | regs[INPUT_CLOCK_SEL] = 0x00; | |
| 93 | regs[OUTPUT_CLOCK_SEL] = 0x3f; | |
| 94 | regs[MUX_CONTROL] = 0x2d; | |
| 95 | regs[PALETTE_PAGE] = 0x00; | |
| 96 | regs[TEST_REGISTER] = 0x00; | |
| 97 | regs[RESET_STATE] = 0x00; | |
| 107 | state->regs[PIXEL_READ_MASK] = 0xff; | |
| 108 | state->regs[GENERAL_CONTROL] = 0x03; | |
| 109 | state->regs[INPUT_CLOCK_SEL] = 0x00; | |
| 110 | state->regs[OUTPUT_CLOCK_SEL] = 0x3f; | |
| 111 | state->regs[MUX_CONTROL] = 0x2d; | |
| 112 | state->regs[PALETTE_PAGE] = 0x00; | |
| 113 | state->regs[TEST_REGISTER] = 0x00; | |
| 114 | state->regs[RESET_STATE] = 0x00; | |
| 98 | 115 | } |
| 99 | 116 | |
| 100 | 117 | |
| 101 | ||
| 102 | 118 | /************************************* |
| 103 | 119 | * |
| 104 | * Save State | |
| 105 | * | |
| 106 | *************************************/ | |
| 107 | ||
| 108 | void tlc34076_state_save(running_machine *machine) | |
| 109 | { | |
| 110 | state_save_register_global_array(machine, local_paletteram); | |
| 111 | state_save_register_global_array(machine, regs); | |
| 112 | state_save_register_global_array(machine, pens); | |
| 113 | ||
| 114 | state_save_register_global(machine, writeindex); | |
| 115 | state_save_register_global(machine, readindex); | |
| 116 | state_save_register_global(machine, dacbits); | |
| 117 | } | |
| 118 | ||
| 119 | ||
| 120 | /************************************* | |
| 121 | * | |
| 122 | 120 | * Read access |
| 123 | 121 | * |
| 124 | 122 | *************************************/ |
| 125 | 123 | |
| 126 | READ8_HANDLER( tlc34076_r ) | |
| 124 | READ8_DEVICE_HANDLER( tlc34076_r ) | |
| 127 | 125 | { |
| 126 | tlc34076_state *state = get_safe_token(device); | |
| 128 | 127 | UINT8 result; |
| 129 | 128 | |
| 130 | 129 | /* keep in range */ |
| 131 | 130 | offset &= 0x0f; |
| 132 | result = regs[offset]; | |
| 131 | result = state->regs[offset]; | |
| 133 | 132 | |
| 134 | 133 | /* switch off the offset */ |
| 135 | 134 | switch (offset) |
| 136 | 135 | { |
| 137 | 136 | case PALETTE_DATA: |
| 138 | if (readindex == 0) | |
| 137 | if (state->readindex == 0) | |
| 139 | 138 | { |
| 140 | palettedata[0] = local_paletteram[3 * regs[PALETTE_READ_ADDR] + 0]; | |
| 141 | palettedata[1] = local_paletteram[3 * regs[PALETTE_READ_ADDR] + 1]; | |
| 142 | palettedata[2] = local_paletteram[3 * regs[PALETTE_READ_ADDR] + 2]; | |
| 139 | state->palettedata[0] = state->local_paletteram[3 * state->regs[PALETTE_READ_ADDR] + 0]; | |
| 140 | state->palettedata[1] = state->local_paletteram[3 * state->regs[PALETTE_READ_ADDR] + 1]; | |
| 141 | state->palettedata[2] = state->local_paletteram[3 * state->regs[PALETTE_READ_ADDR] + 2]; | |
| 143 | 142 | } |
| 144 | result = palettedata[readindex++]; | |
| 145 | if (readindex == 3) | |
| 143 | result = state->palettedata[state->readindex++]; | |
| 144 | if (state->readindex == 3) | |
| 146 | 145 | { |
| 147 | readindex = 0; | |
| 148 | regs[PALETTE_READ_ADDR]++; | |
| 146 | state->readindex = 0; | |
| 147 | state->regs[PALETTE_READ_ADDR]++; | |
| 149 | 148 | } |
| 150 | 149 | break; |
| 151 | 150 | } |
| r8806 | r8807 | |
| 161 | 160 | * |
| 162 | 161 | *************************************/ |
| 163 | 162 | |
| 164 | WRITE8_HANDLER( tlc34076_w ) | |
| 163 | WRITE8_DEVICE_HANDLER( tlc34076_w ) | |
| 165 | 164 | { |
| 165 | tlc34076_state *state = get_safe_token(device); | |
| 166 | 166 | UINT8 oldval; |
| 167 | 167 | |
| 168 | 168 | /* keep in range */ |
| 169 | 169 | offset &= 0x0f; |
| 170 | oldval = regs[offset]; | |
| 171 | regs[offset] = data; | |
| 170 | oldval = state->regs[offset]; | |
| 171 | state->regs[offset] = data; | |
| 172 | 172 | |
| 173 | 173 | /* switch off the offset */ |
| 174 | 174 | switch (offset) |
| 175 | 175 | { |
| 176 | 176 | case PALETTE_WRITE_ADDR: |
| 177 | writeindex = 0; | |
| 177 | state->writeindex = 0; | |
| 178 | 178 | break; |
| 179 | 179 | |
| 180 | 180 | case PALETTE_DATA: |
| 181 | palettedata[writeindex++] = data; | |
| 182 | if (writeindex == 3) | |
| 181 | state->palettedata[state->writeindex++] = data; | |
| 182 | if (state->writeindex == 3) | |
| 183 | 183 | { |
| 184 | local_paletteram[3 * regs[PALETTE_WRITE_ADDR] + 0] = palettedata[0]; | |
| 185 | local_paletteram[3 * regs[PALETTE_WRITE_ADDR] + 1] = palettedata[1]; | |
| 186 | local_paletteram[3 * regs[PALETTE_WRITE_ADDR] + 2] = palettedata[2]; | |
| 187 | writeindex = 0; | |
| 188 | regs[PALETTE_WRITE_ADDR]++; | |
| 184 | state->local_paletteram[3 * state->regs[PALETTE_WRITE_ADDR] + 0] = state->palettedata[0]; | |
| 185 | state->local_paletteram[3 * state->regs[PALETTE_WRITE_ADDR] + 1] = state->palettedata[1]; | |
| 186 | state->local_paletteram[3 * state->regs[PALETTE_WRITE_ADDR] + 2] = state->palettedata[2]; | |
| 187 | state->writeindex = 0; | |
| 188 | state->regs[PALETTE_WRITE_ADDR]++; | |
| 189 | 189 | } |
| 190 | 190 | break; |
| 191 | 191 | |
| 192 | 192 | case PALETTE_READ_ADDR: |
| 193 | readindex = 0; | |
| 193 | state->readindex = 0; | |
| 194 | 194 | break; |
| 195 | 195 | |
| 196 | 196 | case GENERAL_CONTROL: |
| r8806 | r8807 | |
| 247 | 247 | break; |
| 248 | 248 | |
| 249 | 249 | case RESET_STATE: |
| 250 | tlc34076 | |
| 250 | DEVICE_RESET_CALL(tlc34076 | |
| 251 | 251 | break; |
| 252 | 252 | } |
| 253 | 253 | } |
| r8806 | r8807 | |
| 256 | 256 | |
| 257 | 257 | /************************************* |
| 258 | 258 | * |
| 259 | * | |
| 259 | * Dev | |
| 260 | 260 | * |
| 261 | 261 | *************************************/ |
| 262 | 262 | |
| 263 | ||
| 263 | static DEVICE_STA | |
| 264 | 264 | { |
| 265 | return tlc34076_r(space, offset); | |
| 266 | } | |
| 265 | tlc34076_config *config = (tlc34076_config *)downcast<const legacy_device_config_base &>(device->baseconfig()).inline_config(); | |
| 266 | tlc34076_state *state = get_safe_token(device); | |
| 267 | 267 | |
| 268 | WRITE16_HANDLER( tlc34076_lsb_w ) | |
| 269 | { | |
| 270 | if (ACCESSING_BITS_0_7) | |
| 271 | tlc34076_w(space, offset, data); | |
| 272 | } | |
| 268 | state->dacbits = config->res_sel ? 8 : 6; | |
| 273 | 269 | |
| 274 | READ16_HANDLER( tlc34076_msb_r ) | |
| 275 | { | |
| 276 | return tlc34076_r(space, offset) << 8; | |
| 277 | } | |
| 270 | state_save_register_global_array(device->machine, state->local_paletteram); | |
| 271 | state_save_register_global_array(device->machine, state->regs); | |
| 272 | state_save_register_global_array(device->machine, state->pens); | |
| 278 | 273 | |
| 279 | WRITE16_HANDLER( tlc34076_msb_w ) | |
| 280 | { | |
| 281 | if (ACCESSING_BITS_8_15) | |
| 282 | tlc34076_w(space, offset, data >> 8); | |
| 274 | state_save_register_global(device->machine, state->writeindex); | |
| 275 | state_save_register_global(device->machine, state->readindex); | |
| 276 | state_save_register_global(device->machine, state->dacbits); | |
| 283 | 277 | } |
| 284 | 278 | |
| 279 | static const char DEVTEMPLATE_SOURCE[] = __FILE__; | |
| 280 | ||
| 281 | #define DEVTEMPLATE_ID( p, s ) p##tlc34076##s | |
| 282 | #define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET | DT_HAS_INLINE_CONFIG | |
| 283 | #define DEVTEMPLATE_NAME "TLC34076" | |
| 284 | #define DEVTEMPLATE_FAMILY "RAMDAC" | |
| 285 | #include "devtempl.h" | |
| 286 | ||
| 287 | ||
| 288 | DEFINE_LEGACY_DEVICE(TLC34076, tlc34076); |
| r8806 | r8807 | |
|---|---|---|
| 138 | 138 | static void update_vsync_changed_timers(mc6845_t *mc6845); |
| 139 | 139 | |
| 140 | 140 | |
| 141 | mc6845_interface mc6845_null_interface = { 0 }; | |
| 141 | const mc6845_interface mc6845_null_interface = { 0 }; | |
| 142 | 142 | |
| 143 | 143 | |
| 144 | 144 | /* makes sure that the passed in device is the right type */ |
| r8806 | r8807 | |
|---|---|---|
| 83 | 83 | mc6845_on_update_addr_changed_func on_update_addr_changed; |
| 84 | 84 | }; |
| 85 | 85 | |
| 86 | extern mc6845_interface mc6845_null_interface; | |
| 86 | extern const mc6845_interface mc6845_null_interface; | |
| 87 | 87 | |
| 88 | 88 | |
| 89 | 89 | /* select one of the registers for reading or writing */ |
| r8806 | r8807 | |
|---|---|---|
| 7 | 7 | |
| 8 | 8 | ***************************************************************************/ |
| 9 | 9 | |
| 10 | void tlc34076_reset(int dacwidth); | |
| 11 | void tlc34076_state_save(running_machine *machine); | |
| 10 | #define TLC34076_6_BIT 0 | |
| 11 | #define TLC34076_8_BIT 1 | |
| 12 | 12 | |
| 13 | const pen_t *tlc34076_get_pens(v | |
| 13 | const pen_t *tlc34076_get_pens(running_dev | |
| 14 | 14 | |
| 15 | READ8_HANDLER( tlc34076_r ); | |
| 16 | WRITE8_HANDLER( tlc34076_w ); | |
| 17 | 15 | |
| 18 | READ16_HANDLER( tlc34076_lsb_r ); | |
| 19 | WRITE16_HANDLER( tlc34076_lsb_w ); | |
| 20 | READ16_HANDLER( tlc34076_msb_r ); | |
| 21 | WRITE16_HANDLER( tlc34076_msb_w ); | |
| 16 | /*************************************************************************** | |
| 17 | TYPE DEFINITIONS | |
| 18 | ***************************************************************************/ | |
| 22 | 19 | |
| 20 | typedef struct _tlc34076_config tlc34076_config; | |
| 21 | struct _tlc34076_config | |
| 22 | { | |
| 23 | int res_sel; | |
| 24 | }; | |
| 25 | ||
| 26 | DECLARE_LEGACY_DEVICE(TLC34076, tlc34076); | |
| 27 | ||
| 28 | ||
| 29 | /*************************************************************************** | |
| 30 | DEVICE CONFIGURATION MACROS | |
| 31 | ***************************************************************************/ | |
| 32 | ||
| 33 | #define MDRV_TLC34076_ADD(_tag, _res_sel) \ | |
| 34 | MDRV_DEVICE_ADD(_tag, TLC34076, 0) \ | |
| 35 | MDRV_DEVICE_CONFIG_DATA32(tlc34076_config, res_sel, _res_sel) | |
| 36 | ||
| 37 | ||
| 38 | /*************************************************************************** | |
| 39 | DEVICE I/O FUNCTIONS | |
| 40 | ***************************************************************************/ | |
| 41 | ||
| 42 | WRITE8_DEVICE_HANDLER( tlc34076_w ); | |
| 43 | READ8_DEVICE_HANDLER( tlc34076_r ); |
| r8806 | r8807 | |
|---|---|---|
| 139 | 139 | |
| 140 | 140 | |
| 141 | 141 | |
| 142 | UINT8 *vectorram; | |
| 143 | size_t vectorram_size; | |
| 144 | ||
| 145 | 142 | static int flicker; /* beam flicker value */ |
| 146 | 143 | static float flicker_correction = 0.0f; |
| 147 | 144 |
| r8806 | r8807 | |
|---|---|---|
| 10 | 10 | #define VECTOR_COLOR444(c) \ |
| 11 | 11 | MAKE_RGB(pal4bit((c) >> 8), pal4bit((c) >> 4), pal4bit((c) >> 0)) |
| 12 | 12 | |
| 13 | extern UINT8 *vectorram; | |
| 14 | extern size_t vectorram_size; | |
| 15 | ||
| 16 | 13 | VIDEO_START( vector ); |
| 17 | 14 | VIDEO_UPDATE( vector ); |
| 18 | 15 |
| r8806 | r8807 | |
|---|---|---|
| 77 | 77 | |
| 78 | 78 | #include "emu.h" |
| 79 | 79 | #include "video/s2636.h" |
| 80 | #include "sound/s2636.h" | |
| 80 | 81 | |
| 81 | 82 | /************************************* |
| 82 | 83 | * |
| r8806 | r8807 | |
| 318 | 319 | |
| 319 | 320 | assert(offset < s2636->work_ram_size); |
| 320 | 321 | |
| 322 | if ( offset == 0xc7 ) | |
| 323 | { | |
| 324 | const s2636_interface *intf = get_interface(device); | |
| 325 | if ( intf->sound && *intf->sound ) | |
| 326 | { | |
| 327 | s2636_soundport_w(device->machine->device(intf->sound), 0, data); | |
| 328 | } | |
| 329 | } | |
| 330 | ||
| 321 | 331 | s2636->work_ram[offset] = data; |
| 322 | 332 | } |
| 323 | 333 |
| r8806 | r8807 | |
|---|---|---|
| 26 | 26 | int work_ram_size; |
| 27 | 27 | int y_offset; |
| 28 | 28 | int x_offset; |
| 29 | const char *sound; | |
| 29 | 30 | }; |
| 30 | 31 | |
| 31 | 32 | /************************************* |
| r8806 | r8807 | |
|---|---|---|
| 347 | 347 | // ======================> device_t |
| 348 | 348 | |
| 349 | 349 | // device_t represents a device that is live and attached to a running_machine |
| 350 | class device_t | |
| 350 | class device_t : public bindable_object | |
| 351 | 351 | { |
| 352 | 352 | DISABLE_COPYING(device_t); |
| 353 | 353 |
| r8806 | r8807 | |
|---|---|---|
| 62 | 62 | #include "attotime.h" |
| 63 | 63 | #include "fileio.h" // remove me once NVRAM is implemented as device |
| 64 | 64 | #include "tokenize.h" |
| 65 | #include "delegate.h" | |
| 65 | 66 | |
| 66 | 67 | // memory and address spaces |
| 67 | 68 | #include "memory.h" |
| r8806 | r8807 | |
|---|---|---|
| 243 | 243 | { |
| 244 | 244 | cpu_device *cpu = downcast<cpu_device *>(&executing->device()); |
| 245 | 245 | if (cpu != NULL) |
| 246 | m_context.printf("'%s' (%s)", cpu->tag(), core_i64_hex_format(cpu->pc(), cpu->space(AS_PROGRAM)->logaddrchars)); | |
| 246 | m_context.printf("'%s' (%s)", cpu->tag(), core_i64_hex_format(cpu->pc(), cpu->space(AS_PROGRAM)->logaddrchars())); | |
| 247 | 247 | else |
| 248 | 248 | m_context.printf("'%s'", cpu->tag()); |
| 249 | 249 | } |
| r8806 | r8807 | |
|---|---|---|
| 137 | 137 | uint8 cur_byte; |
| 138 | 138 | boolean enabled; |
| 139 | 139 | boolean irq_occurred; |
| 140 | | |
| 140 | | |
| 141 | 141 | signed char vol; |
| 142 | 142 | } dpcm_t; |
| 143 | 143 |
| r8806 | r8807 | |
|---|---|---|
| 227 | 227 | running_device *device; |
| 228 | 228 | }; |
| 229 | 229 | |
| 230 | static void dma_scsp( | |
| 230 | static void dma_scsp( | |
| 231 | 231 | #define scsp_dgate scsp_regs[0x16/2] & 0x4000 |
| 232 | 232 | #define scsp_ddir scsp_regs[0x16/2] & 0x2000 |
| 233 | 233 | #define scsp_dexe scsp_regs[0x16/2] & 0x1000 |
| r8806 | r8807 | |
| 698 | 698 | static void SCSP_UpdateReg(struct _SCSP *SCSP, int reg) |
| 699 | 699 | { |
| 700 | 700 | /* temporary hack until this is converted to a device */ |
| 701 | | |
| 701 | | |
| 702 | 702 | switch(reg&0x3f) |
| 703 | 703 | { |
| 704 | 704 | case 0x2: |
| r8806 | r8807 | |
| 1168 | 1168 | } |
| 1169 | 1169 | } |
| 1170 | 1170 | |
| 1171 | static void dma_scsp( | |
| 1171 | static void dma_scsp( | |
| 1172 | 1172 | { |
| 1173 | 1173 | static UINT16 tmp_dma[3], *scsp_regs; |
| 1174 | 1174 | |
| r8806 | r8807 | |
| 1191 | 1191 | { |
| 1192 | 1192 | for(;SCSP->scsp_dtlg > 0;SCSP->scsp_dtlg-=2) |
| 1193 | 1193 | { |
| 1194 | | |
| 1194 | space-> | |
| 1195 | 1195 | SCSP->scsp_dmea+=2; |
| 1196 | 1196 | SCSP->scsp_drga+=2; |
| 1197 | 1197 | } |
| r8806 | r8807 | |
| 1200 | 1200 | { |
| 1201 | 1201 | for(;SCSP->scsp_dtlg > 0;SCSP->scsp_dtlg-=2) |
| 1202 | 1202 | { |
| 1203 | | |
| 1203 | space-> | |
| 1204 | 1204 | SCSP->scsp_dmea+=2; |
| 1205 | 1205 | SCSP->scsp_drga+=2; |
| 1206 | 1206 | } |
| r8806 | r8807 | |
|---|---|---|
| 33 | 33 | double dr_rate; |
| 34 | 34 | double rr_rate; |
| 35 | 35 | |
| 36 | int pitch; /* current pitch data */ | |
| 36 | int pitch; /* current pitch data */ | |
| 37 | 37 | |
| 38 | 38 | int GF; |
| 39 | 39 | } VOICE; |
| r8806 | r8807 | |
| 60 | 60 | double ar_tbl[8]; |
| 61 | 61 | double dr_tbl[16]; |
| 62 | 62 | |
| 63 | UINT8 control1; | |
| 64 | UINT8 control2; | |
| 63 | UINT8 control1; | |
| 64 | UINT8 control2; | |
| 65 | 65 | |
| 66 | 66 | int gate; /* current state of the GATE output */ |
| 67 | 67 | |
| r8806 | r8807 | |
| 780 | 780 | |
| 781 | 781 | |
| 782 | 782 | /* MAME Interface */ |
| 783 | static STATE_POSTLOAD( msm5232_postload ) | |
| 784 | { | |
| 785 | MSM5232 *chip = (MSM5232 *)param; | |
| 786 | msm5232_init_tables(chip); | |
| 787 | } | |
| 783 | 788 | |
| 784 | 789 | static DEVICE_START( msm5232 ) |
| 785 | 790 | { |
| 786 | 791 | const msm5232_interface *intf = (const msm5232_interface *)device->baseconfig().static_config(); |
| 787 | 792 | int rate = device->clock()/CLOCK_RATE_DIVIDER; |
| 788 | 793 | MSM5232 *chip = get_safe_token(device); |
| 794 | int voicenum; | |
| 789 | 795 | |
| 790 | 796 | chip->device = device; |
| 791 | 797 | |
| 792 | 798 | msm5232_init(chip, intf, device->clock(), rate); |
| 793 | 799 | |
| 794 | chip->stream = stream_create(device,0,11,rate,chip,MSM5232_update_one); | |
| 800 | chip->stream = stream_create(device, 0, 11, rate, chip, MSM5232_update_one); | |
| 801 | ||
| 802 | /* register with the save state system */ | |
| 803 | state_save_register_postload(device->machine, msm5232_postload, chip); | |
| 804 | state_save_register_device_item_array(device, 0, chip->EN_out16); | |
| 805 | state_save_register_device_item_array(device, 0, chip->EN_out8); | |
| 806 | state_save_register_device_item_array(device, 0, chip->EN_out4); | |
| 807 | state_save_register_device_item_array(device, 0, chip->EN_out2); | |
| 808 | state_save_register_device_item(device, 0, chip->noise_cnt); | |
| 809 | state_save_register_device_item(device, 0, chip->noise_rng); | |
| 810 | state_save_register_device_item(device, 0, chip->noise_clocks); | |
| 811 | state_save_register_device_item(device, 0, chip->control1); | |
| 812 | state_save_register_device_item(device, 0, chip->control2); | |
| 813 | state_save_register_device_item(device, 0, chip->gate); | |
| 814 | state_save_register_device_item(device, 0, chip->clock); | |
| 815 | state_save_register_device_item(device, 0, chip->rate); | |
| 816 | ||
| 817 | /* register voice-specific data for save states */ | |
| 818 | for (voicenum = 0; voicenum < 8; voicenum++) | |
| 819 | { | |
| 820 | VOICE *voice = &chip->voi[voicenum]; | |
| 821 | ||
| 822 | state_save_register_device_item(device, voicenum, voice->mode); | |
| 823 | state_save_register_device_item(device, voicenum, voice->TG_count_period); | |
| 824 | state_save_register_device_item(device, voicenum, voice->TG_cnt); | |
| 825 | state_save_register_device_item(device, voicenum, voice->TG_out16); | |
| 826 | state_save_register_device_item(device, voicenum, voice->TG_out8); | |
| 827 | state_save_register_device_item(device, voicenum, voice->TG_out4); | |
| 828 | state_save_register_device_item(device, voicenum, voice->TG_out2); | |
| 829 | state_save_register_device_item(device, voicenum, voice->egvol); | |
| 830 | state_save_register_device_item(device, voicenum, voice->eg_sect); | |
| 831 | state_save_register_device_item(device, voicenum, voice->counter); | |
| 832 | state_save_register_device_item(device, voicenum, voice->eg); | |
| 833 | state_save_register_device_item(device, voicenum, voice->eg_arm); | |
| 834 | state_save_register_device_item(device, voicenum, voice->ar_rate); | |
| 835 | state_save_register_device_item(device, voicenum, voice->dr_rate); | |
| 836 | state_save_register_device_item(device, voicenum, voice->pitch); | |
| 837 | state_save_register_device_item(device, voicenum, voice->GF); | |
| 838 | } | |
| 795 | 839 | } |
| 796 | 840 | |
| 797 | 841 | void msm5232_set_clock(running_device *device, int clock) |
| r8806 | r8807 | |
|---|---|---|
| 66 | 66 | |
| 67 | 67 | bsmt2000_voice voice[MAX_VOICES]; /* the voices */ |
| 68 | 68 | UINT16 * regmap[128]; /* mapping of registers to voice params */ |
| 69 | ||
| 69 | UINT8 mode; /* current mode */ | |
| 70 | ||
| 70 | 71 | UINT32 clock; /* original clock on the chip */ |
| 71 | 72 | UINT8 stereo; /* stereo output? */ |
| 72 | 73 | UINT8 voices; /* number of voices */ |
| r8806 | r8807 | |
| 109 | 110 | ***************************************************************************/ |
| 110 | 111 | |
| 111 | 112 | /*------------------------------------------------- |
| 113 | bsmt2000_postload - save-state load callback | |
| 114 | -------------------------------------------------*/ | |
| 115 | ||
| 116 | static STATE_POSTLOAD( bsmt2000_postload ) | |
| 117 | { | |
| 118 | bsmt2000_chip *chip = (bsmt2000_chip*)param; | |
| 119 | set_mode(chip); | |
| 120 | } | |
| 121 | ||
| 122 | ||
| 123 | /*------------------------------------------------- | |
| 112 | 124 | DEVICE_START( bsmt2000 ) - initialization callback |
| 113 | 125 | -------------------------------------------------*/ |
| 114 | 126 | |
| r8806 | r8807 | |
| 126 | 138 | chip->total_banks = device->region()->bytes() / 0x10000; |
| 127 | 139 | |
| 128 | 140 | /* register chip-wide data for save states */ |
| 141 | state_save_register_postload(device->machine, bsmt2000_postload, chip); | |
| 129 | 142 | state_save_register_device_item(device, 0, chip->last_register); |
| 143 | state_save_register_device_item(device, 0, chip->mode); | |
| 130 | 144 | state_save_register_device_item(device, 0, chip->stereo); |
| 131 | 145 | state_save_register_device_item(device, 0, chip->voices); |
| 132 | 146 | state_save_register_device_item(device, 0, chip->adpcm); |
| r8806 | r8807 | |
| 168 | 182 | voice->rightvol = 0x7fff; |
| 169 | 183 | } |
| 170 | 184 | |
| 171 | /* recompute the mode */ | |
| 185 | /* recompute the mode - this comes from the address of the last register accessed */ | |
| 186 | chip->mode = chip->last_register; | |
| 172 | 187 | set_mode(chip); |
| 173 | 188 | } |
| 174 | 189 | |
| r8806 | r8807 | |
| 360 | 375 | /* force an update */ |
| 361 | 376 | stream_update(chip->stream); |
| 362 | 377 | |
| 363 | /* the mode comes from the address of the last register accessed */ | |
| 364 | switch (chip->last_register) | |
| 378 | switch (chip->mode) | |
| 365 | 379 | { |
| 366 | 380 | /* mode 0: 24kHz, 12 channel PCM, 1 channel ADPCM, mono */ |
| 367 | 381 | default: |
| r0 | r8807 | |
|---|---|---|
| 1 | /*************************************************************************** | |
| 2 | ||
| 3 | PeT mess@utanet.at | |
| 4 | ||
| 5 | ***************************************************************************/ | |
| 6 | ||
| 7 | #include "emu.h" | |
| 8 | #include "streams.h" | |
| 9 | #include "sound/s2636.h" | |
| 10 | ||
| 11 | ||
| 12 | typedef struct _s2636_sound s2636_sound; | |
| 13 | struct _s2636_sound | |
| 14 | { | |
| 15 | sound_stream *channel; | |
| 16 | UINT8 reg[1]; | |
| 17 | int size, pos; | |
| 18 | unsigned level; | |
| 19 | }; | |
| 20 | ||
| 21 | ||
| 22 | static s2636_sound *get_token(running_device *device) | |
| 23 | { | |
| 24 | assert(device != NULL); | |
| 25 | assert(device->type() == SOUND_S2636); | |
| 26 | return (s2636_sound *) downcast<legacy_device_base *>(device)->token(); | |
| 27 | } | |
| 28 | ||
| 29 | ||
| 30 | void s2636_soundport_w (running_device *device, int offset, int data) | |
| 31 | { | |
| 32 | s2636_sound *token = get_token(device); | |
| 33 | ||
| 34 | stream_update(token->channel); | |
| 35 | token->reg[offset] = data; | |
| 36 | switch (offset) | |
| 37 | { | |
| 38 | case 0: | |
| 39 | token->pos = 0; | |
| 40 | token->level = TRUE; | |
| 41 | // frequency 7874/(data+1) | |
| 42 | token->size = device->machine->sample_rate * (data + 1) /7874; | |
| 43 | break; | |
| 44 | } | |
| 45 | } | |
| 46 | ||
| 47 | ||
| 48 | ||
| 49 | /************************************/ | |
| 50 | /* Sound handler update */ | |
| 51 | /************************************/ | |
| 52 | ||
| 53 | static STREAM_UPDATE( s2636_update ) | |
| 54 | { | |
| 55 | int i; | |
| 56 | s2636_sound *token = get_token(device); | |
| 57 | stream_sample_t *buffer = outputs[0]; | |
| 58 | ||
| 59 | for (i = 0; i < samples; i++, buffer++) | |
| 60 | { | |
| 61 | *buffer = 0; | |
| 62 | if (token->reg[0] && token->pos <= token->size / 2) | |
| 63 | { | |
| 64 | *buffer = 0x7fff; | |
| 65 | } | |
| 66 | if (token->pos <= token->size) | |
| 67 | token->pos++; | |
| 68 | if (token->pos > token->size) | |
| 69 | token->pos = 0; | |
| 70 | } | |
| 71 | } | |
| 72 | ||
| 73 | ||
| 74 | ||
| 75 | /************************************/ | |
| 76 | /* Sound handler start */ | |
| 77 | /************************************/ | |
| 78 | ||
| 79 | static DEVICE_START(s2636_sound) | |
| 80 | { | |
| 81 | s2636_sound *token = get_token(device); | |
| 82 | memset(token, 0, sizeof(*token)); | |
| 83 | token->channel = stream_create(device, 0, 1, device->machine->sample_rate, 0, s2636_update); | |
| 84 | } | |
| 85 | ||
| 86 | ||
| 87 | DEVICE_GET_INFO( s2636_sound ) | |
| 88 | { | |
| 89 | switch (state) | |
| 90 | { | |
| 91 | /* --- the following bits of info are returned as 64-bit signed integers --- */ | |
| 92 | case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(s2636_sound); break; | |
| 93 | ||
| 94 | /* --- the following bits of info are returned as pointers to data or functions --- */ | |
| 95 | case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(s2636_sound); break; | |
| 96 | ||
| 97 | /* --- the following bits of info are returned as NULL-terminated strings --- */ | |
| 98 | case DEVINFO_STR_NAME: strcpy(info->s, "S2636"); break; | |
| 99 | case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; | |
| 100 | } | |
| 101 | } | |
| 102 | ||
| 103 | DEFINE_LEGACY_SOUND_DEVICE(S2636, s2636_sound); |
| r8806 | r8807 | |
|---|---|---|
| 159 | 159 | m_bank_installed(false), |
| 160 | 160 | m_bank_offs(0), |
| 161 | 161 | m_stream(NULL), |
| 162 | m_pin7_state(m_config.m_pin7) | |
| 162 | m_pin7_state(m_config.m_pin7), | |
| 163 | m_direct(NULL) | |
| 163 | 164 | { |
| 164 | 165 | } |
| 165 | 166 | |
| r8806 | r8807 | |
| 170 | 171 | |
| 171 | 172 | void okim6295_device::device_start() |
| 172 | 173 | { |
| 174 | // find our direct access | |
| 175 | m_direct = &space()->direct(); | |
| 176 | ||
| 173 | 177 | // create the stream |
| 174 | 178 | int divisor = m_config.m_pin7 ? 132 : 165; |
| 175 | 179 | m_stream = stream_create(this, 0, 1, clock() / divisor, this, static_stream_generate); |
| r8806 | r8807 | |
| 240 | 244 | |
| 241 | 245 | // iterate over voices and accumulate sample data |
| 242 | 246 | for (int voicenum = 0; voicenum < OKIM6295_VOICES; voicenum++) |
| 243 | m_voice[voicenum].generate_adpcm( | |
| 247 | m_voice[voicenum].generate_adpcm(*m_direct, outputs[0], samples); | |
| 244 | 248 | } |
| 245 | 249 | |
| 246 | 250 | |
| r8806 | r8807 | |
| 289 | 293 | |
| 290 | 294 | READ8_DEVICE_HANDLER( okim6295_r ) |
| 291 | 295 | { |
| 292 | return downcast<okim6295_device *>(device)-> | |
| 296 | return downcast<okim6295_device *>(device)-> | |
| 293 | 297 | } |
| 294 | 298 | |
| 295 | ||
| 299 | READ8_MEMBER( okim6295_device:: | |
| 296 | 300 | { |
| 297 | 301 | UINT8 result = 0xf0; // naname expects bits 4-7 to be 1 |
| 298 | 302 | |
| r8806 | r8807 | |
| 312 | 316 | |
| 313 | 317 | WRITE8_DEVICE_HANDLER( okim6295_w ) |
| 314 | 318 | { |
| 315 | downcast<okim6295_device *>(device)-> | |
| 319 | downcast<okim6295_device *>(device)-> | |
| 316 | 320 | } |
| 317 | 321 | |
| 318 | ||
| 322 | WRITE8_MEMBER( okim6295_device:: | |
| 319 | 323 | { |
| 320 | 324 | // if a command is pending, process the second half |
| 321 | 325 | if (m_command != -1) |
| r8806 | r8807 | |
| 337 | 341 | // determine the start/stop positions |
| 338 | 342 | offs_t base = m_command * 8; |
| 339 | 343 | |
| 340 | offs_t start = memory_raw_read_byte(space(), base + 0) << 16; | |
| 341 | start |= memory_raw_read_byte(space(), base + 1) << 8; | |
| 342 | start |= memory_raw_read_byte(space(), base + 2) << 0; | |
| 344 | offs_t start = m_direct->read_raw_byte(base + 0) << 16; | |
| 345 | start |= m_direct->read_raw_byte(base + 1) << 8; | |
| 346 | start |= m_direct->read_raw_byte(base + 2) << 0; | |
| 343 | 347 | start &= 0x3ffff; |
| 344 | 348 | |
| 345 | offs_t stop = memory_raw_read_byte(space(), base + 3) << 16; | |
| 346 | stop |= memory_raw_read_byte(space(), base + 4) << 8; | |
| 347 | stop |= memory_raw_read_byte(space(), base + 5) << 0; | |
| 349 | offs_t stop = m_direct->read_raw_byte(base + 3) << 16; | |
| 350 | stop |= m_direct->read_raw_byte(base + 4) << 8; | |
| 351 | stop |= m_direct->read_raw_byte(base + 5) << 0; | |
| 348 | 352 | stop &= 0x3ffff; |
| 349 | 353 | |
| 350 | 354 | // set up the voice to play this sample |
| r8806 | r8807 | |
| 420 | 424 | // add them to an output stream |
| 421 | 425 | //------------------------------------------------- |
| 422 | 426 | |
| 423 | void okim6295_device::okim_voice::generate_adpcm(c | |
| 427 | void okim6295_device::okim_voice::generate_adpcm(direc | |
| 424 | 428 | { |
| 425 | 429 | // skip if not active |
| 426 | 430 | if (!m_playing) |
| r8806 | r8807 | |
| 430 | 434 | while (samples-- != 0) |
| 431 | 435 | { |
| 432 | 436 | // fetch the next sample byte |
| 433 | int nibble = | |
| 437 | int nibble = direct.read_raw_ | |
| 434 | 438 | |
| 435 | 439 | // output to the buffer, scaling by the volume |
| 436 | 440 | // signal in range -2048..2047, volume in range 2..32 => signal * volume / 2 in range -32768..32767 |
| r0 | r8807 | |
|---|---|---|
| 1 | /***************************************************************************** | |
| 2 | * | |
| 3 | * sound/s2636.h | |
| 4 | * | |
| 5 | ****************************************************************************/ | |
| 6 | ||
| 7 | #ifndef S2636_SOUND_H_ | |
| 8 | #define S2636_SOUND_H_ | |
| 9 | ||
| 10 | ||
| 11 | ||
| 12 | DECLARE_LEGACY_SOUND_DEVICE(S2636, s2636_sound); | |
| 13 | void s2636_soundport_w (running_device *device, int mode, int data); | |
| 14 | ||
| 15 | ||
| 16 | #endif /* VC4000_H_ */ |
| r8806 | r8807 | |
|---|---|---|
| 122 | 122 | void set_bank_base(offs_t base); |
| 123 | 123 | void set_pin7(int pin7); |
| 124 | 124 | |
| 125 | UINT8 status_read(); | |
| 126 | void data_write(UINT8 data); | |
| 125 | DECLARE_READ8_MEMBER( read ); | |
| 126 | DECLARE_WRITE8_MEMBER( write ); | |
| 127 | 127 | |
| 128 | 128 | protected: |
| 129 | 129 | // device-level overrides |
| r8806 | r8807 | |
| 141 | 141 | { |
| 142 | 142 | public: |
| 143 | 143 | okim_voice(); |
| 144 | void generate_adpcm(c | |
| 144 | void generate_adpcm(direc | |
| 145 | 145 | |
| 146 | 146 | adpcm_state m_adpcm; // current ADPCM state |
| 147 | 147 | bool m_playing; |
| r8806 | r8807 | |
| 156 | 156 | |
| 157 | 157 | const okim6295_device_config &m_config; |
| 158 | 158 | |
| 159 | okim_voice m_voice[OKIM6295_VOICES]; | |
| 160 | INT32 m_command; | |
| 161 | bool m_bank_installed; | |
| 162 | offs_t m_bank_offs; | |
| 163 | sound_stream * m_stream; | |
| 164 | UINT8 m_pin7_state; | |
| 159 | okim_voice m_voice[OKIM6295_VOICES]; | |
| 160 | INT32 m_command; | |
| 161 | bool m_bank_installed; | |
| 162 | offs_t m_bank_offs; | |
| 163 | sound_stream * m_stream; | |
| 164 | UINT8 m_pin7_state; | |
| 165 | direct_read_data * m_direct; | |
| 165 | 166 | |
| 166 | 167 | static const UINT8 s_volume_table[16]; |
| 167 | 168 | }; |
| r8806 | r8807 | |
|---|---|---|
| 676 | 676 | mix = auto_alloc_array(device->machine, INT32, 44100*2); |
| 677 | 677 | } |
| 678 | 678 | |
| 679 | static void ymf278b_register_save_state(running_device *device, YMF278BChip *chip) | |
| 680 | { | |
| 681 | int i; | |
| 682 | ||
| 683 | state_save_register_device_item(device, 0, chip->lsitest0); | |
| 684 | state_save_register_device_item(device, 0, chip->lsitest1); | |
| 685 | state_save_register_device_item(device, 0, chip->wavetblhdr); | |
| 686 | state_save_register_device_item(device, 0, chip->memmode); | |
| 687 | state_save_register_device_item(device, 0, chip->memadr); | |
| 688 | state_save_register_device_item(device, 0, chip->fm_l); | |
| 689 | state_save_register_device_item(device, 0, chip->fm_r); | |
| 690 | state_save_register_device_item(device, 0, chip->pcm_l); | |
| 691 | state_save_register_device_item(device, 0, chip->pcm_r); | |
| 692 | state_save_register_device_item(device, 0, chip->timer_a_count); | |
| 693 | state_save_register_device_item(device, 0, chip->timer_b_count); | |
| 694 | state_save_register_device_item(device, 0, chip->enable); | |
| 695 | state_save_register_device_item(device, 0, chip->current_irq); | |
| 696 | state_save_register_device_item(device, 0, chip->irq_line); | |
| 697 | state_save_register_device_item(device, 0, chip->port_A); | |
| 698 | state_save_register_device_item(device, 0, chip->port_B); | |
| 699 | state_save_register_device_item(device, 0, chip->port_C); | |
| 700 | ||
| 701 | for (i = 0; i < 24; ++i) | |
| 702 | { | |
| 703 | state_save_register_device_item(device, i, chip->slots[i].wave); | |
| 704 | state_save_register_device_item(device, i, chip->slots[i].FN); | |
| 705 | state_save_register_device_item(device, i, chip->slots[i].OCT); | |
| 706 | state_save_register_device_item(device, i, chip->slots[i].PRVB); | |
| 707 | state_save_register_device_item(device, i, chip->slots[i].LD); | |
| 708 | state_save_register_device_item(device, i, chip->slots[i].TL); | |
| 709 | state_save_register_device_item(device, i, chip->slots[i].pan); | |
| 710 | state_save_register_device_item(device, i, chip->slots[i].lfo); | |
| 711 | state_save_register_device_item(device, i, chip->slots[i].vib); | |
| 712 | state_save_register_device_item(device, i, chip->slots[i].AM); | |
| 713 | ||
| 714 | state_save_register_device_item(device, i, chip->slots[i].AR); | |
| 715 | state_save_register_device_item(device, i, chip->slots[i].D1R); | |
| 716 | state_save_register_device_item(device, i, chip->slots[i].DL); | |
| 717 | state_save_register_device_item(device, i, chip->slots[i].D2R); | |
| 718 | state_save_register_device_item(device, i, chip->slots[i].RC); | |
| 719 | state_save_register_device_item(device, i, chip->slots[i].RR); | |
| 720 | ||
| 721 | state_save_register_device_item(device, i, chip->slots[i].step); | |
| 722 | state_save_register_device_item(device, i, chip->slots[i].stepptr); | |
| 723 | ||
| 724 | state_save_register_device_item(device, i, chip->slots[i].active); | |
| 725 | state_save_register_device_item(device, i, chip->slots[i].bits); | |
| 726 | state_save_register_device_item(device, i, chip->slots[i].startaddr); | |
| 727 | state_save_register_device_item(device, i, chip->slots[i].loopaddr); | |
| 728 | state_save_register_device_item(device, i, chip->slots[i].endaddr); | |
| 729 | ||
| 730 | state_save_register_device_item(device, i, chip->slots[i].env_step); | |
| 731 | state_save_register_device_item(device, i, chip->slots[i].env_vol); | |
| 732 | state_save_register_device_item(device, i, chip->slots[i].env_vol_step); | |
| 733 | state_save_register_device_item(device, i, chip->slots[i].env_vol_lim); | |
| 734 | } | |
| 735 | } | |
| 736 | ||
| 679 | 737 | static DEVICE_START( ymf278b ) |
| 680 | 738 | { |
| 681 | 739 | static const ymf278b_interface defintrf = { 0 }; |
| r8806 | r8807 | |
| 706 | 764 | for(i=0; i<7; i++) |
| 707 | 765 | chip->mix_level[i] = chip->volume[8*i+8]; |
| 708 | 766 | chip->mix_level[7] = 0; |
| 767 | ||
| 768 | // Register state for saving | |
| 769 | ymf278b_register_save_state(device, chip); | |
| 709 | 770 | } |
| 710 | 771 | |
| 711 | 772 | |
| 712 | ||
| 713 | ||
| 714 | 773 | /************************************************************************** |
| 715 | 774 | * Generic get_info |
| 716 | 775 | **************************************************************************/ |
| r8806 | r8807 | |
|---|---|---|
| 8 | 8 | #include "streams.h" |
| 9 | 9 | #include "k053260.h" |
| 10 | 10 | |
| 11 | /* 2004-02-28: Fixed | |
| 11 | /* 2004-02-28: Fixed PPCM decoding. Games sound much better now.*/ | |
| 12 | 12 | |
| 13 | 13 | #define LOG 0 |
| 14 | 14 | |
| r8806 | r8807 | |
| 22 | 22 | UINT32 start; |
| 23 | 23 | UINT32 bank; |
| 24 | 24 | UINT32 volume; |
| 25 | int | |
| 25 | int | |
| 26 | 26 | UINT32 pan; |
| 27 | 27 | UINT32 pos; |
| 28 | int loop; | |
| 29 | int ppcm; /* packed PCM ( 4 bit signed ) */ | |
| 30 | int ppcm_data; | |
| 28 | int loop; | |
| 29 | int ppcm; /* packed PCM ( 4 bit signed ) */ | |
| 30 | int ppcm_data; | |
| 31 | 31 | }; |
| 32 | 32 | |
| 33 | 33 | typedef struct _k053260_state k053260_state; |
| 34 | struct _k053260_state { | |
| 35 | sound_stream * channel; | |
| 36 | int mode; | |
| 37 | int regs[0x30]; | |
| 38 | UINT8 *rom; | |
| 39 | int rom_size; | |
| 40 | UINT32 *delta_table; | |
| 41 | k053260_channel channels[4]; | |
| 42 | const k053260_interface *intf; | |
| 43 | running_device *device; | |
| 34 | struct _k053260_state | |
| 35 | { | |
| 36 | sound_stream * channel; | |
| 37 | int mode; | |
| 38 | int regs[0x30]; | |
| 39 | UINT8 *rom; | |
| 40 | int rom_size; | |
| 41 | UINT32 *delta_table; | |
| 42 | k053260_channel channels[4]; | |
| 43 | const k053260_interface *intf; | |
| 44 | running_device *device; | |
| 44 | 45 | }; |
| 45 | 46 | |
| 46 | 47 | INLINE k053260_state *get_safe_token(running_device *device) |
| r8806 | r8807 | |
| 51 | 52 | } |
| 52 | 53 | |
| 53 | 54 | |
| 54 | static void InitDeltaTable( k053260_state *ic, int rate, int clock ) { | |
| 55 | static void InitDeltaTable( k053260_state *ic, int rate, int clock ) | |
| 56 | { | |
| 55 | 57 | int i; |
| 56 | 58 | double base = ( double )rate; |
| 57 | 59 | double max = (double)(clock); /* Hz */ |
| r8806 | r8807 | |
| 74 | 76 | } |
| 75 | 77 | } |
| 76 | 78 | |
| 77 | static DEVICE_RESET( k053260 ) { | |
| 79 | static DEVICE_RESET( k053260 ) | |
| 80 | { | |
| 78 | 81 | k053260_state *ic = get_safe_token(device); |
| 79 | 82 | int i; |
| 80 | 83 | |
| r8806 | r8807 | |
| 93 | 96 | } |
| 94 | 97 | } |
| 95 | 98 | |
| 96 | INLINE int limit( int val, int max, int min ) { | |
| 99 | INLINE int limit( int val, int max, int min ) | |
| 100 | { | |
| 97 | 101 | if ( val > max ) |
| 98 | 102 | val = max; |
| 99 | 103 | else if ( val < min ) |
| r8806 | r8807 | |
| 105 | 109 | #define MAXOUT 0x7fff |
| 106 | 110 | #define MINOUT -0x8000 |
| 107 | 111 | |
| 108 | static STREAM_UPDATE( k053260_update ) { | |
| 112 | static STREAM_UPDATE( k053260_update ) | |
| 113 | { | |
| 109 | 114 | static const long dpcmcnv[] = { 0,1,2,4,8,16,32,64, -128, -64, -32, -16, -8, -4, -2, -1}; |
| 110 | 115 | |
| 111 | 116 | int i, j, lvol[4], rvol[4], play[4], loop[4], ppcm_data[4], ppcm[4]; |
| r8806 | r8807 | |
| 233 | 238 | |
| 234 | 239 | InitDeltaTable( ic, rate, device->clock() ); |
| 235 | 240 | |
| 241 | /* register with the save state system */ | |
| 242 | state_save_register_device_item(device, 0, ic->mode); | |
| 243 | state_save_register_device_item_array(device, 0, ic->regs); | |
| 244 | ||
| 245 | for ( i = 0; i < 4; i++ ) | |
| 246 | { | |
| 247 | state_save_register_device_item(device, i, ic->channels[i].rate); | |
| 248 | state_save_register_device_item(device, i, ic->channels[i].size); | |
| 249 | state_save_register_device_item(device, i, ic->channels[i].start); | |
| 250 | state_save_register_device_item(device, i, ic->channels[i].bank); | |
| 251 | state_save_register_device_item(device, i, ic->channels[i].volume); | |
| 252 | state_save_register_device_item(device, i, ic->channels[i].play); | |
| 253 | state_save_register_device_item(device, i, ic->channels[i].pan); | |
| 254 | state_save_register_device_item(device, i, ic->channels[i].pos); | |
| 255 | state_save_register_device_item(device, i, ic->channels[i].loop); | |
| 256 | state_save_register_device_item(device, i, ic->channels[i].ppcm); | |
| 257 | state_save_register_device_item(device, i, ic->channels[i].ppcm_data); | |
| 258 | } | |
| 259 | ||
| 236 | 260 | /* setup SH1 timer if necessary */ |
| 237 | 261 | if ( ic->intf->irq ) |
| 238 | 262 | timer_pulse( device->machine, attotime_mul(ATTOTIME_IN_HZ(device->clock()), 32), NULL, 0, ic->intf->irq ); |
| 239 | 263 | } |
| 240 | 264 | |
| 241 | INLINE void check_bounds( k053260_state *ic, int channel ) { | |
| 265 | INLINE void check_bounds( k053260_state *ic, int channel ) | |
| 266 | { | |
| 242 | 267 | |
| 243 | 268 | int channel_start = ( ic->channels[channel].bank << 16 ) + ic->channels[channel].start; |
| 244 | 269 | int channel_end = channel_start + ic->channels[channel].size - 1; |
| 245 | 270 | |
| 246 | 271 | if ( channel_start > ic->rom_size ) { |
| 247 | logerror("K53260: Attempting to start playing past the end of the | |
| 272 | logerror("K53260: Attempting to start playing past the end of the ROM ( start = %06x, end = %06x ).\n", channel_start, channel_end ); | |
| 248 | 273 | |
| 249 | 274 | ic->channels[channel].play = 0; |
| 250 | 275 | |
| r8806 | r8807 | |
| 252 | 277 | } |
| 253 | 278 | |
| 254 | 279 | if ( channel_end > ic->rom_size ) { |
| 255 | logerror("K53260: Attempting to play past the end of the | |
| 280 | logerror("K53260: Attempting to play past the end of the ROM ( start = %06x, end = %06x ).\n", channel_start, channel_end ); | |
| 256 | 281 | |
| 257 | 282 | ic->channels[channel].size = ic->rom_size - channel_start; |
| 258 | 283 | } |
| r8806 | r8807 | |
| 392 | 417 | } |
| 393 | 418 | break; |
| 394 | 419 | |
| 395 | case 0x2e: /* read | |
| 420 | case 0x2e: /* read ROM */ | |
| 396 | 421 | if ( ic->mode & 1 ) |
| 397 | 422 | { |
| 398 | 423 | UINT32 offs = ic->channels[0].start + ( ic->channels[0].pos >> BASE_SHIFT ) + ( ic->channels[0].bank << 16 ); |
| r8806 | r8807 | |
| 400 | 425 | ic->channels[0].pos += ( 1 << 16 ); |
| 401 | 426 | |
| 402 | 427 | if ( offs > ic->rom_size ) { |
| 403 | logerror("%s: K53260: Attempting to read past | |
| 428 | logerror("%s: K53260: Attempting to read past ROM size in ROM Read Mode (offs = %06x, size = %06x).\n", cpuexec_describe_context(device->machine),offs,ic->rom_size ); | |
| 404 | 429 | |
| 405 | 430 | return 0; |
| 406 | 431 | } |
| r8806 | r8807 | |
| 427 | 452 | /* --- the following bits of info are returned as pointers to data or functions --- */ |
| 428 | 453 | case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( k053260 ); break; |
| 429 | 454 | case DEVINFO_FCT_STOP: /* nothing */ break; |
| 430 | case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( k053260); break; | |
| 455 | case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( k053260 ); break; | |
| 431 | 456 | |
| 432 | 457 | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
| 433 | 458 | case DEVINFO_STR_NAME: strcpy(info->s, "K053260"); break; |
| 434 | case DEVINFO_STR_FAMILY: strcpy(info->s, "Konami custom"); break; | |
| 435 | case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break; | |
| 436 | case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; | |
| 437 | case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break; | |
| 459 | case DEVINFO_STR_FAMILY: strcpy(info->s, "Konami custom"); break; | |
| 460 | case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break; | |
| 461 | case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; | |
| 462 | case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break; | |
| 438 | 463 | } |
| 439 | 464 | } |
| 440 | 465 |
| r8806 | r8807 | |
|---|---|---|
| 392 | 392 | endif |
| 393 | 393 | |
| 394 | 394 | |
| 395 | #------------------------------------------------- | |
| 396 | # S2636 wave generator | |
| 397 | #------------------------------------------------- | |
| 395 | 398 | |
| 399 | ifneq ($(filter S2636,$(SOUNDS)),) | |
| 400 | SOUNDOBJS += $(SOUNDOBJ)/s2636.o | |
| 401 | endif | |
| 402 | ||
| 396 | 403 | #------------------------------------------------- |
| 397 | 404 | # Sega custom sound chips |
| 398 | 405 | #------------------------------------------------- |
| r8806 | r8807 | |
|---|---|---|
| 85 | 85 | #define ENVVOL(chan) (VR0->SOUNDREGS[(0x20/4)*chan+0x04/4]&0xffffff) |
| 86 | 86 | |
| 87 | 87 | /* |
| 88 | #define GETSOUNDREG16(Chan,Offs) memory_read_word_32le(space,VR0->Intf.reg_base+0x20*Chan+Offs) | |
| 89 | #define GETSOUNDREG32(Chan,Offs) memory_read_dword_32le(space,VR0->Intf.reg_base+0x20*Chan+Offs) | |
| 88 | #define GETSOUNDREG16(Chan,Offs) space->read_word(VR0->Intf.reg_base+0x20*Chan+Offs) | |
| 89 | #define GETSOUNDREG32(Chan,Offs) space->read_dword(VR0->Intf.reg_base+0x20*Chan+Offs) | |
| 90 | 90 | |
| 91 | 91 | #define CURSADDR(chan) GETSOUNDREG32(chan,0x00) |
| 92 | 92 | #define DSADDR(chan) GETSOUNDREG16(chan,0x08) |
| r8806 | r8807 | |
|---|---|---|
| 397 | 397 | chip->sound_enable = 1; |
| 398 | 398 | |
| 399 | 399 | /* register with the save state system */ |
| 400 | state_save_register_device_item_pointer(device, 0, chip->soundregs, 0x400); | |
| 400 | 401 | state_save_register_device_item(device, 0, chip->num_voices); |
| 401 | 402 | state_save_register_device_item(device, 0, chip->sound_enable); |
| 402 | 403 | state_save_register_device_item_pointer(device, 0, chip->waveform[0], |
| r8806 | r8807 | |
|---|---|---|
| 1 | 1 | /* |
| 2 | 2 | vlm5030.c |
| 3 | 3 | |
| 4 | VLM5030 emulator | |
| 4 | Sanyo VLM5030 emulator | |
| 5 | 5 | |
| 6 | 6 | Written by Tatsuyuki Satoh |
| 7 | 7 | Based on TMS5220 simulator (tms5220.c) |
| 8 | 8 | |
| 9 | +-------,_,-------+ | |
| 10 | GND -- | 1 40 | <- RST | |
| 11 | (gnd) TST1 -> | 2 39 | ?? TST4 | |
| 12 | OSC2 ck | 3 _ 38 | ?? TST3 | |
| 13 | OSC1 ck | 4 (_) 37 | ?? TST2 | |
| 14 | D0 -> | 5 36 | -> DAO | |
| 15 | D1 -> | 6 35 | -- VREF (+5v thru 5.6k resistor) | |
| 16 | D2 -> | 7 34 | -> MTE | |
| 17 | D3 -> | 8 V 33 | -> /ME | |
| 18 | D4 -> | 9 L 32 | <- VCU | |
| 19 | D5 -> | 10 M 31 | <- START | |
| 20 | D6 -> | 11 5 30 | -> BSY | |
| 21 | D7 -> | 12 0 29 | -- Vdd (+5v) | |
| 22 | A0 <- | 13 3 28 | -> A15 | |
| 23 | A1 <- | 14 0 27 | -> A14 | |
| 24 | A2 <- | 15 26 | -> A13 | |
| 25 | A3 <- | 16 _ 25 | -> A12 | |
| 26 | A4 <- | 17 (_) 24 | -> A11 | |
| 27 | A5 <- | 18 23 | -> A10 | |
| 28 | A6 <- | 19 22 | -> A9 | |
| 29 | A7 <- | 20 21 | -> A8 | |
| 30 | +-----------------+ | |
| 31 | ||
| 32 | TST1 is probably a test mode enable pin, must be grounded for normal operation. | |
| 33 | TST2-4 are some sort of test pins but can be left floating? | |
| 34 | VREF is probably the 0v ref for the output dac | |
| 35 | DAO is the output dac | |
| 36 | /ME is connected to the voice data rom /OE enable | |
| 37 | START strobes in a byte of data over the data bus from host cpu | |
| 38 | OSC1/2 are to both ends of a 3.579545MHz xtal with a 100pf cap from each end to gnd | |
| 39 | VCU makes the data bus select the upper 8 bits of the word register internally instead of the lower 8 bits. it is only useful if you need more than 256 phrases in rom? (recheck this) | |
| 40 | MTE is an output for roms which need to be clocked to latch address before use, or for a latch sitting in front of the voice rom address lines? (recheck this) | |
| 41 | RST not only resets the chip on its rising edge but grabs a byte of mode state data from the data bus on its falling edge? (recheck this) | |
| 42 | ||
| 9 | 43 | note: |
| 10 | 44 | memory read cycle(==sampling rate) = 122.9u(440clock) |
| 11 | 45 | interpolator (LC8109 = 2.5ms) = 20 * samples(125us) |
| r8806 | r8807 | |
|---|---|---|
| 384 | 384 | bit_pos = 7 - (chan->bits_left & 7); |
| 385 | 385 | if (7 == bit_pos) |
| 386 | 386 | { |
| 387 | chan->cur_byte = | |
| 387 | chan->cur_byte = | |
| 388 | 388 | chan->address++; |
| 389 | 389 | chan->length--; |
| 390 | 390 | } |
| r8806 | r8807 | |
|---|---|---|
| 158 | 158 | |
| 159 | 159 | |
| 160 | 160 | // base class for all driver data structures |
| 161 | class driver_data_t | |
| 161 | class driver_data_t : public bindable_object | |
| 162 | 162 | { |
| 163 | 163 | public: |
| 164 | 164 | driver_data_t(running_machine &machine); |
| r8806 | r8807 | |
| 271 | 271 | |
| 272 | 272 | |
| 273 | 273 | // description of the currently-running machine |
| 274 | class running_machine | |
| 274 | class running_machine : public bindable_object | |
| 275 | 275 | { |
| 276 | 276 | DISABLE_COPYING(running_machine); |
| 277 | 277 | |
| r8806 | r8807 | |
| 346 | 346 | |
| 347 | 347 | // CPU information |
| 348 | 348 | cpu_device * firstcpu; // first CPU (allows for quick iteration via typenext) |
| 349 | address_space * m_nonspecific_space;// a dummy address_space used for legacy compatibility | |
| 349 | 350 | |
| 350 | 351 | // game-related information |
| 351 | 352 | const game_driver * gamedrv; // points to the definition of the game machine |
| r8806 | r8807 | |
|---|---|---|
| 85 | 85 | * |
| 86 | 86 | *************************************/ |
| 87 | 87 | |
| 88 | INLINE UINT16 read16be_with_read8_handler(read8_space_func handler, | |
| 88 | INLINE UINT16 read16be_with_read8_handler(read8_space_func handler, | |
| 89 | 89 | { |
| 90 | 90 | UINT16 result = 0; |
| 91 | 91 | if (ACCESSING_BITS_8_15) |
| r8806 | r8807 | |
| 96 | 96 | } |
| 97 | 97 | |
| 98 | 98 | |
| 99 | INLINE void write16be_with_write8_handler(write8_space_func handler, | |
| 99 | INLINE void write16be_with_write8_handler(write8_space_func handler, | |
| 100 | 100 | { |
| 101 | 101 | if (ACCESSING_BITS_8_15) |
| 102 | 102 | (*handler)(space, offset * 2 + 0, data >> 8); |
| r8806 | r8807 | |
| 111 | 111 | * |
| 112 | 112 | *************************************/ |
| 113 | 113 | |
| 114 | INLINE UINT16 read16le_with_read8_handler(read8_space_func handler, | |
| 114 | INLINE UINT16 read16le_with_read8_handler(read8_space_func handler, | |
| 115 | 115 | { |
| 116 | 116 | UINT16 result = 0; |
| 117 | 117 | if (ACCESSING_BITS_0_7) |
| r8806 | r8807 | |
| 122 | 122 | } |
| 123 | 123 | |
| 124 | 124 | |
| 125 | INLINE void write16le_with_write8_handler(write8_space_func handler, | |
| 125 | INLINE void write16le_with_write8_handler(write8_space_func handler, | |
| 126 | 126 | { |
| 127 | 127 | if (ACCESSING_BITS_0_7) |
| 128 | 128 | (*handler)(space, offset * 2 + 0, data >> 0); |
| r8806 | r8807 | |
| 137 | 137 | * |
| 138 | 138 | *************************************/ |
| 139 | 139 | |
| 140 | INLINE UINT32 read32be_with_read8_handler(read8_space_func handler, | |
| 140 | INLINE UINT32 read32be_with_read8_handler(read8_space_func handler, | |
| 141 | 141 | { |
| 142 | 142 | UINT32 result = 0; |
| 143 | 143 | if (ACCESSING_BITS_16_31) |
| r8806 | r8807 | |
| 148 | 148 | } |
| 149 | 149 | |
| 150 | 150 | |
| 151 | INLINE void write32be_with_write8_handler(write8_space_func handler, | |
| 151 | INLINE void write32be_with_write8_handler(write8_space_func handler, | |
| 152 | 152 | { |
| 153 | 153 | if (ACCESSING_BITS_16_31) |
| 154 | 154 | write16be_with_write8_handler(handler, space, offset * 2 + 0, data >> 16, mem_mask >> 16); |
| r8806 | r8807 | |
| 163 | 163 | * |
| 164 | 164 | *************************************/ |
| 165 | 165 | |
| 166 | INLINE UINT32 read32le_with_read8_handler(read8_space_func handler, | |
| 166 | INLINE UINT32 read32le_with_read8_handler(read8_space_func handler, | |
| 167 | 167 | { |
| 168 | 168 | UINT32 result = 0; |
| 169 | 169 | if (ACCESSING_BITS_0_15) |
| r8806 | r8807 | |
| 174 | 174 | } |
| 175 | 175 | |
| 176 | 176 | |
| 177 | INLINE void write32le_with_write8_handler(write8_space_func handler, | |
| 177 | INLINE void write32le_with_write8_handler(write8_space_func handler, | |
| 178 | 178 | { |
| 179 | 179 | if (ACCESSING_BITS_0_15) |
| 180 | 180 | write16le_with_write8_handler(handler, space, offset * 2 + 0, data, mem_mask); |
| r8806 | r8807 | |
| 189 | 189 | * |
| 190 | 190 | *************************************/ |
| 191 | 191 | |
| 192 | INLINE UINT32 read32be_with_16be_handler(read16_space_func handler, | |
| 192 | INLINE UINT32 read32be_with_16be_handler(read16_space_func handler, | |
| 193 | 193 | { |
| 194 | 194 | UINT32 result = 0; |
| 195 | 195 | if (ACCESSING_BITS_16_31) |
| r8806 | r8807 | |
| 200 | 200 | } |
| 201 | 201 | |
| 202 | 202 | |
| 203 | INLINE void write32be_with_16be_handler(write16_space_func handler, | |
| 203 | INLINE void write32be_with_16be_handler(write16_space_func handler, | |
| 204 | 204 | { |
| 205 | 205 | if (ACCESSING_BITS_16_31) |
| 206 | 206 | (*handler)(space, offset * 2 + 0, data >> 16, mem_mask >> 16); |
| r8806 | r8807 | |
| 215 | 215 | * |
| 216 | 216 | *************************************/ |
| 217 | 217 | |
| 218 | INLINE UINT32 read32le_with_16le_handler(read16_space_func handler, | |
| 218 | INLINE UINT32 read32le_with_16le_handler(read16_space_func handler, | |
| 219 | 219 | { |
| 220 | 220 | UINT32 result = 0; |
| 221 | 221 | if (ACCESSING_BITS_0_15) |
| r8806 | r8807 | |
| 226 | 226 | } |
| 227 | 227 | |
| 228 | 228 | |
| 229 | INLINE void write32le_with_16le_handler(write16_space_func handler, | |
| 229 | INLINE void write32le_with_16le_handler(write16_space_func handler, | |
| 230 | 230 | { |
| 231 | 231 | if (ACCESSING_BITS_0_15) |
| 232 | 232 | (*handler)(space, offset * 2 + 0, data, mem_mask); |
| r8806 | r8807 | |
| 241 | 241 | * |
| 242 | 242 | *************************************/ |
| 243 | 243 | |
| 244 | INLINE UINT32 read32be_with_16le_handler(read16_space_func handler, | |
| 244 | INLINE UINT32 read32be_with_16le_handler(read16_space_func handler, | |
| 245 | 245 | { |
| 246 | 246 | UINT32 result = 0; |
| 247 | 247 | mem_mask = FLIPENDIAN_INT32(mem_mask); |
| r8806 | r8807 | |
| 250 | 250 | } |
| 251 | 251 | |
| 252 | 252 | |
| 253 | INLINE void write32be_with_16le_handler(write16_space_func handler, | |
| 253 | INLINE void write32be_with_16le_handler(write16_space_func handler, | |
| 254 | 254 | { |
| 255 | 255 | data = FLIPENDIAN_INT32(data); |
| 256 | 256 | mem_mask = FLIPENDIAN_INT32(mem_mask); |
| r8806 | r8807 | |
| 264 | 264 | * |
| 265 | 265 | *************************************/ |
| 266 | 266 | |
| 267 | INLINE UINT32 read32le_with_16be_handler(read16_space_func handler, | |
| 267 | INLINE UINT32 read32le_with_16be_handler(read16_space_func handler, | |
| 268 | 268 | { |
| 269 | 269 | UINT32 result = 0; |
| 270 | 270 | mem_mask = FLIPENDIAN_INT32(mem_mask); |
| r8806 | r8807 | |
| 273 | 273 | } |
| 274 | 274 | |
| 275 | 275 | |
| 276 | INLINE void write32le_with_16be_handler(write16_space_func handler, | |
| 276 | INLINE void write32le_with_16be_handler(write16_space_func handler, | |
| 277 | 277 | { |
| 278 | 278 | data = FLIPENDIAN_INT32(data); |
| 279 | 279 | mem_mask = FLIPENDIAN_INT32(mem_mask); |
| r8806 | r8807 | |
| 287 | 287 | * |
| 288 | 288 | *************************************/ |
| 289 | 289 | |
| 290 | INLINE UINT64 read64be_with_read8_handler(read8_space_func handler, | |
| 290 | INLINE UINT64 read64be_with_read8_handler(read8_space_func handler, | |
| 291 | 291 | { |
| 292 | 292 | UINT64 result = 0; |
| 293 | 293 | if (ACCESSING_BITS_32_63) |
| r8806 | r8807 | |
| 298 | 298 | } |
| 299 | 299 | |
| 300 | 300 | |
| 301 | INLINE void write64be_with_write8_handler(write8_space_func handler, | |
| 301 | INLINE void write64be_with_write8_handler(write8_space_func handler, | |
| 302 | 302 | { |
| 303 | 303 | if (ACCESSING_BITS_32_63) |
| 304 | 304 | write32be_with_write8_handler(handler, space, offset * 2 + 0, data >> 32, mem_mask >> 32); |
| r8806 | r8807 | |
| 313 | 313 | * |
| 314 | 314 | *************************************/ |
| 315 | 315 | |
| 316 | INLINE UINT64 read64le_with_read8_handler(read8_space_func handler, | |
| 316 | INLINE UINT64 read64le_with_read8_handler(read8_space_func handler, | |
| 317 | 317 | { |
| 318 | 318 | UINT64 result = 0; |
| 319 | 319 | if (ACCESSING_BITS_0_31) |
| r8806 | r8807 | |
| 324 | 324 | } |
| 325 | 325 | |
| 326 | 326 | |
| 327 | INLINE void write64le_with_write8_handler(write8_space_func handler, | |
| 327 | INLINE void write64le_with_write8_handler(write8_space_func handler, | |
| 328 | 328 | { |
| 329 | 329 | if (ACCESSING_BITS_0_31) |
| 330 | 330 | write32le_with_write8_handler(handler, space, offset * 2 + 0, data >> 0, mem_mask >> 0); |
| r8806 | r8807 | |
| 339 | 339 | * |
| 340 | 340 | *************************************/ |
| 341 | 341 | |
| 342 | INLINE UINT32 read64be_with_16be_handler(read16_space_func handler, | |
| 342 | INLINE UINT32 read64be_with_16be_handler(read16_space_func handler, | |
| 343 | 343 | { |
| 344 | 344 | UINT64 result = 0; |
| 345 | 345 | if (ACCESSING_BITS_32_63) |
| r8806 | r8807 | |
| 350 | 350 | } |
| 351 | 351 | |
| 352 | 352 | |
| 353 | INLINE void write64be_with_16be_handler(write16_space_func handler, | |
| 353 | INLINE void write64be_with_16be_handler(write16_space_func handler, | |
| 354 | 354 | { |
| 355 | 355 | if (ACCESSING_BITS_32_63) |
| 356 | 356 | write32be_with_16be_handler(handler, space, offset * 2 + 0, data >> 32, mem_mask >> 32); |
| r8806 | r8807 | |
| 365 | 365 | * |
| 366 | 366 | *************************************/ |
| 367 | 367 | |
| 368 | INLINE UINT32 read64le_with_16le_handler(read16_space_func handler, | |
| 368 | INLINE UINT32 read64le_with_16le_handler(read16_space_func handler, | |
| 369 | 369 | { |
| 370 | 370 | UINT64 result = 0; |
| 371 | 371 | if (ACCESSING_BITS_0_31) |
| r8806 | r8807 | |
| 376 | 376 | } |
| 377 | 377 | |
| 378 | 378 | |
| 379 | INLINE void write64le_with_16le_handler(write16_space_func handler, | |
| 379 | INLINE void write64le_with_16le_handler(write16_space_func handler, | |
| 380 | 380 | { |
| 381 | 381 | if (ACCESSING_BITS_0_31) |
| 382 | 382 | write32le_with_16le_handler(handler, space, offset * 2 + 0, data >> 0, mem_mask >> 0); |
| r8806 | r8807 | |
| 391 | 391 | * |
| 392 | 392 | *************************************/ |
| 393 | 393 | |
| 394 | INLINE UINT32 read64be_with_16le_handler(read16_space_func handler, | |
| 394 | INLINE UINT32 read64be_with_16le_handler(read16_space_func handler, | |
| 395 | 395 | { |
| 396 | 396 | UINT64 result = 0; |
| 397 | 397 | if (ACCESSING_BITS_32_63) |
| r8806 | r8807 | |
| 402 | 402 | } |
| 403 | 403 | |
| 404 | 404 | |
| 405 | INLINE void write64be_with_16le_handler(write16_space_func handler, | |
| 405 | INLINE void write64be_with_16le_handler(write16_space_func handler, | |
| 406 | 406 | { |
| 407 | 407 | if (ACCESSING_BITS_32_63) |
| 408 | 408 | write32be_with_16le_handler(handler, space, offset * 2 + 0, data >> 32, mem_mask >> 32); |
| r8806 | r8807 | |
| 417 | 417 | * |
| 418 | 418 | *************************************/ |
| 419 | 419 | |
| 420 | INLINE UINT32 read64le_with_16be_handler(read16_space_func handler, | |
| 420 | INLINE UINT32 read64le_with_16be_handler(read16_space_func handler, | |
| 421 | 421 | { |
| 422 | 422 | UINT64 result = 0; |
| 423 | 423 | if (ACCESSING_BITS_0_31) |
| r8806 | r8807 | |
| 428 | 428 | } |
| 429 | 429 | |
| 430 | 430 | |
| 431 | INLINE void write64le_with_16be_handler(write16_space_func handler, | |
| 431 | INLINE void write64le_with_16be_handler(write16_space_func handler, | |
| 432 | 432 | { |
| 433 | 433 | if (ACCESSING_BITS_0_31) |
| 434 | 434 | write32le_with_16be_handler(handler, space, offset * 2 + 0, data >> 0, mem_mask >> 0); |
| r8806 | r8807 | |
| 443 | 443 | * |
| 444 | 444 | *************************************/ |
| 445 | 445 | |
| 446 | INLINE UINT64 read64be_with_32be_handler(read32_space_func handler, | |
| 446 | INLINE UINT64 read64be_with_32be_handler(read32_space_func handler, | |
| 447 | 447 | { |
| 448 | 448 | UINT64 result = 0; |
| 449 | 449 | if (ACCESSING_BITS_32_63) |
| r8806 | r8807 | |
| 454 | 454 | } |
| 455 | 455 | |
| 456 | 456 | |
| 457 | INLINE void write64be_with_32be_handler(write32_space_func handler, | |
| 457 | INLINE void write64be_with_32be_handler(write32_space_func handler, | |
| 458 | 458 | { |
| 459 | 459 | if (ACCESSING_BITS_32_63) |
| 460 | 460 | (*handler)(space, offset * 2 + 0, data >> 32, mem_mask >> 32); |
| r8806 | r8807 | |
| 469 | 469 | * |
| 470 | 470 | *************************************/ |
| 471 | 471 | |
| 472 | INLINE UINT64 read64le_with_32le_handler(read32_space_func handler, | |
| 472 | INLINE UINT64 read64le_with_32le_handler(read32_space_func handler, | |
| 473 | 473 | { |
| 474 | 474 | UINT64 result = 0; |
| 475 | 475 | if (ACCESSING_BITS_0_31) |
| r8806 | r8807 | |
| 480 | 480 | } |
| 481 | 481 | |
| 482 | 482 | |
| 483 | INLINE void write64le_with_32le_handler(write32_space_func handler, | |
| 483 | INLINE void write64le_with_32le_handler(write32_space_func handler, | |
| 484 | 484 | { |
| 485 | 485 | if (ACCESSING_BITS_0_31) |
| 486 | 486 | (*handler)(space, offset * 2 + 0, data >> 0, mem_mask >> 0); |
| r8806 | r8807 | |
| 495 | 495 | * |
| 496 | 496 | *************************************/ |
| 497 | 497 | |
| 498 | INLINE UINT64 read64be_with_32le_handler(read32_space_func handler, | |
| 498 | INLINE UINT64 read64be_with_32le_handler(read32_space_func handler, | |
| 499 | 499 | { |
| 500 | 500 | UINT64 result; |
| 501 | 501 | mem_mask = FLIPENDIAN_INT64(mem_mask); |
| r8806 | r8807 | |
| 504 | 504 | } |
| 505 | 505 | |
| 506 | 506 | |
| 507 | INLINE void write64be_with_32le_handler(write32_space_func handler, | |
| 507 | INLINE void write64be_with_32le_handler(write32_space_func handler, | |
| 508 | 508 | { |
| 509 | 509 | data = FLIPENDIAN_INT64(data); |
| 510 | 510 | mem_mask = FLIPENDIAN_INT64(mem_mask); |
| r8806 | r8807 | |
| 518 | 518 | * |
| 519 | 519 | *************************************/ |
| 520 | 520 | |
| 521 | INLINE UINT64 read64le_with_32be_handler(read32_space_func handler, | |
| 521 | INLINE UINT64 read64le_with_32be_handler(read32_space_func handler, | |
| 522 | 522 | { |
| 523 | 523 | UINT64 result; |
| 524 | 524 | mem_mask = FLIPENDIAN_INT64(mem_mask); |
| r8806 | r8807 | |
| 527 | 527 | } |
| 528 | 528 | |
| 529 | 529 | |
| 530 | INLINE void write64le_with_32be_handler(write32_space_func handler, | |
| 530 | INLINE void write64le_with_32be_handler(write32_space_func handler, | |
| 531 | 531 | { |
| 532 | 532 | data = FLIPENDIAN_INT64(data); |
| 533 | 533 | mem_mask = FLIPENDIAN_INT64(mem_mask); |
| r8806 | r8807 | |
|---|---|---|
| 85 | 85 | latch_w - handle a write to a given latch |
| 86 | 86 | -------------------------------------------------*/ |
| 87 | 87 | |
| 88 | INLINE void latch_w( | |
| 88 | INLINE void latch_w( | |
| 89 | 89 | { |
| 90 | 90 | timer_call_after_resynch(space->machine, NULL, which | (value << 8), latch_callback); |
| 91 | 91 | } |
| r8806 | r8807 | |
| 95 | 95 | latch_r - handle a read from a given latch |
| 96 | 96 | -------------------------------------------------*/ |
| 97 | 97 | |
| 98 | INLINE UINT16 latch_r( | |
| 98 | INLINE UINT16 latch_r( | |
| 99 | 99 | { |
| 100 | 100 | generic_audio_private *state = space->machine->generic_audio_data; |
| 101 | 101 | state->latch_read[which] = 1; |
| r8806 | r8807 | |
| 107 | 107 | latch_clear - clear a given latch |
| 108 | 108 | -------------------------------------------------*/ |
| 109 | 109 | |
| 110 | INLINE void latch_clear( | |
| 110 | INLINE void latch_clear( | |
| 111 | 111 | { |
| 112 | 112 | generic_audio_private *state = space->machine->generic_audio_data; |
| 113 | 113 | state->latched_value[which] = state->latch_clear_value; |
| r8806 | r8807 | |
|---|---|---|
| 78 | 78 | m_space_config[spacenum].m_addrbus_width = get_legacy_config_int(DEVINFO_INT_ADDRBUS_WIDTH + spacenum); |
| 79 | 79 | m_space_config[spacenum].m_addrbus_shift = get_legacy_config_int(DEVINFO_INT_ADDRBUS_SHIFT + spacenum); |
| 80 | 80 | m_space_config[spacenum].m_logaddr_width = get_legacy_config_int(CPUINFO_INT_LOGADDR_WIDTH + spacenum); |
| 81 | if (m_space_config[spacenum].m_logaddr_width == 0) | |
| 82 | m_space_config[spacenum].m_logaddr_width = m_space_config[spacenum].m_addrbus_width; | |
| 81 | 83 | m_space_config[spacenum].m_page_shift = get_legacy_config_int(CPUINFO_INT_PAGE_SHIFT + spacenum); |
| 82 | 84 | m_space_config[spacenum].m_internal_map = reinterpret_cast<address_map_constructor>(get_legacy_config_fct(DEVINFO_PTR_INTERNAL_MEMORY_MAP + spacenum)); |
| 83 | 85 | m_space_config[spacenum].m_default_map = reinterpret_cast<address_map_constructor>(get_legacy_config_fct(DEVINFO_PTR_DEFAULT_MEMORY_MAP + spacenum)); |
| r8806 | r8807 | |
|---|---|---|
| 4 | 4 | |
| 5 | 5 | Functions which handle device memory access. |
| 6 | 6 | |
| 7 | Copyright Nicola Salmoria and the MAME Team. | |
| 8 | Visit http://mamedev.org for licensing and usage restrictions. | |
| 7 | **************************************************************************** | |
| 9 | 8 | |
| 9 | Copyright Aaron Giles | |
| 10 | All rights reserved. | |
| 11 | ||
| 12 | Redistribution and use in source and binary forms, with or without | |
| 13 | modification, are permitted provided that the following conditions are | |
| 14 | met: | |
| 15 | ||
| 16 | * Redistributions of source code must retain the above copyright | |
| 17 | notice, this list of conditions and the following disclaimer. | |
| 18 | * Redistributions in binary form must reproduce the above copyright | |
| 19 | notice, this list of conditions and the following disclaimer in | |
| 20 | the documentation and/or other materials provided with the | |
| 21 | distribution. | |
| 22 | * Neither the name 'MAME' nor the names of its contributors may be | |
| 23 | used to endorse or promote products derived from this software | |
| 24 | without specific prior written permission. | |
| 25 | ||
| 26 | THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR | |
| 27 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 28 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| 29 | DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, | |
| 30 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 31 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| 32 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 33 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
| 34 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | |
| 35 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
| 36 | POSSIBILITY OF SUCH DAMAGE. | |
| 37 | ||
| 10 | 38 | **************************************************************************** |
| 11 | 39 | |
| 12 | 40 | Basic theory of memory handling: |
| r8806 | r8807 | |
| 177 | 205 | #include "debug/debugcpu.h" |
| 178 | 206 | |
| 179 | 207 | |
| 180 | /*************************************************************************** | |
| 181 | DEBUGGING | |
| 182 | ***************************************************************************/ | |
| 208 | //************************************************************************** | |
| 209 | // DEBUGGING | |
| 210 | //************************************************************************** | |
| 183 | 211 | |
| 184 | 212 | #define MEM_DUMP (0) |
| 185 | 213 | #define VERBOSE (0) |
| 186 | #define ALLOW_ONLY_AUTO_MALLOC_BANKS 0 | |
| 187 | 214 | |
| 188 | 215 | #define VPRINTF(x) do { if (VERBOSE) mame_printf_debug x; } while (0) |
| 189 | 216 | |
| 190 | 217 | |
| 191 | 218 | |
| 192 | /*************************************************************************** | |
| 193 | CONSTANTS | |
| 194 | ***************************************************************************/ | |
| 219 | //************************************************************************** | |
| 220 | // CONSTANTS | |
| 221 | //************************************************************************** | |
| 195 | 222 | |
| 196 | /* banking constants */ | |
| 197 | #define MAX_BANK_ENTRIES 4096 /* maximum number of possible bank values */ | |
| 223 | // banking constants | |
| 224 | const int BANK_ENTRY_UNSPECIFIED = -1; | |
| 198 | 225 | |
| 199 | /* address map lookup table definitions */ | |
| 200 | #define LEVEL1_BITS 18 /* number of address bits in the level 1 table */ | |
| 201 | #define LEVEL2_BITS (32 - LEVEL1_BITS) /* number of address bits in the level 2 table */ | |
| 202 | #define SUBTABLE_COUNT 64 /* number of slots reserved for subtables */ | |
| 203 | #define SUBTABLE_BASE (256 - SUBTABLE_COUNT) /* first index of a subtable */ | |
| 204 | #define ENTRY_COUNT (SUBTABLE_BASE) /* number of legitimate (non-subtable) entries */ | |
| 205 | #define SUBTABLE_ALLOC 8 /* number of subtables to allocate at a time */ | |
| 226 | // shares are initially mapped to this invalid pointer | |
| 227 | static void *UNMAPPED_SHARE_PTR = ((void *)-1); | |
| 206 | 228 | |
| 207 | /* shares are initially mapped to this invalid pointer */ | |
| 208 | #define UNMAPPED_SHARE_PTR ((void *)-1) | |
| 229 | // other address map constants | |
| 230 | const int MEMORY_BLOCK_CHUNK = 65536; // minimum chunk size of allocated memory blocks | |
| 209 | 231 | |
| 210 | /* other address map constants */ | |
| 211 | #define MEMORY_BLOCK_CHUNK 65536 /* minimum chunk size of allocated memory blocks */ | |
| 212 | ||
| 213 | /* read or write constants */ | |
| 214 | enum _read_or_write | |
| 215 | { | |
| 216 | ROW_READ, | |
| 217 | ROW_WRITE | |
| 218 | }; | |
| 219 | typedef enum _read_or_write read_or_write; | |
| 220 | ||
| 221 | /* static data access handler constants */ | |
| 232 | // static data access handler constants | |
| 222 | 233 | enum |
| 223 | 234 | { |
| 224 | STATIC_INVALID = 0, /* invalid - should never be used */ | |
| 225 | STATIC_BANK1 = 1, /* first memory bank */ | |
| 226 | STATIC_BANKMAX = 122, /* last memory bank */ | |
| 227 | STATIC_RAM, /* RAM - reads/writes map to dynamic banks */ | |
| 228 | STATIC_ROM, /* ROM - reads = RAM; writes = UNMAP */ | |
| 229 | STATIC_NOP, /* NOP - reads = unmapped value; writes = no-op */ | |
| 230 | STATIC_UNMAP, /* unmapped - same as NOP except we log errors */ | |
| 231 | STATIC_WATCHPOINT, /* watchpoint - used internally */ | |
| 232 | STATIC_COUNT /* total number of static handlers */ | |
| 235 | STATIC_INVALID = 0, // invalid - should never be used | |
| 236 | STATIC_BANK1 = 1, // first memory bank | |
| 237 | STATIC_BANKMAX = 122, // last memory bank | |
| 238 | STATIC_RAM, // RAM - reads/writes map to dynamic banks | |
| 239 | STATIC_ROM, // ROM - reads = RAM; writes = UNMAP | |
| 240 | STATIC_NOP, // NOP - reads = unmapped value; writes = no-op | |
| 241 | STATIC_UNMAP, // unmapped - same as NOP except we log errors | |
| 242 | STATIC_WATCHPOINT, // watchpoint - used internally | |
| 243 | STATIC_COUNT // total number of static handlers | |
| 233 | 244 | }; |
| 234 | 245 | |
| 235 | 246 | |
| 236 | 247 | |
| 237 | /*************************************************************************** | |
| 238 | MACROS | |
| 239 | ***************************************************************************/ | |
| 248 | //************************************************************************** | |
| 249 | // TYPE DEFINITIONS | |
| 250 | //************************************************************************** | |
| 240 | 251 | |
| 241 | /* table lookup helpers */ | |
| 242 | #define LEVEL1_INDEX(a) ((a) >> LEVEL2_BITS) | |
| 243 | #define LEVEL2_INDEX(e,a) ((1 << LEVEL1_BITS) + (((e) - SUBTABLE_BASE) << LEVEL2_BITS) + ((a) & ((1 << LEVEL2_BITS) - 1))) | |
| 244 | 252 | |
| 245 | /* helper macros */ | |
| 246 | #define HANDLER_IS_RAM(h) ((FPTR)(h) == STATIC_RAM) | |
| 247 | #define HANDLER_IS_ROM(h) ((FPTR)(h) == STATIC_ROM) | |
| 248 | #define HANDLER_IS_BANK(h) ((FPTR)(h) >= STATIC_BANK1 && (FPTR)(h) <= STATIC_BANKMAX) | |
| 249 | #define HANDLER_IS_STATIC(h) ((FPTR)(h) < STATIC_COUNT) | |
| 253 | // ======================> memory_block | |
| 250 | 254 | |
| 251 | #define HANDLER_TO_BANK(h) ((UINT32)(FPTR)(h)) | |
| 255 | // a memory block is a chunk of RAM associated with a range of memory in a device's address space | |
| 256 | class memory_block | |
| 257 | { | |
| 258 | DISABLE_COPYING(memory_block); | |
| 252 | 259 | |
| 253 | #define SUBTABLE_PTR(tabledata, entry) (&(tabledata)->table[(1 << LEVEL1_BITS) + (((entry) - SUBTABLE_BASE) << LEVEL2_BITS)]) | |
| 260 | friend class simple_list<memory_block>; | |
| 261 | friend resource_pool_object<memory_block>::~resource_pool_object(); | |
| 254 | 262 | |
| 263 | public: | |
| 264 | // construction/destruction | |
| 265 | memory_block(address_space &space, offs_t bytestart, offs_t byteend, void *memory = NULL); | |
| 266 | ~memory_block(); | |
| 255 | 267 | |
| 268 | // getters | |
| 269 | memory_block *next() const { return m_next; } | |
| 270 | offs_t bytestart() const { return m_bytestart; } | |
| 271 | offs_t byteend() const { return m_byteend; } | |
| 272 | UINT8 *data() const { return m_data; } | |
| 256 | 273 | |
| 257 | /*************************************************************************** | |
| 258 | TYPE DEFINITIONS | |
| 259 | ***************************************************************************/ | |
| 274 | // is the given range contained by this memory block? | |
| 275 | bool contains(address_space &space, offs_t bytestart, offs_t byteend) const | |
| 276 | { | |
| 277 | return (&space == &m_space && m_bytestart <= bytestart && m_byteend >= byteend); | |
| 278 | } | |
| 260 | 279 | |
| 261 | /* a memory block is a chunk of RAM associated with a range of memory in a device's address space */ | |
| 262 | typedef struct _memory_block memory_block; | |
| 263 | struct _memory_block | |
| 264 | { | |
| 265 | memory_block * next; /* next memory block in the list */ | |
| 266 | const address_space * space; /* which address space are we associated with? */ | |
| 267 | UINT8 isallocated; /* did we allocate this ourselves? */ | |
| 268 | offs_t bytestart, byteend; /* byte-normalized start/end for verifying a match */ | |
| 269 | UINT8 * data; /* pointer to the data for this block */ | |
| 280 | private: | |
| 281 | // internal state | |
| 282 | memory_block * m_next; // next memory block in the list | |
| 283 | running_machine & m_machine; // need the machine to free our memory | |
| 284 | address_space & m_space; // which address space are we associated with? | |
| 285 | bool m_isallocated; // did we allocate this ourselves? | |
| 286 | offs_t m_bytestart, m_byteend; // byte-normalized start/end for verifying a match | |
| 287 | UINT8 * m_data; // pointer to the data for this block | |
| 270 | 288 | }; |
| 271 | 289 | |
| 272 | /* a bank reference is an entry in a list of address spaces that reference a given bank */ | |
| 273 | typedef struct _bank_reference bank_reference; | |
| 274 | struct _bank_reference | |
| 275 | { | |
| 276 | bank_reference * next; /* link to the next reference */ | |
| 277 | const address_space * space; /* address space that references us */ | |
| 278 | }; | |
| 279 | 290 | |
| 280 | /* a bank is a global pointer to memory that can be shared across devices and changed dynamically */ | |
| 281 | typedef struct _bank_info bank_info; | |
| 282 | struct _bank_info | |
| 283 | { | |
| 284 | bank_info * next; /* next bank in sequence */ | |
| 285 | UINT8 index; /* array index for this handler */ | |
| 286 | UINT8 read; /* is this bank used for reads? */ | |
| 287 | UINT8 write; /* is this bank used for writes? */ | |
| 288 | void * handler; /* handler for this bank */ | |
| 289 | bank_reference * reflist; /* linked list of address spaces referencing this bank */ | |
| 290 | offs_t bytestart; /* byte-adjusted start offset */ | |
| 291 | offs_t byteend; /* byte-adjusted end offset */ | |
| 292 | UINT16 curentry; /* current entry */ | |
| 293 | void * entry[MAX_BANK_ENTRIES];/* array of entries for this bank */ | |
| 294 | void * entryd[MAX_BANK_ENTRIES];/* array of decrypted entries for this bank */ | |
| 295 | char * name; /* friendly name for this bank */ | |
| 296 | char tag[1]; /* tag associated with this bank */ | |
| 297 | }; | |
| 291 | // ======================> memory_bank | |
| 298 | 292 | |
| 299 | /* In memory.h: typedef struct _direct_range direct_range; */ | |
| 300 | struct _direct_range | |
| 293 | // a memory bank is a global pointer to memory that can be shared across devices and changed dynamically | |
| 294 | class memory_bank | |
| 301 | 295 | { |
| 302 | direct_range * next; /* pointer to the next range in the list */ | |
| 303 | offs_t bytestart; /* starting byte offset of the range */ | |
| 304 | offs_t byteend; /* ending byte offset of the range */ | |
| 305 | }; | |
| 296 | friend class simple_list<memory_bank>; | |
| 297 | friend resource_pool_object<memory_bank>::~resource_pool_object(); | |
| 298 | ||
| 299 | // a bank reference is an entry in a list of address spaces that reference a given bank | |
| 300 | class bank_reference | |
| 301 | { | |
| 302 | friend class simple_list<bank_reference>; | |
| 303 | friend resource_pool_object<bank_reference>::~resource_pool_object(); | |
| 304 | ||
| 305 | public: | |
| 306 | // construction/destruction | |
| 307 | bank_reference(address_space &space, read_or_write readorwrite) | |
| 308 | : m_next(NULL), | |
| 309 | m_space(space), | |
| 310 | m_readorwrite(readorwrite) { } | |
| 306 | 311 | |
| 307 | /* In memory.h: typedef struct _handler_data handler_data */ | |
| 308 | struct _handler_data | |
| 309 | { | |
| 310 | memory_handler handler; /* function pointer for handler */ | |
| 311 | void * object; /* object associated with the handler */ | |
| 312 | const char * name; /* name of the handler */ | |
| 313 | memory_handler subhandler; /* function pointer for subhandler */ | |
| 314 | void * subobject; /* object associated with the subhandler */ | |
| 315 | UINT8 subunits; /* number of subunits to access */ | |
| 316 | UINT8 subshift[8]; /* shift amounts for up to 8 subunits */ | |
| 317 | offs_t bytestart; /* byte-adjusted start address for handler */ | |
| 318 | offs_t byteend; /* byte-adjusted end address for handler */ | |
| 319 | offs_t bytemask; /* byte-adjusted mask against the final address */ | |
| 320 | UINT8 ** bankbaseptr; /* pointer to the bank base */ | |
| 321 | }; | |
| 312 | // getters | |
| 313 | bank_reference *next() const { return m_next; } | |
| 314 | address_space &space() const { return m_space; } | |
| 315 | ||
| 316 | // does this reference match the space+read/write combination? | |
| 317 | bool matches(address_space &space, read_or_write readorwrite) const | |
| 318 | { | |
| 319 | return (&space == &m_space && (readorwrite == ROW_READWRITE || readorwrite == m_readorwrite)); | |
| 320 | } | |
| 322 | 321 | |
| 323 | /* In memory.h: typedef struct _subtable_data subtable_data; */ | |
| 324 | struct _subtable_data | |
| 325 | { | |
| 326 | UINT8 checksum_valid; /* is the checksum valid */ | |
| 327 | UINT32 checksum; /* checksum over all the bytes */ | |
| 328 | UINT32 usecount; /* number of times this has been used */ | |
| 329 | }; | |
| 322 | private: | |
| 323 | // internal state | |
| 324 | bank_reference * m_next; // link to the next reference | |
| 325 | address_space & m_space; // address space that references us | |
| 326 | read_or_write m_readorwrite; // used for read or write? | |
| 327 | }; | |
| 328 | ||
| 329 | // a bank_entry contains a raw and decrypted pointer | |
| 330 | struct bank_entry | |
| 331 | { | |
| 332 | UINT8 * m_raw; | |
| 333 | UINT8 * m_decrypted; | |
| 334 | }; | |
| 330 | 335 | |
| 331 | struct _memory_private | |
| 332 | { | |
| 333 | UINT8 initialized; /* have we completed initialization? */ | |
| 336 | public: | |
| 337 | // construction/destruction | |
| 338 | memory_bank(address_space &space, int index, offs_t bytestart, offs_t byteend, const char *tag = NULL); | |
| 339 | ~memory_bank(); | |
| 340 | ||
| 341 | // getters | |
| 342 | memory_bank *next() const { return m_next; } | |
| 343 | int index() const { return m_index; } | |
| 344 | int entry() const { return m_curentry; } | |
| 345 | bool anonymous() const { return m_anonymous; } | |
| 346 | offs_t bytestart() const { return m_bytestart; } | |
| 347 | void *base() const { return *m_baseptr; } | |
| 348 | void *base_decrypted() const { return *m_basedptr; } | |
| 349 | const char *tag() const { return m_tag; } | |
| 350 | const char *name() const { return m_name; } | |
| 334 | 351 | |
| 335 | const address_space * spacelist; /* list of address spaces */ | |
| 352 | // compare a range against our range | |
| 353 | bool matches_exactly(offs_t bytestart, offs_t byteend) const { return (m_bytestart == bytestart && m_byteend == byteend); } | |
| 354 | bool fully_covers(offs_t bytestart, offs_t byteend) const { return m_bytestart <= bytestart && m_byteend >= byteend; } | |
| 355 | bool partially_covers(offs_t bytestart, offs_t byteend) const { return m_bytestart <= byteend && m_byteend >= bytestart; } | |
| 336 | 356 | |
| 337 | UINT8 * bank_ptr[STATIC_COUNT]; /* array of bank pointers */ | |
| 338 | UINT8 * bankd_ptr[STATIC_COUNT]; /* array of decrypted bank pointers */ | |
| 357 | // track and verify address space references to this bank | |
| 358 | bool references_space(address_space &space, read_or_write readorwrite) const; | |
| 359 | void add_reference(address_space &space, read_or_write readorwrite); | |
| 339 | 360 | |
| 340 | memory_block * memory_block_list; /* head of the list of memory blocks */ | |
| 361 | // set the base explicitly | |
| 362 | void set_base(void *base); | |
| 363 | void set_base_decrypted(void *base); | |
| 341 | 364 | |
| 342 | tagmap_t<bank_info *> bankmap; /* map for fast bank lookups */ | |
| 343 | bank_info * banklist; /* data gathered for each bank */ | |
| 344 | UINT8 banknext; /* next bank to allocate */ | |
| 365 | // configure and set entries | |
| 366 | void configure(int entrynum, void *base); | |
| 367 | void configure_decrypted(int entrynum, void *base); | |
| 368 | void set_entry(int entrynum); | |
| 369 | ||
| 370 | private: | |
| 371 | // internal helpers | |
| 372 | void invalidate_references(); | |
| 373 | void expand_entries(int entrynum); | |
| 345 | 374 | |
| 346 | tagmap_t<void *> sharemap; /* map for share lookups */ | |
| 347 | ||
| 348 | UINT8 * wptable; /* watchpoint-fill table */ | |
| 375 | // internal state | |
| 376 | memory_bank * m_next; // next bank in sequence | |
| 377 | running_machine & m_machine; // need the machine to free our memory | |
| 378 | UINT8 ** m_baseptr; // pointer to our base pointer in the global array | |
| 379 | UINT8 ** m_basedptr; // same for the decrypted base pointer | |
| 380 | UINT8 m_index; // array index for this handler | |
| 381 | bool m_anonymous; // are we anonymous or explicit? | |
| 382 | offs_t m_bytestart; // byte-adjusted start offset | |
| 383 | offs_t m_byteend; // byte-adjusted end offset | |
| 384 | int m_curentry; // current entry | |
| 385 | bank_entry * m_entry; // array of entries (dynamically allocated) | |
| 386 | int m_entry_count; // number of allocated entries | |
| 387 | astring m_name; // friendly name for this bank | |
| 388 | astring m_tag; // tag for this bank | |
| 389 | simple_list<bank_reference> m_reflist; // linked list of address spaces referencing this bank | |
| 349 | 390 | }; |
| 350 | 391 | |
| 351 | 392 | |
| 393 | // ======================> handler_entry | |
| 352 | 394 | |
| 353 | /*************************************************************************** | |
| 354 | GLOBAL VARIABLES | |
| 355 | ***************************************************************************/ | |
| 395 | // a handler entry contains information about a memory handler | |
| 396 | class handler_entry : public bindable_object | |
| 397 | { | |
| 398 | DISABLE_COPYING(handler_entry); | |
| 356 | 399 | |
| 357 | #define ACCESSOR_GROUP(width) \ | |
| 358 | { \ | |
| 359 | memory_read_byte_##width, \ | |
| 360 | memory_read_word_##width, \ | |
| 361 | memory_read_word_masked_##width, \ | |
| 362 | memory_read_dword_##width, \ | |
| 363 | memory_read_dword_masked_##width, \ | |
| 364 | memory_read_qword_##width, \ | |
| 365 | memory_read_qword_masked_##width, \ | |
| 366 | memory_write_byte_##width, \ | |
| 367 | memory_write_word_##width, \ | |
| 368 | memory_write_word_masked_##width, \ | |
| 369 | memory_write_dword_##width, \ | |
| 370 | memory_write_dword_masked_##width, \ | |
| 371 | memory_write_qword_##width, \ | |
| 372 | memory_write_qword_masked_##width \ | |
| 373 | } | |
| 400 | protected: | |
| 401 | // construction/destruction | |
| 402 | handler_entry(UINT8 width, endianness_t endianness, UINT8 **rambaseptr); | |
| 403 | virtual ~handler_entry(); | |
| 404 | ||
| 405 | public: | |
| 406 | // getters | |
| 407 | bool populated() const { return m_populated; } | |
| 408 | offs_t bytestart() const { return m_bytestart; } | |
| 409 | offs_t byteend() const { return m_byteend; } | |
| 410 | offs_t bytemask() const { return m_bytemask; } | |
| 411 | virtual const char *name() const = 0; | |
| 374 | 412 | |
| 375 | static const data_accessors memory_accessors[4][2] = | |
| 376 | { | |
| 377 | { ACCESSOR_GROUP(8le), ACCESSOR_GROUP(8be) }, | |
| 378 | { ACCESSOR_GROUP(16le), ACCESSOR_GROUP(16be) }, | |
| 379 | { ACCESSOR_GROUP(32le), ACCESSOR_GROUP(32be) }, | |
| 380 | { ACCESSOR_GROUP(64le), ACCESSOR_GROUP(64be) } | |
| 381 | }; | |
| 413 | // return offset within the range referenced by this handler | |
| 414 | offs_t byteoffset(offs_t byteaddress) const { return (byteaddress - m_bytestart) & m_bytemask; } | |
| 382 | 415 | |
| 416 | // return a pointer to the backing RAM at the given offset | |
| 417 | UINT8 *ramptr(offs_t offset = 0) const { return *m_rambaseptr + offset; } | |
| 383 | 418 | |
| 419 | // see if we are an exact match to the given parameters | |
| 420 | bool matches_exactly(offs_t bytestart, offs_t byteend, offs_t bytemask) const | |
| 421 | { | |
| 422 | return (m_populated && m_bytestart == bytestart && m_byteend == byteend && m_bytemask == bytemask); | |
| 423 | } | |
| 384 | 424 | |
| 385 | /*************************************************************************** | |
| 386 | FUNCTION PROTOTYPES | |
| 387 | ***************************************************************************/ | |
| 425 | // get the start/end address with the given mirror | |
| 426 | void mirrored_start_end(offs_t byteaddress, offs_t &start, offs_t &end) const | |
| 427 | { | |
| 428 | offs_t mirrorbits = (byteaddress - m_bytestart) & ~m_bytemask; | |
| 429 | start = m_bytestart | mirrorbits; | |
| 430 | end = m_byteend | mirrorbits; | |
| 431 | } | |
| 388 | 432 | |
| 389 | /* internal initialization */ | |
| 390 | static void memory_init_spaces(running_machine *machine); | |
| 391 | static void memory_init_preflight(running_machine *machine); | |
| 392 | static void memory_init_populate(running_machine *machine); | |
| 393 | static void memory_init_map_entry(address_space *space, const address_map_entry *entry, read_or_write readorwrite); | |
| 394 | static void memory_init_allocate(running_machine *machine); | |
| 395 | static void memory_init_locate(running_machine *machine); | |
| 396 | static void memory_exit(running_machine &machine); | |
| 433 | // configure the handler addresses, and mark as populated | |
| 434 | void configure(offs_t bytestart, offs_t byteend, offs_t bytemask) | |
| 435 | { | |
| 436 | m_populated = true; | |
| 437 | m_bytestart = bytestart; | |
| 438 | m_byteend = byteend; | |
| 439 | m_bytemask = bytemask; | |
| 440 | } | |
| 397 | 441 | |
| 398 | /* memory mapping helpers */ | |
| 399 | static void space_map_range(address_space *space, read_or_write readorwrite, int handlerbits, int handlerunitmask, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, genf *handler, void *object, const char *handler_name); | |
| 400 | static void *space_find_backing_memory(const address_space *space, offs_t addrstart, offs_t addrend); | |
| 401 | static int space_needs_backing_store(const address_space *space, const address_map_entry *entry); | |
| 442 | // apply a global mask | |
| 443 | void apply_mask(offs_t bytemask) { m_bytemask &= bytemask; } | |
| 402 | 444 | |
| 403 | /* banking helpers */ | |
| 404 | static genf *bank_find_or_allocate(const address_space *space, const char *tag, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read_or_write readorwrite); | |
| 405 | static STATE_POSTLOAD( bank_reattach ); | |
| 445 | protected: | |
| 446 | // internal helpers | |
| 447 | void configure_subunits(UINT64 handlermask, int handlerbits); | |
| 406 | 448 | |
| 407 | /* table management */ | |
| 408 | static UINT8 table_assign_handler(const address_space *space, handler_data **table, void *object, genf *handler, const char *handler_name, offs_t bytestart, offs_t byteend, offs_t bytemask); | |
| 409 | static void table_compute_subhandler(handler_data **table, UINT8 entry, read_or_write readorwrite, int spacebits, int spaceendian, int handlerbits, int handlerunitmask); | |
| 410 | static void table_populate_range(address_table *tabledata, offs_t bytestart, offs_t byteend, UINT8 handler); | |
| 411 | static void table_populate_range_mirrored(address_space *space, address_table *tabledata, offs_t bytestart, offs_t byteend, offs_t bytemirror, UINT8 handler); | |
| 412 | static UINT8 table_derive_range(const address_table *table, offs_t byteaddress, offs_t *bytestart, offs_t *byteend); | |
| 449 | // internal state | |
| 450 | bool m_populated; // populated? | |
| 451 | UINT8 m_datawidth; | |
| 452 | endianness_t m_endianness; | |
| 453 | offs_t m_bytestart; // byte-adjusted start address for handler | |
| 454 | offs_t m_byteend; // byte-adjusted end address for handler | |
| 455 | offs_t m_bytemask; // byte-adjusted mask against the final address | |
| 456 | UINT8 ** m_rambaseptr; // pointer to the bank base | |
| 457 | UINT8 m_subunits; // for width stubs, the number of subunits | |
| 458 | UINT8 m_subshift[8]; // for width stubs, the shift of each subunit | |
| 459 | }; | |
| 413 | 460 | |
| 414 | /* subtable management */ | |
| 415 | static UINT8 subtable_alloc(address_table *tabledata); | |
| 416 | static void subtable_realloc(address_table *tabledata, UINT8 subentry); | |
| 417 | static int subtable_merge(address_table *tabledata); | |
| 418 | static void subtable_release(address_table *tabledata, UINT8 subentry); | |
| 419 | static UINT8 *subtable_open(address_table *tabledata, offs_t l1index); | |
| 420 | static void subtable_close(address_table *tabledata, offs_t l1index); | |
| 421 | 461 | |
| 422 | /* direct memory ranges */ | |
| 423 | static direct_range *direct_range_find(address_space *space, offs_t byteaddress, UINT8 *entry); | |
| 424 | static void direct_range_remove_intersecting(address_space *space, offs_t bytestart, offs_t byteend); | |
| 462 | // ======================> handler_entry_read | |
| 425 | 463 | |
| 426 | /* memory block allocation */ | |
| 427 | static void *block_allocate(const address_space *space, offs_t bytestart, offs_t byteend, void *memory); | |
| 428 | static address_map_entry *block_assign_intersecting(address_space *space, offs_t bytestart, offs_t byteend, UINT8 *base); | |
| 464 | // a read-access-specific extension of handler_entry | |
| 465 | class handler_entry_read : public handler_entry | |
| 466 | { | |
| 467 | public: | |
| 468 | // construction/destruction | |
| 469 | handler_entry_read(UINT8 width, endianness_t endianness, UINT8 **rambaseptr) | |
| 470 | : handler_entry(width, endianness, rambaseptr) | |
| 471 | { | |
| 472 | m_legacy_object.space = NULL; | |
| 473 | m_legacy_handler.space8 = NULL; | |
| 474 | } | |
| 475 | ||
| 476 | // getters | |
| 477 | virtual const char *name() const; | |
| 429 | 478 | |
| 430 | /* internal handlers */ | |
| 431 | static memory_handler get_stub_handler(read_or_write readorwrite, int spacedbits, int handlerdbits); | |
| 432 | static genf *get_static_handler(int handlerbits, int readorwrite, int which); | |
| 479 | // configure delegate callbacks | |
| 480 | void set_delegate(read8_delegate delegate, UINT64 mask = 0); | |
| 481 | void set_delegate(read16_delegate delegate, UINT64 mask = 0); | |
| 482 | void set_delegate(read32_delegate delegate, UINT64 mask = 0); | |
| 483 | void set_delegate(read64_delegate delegate, UINT64 mask = 0); | |
| 433 | 484 | |
| 434 | /* debugging */ | |
| 435 | static const char *handler_to_string(const address_space *space, const address_table *table, UINT8 entry); | |
| 436 | static void dump_map(FILE *file, const address_space *space, const address_table *table); | |
| 437 | static void mem_dump(running_machine *machine); | |
| 485 | // configure legacy address space functions | |
| 486 | void set_legacy_func(address_space &space, read8_space_func func, const char *name, UINT64 mask = 0); | |
| 487 | void set_legacy_func(address_space &space, read16_space_func func, const char *name, UINT64 mask = 0); | |
| 488 | void set_legacy_func(address_space &space, read32_space_func func, const char *name, UINT64 mask = 0); | |
| 489 | void set_legacy_func(address_space &space, read64_space_func func, const char *name, UINT64 mask = 0); | |
| 438 | 490 | |
| 439 | /* input port handlers */ | |
| 440 | static UINT8 input_port_read8(const input_port_config *port, offs_t offset); | |
| 441 | static UINT16 input_port_read16(const input_port_config *port, offs_t offset, UINT16 mem_mask); | |
| 442 | static UINT32 input_port_read32(const input_port_config *port, offs_t offset, UINT32 mem_mask); | |
| 443 | static UINT64 input_port_read64(const input_port_config *port, offs_t offset, UINT64 mem_mask); | |
| 491 | // configure legacy device functions | |
| 492 | void set_legacy_func(device_t &device, read8_device_func func, const char *name, UINT64 mask = 0); | |
| 493 | void set_legacy_func(device_t &device, read16_device_func func, const char *name, UINT64 mask = 0); | |
| 494 | void set_legacy_func(device_t &device, read32_device_func func, const char *name, UINT64 mask = 0); | |
| 495 | void set_legacy_func(device_t &device, read64_device_func func, const char *name, UINT64 mask = 0); | |
| 444 | 496 | |
| 445 | /* output port handlers */ | |
| 446 | static void input_port_write8(const input_port_config *port, offs_t offset, UINT8 data); | |
| 447 | static void input_port_write16(const input_port_config *port, offs_t offset, UINT16 data, UINT16 mem_mask); | |
| 448 | static void input_port_write32(const input_port_config *port, offs_t offset, UINT32 data, UINT32 mem_mask); | |
| 449 | static void input_port_write64(const input_port_config *port, offs_t offset, UINT64 data, UINT64 mem_mask); | |
| 497 | // configure I/O port access | |
| 498 | void set_ioport(const input_port_config &ioport); | |
| 499 | ||
| 500 | // read via the underlying delegates | |
| 501 | UINT8 read8(address_space &space, offs_t offset, UINT8 mask) const { return m_read8(space, offset, mask); } | |
| 502 | UINT16 read16(address_space &space, offs_t offset, UINT16 mask) const { return m_read16(space, offset, mask); } | |
| 503 | UINT32 read32(address_space &space, offs_t offset, UINT32 mask) const { return m_read32(space, offset, mask); } | |
| 504 | UINT64 read64(address_space &space, offs_t offset, UINT64 mask) const { return m_read64(space, offset, mask); } | |
| 450 | 505 | |
| 506 | private: | |
| 507 | // stubs for converting between address sizes | |
| 508 | UINT16 read_stub_16_from_8(address_space &space, offs_t offset, UINT16 mask); | |
| 509 | UINT32 read_stub_32_from_8(address_space &space, offs_t offset, UINT32 mask); | |
| 510 | UINT64 read_stub_64_from_8(address_space &space, offs_t offset, UINT64 mask); | |
| 511 | UINT32 read_stub_32_from_16(address_space &space, offs_t offset, UINT32 mask); | |
| 512 | UINT64 read_stub_64_from_16(address_space &space, offs_t offset, UINT64 mask); | |
| 513 | UINT64 read_stub_64_from_32(address_space &space, offs_t offset, UINT64 mask); | |
| 451 | 514 | |
| 515 | // stubs for calling legacy read handlers | |
| 516 | UINT8 read_stub_legacy(address_space &space, offs_t offset, UINT8 mask); | |
| 517 | UINT16 read_stub_legacy(address_space &space, offs_t offset, UINT16 mask); | |
| 518 | UINT32 read_stub_legacy(address_space &space, offs_t offset, UINT32 mask); | |
| 519 | UINT64 read_stub_legacy(address_space &space, offs_t offset, UINT64 mask); | |
| 452 | 520 | |
| 453 | /*************************************************************************** | |
| 454 | INLINE FUNCTIONS | |
| 455 | ***************************************************************************/ | |
| 521 | // stubs for reading I/O ports | |
| 522 | template<typename _UintType> | |
| 523 | _UintType read_stub_ioport(address_space &space, offs_t offset, _UintType mask) { return input_port_read_direct(m_ioport); } | |
| 456 | 524 | |
| 457 | /*------------------------------------------------- | |
| 458 | force_opbase_update - ensure that we update | |
| 459 | the opcode base | |
| 460 | -------------------------------------------------*/ | |
| 525 | // internal state | |
| 526 | read8_delegate m_read8; | |
| 527 | read16_delegate m_read16; | |
| 528 | read32_delegate m_read32; | |
| 529 | read64_delegate m_read64; | |
| 530 | const input_port_config * m_ioport; | |
| 461 | 531 | |
| 462 | INLINE void force_opbase_update(const address_space *space) | |
| 463 | { | |
| 464 | address_space *spacerw = (address_space *)space; | |
| 465 | spacerw->direct.byteend = 0; | |
| 466 | spacerw->direct.bytestart = 1; | |
| 467 | } | |
| 532 | // unions to hold legacy objects and callbacks | |
| 533 | union | |
| 534 | { | |
| 535 | address_space * space; | |
| 536 | device_t * device; | |
| 537 | } m_legacy_object; | |
| 468 | 538 | |
| 539 | union | |
| 540 | { | |
| 541 | read8_space_func space8; | |
| 542 | read16_space_func space16; | |
| 543 | read32_space_func space32; | |
| 544 | read64_space_func space64; | |
| 545 | read8_device_func device8; | |
| 546 | read16_device_func device16; | |
| 547 | read32_device_func device32; | |
| 548 | read64_device_func device64; | |
| 549 | } m_legacy_handler; | |
| 550 | }; | |
| 469 | 551 | |
| 470 | /*------------------------------------------------- | |
| 471 | adjust_addresses - adjust addresses for a | |
| 472 | given address space in a standard fashion | |
| 473 | -------------------------------------------------*/ | |
| 474 | 552 | |
| 475 | INLINE void adjust_addresses(const address_space *space, offs_t *start, offs_t *end, offs_t *mask, offs_t *mirror) | |
| 553 | // ======================> handler_entry_write | |
| 554 | ||
| 555 | // a write-access-specific extension of handler_entry | |
| 556 | class handler_entry_write : public handler_entry | |
| 476 | 557 | { |
| 477 | /* adjust start/end/mask values */ | |
| 478 | if (*mask == 0) | |
| 479 | *mask = space->addrmask & ~*mirror; | |
| 480 | else | |
| 481 | *mask &= space->addrmask; | |
| 482 | *start &= ~*mirror & space->addrmask; | |
| 483 | *end &= ~*mirror & space->addrmask; | |
| 558 | public: | |
| 559 | // construction/destruction | |
| 560 | handler_entry_write(UINT8 width, endianness_t endianness, UINT8 **rambaseptr) | |
| 561 | : handler_entry(width, endianness, rambaseptr) | |
| 562 | { | |
| 563 | m_legacy_object.space = NULL; | |
| 564 | m_legacy_handler.space8 = NULL; | |
| 565 | } | |
| 566 | ||
| 567 | // getters | |
| 568 | virtual const char *name() const; | |
| 484 | 569 | |
| 485 | /* adjust to byte values */ | |
| 486 | *start = memory_address_to_byte(space, *start); | |
| 487 | *end = memory_address_to_byte_end(space, *end); | |
| 488 | *mask = memory_address_to_byte_end(space, *mask); | |
| 489 | *mirror = memory_address_to_byte(space, *mirror); | |
| 490 | } | |
| 570 | // configure delegate callbacks | |
| 571 | void set_delegate(write8_delegate delegate, UINT64 mask = 0); | |
| 572 | void set_delegate(write16_delegate delegate, UINT64 mask = 0); | |
| 573 | void set_delegate(write32_delegate delegate, UINT64 mask = 0); | |
| 574 | void set_delegate(write64_delegate delegate, UINT64 mask = 0); | |
| 575 | ||
| 576 | // configure legacy address space functions | |
| 577 | void set_legacy_func(address_space &space, write8_space_func func, const char *name, UINT64 mask = 0); | |
| 578 | void set_legacy_func(address_space &space, write16_space_func func, const char *name, UINT64 mask = 0); | |
| 579 | void set_legacy_func(address_space &space, write32_space_func func, const char *name, UINT64 mask = 0); | |
| 580 | void set_legacy_func(address_space &space, write64_space_func func, const char *name, UINT64 mask = 0); | |
| 491 | 581 | |
| 582 | // configure legacy device functions | |
| 583 | void set_legacy_func(device_t &device, write8_device_func func, const char *name, UINT64 mask = 0); | |
| 584 | void set_legacy_func(device_t &device, write16_device_func func, const char *name, UINT64 mask = 0); | |
| 585 | void set_legacy_func(device_t &device, write32_device_func func, const char *name, UINT64 mask = 0); | |
| 586 | void set_legacy_func(device_t &device, write64_device_func func, const char *name, UINT64 mask = 0); | |
| 587 | ||
| 588 | // configure I/O port access | |
| 589 | void set_ioport(const input_port_config &ioport); | |
| 492 | 590 | |
| 493 | /*------------------------------------------------- | |
| 494 | bank_references_space - return true if the | |
| 495 | given bank is referenced by a particular | |
| 496 | address space | |
| 497 | -------------------------------------------------*/ | |
| 591 | // write via the underlying delegates | |
| 592 | void write8(address_space &space, offs_t offset, UINT8 data, UINT8 mask) const { m_write8(space, offset, data, mask); } | |
| 593 | void write16(address_space &space, offs_t offset, UINT16 data, UINT16 mask) const { m_write16(space, offset, data, mask); } | |
| 594 | void write32(address_space &space, offs_t offset, UINT32 data, UINT32 mask) const { m_write32(space, offset, data, mask); } | |
| 595 | void write64(address_space &space, offs_t offset, UINT64 data, UINT64 mask) const { m_write64(space, offset, data, mask); } | |
| 498 | 596 | |
| 499 | INLINE int bank_references_space(const bank_info *bank, const address_space *space) | |
| 500 | { | |
| 501 | bank_reference *ref; | |
| 597 | private: | |
| 598 | // stubs for converting between address sizes | |
| 599 | void write_stub_16_from_8(address_space &space, offs_t offset, UINT16 data, UINT16 mask); | |
| 600 | void write_stub_32_from_8(address_space &space, offs_t offset, UINT32 data, UINT32 mask); | |
| 601 | void write_stub_64_from_8(address_space &space, offs_t offset, UINT64 data, UINT64 mask); | |
| 602 | void write_stub_32_from_16(address_space &space, offs_t offset, UINT32 data, UINT32 mask); | |
| 603 | void write_stub_64_from_16(address_space &space, offs_t offset, UINT64 data, UINT64 mask); | |
| 604 | void write_stub_64_from_32(address_space &space, offs_t offset, UINT64 data, UINT64 mask); | |
| 605 | ||
| 606 | // stubs for calling legacy write handlers | |
| 607 | void write_stub_legacy(address_space &space, offs_t offset, UINT8 data, UINT8 mask); | |
| 608 | void write_stub_legacy(address_space &space, offs_t offset, UINT16 data, UINT16 mask); | |
| 609 | void write_stub_legacy(address_space &space, offs_t offset, UINT32 data, UINT32 mask); | |
| 610 | void write_stub_legacy(address_space &space, offs_t offset, UINT64 data, UINT64 mask); | |
| 611 | ||
| 612 | // stubs for writing I/O ports | |
| 613 | template<typename _UintType> | |
| 614 | void write_stub_ioport(address_space &space, offs_t offset, _UintType data, _UintType mask) { input_port_write_direct(m_ioport, data, mask); } | |
| 502 | 615 | |
| 503 | for (ref = bank->reflist; ref != NULL; ref = ref->next) | |
| 504 | if (ref->space == space) | |
| 505 | return TRUE; | |
| 506 | return FALSE; | |
| 507 | } | |
| 616 | // internal state | |
| 617 | write8_delegate m_write8; | |
| 618 | write16_delegate m_write16; | |
| 619 | write32_delegate m_write32; | |
| 620 | write64_delegate m_write64; | |
| 621 | const input_port_config * m_ioport; | |
| 508 | 622 | |
| 623 | // unions to hold legacy objects and callbacks | |
| 624 | union | |
| 625 | { | |
| 626 | address_space * space; | |
| 627 | device_t * device; | |
| 628 | } m_legacy_object; | |
| 509 | 629 | |
| 510 | /*------------------------------------------------- | |
| 511 | add_bank_reference - add a new address space | |
| 512 | reference to a bank | |
| 513 | -------------------------------------------------*/ | |
| 630 | union | |
| 631 | { | |
| 632 | write8_space_func space8; | |
| 633 | write16_space_func space16; | |
| 634 | write32_space_func space32; | |
| 635 | write64_space_func space64; | |
| 636 | write8_device_func device8; | |
| 637 | write16_device_func device16; | |
| 638 | write32_device_func device32; | |
| 639 | write64_device_func device64; | |
| 640 | } m_legacy_handler; | |
| 641 | }; | |
| 514 | 642 | |
| 515 | INLINE void add_bank_reference(bank_info *bank, const address_space *space) | |
| 516 | { | |
| 517 | bank_reference **refptr; | |
| 518 | 643 | |
| 519 | /* make sure we don't already have a reference to the bank */ | |
| 520 | for (refptr = &bank->reflist; *refptr != NULL; refptr = &(*refptr)->next) | |
| 521 | if ((*refptr)->space == space) | |
| 522 | return; | |
| 644 | // ======================> address_table | |
| 523 | 645 | |
| 524 | /* allocate a new entry and fill it */ | |
| 525 | (*refptr) = auto_alloc(space->machine, bank_reference); | |
| 526 | (*refptr)->next = NULL; | |
| 527 | (*refptr)->space = space; | |
| 528 | } | |
| 646 | // address_table contains information about read/write accesses within an address space | |
| 647 | class address_table : public bindable_object | |
| 648 | { | |
| 649 | // address map lookup table definitions | |
| 650 | static const int LEVEL1_BITS = 18; // number of address bits in the level 1 table | |
| 651 | static const int LEVEL2_BITS = 32 - LEVEL1_BITS; // number of address bits in the level 2 table | |
| 652 | static const int SUBTABLE_COUNT = 64; // number of slots reserved for subtables | |
| 653 | static const int SUBTABLE_BASE = 256 - SUBTABLE_COUNT; // first index of a subtable | |
| 654 | static const int ENTRY_COUNT = SUBTABLE_BASE; // number of legitimate (non-subtable) entries | |
| 655 | static const int SUBTABLE_ALLOC = 8; // number of subtables to allocate at a time | |
| 529 | 656 | |
| 657 | inline int level2_bits() const { return m_large ? LEVEL2_BITS : 0; } | |
| 530 | 658 | |
| 531 | /*------------------------------------------------- | |
| 532 | read_byte_generic - read a byte from an | |
| 533 | arbitrary address space | |
| 534 | -------------------------------------------------*/ | |
| 659 | public: | |
| 660 | // construction/destruction | |
| 661 | address_table(address_space &space, bool large); | |
| 662 | ~address_table(); | |
| 663 | ||
| 664 | // getters | |
| 665 | virtual handler_entry &handler(UINT32 index) const = 0; | |
| 666 | bool watchpoints_enabled() const { return (m_live_lookup == s_watchpoint_table); } | |
| 535 | 667 | |
| 536 | INLINE UINT8 read_byte_generic(const address_space *space, offs_t byteaddress) | |
| 537 | { | |
| 538 | const handler_data *handler; | |
| 539 | offs_t byteoffset; | |
| 540 | UINT32 entry; | |
| 541 | UINT8 result; | |
| 668 | // address lookups | |
| 669 | UINT32 lookup_live(offs_t byteaddress) const { return m_large ? lookup_live_large(byteaddress) : lookup_live_small(byteaddress); } | |
| 670 | UINT32 lookup_live_small(offs_t byteaddress) const { return m_live_lookup[byteaddress]; } | |
| 542 | 671 | |
| 543 | profiler_mark_start(PROFILER_MEMREAD); | |
| 672 | UINT32 lookup_live_large(offs_t byteaddress) const | |
| 673 | { | |
| 674 | UINT32 entry = m_live_lookup[level1_index_large(byteaddress)]; | |
| 675 | if (entry >= SUBTABLE_BASE) | |
| 676 | entry = m_live_lookup[level2_index_large(entry, byteaddress)]; | |
| 677 | return entry; | |
| 678 | } | |
| 544 | 679 | |
| 545 | byteaddress &= space->bytemask; | |
| 546 | entry = space->readlookup[LEVEL1_INDEX(byteaddress)]; | |
| 547 | if (entry >= SUBTABLE_BASE) | |
| 548 | entry = space->readlookup[LEVEL2_INDEX(entry, byteaddress)]; | |
| 549 | handler = space->read.handlers[entry]; | |
| 680 | UINT32 lookup(offs_t byteaddress) const | |
| 681 | { | |
| 682 | UINT32 entry = m_live_lookup[level1_index(byteaddress)]; | |
| 683 | if (entry >= SUBTABLE_BASE) | |
| 684 | entry = m_live_lookup[level2_index(entry, byteaddress)]; | |
| 685 | return entry; | |
| 686 | } | |
| 550 | 687 | |
| 551 | byteoffset = (byteaddress - handler->bytestart) & handler->bytemask; | |
| 552 | if (entry < STATIC_RAM) | |
| 553 | result = (*handler->bankbaseptr)[byteoffset]; | |
| 554 | else | |
| 555 | result = (*handler->handler.read.shandler8)((const address_space *)handler->object, byteoffset); | |
| 688 | // enable watchpoints by swapping in the watchpoint table | |
| 689 | void enable_watchpoints(bool enable = true) { m_live_lookup = enable ? s_watchpoint_table : m_table; } | |
| 556 | 690 | |
| 557 | profiler_mark_end(); | |
| 558 | return result; | |
| 559 | } | |
| 691 | // table mapping helpers | |
| 692 | UINT8 map_range(offs_t bytestart, offs_t byteend, offs_t bytemask, offs_t bytemirror, UINT8 staticentry = 0); | |
| 693 | UINT8 derive_range(offs_t byteaddress, offs_t &bytestart, offs_t &byteend) const; | |
| 560 | 694 | |
| 695 | // misc helpers | |
| 696 | void mask_all_handlers(offs_t mask); | |
| 697 | const char *handler_name(UINT8 entry) const; | |
| 561 | 698 | |
| 562 | /*------------------------------------------------- | |
| 563 | write_byte_generic - write a byte to an | |
| 564 | arbitrary address space | |
| 565 | -------------------------------------------------*/ | |
| 699 | protected: | |
| 700 | // determine table indexes based on the address | |
| 701 | UINT32 level1_index_large(offs_t address) const { return address >> LEVEL2_BITS; } | |
| 702 | UINT32 level2_index_large(UINT8 l1entry, offs_t address) const { return (1 << LEVEL1_BITS) + ((l1entry - SUBTABLE_BASE) << LEVEL2_BITS) + (address & ((1 << LEVEL2_BITS) - 1)); } | |
| 703 | UINT32 level1_index(offs_t address) const { return m_large ? level1_index_large(address) : address; } | |
| 704 | UINT32 level2_index(UINT8 l1entry, offs_t address) const { return m_large ? level2_index_large(l1entry, address) : 0; } | |
| 566 | 705 | |
| 567 | INLINE void write_byte_generic(const address_space *space, offs_t byteaddress, UINT8 data) | |
| 568 | { | |
| 569 | const handler_data *handler; | |
| 570 | offs_t byteoffset; | |
| 571 | UINT32 entry; | |
| 706 | // table population/depopulation | |
| 707 | void populate_range_mirrored(offs_t bytestart, offs_t byteend, offs_t bytemirror, UINT8 handler); | |
| 708 | void populate_range(offs_t bytestart, offs_t byteend, UINT8 handler); | |
| 709 | void depopulate_unused(); | |
| 572 | 710 | |
| 573 | profiler_mark_start(PROFILER_MEMWRITE); | |
| 711 | // subtable management | |
| 712 | UINT8 subtable_alloc(); | |
| 713 | void subtable_realloc(UINT8 subentry); | |
| 714 | int subtable_merge(); | |
| 715 | void subtable_release(UINT8 subentry); | |
| 716 | UINT8 *subtable_open(offs_t l1index); | |
| 717 | void subtable_close(offs_t l1index); | |
| 718 | UINT8 *subtable_ptr(UINT8 entry) { return &m_table[level2_index(entry, 0)]; } | |
| 574 | 719 | |
| 575 | byteaddress &= space->bytemask; | |
| 576 | entry = space->writelookup[LEVEL1_INDEX(byteaddress)]; | |
| 577 | if (entry >= SUBTABLE_BASE) | |
| 578 | entry = space->writelookup[LEVEL2_INDEX(entry, byteaddress)]; | |
| 579 | handler = space->write.handlers[entry]; | |
| 720 | // internal state | |
| 721 | UINT8 * m_table; // pointer to base of table | |
| 722 | UINT8 * m_live_lookup; // current lookup | |
| 723 | address_space & m_space; // pointer back to the space | |
| 724 | bool m_large; // large memory model? | |
| 580 | 725 | |
| 581 | byteoffset = (byteaddress - handler->bytestart) & handler->bytemask; | |
| 582 | if (entry < STATIC_RAM) | |
| 583 | (*handler->bankbaseptr)[byteoffset] = data; | |
| 584 | else | |
| 585 | (*handler->handler.write.shandler8)((const address_space *)handler->object, byteoffset, data); | |
| 726 | // subtable_data is an internal class with information about each subtable | |
| 727 | class subtable_data | |
| 728 | { | |
| 729 | public: | |
| 730 | subtable_data() | |
| 731 | : m_checksum_valid(false), | |
| 732 | m_checksum(0), | |
| 733 | m_usecount(0) { } | |
| 734 | ||
| 735 | bool m_checksum_valid; // is the checksum valid | |
| 736 | UINT32 m_checksum; // checksum over all the bytes | |
| 737 | UINT32 m_usecount; // number of times this has been used | |
| 738 | }; | |
| 739 | subtable_data * m_subtable; // info about each subtable | |
| 740 | UINT8 m_subtable_alloc; // number of subtables allocated | |
| 741 | ||
| 742 | // static global read-only watchpoint table | |
| 743 | static UINT8 s_watchpoint_table[1 << LEVEL1_BITS]; | |
| 744 | }; | |
| 586 | 745 | |
| 587 | profiler_mark_end(); | |
| 588 | } | |
| 589 | 746 | |
| 747 | // ======================> address_table_read | |
| 590 | 748 | |
| 591 | /*------------------------------------------------- | |
| 592 | read_word_generic - read a word from an | |
| 593 | arbitrary address space | |
| 594 | -------------------------------------------------*/ | |
| 595 | ||
| 596 | INLINE UINT16 read_word_generic(const address_space *space, offs_t byteaddress, UINT16 mem_mask) | |
| 749 | // read access-specific version of an address table | |
| 750 | class address_table_read : public address_table | |
| 597 | 751 | { |
| 598 | const handler_data *handler; | |
| 599 | offs_t byteoffset; | |
| 600 | UINT32 entry; | |
| 601 | UINT16 result; | |
| 752 | public: | |
| 753 | // construction/destruction | |
| 754 | address_table_read(address_space &space, bool large); | |
| 755 | ~address_table_read(); | |
| 602 | 756 | |
| 603 | profiler_mark_start(PROFILER_MEMREAD); | |
| 757 | // getters | |
| 758 | virtual handler_entry &handler(UINT32 index) const; | |
| 759 | handler_entry_read &handler_read(UINT32 index) const { assert(index < ARRAY_LENGTH(m_handlers)); return *m_handlers[index]; } | |
| 760 | ||
| 761 | private: | |
| 762 | // internal unmapped handler | |
| 763 | template<typename _UintType> | |
| 764 | _UintType unmap_r(address_space &space, offs_t offset, _UintType mask) | |
| 765 | { | |
| 766 | if (m_space.log_unmap() && !m_space.debugger_access()) | |
| 767 | logerror("%s: unmapped %s memory read from %s\n", cpuexec_describe_context(&m_space.m_machine), m_space.name(), core_i64_hex_format(m_space.byte_to_address(offset), m_space.addrchars())); | |
| 768 | return m_space.unmap(); | |
| 769 | } | |
| 770 | ||
| 771 | // internal no-op handler | |
| 772 | template<typename _UintType> | |
| 773 | _UintType nop_r(address_space &space, offs_t offset, _UintType mask) | |
| 774 | { | |
| 775 | return m_space.unmap(); | |
| 776 | } | |
| 604 | 777 | |
| 605 | byteaddress &= space->bytemask; | |
| 606 | entry = space->readlookup[LEVEL1_INDEX(byteaddress)]; | |
| 607 | if (entry >= SUBTABLE_BASE) | |
| 608 | entry = space->readlookup[LEVEL2_INDEX(entry, byteaddress)]; | |
| 609 | handler = space->read.handlers[entry]; | |
| 778 | // internal watchpoint handler | |
| 779 | template<typename _UintType> | |
| 780 | _UintType watchpoint_r(address_space &space, offs_t offset, _UintType mask) | |
| 781 | { | |
| 782 | m_space.device().debug()->memory_read_hook(m_space, offset, mask); | |
| 610 | 783 | |
| 611 | byteoffset = (byteaddress - handler->bytestart) & handler->bytemask; | |
| 612 | if (entry < STATIC_RAM) | |
| 613 | result = *(UINT16 *)&(*handler->bankbaseptr)[byteoffset & ~1]; | |
| 614 | else | |
| 615 | result = (*handler->handler.read.shandler16)((const address_space *)handler->object, byteoffset >> 1, mem_mask); | |
| 784 | UINT8 *oldtable = m_live_lookup; | |
| 785 | m_live_lookup = m_table; | |
| 786 | _UintType result; | |
| 787 | if (sizeof(_UintType) == 1) result = m_space.read_byte(offset); | |
| 788 | if (sizeof(_UintType) == 2) result = m_space.read_word(offset, mask); | |
| 789 | if (sizeof(_UintType) == 4) result = m_space.read_dword(offset, mask); | |
| 790 | if (sizeof(_UintType) == 8) result = m_space.read_qword(offset, mask); | |
| 791 | m_live_lookup = oldtable; | |
| 792 | return result; | |
| 793 | } | |
| 616 | 794 | |
| 617 | profiler_mark_end(); | |
| 618 | return result; | |
| 619 | } | |
| 795 | // internal state | |
| 796 | handler_entry_read * m_handlers[256]; // array of user-installed handlers | |
| 797 | }; | |
| 620 | 798 | |
| 621 | 799 | |
| 622 | /*------------------------------------------------- | |
| 623 | write_word_generic - write a word to an | |
| 624 | arbitrary address space | |
| 625 | -------------------------------------------------*/ | |
| 800 | // ======================> address_table_write | |
| 626 | 801 | |
| 627 | INLINE void write_word_generic(const address_space *space, offs_t byteaddress, UINT16 data, UINT16 mem_mask) | |
| 802 | // write access-specific version of an address table | |
| 803 | class address_table_write : public address_table | |
| 628 | 804 | { |
| 629 | const handler_data *handler; | |
| 630 | offs_t byteoffset; | |
| 631 | UINT32 entry; | |
| 805 | public: | |
| 806 | // construction/destruction | |
| 807 | address_table_write(address_space &space, bool large); | |
| 808 | ~address_table_write(); | |
| 632 | 809 | |
| 633 | profiler_mark_start(PROFILER_MEMWRITE); | |
| 810 | // getters | |
| 811 | virtual handler_entry &handler(UINT32 index) const; | |
| 812 | handler_entry_write &handler_write(UINT32 index) const { assert(index < ARRAY_LENGTH(m_handlers)); return *m_handlers[index]; } | |
| 634 | 813 | |
| 635 | byteaddress &= space->bytemask; | |
| 636 | entry = space->writelookup[LEVEL1_INDEX(byteaddress)]; | |
| 637 | if (entry >= SUBTABLE_BASE) | |
| 638 | entry = space->writelookup[LEVEL2_INDEX(entry, byteaddress)]; | |
| 639 | handler = space->write.handlers[entry]; | |
| 814 | private: | |
| 815 | // internal handlers | |
| 816 | template<typename _UintType> | |
| 817 | void unmap_w(address_space &space, offs_t offset, _UintType data, _UintType mask) | |
| 818 | { | |
| 819 | if (m_space.log_unmap() && !m_space.debugger_access()) | |
| 820 | logerror("%s: unmapped %s memory write to %s\n", cpuexec_describe_context(&m_space.m_machine), m_space.name(), core_i64_hex_format(m_space.byte_to_address(offset), m_space.addrchars())); | |
| 821 | } | |
| 640 | 822 | |
| 641 | byteoffset = (byteaddress - handler->bytestart) & handler->bytemask; | |
| 642 | if (entry < STATIC_RAM) | |
| 823 | template<typename _UintType> | |
| 824 | void nop_w(address_space &space, offs_t offset, _UintType data, _UintType mask) | |
| 643 | 825 | { |
| 644 | UINT16 *dest = (UINT16 *)&(*handler->bankbaseptr)[byteoffset & ~1]; | |
| 645 | *dest = (*dest & ~mem_mask) | (data & mem_mask); | |
| 646 | 826 | } |
| 647 | else | |
| 648 | (*handler->handler.write.shandler16)((const address_space *)handler->object, byteoffset >> 1, data, mem_mask); | |
| 649 | 827 | |
| 650 | profiler_mark_end(); | |
| 651 | } | |
| 828 | template<typename _UintType> | |
| 829 | void watchpoint_w(address_space &space, offs_t offset, _UintType data, _UintType mask) | |
| 830 | { | |
| 831 | m_space.device().debug()->memory_write_hook(m_space, offset, data, 0xff); | |
| 652 | 832 | |
| 833 | UINT8 *oldtable = m_live_lookup; | |
| 834 | m_live_lookup = m_table; | |
| 835 | if (sizeof(_UintType) == 1) m_space.write_byte(offset, data); | |
| 836 | if (sizeof(_UintType) == 2) m_space.write_word(offset, data, mask); | |
| 837 | if (sizeof(_UintType) == 4) m_space.write_dword(offset, data, mask); | |
| 838 | if (sizeof(_UintType) == 8) m_space.write_qword(offset, data, mask); | |
| 839 | m_live_lookup = oldtable; | |
| 840 | } | |
| 653 | 841 | |
| 654 | /*------------------------------------------------- | |
| 655 | read_dword_generic - read a dword from an | |
| 656 | arbitrary address space | |
| 657 | -------------------------------------------------*/ | |
| 842 | // internal state | |
| 843 | handler_entry_write * m_handlers[256]; // array of user-installed handlers | |
| 844 | }; | |
| 658 | 845 | |
| 659 | INLINE UINT32 read_dword_generic(const address_space *space, offs_t byteaddress, UINT32 mem_mask) | |
| 660 | { | |
| 661 | const handler_data *handler; | |
| 662 | offs_t byteoffset; | |
| 663 | UINT32 entry; | |
| 664 | UINT32 result; | |
| 665 | 846 | |
| 666 | ||
| 847 | // ======================> addr | |
| 667 | 848 | |
| 668 | byteaddress &= space->bytemask; | |
| 669 | entry = space->readlookup[LEVEL1_INDEX(byteaddress)]; | |
| 670 | if (entry >= SUBTABLE_BASE) | |
| 671 | entry = space->readlookup[LEVEL2_INDEX(entry, byteaddress)]; | |
| 672 | handler = space->read.handlers[entry]; | |
| 849 | // this is a derived class of address_space with specific width, endianness, and table size | |
| 850 | template<typename _NativeType, endianness_t _Endian, bool _Large> | |
| 851 | class address_space_specific : public address_space | |
| 852 | { | |
| 853 | typedef address_space_specific<_NativeType, _Endian, _Large> this_type; | |
| 673 | 854 | |
| 674 | byteoffset = (byteaddress - handler->bytestart) & handler->bytemask; | |
| 675 | if (entry < STATIC_RAM) | |
| 676 | result = *(UINT32 *)&(*handler->bankbaseptr)[byteoffset & ~3]; | |
| 677 | else | |
| 678 | result = (*handler->handler.read.shandler32)((const address_space *)handler->object, byteoffset >> 2, mem_mask); | |
| 855 | // helpers to simplify core code | |
| 856 | offs_t endian_xor(offs_t value) { if (_Endian == ENDIANNESS_BIG) value = ~value; return value; } | |
| 857 | int endian_shift(int levalue, int bevalue) { return (_Endian == ENDIANNESS_LITTLE) ? levalue : bevalue; } | |
| 858 | UINT32 read_lookup(offs_t byteaddress) const { return _Large ? m_read.lookup_live_large(byteaddress) : m_read.lookup_live_small(byteaddress); } | |
| 859 | UINT32 write_lookup(offs_t byteaddress) const { return _Large ? m_write.lookup_live_large(byteaddress) : m_write.lookup_live_small(byteaddress); } | |
| 679 | 860 | |
| 680 | profiler_mark_end(); | |
| 681 | return result; | |
| 682 | } | |
| 861 | public: | |
| 862 | // construction/destruction | |
| 863 | address_space_specific(device_memory_interface &memory, int spacenum) | |
| 864 | : address_space(memory, spacenum, _Large), | |
| 865 | m_read(*this, _Large), | |
| 866 | m_write(*this, _Large) { } | |
| 867 | ||
| 868 | // accessors | |
| 869 | virtual address_table_read &read() { return m_read; } | |
| 870 | virtual address_table_write &write() { return m_write; } | |
| 683 | 871 | |
| 872 | // watchpoint control | |
| 873 | virtual void enable_read_watchpoints(bool enable = true) { m_read.enable_watchpoints(enable); } | |
| 874 | virtual void enable_write_watchpoints(bool enable = true) { m_write.enable_watchpoints(enable); } | |
| 684 | 875 | |
| 685 | /*------------------------------------------------- | |
| 686 | write_dword_generic - write a dword to an | |
| 687 | arbitrary address space | |
| 688 | -------------------------------------------------*/ | |
| 689 | ||
| 690 | INLINE void write_dword_generic(const address_space *space, offs_t byteaddress, UINT32 data, UINT32 mem_mask) | |
| 691 | { | |
| 692 | const handler_data *handler; | |
| 693 | offs_t byteoffset; | |
| 694 | UINT32 entry; | |
| 695 | ||
| 696 | profiler_mark_start(PROFILER_MEMWRITE); | |
| 697 | ||
| 698 | byteaddress &= space->bytemask; | |
| 699 | entry = space->writelookup[LEVEL1_INDEX(byteaddress)]; | |
| 700 | if (entry >= SUBTABLE_BASE) | |
| 701 | entry = space->writelookup[LEVEL2_INDEX(entry, byteaddress)]; | |
| 702 | handler = space->write.handlers[entry]; | |
| 703 | ||
| 704 | byteoffset = (byteaddress - handler->bytestart) & handler->bytemask; | |
| 705 | if (entry < STATIC_RAM) | |
| 876 | // generate accessor table | |
| 877 | virtual void accessors(data_accessors &accessors) const | |
| 706 | 878 | { |
| 707 | UINT32 *dest = (UINT32 *)&(*handler->bankbaseptr)[byteoffset & ~3]; | |
| 708 | *dest = (*dest & ~mem_mask) | (data & mem_mask); | |
| 879 | accessors.read_byte = reinterpret_cast<UINT8 (*)(address_space *, offs_t)>(&read_byte_static); | |
| 880 | accessors.read_word = reinterpret_cast<UINT16 (*)(address_space *, offs_t)>(&read_word_static); | |
| 881 | accessors.read_word_masked = reinterpret_cast<UINT16 (*)(address_space *, offs_t, UINT16)>(&read_word_masked_static); | |
| 882 | accessors.read_dword = reinterpret_cast<UINT32 (*)(address_space *, offs_t)>(&read_dword_static); | |
| 883 | accessors.read_dword_masked = reinterpret_cast<UINT32 (*)(address_space *, offs_t, UINT32)>(&read_dword_masked_static); | |
| 884 | accessors.read_qword = reinterpret_cast<UINT64 (*)(address_space *, offs_t)>(&read_qword_static); | |
| 885 | accessors.read_qword_masked = reinterpret_cast<UINT64 (*)(address_space *, offs_t, UINT64)>(&read_qword_masked_static); | |
| 886 | accessors.write_byte = reinterpret_cast<void (*)(address_space *, offs_t, UINT8)>(&write_byte_static); | |
| 887 | accessors.write_word = reinterpret_cast<void (*)(address_space *, offs_t, UINT16)>(&write_word_static); | |
| 888 | accessors.write_word_masked = reinterpret_cast<void (*)(address_space *, offs_t, UINT16, UINT16)>(&write_word_masked_static); | |
| 889 | accessors.write_dword = reinterpret_cast<void (*)(address_space *, offs_t, UINT32)>(&write_dword_static); | |
| 890 | accessors.write_dword_masked = reinterpret_cast<void (*)(address_space *, offs_t, UINT32, UINT32)>(&write_dword_masked_static); | |
| 891 | accessors.write_qword = reinterpret_cast<void (*)(address_space *, offs_t, UINT64)>(&write_qword_static); | |
| 892 | accessors.write_qword_masked = reinterpret_cast<void (*)(address_space *, offs_t, UINT64, UINT64)>(&write_qword_masked_static); | |
| 709 | 893 | } |
| 710 | else | |
| 711 | (*handler->handler.write.shandler32)((const address_space *)handler->object, byteoffset >> 2, data, mem_mask); | |
| 712 | 894 | |
| 713 | profiler_mark_end(); | |
| 714 | } | |
| 895 | // | |
| 896 | virtual void *get_read_ptr(offs_t byteaddress) | |
| 897 | { | |
| 898 | // perform the lookup | |
| 899 | byteaddress &= m_bytemask; | |
| 900 | UINT32 entry = read_lookup(byteaddress); | |
| 901 | const handler_entry_read &handler = m_read.handler_read(entry); | |
| 715 | 902 | |
| 903 | // 8-bit case: RAM/ROM | |
| 904 | if (entry >= STATIC_RAM) | |
| 905 | return NULL; | |
| 906 | return handler.ramptr(handler.byteoffset(byteaddress)); | |
| 907 | } | |
| 716 | 908 | |
| 717 | /*------------------------------------------------- | |
| 718 | read_qword_generic - read a qword from an | |
| 719 | arbitrary address space | |
| 720 | -------------------------------------------------*/ | |
| 909 | virtual void *get_write_ptr(offs_t byteaddress) | |
| 910 | { | |
| 911 | // perform the lookup | |
| 912 | byteaddress &= m_bytemask; | |
| 913 | UINT32 entry = read_lookup(byteaddress); | |
| 914 | const handler_entry_write &handler = m_write.handler_write(entry); | |
| 721 | 915 | |
| 722 | INLINE UINT64 read_qword_generic(const address_space *space, offs_t byteaddress, UINT64 mem_mask) | |
| 723 | { | |
| 724 | const handler_data *handler; | |
| 725 | offs_t byteoffset; | |
| 726 | UINT32 entry; | |
| 727 | UINT64 result; | |
| 916 | // 8-bit case: RAM/ROM | |
| 917 | if (entry >= STATIC_RAM) | |
| 918 | return NULL; | |
| 919 | return handler.ramptr(handler.byteoffset(byteaddress)); | |
| 920 | } | |
| 728 | 921 | |
| 729 | profiler_mark_start(PROFILER_MEMREAD); | |
| 922 | // native read | |
| 923 | _NativeType read_native(offs_t offset, _NativeType mask) | |
| 924 | { | |
| 925 | profiler_mark_start(PROFILER_MEMREAD); | |
| 730 | 926 | |
| 731 | byteaddress &= space->bytemask; | |
| 732 | entry = space->readlookup[LEVEL1_INDEX(byteaddress)]; | |
| 733 | if (entry >= SUBTABLE_BASE) | |
| 734 | entry = space->readlookup[LEVEL2_INDEX(entry, byteaddress)]; | |
| 735 | handler = space->read.handlers[entry]; | |
| 927 | // look up the handler | |
| 928 | offs_t byteaddress = offset & m_bytemask; | |
| 929 | UINT32 entry = read_lookup(byteaddress); | |
| 930 | const handler_entry_read &handler = m_read.handler_read(entry); | |
| 736 | 931 | |
| 737 | byteoffset = (byteaddress - handler->bytestart) & handler->bytemask; | |
| 738 | if (entry < STATIC_RAM) | |
| 739 | result = *(UINT64 *)&(*handler->bankbaseptr)[byteoffset & ~7]; | |
| 740 | else | |
| 741 | result = (*handler->handler.read.shandler64)((const address_space *)handler->object, byteoffset >> 3, mem_mask); | |
| 932 | // either read directly from RAM, or call the delegate | |
| 933 | offset = handler.byteoffset(byteaddress) / sizeof(_NativeType); | |
| 934 | _NativeType result; | |
| 935 | if (entry < STATIC_RAM) result = *reinterpret_cast<_NativeType *>(handler.ramptr(offset * sizeof(_NativeType))); | |
| 936 | else if (sizeof(_NativeType) == 1) result = handler.read8(*this, offset, mask); | |
| 937 | else if (sizeof(_NativeType) == 2) result = handler.read16(*this, offset, mask); | |
| 938 | else if (sizeof(_NativeType) == 4) result = handler.read32(*this, offset, mask); | |
| 939 | else if (sizeof(_NativeType) == 8) result = handler.read64(*this, offset, mask); | |
| 742 | 940 | |
| 743 | profiler_mark_end(); | |
| 744 | return result; | |
| 745 | } | |
| 941 | profiler_mark_end(); | |
| 942 | return result; | |
| 943 | } | |
| 746 | 944 | |
| 945 | // native write | |
| 946 | void write_native(offs_t offset, _NativeType data, _NativeType mask) | |
| 947 | { | |
| 948 | profiler_mark_start(PROFILER_MEMWRITE); | |
| 747 | 949 | |
| 748 | /*------------------------------------------------- | |
| 749 | write_qword_generic - write a qword to an | |
| 750 | arbitrary address space | |
| 751 | -------------------------------------------------*/ | |
| 950 | // look up the handler | |
| 951 | offs_t byteaddress = offset & m_bytemask; | |
| 952 | UINT32 entry = write_lookup(byteaddress); | |
| 953 | const handler_entry_write &handler = m_write.handler_write(entry); | |
| 752 | 954 | |
| 753 | INLINE void write_qword_generic(const address_space *space, offs_t byteaddress, UINT64 data, UINT64 mem_mask) | |
| 754 | { | |
| 755 | const handler_data *handler; | |
| 756 | offs_t offset; | |
| 757 | UINT32 entry; | |
| 955 | // either write directly to RAM, or call the delegate | |
| 956 | offset = handler.byteoffset(byteaddress) / sizeof(_NativeType); | |
| 957 | if (entry < STATIC_RAM) | |
| 958 | { | |
| 959 | _NativeType *dest = reinterpret_cast<_NativeType *>(handler.ramptr(offset * sizeof(_NativeType))); | |
| 960 | *dest = (*dest & ~mask) | (data & mask); | |
| 961 | } | |
| 962 | else if (sizeof(_NativeType) == 1) handler.write8(*this, offset, data, mask); | |
| 963 | else if (sizeof(_NativeType) == 2) handler.write16(*this, offset, data, mask); | |
| 964 | else if (sizeof(_NativeType) == 4) handler.write32(*this, offset, data, mask); | |
| 965 | else if (sizeof(_NativeType) == 8) handler.write64(*this, offset, data, mask); | |
| 758 | 966 | |
| 759 | profiler_mark_start(PROFILER_MEMWRITE); | |
| 967 | profiler_mark_end(); | |
| 968 | } | |
| 760 | 969 | |
| 761 | byteaddress &= space->bytemask; | |
| 762 | entry = space->writelookup[LEVEL1_INDEX(byteaddress)]; | |
| 763 | if (entry >= SUBTABLE_BASE) | |
| 764 | entry = space->writelookup[LEVEL2_INDEX(entry, byteaddress)]; | |
| 765 | handler = space->write.handlers[entry]; | |
| 766 | ||
| 767 | offset = (byteaddress - handler->bytestart) & handler->bytemask; | |
| 768 | if (entry < STATIC_RAM) | |
| 970 | // read byte | |
| 971 | UINT8 read_byte_direct(offs_t address) | |
| 769 | 972 | { |
| 770 | UINT64 *dest = (UINT64 *)&(*handler->bankbaseptr)[offset & ~7]; | |
| 771 | *dest = (*dest & ~mem_mask) | (data & mem_mask); | |
| 973 | if (sizeof(_NativeType) == 1) | |
| 974 | return read_native(address, 0xff); | |
| 975 | ||
| 976 | if (sizeof(_NativeType) > 1) | |
| 977 | { | |
| 978 | UINT32 shift = (endian_xor(address) & (sizeof(_NativeType) - 1)) * 8; | |
| 979 | return read_native(address, (_NativeType)0xff << shift) >> shift; | |
| 980 | } | |
| 772 | 981 | } |
| 773 | else | |
| 774 | (*handler->handler.write.shandler64)((const address_space *)handler->object, offset >> 3, data, mem_mask); | |
| 982 | ||
| 983 | // read word | |
| 984 | UINT16 read_word_direct(offs_t address, UINT16 mask) | |
| 985 | { | |
| 986 | if (sizeof(_NativeType) == 2) | |
| 987 | return read_native(address, mask); | |
| 775 | 988 | |
| 776 | profiler_mark_end(); | |
| 777 | } | |
| 989 | if (sizeof(_NativeType) > 2) | |
| 990 | { | |
| 991 | UINT32 shift = (endian_xor(address) & (sizeof(_NativeType) - 2)) * 8; | |
| 992 | return read_native(address, (_NativeType)mask << shift) >> shift; | |
| 993 | } | |
| 994 | ||
| 995 | if (sizeof(_NativeType) < 2) | |
| 996 | { | |
| 997 | UINT16 result = 0; | |
| 998 | if (EXPECTED(mask & (0xff << endian_shift(0,8)))) result |= read_byte_direct(address + 0) << endian_shift(0,8); | |
| 999 | if (EXPECTED(mask & (0xff << endian_shift(8,0)))) result |= read_byte_direct(address + 1) << endian_shift(8,0); | |
| 1000 | return result; | |
| 1001 | } | |
| 1002 | } | |
| 778 | 1003 | |
| 1004 | // read dword | |
| 1005 | UINT32 read_dword_direct(offs_t address, UINT32 mask) | |
| 1006 | { | |
| 1007 | if (sizeof(_NativeType) == 4) | |
| 1008 | return read_native(address, mask); | |
| 779 | 1009 | |
| 1010 | if (sizeof(_NativeType) > 4) | |
| 1011 | { | |
| 1012 | UINT32 shift = (endian_xor(address) & (sizeof(_NativeType) - 4)) * 8; | |
| 1013 | return read_native(address, (_NativeType)mask << shift) >> shift; | |
| 1014 | } | |
| 1015 | ||
| 1016 | if (sizeof(_NativeType) < 4) | |
| 1017 | { | |
| 1018 | UINT32 result = 0; | |
| 1019 | if (EXPECTED(mask & (0xffff << endian_shift(0,16)))) result |= read_word_direct(address + 0, mask >> endian_shift(0,16)) << endian_shift(0,16); | |
| 1020 | if (EXPECTED(mask & (0xffff << endian_shift(16,0)))) result |= read_word_direct(address + 2, mask >> endian_shift(16,0)) << endian_shift(16,0); | |
| 1021 | return result; | |
| 1022 | } | |
| 1023 | } | |
| 780 | 1024 | |
| 781 | /*************************************************************************** | |
| 782 | CORE SYSTEM OPERATIONS | |
| 783 | ***************************************************************************/ | |
| 1025 | // read qword | |
| 1026 | UINT64 read_qword_direct(offs_t address, UINT64 mask) | |
| 1027 | { | |
| 1028 | if (sizeof(_NativeType) == 8) | |
| 1029 | return read_native(address, mask); | |
| 784 | 1030 | |
| 785 | /*------------------------------------------------- | |
| 786 | memory_init - initialize the memory system | |
| 787 | -------------------------------------------------*/ | |
| 1031 | if (sizeof(_NativeType) < 8) | |
| 1032 | { | |
| 1033 | UINT64 result = 0; | |
| 1034 | if (EXPECTED(mask & (U64(0xffffffff) << endian_shift(0,32)))) result |= (UINT64)read_dword_direct(address + 0, mask >> endian_shift(0,32)) << endian_shift(0,32); | |
| 1035 | if (EXPECTED(mask & (U64(0xffffffff) << endian_shift(32,0)))) result |= (UINT64)read_dword_direct(address + 4, mask >> endian_shift(32,0)) << endian_shift(32,0); | |
| 1036 | return result; | |
| 1037 | } | |
| 1038 | } | |
| 788 | 1039 | |
| 789 | void memory_init(running_machine *machine) | |
| 790 | { | |
| 791 | memory_private *memdata; | |
| 1040 | // write byte | |
| 1041 | void write_byte_direct(offs_t address, UINT8 data) | |
| 1042 | { | |
| 1043 | if (sizeof(_NativeType) == 1) | |
| 1044 | return write_native(address, data, 0xff); | |
| 1045 | ||
| 1046 | if (sizeof(_NativeType) > 1) | |
| 1047 | { | |
| 1048 | UINT32 shift = (endian_xor(address) & (sizeof(_NativeType) - 1)) * 8; | |
| 1049 | return write_native(address, (_NativeType)data << shift, (_NativeType)0xff << shift); | |
| 1050 | } | |
| 1051 | } | |
| 1052 | ||
| 1053 | // write word | |
| 1054 | void write_word_direct(offs_t address, UINT16 data, UINT16 mask) | |
| 1055 | { | |
| 1056 | if (sizeof(_NativeType) == 2) | |
| 1057 | return write_native(address, data, mask); | |
| 1058 | ||
| 1059 | if (sizeof(_NativeType) > 2) | |
| 1060 | { | |
| 1061 | UINT32 shift = (endian_xor(address) & (sizeof(_NativeType) - 2)) * 8; | |
| 1062 | return write_native(address, (_NativeType)data << shift, (_NativeType)mask << shift); | |
| 1063 | } | |
| 792 | 1064 | |
| 793 | machine->add_notifier(MACHINE_NOTIFY_EXIT, memory_exit); | |
| 1065 | if (sizeof(_NativeType) < 2) | |
| 1066 | { | |
| 1067 | if (EXPECTED(mask & (0xff << endian_shift(0,8)))) write_byte_direct(address + 0, data >> endian_shift(0,8)); | |
| 1068 | if (EXPECTED(mask & (0xff << endian_shift(8,0)))) write_byte_direct(address + 1, data >> endian_shift(8,0)); | |
| 1069 | } | |
| 1070 | } | |
| 1071 | ||
| 1072 | // write dword | |
| 1073 | void write_dword_direct(offs_t address, UINT32 data, UINT32 mask) | |
| 1074 | { | |
| 1075 | if (sizeof(_NativeType) == 4) | |
| 1076 | return write_native(address, data, mask); | |
| 1077 | ||
| 1078 | if (sizeof(_NativeType) > 4) | |
| 1079 | { | |
| 1080 | UINT32 shift = (endian_xor(address) & (sizeof(_NativeType) - 4)) * 8; | |
| 1081 | return write_native(address, (_NativeType)data << shift, (_NativeType)mask << shift); | |
| 1082 | } | |
| 794 | 1083 | |
| 795 | /* allocate our private data */ | |
| 796 | memdata = machine->memory_data = auto_alloc_clear(machine, memory_private); | |
| 1084 | if (sizeof(_NativeType) < 4) | |
| 1085 | { | |
| 1086 | if (EXPECTED(mask & (0xffff << endian_shift(0,16)))) write_word_direct(address + 0, data >> endian_shift(0,16), mask >> endian_shift(0,16)); | |
| 1087 | if (EXPECTED(mask & (0xffff << endian_shift(16,0)))) write_word_direct(address + 2, data >> endian_shift(16,0), mask >> endian_shift(16,0)); | |
| 1088 | } | |
| 1089 | } | |
| 1090 | ||
| 1091 | // write qword | |
| 1092 | void write_qword_direct(offs_t address, UINT64 data, UINT64 mask) | |
| 1093 | { | |
| 1094 | if (sizeof(_NativeType) == 8) | |
| 1095 | return write_native(address, data, mask); | |
| 1096 | ||
| 1097 | if (sizeof(_NativeType) < 8) | |
| 1098 | { | |
| 1099 | if (EXPECTED(mask & (U64(0xffffffff) << endian_shift(0,32)))) write_dword_direct(address + 0, data >> endian_shift(0,32), mask >> endian_shift(0,32)); | |
| 1100 | if (EXPECTED(mask & (U64(0xffffffff) << endian_shift(32,0)))) write_dword_direct(address + 4, data >> endian_shift(32,0), mask >> endian_shift(32,0)); | |
| 1101 | } | |
| 1102 | } | |
| 1103 | ||
| 1104 | // virtual access to these functions | |
| 1105 | UINT8 read_byte(offs_t address) { return read_byte_direct(address); } | |
| 1106 | UINT16 read_word(offs_t address, UINT16 mask) { return read_word_direct(address, mask); } | |
| 1107 | UINT32 read_dword(offs_t address, UINT32 mask) { return read_dword_direct(address, mask); } | |
| 1108 | UINT64 read_qword(offs_t address, UINT64 mask) { return read_qword_direct(address, mask); } | |
| 1109 | void write_byte(offs_t address, UINT8 data) { write_byte_direct(address, data); } | |
| 1110 | void write_word(offs_t address, UINT16 data, UINT16 mask) { write_word_direct(address, data, mask); } | |
| 1111 | void write_dword(offs_t address, UINT32 data, UINT32 mask) { write_dword_direct(address, data, mask); } | |
| 1112 | void write_qword(offs_t address, UINT64 data, UINT64 mask) { write_qword_direct(address, data, mask); } | |
| 1113 | ||
| 1114 | // static access to these functions | |
| 1115 | static UINT8 read_byte_static(this_type *space, offs_t address) { return space->read_byte_direct(address); } | |
| 1116 | static UINT16 read_word_static(this_type *space, offs_t address) { return space->read_word_direct(address, 0xffff); } | |
| 1117 | static UINT16 read_word_masked_static(this_type *space, offs_t address, UINT16 mask) { return space->read_word_direct(address, mask); } | |
| 1118 | static UINT32 read_dword_static(this_type *space, offs_t address) { return space->read_dword_direct(address, 0xffffffff); } | |
| 1119 | static UINT32 read_dword_masked_static(this_type *space, offs_t address, UINT32 mask) { return space->read_dword_direct(address, mask); } | |
| 1120 | static UINT64 read_qword_static(this_type *space, offs_t address) { return space->read_qword_direct(address, U64(0xffffffffffffffff)); } | |
| 1121 | static UINT64 read_qword_masked_static(this_type *space, offs_t address, UINT64 mask) { return space->read_qword_direct(address, mask); } | |
| 1122 | static void write_byte_static(this_type *space, offs_t address, UINT8 data) { space->write_byte_direct(address, data); } | |
| 1123 | static void write_word_static(this_type *space, offs_t address, UINT16 data) { space->write_word_direct(address, data, 0xffff); } | |
| 1124 | static void write_word_masked_static(this_type *space, offs_t address, UINT16 data, UINT16 mask) { space->write_word_direct(address, data, mask); } | |
| 1125 | static void write_dword_static(this_type *space, offs_t address, UINT32 data) { space->write_dword_direct(address, data, 0xffffffff); } | |
| 1126 | static void write_dword_masked_static(this_type *space, offs_t address, UINT32 data, UINT32 mask) { space->write_dword_direct(address, data, mask); } | |
| 1127 | static void write_qword_static(this_type *space, offs_t address, UINT64 data) { space->write_qword_direct(address, data, U64(0xffffffffffffffff)); } | |
| 1128 | static void write_qword_masked_static(this_type *space, offs_t address, UINT64 data, UINT64 mask) { space->write_qword_direct(address, data, mask); } | |
| 797 | 1129 | |
| 798 | /* build up the list of address spaces */ | |
| 799 | memory_init_spaces(machine); | |
| 1130 | address_table_read m_read; // memory read lookup table | |
| 1131 | address_table_write m_write; // memory write lookup table | |
| 1132 | }; | |
| 800 | 1133 | |
| 801 | /* preflight the memory handlers and check banks */ | |
| 802 | memory_init_preflight(machine); | |
| 1134 | typedef address_space_specific<UINT8, ENDIANNESS_LITTLE, false> address_space_8le_small; | |
| 1135 | typedef address_space_specific<UINT8, ENDIANNESS_BIG, false> address_space_8be_small; | |
| 1136 | typedef address_space_specific<UINT16, ENDIANNESS_LITTLE, false> address_space_16le_small; | |
| 1137 | typedef address_space_specific<UINT16, ENDIANNESS_BIG, false> address_space_16be_small; | |
| 1138 | typedef address_space_specific<UINT32, ENDIANNESS_LITTLE, false> address_space_32le_small; | |
| 1139 | typedef address_space_specific<UINT32, ENDIANNESS_BIG, false> address_space_32be_small; | |
| 1140 | typedef address_space_specific<UINT64, ENDIANNESS_LITTLE, false> address_space_64le_small; | |
| 1141 | typedef address_space_specific<UINT64, ENDIANNESS_BIG, false> address_space_64be_small; | |
| 803 | 1142 | |
| 804 | /* then fill in the tables */ | |
| 805 | memory_init_populate(machine); | |
| 1143 | typedef address_space_specific<UINT8, ENDIANNESS_LITTLE, true> address_space_8le_large; | |
| 1144 | typedef address_space_specific<UINT8, ENDIANNESS_BIG, true> address_space_8be_large; | |
| 1145 | typedef address_space_specific<UINT16, ENDIANNESS_LITTLE, true> address_space_16le_large; | |
| 1146 | typedef address_space_specific<UINT16, ENDIANNESS_BIG, true> address_space_16be_large; | |
| 1147 | typedef address_space_specific<UINT32, ENDIANNESS_LITTLE, true> address_space_32le_large; | |
| 1148 | typedef address_space_specific<UINT32, ENDIANNESS_BIG, true> address_space_32be_large; | |
| 1149 | typedef address_space_specific<UINT64, ENDIANNESS_LITTLE, true> address_space_64le_large; | |
| 1150 | typedef address_space_specific<UINT64, ENDIANNESS_BIG, true> address_space_64be_large; | |
| 806 | 1151 | |
| 807 | /* allocate any necessary memory */ | |
| 808 | memory_init_allocate(machine); | |
| 809 | 1152 | |
| 810 | /* find all the allocated pointers */ | |
| 811 | memory_init_locate(machine); | |
| 1153 | // ======================> _memory_private | |
| 812 | 1154 | |
| 813 | /* dump the final memory configuration */ | |
| 814 | mem_dump(machine); | |
| 815 | ||
| 816 | /* we are now initialized */ | |
| 817 | memdata->initialized = TRUE; | |
| 818 | } | |
| 819 | ||
| 820 | ||
| 821 | ||
| 822 | /*************************************************************************** | |
| 823 | DIRECT ACCESS CONTROL | |
| 824 | ***************************************************************************/ | |
| 825 | ||
| 826 | /*------------------------------------------------- | |
| 827 | memory_set_decrypted_region - registers an | |
| 828 | address range as having a decrypted data | |
| 829 | pointer | |
| 830 | -------------------------------------------------*/ | |
| 831 | ||
| 832 | void memory_set_decrypted_region(const address_space *space, offs_t addrstart, offs_t addrend, void *base) | |
| 1155 | // holds internal state for the memory system | |
| 1156 | struct _memory_private | |
| 833 | 1157 | { |
| 834 | offs_t bytestart = memory_address_to_byte(space, addrstart); | |
| 835 | offs_t byteend = memory_address_to_byte_end(space, addrend); | |
| 836 | int found = FALSE; | |
| 837 | bank_info *bank; | |
| 1158 | bool initialized; // have we completed initialization? | |
| 838 | 1159 | |
| 839 | /* loop over banks looking for a match */ | |
| 840 | for (bank = space->machine->memory_data->banklist; bank != NULL; bank = bank->next) | |
| 841 | { | |
| 842 | /* consider this bank if it is used for reading and matches the address space */ | |
| 843 | if (bank->read && bank_references_space(bank, space)) | |
| 844 | { | |
| 845 | /* verify that the region fully covers the decrypted range */ | |
| 846 | if (bank->bytestart >= bytestart && bank->byteend <= byteend) | |
| 847 | { | |
| 848 | /* set the decrypted pointer for the corresponding memory bank */ | |
| 849 | space->machine->memory_data->bankd_ptr[bank->index] = (UINT8 *)base + bank->bytestart - bytestart; | |
| 850 | found = TRUE; | |
| 1160 | UINT8 * bank_ptr[STATIC_COUNT]; // array of bank pointers | |
| 1161 | UINT8 * bankd_ptr[STATIC_COUNT]; // array of decrypted bank pointers | |
| 851 | 1162 | |
| 852 | /* if we are executing from here, force an opcode base update */ | |
| 853 | if (space->direct.entry == bank->index) | |
| 854 | force_opbase_update(space); | |
| 855 | } | |
| 1163 | simple_list<address_space> spacelist; // list of address spaces | |
| 1164 | simple_list<memory_block> blocklist; // head of the list of memory blocks | |
| 856 | 1165 | |
| 857 | /* fatal error if the decrypted region straddles the bank */ | |
| 858 | else if (bank->bytestart < byteend && bank->byteend > bytestart) | |
| 859 | fatalerror("memory_set_decrypted_region found straddled region %08X-%08X for device '%s'", bytestart, byteend, space->cpu->tag()); | |
| 860 | } | |
| 861 | } | |
| 1166 | simple_list<memory_bank> banklist; // data gathered for each bank | |
| 1167 | tagmap_t<memory_bank *> bankmap; // map for fast bank lookups | |
| 1168 | UINT8 banknext; // next bank to allocate | |
| 862 | 1169 | |
| 863 | /* fatal error as well if we didn't find any relevant memory banks */ | |
| 864 | if (!found) | |
| 865 | fatalerror("memory_set_decrypted_region unable to find matching region %08X-%08X for device '%s'", bytestart, byteend, space->cpu->tag()); | |
| 866 | } | |
| 1170 | tagmap_t<void *> sharemap; // map for share lookups | |
| 1171 | }; | |
| 867 | 1172 | |
| 868 | 1173 | |
| 869 | /*------------------------------------------------- | |
| 870 | memory_set_direct_update_handler - register a | |
| 871 | handler for opcode base changes on a given | |
| 872 | device | |
| 873 | -------------------------------------------------*/ | |
| 874 | 1174 | |
| 875 | direct_update_func memory_set_direct_update_handler(const address_space *space, direct_update_func function) | |
| 876 | { | |
| 877 | address_space *spacerw = (address_space *)space; | |
| 878 | direct_update_func old = spacerw->directupdate; | |
| 879 | spacerw->directupdate = function; | |
| 880 | return old; | |
| 881 | } | |
| 1175 | //************************************************************************** | |
| 1176 | // GLOBAL VARIABLES | |
| 1177 | //************************************************************************** | |
| 882 | 1178 | |
| 1179 | // global watchpoint table | |
| 1180 | UINT8 address_table::s_watchpoint_table[1 << LEVEL1_BITS]; | |
| 883 | 1181 | |
| 884 | /*------------------------------------------------- | |
| 885 | memory_set_direct_region - called by device | |
| 886 | cores to update the opcode base for the given | |
| 887 | address | |
| 888 | -------------------------------------------------*/ | |
| 889 | 1182 | |
| 890 | int memory_set_direct_region(const address_space *space, offs_t *byteaddress) | |
| 891 | { | |
| 892 | memory_private *memdata = space->machine->memory_data; | |
| 893 | address_space *spacerw = (address_space *)space; | |
| 894 | UINT8 *base = NULL, *based = NULL; | |
| 895 | const handler_data *handlers; | |
| 896 | direct_range *range; | |
| 897 | offs_t maskedbits; | |
| 898 | offs_t overrideaddress = *byteaddress; | |
| 899 | UINT8 entry; | |
| 900 | 1183 | |
| 901 | /* allow overrides */ | |
| 902 | if (spacerw->directupdate != NULL) | |
| 903 | { | |
| 904 | overrideaddress = (*spacerw->directupdate)(spacerw, overrideaddress, &spacerw->direct); | |
| 905 | if (overrideaddress == ~0) | |
| 906 | return TRUE; | |
| 1184 | //************************************************************************** | |
| 1185 | // FUNCTION PROTOTYPES | |
| 1186 | //************************************************************************** | |
| 907 | 1187 | |
| 908 | *byteaddress = overrideaddress; | |
| 909 | } | |
| 1188 | // banking helpers | |
| 1189 | static STATE_POSTLOAD( bank_reattach ); | |
| 910 | 1190 | |
| 911 | /* remove the masked bits (we'll put them back later) */ | |
| 912 | maskedbits = overrideaddress & ~spacerw->bytemask; | |
| 1191 | // debugging | |
| 1192 | static void generate_memdump(running_machine *machine); | |
| 913 | 1193 | |
| 914 | /* find or allocate a matching range */ | |
| 915 | range = direct_range_find(spacerw, overrideaddress, &entry); | |
| 916 | 1194 | |
| 917 | /* keep track of current entry */ | |
| 918 | spacerw->direct.entry = entry; | |
| 919 | 1195 | |
| 920 | /* if we don't map to a bank, return FALSE */ | |
| 921 | if (entry < STATIC_BANK1 || entry >= STATIC_RAM) | |
| 922 | { | |
| 923 | /* ensure future updates to land here as well until we get back into a bank */ | |
| 924 | spacerw->direct.byteend = 0; | |
| 925 | spacerw->direct.bytestart = 1; | |
| 926 | return FALSE; | |
| 927 | } | |
| 1196 | //************************************************************************** | |
| 1197 | // CORE SYSTEM OPERATIONS | |
| 1198 | //************************************************************************** | |
| 928 | 1199 | |
| 929 | /* if no decrypted opcodes, point to the same base */ | |
| 930 | base = memdata->bank_ptr[entry]; | |
| 931 | based = memdata->bankd_ptr[entry]; | |
| 932 | if (based == NULL) | |
| 933 | based = base; | |
| 1200 | //------------------------------------------------- | |
| 1201 | // memory_init - initialize the memory system | |
| 1202 | //------------------------------------------------- | |
| 934 | 1203 | |
| 935 | /* compute the adjusted base */ | |
| 936 | handlers = spacerw->read.handlers[entry]; | |
| 937 | spacerw->direct.bytemask = handlers->bytemask; | |
| 938 | spacerw->direct.raw = base - (handlers->bytestart & spacerw->direct.bytemask); | |
| 939 | spacerw->direct.decrypted = based - (handlers->bytestart & spacerw->direct.bytemask); | |
| 940 | spacerw->direct.bytestart = maskedbits | range->bytestart; | |
| 941 | spacerw->direct.byteend = maskedbits | range->byteend; | |
| 942 | return TRUE; | |
| 943 | } | |
| 1204 | void memory_init(running_machine *machine) | |
| 1205 | { | |
| 1206 | // allocate our private data | |
| 1207 | memory_private *memdata = machine->memory_data = auto_alloc_clear(machine, memory_private); | |
| 1208 | memdata->banknext = STATIC_BANK1; | |
| 1209 | ||
| 1210 | // loop over devices and spaces within each device | |
| 1211 | device_memory_interface *memory = NULL; | |
| 1212 | for (bool gotone = machine->m_devicelist.first(memory); gotone; gotone = memory->next(memory)) | |
| 1213 | for (int spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++) | |
| 1214 | { | |
| 1215 | // if there is a configuration for this space, we need an address space | |
| 1216 | const address_space_config *spaceconfig = memory->space_config(spacenum); | |
| 1217 | if (spaceconfig != NULL) | |
| 1218 | memdata->spacelist.append(address_space::allocate(*machine, *spaceconfig, *memory, spacenum)); | |
| 1219 | } | |
| 944 | 1220 | |
| 1221 | // construct and preprocess the address_map for each space | |
| 1222 | for (address_space *space = memdata->spacelist.first(); space != NULL; space = space->next()) | |
| 1223 | space->prepare_map(); | |
| 945 | 1224 | |
| 946 | /*------------------------------------------------- | |
| 947 | memory_get_read_ptr - return a pointer the | |
| 948 | memory byte provided in the given address | |
| 949 | space, or NULL if it is not mapped to a bank | |
| 950 | -------------------------------------------------*/ | |
| 1225 | // create the handlers from the resulting address maps | |
| 1226 | for (address_space *space = memdata->spacelist.first(); space != NULL; space = space->next()) | |
| 1227 | space->populate_from_map(); | |
| 951 | 1228 | |
| 952 | void *memory_get_read_ptr(const address_space *space, offs_t byteaddress) | |
| 953 | { | |
| 954 | const handler_data *handler; | |
| 955 | offs_t byteoffset; | |
| 956 | UINT8 entry; | |
| 1229 | // allocate memory needed to back each address space | |
| 1230 | for (address_space *space = memdata->spacelist.first(); space != NULL; space = space->next()) | |
| 1231 | space->allocate_memory(); | |
| 957 | 1232 | |
| 958 | /* perform the lookup */ | |
| 959 | byteaddress &= space->bytemask; | |
| 960 | entry = space->read.table[LEVEL1_INDEX(byteaddress)]; | |
| 961 | if (entry >= SUBTABLE_BASE) | |
| 962 | entry = space->read.table[LEVEL2_INDEX(entry, byteaddress)]; | |
| 963 | handler = space->read.handlers[entry]; | |
| 1233 | // find all the allocated pointers | |
| 1234 | for (address_space *space = memdata->spacelist.first(); space != NULL; space = space->next()) | |
| 1235 | space->locate_memory(); | |
| 964 | 1236 | |
| 965 | /* 8-bit case: RAM/ROM */ | |
| 966 | if (entry >= STATIC_RAM) | |
| 967 | return NULL; | |
| 968 | byteoffset = (byteaddress - handler->bytestart) & handler->bytemask; | |
| 969 | return &(*handler->bankbaseptr)[byteoffset]; | |
| 970 | } | |
| 1237 | // register a callback to reset banks when reloading state | |
| 1238 | state_save_register_postload(machine, bank_reattach, NULL); | |
| 971 | 1239 | |
| 1240 | // dump the final memory configuration | |
| 1241 | generate_memdump(machine); | |
| 972 | 1242 | |
| 973 | /*------------------------------------------------- | |
| 974 | memory_get_write_ptr - return a pointer the | |
| 975 | memory byte provided in the given address | |
| 976 | space, or NULL if it is not mapped to a | |
| 977 | writeable bank | |
| 978 | -------------------------------------------------*/ | |
| 1243 | // borrow the first address space to be used as a dummy space | |
| 1244 | machine->m_nonspecific_space = memdata->spacelist.first(); | |
| 979 | 1245 | |
| 980 | void *memory_get_write_ptr(const address_space *space, offs_t byteaddress) | |
| 981 | { | |
| 982 | const handler_data *handler; | |
| 983 | offs_t byteoffset; | |
| 984 | UINT8 entry; | |
| 985 | ||
| 986 | /* perform the lookup */ | |
| 987 | byteaddress &= space->bytemask; | |
| 988 | entry = space->write.table[LEVEL1_INDEX(byteaddress)]; | |
| 989 | if (entry >= SUBTABLE_BASE) | |
| 990 | entry = space->write.table[LEVEL2_INDEX(entry, byteaddress)]; | |
| 991 | handler = space->write.handlers[entry]; | |
| 992 | ||
| 993 | /* 8-bit case: RAM/ROM */ | |
| 994 | if (entry >= STATIC_RAM) | |
| 995 | return NULL; | |
| 996 | byteoffset = (byteaddress - handler->bytestart) & handler->bytemask; | |
| 997 | return &(*handler->bankbaseptr)[byteoffset]; | |
| 1246 | // we are now initialized | |
| 1247 | memdata->initialized = true; | |
| 998 | 1248 | } |
| 999 | 1249 | |
| 1000 | 1250 | |
| 1001 | 1251 | |
| 1002 | /*************************************************************************** | |
| 1003 | MEMORY BANKING | |
| 1004 | ***************************************************************************/ | |
| 1252 | //************************************************************************** | |
| 1253 | // MEMORY BANKING | |
| 1254 | //************************************************************************** | |
| 1005 | 1255 | |
| 1006 | /*------------------------------------------------- | |
| 1007 | memory_configure_bank - configure the | |
| 1008 | addresses for a bank | |
| 1009 | -------------------------------------------------*/ | |
| 1256 | //------------------------------------------------- | |
| 1257 | // memory_configure_bank - configure the | |
| 1258 | // addresses for a bank | |
| 1259 | //------------------------------------------------- | |
| 1010 | 1260 | |
| 1011 | 1261 | void memory_configure_bank(running_machine *machine, const char *tag, int startentry, int numentries, void *base, offs_t stride) |
| 1012 | 1262 | { |
| 1013 | memory_private *memdata = machine->memory_data; | |
| 1014 | bank_info *bank = memdata->bankmap.find_hash_only(tag); | |
| 1015 | int entrynum; | |
| 1016 | ||
| 1017 | /* validation checks */ | |
| 1263 | // validation checks | |
| 1264 | memory_bank *bank = machine->memory_data->bankmap.find_hash_only(tag); | |
| 1018 | 1265 | if (bank == NULL) |
| 1019 | 1266 | fatalerror("memory_configure_bank called for unknown bank '%s'", tag); |
| 1020 | if (startentry < 0 || startentry + numentries > MAX_BANK_ENTRIES) | |
| 1021 | fatalerror("memory_configure_bank called with out-of-range entries %d-%d", startentry, startentry + numentries - 1); | |
| 1022 | if (!base) | |
| 1267 | if (base == NULL) | |
| 1023 | 1268 | fatalerror("memory_configure_bank called NULL base"); |
| 1024 | 1269 | |
| 1025 | /* fill in the requested bank entries */ | |
| 1026 | for (entrynum = startentry; entrynum < startentry + numentries; entrynum++) | |
| 1027 | bank->entry[entrynum] = (UINT8 *)base + (entrynum - startentry) * stride; | |
| 1028 | ||
| 1029 | /* if we have no bankptr yet, set it to the first entry */ | |
| 1030 | if (memdata->bank_ptr[bank->index] == NULL) | |
| 1031 | memdata->bank_ptr[bank->index] = (UINT8 *)bank->entry[0]; | |
| 1270 | // fill in the requested bank entries (backwards to improve allocation) | |
| 1271 | for (int entrynum = startentry + numentries - 1; entrynum >= startentry; entrynum--) | |
| 1272 | bank->configure(entrynum, reinterpret_cast<UINT8 *>(base) + (entrynum - startentry) * stride); | |
| 1032 | 1273 | } |
| 1033 | 1274 | |
| 1034 | 1275 | |
| 1035 | /*------------------------------------------------- | |
| 1036 | memory_configure_bank_decrypted - configure | |
| 1037 | the decrypted addresses for a bank | |
| 1038 | -------------------------------------------------*/ | |
| 1276 | //------------------------------------------------- | |
| 1277 | // memory_configure_bank_decrypted - configure | |
| 1278 | // the decrypted addresses for a bank | |
| 1279 | //------------------------------------------------- | |
| 1039 | 1280 | |
| 1040 | 1281 | void memory_configure_bank_decrypted(running_machine *machine, const char *tag, int startentry, int numentries, void *base, offs_t stride) |
| 1041 | 1282 | { |
| 1042 | memory_private *memdata = machine->memory_data; | |
| 1043 | bank_info *bank = memdata->bankmap.find_hash_only(tag); | |
| 1044 | int entrynum; | |
| 1045 | ||
| 1046 | /* validation checks */ | |
| 1283 | // validation checks | |
| 1284 | memory_bank *bank = machine->memory_data->bankmap.find_hash_only(tag); | |
| 1047 | 1285 | if (bank == NULL) |
| 1048 | 1286 | fatalerror("memory_configure_bank_decrypted called for unknown bank '%s'", tag); |
| 1049 | if (startentry < 0 || startentry + numentries > MAX_BANK_ENTRIES) | |
| 1050 | fatalerror("memory_configure_bank_decrypted called with out-of-range entries %d-%d", startentry, startentry + numentries - 1); | |
| 1051 | if (!base) | |
| 1287 | if (base == NULL) | |
| 1052 | 1288 | fatalerror("memory_configure_bank_decrypted called NULL base"); |
| 1053 | 1289 | |
| 1054 | /* fill in the requested bank entries */ | |
| 1055 | for (entrynum = startentry; entrynum < startentry + numentries; entrynum++) | |
| 1056 | bank->entryd[entrynum] = (UINT8 *)base + (entrynum - startentry) * stride; | |
| 1057 | ||
| 1058 | /* if we have no bankptr yet, set it to the first entry */ | |
| 1059 | if (memdata->bankd_ptr[bank->index] == NULL) | |
| 1060 | memdata->bankd_ptr[bank->index] = (UINT8 *)bank->entryd[0]; | |
| 1290 | // fill in the requested bank entries (backwards to improve allocation) | |
| 1291 | for (int entrynum = startentry + numentries - 1; entrynum >= startentry; entrynum--) | |
| 1292 | bank->configure_decrypted(entrynum, reinterpret_cast<UINT8 *>(base) + (entrynum - startentry) * stride); | |
| 1061 | 1293 | } |
| 1062 | 1294 | |
| 1063 | 1295 | |
| 1064 | /*------------------------------------------------- | |
| 1065 | memory_set_bank - select one pre-configured | |
| 1066 | entry to be the new bank base | |
| 1067 | -------------------------------------------------*/ | |
| 1296 | //------------------------------------------------- | |
| 1297 | // memory_set_bank - select one pre-configured | |
| 1298 | // entry to be the new bank base | |
| 1299 | //------------------------------------------------- | |
| 1068 | 1300 | |
| 1069 | 1301 | void memory_set_bank(running_machine *machine, const char *tag, int entrynum) |
| 1070 | 1302 | { |
| 1071 | memory_private *memdata = machine->memory_data; | |
| 1072 | bank_info *bank = memdata->bankmap.find_hash_only(tag); | |
| 1073 | bank_reference *ref; | |
| 1074 | ||
| 1075 | /* validation checks */ | |
| 1303 | // validation checks | |
| 1304 | memory_bank *bank = machine->memory_data->bankmap.find_hash_only(tag); | |
| 1076 | 1305 | if (bank == NULL) |
| 1077 | 1306 | fatalerror("memory_set_bank called for unknown bank '%s'", tag); |
| 1078 | if (entrynum < 0 || entrynum > MAX_BANK_ENTRIES) | |
| 1079 | fatalerror("memory_set_bank called with out-of-range entry %d", entrynum); | |
| 1080 | if (!bank->entry[entrynum]) | |
| 1081 | fatalerror("memory_set_bank called for bank '%s' with invalid bank entry %d", tag, entrynum); | |
| 1082 | 1307 | |
| 1083 | /* set the base */ | |
| 1084 | bank->curentry = entrynum; | |
| 1085 | memdata->bank_ptr[bank->index] = (UINT8 *)bank->entry[entrynum]; | |
| 1086 | memdata->bankd_ptr[bank->index] = (UINT8 *)bank->entryd[entrynum]; | |
| 1087 | ||
| 1088 | /* invalidate all the direct references to any referenced address spaces */ | |
| 1089 | for (ref = bank->reflist; ref != NULL; ref = ref->next) | |
| 1090 | force_opbase_update(ref->space); | |
| 1308 | // set the base | |
| 1309 | bank->set_entry(entrynum); | |
| 1091 | 1310 | } |
| 1092 | 1311 | |
| 1093 | 1312 | |
| 1094 | /*------------------------------------------------- | |
| 1095 | memory_get_bank - return the currently | |
| 1096 | selected bank | |
| 1097 | -------------------------------------------------*/ | |
| 1313 | //------------------------------------------------- | |
| 1314 | // memory_get_bank - return the currently | |
| 1315 | // selected bank | |
| 1316 | //------------------------------------------------- | |
| 1098 | 1317 | |
| 1099 | 1318 | int memory_get_bank(running_machine *machine, const char *tag) |
| 1100 | 1319 | { |
| 1101 | memory_private *memdata = machine->memory_data; | |
| 1102 | bank_info *bank = memdata->bankmap.find_hash_only(tag); | |
| 1103 | ||
| 1104 | /* validation checks */ | |
| 1320 | // validation checks | |
| 1321 | memory_bank *bank = machine->memory_data->bankmap.find_hash_only(tag); | |
| 1105 | 1322 | if (bank == NULL) |
| 1106 | 1323 | fatalerror("memory_get_bank called for unknown bank '%s'", tag); |
| 1107 | return bank->curentry; | |
| 1324 | ||
| 1325 | // return the current entry | |
| 1326 | return bank->entry(); | |
| 1108 | 1327 | } |
| 1109 | 1328 | |
| 1110 | 1329 | |
| 1111 | /*------------------------------------------------- | |
| 1112 | memory_set_bankptr - set the base of a bank | |
| 1113 | -------------------------------------------------*/ | |
| 1330 | //------------------------------------------------- | |
| 1331 | // memory_set_bankptr - set the base of a bank | |
| 1332 | //------------------------------------------------- | |
| 1114 | 1333 | |
| 1115 | 1334 | void memory_set_bankptr(running_machine *machine, const char *tag, void *base) |
| 1116 | 1335 | { |
| 1117 | memory_private *memdata = machine->memory_data; | |
| 1118 | bank_info *bank = memdata->bankmap.find_hash_only(tag); | |
| 1119 | bank_reference *ref; | |
| 1120 | ||
| 1121 | /* validation checks */ | |
| 1336 | // validation checks | |
| 1337 | memory_bank *bank = machine->memory_data->bankmap.find_hash_only(tag); | |
| 1122 | 1338 | if (bank == NULL) |
| 1123 | fatalerror("memory_set_bankptr called for unknown bank '%s'", tag); | |
| 1124 | if (base == NULL) | |
| 1125 | fatalerror("memory_set_bankptr called NULL base"); | |
| 1126 | // if (ALLOW_ONLY_AUTO_MALLOC_BANKS) | |
| 1127 | // validate_auto_malloc_memory(base, bank->byteend - bank->bytestart + 1); | |
| 1339 | throw emu_fatalerror("memory_set_bankptr called for unknown bank '%s'", tag); | |
| 1128 | 1340 | |
| 1129 | /* set the base */ | |
| 1130 | memdata->bank_ptr[bank->index] = (UINT8 *)base; | |
| 1131 | ||
| 1132 | /* invalidate all the direct references to any referenced address spaces */ | |
| 1133 | for (ref = bank->reflist; ref != NULL; ref = ref->next) | |
| 1134 | force_opbase_update(ref->space); | |
| 1341 | // set the base | |
| 1342 | bank->set_base(base); | |
| 1135 | 1343 | } |
| 1136 | 1344 | |
| 1137 | 1345 | |
| 1346 | //------------------------------------------------- | |
| 1347 | // memory_dump - dump the internal memory tables | |
| 1348 | // to the given file | |
| 1349 | //------------------------------------------------- | |
| 1138 | 1350 | |
| 1139 | /*************************************************************************** | |
| 1140 | DYNAMIC ADDRESS SPACE MAPPING | |
| 1141 | ***************************************************************************/ | |
| 1351 | void memory_dump(running_machine *machine, FILE *file) | |
| 1352 | { | |
| 1353 | // skip if we can't open the file | |
| 1354 | if (file == NULL) | |
| 1355 | return; | |
| 1142 | 1356 | |
| 1143 | /*------------------------------------------------- | |
| 1144 | _memory_install_handler - install a new memory | |
| 1145 | handler into the given address space, | |
| 1146 | returning a pointer to the memory backing it, | |
| 1147 | if present | |
| 1148 | -------------------------------------------------*/ | |
| 1357 | // loop over address spaces | |
| 1358 | for (address_space *space = machine->memory_data->spacelist.first(); space != NULL; space = space->next()) | |
| 1359 | { | |
| 1360 | fprintf(file, "\n\n" | |
| 1361 | "====================================================\n" | |
| 1362 | "Device '%s' %s address space read handler dump\n" | |
| 1363 | "====================================================\n", space->device().tag(), space->name()); | |
| 1364 | space->dump_map(file, ROW_READ); | |
| 1149 | 1365 | |
| 1150 | #ifdef UNUSED_CODE | |
| 1151 | void *_memory_install_handler(const address_space *space, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, FPTR rhandler, FPTR whandler) | |
| 1152 | { | |
| 1153 | address_space *spacerw = (address_space *)space; | |
| 1154 | if (rhandler >= STATIC_COUNT) | |
| 1155 | fatalerror("Attempted to install non-static read handler via memory_install_handler() in space %s of device '%s'\n", space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1156 | if (whandler >= STATIC_COUNT) | |
| 1157 | fatalerror("Attempted to install non-static write handler via memory_install_handler() in space %s of device '%s'\n", space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1158 | if (rhandler != 0) | |
| 1159 | space_map_range(spacerw, ROW_READ, spacerw->dbits, 0, addrstart, addrend, addrmask, addrmirror, (genf *)(FPTR)rhandler, spacerw, NULL); | |
| 1160 | if (whandler != 0) | |
| 1161 | space_map_range(spacerw, ROW_WRITE, spacerw->dbits, 0, addrstart, addrend, addrmask, addrmirror, (genf *)(FPTR)whandler, spacerw, NULL); | |
| 1162 | mem_dump(space->machine); | |
| 1163 | return space_find_backing_memory(spacerw, addrstart, addrend); | |
| 1366 | fprintf(file, "\n\n" | |
| 1367 | "====================================================\n" | |
| 1368 | "Device '%s' %s address space write handler dump\n" | |
| 1369 | "====================================================\n", space->device().tag(), space->name()); | |
| 1370 | space->dump_map(file, ROW_WRITE); | |
| 1371 | } | |
| 1164 | 1372 | } |
| 1165 | #endif | |
| 1166 | 1373 | |
| 1167 | 1374 | |
| 1168 | /*------------------------------------------------- | |
| 1169 | _memory_install_handler8 - same as above but | |
| 1170 | explicitly for 8-bit handlers | |
| 1171 | -------------------------------------------------*/ | |
| 1375 | //------------------------------------------------- | |
| 1376 | // generate_memdump - internal memory dump | |
| 1377 | //------------------------------------------------- | |
| 1172 | 1378 | |
| 1173 | ||
| 1379 | ||
| 1174 | 1380 | { |
| 1175 | address_space *spacerw = (address_space *)space; | |
| 1176 | if (rhandler != NULL && (FPTR)rhandler < STATIC_COUNT) | |
| 1177 | fatalerror("Attempted to install invalid read handler in space %s of device '%s'\n", space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1178 | if (whandler != NULL && (FPTR)whandler < STATIC_COUNT) | |
| 1179 | fatalerror("Attempted to install invalid write handler in space %s of device '%s'\n", space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1180 | if (rhandler != NULL) | |
| 1181 | space_map_range(spacerw, ROW_READ, 8, handlerunitmask, addrstart, addrend, addrmask, addrmirror, (genf *)rhandler, spacerw, rhandler_name); | |
| 1182 | if (whandler != NULL) | |
| 1183 | space_map_range(spacerw, ROW_WRITE, 8, handlerunitmask, addrstart, addrend, addrmask, addrmirror, (genf *)whandler, spacerw, whandler_name); | |
| 1184 | mem_dump(space->machine); | |
| 1185 | return (UINT8 *)space_find_backing_memory(spacerw, addrstart, addrend); | |
| 1381 | if (MEM_DUMP) | |
| 1382 | { | |
| 1383 | FILE *file = fopen("memdump.log", "w"); | |
| 1384 | if (file) | |
| 1385 | { | |
| 1386 | memory_dump(machine, file); | |
| 1387 | fclose(file); | |
| 1388 | } | |
| 1389 | } | |
| 1186 | 1390 | } |
| 1187 | 1391 | |
| 1188 | 1392 | |
| 1189 | /*------------------------------------------------- | |
| 1190 | _memory_install_handler16 - same as above but | |
| 1191 | explicitly for 16-bit handlers | |
| 1192 | -------------------------------------------------*/ | |
| 1393 | //------------------------------------------------- | |
| 1394 | // bank_reattach - reconnect banks after a load | |
| 1395 | //------------------------------------------------- | |
| 1193 | 1396 | |
| 1194 | ||
| 1397 | ||
| 1195 | 1398 | { |
| 1196 | address_space *spacerw = (address_space *)space; | |
| 1197 | if (rhandler != NULL && (FPTR)rhandler < STATIC_COUNT) | |
| 1198 | fatalerror("Attempted to install invalid read handler in space %s of device '%s'\n", space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1199 | if (whandler != NULL && (FPTR)whandler < STATIC_COUNT) | |
| 1200 | fatalerror("Attempted to install invalid write handler in space %s of device '%s'\n", space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1201 | if (rhandler != NULL) | |
| 1202 | space_map_range(spacerw, ROW_READ, 16, handlerunitmask, addrstart, addrend, addrmask, addrmirror, (genf *)rhandler, spacerw, rhandler_name); | |
| 1203 | if (whandler != NULL) | |
| 1204 | space_map_range(spacerw, ROW_WRITE, 16, handlerunitmask, addrstart, addrend, addrmask, addrmirror, (genf *)whandler, spacerw, whandler_name); | |
| 1205 | mem_dump(space->machine); | |
| 1206 | return (UINT16 *)space_find_backing_memory(spacerw, addrstart, addrend); | |
| 1399 | // for each non-anonymous bank, explicitly reset its entry | |
| 1400 | for (memory_bank *bank = machine->memory_data->banklist.first(); bank != NULL; bank = bank->next()) | |
| 1401 | if (!bank->anonymous() && bank->entry() != BANK_ENTRY_UNSPECIFIED) | |
| 1402 | bank->set_entry(bank->entry()); | |
| 1207 | 1403 | } |
| 1208 | 1404 | |
| 1209 | 1405 | |
| 1210 | /*------------------------------------------------- | |
| 1211 | _memory_install_handler32 - same as above but | |
| 1212 | explicitly for 32-bit handlers | |
| 1213 | -------------------------------------------------*/ | |
| 1214 | 1406 | |
| 1215 | UINT32 *_memory_install_handler32(const address_space *space, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_space_func rhandler, const char *rhandler_name, write32_space_func whandler, const char *whandler_name, int handlerunitmask) | |
| 1216 | { | |
| 1217 | address_space *spacerw = (address_space *)space; | |
| 1218 | if (rhandler != NULL && (FPTR)rhandler < STATIC_COUNT) | |
| 1219 | fatalerror("Attempted to install invalid read handler in space %s of device '%s'\n", space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1220 | if (whandler != NULL && (FPTR)whandler < STATIC_COUNT) | |
| 1221 | fatalerror("Attempted to install invalid write handler in space %s of device '%s'\n", space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1222 | if (rhandler != NULL) | |
| 1223 | space_map_range(spacerw, ROW_READ, 32, handlerunitmask, addrstart, addrend, addrmask, addrmirror, (genf *)rhandler, spacerw, rhandler_name); | |
| 1224 | if (whandler != NULL) | |
| 1225 | space_map_range(spacerw, ROW_WRITE, 32, handlerunitmask, addrstart, addrend, addrmask, addrmirror, (genf *)whandler, spacerw, whandler_name); | |
| 1226 | mem_dump(space->machine); | |
| 1227 | return (UINT32 *)space_find_backing_memory(spacerw, addrstart, addrend); | |
| 1228 | } | |
| 1407 | //************************************************************************** | |
| 1408 | // ADDRESS SPACE | |
| 1409 | //************************************************************************** | |
| 1229 | 1410 | |
| 1411 | //------------------------------------------------- | |
| 1412 | // address_space - constructor | |
| 1413 | //------------------------------------------------- | |
| 1230 | 1414 | |
| 1231 | /*------------------------------------------------- | |
| 1232 | _memory_install_handler64 - same as above but | |
| 1233 | explicitly for 64-bit handlers | |
| 1234 | -------------------------------------------------*/ | |
| 1235 | ||
| 1236 | UINT64 *_memory_install_handler64(const address_space *space, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_space_func rhandler, const char *rhandler_name, write64_space_func whandler, const char *whandler_name, int handlerunitmask) | |
| 1415 | address_space::address_space(device_memory_interface &memory, int spacenum, bool large) | |
| 1416 | : machine(memory.device().machine), | |
| 1417 | cpu(&memory.device()), | |
| 1418 | m_machine(*memory.device().machine), | |
| 1419 | m_next(NULL), | |
| 1420 | m_config(*memory.space_config(spacenum)), | |
| 1421 | m_device(memory.device()), | |
| 1422 | m_map(NULL), | |
| 1423 | m_addrmask(0xffffffffUL >> (32 - m_config.m_addrbus_width)), | |
| 1424 | m_bytemask(address_to_byte_end(m_addrmask)), | |
| 1425 | m_logaddrmask(0xffffffffUL >> (32 - m_config.m_logaddr_width)), | |
| 1426 | m_logbytemask(address_to_byte_end(m_logaddrmask)), | |
| 1427 | m_unmap(0), | |
| 1428 | m_spacenum(spacenum), | |
| 1429 | m_debugger_access(false), | |
| 1430 | m_log_unmap(true), | |
| 1431 | m_direct(*auto_alloc(memory.device().machine, direct_read_data(*this))), | |
| 1432 | m_name(memory.space_config(spacenum)->name()), | |
| 1433 | m_addrchars((m_config.m_databus_width + 3) / 4), | |
| 1434 | m_logaddrchars((m_config.m_logaddr_width + 3) / 4) | |
| 1237 | 1435 | { |
| 1238 | address_space *spacerw = (address_space *)space; | |
| 1239 | if (rhandler != NULL && (FPTR)rhandler < STATIC_COUNT) | |
| 1240 | fatalerror("Attempted to install invalid read handler in space %s of device '%s'\n", space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1241 | if (whandler != NULL && (FPTR)whandler < STATIC_COUNT) | |
| 1242 | fatalerror("Attempted to install invalid write handler in space %s of device '%s'\n", space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1243 | if (rhandler != NULL) | |
| 1244 | space_map_range(spacerw, ROW_READ, 64, handlerunitmask, addrstart, addrend, addrmask, addrmirror, (genf *)rhandler, spacerw, rhandler_name); | |
| 1245 | if (whandler != NULL) | |
| 1246 | space_map_range(spacerw, ROW_WRITE, 64, handlerunitmask, addrstart, addrend, addrmask, addrmirror, (genf *)whandler, spacerw, whandler_name); | |
| 1247 | mem_dump(space->machine); | |
| 1248 | return (UINT64 *)space_find_backing_memory(spacerw, addrstart, addrend); | |
| 1436 | // notify the device | |
| 1437 | memory.set_address_space(spacenum, *this); | |
| 1249 | 1438 | } |
| 1250 | 1439 | |
| 1251 | 1440 | |
| 1252 | /*------------------------------------------------- | |
| 1253 | _memory_install_device_handler8 - same as above | |
| 1254 | but explicitly for 8-bit handlers | |
| 1255 | -------------------------------------------------*/ | |
| 1441 | //------------------------------------------------- | |
| 1442 | // ~address_space - destructor | |
| 1443 | //------------------------------------------------- | |
| 1256 | 1444 | |
| 1257 | ||
| 1445 | ||
| 1258 | 1446 | { |
| 1259 | address_space *spacerw = (address_space *)space; | |
| 1260 | if (rhandler != NULL && (FPTR)rhandler < STATIC_COUNT) | |
| 1261 | fatalerror("Attempted to install invalid read handler for device '%s' in space %s of device '%s'\n", device->tag(), space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1262 | if (whandler != NULL && (FPTR)whandler < STATIC_COUNT) | |
| 1263 | fatalerror("Attempted to install invalid write handler for device '%s' in space %s of device '%s'\n", device->tag(), space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1264 | if (rhandler != NULL) | |
| 1265 | space_map_range(spacerw, ROW_READ, 8, handlerunitmask, addrstart, addrend, addrmask, addrmirror, (genf *)rhandler, (void *)device, rhandler_name); | |
| 1266 | if (whandler != NULL) | |
| 1267 | space_map_range(spacerw, ROW_WRITE, 8, handlerunitmask, addrstart, addrend, addrmask, addrmirror, (genf *)whandler, (void *)device, whandler_name); | |
| 1268 | mem_dump(space->machine); | |
| 1269 | return (UINT8 *)space_find_backing_memory(spacerw, addrstart, addrend); | |
| 1447 | global_free(&m_direct); | |
| 1448 | global_free(m_map); | |
| 1270 | 1449 | } |
| 1271 | 1450 | |
| 1272 | 1451 | |
| 1273 | /*------------------------------------------------- | |
| 1274 | _memory_install_device_handler16 - same as | |
| 1275 | above but explicitly for 16-bit handlers | |
| 1276 | -------------------------------------------------*/ | |
| 1452 | //------------------------------------------------- | |
| 1453 | // allocate - static smart allocator of subtypes | |
| 1454 | //------------------------------------------------- | |
| 1277 | 1455 | |
| 1278 | UINT16 *_memory_install_device_handler16(const address_space *space, device_t *device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_device_func rhandler, const char *rhandler_name, write16_device_func whandler, const char *whandler_name, int handlerunitmask) | |
| 1279 | { | |
| 1280 | address_space *spacerw = (address_space *)space; | |
| 1281 | if (rhandler != NULL && (FPTR)rhandler < STATIC_COUNT) | |
| 1282 | fatalerror("Attempted to install invalid read handler for device '%s' in space %s of device '%s'\n", device->tag(), space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1283 | if (whandler != NULL && (FPTR)whandler < STATIC_COUNT) | |
| 1284 | fatalerror("Attempted to install invalid write handler for device '%s' in space %s of device '%s'\n", device->tag(), space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1285 | if (rhandler != NULL) | |
| 1286 | space_map_range(spacerw, ROW_READ, 16, handlerunitmask, addrstart, addrend, addrmask, addrmirror, (genf *)rhandler, (void *)device, rhandler_name); | |
| 1287 | if (whandler != NULL) | |
| 1288 | space_map_range(spacerw, ROW_WRITE, 16, handlerunitmask, addrstart, addrend, addrmask, addrmirror, (genf *)whandler, (void *)device, whandler_name); | |
| 1289 | mem_dump(space->machine); | |
| 1290 | return (UINT16 *)space_find_backing_memory(spacerw, addrstart, addrend); | |
| 1291 | } | |
| 1456 | address_space &address_space::allocate(running_machine &machine, const address_space_config &config, device_memory_interface &memory, int spacenum) | |
| 1457 | { | |
| 1458 | // allocate one of the appropriate type | |
| 1459 | bool large = (config.addr2byte_end(0xffffffffUL >> (32 - config.m_addrbus_width)) >= (1 << 18)); | |
| 1292 | 1460 | |
| 1461 | switch (config.data_width()) | |
| 1462 | { | |
| 1463 | case 8: | |
| 1464 | if (config.endianness() == ENDIANNESS_LITTLE) | |
| 1465 | { | |
| 1466 | if (large) | |
| 1467 | return *auto_alloc(&machine, address_space_8le_large(memory, spacenum)); | |
| 1468 | else | |
| 1469 | return *auto_alloc(&machine, address_space_8le_small(memory, spacenum)); | |
| 1470 | } | |
| 1471 | else | |
| 1472 | { | |
| 1473 | if (large) | |
| 1474 | return *auto_alloc(&machine, address_space_8be_large(memory, spacenum)); | |
| 1475 | else | |
| 1476 | return *auto_alloc(&machine, address_space_8be_small(memory, spacenum)); | |
| 1477 | } | |
| 1293 | 1478 | |
| 1294 | /*------------------------------------------------- | |
| 1295 | _memory_install_device_handler32 - same as | |
| 1296 | above but explicitly for 32-bit handlers | |
| 1297 | -------------------------------------------------*/ | |
| 1479 | case 16: | |
| 1480 | if (config.endianness() == ENDIANNESS_LITTLE) | |
| 1481 | { | |
| 1482 | if (large) | |
| 1483 | return *auto_alloc(&machine, address_space_16le_large(memory, spacenum)); | |
| 1484 | else | |
| 1485 | return *auto_alloc(&machine, address_space_16le_small(memory, spacenum)); | |
| 1486 | } | |
| 1487 | else | |
| 1488 | { | |
| 1489 | if (large) | |
| 1490 | return *auto_alloc(&machine, address_space_16be_large(memory, spacenum)); | |
| 1491 | else | |
| 1492 | return *auto_alloc(&machine, address_space_16be_small(memory, spacenum)); | |
| 1493 | } | |
| 1298 | 1494 | |
| 1299 | UINT32 *_memory_install_device_handler32(const address_space *space, device_t *device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_device_func rhandler, const char *rhandler_name, write32_device_func whandler, const char *whandler_name, int handlerunitmask) | |
| 1300 | { | |
| 1301 | address_space *spacerw = (address_space *)space; | |
| 1302 | if (rhandler != NULL && (FPTR)rhandler < STATIC_COUNT) | |
| 1303 | fatalerror("Attempted to install invalid read handler for device '%s' in space %s of device '%s'\n", device->tag(), space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1304 | if (whandler != NULL && (FPTR)whandler < STATIC_COUNT) | |
| 1305 | fatalerror("Attempted to install invalid write handler for device '%s' in space %s of device '%s'\n", device->tag(), space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1306 | if (rhandler != NULL) | |
| 1307 | space_map_range(spacerw, ROW_READ, 32, handlerunitmask, addrstart, addrend, addrmask, addrmirror, (genf *)rhandler, (void *)device, rhandler_name); | |
| 1308 | if (whandler != NULL) | |
| 1309 | space_map_range(spacerw, ROW_WRITE, 32, handlerunitmask, addrstart, addrend, addrmask, addrmirror, (genf *)whandler, (void *)device, whandler_name); | |
| 1310 | mem_dump(space->machine); | |
| 1311 | return (UINT32 *)space_find_backing_memory(spacerw, addrstart, addrend); | |
| 1495 | case 32: | |
| 1496 | if (config.endianness() == ENDIANNESS_LITTLE) | |
| 1497 | { | |
| 1498 | if (large) | |
| 1499 | return *auto_alloc(&machine, address_space_32le_large(memory, spacenum)); | |
| 1500 | else | |
| 1501 | return *auto_alloc(&machine, address_space_32le_small(memory, spacenum)); | |
| 1502 | } | |
| 1503 | else | |
| 1504 | { | |
| 1505 | if (large) | |
| 1506 | return *auto_alloc(&machine, address_space_32be_large(memory, spacenum)); | |
| 1507 | else | |
| 1508 | return *auto_alloc(&machine, address_space_32be_small(memory, spacenum)); | |
| 1509 | } | |
| 1510 | ||
| 1511 | case 64: | |
| 1512 | if (config.endianness() == ENDIANNESS_LITTLE) | |
| 1513 | { | |
| 1514 | if (large) | |
| 1515 | return *auto_alloc(&machine, address_space_64le_large(memory, spacenum)); | |
| 1516 | else | |
| 1517 | return *auto_alloc(&machine, address_space_64le_small(memory, spacenum)); | |
| 1518 | } | |
| 1519 | else | |
| 1520 | { | |
| 1521 | if (large) | |
| 1522 | return *auto_alloc(&machine, address_space_64be_large(memory, spacenum)); | |
| 1523 | else | |
| 1524 | return *auto_alloc(&machine, address_space_64be_small(memory, spacenum)); | |
| 1525 | } | |
| 1526 | } | |
| 1527 | throw emu_fatalerror("Invalid width %d specified for address_space::allocate", config.data_width()); | |
| 1312 | 1528 | } |
| 1313 | 1529 | |
| 1314 | 1530 | |
| 1315 | /*------------------------------------------------- | |
| 1316 | _memory_install_device_handler64 - same as | |
| 1317 | above but explicitly for 64-bit handlers | |
| 1318 | -------------------------------------------------*/ | |
| 1531 | //------------------------------------------------- | |
| 1532 | // adjust_addresses - adjust addresses for a | |
| 1533 | // given address space in a standard fashion | |
| 1534 | //------------------------------------------------- | |
| 1319 | 1535 | |
| 1320 | ||
| 1536 | ||
| 1321 | 1537 | { |
| 1322 | address_space *spacerw = (address_space *)space; | |
| 1323 | if (rhandler != NULL && (FPTR)rhandler < STATIC_COUNT) | |
| 1324 | fatalerror("Attempted to install invalid read handler for device '%s' in space %s of device '%s'\n", device->tag(), space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1325 | if (whandler != NULL && (FPTR)whandler < STATIC_COUNT) | |
| 1326 | fatalerror("Attempted to install invalid write handler for device '%s' in space %s of device '%s'\n", device->tag(), space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1327 | if (rhandler != NULL) | |
| 1328 | space_map_range(spacerw, ROW_READ, 64, handlerunitmask, addrstart, addrend, addrmask, addrmirror, (genf *)rhandler, (void *)device, rhandler_name); | |
| 1329 | if (whandler != NULL) | |
| 1330 | space_map_range(spacerw, ROW_WRITE, 64, handlerunitmask, addrstart, addrend, addrmask, addrmirror, (genf *)whandler, (void *)device, whandler_name); | |
| 1331 | mem_dump(space->machine); | |
| 1332 | return (UINT64 *)space_find_backing_memory(spacerw, addrstart, addrend); | |
| 1538 | // adjust start/end/mask values | |
| 1539 | if (mask == 0) | |
| 1540 | mask = m_addrmask & ~mirror; | |
| 1541 | else | |
| 1542 | mask &= m_addrmask; | |
| 1543 | start &= ~mirror & m_addrmask; | |
| 1544 | end &= ~mirror & m_addrmask; | |
| 1545 | ||
| 1546 | // adjust to byte values | |
| 1547 | start = address_to_byte(start); | |
| 1548 | end = address_to_byte_end(end); | |
| 1549 | mask = address_to_byte_end(mask); | |
| 1550 | mirror = address_to_byte(mirror); | |
| 1333 | 1551 | } |
| 1334 | 1552 | |
| 1335 | 1553 | |
| 1336 | /*------------------------------------------------- | |
| 1337 | _memory_install_port - install a | |
| 1338 | new port handler into the given address space | |
| 1339 | -------------------------------------------------*/ | |
| 1554 | //------------------------------------------------- | |
| 1555 | // prepare_map - allocate the address map and | |
| 1556 | // walk through it to find implcit memory regions | |
| 1557 | // and identify shared regions | |
| 1558 | //------------------------------------------------- | |
| 1340 | 1559 | |
| 1341 | void | |
| 1560 | void | |
| 1342 | 1561 | { |
| 1343 | address_space *spacerw = (address_space *)space; | |
| 1344 | genf *rhandler = NULL; | |
| 1345 | genf *whandler = NULL; | |
| 1562 | const region_info *devregion = (m_spacenum == ADDRESS_SPACE_0) ? m_machine.region(m_device.tag()) : NULL; | |
| 1563 | UINT32 devregionsize = (devregion != NULL) ? devregion->bytes() : 0; | |
| 1346 | 1564 | |
| 1347 | /* pick the appropriate read/write handlers */ | |
| 1348 | switch (space->dbits) | |
| 1565 | // allocate the address map | |
| 1566 | m_map = global_alloc(address_map(m_device.baseconfig(), m_spacenum)); | |
| 1567 | ||
| 1568 | // extract global parameters specified by the map | |
| 1569 | m_unmap = (m_map->m_unmapval == 0) ? 0 : ~0; | |
| 1570 | if (m_map->m_globalmask != 0) | |
| 1349 | 1571 | { |
| 1350 | case 8: rhandler = (genf *)input_port_read8; whandler = (genf *)input_port_write8; break; | |
| 1351 | case 16: rhandler = (genf *)input_port_read16; whandler = (genf *)input_port_write16; break; | |
| 1352 | case 32: rhandler = (genf *)input_port_read32; whandler = (genf *)input_port_write32; break; | |
| 1353 | case 64: rhandler = (genf *)input_port_read64; whandler = (genf *)input_port_write64; break; | |
| 1572 | m_addrmask = m_map->m_globalmask; | |
| 1573 | m_bytemask = address_to_byte_end(m_addrmask); | |
| 1354 | 1574 | } |
| 1355 | 1575 | |
| 1356 | /* assign the read handler */ | |
| 1357 | if (rtag != NULL) | |
| 1576 | // make a pass over the address map, adjusting for the device and getting memory pointers | |
| 1577 | for (address_map_entry *entry = m_map->m_entrylist.first(); entry != NULL; entry = entry->next()) | |
| 1358 | 1578 | { |
| 1359 | const input_port_config *port = space->machine->port(rtag); | |
| 1360 | if (port == NULL) | |
| 1361 | fatalerror("Attempted to map non-existent port '%s' for read in space %s of device '%s'\n", rtag, space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1362 | space_map_range(spacerw, ROW_READ, space->dbits, 0, addrstart, addrend, addrmask, addrmirror, rhandler, (void *)port, rtag); | |
| 1363 | } | |
| 1579 | // if we have a share entry, add it to our map | |
| 1580 | if (entry->m_share != NULL) | |
| 1581 | m_machine.memory_data->sharemap.add(entry->m_share, UNMAPPED_SHARE_PTR, false); | |
| 1582 | ||
| 1583 | // computed adjusted addresses first | |
| 1584 | entry->m_bytestart = entry->m_addrstart; | |
| 1585 | entry->m_byteend = entry->m_addrend; | |
| 1586 | entry->m_bytemirror = entry->m_addrmirror; | |
| 1587 | entry->m_bytemask = entry->m_addrmask; | |
| 1588 | adjust_addresses(entry->m_bytestart, entry->m_byteend, entry->m_bytemask, entry->m_bytemirror); | |
| 1364 | 1589 | |
| 1365 | /* assign the write handler */ | |
| 1366 | if (wtag != NULL) | |
| 1367 | { | |
| 1368 | const input_port_config *port = space->machine->port(wtag); | |
| 1369 | if (port == NULL) | |
| 1370 | fatalerror("Attempted to map non-existent port '%s' for write in space %s of device '%s'\n", wtag, space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1371 | space_map_range(spacerw, ROW_WRITE, space->dbits, 0, addrstart, addrend, addrmask, addrmirror, whandler, (void *)port, wtag); | |
| 1590 | // if this is a ROM handler without a specified region, attach it to the implicit region | |
| 1591 | if (m_spacenum == ADDRESS_SPACE_0 && entry->m_read.m_type == AMH_ROM && entry->m_region == NULL) | |
| 1592 | { | |
| 1593 | // make sure it fits within the memory region before doing so, however | |
| 1594 | if (entry->m_byteend < devregionsize) | |
| 1595 | { | |
| 1596 | entry->m_region = m_device.tag(); | |
| 1597 | entry->m_rgnoffs = entry->m_bytestart; | |
| 1598 | } | |
| 1599 | } | |
| 1600 | ||
| 1601 | // validate adjusted addresses against implicit regions | |
| 1602 | if (entry->m_region != NULL && entry->m_share == NULL && entry->m_baseptr == NULL) | |
| 1603 | { | |
| 1604 | const region_info *region = m_machine.region(entry->m_region); | |
| 1605 | if (region == NULL) | |
| 1606 | fatalerror("Error: device '%s' %s space memory map entry %X-%X references non-existant region \"%s\"", m_device.tag(), m_name, entry->m_addrstart, entry->m_addrend, entry->m_region); | |
| 1607 | ||
| 1608 | // validate the region | |
| 1609 | if (entry->m_rgnoffs + (entry->m_byteend - entry->m_bytestart + 1) > region->bytes()) | |
| 1610 | fatalerror("Error: device '%s' %s space memory map entry %X-%X extends beyond region \"%s\" size (%X)", m_device.tag(), m_name, entry->m_addrstart, entry->m_addrend, entry->m_region, region->bytes()); | |
| 1611 | } | |
| 1612 | ||
| 1613 | // convert any region-relative entries to their memory pointers | |
| 1614 | if (entry->m_region != NULL) | |
| 1615 | entry->m_memory = m_machine.region(entry->m_region)->base() + entry->m_rgnoffs; | |
| 1372 | 1616 | } |
| 1373 | 1617 | |
| 1374 | /* update the memory dump */ | |
| 1375 | mem_dump(space->machine); | |
| 1618 | // now loop over all the handlers and enforce the address mask | |
| 1619 | read().mask_all_handlers(m_bytemask); | |
| 1620 | write().mask_all_handlers(m_bytemask); | |
| 1376 | 1621 | } |
| 1377 | 1622 | |
| 1378 | 1623 | |
| 1379 | /*------------------------------------------------- | |
| 1380 | _memory_install_bank - install a | |
| 1381 | new port handler into the given address space | |
| 1382 | -------------------------------------------------*/ | |
| 1624 | //------------------------------------------------- | |
| 1625 | // populate_from_map - walk the map in reverse | |
| 1626 | // order and install the appropriate handler for | |
| 1627 | // each case | |
| 1628 | //------------------------------------------------- | |
| 1383 | 1629 | |
| 1384 | void | |
| 1630 | void | |
| 1385 | 1631 | { |
| 1386 | address_space *spacerw = (address_space *)space; | |
| 1632 | // no map, nothing to do | |
| 1633 | if (m_map == NULL) | |
| 1634 | return; | |
| 1387 | 1635 | |
| 1388 | /* map the read bank */ | |
| 1389 | if (rtag != NULL) | |
| 1636 | // install the handlers, using the original, unadjusted memory map | |
| 1637 | const address_map_entry *last_entry = NULL; | |
| 1638 | while (last_entry != m_map->m_entrylist.first()) | |
| 1390 | 1639 | { |
| 1391 | genf *handler = bank_find_or_allocate(space, rtag, addrstart, addrend, addrmask, addrmirror, ROW_READ); | |
| 1392 | space_map_range(spacerw, ROW_READ, space->dbits, 0, addrstart, addrend, addrmask, addrmirror, handler, spacerw, rtag); | |
| 1393 | } | |
| 1640 | // find the entry before the last one we processed | |
| 1641 | const address_map_entry *entry; | |
| 1642 | for (entry = m_map->m_entrylist.first(); entry->next() != last_entry; entry = entry->next()) ; | |
| 1643 | last_entry = entry; | |
| 1394 | 1644 | |
| 1395 | /* map the write bank */ | |
| 1396 | if (wtag != NULL) | |
| 1397 | { | |
| 1398 | genf *handler = bank_find_or_allocate(space, wtag, addrstart, addrend, addrmask, addrmirror, ROW_WRITE); | |
| 1399 | space_map_range(spacerw, ROW_WRITE, space->dbits, 0, addrstart, addrend, addrmask, addrmirror, handler, spacerw, wtag); | |
| 1645 | // map both read and write halves | |
| 1646 | populate_map_entry(*entry, ROW_READ); | |
| 1647 | populate_map_entry(*entry, ROW_WRITE); | |
| 1400 | 1648 | } |
| 1401 | ||
| 1402 | /* update the memory dump */ | |
| 1403 | mem_dump(space->machine); | |
| 1404 | 1649 | } |
| 1405 | 1650 | |
| 1406 | 1651 | |
| 1407 | /*------------------------------------------------- | |
| 1408 | _memory_install_ram - install a simple fixed | |
| 1409 | RAM region into the given address space | |
| 1410 | -------------------------------------------------*/ | |
| 1652 | //------------------------------------------------- | |
| 1653 | // populate_map_entry - map a single read or | |
| 1654 | // write entry based on information from an | |
| 1655 | // address map entry | |
| 1656 | //------------------------------------------------- | |
| 1411 | 1657 | |
| 1412 | void | |
| 1658 | void | |
| 1413 | 1659 | { |
| 1414 | memory_private *memdata = space->machine->memory_data; | |
| 1415 | address_space *spacerw = (address_space *)space; | |
| 1416 | FPTR bankindex; | |
| 1417 | genf *handler; | |
| 1660 | const map_handler_data &data = (readorwrite == ROW_READ) ? entry.m_read : entry.m_write; | |
| 1661 | bindable_object *object; | |
| 1662 | device_t *device; | |
| 1418 | 1663 | |
| 1419 | /* map for read */ | |
| 1420 | if (install_read) | |
| 1664 | // based on the handler type, alter the bits, name, funcptr, and object | |
| 1665 | switch (data.m_type) | |
| 1421 | 1666 | { |
| 1422 | handler = bank_find_or_allocate(space, NULL, addrstart, addrend, addrmask, addrmirror, ROW_READ); | |
| 1423 | space_map_range(spacerw, ROW_READ, space->dbits, 0, addrstart, addrend, addrmask, addrmirror, handler, spacerw, "ram"); | |
| 1667 | case AMH_NONE: | |
| 1668 | return; | |
| 1424 | 1669 | |
| 1425 | /* if we are provided a pointer, set it */ | |
| 1426 | bankindex = (FPTR)handler; | |
| 1427 | if (baseptr != NULL) | |
| 1428 | memdata->bank_ptr[bankindex] = (UINT8 *)baseptr; | |
| 1670 | case AMH_ROM: | |
| 1671 | // writes to ROM are no-ops | |
| 1672 | if (readorwrite == ROW_WRITE) | |
| 1673 | return; | |
| 1674 | // fall through to the RAM case otherwise | |
| 1429 | 1675 | |
| 1430 | /* if we don't have a bank pointer yet, try to find one */ | |
| 1431 | if (memdata->bank_ptr[bankindex] == NULL) | |
| 1432 | memdata->bank_ptr[bankindex] = (UINT8 *)space_find_backing_memory(space, addrstart, addrend); | |
| 1676 | case AMH_RAM: | |
| 1677 | install_ram(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, readorwrite); | |
| 1678 | break; | |
| 1433 | 1679 | |
| 1434 | /* if we still don't have a pointer, and we're past the initialization phase, allocate a new block */ | |
| 1435 | if (memdata->bank_ptr[bankindex] == NULL && memdata->initialized) | |
| 1436 | { | |
| 1437 | if (space->machine->phase() >= MACHINE_PHASE_RESET) | |
| 1438 | fatalerror("Attempted to call memory_install_ram() after initialization time without a baseptr!"); | |
| 1439 | memdata->bank_ptr[bankindex] = (UINT8 *)block_allocate(space, memory_address_to_byte(space, addrstart), memory_address_to_byte_end(space, addrend), NULL); | |
| 1440 | } | |
| 1441 | } | |
| 1680 | case AMH_NOP: | |
| 1681 | unmap(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, readorwrite, true); | |
| 1682 | break; | |
| 1442 | 1683 | |
| 1443 | /* map for write */ | |
| 1444 | if (install_write) | |
| 1445 | { | |
| 1446 | handler = bank_find_or_allocate(space, NULL, addrstart, addrend, addrmask, addrmirror, ROW_WRITE); | |
| 1447 | space_map_range(spacerw, ROW_WRITE, space->dbits, 0, addrstart, addrend, addrmask, addrmirror, handler, spacerw, "ram"); | |
| 1684 | case AMH_UNMAP: | |
| 1685 | unmap(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, readorwrite, false); | |
| 1686 | break; | |
| 1448 | 1687 | |
| 1449 | /* if we are provided a pointer, set it */ | |
| 1450 | bankindex = (FPTR)handler; | |
| 1451 | if (baseptr != NULL) | |
| 1452 | memdata->bank_ptr[bankindex] = (UINT8 *)baseptr; | |
| 1688 | case AMH_DRIVER_DELEGATE: | |
| 1689 | case AMH_DEVICE_DELEGATE: | |
| 1690 | if (data.m_type == AMH_DRIVER_DELEGATE) | |
| 1691 | { | |
| 1692 | object = m_machine.driver_data<driver_data_t>(); | |
| 1693 | if (object == NULL) | |
| 1694 | throw emu_fatalerror("Attempted to map a driver delegate in space %s of device '%s' when there is no driver data\n", m_name, m_device.tag()); | |
| 1695 | } | |
| 1696 | else | |
| 1697 | { | |
| 1698 | object = m_machine.device(data.m_tag); | |
| 1699 | if (object == NULL) | |
| 1700 | throw emu_fatalerror("Attempted to map a non-existent device '%s' in space %s of device '%s'\n", data.m_tag, m_name, m_device.tag()); | |
| 1701 | } | |
| 1453 | 1702 | |
| 1454 | /* if we don't have a bank pointer yet, try to find one */ | |
| 1455 | if (memdata->bank_ptr[bankindex] == NULL) | |
| 1456 | memdata->bank_ptr[bankindex] = (UINT8 *)space_find_backing_memory(space, addrstart, addrend); | |
| 1703 | if (readorwrite == ROW_READ) | |
| 1704 | switch (data.m_bits) | |
| 1705 | { | |
| 1706 | case 8: install_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, read8_delegate(entry.m_rproto8, *object), data.m_mask); break; | |
| 1707 | case 16: install_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, read16_delegate(entry.m_rproto16, *object), data.m_mask); break; | |
| 1708 | case 32: install_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, read32_delegate(entry.m_rproto32, *object), data.m_mask); break; | |
| 1709 | case 64: install_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, read64_delegate(entry.m_rproto64, *object), data.m_mask); break; | |
| 1710 | } | |
| 1711 | else | |
| 1712 | switch (data.m_bits) | |
| 1713 | { | |
| 1714 | case 8: install_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, write8_delegate(entry.m_wproto8, *object), data.m_mask); break; | |
| 1715 | case 16: install_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, write16_delegate(entry.m_wproto16, *object), data.m_mask); break; | |
| 1716 | case 32: install_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, write32_delegate(entry.m_wproto32, *object), data.m_mask); break; | |
| 1717 | case 64: install_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, write64_delegate(entry.m_wproto64, *object), data.m_mask); break; | |
| 1718 | } | |
| 1719 | break; | |
| 1457 | 1720 | |
| 1458 | /* if we still don't have a pointer, and we're past the initialization phase, allocate a new block */ | |
| 1459 | if (memdata->bank_ptr[bankindex] == NULL && memdata->initialized) | |
| 1460 | { | |
| 1461 | if (space->machine->phase() >= MACHINE_PHASE_RESET) | |
| 1462 | fatalerror("Attempted to call memory_install_ram() after initialization time without a baseptr!"); | |
| 1463 | memdata->bank_ptr[bankindex] = (UINT8 *)block_allocate(space, memory_address_to_byte(space, addrstart), memory_address_to_byte_end(space, addrend), NULL); | |
| 1464 | } | |
| 1721 | case AMH_LEGACY_SPACE_HANDLER: | |
| 1722 | if (readorwrite == ROW_READ) | |
| 1723 | switch (data.m_bits) | |
| 1724 | { | |
| 1725 | case 8: install_legacy_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rspace8, data.m_name, data.m_mask); break; | |
| 1726 | case 16: install_legacy_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rspace16, data.m_name, data.m_mask); break; | |
| 1727 | case 32: install_legacy_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rspace32, data.m_name, data.m_mask); break; | |
| 1728 | case 64: install_legacy_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rspace64, data.m_name, data.m_mask); break; | |
| 1729 | } | |
| 1730 | else | |
| 1731 | switch (data.m_bits) | |
| 1732 | { | |
| 1733 | case 8: install_legacy_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wspace8, data.m_name, data.m_mask); break; | |
| 1734 | case 16: install_legacy_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wspace16, data.m_name, data.m_mask); break; | |
| 1735 | case 32: install_legacy_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wspace32, data.m_name, data.m_mask); break; | |
| 1736 | case 64: install_legacy_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wspace64, data.m_name, data.m_mask); break; | |
| 1737 | } | |
| 1738 | break; | |
| 1739 | ||
| 1740 | case AMH_LEGACY_DEVICE_HANDLER: | |
| 1741 | device = m_machine.device(data.m_tag); | |
| 1742 | if (device == NULL) | |
| 1743 | fatalerror("Attempted to map a non-existent device '%s' in space %s of device '%s'\n", data.m_tag, m_name, m_device.tag()); | |
| 1744 | ||
| 1745 | if (readorwrite == ROW_READ) | |
| 1746 | switch (data.m_bits) | |
| 1747 | { | |
| 1748 | case 8: install_legacy_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rdevice8, data.m_name, data.m_mask); break; | |
| 1749 | case 16: install_legacy_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rdevice16, data.m_name, data.m_mask); break; | |
| 1750 | case 32: install_legacy_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rdevice32, data.m_name, data.m_mask); break; | |
| 1751 | case 64: install_legacy_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rdevice64, data.m_name, data.m_mask); break; | |
| 1752 | } | |
| 1753 | else | |
| 1754 | switch (data.m_bits) | |
| 1755 | { | |
| 1756 | case 8: install_legacy_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wdevice8, data.m_name, data.m_mask); break; | |
| 1757 | case 16: install_legacy_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wdevice16, data.m_name, data.m_mask); break; | |
| 1758 | case 32: install_legacy_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wdevice32, data.m_name, data.m_mask); break; | |
| 1759 | case 64: install_legacy_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wdevice64, data.m_name, data.m_mask); break; | |
| 1760 | } | |
| 1761 | break; | |
| 1762 | ||
| 1763 | case AMH_PORT: | |
| 1764 | install_port(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, | |
| 1765 | (readorwrite == ROW_READ) ? data.m_tag : NULL, | |
| 1766 | (readorwrite == ROW_WRITE) ? data.m_tag : NULL); | |
| 1767 | break; | |
| 1768 | ||
| 1769 | case AMH_BANK: | |
| 1770 | install_bank(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, | |
| 1771 | (readorwrite == ROW_READ) ? data.m_tag : NULL, | |
| 1772 | (readorwrite == ROW_WRITE) ? data.m_tag : NULL); | |
| 1773 | break; | |
| 1465 | 1774 | } |
| 1466 | ||
| 1467 | return (void *)space_find_backing_memory(spacerw, addrstart, addrend); | |
| 1468 | 1775 | } |
| 1469 | 1776 | |
| 1470 | 1777 | |
| 1471 | /*------------------------------------------------- | |
| 1472 | _memory_unmap - unmap a section of address | |
| 1473 | space | |
| 1474 | -------------------------------------------------*/ | |
| 1778 | //------------------------------------------------- | |
| 1779 | // allocate_memory - determine all neighboring | |
| 1780 | // address ranges and allocate memory to back | |
| 1781 | // them | |
| 1782 | //------------------------------------------------- | |
| 1475 | 1783 | |
| 1476 | void | |
| 1784 | void | |
| 1477 | 1785 | { |
| 1478 | | |
| 1786 | | |
| 1479 | 1787 | |
| 1480 | if (unmap_read) | |
| 1481 | space_map_range(spacerw, ROW_READ, space->dbits, 0, addrstart, addrend, addrmask, addrmirror, (genf *)(FPTR)(quiet ? STATIC_NOP : STATIC_UNMAP), spacerw, "unmapped"); | |
| 1482 | if (unmap_write) | |
| 1483 | space_map_range(spacerw, ROW_WRITE, space->dbits, 0, addrstart, addrend, addrmask, addrmirror, (genf *)(FPTR)(quiet ? STATIC_NOP : STATIC_UNMAP), spacerw, "unmapped"); | |
| 1484 | } | |
| 1788 | // make a first pass over the memory map and track blocks with hardcoded pointers | |
| 1789 | // we do this to make sure they are found by space_find_backing_memory first | |
| 1790 | memory_block *prev_memblock_tail = blocklist.last(); | |
| 1791 | for (address_map_entry *entry = m_map->m_entrylist.first(); entry != NULL; entry = entry->next()) | |
| 1792 | if (entry->m_memory != NULL) | |
| 1793 | blocklist.append(*auto_alloc(&m_machine, memory_block(*this, entry->m_bytestart, entry->m_byteend, entry->m_memory))); | |
| 1485 | 1794 | |
| 1795 | // loop over all blocks just allocated and assign pointers from them | |
| 1796 | address_map_entry *unassigned = NULL; | |
| 1797 | memory_block *first_new_block = (prev_memblock_tail != NULL) ? prev_memblock_tail->next() : blocklist.first(); | |
| 1798 | for (memory_block *memblock = first_new_block; memblock != NULL; memblock = memblock->next()) | |
| 1799 | unassigned = block_assign_intersecting(memblock->bytestart(), memblock->byteend(), memblock->data()); | |
| 1486 | 1800 | |
| 1801 | // if we don't have an unassigned pointer yet, try to find one | |
| 1802 | if (unassigned == NULL) | |
| 1803 | unassigned = block_assign_intersecting(~0, 0, NULL); | |
| 1487 | 1804 | |
| 1488 | /*************************************************************************** | |
| 1489 | DEBUGGER HELPERS | |
| 1490 | ***************************************************************************/ | |
| 1805 | // loop until we've assigned all memory in this space | |
| 1806 | while (unassigned != NULL) | |
| 1807 | { | |
| 1808 | // work in MEMORY_BLOCK_CHUNK-sized chunks | |
| 1809 | offs_t curblockstart = unassigned->m_bytestart / MEMORY_BLOCK_CHUNK; | |
| 1810 | offs_t curblockend = unassigned->m_byteend / MEMORY_BLOCK_CHUNK; | |
| 1491 | 1811 | |
| 1492 | /*------------------------------------------------- | |
| 1493 | memory_get_handler_string - return a string | |
| 1494 | describing the handler at a particular offset | |
| 1495 | -------------------------------------------------*/ | |
| 1812 | // loop while we keep finding unassigned blocks in neighboring MEMORY_BLOCK_CHUNK chunks | |
| 1813 | bool changed; | |
| 1814 | do | |
| 1815 | { | |
| 1816 | changed = false; | |
| 1496 | 1817 | |
| 1497 | const char *memory_get_handler_string(const address_space *space, int read0_or_write1, offs_t byteaddress) | |
| 1498 | { | |
| 1499 | const address_table *table = read0_or_write1 ? &space->write : &space->read; | |
| 1500 | UINT8 entry; | |
| 1818 | // scan for unmapped blocks in the adjusted map | |
| 1819 | for (address_map_entry *entry = m_map->m_entrylist.first(); entry != NULL; entry = entry->next()) | |
| 1820 | if (entry->m_memory == NULL && entry != unassigned && needs_backing_store(entry)) | |
| 1821 | { | |
| 1822 | // get block start/end blocks for this block | |
| 1823 | offs_t blockstart = entry->m_bytestart / MEMORY_BLOCK_CHUNK; | |
| 1824 | offs_t blockend = entry->m_byteend / MEMORY_BLOCK_CHUNK; | |
| 1501 | 1825 | |
| 1502 | /* perform the lookup */ | |
| 1503 | byteaddress &= space->bytemask; | |
| 1504 | entry = table->table[LEVEL1_INDEX(byteaddress)]; | |
| 1505 | if (entry >= SUBTABLE_BASE) | |
| 1506 | entry = table->table[LEVEL2_INDEX(entry, byteaddress)]; | |
| 1826 | // if we intersect or are adjacent, adjust the start/end | |
| 1827 | if (blockstart <= curblockend + 1 && blockend >= curblockstart - 1) | |
| 1828 | { | |
| 1829 | if (blockstart < curblockstart) | |
| 1830 | curblockstart = blockstart, changed = true; | |
| 1831 | if (blockend > curblockend) | |
| 1832 | curblockend = blockend, changed = true; | |
| 1833 | } | |
| 1834 | } | |
| 1835 | } while (changed); | |
| 1507 | 1836 | |
| 1508 | /* 8-bit case: RAM/ROM */ | |
| 1509 | return handler_to_string(space, table, entry); | |
| 1837 | // we now have a block to allocate; do it | |
| 1838 | offs_t curbytestart = curblockstart * MEMORY_BLOCK_CHUNK; | |
| 1839 | offs_t curbyteend = curblockend * MEMORY_BLOCK_CHUNK + (MEMORY_BLOCK_CHUNK - 1); | |
| 1840 | memory_block &block = blocklist.append(*auto_alloc(&m_machine, memory_block(*this, curbytestart, curbyteend))); | |
| 1841 | ||
| 1842 | // assign memory that intersected the new block | |
| 1843 | unassigned = block_assign_intersecting(curbytestart, curbyteend, block.data()); | |
| 1844 | } | |
| 1510 | 1845 | } |
| 1511 | 1846 | |
| 1512 | 1847 | |
| 1513 | /*------------------------------------------------- | |
| 1514 | memory_enable_read_watchpoints - enable/disable | |
| 1515 | read watchpoint tracking for a given address | |
| 1516 | space | |
| 1517 | -------------------------------------------------*/ | |
| 1848 | //------------------------------------------------- | |
| 1849 | // locate_memory - find all the requested | |
| 1850 | // pointers into the final allocated memory | |
| 1851 | //------------------------------------------------- | |
| 1518 | 1852 | |
| 1519 | void | |
| 1853 | void | |
| 1520 | 1854 | { |
| 1521 | address_space *spacerw = (address_space *)space; | |
| 1522 | if (enable) | |
| 1523 | spacerw->readlookup = space->machine->memory_data->wptable; | |
| 1524 | else | |
| 1525 | spacerw->readlookup = spacerw->read.table; | |
| 1855 | // fill in base/size entries | |
| 1856 | for (const address_map_entry *entry = m_map->m_entrylist.first(); entry != NULL; entry = entry->next()) | |
| 1857 | { | |
| 1858 | if (entry->m_baseptr != NULL) | |
| 1859 | *entry->m_baseptr = entry->m_memory; | |
| 1860 | if (entry->m_baseptroffs_plus1 != 0) | |
| 1861 | *(void **)(reinterpret_cast<UINT8 *>(m_machine.driver_data<void>()) + entry->m_baseptroffs_plus1 - 1) = entry->m_memory; | |
| 1862 | if (entry->m_genbaseptroffs_plus1 != 0) | |
| 1863 | *(void **)((UINT8 *)&m_machine.generic + entry->m_genbaseptroffs_plus1 - 1) = entry->m_memory; | |
| 1864 | if (entry->m_sizeptr != NULL) | |
| 1865 | *entry->m_sizeptr = entry->m_byteend - entry->m_bytestart + 1; | |
| 1866 | if (entry->m_sizeptroffs_plus1 != 0) | |
| 1867 | *(size_t *)(reinterpret_cast<UINT8 *>(m_machine.driver_data<void>()) + entry->m_sizeptroffs_plus1 - 1) = entry->m_byteend - entry->m_bytestart + 1; | |
| 1868 | if (entry->m_gensizeptroffs_plus1 != 0) | |
| 1869 | *(size_t *)((UINT8 *)&m_machine.generic + entry->m_gensizeptroffs_plus1 - 1) = entry->m_byteend - entry->m_bytestart + 1; | |
| 1870 | } | |
| 1871 | ||
| 1872 | // once this is done, find the starting bases for the banks | |
| 1873 | for (memory_bank *bank = m_machine.memory_data->banklist.first(); bank != NULL; bank = bank->next()) | |
| 1874 | if (bank->base() == NULL && bank->references_space(*this, ROW_READWRITE)) | |
| 1875 | { | |
| 1876 | // set the initial bank pointer | |
| 1877 | for (address_map_entry *entry = m_map->m_entrylist.first(); entry != NULL; entry = entry->next()) | |
| 1878 | if (entry->m_bytestart == bank->bytestart() && entry->m_memory != NULL) | |
| 1879 | { | |
| 1880 | bank->set_base(entry->m_memory); | |
| 1881 | VPRINTF(("assigned bank '%s' pointer to memory from range %08X-%08X [%p]\n", bank->tag(), entry->m_addrstart, entry->m_addrend, entry->m_memory)); | |
| 1882 | break; | |
| 1883 | } | |
| 1884 | ||
| 1885 | // if the entry was set ahead of time, override the automatically found pointer | |
| 1886 | if (!bank->anonymous() && bank->entry() != BANK_ENTRY_UNSPECIFIED) | |
| 1887 | bank->set_entry(bank->entry()); | |
| 1888 | } | |
| 1526 | 1889 | } |
| 1527 | 1890 | |
| 1528 | 1891 | |
| 1529 | /*------------------------------------------------- | |
| 1530 | memory_enable_write_watchpoints - enable/disable | |
| 1531 | write watchpoint tracking for a given address | |
| 1532 | space | |
| 1533 | -------------------------------------------------*/ | |
| 1892 | //------------------------------------------------- | |
| 1893 | // set_decrypted_region - registers an address | |
| 1894 | // range as having a decrypted data pointer | |
| 1895 | //------------------------------------------------- | |
| 1534 | 1896 | |
| 1535 | void | |
| 1897 | void add | |
| 1536 | 1898 | { |
| 1537 | address_space *spacerw = (address_space *)space; | |
| 1538 | if (enable) | |
| 1539 | spacerw->writelookup = space->machine->memory_data->wptable; | |
| 1540 | else | |
| 1541 | spacerw->writelookup = spacerw->write.table; | |
| 1899 | offs_t bytestart = address_to_byte(addrstart); | |
| 1900 | offs_t byteend = address_to_byte_end(addrend); | |
| 1901 | bool found = false; | |
| 1902 | ||
| 1903 | // loop over banks looking for a match | |
| 1904 | for (memory_bank *bank = m_machine.memory_data->banklist.first(); bank != NULL; bank = bank->next()) | |
| 1905 | { | |
| 1906 | // consider this bank if it is used for reading and matches the address space | |
| 1907 | if (bank->references_space(*this, ROW_READ)) | |
| 1908 | { | |
| 1909 | // verify that the region fully covers the decrypted range | |
| 1910 | if (bank->fully_covers(bytestart, byteend)) | |
| 1911 | { | |
| 1912 | // set the decrypted pointer for the corresponding memory bank | |
| 1913 | bank->set_base_decrypted(reinterpret_cast<UINT8 *>(base) + bank->bytestart() - bytestart); | |
| 1914 | found = true; | |
| 1915 | } | |
| 1916 | ||
| 1917 | // fatal error if the decrypted region straddles the bank | |
| 1918 | else if (bank->partially_covers(bytestart, byteend)) | |
| 1919 | throw emu_fatalerror("memory_set_decrypted_region found straddled region %08X-%08X for device '%s'", bytestart, byteend, m_device.tag()); | |
| 1920 | } | |
| 1921 | } | |
| 1922 | ||
| 1923 | // fatal error as well if we didn't find any relevant memory banks | |
| 1924 | if (!found) | |
| 1925 | throw emu_fatalerror("memory_set_decrypted_region unable to find matching region %08X-%08X for device '%s'", bytestart, byteend, m_device.tag()); | |
| 1542 | 1926 | } |
| 1543 | 1927 | |
| 1544 | 1928 | |
| 1545 | /*------------------------------------------------- | |
| 1546 | memory_set_debugger_access - control whether | |
| 1547 | subsequent accesses are treated as coming from | |
| 1548 | the debugger | |
| 1549 | -------------------------------------------------*/ | |
| 1929 | //------------------------------------------------- | |
| 1930 | // block_assign_intersecting - find all | |
| 1931 | // intersecting blocks and assign their pointers | |
| 1932 | //------------------------------------------------- | |
| 1550 | 1933 | |
| 1551 | ||
| 1934 | a | |
| 1552 | 1935 | { |
| 1553 | address_space *spacerw = (address_space *)space; | |
| 1554 | spacerw->debugger_access = debugger; | |
| 1555 | } | |
| 1936 | memory_private *memdata = m_machine.memory_data; | |
| 1937 | address_map_entry *unassigned = NULL; | |
| 1556 | 1938 | |
| 1939 | // loop over the adjusted map and assign memory to any blocks we can | |
| 1940 | for (address_map_entry *entry = m_map->m_entrylist.first(); entry != NULL; entry = entry->next()) | |
| 1941 | { | |
| 1942 | // if we haven't assigned this block yet, see if we have a mapped shared pointer for it | |
| 1943 | if (entry->m_memory == NULL && entry->m_share != NULL) | |
| 1944 | { | |
| 1945 | void *shareptr = memdata->sharemap.find(entry->m_share); | |
| 1946 | if (shareptr != UNMAPPED_SHARE_PTR) | |
| 1947 | { | |
| 1948 | entry->m_memory = shareptr; | |
| 1949 | VPRINTF(("memory range %08X-%08X -> shared_ptr '%s' [%p]\n", entry->m_addrstart, entry->m_addrend, entry->m_share, entry->m_memory)); | |
| 1950 | } | |
| 1951 | } | |
| 1557 | 1952 | |
| 1558 | /*------------------------------------------------- | |
| 1559 | memory_set_log_unmap - sets whether unmapped | |
| 1560 | memory accesses should be logged or not | |
| 1561 | -------------------------------------------------*/ | |
| 1953 | // otherwise, look for a match in this block | |
| 1954 | if (entry->m_memory == NULL && entry->m_bytestart >= bytestart && entry->m_byteend <= byteend) | |
| 1955 | { | |
| 1956 | entry->m_memory = base + (entry->m_bytestart - bytestart); | |
| 1957 | VPRINTF(("memory range %08X-%08X -> found in block from %08X-%08X [%p]\n", entry->m_addrstart, entry->m_addrend, bytestart, byteend, entry->m_memory)); | |
| 1958 | } | |
| 1562 | 1959 | |
| 1563 | void memory_set_log_unmap(const address_space *space, int log) | |
| 1564 | { | |
| 1565 | address_space *spacerw = (address_space *)space; | |
| 1566 | spacerw->log_unmap = log; | |
| 1960 | // if we're the first match on a shared pointer, assign it now | |
| 1961 | if (entry->m_memory != NULL && entry->m_share != NULL) | |
| 1962 | { | |
| 1963 | void *shareptr = memdata->sharemap.find(entry->m_share); | |
| 1964 | if (shareptr == UNMAPPED_SHARE_PTR) | |
| 1965 | memdata->sharemap.add(entry->m_share, entry->m_memory, TRUE); | |
| 1966 | } | |
| 1967 | ||
| 1968 | // keep track of the first unassigned entry | |
| 1969 | if (entry->m_memory == NULL && unassigned == NULL && needs_backing_store(entry)) | |
| 1970 | unassigned = entry; | |
| 1971 | } | |
| 1972 | ||
| 1973 | return unassigned; | |
| 1567 | 1974 | } |
| 1568 | 1975 | |
| 1569 | 1976 | |
| 1570 | /*------------------------------------------------- | |
| 1571 | memory_get_log_unmap - gets whether unmapped | |
| 1572 | memory accesses should be logged or not | |
| 1573 | -------------------------------------------------*/ | |
| 1977 | //------------------------------------------------- | |
| 1978 | // get_handler_string - return a string | |
| 1979 | // describing the handler at a particular offset | |
| 1980 | //------------------------------------------------- | |
| 1574 | 1981 | |
| 1575 | ||
| 1982 | const cha | |
| 1576 | 1983 | { |
| 1577 | return space->log_unmap; | |
| 1984 | if (readorwrite == ROW_READ) | |
| 1985 | return read().handler_name(read().lookup(byteaddress)); | |
| 1986 | else | |
| 1987 | return write().handler_name(write().lookup(byteaddress)); | |
| 1578 | 1988 | } |
| 1579 | 1989 | |
| 1580 | 1990 | |
| 1581 | /*------------------------------------------------- | |
| 1582 | memory_dump - dump the internal memory tables | |
| 1583 | to the given file | |
| 1584 | -------------------------------------------------*/ | |
| 1991 | //------------------------------------------------- | |
| 1992 | // dump_map - dump the contents of a single | |
| 1993 | // address space | |
| 1994 | //------------------------------------------------- | |
| 1585 | 1995 | |
| 1586 | void | |
| 1996 | void add | |
| 1587 | 1997 | { |
| 1588 | memory_private *memdata = machine->memory_data; | |
| 1589 | const address_space *space; | |
| 1998 | const address_table &table = (readorwrite == ROW_READ) ? static_cast<address_table &>(read()) : static_cast<address_table &>(write()); | |
| 1590 | 1999 | |
| 1591 | /* skip if we can't open the file */ | |
| 1592 | if (!file) | |
| 1593 | return; | |
| 2000 | // dump generic information | |
| 2001 | fprintf(file, " Address bits = %d\n", m_config.m_addrbus_width); | |
| 2002 | fprintf(file, " Data bits = %d\n", m_config.m_databus_width); | |
| 2003 | fprintf(file, " Address mask = %X\n", m_bytemask); | |
| 2004 | fprintf(file, "\n"); | |
| 1594 | 2005 | |
| 1595 | /* loop over valid address spaces */ | |
| 1596 | for (space = memdata->spacelist; space != NULL; space = space->next) | |
| 2006 | // iterate over addresses | |
| 2007 | offs_t bytestart, byteend; | |
| 2008 | for (offs_t byteaddress = 0; byteaddress <= m_bytemask; byteaddress = byteend) | |
| 1597 | 2009 | { |
| 1598 | fprintf(file, "\n\n" | |
| 1599 | "====================================================\n" | |
| 1600 | "Device '%s' %s address space read handler dump\n" | |
| 1601 | "====================================================\n", space->cpu->tag(), space->name); | |
| 1602 | dump_map(file, space, &space->read); | |
| 1603 | ||
| 1604 | fprintf(file, "\n\n" | |
| 1605 | "====================================================\n" | |
| 1606 | "Device '%s' %s address space write handler dump\n" | |
| 1607 | "====================================================\n", space->cpu->tag(), space->name); | |
| 1608 | dump_map(file, space, &space->write); | |
| 2010 | UINT8 entry = table.derive_range(byteaddress, bytestart, byteend); | |
| 2011 | fprintf(file, "%08X-%08X = %02X: %s [offset=%08X]\n", | |
| 2012 | bytestart, byteend, entry, table.handler_name(entry), table.handler(entry).bytestart()); | |
| 2013 | if (++byteend == 0) | |
| 2014 | break; | |
| 1609 | 2015 | } |
| 1610 | 2016 | } |
| 1611 | 2017 | |
| 1612 | 2018 | |
| 2019 | //************************************************************************** | |
| 2020 | // DYNAMIC ADDRESS SPACE MAPPING | |
| 2021 | //************************************************************************** | |
| 1613 | 2022 | |
| 1614 | /*************************************************************************** | |
| 1615 | INTERNAL INITIALIZATION | |
| 1616 | ***************************************************************************/ | |
| 2023 | //------------------------------------------------- | |
| 2024 | // unmap - unmap a section of address space | |
| 2025 | //------------------------------------------------- | |
| 1617 | 2026 | |
| 1618 | /*------------------------------------------------- | |
| 1619 | memory_init_spaces - create the address | |
| 1620 | spaces | |
| 1621 | -------------------------------------------------*/ | |
| 1622 | ||
| 1623 | static void memory_init_spaces(running_machine *machine) | |
| 2027 | void address_space::unmap(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read_or_write readorwrite, bool quiet) | |
| 1624 | 2028 | { |
| 1625 | memory_private *memdata = machine->memory_data; | |
| 1626 | address_space **nextptr = (address_space **)&memdata->spacelist; | |
| 1627 | int spacenum; | |
| 2029 | // read space | |
| 2030 | if (readorwrite == ROW_READ || readorwrite == ROW_READWRITE) | |
| 2031 | read().map_range(addrstart, addrend, addrmask, addrmirror, quiet ? STATIC_NOP : STATIC_UNMAP); | |
| 1628 | 2032 | |
| 1629 | /* create a global watchpoint-filled table */ | |
| 1630 | memdata->wptable = auto_alloc_array(machine, UINT8, 1 << LEVEL1_BITS); | |
| 1631 | memset(memdata->wptable, STATIC_WATCHPOINT, 1 << LEVEL1_BITS); | |
| 2033 | // write space | |
| 2034 | if (readorwrite == ROW_WRITE || readorwrite == ROW_READWRITE) | |
| 2035 | write().map_range(addrstart, addrend, addrmask, addrmirror, quiet ? STATIC_NOP : STATIC_UNMAP); | |
| 2036 | } | |
| 1632 | 2037 | |
| 1633 | /* loop over devices */ | |
| 1634 | device_memory_interface *memory = NULL; | |
| 1635 | for (bool gotone = machine->m_devicelist.first(memory); gotone; gotone = memory->next(memory)) | |
| 1636 | for (spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++) | |
| 1637 | { | |
| 1638 | const address_space_config *spaceconfig = memory->space_config(spacenum); | |
| 1639 | if (spaceconfig != NULL) | |
| 1640 | { | |
| 1641 | address_space *space = auto_alloc_clear(machine, address_space); | |
| 1642 | int ashift = spaceconfig->m_addrbus_shift; | |
| 1643 | int abits = spaceconfig->m_addrbus_width; | |
| 1644 | int dbits = spaceconfig->m_databus_width; | |
| 1645 | int logbits = spaceconfig->m_logaddr_width; | |
| 1646 | endianness_t endianness = spaceconfig->m_endianness; | |
| 1647 | int accessorindex = (dbits == 8) ? 0 : (dbits == 16) ? 1 : (dbits == 32) ? 2 : 3; | |
| 1648 | int entrynum; | |
| 1649 | 2038 | |
| 1650 | /* if logbits is 0, revert to abits */ | |
| 1651 | if (logbits == 0) | |
| 1652 | logbits = abits; | |
| 2039 | //------------------------------------------------- | |
| 2040 | // install_port - install a new I/O port handler | |
| 2041 | // into this address space | |
| 2042 | //------------------------------------------------- | |
| 1653 | 2043 | |
| 1654 | /* determine the address and data bits */ | |
| 1655 | space->machine = machine; | |
| 1656 | space->cpu = &memory->device(); | |
| 1657 | space->name = spaceconfig->m_name; | |
| 1658 | space->accessors = memory_accessors[accessorindex][(endianness == ENDIANNESS_LITTLE) ? 0 : 1]; | |
| 1659 | space->addrmask = 0xffffffffUL >> (32 - abits); | |
| 1660 | space->bytemask = (ashift < 0) ? ((space->addrmask << -ashift) | ((1 << -ashift) - 1)) : (space->addrmask >> ashift); | |
| 1661 | space->logaddrmask = 0xffffffffUL >> (32 - logbits); | |
| 1662 | space->logbytemask = (ashift < 0) ? ((space->logaddrmask << -ashift) | ((1 << -ashift) - 1)) : (space->logaddrmask >> ashift); | |
| 1663 | space->spacenum = spacenum; | |
| 1664 | space->endianness = endianness; | |
| 1665 | space->ashift = ashift; | |
| 1666 | space->abits = abits; | |
| 1667 | space->dbits = dbits; | |
| 1668 | space->addrchars = (abits + 3) / 4; | |
| 1669 | space->logaddrchars = (logbits + 3) / 4; | |
| 1670 | space->log_unmap = TRUE; | |
| 2044 | void address_space::install_port(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, const char *rtag, const char *wtag) | |
| 2045 | { | |
| 2046 | // read handler | |
| 2047 | if (rtag != NULL) | |
| 2048 | { | |
| 2049 | // find the port | |
| 2050 | const input_port_config *port = m_machine.port(rtag); | |
| 2051 | if (port == NULL) | |
| 2052 | throw emu_fatalerror("Attempted to map non-existent port '%s' for read in space %s of device '%s'\n", rtag, m_name, m_device.tag()); | |
| 1671 | 2053 | |
| 1672 | /* allocate subtable information; we malloc this manually because it will be realloc'ed */ | |
| 1673 | space->read.subtable = auto_alloc_array_clear(machine, subtable_data, SUBTABLE_COUNT); | |
| 1674 | space->write.subtable = auto_alloc_array_clear(machine, subtable_data, SUBTABLE_COUNT); | |
| 2054 | // map the range and set the ioport | |
| 2055 | UINT32 entry = read().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2056 | read().handler_read(entry).set_ioport(*port); | |
| 2057 | } | |
| 1675 | 2058 | |
| 1676 | /* allocate the handler table */ | |
| 1677 | space->read.handlers[0] = auto_alloc_array_clear(machine, handler_data, ARRAY_LENGTH(space->read.handlers)); | |
| 1678 | space->write.handlers[0] = auto_alloc_array_clear(machine, handler_data, ARRAY_LENGTH(space->write.handlers)); | |
| 1679 | for (entrynum = 1; entrynum < ARRAY_LENGTH(space->read.handlers); entrynum++) | |
| 1680 | { | |
| 1681 | space->read.handlers[entrynum] = space->read.handlers[0] + entrynum; | |
| 1682 | space->write.handlers[entrynum] = space->write.handlers[0] + entrynum; | |
| 1683 | } | |
| 2059 | if (wtag != NULL) | |
| 2060 | { | |
| 2061 | // find the port | |
| 2062 | const input_port_config *port = m_machine.port(wtag); | |
| 2063 | if (port == NULL) | |
| 2064 | fatalerror("Attempted to map non-existent port '%s' for write in space %s of device '%s'\n", wtag, m_name, m_device.tag()); | |
| 1684 | 2065 | |
| 1685 | /* init the static handlers */ | |
| 1686 | for (entrynum = 0; entrynum < ENTRY_COUNT; entrynum++) | |
| 1687 | { | |
| 1688 | space->read.handlers[entrynum]->handler.generic = get_static_handler(space->dbits, 0, entrynum); | |
| 1689 | space->read.handlers[entrynum]->object = space; | |
| 1690 | space->write.handlers[entrynum]->handler.generic = get_static_handler(space->dbits, 1, entrynum); | |
| 1691 | space->write.handlers[entrynum]->object = space; | |
| 1692 | } | |
| 2066 | // map the range and set the ioport | |
| 2067 | UINT32 entry = write().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2068 | write().handler_write(entry).set_ioport(*port); | |
| 2069 | } | |
| 1693 | 2070 | |
| 1694 | /* make sure we fix up the mask for the unmap and watchpoint handlers */ | |
| 1695 | space->read.handlers[STATIC_UNMAP]->bytemask = ~0; | |
| 1696 | space->write.handlers[STATIC_UNMAP]->bytemask = ~0; | |
| 1697 | space->read.handlers[STATIC_WATCHPOINT]->bytemask = ~0; | |
| 1698 | space->write.handlers[STATIC_WATCHPOINT]->bytemask = ~0; | |
| 2071 | // update the memory dump | |
| 2072 | generate_memdump(&m_machine); | |
| 2073 | } | |
| 1699 | 2074 | |
| 1700 | /* allocate memory */ | |
| 1701 | space->read.machine = machine; | |
| 1702 | space->read.table = auto_alloc_array(machine, UINT8, 1 << LEVEL1_BITS); | |
| 1703 | space->write.machine = machine; | |
| 1704 | space->write.table = auto_alloc_array(machine, UINT8, 1 << LEVEL1_BITS); | |
| 1705 | 2075 | |
| 1706 | /* initialize everything to unmapped */ | |
| 1707 | memset(space->read.table, STATIC_UNMAP, 1 << LEVEL1_BITS); | |
| 1708 | memset(space->write.table, STATIC_UNMAP, 1 << LEVEL1_BITS); | |
| 2076 | //------------------------------------------------- | |
| 2077 | // install_bank - install a range as mapping to | |
| 2078 | // a particular bank | |
| 2079 | //------------------------------------------------- | |
| 1709 | 2080 | |
| 1710 | /* initialize the lookups */ | |
| 1711 | space->readlookup = space->read.table; | |
| 1712 | space->writelookup = space->write.table; | |
| 2081 | void address_space::install_bank(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, const char *rtag, const char *wtag) | |
| 2082 | { | |
| 2083 | // map the read bank | |
| 2084 | if (rtag != NULL) | |
| 2085 | { | |
| 2086 | memory_bank &bank = bank_find_or_allocate(rtag, addrstart, addrend, addrmask, addrmirror, ROW_READ); | |
| 2087 | read().map_range(addrstart, addrend, addrmask, addrmirror, bank.index()); | |
| 2088 | } | |
| 1713 | 2089 | |
| 1714 | /* set the direct access information base */ | |
| 1715 | space->direct.raw = space->direct.decrypted = NULL; | |
| 1716 | space->direct.bytemask = space->bytemask; | |
| 1717 | space->direct.bytestart = 1; | |
| 1718 | space->direct.byteend = 0; | |
| 1719 | space->direct.entry = STATIC_UNMAP; | |
| 1720 | space->directupdate = NULL; | |
| 2090 | // map the write bank | |
| 2091 | if (wtag != NULL) | |
| 2092 | { | |
| 2093 | memory_bank &bank = bank_find_or_allocate(wtag, addrstart, addrend, addrmask, addrmirror, ROW_WRITE); | |
| 2094 | write().map_range(addrstart, addrend, addrmask, addrmirror, bank.index()); | |
| 2095 | } | |
| 1721 | 2096 | |
| 1722 | /* link us in */ | |
| 1723 | *nextptr = space; | |
| 1724 | nextptr = (address_space **)&space->next; | |
| 1725 | ||
| 1726 | /* notify the device */ | |
| 1727 | memory->set_address_space(spacenum, space); | |
| 1728 | } | |
| 1729 | } | |
| 2097 | // update the memory dump | |
| 2098 | generate_memdump(&m_machine); | |
| 1730 | 2099 | } |
| 1731 | 2100 | |
| 1732 | 2101 | |
| 1733 | /*------------------------------------------------- | |
| 1734 | memory_init_preflight - verify the memory structs | |
| 1735 | and track which banks are referenced | |
| 1736 | -------------------------------------------------*/ | |
| 2102 | //------------------------------------------------- | |
| 2103 | // install_ram - install a simple fixed RAM | |
| 2104 | // region into the given address space | |
| 2105 | //------------------------------------------------- | |
| 1737 | 2106 | |
| 1738 | ||
| 2107 | ||
| 1739 | 2108 | { |
| 1740 | memory_private *memdata = machine->memory_data; | |
| 1741 | address_space *space; | |
| 2109 | memory_private *memdata = m_machine.memory_data; | |
| 1742 | 2110 | |
| 1743 | /* reset the banking state */ | |
| 1744 | memdata->banknext = STATIC_BANK1; | |
| 1745 | ||
| 1746 | /* loop over valid address spaces */ | |
| 1747 | for (space = (address_space *)memdata->spacelist; space != NULL; space = (address_space *)space->next) | |
| 2111 | // map for read | |
| 2112 | if (readorwrite == ROW_READ || readorwrite == ROW_READWRITE) | |
| 1748 | 2113 | { |
| 1749 | const region_info *devregion = (space->spacenum == ADDRESS_SPACE_0) ? space->machine->region(space->cpu->tag()) : NULL; | |
| 1750 | int devregionsize = (devregion != NULL) ? devregion->bytes() : 0; | |
| 1751 | address_map_entry *entry; | |
| 1752 | int entrynum; | |
| 2114 | // find a bank and map it | |
| 2115 | memory_bank &bank = bank_find_or_allocate(NULL, addrstart, addrend, addrmask, addrmirror, ROW_READ); | |
| 2116 | read().map_range(addrstart, addrend, addrmask, addrmirror, bank.index()); | |
| 1753 | 2117 | |
| 1754 | /* allocate the address map */ | |
| 1755 | space->map = global_alloc(address_map(space->cpu->baseconfig(), space->spacenum)); | |
| 2118 | // if we are provided a pointer, set it | |
| 2119 | if (baseptr != NULL) | |
| 2120 | bank.set_base(baseptr); | |
| 1756 | 2121 | |
| 1757 | /* extract global parameters specified by the map */ | |
| 1758 | space->unmap = (space->map->m_unmapval == 0) ? 0 : ~0; | |
| 1759 | if (space->map->m_globalmask != 0) | |
| 2122 | // if we don't have a bank pointer yet, try to find one | |
| 2123 | if (bank.base() == NULL) | |
| 1760 | 2124 | { |
| 1761 | space->addrmask = space->map->m_globalmask; | |
| 1762 | space->bytemask = memory_address_to_byte_end(space, space->addrmask); | |
| 2125 | void *backing = find_backing_memory(addrstart, addrend); | |
| 2126 | if (backing != NULL) | |
| 2127 | bank.set_base(backing); | |
| 1763 | 2128 | } |
| 1764 | 2129 | |
| 1765 | /* make a pass over the address map, adjusting for the device and getting memory pointers */ | |
| 1766 | for (entry = space->map->m_entrylist; entry != NULL; entry = entry->m_next) | |
| 2130 | // if we still don't have a pointer, and we're past the initialization phase, allocate a new block | |
| 2131 | if (bank.base() == NULL && memdata->initialized) | |
| 1767 | 2132 | { |
| 1768 | /* if we have a share entry, add it to our map */ | |
| 1769 | if (entry->m_share != NULL) | |
| 1770 | memdata->sharemap.add(entry->m_share, UNMAPPED_SHARE_PTR, FALSE); | |
| 2133 | if (m_machine.phase() >= MACHINE_PHASE_RESET) | |
| 2134 | fatalerror("Attempted to call memory_install_ram() after initialization time without a baseptr!"); | |
| 2135 | memory_block &block = memdata->blocklist.append(*auto_alloc(&m_machine, memory_block(*this, address_to_byte(addrstart), address_to_byte_end(addrend)))); | |
| 2136 | bank.set_base(block.data()); | |
| 2137 | } | |
| 2138 | } | |
| 1771 | 2139 | |
| 1772 | /* computed adjusted addresses first */ | |
| 1773 | entry->m_bytestart = entry->m_addrstart; | |
| 1774 | entry->m_byteend = entry->m_addrend; | |
| 1775 | entry->m_bytemirror = entry->m_addrmirror; | |
| 1776 | entry->m_bytemask = entry->m_addrmask; | |
| 1777 | adjust_addresses(space, &entry->m_bytestart, &entry->m_byteend, &entry->m_bytemask, &entry->m_bytemirror); | |
| 2140 | // map for write | |
| 2141 | if (readorwrite == ROW_WRITE || readorwrite == ROW_READWRITE) | |
| 2142 | { | |
| 2143 | // find a bank and map it | |
| 2144 | memory_bank &bank = bank_find_or_allocate(NULL, addrstart, addrend, addrmask, addrmirror, ROW_WRITE); | |
| 2145 | write().map_range(addrstart, addrend, addrmask, addrmirror, bank.index()); | |
| 1778 | 2146 | |
| 1779 | /* if this is a ROM handler without a specified region, attach it to the implicit region */ | |
| 1780 | if (space->spacenum == ADDRESS_SPACE_0 && entry->m_read.type == AMH_ROM && entry->m_region == NULL) | |
| 1781 | { | |
| 1782 | /* make sure it fits within the memory region before doing so, however */ | |
| 1783 | if (entry->m_byteend < devregionsize) | |
| 1784 | { | |
| 1785 | entry->m_region = space->cpu->tag(); | |
| 1786 | entry->m_rgnoffs = entry->m_bytestart; | |
| 1787 | } | |
| 1788 | } | |
| 2147 | // if we are provided a pointer, set it | |
| 2148 | if (baseptr != NULL) | |
| 2149 | bank.set_base(baseptr); | |
| 1789 | 2150 | |
| 1790 | /* validate adjusted addresses against implicit regions */ | |
| 1791 | if (entry->m_region != NULL && entry->m_share == NULL && entry->m_baseptr == NULL) | |
| 1792 | { | |
| 1793 | const region_info *region = machine->region(entry->m_region); | |
| 1794 | if (region == NULL) | |
| 1795 | fatalerror("Error: device '%s' %s space memory map entry %X-%X references non-existant region \"%s\"", space->cpu->tag(), space->name, entry->m_addrstart, entry->m_addrend, entry->m_region); | |
| 1796 | ||
| 1797 | /* validate the region */ | |
| 1798 | if (entry->m_rgnoffs + (entry->m_byteend - entry->m_bytestart + 1) > region->bytes()) | |
| 1799 | fatalerror("Error: device '%s' %s space memory map entry %X-%X extends beyond region \"%s\" size (%X)", space->cpu->tag(), space->name, entry->m_addrstart, entry->m_addrend, entry->m_region, region->bytes()); | |
| 1800 | } | |
| 1801 | ||
| 1802 | /* convert any region-relative entries to their memory pointers */ | |
| 1803 | if (entry->m_region != NULL) | |
| 1804 | entry->m_memory = machine->region(entry->m_region)->base() + entry->m_rgnoffs; | |
| 2151 | // if we don't have a bank pointer yet, try to find one | |
| 2152 | if (bank.base() == NULL) | |
| 2153 | { | |
| 2154 | void *backing = find_backing_memory(addrstart, addrend); | |
| 2155 | if (backing != NULL) | |
| 2156 | bank.set_base(backing); | |
| 1805 | 2157 | } |
| 1806 | 2158 | |
| 1807 | /* now loop over all the handlers and enforce the address mask */ | |
| 1808 | /* we don't loop over map entries because the mask applies to static handlers as well */ | |
| 1809 | for (entrynum = 0; entrynum < ENTRY_COUNT; entrynum++) | |
| 2159 | // if we still don't have a pointer, and we're past the initialization phase, allocate a new block | |
| 2160 | if (bank.base() == NULL && memdata->initialized) | |
| 1810 | 2161 | { |
| 1811 | space->read.handlers[entrynum]->bytemask &= space->bytemask; | |
| 1812 | space->write.handlers[entrynum]->bytemask &= space->bytemask; | |
| 2162 | if (m_machine.phase() >= MACHINE_PHASE_RESET) | |
| 2163 | fatalerror("Attempted to call memory_install_ram() after initialization time without a baseptr!"); | |
| 2164 | memory_block &block = memdata->blocklist.append(*auto_alloc(&m_machine, memory_block(*this, address_to_byte(addrstart), address_to_byte_end(addrend)))); | |
| 2165 | bank.set_base(block.data()); | |
| 1813 | 2166 | } |
| 1814 | 2167 | } |
| 2168 | ||
| 2169 | return (void *)find_backing_memory(addrstart, addrend); | |
| 1815 | 2170 | } |
| 1816 | 2171 | |
| 1817 | 2172 | |
| 1818 | /*------------------------------------------------- | |
| 1819 | memory_init_populate - populate the memory | |
| 1820 | mapping tables with entries | |
| 1821 | -------------------------------------------------*/ | |
| 2173 | //------------------------------------------------- | |
| 2174 | // install_handler - install 8-bit read/write | |
| 2175 | // delegate handlers for the space | |
| 2176 | //------------------------------------------------- | |
| 1822 | 2177 | |
| 1823 | s | |
| 2178 | UINT8 *address_spa | |
| 1824 | 2179 | { |
| 1825 | memory_private *memdata = machine->memory_data; | |
| 1826 | address_space *space; | |
| 2180 | UINT32 entry = read().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2181 | read().handler_read(entry).set_delegate(handler, unitmask); | |
| 2182 | generate_memdump(machine); | |
| 2183 | return reinterpret_cast<UINT8 *>(find_backing_memory(addrstart, addrend)); | |
| 2184 | } | |
| 1827 | 2185 | |
| 1828 | /* loop over valid address spaces */ | |
| 1829 | for (space = (address_space *)memdata->spacelist; space != NULL; space = (address_space *)space->next) | |
| 1830 | if (space->map != NULL) | |
| 1831 | { | |
| 1832 | const address_map_entry *last_entry = NULL; | |
| 2186 | UINT8 *address_space::install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write8_delegate handler, UINT64 unitmask) | |
| 2187 | { | |
| 2188 | UINT32 entry = write().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2189 | write().handler_write(entry).set_delegate(handler, unitmask); | |
| 2190 | generate_memdump(machine); | |
| 2191 | return reinterpret_cast<UINT8 *>(find_backing_memory(addrstart, addrend)); | |
| 2192 | } | |
| 1833 | 2193 | |
| 1834 | /* install the handlers, using the original, unadjusted memory map */ | |
| 1835 | while (last_entry != space->map->m_entrylist) | |
| 1836 | { | |
| 1837 | const address_map_entry *entry; | |
| 2194 | UINT8 *address_space::install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_delegate rhandler, write8_delegate whandler, UINT64 unitmask) | |
| 2195 | { | |
| 2196 | install_handler(addrstart, addrend, addrmask, addrmirror, rhandler, unitmask); | |
| 2197 | return install_handler(addrstart, addrend, addrmask, addrmirror, whandler, unitmask); | |
| 2198 | } | |
| 1838 | 2199 | |
| 1839 | /* find the entry before the last one we processed */ | |
| 1840 | for (entry = space->map->m_entrylist; entry->m_next != last_entry; entry = entry->m_next) ; | |
| 1841 | last_entry = entry; | |
| 1842 | 2200 | |
| 1843 | /* map both read and write halves */ | |
| 1844 | memory_init_map_entry(space, entry, ROW_READ); | |
| 1845 | memory_init_map_entry(space, entry, ROW_WRITE); | |
| 1846 | } | |
| 1847 | } | |
| 2201 | //------------------------------------------------- | |
| 2202 | // install_legacy_handler - install 8-bit read/ | |
| 2203 | // write legacy address space handlers for the | |
| 2204 | // space | |
| 2205 | //------------------------------------------------- | |
| 2206 | ||
| 2207 | UINT8 *address_space::install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_space_func rhandler, const char *rname, UINT64 unitmask) | |
| 2208 | { | |
| 2209 | UINT32 entry = read().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2210 | read().handler_read(entry).set_legacy_func(*this, rhandler, rname, unitmask); | |
| 2211 | generate_memdump(machine); | |
| 2212 | return reinterpret_cast<UINT8 *>(find_backing_memory(addrstart, addrend)); | |
| 1848 | 2213 | } |
| 1849 | 2214 | |
| 2215 | UINT8 *address_space::install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write8_space_func whandler, const char *wname, UINT64 unitmask) | |
| 2216 | { | |
| 2217 | UINT32 entry = write().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2218 | write().handler_write(entry).set_legacy_func(*this, whandler, wname, unitmask); | |
| 2219 | generate_memdump(machine); | |
| 2220 | return reinterpret_cast<UINT8 *>(find_backing_memory(addrstart, addrend)); | |
| 2221 | } | |
| 1850 | 2222 | |
| 1851 | /*------------------------------------------------- | |
| 1852 | memory_init_map_entry - map a single read or | |
| 1853 | write entry based on information from an | |
| 1854 | address map entry | |
| 1855 | -------------------------------------------------*/ | |
| 1856 | ||
| 1857 | static void memory_init_map_entry(address_space *space, const address_map_entry *entry, read_or_write readorwrite) | |
| 2223 | UINT8 *address_space::install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_space_func rhandler, const char *rname, write8_space_func whandler, const char *wname, UINT64 unitmask) | |
| 1858 | 2224 | { |
| 1859 | const map_handler_data *handler = (readorwrite == ROW_READ) ? &entry->m_read : &entry->m_write; | |
| 1860 | device_t *device; | |
| 2225 | install_legacy_handler(addrstart, addrend, addrmask, addrmirror, rhandler, rname, unitmask); | |
| 2226 | return install_legacy_handler(addrstart, addrend, addrmask, addrmirror, whandler, wname, unitmask); | |
| 2227 | } | |
| 1861 | 2228 | |
| 1862 | /* based on the handler type, alter the bits, name, funcptr, and object */ | |
| 1863 | switch (handler->type) | |
| 1864 | { | |
| 1865 | case AMH_NONE: | |
| 1866 | return; | |
| 1867 | 2229 | |
| 1868 | case AMH_ROM: | |
| 1869 | if (readorwrite == ROW_WRITE) | |
| 1870 | return; | |
| 1871 | /* fall through to the RAM case otherwise */ | |
| 2230 | //------------------------------------------------- | |
| 2231 | // install_legacy_handler - install 8-bit read/ | |
| 2232 | // write legacy device handlers for the space | |
| 2233 | //------------------------------------------------- | |
| 1872 | 2234 | |
| 1873 | case AMH_RAM: | |
| 1874 | _memory_install_ram(space, entry->m_addrstart, entry->m_addrend, entry->m_addrmask, entry->m_addrmirror, | |
| 1875 | readorwrite == ROW_READ, readorwrite == ROW_WRITE, NULL); | |
| 1876 | break; | |
| 2235 | UINT8 *address_space::install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_device_func rhandler, const char *rname, UINT64 unitmask) | |
| 2236 | { | |
| 2237 | UINT32 entry = read().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2238 | read().handler_read(entry).set_legacy_func(device, rhandler, rname, unitmask); | |
| 2239 | generate_memdump(machine); | |
| 2240 | return reinterpret_cast<UINT8 *>(find_backing_memory(addrstart, addrend)); | |
| 2241 | } | |
| 1877 | 2242 | |
| 1878 | case AMH_NOP: | |
| 1879 | _memory_unmap(space, entry->m_addrstart, entry->m_addrend, entry->m_addrmask, entry->m_addrmirror, | |
| 1880 | readorwrite == ROW_READ, readorwrite == ROW_WRITE, TRUE); | |
| 1881 | break; | |
| 2243 | UINT8 *address_space::install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write8_device_func whandler, const char *wname, UINT64 unitmask) | |
| 2244 | { | |
| 2245 | UINT32 entry = write().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2246 | write().handler_write(entry).set_legacy_func(device, whandler, wname, unitmask); | |
| 2247 | generate_memdump(machine); | |
| 2248 | return reinterpret_cast<UINT8 *>(find_backing_memory(addrstart, addrend)); | |
| 2249 | } | |
| 1882 | 2250 | |
| 1883 | case AMH_UNMAP: | |
| 1884 | _memory_unmap(space, entry->m_addrstart, entry->m_addrend, entry->m_addrmask, entry->m_addrmirror, | |
| 1885 | readorwrite == ROW_READ, readorwrite == ROW_WRITE, FALSE); | |
| 1886 | break; | |
| 2251 | UINT8 *address_space::install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_device_func rhandler, const char *rname, write8_device_func whandler, const char *wname, UINT64 unitmask) | |
| 2252 | { | |
| 2253 | install_legacy_handler(device, addrstart, addrend, addrmask, addrmirror, rhandler, rname, unitmask); | |
| 2254 | return install_legacy_handler(device, addrstart, addrend, addrmask, addrmirror, whandler, wname, unitmask); | |
| 2255 | } | |
| 1887 | 2256 | |
| 1888 | case AMH_HANDLER: | |
| 1889 | switch ((handler->bits != 0) ? handler->bits : space->dbits) | |
| 1890 | { | |
| 1891 | case 8: | |
| 1892 | _memory_install_handler8(space, entry->m_addrstart, entry->m_addrend, entry->m_addrmask, entry->m_addrmirror, | |
| 1893 | (readorwrite == ROW_READ) ? handler->handler.read.shandler8 : NULL, handler->name, | |
| 1894 | (readorwrite == ROW_WRITE) ? handler->handler.write.shandler8 : NULL, handler->name, | |
| 1895 | handler->mask); | |
| 1896 | break; | |
| 1897 | 2257 | |
| 1898 | case 16: | |
| 1899 | _memory_install_handler16(space, entry->m_addrstart, entry->m_addrend, entry->m_addrmask, entry->m_addrmirror, | |
| 1900 | (readorwrite == ROW_READ) ? handler->handler.read.shandler16 : NULL, handler->name, | |
| 1901 | (readorwrite == ROW_WRITE) ? handler->handler.write.shandler16 : NULL, handler->name, | |
| 1902 | handler->mask); | |
| 1903 | break; | |
| 2258 | //------------------------------------------------- | |
| 2259 | // install_handler - install 16-bit read/write | |
| 2260 | // delegate handlers for the space | |
| 2261 | //------------------------------------------------- | |
| 1904 | 2262 | |
| 1905 | case 32: | |
| 1906 | _memory_install_handler32(space, entry->m_addrstart, entry->m_addrend, entry->m_addrmask, entry->m_addrmirror, | |
| 1907 | (readorwrite == ROW_READ) ? handler->handler.read.shandler32 : NULL, handler->name, | |
| 1908 | (readorwrite == ROW_WRITE) ? handler->handler.write.shandler32 : NULL, handler->name, | |
| 1909 | handler->mask); | |
| 1910 | break; | |
| 2263 | UINT16 *address_space::install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_delegate handler, UINT64 unitmask) | |
| 2264 | { | |
| 2265 | UINT32 entry = read().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2266 | read().handler_read(entry).set_delegate(handler, unitmask); | |
| 2267 | generate_memdump(machine); | |
| 2268 | return reinterpret_cast<UINT16 *>(find_backing_memory(addrstart, addrend)); | |
| 2269 | } | |
| 1911 | 2270 | |
| 1912 | case 64: | |
| 1913 | _memory_install_handler64(space, entry->m_addrstart, entry->m_addrend, entry->m_addrmask, entry->m_addrmirror, | |
| 1914 | (readorwrite == ROW_READ) ? handler->handler.read.shandler64 : NULL, handler->name, | |
| 1915 | (readorwrite == ROW_WRITE) ? handler->handler.write.shandler64 : NULL, handler->name, | |
| 1916 | handler->mask); | |
| 1917 | break; | |
| 1918 | } | |
| 1919 | break; | |
| 2271 | UINT16 *address_space::install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write16_delegate handler, UINT64 unitmask) | |
| 2272 | { | |
| 2273 | UINT32 entry = write().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2274 | write().handler_write(entry).set_delegate(handler, unitmask); | |
| 2275 | generate_memdump(machine); | |
| 2276 | return reinterpret_cast<UINT16 *>(find_backing_memory(addrstart, addrend)); | |
| 2277 | } | |
| 1920 | 2278 | |
| 1921 | case AMH_DEVICE_HANDLER: | |
| 1922 | device = space->machine->device(handler->tag); | |
| 1923 | if (device == NULL) | |
| 1924 | fatalerror("Attempted to map a non-existent device '%s' in space %s of device '%s'\n", handler->tag, space->name, (space->cpu != NULL) ? space->cpu->tag() : "??"); | |
| 1925 | switch ((handler->bits != 0) ? handler->bits : space->dbits) | |
| 1926 | { | |
| 1927 | case 8: | |
| 1928 | _memory_install_device_handler8(space, device, entry->m_addrstart, entry->m_addrend, entry->m_addrmask, entry->m_addrmirror, | |
| 1929 | (readorwrite == ROW_READ) ? handler->handler.read.dhandler8 : NULL, handler->name, | |
| 1930 | (readorwrite == ROW_WRITE) ? handler->handler.write.dhandler8 : NULL, handler->name, | |
| 1931 | handler->mask); | |
| 1932 | break; | |
| 2279 | UINT16 *address_space::install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_delegate rhandler, write16_delegate whandler, UINT64 unitmask) | |
| 2280 | { | |
| 2281 | install_handler(addrstart, addrend, addrmask, addrmirror, rhandler, unitmask); | |
| 2282 | return install_handler(addrstart, addrend, addrmask, addrmirror, whandler, unitmask); | |
| 2283 | } | |
| 1933 | 2284 | |
| 1934 | case 16: | |
| 1935 | _memory_install_device_handler16(space, device, entry->m_addrstart, entry->m_addrend, entry->m_addrmask, entry->m_addrmirror, | |
| 1936 | (readorwrite == ROW_READ) ? handler->handler.read.dhandler16 : NULL, handler->name, | |
| 1937 | (readorwrite == ROW_WRITE) ? handler->handler.write.dhandler16 : NULL, handler->name, | |
| 1938 | handler->mask); | |
| 1939 | break; | |
| 1940 | 2285 | |
| 1941 | case 32: | |
| 1942 | _memory_install_device_handler32(space, device, entry->m_addrstart, entry->m_addrend, entry->m_addrmask, entry->m_addrmirror, | |
| 1943 | (readorwrite == ROW_READ) ? handler->handler.read.dhandler32 : NULL, handler->name, | |
| 1944 | (readorwrite == ROW_WRITE) ? handler->handler.write.dhandler32 : NULL, handler->name, | |
| 1945 | handler->mask); | |
| 1946 | break; | |
| 2286 | //------------------------------------------------- | |
| 2287 | // install_legacy_handler - install 16-bit read/ | |
| 2288 | // write legacy address space handlers for the | |
| 2289 | // space | |
| 2290 | //------------------------------------------------- | |
| 1947 | 2291 | |
| 1948 | case 64: | |
| 1949 | _memory_install_device_handler64(space, device, entry->m_addrstart, entry->m_addrend, entry->m_addrmask, entry->m_addrmirror, | |
| 1950 | (readorwrite == ROW_READ) ? handler->handler.read.dhandler64 : NULL, handler->name, | |
| 1951 | (readorwrite == ROW_WRITE) ? handler->handler.write.dhandler64 : NULL, handler->name, | |
| 1952 | handler->mask); | |
| 1953 | break; | |
| 1954 | } | |
| 1955 | break; | |
| 2292 | UINT16 *address_space::install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_space_func rhandler, const char *rname, UINT64 unitmask) | |
| 2293 | { | |
| 2294 | UINT32 entry = read().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2295 | read().handler_read(entry).set_legacy_func(*this, rhandler, rname, unitmask); | |
| 2296 | generate_memdump(machine); | |
| 2297 | return reinterpret_cast<UINT16 *>(find_backing_memory(addrstart, addrend)); | |
| 2298 | } | |
| 1956 | 2299 | |
| 1957 | case AMH_PORT: | |
| 1958 | _memory_install_port(space, entry->m_addrstart, entry->m_addrend, entry->m_addrmask, entry->m_addrmirror, | |
| 1959 | (readorwrite == ROW_READ) ? handler->tag : NULL, | |
| 1960 | (readorwrite == ROW_WRITE) ? handler->tag : NULL); | |
| 1961 | break; | |
| 2300 | UINT16 *address_space::install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write16_space_func whandler, const char *wname, UINT64 unitmask) | |
| 2301 | { | |
| 2302 | UINT32 entry = write().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2303 | write().handler_write(entry).set_legacy_func(*this, whandler, wname, unitmask); | |
| 2304 | generate_memdump(machine); | |
| 2305 | return reinterpret_cast<UINT16 *>(find_backing_memory(addrstart, addrend)); | |
| 2306 | } | |
| 1962 | 2307 | |
| 1963 | case AMH_BANK: | |
| 1964 | _memory_install_bank(space, entry->m_addrstart, entry->m_addrend, entry->m_addrmask, entry->m_addrmirror, | |
| 1965 | (readorwrite == ROW_READ) ? handler->tag : NULL, | |
| 1966 | (readorwrite == ROW_WRITE) ? handler->tag : NULL); | |
| 1967 | break; | |
| 1968 | } | |
| 2308 | UINT16 *address_space::install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_space_func rhandler, const char *rname, write16_space_func whandler, const char *wname, UINT64 unitmask) | |
| 2309 | { | |
| 2310 | install_legacy_handler(addrstart, addrend, addrmask, addrmirror, rhandler, rname, unitmask); | |
| 2311 | return install_legacy_handler(addrstart, addrend, addrmask, addrmirror, whandler, wname, unitmask); | |
| 1969 | 2312 | } |
| 1970 | 2313 | |
| 1971 | 2314 | |
| 1972 | /*------------------------------------------------- | |
| 1973 | memory_init_allocate - allocate memory for | |
| 1974 | device address spaces | |
| 1975 | -------------------------------------------------*/ | |
| 2315 | //------------------------------------------------- | |
| 2316 | // install_legacy_handler - install 16-bit read/ | |
| 2317 | // write legacy device handlers for the space | |
| 2318 | //------------------------------------------------- | |
| 1976 | 2319 | |
| 1977 | s | |
| 2320 | UINT16 *address_space::install_legacy_handler(device_t &dev | |
| 1978 | 2321 | { |
| 1979 | memory_private *memdata = machine->memory_data; | |
| 1980 | address_space *space; | |
| 2322 | UINT32 entry = read().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2323 | read().handler_read(entry).set_legacy_func(device, rhandler, rname, unitmask); | |
| 2324 | generate_memdump(machine); | |
| 2325 | return reinterpret_cast<UINT16 *>(find_backing_memory(addrstart, addrend)); | |
| 2326 | } | |
| 1981 | 2327 | |
| 1982 | /* loop over valid address spaces */ | |
| 1983 | for (space = (address_space *)memdata->spacelist; space != NULL; space = (address_space *)space->next) | |
| 1984 | { | |
| 1985 | address_map_entry *unassigned = NULL; | |
| 1986 | address_map_entry *entry; | |
| 1987 | memory_block *prev_memblock_head = memdata->memory_block_list; | |
| 1988 | memory_block *memblock; | |
| 2328 | UINT16 *address_space::install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write16_device_func whandler, const char *wname, UINT64 unitmask) | |
| 2329 | { | |
| 2330 | UINT32 entry = write().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2331 | write().handler_write(entry).set_legacy_func(device, whandler, wname, unitmask); | |
| 2332 | generate_memdump(machine); | |
| 2333 | return reinterpret_cast<UINT16 *>(find_backing_memory(addrstart, addrend)); | |
| 2334 | } | |
| 1989 | 2335 | |
| 1990 | /* make a first pass over the memory map and track blocks with hardcoded pointers */ | |
| 1991 | /* we do this to make sure they are found by space_find_backing_memory first */ | |
| 1992 | for (entry = space->map->m_entrylist; entry != NULL; entry = entry->m_next) | |
| 1993 | if (entry->m_memory != NULL) | |
| 1994 | block_allocate(space, entry->m_bytestart, entry->m_byteend, entry->m_memory); | |
| 2336 | UINT16 *address_space::install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_device_func rhandler, const char *rname, write16_device_func whandler, const char *wname, UINT64 unitmask) | |
| 2337 | { | |
| 2338 | install_legacy_handler(device, addrstart, addrend, addrmask, addrmirror, rhandler, rname, unitmask); | |
| 2339 | return install_legacy_handler(device, addrstart, addrend, addrmask, addrmirror, whandler, wname, unitmask); | |
| 2340 | } | |
| 1995 | 2341 | |
| 1996 | /* loop over all blocks just allocated and assign pointers from them */ | |
| 1997 | for (memblock = memdata->memory_block_list; memblock != prev_memblock_head; memblock = memblock->next) | |
| 1998 | unassigned = block_assign_intersecting(space, memblock->bytestart, memblock->byteend, memblock->data); | |
| 1999 | 2342 | |
| 2000 | /* if we don't have an unassigned pointer yet, try to find one */ | |
| 2001 | if (unassigned == NULL) | |
| 2002 | unassigned = block_assign_intersecting(space, ~0, 0, NULL); | |
| 2343 | //------------------------------------------------- | |
| 2344 | // install_handler - install 32-bit read/write | |
| 2345 | // delegate handlers for the space | |
| 2346 | //------------------------------------------------- | |
| 2003 | 2347 | |
| 2004 | /* loop until we've assigned all memory in this space */ | |
| 2005 | while (unassigned != NULL) | |
| 2006 | { | |
| 2007 | offs_t curbytestart, curbyteend; | |
| 2008 | int changed; | |
| 2009 | void *block; | |
| 2348 | UINT32 *address_space::install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_delegate handler, UINT64 unitmask) | |
| 2349 | { | |
| 2350 | UINT32 entry = read().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2351 | read().handler_read(entry).set_delegate(handler, unitmask); | |
| 2352 | generate_memdump(machine); | |
| 2353 | return reinterpret_cast<UINT32 *>(find_backing_memory(addrstart, addrend)); | |
| 2354 | } | |
| 2010 | 2355 | |
| 2011 | /* work in MEMORY_BLOCK_CHUNK-sized chunks */ | |
| 2012 | offs_t curblockstart = unassigned->m_bytestart / MEMORY_BLOCK_CHUNK; | |
| 2013 | offs_t curblockend = unassigned->m_byteend / MEMORY_BLOCK_CHUNK; | |
| 2356 | UINT32 *address_space::install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write32_delegate handler, UINT64 unitmask) | |
| 2357 | { | |
| 2358 | UINT32 entry = write().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2359 | write().handler_write(entry).set_delegate(handler, unitmask); | |
| 2360 | generate_memdump(machine); | |
| 2361 | return reinterpret_cast<UINT32 *>(find_backing_memory(addrstart, addrend)); | |
| 2362 | } | |
| 2014 | 2363 | |
| 2015 | /* loop while we keep finding unassigned blocks in neighboring MEMORY_BLOCK_CHUNK chunks */ | |
| 2016 | do | |
| 2017 | { | |
| 2018 | changed = FALSE; | |
| 2364 | UINT32 *address_space::install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_delegate rhandler, write32_delegate whandler, UINT64 unitmask) | |
| 2365 | { | |
| 2366 | install_handler(addrstart, addrend, addrmask, addrmirror, rhandler, unitmask); | |
| 2367 | return install_handler(addrstart, addrend, addrmask, addrmirror, whandler, unitmask); | |
| 2368 | } | |
| 2019 | 2369 | |
| 2020 | /* scan for unmapped blocks in the adjusted map */ | |
| 2021 | for (entry = space->map->m_entrylist; entry != NULL; entry = entry->m_next) | |
| 2022 | if (entry->m_memory == NULL && entry != unassigned && space_needs_backing_store(space, entry)) | |
| 2023 | { | |
| 2024 | offs_t blockstart, blockend; | |
| 2025 | 2370 | |
| 2026 | /* get block start/end blocks for this block */ | |
| 2027 | blockstart = entry->m_bytestart / MEMORY_BLOCK_CHUNK; | |
| 2028 | blockend = entry->m_byteend / MEMORY_BLOCK_CHUNK; | |
| 2371 | //------------------------------------------------- | |
| 2372 | // install_legacy_handler - install 32-bit read/ | |
| 2373 | // write legacy address space handlers for the | |
| 2374 | // space | |
| 2375 | //------------------------------------------------- | |
| 2029 | 2376 | |
| 2030 | /* if we intersect or are adjacent, adjust the start/end */ | |
| 2031 | if (blockstart <= curblockend + 1 && blockend >= curblockstart - 1) | |
| 2032 | { | |
| 2033 | if (blockstart < curblockstart) | |
| 2034 | curblockstart = blockstart, changed = TRUE; | |
| 2035 | if (blockend > curblockend) | |
| 2036 | curblockend = blockend, changed = TRUE; | |
| 2037 | } | |
| 2038 | } | |
| 2039 | } while (changed); | |
| 2377 | UINT32 *address_space::install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_space_func rhandler, const char *rname, UINT64 unitmask) | |
| 2378 | { | |
| 2379 | UINT32 entry = read().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2380 | read().handler_read(entry).set_legacy_func(*this, rhandler, rname, unitmask); | |
| 2381 | generate_memdump(machine); | |
| 2382 | return reinterpret_cast<UINT32 *>(find_backing_memory(addrstart, addrend)); | |
| 2383 | } | |
| 2040 | 2384 | |
| 2041 | /* we now have a block to allocate; do it */ | |
| 2042 | curbytestart = curblockstart * MEMORY_BLOCK_CHUNK; | |
| 2043 | curbyteend = curblockend * MEMORY_BLOCK_CHUNK + (MEMORY_BLOCK_CHUNK - 1); | |
| 2044 | block = block_allocate(space, curbytestart, curbyteend, NULL); | |
| 2385 | UINT32 *address_space::install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write32_space_func whandler, const char *wname, UINT64 unitmask) | |
| 2386 | { | |
| 2387 | UINT32 entry = write().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2388 | write().handler_write(entry).set_legacy_func(*this, whandler, wname, unitmask); | |
| 2389 | generate_memdump(machine); | |
| 2390 | return reinterpret_cast<UINT32 *>(find_backing_memory(addrstart, addrend)); | |
| 2391 | } | |
| 2045 | 2392 | |
| 2046 | /* assign memory that intersected the new block */ | |
| 2047 | unassigned = block_assign_intersecting(space, curbytestart, curbyteend, (UINT8 *)block); | |
| 2048 | } | |
| 2049 | } | |
| 2393 | UINT32 *address_space::install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_space_func rhandler, const char *rname, write32_space_func whandler, const char *wname, UINT64 unitmask) | |
| 2394 | { | |
| 2395 | install_legacy_handler(addrstart, addrend, addrmask, addrmirror, rhandler, rname, unitmask); | |
| 2396 | return install_legacy_handler(addrstart, addrend, addrmask, addrmirror, whandler, wname, unitmask); | |
| 2050 | 2397 | } |
| 2051 | 2398 | |
| 2052 | 2399 | |
| 2053 | /*------------------------------------------------- | |
| 2054 | memory_init_locate - find all the requested | |
| 2055 | pointers into the final allocated memory | |
| 2056 | -------------------------------------------------*/ | |
| 2400 | //------------------------------------------------- | |
| 2401 | // install_legacy_handler - install 32-bit read/ | |
| 2402 | // write legacy device handlers for the space | |
| 2403 | //------------------------------------------------- | |
| 2057 | 2404 | |
| 2058 | s | |
| 2405 | UINT32 *address_space::install_legacy_handler(device_t &dev | |
| 2059 | 2406 | { |
| 2060 | memory_private *memdata = machine->memory_data; | |
| 2061 | address_space *space; | |
| 2062 | bank_info *bank; | |
| 2407 | UINT32 entry = read().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2408 | read().handler_read(entry).set_legacy_func(device, rhandler, rname, unitmask); | |
| 2409 | generate_memdump(machine); | |
| 2410 | return reinterpret_cast<UINT32 *>(find_backing_memory(addrstart, addrend)); | |
| 2411 | } | |
| 2063 | 2412 | |
| 2064 | /* loop over valid address spaces */ | |
| 2065 | for (space = (address_space *)memdata->spacelist; space != NULL; space = (address_space *)space->next) | |
| 2066 | { | |
| 2067 | const address_map_entry *entry; | |
| 2413 | UINT32 *address_space::install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write32_device_func whandler, const char *wname, UINT64 unitmask) | |
| 2414 | { | |
| 2415 | UINT32 entry = write().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2416 | write().handler_write(entry).set_legacy_func(device, whandler, wname, unitmask); | |
| 2417 | generate_memdump(machine); | |
| 2418 | return reinterpret_cast<UINT32 *>(find_backing_memory(addrstart, addrend)); | |
| 2419 | } | |
| 2068 | 2420 | |
| 2069 | /* fill in base/size entries */ | |
| 2070 | for (entry = space->map->m_entrylist; entry != NULL; entry = entry->m_next) | |
| 2071 | { | |
| 2072 | if (entry->m_baseptr != NULL) | |
| 2073 | *entry->m_baseptr = entry->m_memory; | |
| 2074 | if (entry->m_baseptroffs_plus1 != 0) | |
| 2075 | *(void **)(reinterpret_cast<UINT8 *>(machine->driver_data<void>()) + entry->m_baseptroffs_plus1 - 1) = entry->m_memory; | |
| 2076 | if (entry->m_genbaseptroffs_plus1 != 0) | |
| 2077 | *(void **)((UINT8 *)&machine->generic + entry->m_genbaseptroffs_plus1 - 1) = entry->m_memory; | |
| 2078 | if (entry->m_sizeptr != NULL) | |
| 2079 | *entry->m_sizeptr = entry->m_byteend - entry->m_bytestart + 1; | |
| 2080 | if (entry->m_sizeptroffs_plus1 != 0) | |
| 2081 | *(size_t *)(reinterpret_cast<UINT8 *>(machine->driver_data<void>()) + entry->m_sizeptroffs_plus1 - 1) = entry->m_byteend - entry->m_bytestart + 1; | |
| 2082 | if (entry->m_gensizeptroffs_plus1 != 0) | |
| 2083 | *(size_t *)((UINT8 *)&machine->generic + entry->m_gensizeptroffs_plus1 - 1) = entry->m_byteend - entry->m_bytestart + 1; | |
| 2084 | } | |
| 2085 | } | |
| 2421 | UINT32 *address_space::install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_device_func rhandler, const char *rname, write32_device_func whandler, const char *wname, UINT64 unitmask) | |
| 2422 | { | |
| 2423 | install_legacy_handler(device, addrstart, addrend, addrmask, addrmirror, rhandler, rname, unitmask); | |
| 2424 | return install_legacy_handler(device, addrstart, addrend, addrmask, addrmirror, whandler, wname, unitmask); | |
| 2425 | } | |
| 2086 | 2426 | |
| 2087 | /* once this is done, find the starting bases for the banks */ | |
| 2088 | for (bank = memdata->banklist; bank != NULL; bank = bank->next) | |
| 2089 | { | |
| 2090 | address_map_entry *entry; | |
| 2091 | bank_reference *ref; | |
| 2092 | int foundit = FALSE; | |
| 2093 | 2427 | |
| 2094 | /* set the initial bank pointer */ | |
| 2095 | for (ref = bank->reflist; !foundit && ref != NULL; ref = ref->next) | |
| 2096 | for (entry = ref->space->map->m_entrylist; entry != NULL; entry = entry->m_next) | |
| 2097 | if (entry->m_bytestart == bank->bytestart && entry->m_memory != NULL) | |
| 2098 | { | |
| 2099 | memdata->bank_ptr[bank->index] = (UINT8 *)entry->m_memory; | |
| 2100 | foundit = TRUE; | |
| 2101 | VPRINTF(("assigned bank '%s' pointer to memory from range %08X-%08X [%p]\n", bank->tag, entry->m_addrstart, entry->m_addrend, entry->m_memory)); | |
| 2102 | break; | |
| 2103 | } | |
| 2428 | //------------------------------------------------- | |
| 2429 | // install_handler64 - install 64-bit read/write | |
| 2430 | // delegate handlers for the space | |
| 2431 | //------------------------------------------------- | |
| 2104 | 2432 | |
| 2105 | /* if the entry was set ahead of time, override the automatically found pointer */ | |
| 2106 | if (bank->tag[0] != '~' && bank->curentry != MAX_BANK_ENTRIES) | |
| 2107 | memdata->bank_ptr[bank->index] = (UINT8 *)bank->entry[bank->curentry]; | |
| 2108 | } | |
| 2433 | UINT64 *address_space::install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_delegate handler, UINT64 unitmask) | |
| 2434 | { | |
| 2435 | UINT32 entry = read().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2436 | read().handler_read(entry).set_delegate(handler, unitmask); | |
| 2437 | generate_memdump(machine); | |
| 2438 | return reinterpret_cast<UINT64 *>(find_backing_memory(addrstart, addrend)); | |
| 2439 | } | |
| 2109 | 2440 | |
| 2110 | /* request a callback to fix up the banks when done */ | |
| 2111 | state_save_register_postload(machine, bank_reattach, NULL); | |
| 2441 | UINT64 *address_space::install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write64_delegate handler, UINT64 unitmask) | |
| 2442 | { | |
| 2443 | UINT32 entry = write().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2444 | write().handler_write(entry).set_delegate(handler, unitmask); | |
| 2445 | generate_memdump(machine); | |
| 2446 | return reinterpret_cast<UINT64 *>(find_backing_memory(addrstart, addrend)); | |
| 2112 | 2447 | } |
| 2113 | 2448 | |
| 2449 | UINT64 *address_space::install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_delegate rhandler, write64_delegate whandler, UINT64 unitmask) | |
| 2450 | { | |
| 2451 | install_handler(addrstart, addrend, addrmask, addrmirror, rhandler, unitmask); | |
| 2452 | return install_handler(addrstart, addrend, addrmask, addrmirror, whandler, unitmask); | |
| 2453 | } | |
| 2114 | 2454 | |
| 2115 | /*------------------------------------------------- | |
| 2116 | memory_exit - free memory | |
| 2117 | -------------------------------------------------*/ | |
| 2118 | 2455 | |
| 2119 | static void memory_exit(running_machine &machine) | |
| 2456 | //------------------------------------------------- | |
| 2457 | // install_legacy_handler - install 64-bit read/ | |
| 2458 | // write legacy address space handlers for the | |
| 2459 | // space | |
| 2460 | //------------------------------------------------- | |
| 2461 | ||
| 2462 | UINT64 *address_space::install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_space_func rhandler, const char *rname, UINT64 unitmask) | |
| 2120 | 2463 | { |
| 2121 | memory_private *memdata = machine.memory_data; | |
| 2122 | address_space *space; | |
| 2464 | UINT32 entry = read().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2465 | read().handler_read(entry).set_legacy_func(*this, rhandler, rname, unitmask); | |
| 2466 | generate_memdump(machine); | |
| 2467 | return reinterpret_cast<UINT64 *>(find_backing_memory(addrstart, addrend)); | |
| 2468 | } | |
| 2123 | 2469 | |
| 2124 | /* free all the address spaces and tables */ | |
| 2125 | for (space = (address_space *)memdata->spacelist; space != NULL; space = space->next) | |
| 2126 | { | |
| 2127 | /* free the address map and tables */ | |
| 2128 | global_free(space->map); | |
| 2129 | } | |
| 2470 | UINT64 *address_space::install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write64_space_func whandler, const char *wname, UINT64 unitmask) | |
| 2471 | { | |
| 2472 | UINT32 entry = write().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2473 | write().handler_write(entry).set_legacy_func(*this, whandler, wname, unitmask); | |
| 2474 | generate_memdump(machine); | |
| 2475 | return reinterpret_cast<UINT64 *>(find_backing_memory(addrstart, addrend)); | |
| 2130 | 2476 | } |
| 2131 | 2477 | |
| 2478 | UINT64 *address_space::install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_space_func rhandler, const char *rname, write64_space_func whandler, const char *wname, UINT64 unitmask) | |
| 2479 | { | |
| 2480 | install_legacy_handler(addrstart, addrend, addrmask, addrmirror, rhandler, rname, unitmask); | |
| 2481 | return install_legacy_handler(addrstart, addrend, addrmask, addrmirror, whandler, wname, unitmask); | |
| 2482 | } | |
| 2132 | 2483 | |
| 2133 | 2484 | |
| 2134 | /*************************************************************************** | |
| 2135 | MEMORY MAPPING HELPERS | |
| 2136 | ***************************************************************************/ | |
| 2485 | //------------------------------------------------- | |
| 2486 | // install_legacy_handler - install 64-bit read/ | |
| 2487 | // write legacy device handlers for the space | |
| 2488 | //------------------------------------------------- | |
| 2137 | 2489 | |
| 2138 | /*------------------------------------------------- | |
| 2139 | space_map_range - maps a range of addresses | |
| 2140 | to the specified handler within an address | |
| 2141 | space | |
| 2142 | -------------------------------------------------*/ | |
| 2490 | UINT64 *address_space::install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_device_func rhandler, const char *rname, UINT64 unitmask) | |
| 2491 | { | |
| 2492 | UINT32 entry = read().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2493 | read().handler_read(entry).set_legacy_func(device, rhandler, rname, unitmask); | |
| 2494 | generate_memdump(machine); | |
| 2495 | return reinterpret_cast<UINT64 *>(find_backing_memory(addrstart, addrend)); | |
| 2496 | } | |
| 2143 | 2497 | |
| 2144 | ||
| 2498 | UINT64 * | |
| 2145 | 2499 | { |
| 2146 | address_table *tabledata = (readorwrite == ROW_WRITE) ? &space->write : &space->read; | |
| 2147 | int reset_write = (space->writelookup == space->write.table); | |
| 2148 | int reset_read = (space->readlookup == space->read.table); | |
| 2149 | offs_t bytestart, byteend, bytemask, bytemirror; | |
| 2150 | UINT8 entry; | |
| 2500 | UINT32 entry = write().map_range(addrstart, addrend, addrmask, addrmirror); | |
| 2501 | write().handler_write(entry).set_legacy_func(device, whandler, wname, unitmask); | |
| 2502 | generate_memdump(machine); | |
| 2503 | return reinterpret_cast<UINT64 *>(find_backing_memory(addrstart, addrend)); | |
| 2504 | } | |
| 2151 | 2505 | |
| 2152 | /* sanity checks */ | |
| 2153 | assert(space != NULL); | |
| 2154 | assert(handlerbits == 8 || handlerbits == 16 || handlerbits == 32 || handlerbits == 64); | |
| 2506 | UINT64 *address_space::install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_device_func rhandler, const char *rname, write64_device_func whandler, const char *wname, UINT64 unitmask) | |
| 2507 | { | |
| 2508 | install_legacy_handler(device, addrstart, addrend, addrmask, addrmirror, rhandler, rname, unitmask); | |
| 2509 | return install_legacy_handler(device, addrstart, addrend, addrmask, addrmirror, whandler, wname, unitmask); | |
| 2510 | } | |
| 2155 | 2511 | |
| 2156 | /* adjust the incoming addresses */ | |
| 2157 | bytestart = addrstart; | |
| 2158 | byteend = addrend; | |
| 2159 | bytemirror = addrmirror; | |
| 2160 | bytemask = addrmask; | |
| 2161 | adjust_addresses(space, &bytestart, &byteend, &bytemask, &bytemirror); | |
| 2162 | 2512 | |
| 2163 | /* validity checks */ | |
| 2164 | assert_always(!HANDLER_IS_ROM(handler), "space_map_range called with ROM after initialization"); | |
| 2165 | assert_always(!HANDLER_IS_RAM(handler), "space_map_range called with RAM after initialization"); | |
| 2166 | assert_always(addrstart <= addrend, "space_map_range called with start greater than end"); | |
| 2167 | assert_always(handlerbits <= space->dbits, "space_map_range called with handlers larger than the address space"); | |
| 2168 | assert_always((bytestart & (space->dbits / 8 - 1)) == 0, "space_map_range called with misaligned start address"); | |
| 2169 | assert_always((byteend & (space->dbits / 8 - 1)) == (space->dbits / 8 - 1), "space_map_range called with misaligned end address"); | |
| 2170 | 2513 | |
| 2171 | /* get the final handler index */ | |
| 2172 | entry = table_assign_handler(space, tabledata->handlers, object, handler, handler_name, bytestart, byteend, bytemask); | |
| 2514 | //************************************************************************** | |
| 2515 | // INTERNAL INITIALIZATION | |
| 2516 | //************************************************************************** | |
| 2173 | 2517 | |
| 2174 | /* fix up the handler if a stub is required */ | |
| 2175 | if (handlerbits != space->dbits) | |
| 2176 | table_compute_subhandler(tabledata->handlers, entry, readorwrite, space->dbits, space->endianness, handlerbits, handlerunitmask); | |
| 2177 | 2518 | |
| 2178 | /* populate it */ | |
| 2179 | table_populate_range_mirrored(space, tabledata, bytestart, byteend, bytemirror, entry); | |
| 2519 | //************************************************************************** | |
| 2520 | // MEMORY MAPPING HELPERS | |
| 2521 | //************************************************************************** | |
| 2180 | 2522 | |
| 2181 | /* reset read/write pointers if necessary (could have moved due to realloc) */ | |
| 2182 | if (reset_write) | |
| 2183 | space->writelookup = space->write.table; | |
| 2184 | if (reset_read) | |
| 2185 | space->readlookup = space->read.table; | |
| 2523 | //------------------------------------------------- | |
| 2524 | // find_backing_memory - return a pointer to | |
| 2525 | // the base of RAM associated with the given | |
| 2526 | // device and offset | |
| 2527 | //------------------------------------------------- | |
| 2186 | 2528 | |
| 2187 | /* recompute any direct access on this space if it is a read modification */ | |
| 2188 | if (readorwrite == ROW_READ && entry == space->direct.entry) | |
| 2189 | { | |
| 2190 | space->direct.entry = STATIC_UNMAP; | |
| 2191 | space->direct.bytestart = 1; | |
| 2192 | space->direct.byteend = 0; | |
| 2193 | } | |
| 2194 | } | |
| 2195 | ||
| 2196 | ||
| 2197 | /*------------------------------------------------- | |
| 2198 | space_find_backing_memory - return a pointer to | |
| 2199 | the base of RAM associated with the given | |
| 2200 | device and offset | |
| 2201 | -------------------------------------------------*/ | |
| 2202 | ||
| 2203 | static void *space_find_backing_memory(const address_space *space, offs_t addrstart, offs_t addrend) | |
| 2529 | void *address_space::find_backing_memory(offs_t addrstart, offs_t addrend) | |
| 2204 | 2530 | { |
| 2205 | offs_t bytestart = memory_address_to_byte(space, addrstart); | |
| 2206 | offs_t byteend = memory_address_to_byte_end(space, addrend); | |
| 2207 | memory_private *memdata = space->machine->memory_data; | |
| 2208 | address_map_entry *entry; | |
| 2209 | memory_block *block; | |
| 2531 | offs_t bytestart = address_to_byte(addrstart); | |
| 2532 | offs_t byteend = address_to_byte_end(addrend); | |
| 2210 | 2533 | |
| 2211 | VPRINTF(("space | |
| 2534 | VPRINTF(("address_space::find_backing_memory('%s',%s,%08X-%08X) -> ", m_d | |
| 2212 | 2535 | |
| 2213 | /* look in the address map first */ | |
| 2214 | for (entry = space->map->m_entrylist; entry != NULL; entry = entry->m_next) | |
| 2536 | // look in the address map first | |
| 2537 | for (address_map_entry *entry = m_map->m_entrylist.first(); entry != NULL; entry = entry->next()) | |
| 2215 | 2538 | { |
| 2216 | 2539 | offs_t maskstart = bytestart & entry->m_bytemask; |
| 2217 | 2540 | offs_t maskend = byteend & entry->m_bytemask; |
| r8806 | r8807 | |
| 2222 | 2545 | } |
| 2223 | 2546 | } |
| 2224 | 2547 | |
| 2225 | /* if not found there, look in the allocated blocks */ | |
| 2226 | for (block = memdata->memory_block_list; block != NULL; block = block->next) | |
| 2227 | if (block->space == space && block->bytestart <= bytestart && block->byteend >= byteend) | |
| 2548 | // if not found there, look in the allocated blocks | |
| 2549 | for (memory_block *block = m_machine.memory_data->blocklist.first(); block != NULL; block = block->next()) | |
| 2550 | if (block->contains(*this, bytestart, byteend)) | |
| 2228 | 2551 | { |
| 2229 | VPRINTF(("found in allocated memory block %08X-%08X [%p]\n", block->bytestart, block->byteend, block->data + (bytestart - block->bytestart))); | |
| 2230 | return block->data + bytestart - block->bytestart; | |
| 2552 | VPRINTF(("found in allocated memory block %08X-%08X [%p]\n", block->bytestart(), block->byteend(), block->data() + (bytestart - block->bytestart()))); | |
| 2553 | return block->data() + bytestart - block->bytestart(); | |
| 2231 | 2554 | } |
| 2232 | 2555 | |
| 2233 | 2556 | VPRINTF(("did not find\n")); |
| r8806 | r8807 | |
| 2235 | 2558 | } |
| 2236 | 2559 | |
| 2237 | 2560 | |
| 2238 | /*------------------------------------------------- | |
| 2239 | space_needs_backing_store - return whether a | |
| 2240 | given memory map entry implies the need of | |
| 2241 | allocating and registering memory | |
| 2242 | -------------------------------------------------*/ | |
| 2561 | //------------------------------------------------- | |
| 2562 | // space_needs_backing_store - return whether a | |
| 2563 | // given memory map entry implies the need of | |
| 2564 | // allocating and registering memory | |
| 2565 | //------------------------------------------------- | |
| 2243 | 2566 | |
| 2244 | ||
| 2567 | bool | |
| 2245 | 2568 | { |
| 2246 | / | |
| 2569 | // if we are asked to provide a base pointer, then yes, we do need backing | |
| 2247 | 2570 | if (entry->m_baseptr != NULL || entry->m_baseptroffs_plus1 != 0 || entry->m_genbaseptroffs_plus1 != 0) |
| 2248 | return | |
| 2571 | return true; | |
| 2249 | 2572 | |
| 2250 | /* if we're writing to any sort of bank or RAM, then yes, we do need backing */ | |
| 2251 | if (entry->m_write.type == AMH_BANK || entry->m_write.type == AMH_RAM) | |
| 2252 | return TRUE; | |
| 2573 | // if we're writing to any sort of bank or RAM, then yes, we do need backing | |
| 2574 | if (entry->m_write.m_type == AMH_BANK || entry->m_write.m_type == AMH_RAM) | |
| 2575 | return true; | |
| 2253 | 2576 | |
| 2254 | /* if we're reading from RAM or from ROM outside of address space 0 or its region, then yes, we do need backing */ | |
| 2255 | const region_info *region = space->machine->region(space->cpu->tag()); | |
| 2256 | if (entry->m_read.type == AMH_RAM || | |
| 2257 | (entry->m_read.type == AMH_ROM && (space->spacenum != ADDRESS_SPACE_0 || region == NULL || entry->m_addrstart >= region->bytes()))) | |
| 2258 | return TRUE; | |
| 2577 | // if we're reading from RAM or from ROM outside of address space 0 or its region, then yes, we do need backing | |
| 2578 | const region_info *region = m_machine.region(m_device.tag()); | |
| 2579 | if (entry->m_read.m_type == AMH_RAM || | |
| 2580 | (entry->m_read.m_type == AMH_ROM && (m_spacenum != ADDRESS_SPACE_0 || region == NULL || entry->m_addrstart >= region->bytes()))) | |
| 2581 | return true; | |
| 2259 | 2582 | |
| 2260 | /* all other cases don't need backing */ | |
| 2261 | return FALSE; | |
| 2583 | // all other cases don't need backing | |
| 2584 | return false; | |
| 2262 | 2585 | } |
| 2263 | 2586 | |
| 2264 | 2587 | |
| 2265 | 2588 | |
| 2266 | /*************************************************************************** | |
| 2267 | BANKING HELPERS | |
| 2268 | ***************************************************************************/ | |
| 2589 | //************************************************************************** | |
| 2590 | // BANKING HELPERS | |
| 2591 | //************************************************************************** | |
| 2269 | 2592 | |
| 2270 | /*------------------------------------------------- | |
| 2271 | bank_find_or_allocate - allocate a new | |
| 2272 | bank, or find an existing one, and return the | |
| 2273 | read/write handler | |
| 2274 | -------------------------------------------------*/ | |
| 2593 | //------------------------------------------------- | |
| 2594 | // bank_find_or_allocate - allocate a new | |
| 2595 | // bank, or find an existing one, and return the | |
| 2596 | // read/write handler | |
| 2597 | //------------------------------------------------- | |
| 2275 | 2598 | |
| 2276 | s | |
| 2599 | memory_bank &address_spa | |
| 2277 | 2600 | { |
| 2278 | memory_private *memdata = space->machine->memory_data; | |
| 2601 | memory_private *memdata = m_machine.memory_data; | |
| 2602 | ||
| 2603 | // adjust the addresses, handling mirrors and such | |
| 2279 | 2604 | offs_t bytemirror = addrmirror; |
| 2280 | 2605 | offs_t bytestart = addrstart; |
| 2281 | 2606 | offs_t bytemask = addrmask; |
| 2282 | 2607 | offs_t byteend = addrend; |
| 2283 | bank_info *bank = NULL; | |
| 2284 | char temptag[10]; | |
| 2285 | char name[30]; | |
| 2608 | adjust_addresses(bytestart, byteend, bytemask, bytemirror); | |
| 2286 | 2609 | |
| 2287 | /* adjust the addresses, handling mirrors and such */ | |
| 2288 | adjust_addresses(space, &bytestart, &byteend, &bytemask, &bytemirror); | |
| 2289 | ||
| 2290 | /* if this bank is named, look it up */ | |
| 2610 | // if this bank is named, look it up | |
| 2611 | memory_bank *bank = NULL; | |
| 2291 | 2612 | if (tag != NULL) |
| 2292 | 2613 | bank = memdata->bankmap.find_hash_only(tag); |
| 2293 | 2614 | |
| 2294 | / | |
| 2615 | // else try to find an exact match | |
| 2295 | 2616 | else |
| 2296 | { | |
| 2297 | for (bank = memdata->banklist; bank != NULL; bank = bank->next) | |
| 2298 | if (bank->tag[0] == '~' && bank->bytestart == bytestart && bank->byteend == byteend && bank->reflist != NULL && bank->reflist->space == space) | |
| 2617 | for (bank = memdata->banklist.first(); bank != NULL; bank = bank->next()) | |
| 2618 | if (bank->anonymous() && bank->references_space(*this, ROW_READWRITE) && bank->matches_exactly(bytestart, byteend)) | |
| 2299 | 2619 | break; |
| 2300 | } | |
| 2301 | 2620 | |
| 2302 | / | |
| 2621 | // if we don't have a bank yet, find a free one | |
| 2303 | 2622 | if (bank == NULL) |
| 2304 | 2623 | { |
| 2624 | // handle failure | |
| 2305 | 2625 | int banknum = memdata->banknext++; |
| 2306 | ||
| 2307 | /* handle failure */ | |
| 2308 | 2626 | if (banknum > STATIC_BANKMAX) |
| 2309 | 2627 | { |
| 2310 | 2628 | if (tag != NULL) |
| 2311 | fatalerror("Unable to allocate new bank '%s'", tag); | |
| 2629 | throw emu_fatalerror("Unable to allocate new bank '%s'", tag); | |
| 2312 | 2630 | else |
| 2313 | fatalerror("Unable to allocate bank for RAM/ROM area %X-%X\n", bytestart, byteend); | |
| 2631 | throw emu_fatalerror("Unable to allocate bank for RAM/ROM area %X-%X\n", bytestart, byteend); | |
| 2314 | 2632 | } |
| 2315 | 2633 | |
| 2316 | /* generate an internal tag if we don't have one */ | |
| 2317 | if (tag == NULL) | |
| 2318 | { | |
| 2319 | sprintf(temptag, "~%d~", banknum); | |
| 2320 | tag = temptag; | |
| 2321 | sprintf(name, "Internal bank #%d", banknum); | |
| 2322 | } | |
| 2323 | else | |
| 2324 | sprintf(name, "Bank '%s'", tag); | |
| 2634 | // allocate the bank | |
| 2635 | bank = auto_alloc(&m_machine, memory_bank(*this, banknum, bytestart, byteend, tag)); | |
| 2636 | memdata->banklist.append(*bank); | |
| 2325 | 2637 | |
| 2326 | /* allocate the bank */ | |
| 2327 | bank = (bank_info *)auto_alloc_array_clear(space->machine, UINT8, sizeof(bank_info) + strlen(tag) + 1 + strlen(name)); | |
| 2638 | // for named banks, add to the map and register for save states | |
| 2639 | if (tag != NULL) | |
| 2640 | memdata->bankmap.add_unique_hash(tag, bank, false); | |
| 2641 | } | |
| 2328 | 2642 | |
| 2329 | /* populate it */ | |
| 2330 | bank->index = banknum; | |
| 2331 | bank->handler = (void *)(FPTR)(STATIC_BANK1 + banknum - 1); | |
| 2332 | bank->bytestart = bytestart; | |
| 2333 | bank->byteend = byteend; | |
| 2334 | bank->curentry = MAX_BANK_ENTRIES; | |
| 2335 | strcpy(bank->tag, tag); | |
| 2336 | bank->name = bank->tag + strlen(tag) + 1; | |
| 2337 | strcpy(bank->name, name); | |
| 2643 | // add a reference for this space | |
| 2644 | bank->add_reference(*this, readorwrite); | |
| 2645 | return *bank; | |
| 2646 | } | |
| 2338 | 2647 | |
| 2339 | /* add us to the list */ | |
| 2340 | bank->next = memdata->banklist; | |
| 2341 | memdata->banklist = bank; | |
| 2342 | 2648 | |
| 2343 | /* for named banks, add to the map and register for save states */ | |
| 2344 | if (tag[0] != '~') | |
| 2345 | { | |
| 2346 | memdata->bankmap.add_unique_hash(tag, bank, FALSE); | |
| 2347 | if (state_save_registration_allowed(space->machine)) | |
| 2348 | state_save_register_item(space->machine, "memory", bank->tag, 0, bank->curentry); | |
| 2349 | } | |
| 2350 | } | |
| 2351 | 2649 | |
| 2352 | /* update the read/write state for this bank */ | |
| 2353 | if (readorwrite == ROW_READ) | |
| 2354 | bank->read = TRUE; | |
| 2355 | if (readorwrite == ROW_WRITE) | |
| 2356 | bank->write = TRUE; | |
| 2650 | //************************************************************************** | |
| 2651 | // TABLE MANAGEMENT | |
| 2652 | //************************************************************************** | |
| 2357 | 2653 | |
| 2358 | /* add a reference for this space */ | |
| 2359 | add_bank_reference(bank, space); | |
| 2360 | return (genf *)bank->handler; | |
| 2654 | //------------------------------------------------- | |
| 2655 | // address_table - constructor | |
| 2656 | //------------------------------------------------- | |
| 2657 | ||
| 2658 | address_table::address_table(address_space &space, bool large) | |
| 2659 | : m_table(auto_alloc_array(&space.m_machine, UINT8, 1 << LEVEL1_BITS)), | |
| 2660 | m_live_lookup(m_table), | |
| 2661 | m_space(space), | |
| 2662 | m_large(large), | |
| 2663 | m_subtable(auto_alloc_array(&space.m_machine, subtable_data, SUBTABLE_COUNT)), | |
| 2664 | m_subtable_alloc(0) | |
| 2665 | { | |
| 2666 | // make our static table all watchpoints | |
| 2667 | if (s_watchpoint_table[0] != STATIC_WATCHPOINT) | |
| 2668 | memset(s_watchpoint_table, STATIC_WATCHPOINT, sizeof(s_watchpoint_table)); | |
| 2669 | ||
| 2670 | // initialize everything to unmapped | |
| 2671 | memset(m_table, STATIC_UNMAP, 1 << LEVEL1_BITS); | |
| 2361 | 2672 | } |
| 2362 | 2673 | |
| 2363 | 2674 | |
| 2364 | /*------------------------------------------------- | |
| 2365 | bank_reattach - reconnect banks after a load | |
| 2366 | -------------------------------------------------*/ | |
| 2675 | //------------------------------------------------- | |
| 2676 | // ~address_table - destructor | |
| 2677 | //------------------------------------------------- | |
| 2367 | 2678 | |
| 2368 | sta | |
| 2679 | address_ta | |
| 2369 | 2680 | { |
| 2370 | memory_private *memdata = machine->memory_data; | |
| 2371 | bank_info *bank; | |
| 2372 | ||
| 2373 | /* once this is done, find the starting bases for the banks */ | |
| 2374 | for (bank = memdata->banklist; bank != NULL; bank = bank->next) | |
| 2375 | if (bank->tag[0] != '~') | |
| 2376 | { | |
| 2377 | /* if this entry has a changed entry, set the appropriate pointer */ | |
| 2378 | if (bank->curentry != MAX_BANK_ENTRIES) | |
| 2379 | memdata->bank_ptr[bank->index] = (UINT8 *)bank->entry[bank->curentry]; | |
| 2380 | } | |
| 2681 | auto_free(&m_space.m_machine, m_table); | |
| 2682 | auto_free(&m_space.m_machine, m_subtable); | |
| 2381 | 2683 | } |
| 2382 | 2684 | |
| 2383 | 2685 | |
| 2686 | //------------------------------------------------- | |
| 2687 | // map_range - finds an approprite handler entry | |
| 2688 | // and requests to populate the address map with | |
| 2689 | // it | |
| 2690 | //------------------------------------------------- | |
| 2384 | 2691 | |
| 2385 | /*************************************************************************** | |
| 2386 | TABLE MANAGEMENT | |
| 2387 | ***************************************************************************/ | |
| 2388 | ||
| 2389 | /*------------------------------------------------- | |
| 2390 | table_assign_handler - finds the index of a | |
| 2391 | handler, or allocates a new one as necessary | |
| 2392 | -------------------------------------------------*/ | |
| 2393 | ||
| 2394 | static UINT8 table_assign_handler(const address_space *space, handler_data **table, void *object, genf *handler, const char *handler_name, offs_t bytestart, offs_t byteend, offs_t bytemask) | |
| 2692 | UINT8 address_table::map_range(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, UINT8 staticentry) | |
| 2395 | 2693 | { |
| 2396 | int entry; | |
| 2694 | // convert addresses to bytes | |
| 2695 | offs_t bytestart = addrstart; | |
| 2696 | offs_t byteend = addrend; | |
| 2697 | offs_t bytemask = addrmask; | |
| 2698 | offs_t bytemirror = addrmirror; | |
| 2699 | m_space.adjust_addresses(bytestart, byteend, bytemask, bytemirror); | |
| 2397 | 2700 | |
| 2398 | /* all static handlers are hardcoded */ | |
| 2399 | if (HANDLER_IS_STATIC(handler)) | |
| 2400 | { | |
| 2401 | entry = (FPTR)handler; | |
| 2701 | // validity checks | |
| 2702 | assert_always(addrstart <= addrend, "address_table::map_range called with start greater than end"); | |
| 2703 | assert_always((bytestart & (m_space.data_width() / 8 - 1)) == 0, "address_table::map_range called with misaligned start address"); | |
| 2704 | assert_always((byteend & (m_space.data_width() / 8 - 1)) == (m_space.data_width() / 8 - 1), "address_table::map_range called with misaligned end address"); | |
| 2402 | 2705 | |
| 2403 | /* if it is a bank, copy in the relevant information */ | |
| 2404 | if (HANDLER_IS_BANK(handler)) | |
| 2405 | { | |
| 2406 | handler_data *hdata = table[entry]; | |
| 2407 | hdata->bytestart = bytestart; | |
| 2408 | hdata->byteend = byteend; | |
| 2409 | hdata->bytemask = bytemask; | |
| 2410 | hdata->bankbaseptr = &space->machine->memory_data->bank_ptr[entry]; | |
| 2411 | hdata->name = handler_name; | |
| 2412 | } | |
| 2413 | return entry; | |
| 2414 | } | |
| 2415 | ||
| 2416 | /* otherwise, we have to search */ | |
| 2417 | for (entry = STATIC_COUNT; entry < SUBTABLE_BASE; entry++) | |
| 2706 | // if we weren't given an explicit entry, find a free one | |
| 2707 | UINT8 entry = staticentry; | |
| 2708 | if (entry == STATIC_INVALID) | |
| 2418 | 2709 | { |
| 2419 | handler_data *hdata = table[entry]; | |
| 2420 | ||
| 2421 | /* if we hit a NULL hdata, then we need to allocate this one as a new one */ | |
| 2422 | if (hdata->handler.generic == NULL) | |
| 2710 | // two attempts to find an empty | |
| 2711 | for (int attempt = 0; attempt < 2; attempt++) | |
| 2423 | 2712 | { |
| 2424 | hdata->handler.generic = handler; | |
| 2425 | hdata->bytestart = bytestart; | |
| 2426 | hdata->byteend = byteend; | |
| 2427 | hdata->bytemask = bytemask; | |
| 2428 | hdata->name = handler_name; | |
| 2429 | hdata->object = object; | |
| 2430 | return entry; | |
| 2713 | // scan all possible assigned entries for something unpopulated, or for an exact match | |
| 2714 | for (UINT8 scanentry = STATIC_COUNT; scanentry < SUBTABLE_BASE; scanentry++) | |
| 2715 | { | |
| 2716 | handler_entry &curentry = handler(scanentry); | |
| 2717 | ||
| 2718 | // exact match takes precedence, and in fact doesn't need any | |
| 2719 | // further configuration or population | |
| 2720 | if (curentry.matches_exactly(bytestart, byteend, bytemask)) | |
| 2721 | return scanentry; | |
| 2722 | ||
| 2723 | // unpopulated is our second choice | |
| 2724 | if (entry == STATIC_INVALID && !curentry.populated()) | |
| 2725 | entry = scanentry; | |
| 2726 | } | |
| 2727 | ||
| 2728 | // if we didn't find anything, find something to depopulate | |
| 2729 | if (entry != STATIC_INVALID) | |
| 2730 | break; | |
| 2731 | depopulate_unused(); | |
| 2431 | 2732 | } |
| 2432 | 2733 | |
| 2433 | /* if we find a perfect match, return a duplicate entry */ | |
| 2434 | if (hdata->handler.generic == handler && hdata->bytestart == bytestart && hdata->bytemask == bytemask && hdata->object == object) | |
| 2435 | return entry; | |
| 2734 | // if we utterly failed, it's fatal | |
| 2735 | if (entry == STATIC_INVALID) | |
| 2736 | throw emu_fatalerror("Out of handler entries in address table"); | |
| 2436 | 2737 | } |
| 2437 | return 0; | |
| 2438 | } | |
| 2439 | 2738 | |
| 2739 | // configure the entry to our parameters | |
| 2740 | handler_entry &curentry = handler(entry); | |
| 2741 | curentry.configure(bytestart, byteend, bytemask); | |
| 2440 | 2742 | |
| 2441 | /*------------------------------------------------- | |
| 2442 | table_compute_subhandler - compute data for | |
| 2443 | a subhandler | |
| 2444 | -------------------------------------------------*/ | |
| 2445 | ||
| 2446 | static void table_compute_subhandler(handler_data **table, UINT8 entry, read_or_write readorwrite, int spacebits, int spaceendian, int handlerbits, int handlerunitmask) | |
| 2447 | { | |
| 2448 | int maxunits = spacebits / handlerbits; | |
| 2449 | handler_data *hdata = table[entry]; | |
| 2450 | int unitnum; | |
| 2451 | ||
| 2452 | assert_always(!HANDLER_IS_STATIC(entry), "table_compute_subhandler called with static handlers and mismatched data bus widths"); | |
| 2453 | ||
| 2454 | /* copy raw data to the subhandler data */ | |
| 2455 | hdata->subobject = hdata->object; | |
| 2456 | hdata->subhandler = hdata->handler; | |
| 2457 | ||
| 2458 | /* fill in a stub as the real handler */ | |
| 2459 | hdata->object = hdata; | |
| 2460 | hdata->handler = get_stub_handler(readorwrite, spacebits, handlerbits); | |
| 2461 | ||
| 2462 | /* compute the number of subunits */ | |
| 2463 | hdata->subunits = 0; | |
| 2464 | for (unitnum = 0; unitnum < maxunits; unitnum++) | |
| 2465 | if (handlerunitmask & (1 << unitnum)) | |
| 2466 | hdata->subunits++; | |
| 2467 | assert_always(hdata->subunits > 0, "table_compute_subhandler called with no bytes specified in mask"); | |
| 2468 | ||
| 2469 | /* then fill in the shifts based on the endianness */ | |
| 2470 | if (spaceendian == ENDIANNESS_LITTLE) | |
| 2471 | { | |
| 2472 | UINT8 *unitshift = &hdata->subshift[0]; | |
| 2473 | for (unitnum = 0; unitnum < maxunits; unitnum++) | |
| 2474 | if (handlerunitmask & (1 << unitnum)) | |
| 2475 | *unitshift++ = unitnum * handlerbits; | |
| 2476 | } | |
| 2477 | else | |
| 2478 | { | |
| 2479 | UINT8 *unitshift = &hdata->subshift[hdata->subunits]; | |
| 2480 | for (unitnum = 0; unitnum < maxunits; unitnum++) | |
| 2481 | if (handlerunitmask & (1 << unitnum)) | |
| 2482 | *--unitshift = unitnum * handlerbits; | |
| 2483 | } | |
| 2743 | // populate it | |
| 2744 | populate_range_mirrored(bytestart, byteend, bytemirror, entry); | |
| 2745 | ||
| 2746 | // recompute any direct access on this space if it is a read modification | |
| 2747 | m_space.m_direct.force_update(entry); | |
| 2748 | return entry; | |
| 2484 | 2749 | } |
| 2485 | 2750 | |
| 2486 | 2751 | |
| 2487 | /*------------------------------------------------- | |
| 2488 | table_populate_range - assign a memory handler | |
| 2489 | to a range of addresses | |
| 2490 | -------------------------------------------------*/ | |
| 2752 | //------------------------------------------------- | |
| 2753 | // populate_range - assign a memory handler to a | |
| 2754 | // range of addresses | |
| 2755 | //------------------------------------------------- | |
| 2491 | 2756 | |
| 2492 | ||
| 2757 | ||
| 2493 | 2758 | { |
| 2494 | offs_t l2mask = (1 << LEVEL2_BITS) - 1; | |
| 2495 | offs_t l1start = bytestart >> LEVEL2_BITS; | |
| 2759 | offs_t l2mask = (1 << level2_bits()) - 1; | |
| 2760 | offs_t l1start = bytestart >> level2_bits(); | |
| 2496 | 2761 | offs_t l2start = bytestart & l2mask; |
| 2497 | offs_t l1stop = byteend >> | |
| 2762 | offs_t l1stop = byteend >> level2_bits(); | |
| 2498 | 2763 | offs_t l2stop = byteend & l2mask; |
| 2499 | offs_t l1index; | |
| 2500 | 2764 | |
| 2501 | / | |
| 2765 | // sanity check | |
| 2502 | 2766 | if (bytestart > byteend) |
| 2503 | 2767 | return; |
| 2504 | 2768 | |
| 2505 | / | |
| 2769 | // handle the starting edge if it's not on a block boundary | |
| 2506 | 2770 | if (l2start != 0) |
| 2507 | 2771 | { |
| 2508 | UINT8 *subtable = subtable_open( | |
| 2772 | UINT8 *subtable = subtable_open( | |
| 2509 | 2773 | |
| 2510 | / | |
| 2774 | // if the start and stop end within the same block, handle that | |
| 2511 | 2775 | if (l1start == l1stop) |
| 2512 | 2776 | { |
| 2513 | memset(&subtable[l2start], handler, l2stop - l2start + 1); | |
| 2514 | subtable_close(tabledata, l1start); | |
| 2777 | memset(&subtable[l2start], handlerindex, l2stop - l2start + 1); | |
| 2778 | subtable_close(l1start); | |
| 2515 | 2779 | return; |
| 2516 | 2780 | } |
| 2517 | 2781 | |
| 2518 | /* otherwise, fill until the end */ | |
| 2519 | memset(&subtable[l2start], handler, (1 << LEVEL2_BITS) - l2start); | |
| 2520 | subtable_close(tabledata, l1start); | |
| 2521 | if (l1start != (offs_t)~0) l1start++; | |
| 2782 | // otherwise, fill until the end | |
| 2783 | memset(&subtable[l2start], handlerindex, (1 << level2_bits()) - l2start); | |
| 2784 | subtable_close(l1start); | |
| 2785 | if (l1start != (offs_t)~0) | |
| 2786 | l1start++; | |
| 2522 | 2787 | } |
| 2523 | 2788 | |
| 2524 | / | |
| 2789 | // handle the trailing edge if it's not on a block boundary | |
| 2525 | 2790 | if (l2stop != l2mask) |
| 2526 | 2791 | { |
| 2527 | UINT8 *subtable = subtable_open( | |
| 2792 | UINT8 *subtable = subtable_open( | |
| 2528 | 2793 | |
| 2529 | /* fill from the beginning */ | |
| 2530 | memset(&subtable[0], handler, l2stop + 1); | |
| 2531 | subtable_close(tabledata, l1stop); | |
| 2794 | // fill from the beginning | |
| 2795 | memset(&subtable[0], handlerindex, l2stop + 1); | |
| 2796 | subtable_close(l1stop); | |
| 2532 | 2797 | |
| 2533 | / | |
| 2798 | // if the start and stop end within the same block, handle that | |
| 2534 | 2799 | if (l1start == l1stop) |
| 2535 | 2800 | return; |
| 2536 | if (l1stop != 0) l1stop--; | |
| 2801 | if (l1stop != 0) | |
| 2802 | l1stop--; | |
| 2537 | 2803 | } |
| 2538 | 2804 | |
| 2539 | /* now fill in the middle tables */ | |
| 2540 | for (l1index = l1start; l1index <= l1stop; l1index++) | |
| 2805 | // now fill in the middle tables | |
| 2806 | for (offs_t l1index = l1start; l1index <= l1stop; l1index++) | |
| 2541 | 2807 | { |
| 2542 | /* if we have a subtable here, release it */ | |
| 2543 | if (tabledata->table[l1index] >= SUBTABLE_BASE) | |
| 2544 | subtable_release(tabledata, tabledata->table[l1index]); | |
| 2545 | tabledata->table[l1index] = handler; | |
| 2808 | // if we have a subtable here, release it | |
| 2809 | if (m_table[l1index] >= SUBTABLE_BASE) | |
| 2810 | subtable_release(m_table[l1index]); | |
| 2811 | m_table[l1index] = handlerindex; | |
| 2546 | 2812 | } |
| 2547 | 2813 | } |
| 2548 | 2814 | |
| 2549 | 2815 | |
| 2550 | /*------------------------------------------------- | |
| 2551 | table_populate_range_mirrored - assign a | |
| 2552 | memory handler to a range of addresses | |
| 2553 | including mirrors | |
| 2554 | -------------------------------------------------*/ | |
| 2816 | //------------------------------------------------- | |
| 2817 | // populate_range_mirrored - assign a memory | |
| 2818 | // handler to a range of addresses including | |
| 2819 | // mirrors | |
| 2820 | //------------------------------------------------- | |
| 2555 | 2821 | |
| 2556 | ||
| 2822 | ||
| 2557 | 2823 | { |
| 2558 | offs_t lmirrorbit[LEVEL2_BITS], lmirrorbits, hmirrorbit[32 - LEVEL2_BITS], hmirrorbits, lmirrorcount, hmirrorcount; | |
| 2824 | // determine the mirror bits | |
| 2825 | offs_t lmirrorbits = 0; | |
| 2826 | offs_t lmirrorbit[32]; | |
| 2827 | for (int bit = 0; bit < level2_bits(); bit++) | |
| 2828 | if (bytemirror & (1 << bit)) | |
| 2829 | lmirrorbit[lmirrorbits++] = 1 << bit; | |
| 2830 | ||
| 2831 | offs_t hmirrorbits = 0; | |
| 2832 | offs_t hmirrorbit[32]; | |
| 2833 | for (int bit = level2_bits(); bit < 32; bit++) | |
| 2834 | if (bytemirror & (1 << bit)) | |
| 2835 | hmirrorbit[hmirrorbits++] = 1 << bit; | |
| 2836 | ||
| 2837 | // loop over mirrors in the level 2 table | |
| 2559 | 2838 | UINT8 prev_entry = STATIC_INVALID; |
| 2560 | int cur_index, prev_index = 0; | |
| 2561 | int i; | |
| 2562 | ||
| 2563 | /* determine the mirror bits */ | |
| 2564 | hmirrorbits = lmirrorbits = 0; | |
| 2565 | for (i = 0; i < LEVEL2_BITS; i++) | |
| 2566 | if (bytemirror & (1 << i)) | |
| 2567 | lmirrorbit[lmirrorbits++] = 1 << i; | |
| 2568 | for (i = LEVEL2_BITS; i < 32; i++) | |
| 2569 | if (bytemirror & (1 << i)) | |
| 2570 | hmirrorbit[hmirrorbits++] = 1 << i; | |
| 2571 | ||
| 2572 | /* loop over mirrors in the level 2 table */ | |
| 2573 | for (hmirrorcount = 0; hmirrorcount < (1 << hmirrorbits); hmirrorcount++) | |
| 2839 | int prev_index = 0; | |
| 2840 | for (offs_t hmirrorcount = 0; hmirrorcount < (1 << hmirrorbits); hmirrorcount++) | |
| 2574 | 2841 | { |
| 2575 | / | |
| 2842 | // compute the base of this mirror | |
| 2576 | 2843 | offs_t hmirrorbase = 0; |
| 2577 | for (i = 0; i < hmirrorbits; i++) | |
| 2578 | if (hmirrorcount & (1 << i)) | |
| 2579 | hmirrorbase |= hmirrorbit[i]; | |
| 2844 | for (int bit = 0; bit < hmirrorbits; bit++) | |
| 2845 | if (hmirrorcount & (1 << bit)) | |
| 2846 | hmirrorbase |= hmirrorbit[bit]; | |
| 2580 | 2847 | |
| 2581 | /* invalidate any intersecting cached ranges */ | |
| 2582 | for (lmirrorcount = 0; lmirrorcount < (1 << lmirrorbits); lmirrorcount++) | |
| 2848 | // invalidate any intersecting cached ranges | |
| 2849 | for (offs_t lmirrorcount = 0; lmirrorcount < (1 << lmirrorbits); lmirrorcount++) | |
| 2583 | 2850 | { |
| 2584 | / | |
| 2851 | // compute the base of this mirror | |
| 2585 | 2852 | offs_t lmirrorbase = hmirrorbase; |
| 2586 | for (i = 0; i < lmirrorbits; i++) | |
| 2587 | if (lmirrorcount & (1 << i)) | |
| 2588 | lmirrorbase |= lmirrorbit[i]; | |
| 2589 | direct_range_remove_intersecting(space, bytestart + lmirrorbase, byteend + lmirrorbase); | |
| 2853 | for (int bit = 0; bit < lmirrorbits; bit++) | |
| 2854 | if (lmirrorcount & (1 << bit)) | |
| 2855 | lmirrorbase |= lmirrorbit[bit]; | |
| 2856 | m_space.m_direct.remove_intersecting_ranges(bytestart + lmirrorbase, byteend + lmirrorbase); | |
| 2590 | 2857 | } |
| 2591 | 2858 | |
| 2592 | /* if this is not our first time through, and the level 2 entry matches the previous | |
| 2593 | level 2 entry, just do a quick map and get out; note that this only works for entries | |
| 2594 | which don't span multiple level 1 table entries */ | |
| 2595 | cur_index = LEVEL1_INDEX(bytestart + hmirrorbase); | |
| 2596 | if (cur_index == LEVEL1_INDEX(byteend + hmirrorbase)) | |
| 2859 | // if this is not our first time through, and the level 2 entry matches the previous | |
| 2860 | // level 2 entry, just do a quick map and get out; note that this only works for entries | |
| 2861 | // which don't span multiple level 1 table entries | |
| 2862 | int cur_index = level1_index(bytestart + hmirrorbase); | |
| 2863 | if (cur_index == level1_index(byteend + hmirrorbase)) | |
| 2597 | 2864 | { |
| 2598 | if (hmirrorcount != 0 && prev_entry == | |
| 2865 | if (hmirrorcount != 0 && prev_entry == m_ | |
| 2599 | 2866 | { |
| 2600 | VPRINTF(("Quick mapping subtable at %08X to match subtable at %08X\n", cur_index << | |
| 2867 | VPRINTF(("Quick mapping subtable at %08X to match subtable at %08X\n", cur_index << level2_bits(), prev_index << level2_bits())); | |
| 2601 | 2868 | |
| 2602 | /* release the subtable if the old value was a subtable */ | |
| 2603 | if (tabledata->table[cur_index] >= SUBTABLE_BASE) | |
| 2604 | subtable_release(tabledata, tabledata->table[cur_index]); | |
| 2869 | // release the subtable if the old value was a subtable | |
| 2870 | if (m_table[cur_index] >= SUBTABLE_BASE) | |
| 2871 | subtable_release(m_table[cur_index]); | |
| 2605 | 2872 | |
| 2606 | /* reallocate the subtable if the new value is a subtable */ | |
| 2607 | if (tabledata->table[prev_index] >= SUBTABLE_BASE) | |
| 2608 | subtable_realloc(tabledata, tabledata->table[prev_index]); | |
| 2873 | // reallocate the subtable if the new value is a subtable | |
| 2874 | if (m_table[prev_index] >= SUBTABLE_BASE) | |
| 2875 | subtable_realloc(m_table[prev_index]); | |
| 2609 | 2876 | |
| 2610 | /* set the new value and short-circuit the mapping step */ | |
| 2611 | tabledata->table[cur_index] = tabledata->table[prev_index]; | |
| 2877 | // set the new value and short-circuit the mapping step | |
| 2878 | m_table[cur_index] = m_table[prev_index]; | |
| 2612 | 2879 | continue; |
| 2613 | 2880 | } |
| 2614 | 2881 | prev_index = cur_index; |
| 2615 | prev_entry = | |
| 2882 | prev_entry = m_ | |
| 2616 | 2883 | } |
| 2617 | 2884 | |
| 2618 | /* loop over mirrors in the level 1 table */ | |
| 2619 | for (lmirrorcount = 0; lmirrorcount < (1 << lmirrorbits); lmirrorcount++) | |
| 2885 | // loop over mirrors in the level 1 table | |
| 2886 | for (offs_t lmirrorcount = 0; lmirrorcount < (1 << lmirrorbits); lmirrorcount++) | |
| 2620 | 2887 | { |
| 2621 | / | |
| 2888 | // compute the base of this mirror | |
| 2622 | 2889 | offs_t lmirrorbase = hmirrorbase; |
| 2623 | for (i = 0; i < lmirrorbits; i++) | |
| 2624 | if (lmirrorcount & (1 << i)) | |
| 2625 | lmirrorbase |= lmirrorbit[i]; | |
| 2890 | for (int bit = 0; bit < lmirrorbits; bit++) | |
| 2891 | if (lmirrorcount & (1 << bit)) | |
| 2892 | lmirrorbase |= lmirrorbit[bit]; | |
| 2626 | 2893 | |
| 2627 | /* populate the tables */ | |
| 2628 | table_populate_range(tabledata, bytestart + lmirrorbase, byteend + lmirrorbase, handler); | |
| 2894 | // populate the tables | |
| 2895 | populate_range(bytestart + lmirrorbase, byteend + lmirrorbase, handlerindex); | |
| 2629 | 2896 | } |
| 2630 | 2897 | } |
| 2631 | 2898 | } |
| 2632 | 2899 | |
| 2633 | 2900 | |
| 2634 | /*------------------------------------------------- | |
| 2635 | table_derive_range - look up the entry for | |
| 2636 | a memory range, and then compute the extent | |
| 2637 | of that range based on the lookup tables | |
| 2638 | -------------------------------------------------*/ | |
| 2901 | //------------------------------------------------- | |
| 2902 | // depopulate_unused - scan the table and | |
| 2903 | // eliminate entries that are no longer used | |
| 2904 | //------------------------------------------------- | |
| 2639 | 2905 | |
| 2640 | ||
| 2906 | ||
| 2641 | 2907 | { |
| 2642 | UINT32 curentry, entry, curl1entry, l1entry; | |
| 2643 | const handler_data *handler; | |
| 2644 | offs_t minscan, maxscan; | |
| 2908 | assert(false); | |
| 2909 | } | |
| 2645 | 2910 | |
| 2646 | /* look up the initial address to get the entry we care about */ | |
| 2647 | entry = l1entry = table->table[LEVEL1_INDEX(byteaddress)]; | |
| 2911 | ||
| 2912 | //------------------------------------------------- | |
| 2913 | // derive_range - look up the entry for a memory | |
| 2914 | // range, and then compute the extent of that | |
| 2915 | // range based on the lookup tables | |
| 2916 | //------------------------------------------------- | |
| 2917 | ||
| 2918 | UINT8 address_table::derive_range(offs_t byteaddress, offs_t &bytestart, offs_t &byteend) const | |
| 2919 | { | |
| 2920 | // look up the initial address to get the entry we care about | |
| 2921 | UINT8 l1entry; | |
| 2922 | UINT8 entry = l1entry = m_table[level1_index(byteaddress)]; | |
| 2648 | 2923 | if (l1entry >= SUBTABLE_BASE) |
| 2649 | entry = table->table[LEVEL2_INDEX(l1entry, byteaddress)]; | |
| 2650 | handler = table->handlers[entry]; | |
| 2924 | entry = m_table[level2_index(l1entry, byteaddress)]; | |
| 2651 | 2925 | |
| 2652 | /* use the bytemask of the entry to set minimum and maximum bounds */ | |
| 2653 | minscan = handler->bytestart | ((byteaddress - handler->bytestart) & ~handler->bytemask); | |
| 2654 | maxscan = handler->byteend | ((byteaddress - handler->bytestart) & ~handler->bytemask); | |
| 2926 | // use the bytemask of the entry to set minimum and maximum bounds | |
| 2927 | offs_t minscan, maxscan; | |
| 2928 | handler(entry).mirrored_start_end(byteaddress, minscan, maxscan); | |
| 2655 | 2929 | |
| 2656 | /* first scan backwards to find the start address */ | |
| 2657 | curl1entry = l1entry; | |
| 2658 | curentry = entry; | |
| 2659 | *bytestart = byteaddress; | |
| 2930 | // first scan backwards to find the start address | |
| 2931 | UINT8 curl1entry = l1entry; | |
| 2932 | UINT8 curentry = entry; | |
| 2933 | bytestart = byteaddress; | |
| 2660 | 2934 | while (1) |
| 2661 | 2935 | { |
| 2662 | / | |
| 2936 | // if we need to scan the subtable, do it | |
| 2663 | 2937 | if (curentry != curl1entry) |
| 2664 | 2938 | { |
| 2665 | UINT32 minindex = | |
| 2939 | UINT32 minindex = level2_index(curl1entry, 0); | |
| 2666 | 2940 | UINT32 index; |
| 2667 | 2941 | |
| 2668 | /* scan backwards from the current address, until the previous entry doesn't match */ | |
| 2669 | for (index = LEVEL2_INDEX(curl1entry, *bytestart); index > minindex; index--, *bytestart -= 1) | |
| 2670 | if (table->table[index - 1] != entry) | |
| 2942 | // scan backwards from the current address, until the previous entry doesn't match | |
| 2943 | for (index = level2_index(curl1entry, bytestart); index > minindex; index--, bytestart -= 1) | |
| 2944 | if (m_table[index - 1] != entry) | |
| 2671 | 2945 | break; |
| 2672 | 2946 | |
| 2673 | / | |
| 2947 | // if we didn't hit the beginning, then we're finished scanning | |
| 2674 | 2948 | if (index != minindex) |
| 2675 | 2949 | break; |
| 2676 | 2950 | } |
| 2677 | 2951 | |
| 2678 | /* move to the beginning of this L1 entry; stop at the minimum address */ | |
| 2679 | *bytestart &= ~((1 << LEVEL2_BITS) - 1); | |
| 2680 | if (*bytestart <= minscan) | |
| 2952 | // move to the beginning of this L1 entry; stop at the minimum address | |
| 2953 | bytestart &= ~((1 << level2_bits()) - 1); | |
| 2954 | if (bytestart <= minscan) | |
| 2681 | 2955 | break; |
| 2682 | 2956 | |
| 2683 | /* look up the entry of the byte at the end of the previous L1 entry; if it doesn't match, stop */ | |
| 2684 | curentry = curl1entry = table->table[LEVEL1_INDEX(*bytestart - 1)]; | |
| 2957 | // look up the entry of the byte at the end of the previous L1 entry; if it doesn't match, stop | |
| 2958 | curentry = curl1entry = m_table[level1_index(bytestart - 1)]; | |
| 2685 | 2959 | if (curl1entry >= SUBTABLE_BASE) |
| 2686 | curentry = table | |
| 2960 | curentry = m_table[ | |
| 2687 | 2961 | if (curentry != entry) |
| 2688 | 2962 | break; |
| 2689 | 2963 | |
| 2690 | /* move into the previous entry and resume searching */ | |
| 2691 | *bytestart -= 1; | |
| 2964 | // move into the previous entry and resume searching | |
| 2965 | bytestart -= 1; | |
| 2692 | 2966 | } |
| 2693 | 2967 | |
| 2694 | / | |
| 2968 | // then scan forwards to find the end address | |
| 2695 | 2969 | curl1entry = l1entry; |
| 2696 | 2970 | curentry = entry; |
| 2697 | | |
| 2971 | | |
| 2698 | 2972 | while (1) |
| 2699 | 2973 | { |
| 2700 | / | |
| 2974 | // if we need to scan the subtable, do it | |
| 2701 | 2975 | if (curentry != curl1entry) |
| 2702 | 2976 | { |
| 2703 | UINT32 maxindex = | |
| 2977 | UINT32 maxindex = level2_index(curl1entry, ~0); | |
| 2704 | 2978 | UINT32 index; |
| 2705 | 2979 | |
| 2706 | /* scan forwards from the current address, until the next entry doesn't match */ | |
| 2707 | for (index = LEVEL2_INDEX(curl1entry, *byteend); index < maxindex; index++, *byteend += 1) | |
| 2708 | if (table->table[index + 1] != entry) | |
| 2980 | // scan forwards from the current address, until the next entry doesn't match | |
| 2981 | for (index = level2_index(curl1entry, byteend); index < maxindex; index++, byteend += 1) | |
| 2982 | if (m_table[index + 1] != entry) | |
| 2709 | 2983 | break; |
| 2710 | 2984 | |
| 2711 | / | |
| 2985 | // if we didn't hit the end, then we're finished scanning | |
| 2712 | 2986 | if (index != maxindex) |
| 2713 | 2987 | break; |
| 2714 | 2988 | } |
| 2715 | 2989 | |
| 2716 | /* move to the end of this L1 entry; stop at the maximum address */ | |
| 2717 | *byteend |= (1 << LEVEL2_BITS) - 1; | |
| 2718 | if (*byteend >= maxscan) | |
| 2990 | // move to the end of this L1 entry; stop at the maximum address | |
| 2991 | byteend |= (1 << level2_bits()) - 1; | |
| 2992 | if (byteend >= maxscan) | |
| 2719 | 2993 | break; |
| 2720 | 2994 | |
| 2721 | /* look up the entry of the byte at the start of the next L1 entry; if it doesn't match, stop */ | |
| 2722 | curentry = curl1entry = table->table[LEVEL1_INDEX(*byteend + 1)]; | |
| 2995 | // look up the entry of the byte at the start of the next L1 entry; if it doesn't match, stop | |
| 2996 | curentry = curl1entry = m_table[level1_index(byteend + 1)]; | |
| 2723 | 2997 | if (curl1entry >= SUBTABLE_BASE) |
| 2724 | curentry = table | |
| 2998 | curentry = m_table[ | |
| 2725 | 2999 | if (curentry != entry) |
| 2726 | 3000 | break; |
| 2727 | 3001 | |
| 2728 | /* move into the next entry and resume searching */ | |
| 2729 | *byteend += 1; | |
| 3002 | // move into the next entry and resume searching | |
| 3003 | byteend += 1; | |
| 2730 | 3004 | } |
| 2731 | 3005 | |
| 2732 | 3006 | return entry; |
| 2733 | 3007 | } |
| 2734 | 3008 | |
| 2735 | 3009 | |
| 3010 | //------------------------------------------------- | |
| 3011 | // mask_all_handlers - apply a mask to all | |
| 3012 | // address handlers | |
| 3013 | //------------------------------------------------- | |
| 2736 | 3014 | |
| 2737 | /*************************************************************************** | |
| 2738 | SUBTABLE MANAGEMENT | |
| 2739 | ***************************************************************************/ | |
| 3015 | void address_table::mask_all_handlers(offs_t mask) | |
| 3016 | { | |
| 3017 | // we don't loop over map entries because the mask applies to static handlers as well | |
| 3018 | for (int entrynum = 0; entrynum < ENTRY_COUNT; entrynum++) | |
| 3019 | handler(entrynum).apply_mask(mask); | |
| 3020 | } | |
| 2740 | 3021 | |
| 2741 | /*------------------------------------------------- | |
| 2742 | subtable_alloc - allocate a fresh subtable | |
| 2743 | and set its usecount to 1 | |
| 2744 | -------------------------------------------------*/ | |
| 2745 | 3022 | |
| 2746 | static UINT8 subtable_alloc(address_table *tabledata) | |
| 3023 | ||
| 3024 | //************************************************************************** | |
| 3025 | // SUBTABLE MANAGEMENT | |
| 3026 | //************************************************************************** | |
| 3027 | ||
| 3028 | //------------------------------------------------- | |
| 3029 | // subtable_alloc - allocate a fresh subtable | |
| 3030 | // and set its usecount to 1 | |
| 3031 | //------------------------------------------------- | |
| 3032 | ||
| 3033 | UINT8 address_table::subtable_alloc() | |
| 2747 | 3034 | { |
| 2748 | / | |
| 3035 | // loop | |
| 2749 | 3036 | while (1) |
| 2750 | 3037 | { |
| 2751 | UINT8 subindex; | |
| 2752 | ||
| 2753 | /* find a subtable with a usecount of 0 */ | |
| 2754 | for (subindex = 0; subindex < SUBTABLE_COUNT; subindex++) | |
| 2755 | if (tabledata->subtable[subindex].usecount == 0) | |
| 3038 | // find a subtable with a usecount of 0 | |
| 3039 | for (UINT8 subindex = 0; subindex < SUBTABLE_COUNT; subindex++) | |
| 3040 | if (m_subtable[subindex].m_usecount == 0) | |
| 2756 | 3041 | { |
| 2757 | /* if this is past our allocation budget, allocate some more */ | |
| 2758 | if (subindex >= tabledata->subtable_alloc) | |
| 3042 | // if this is past our allocation budget, allocate some more | |
| 3043 | if (subindex >= m_subtable_alloc) | |
| 2759 | 3044 | { |
| 2760 | UINT32 oldsize = (1 << LEVEL1_BITS) + (tabledata->subtable_alloc << LEVEL2_BITS); | |
| 2761 | tabledata->subtable_alloc += SUBTABLE_ALLOC; | |
| 2762 | UINT32 newsize = (1 << LEVEL1_BITS) + (tabledata->subtable_alloc << LEVEL2_BITS); | |
| 3045 | UINT32 oldsize = (1 << LEVEL1_BITS) + (m_subtable_alloc << level2_bits()); | |
| 3046 | m_subtable_alloc += SUBTABLE_ALLOC; | |
| 3047 | UINT32 newsize = (1 << LEVEL1_BITS) + (m_subtable_alloc << level2_bits()); | |
| 2763 | 3048 | |
| 2764 | UINT8 *newtable = auto_alloc_array(tabledata->machine, UINT8, newsize); | |
| 2765 | memcpy(newtable, tabledata->table, oldsize); | |
| 2766 | auto_free(tabledata->machine, tabledata->table); | |
| 2767 | tabledata->table = newtable; | |
| 3049 | UINT8 *newtable = auto_alloc_array_clear(&m_space.m_machine, UINT8, newsize); | |
| 3050 | memcpy(newtable, m_table, oldsize); | |
| 3051 | if (m_live_lookup == m_table) | |
| 3052 | m_live_lookup = newtable; | |
| 3053 | auto_free(&m_space.m_machine, m_table); | |
| 3054 | m_table = newtable; | |
| 2768 | 3055 | } |
| 2769 | 3056 | |
| 2770 | /* bump the usecount and return */ | |
| 2771 | tabledata->subtable[subindex].usecount++; | |
| 3057 | // bump the usecount and return | |
| 3058 | m_subtable[subindex].m_usecount++; | |
| 2772 | 3059 | return subindex + SUBTABLE_BASE; |
| 2773 | 3060 | } |
| 2774 | 3061 | |
| 2775 | /* merge any subtables we can */ | |
| 2776 | if (!subtable_merge(tabledata)) | |
| 3062 | // merge any subtables we can | |
| 3063 | if (!subtable_merge()) | |
| 2777 | 3064 | fatalerror("Ran out of subtables!"); |
| 2778 | 3065 | } |
| 2779 | 3066 | } |
| 2780 | 3067 | |
| 2781 | 3068 | |
| 2782 | /*------------------------------------------------- | |
| 2783 | subtable_realloc - increment the usecount on | |
| 2784 | a subtable | |
| 2785 | -------------------------------------------------*/ | |
| 3069 | //------------------------------------------------- | |
| 3070 | // subtable_realloc - increment the usecount on | |
| 3071 | // a subtable | |
| 3072 | //------------------------------------------------- | |
| 2786 | 3073 | |
| 2787 | ||
| 3074 | ||
| 2788 | 3075 | { |
| 2789 | 3076 | UINT8 subindex = subentry - SUBTABLE_BASE; |
| 2790 | 3077 | |
| 2791 | /* sanity check */ | |
| 2792 | if (tabledata->subtable[subindex].usecount <= 0) | |
| 3078 | // sanity check | |
| 3079 | if (m_subtable[subindex].m_usecount <= 0) | |
| 2793 | 3080 | fatalerror("Called subtable_realloc on a table with a usecount of 0"); |
| 2794 | 3081 | |
| 2795 | /* increment the usecount */ | |
| 2796 | tabledata->subtable[subindex].usecount++; | |
| 3082 | // increment the usecount | |
| 3083 | m_subtable[subindex].m_usecount++; | |
| 2797 | 3084 | } |
| 2798 | 3085 | |
| 2799 | 3086 | |
| 2800 | /*------------------------------------------------- | |
| 2801 | subtable_merge - merge any duplicate | |
| 2802 | subtables | |
| 2803 | -------------------------------------------------*/ | |
| 3087 | //------------------------------------------------- | |
| 3088 | // subtable_merge - merge any duplicate | |
| 3089 | // subtables | |
| 3090 | //------------------------------------------------- | |
| 2804 | 3091 | |
| 2805 | ||
| 3092 | ||
| 2806 | 3093 | { |
| 2807 | 3094 | int merged = 0; |
| 2808 | 3095 | UINT8 subindex; |
| 2809 | 3096 | |
| 2810 | 3097 | VPRINTF(("Merging subtables....\n")); |
| 2811 | 3098 | |
| 2812 | / | |
| 3099 | // okay, we failed; update all the checksums and merge tables | |
| 2813 | 3100 | for (subindex = 0; subindex < SUBTABLE_COUNT; subindex++) |
| 2814 | if (! | |
| 3101 | if (!m_ | |
| 2815 | 3102 | { |
| 2816 | UINT32 *subtable = | |
| 3103 | UINT32 *subtable = reinterpret_cast<UINT32 *> | |
| 2817 | 3104 | UINT32 checksum = 0; |
| 2818 | int l2index; | |
| 2819 | 3105 | |
| 2820 | /* update the checksum */ | |
| 2821 | for (l2index = 0; l2index < (1 << LEVEL2_BITS)/4; l2index++) | |
| 3106 | // update the checksum | |
| 3107 | for (int l2index = 0; l2index < (1 << level2_bits())/4; l2index++) | |
| 2822 | 3108 | checksum += subtable[l2index]; |
| 2823 | tabledata->subtable[subindex].checksum = checksum; | |
| 2824 | tabledata->subtable[subindex].checksum_valid = 1; | |
| 3109 | m_subtable[subindex].m_checksum = checksum; | |
| 3110 | m_subtable[subindex].m_checksum_valid = true; | |
| 2825 | 3111 | } |
| 2826 | 3112 | |
| 2827 | / | |
| 3113 | // see if there's a matching checksum | |
| 2828 | 3114 | for (subindex = 0; subindex < SUBTABLE_COUNT; subindex++) |
| 2829 | if ( | |
| 3115 | if (m_ | |
| 2830 | 3116 | { |
| 2831 | UINT8 *subtable = SUBTABLE_PTR(tabledata, subindex + SUBTABLE_BASE); | |
| 2832 | UINT32 checksum = tabledata->subtable[subindex].checksum; | |
| 3117 | UINT8 *subtable = subtable_ptr(subindex + SUBTABLE_BASE); | |
| 3118 | UINT32 checksum = m_subtable[subindex].m_checksum; | |
| 2833 | 3119 | UINT8 sumindex; |
| 2834 | 3120 | |
| 2835 | 3121 | for (sumindex = subindex + 1; sumindex < SUBTABLE_COUNT; sumindex++) |
| 2836 | if (tabledata->subtable[sumindex].usecount != 0 && | |
| 2837 | tabledata->subtable[sumindex].checksum == checksum && | |
| 2838 | !memcmp(subtable, SUBTABLE_PTR(tabledata, sumindex + SUBTABLE_BASE), 1 << LEVEL2_BITS)) | |
| 3122 | if (m_subtable[sumindex].m_usecount != 0 && | |
| 3123 | m_subtable[sumindex].m_checksum == checksum && | |
| 3124 | !memcmp(subtable, subtable_ptr(sumindex + SUBTABLE_BASE), 1 << level2_bits())) | |
| 2839 | 3125 | { |
| 2840 | 3126 | int l1index; |
| 2841 | 3127 | |
| 2842 | 3128 | VPRINTF(("Merging subtable %d and %d....\n", subindex, sumindex)); |
| 2843 | 3129 | |
| 2844 | /* find all the entries in the L1 tables that pointed to the old one, and point them to the merged table */ | |
| 2845 | for (l1index = 0; l1index <= (0xffffffffUL >> LEVEL2_BITS); l1index++) | |
| 2846 | if (tabledata->table[l1index] == sumindex + SUBTABLE_BASE) | |
| 3130 | // find all the entries in the L1 tables that pointed to the old one, and point them to the merged table | |
| 3131 | for (l1index = 0; l1index <= (0xffffffffUL >> level2_bits()); l1index++) | |
| 3132 | if (m_table[l1index] == sumindex + SUBTABLE_BASE) | |
| 2847 | 3133 | { |
| 2848 | subtable_release(tabledata, sumindex + SUBTABLE_BASE); | |
| 2849 | subtable_realloc(tabledata, subindex + SUBTABLE_BASE); | |
| 2850 | tabledata->table[l1index] = subindex + SUBTABLE_BASE; | |
| 3134 | subtable_release(sumindex + SUBTABLE_BASE); | |
| 3135 | subtable_realloc(subindex + SUBTABLE_BASE); | |
| 3136 | m_table[l1index] = subindex + SUBTABLE_BASE; | |
| 2851 | 3137 | merged++; |
| 2852 | 3138 | } |
| 2853 | 3139 | } |
| r8806 | r8807 | |
| 2857 | 3143 | } |
| 2858 | 3144 | |
| 2859 | 3145 | |
| 2860 | /*------------------------------------------------- | |
| 2861 | subtable_release - decrement the usecount on | |
| 2862 | a subtable and free it if we're done | |
| 2863 | -------------------------------------------------*/ | |
| 3146 | //------------------------------------------------- | |
| 3147 | // subtable_release - decrement the usecount on | |
| 3148 | // a subtable and free it if we're done | |
| 3149 | //------------------------------------------------- | |
| 2864 | 3150 | |
| 2865 | ||
| 3151 | ||
| 2866 | 3152 | { |
| 2867 | 3153 | UINT8 subindex = subentry - SUBTABLE_BASE; |
| 2868 | 3154 | |
| 2869 | /* sanity check */ | |
| 2870 | if (tabledata->subtable[subindex].usecount <= 0) | |
| 3155 | // sanity check | |
| 3156 | if (m_subtable[subindex].m_usecount <= 0) | |
| 2871 | 3157 | fatalerror("Called subtable_release on a table with a usecount of 0"); |
| 2872 | 3158 | |
| 2873 | /* decrement the usecount and clear the checksum if we're at 0 */ | |
| 2874 | tabledata->subtable[subindex].usecount--; | |
| 2875 | if (tabledata->subtable[subindex].usecount == 0) | |
| 2876 | tabledata->subtable[subindex].checksum = 0; | |
| 3159 | // decrement the usecount and clear the checksum if we're at 0 | |
| 3160 | m_subtable[subindex].m_usecount--; | |
| 3161 | if (m_subtable[subindex].m_usecount == 0) | |
| 3162 | m_subtable[subindex].m_checksum = 0; | |
| 2877 | 3163 | } |
| 2878 | 3164 | |
| 2879 | 3165 | |
| 2880 | /*------------------------------------------------- | |
| 2881 | subtable_open - gain access to a subtable for | |
| 2882 | modification | |
| 2883 | -------------------------------------------------*/ | |
| 3166 | //------------------------------------------------- | |
| 3167 | // subtable_open - gain access to a subtable for | |
| 3168 | // modification | |
| 3169 | //------------------------------------------------- | |
| 2884 | 3170 | |
| 2885 | ||
| 3171 | ||
| 2886 | 3172 | { |
| 2887 | UINT8 subentry = | |
| 3173 | UINT8 subentry = m_ | |
| 2888 | 3174 | |
| 2889 | / | |
| 3175 | // if we don't have a subtable yet, allocate a new one | |
| 2890 | 3176 | if (subentry < SUBTABLE_BASE) |
| 2891 | 3177 | { |
| 2892 | UINT8 newentry = subtable_alloc(tabledata); | |
| 2893 | memset(SUBTABLE_PTR(tabledata, newentry), subentry, 1 << LEVEL2_BITS); | |
| 2894 | tabledata->table[l1index] = newentry; | |
| 2895 | tabledata->subtable[newentry - SUBTABLE_BASE].checksum = (subentry + (subentry << 8) + (subentry << 16) + (subentry << 24)) * ((1 << LEVEL2_BITS)/4); | |
| 3178 | UINT8 newentry = subtable_alloc(); | |
| 3179 | memset(subtable_ptr(newentry), subentry, 1 << level2_bits()); | |
| 3180 | m_table[l1index] = newentry; | |
| 3181 | m_subtable[newentry - SUBTABLE_BASE].m_checksum = (subentry + (subentry << 8) + (subentry << 16) + (subentry << 24)) * ((1 << level2_bits())/4); | |
| 2896 | 3182 | subentry = newentry; |
| 2897 | 3183 | } |
| 2898 | 3184 | |
| 2899 | /* if we're sharing this subtable, we also need to allocate a fresh copy */ | |
| 2900 | else if (tabledata->subtable[subentry - SUBTABLE_BASE].usecount > 1) | |
| 3185 | // if we're sharing this subtable, we also need to allocate a fresh copy | |
| 3186 | else if (m_subtable[subentry - SUBTABLE_BASE].m_usecount > 1) | |
| 2901 | 3187 | { |
| 2902 | UINT8 newentry = subtable_alloc( | |
| 3188 | UINT8 newentry = subtable_alloc( | |
| 2903 | 3189 | |
| 2904 | /* allocate may cause some additional merging -- look up the subentry again */ | |
| 2905 | /* when we're done; it should still require a split */ | |
| 2906 | subentry = tabledata->table[l1index]; | |
| 3190 | // allocate may cause some additional merging -- look up the subentry again | |
| 3191 | // when we're done; it should still require a split | |
| 3192 | subentry = m_table[l1index]; | |
| 2907 | 3193 | assert(subentry >= SUBTABLE_BASE); |
| 2908 | assert( | |
| 3194 | assert(m_ | |
| 2909 | 3195 | |
| 2910 | memcpy(SUBTABLE_PTR(tabledata, newentry), SUBTABLE_PTR(tabledata, subentry), 1 << LEVEL2_BITS); | |
| 2911 | subtable_release(tabledata, subentry); | |
| 2912 | tabledata->table[l1index] = newentry; | |
| 2913 | tabledata->subtable[newentry - SUBTABLE_BASE].checksum = tabledata->subtable[subentry - SUBTABLE_BASE].checksum; | |
| 3196 | memcpy(subtable_ptr(newentry), subtable_ptr(subentry), 1 << level2_bits()); | |
| 3197 | subtable_release(subentry); | |
| 3198 | m_table[l1index] = newentry; | |
| 3199 | m_subtable[newentry - SUBTABLE_BASE].m_checksum = m_subtable[subentry - SUBTABLE_BASE].m_checksum; | |
| 2914 | 3200 | subentry = newentry; |
| 2915 | 3201 | } |
| 2916 | 3202 | |
| 2917 | /* mark the table dirty */ | |
| 2918 | tabledata->subtable[subentry - SUBTABLE_BASE].checksum_valid = 0; | |
| 3203 | // mark the table dirty | |
| 3204 | m_subtable[subentry - SUBTABLE_BASE].m_checksum_valid = false; | |
| 2919 | 3205 | |
| 2920 | /* return the pointer to the subtable */ | |
| 2921 | return SUBTABLE_PTR(tabledata, subentry); | |
| 3206 | // return the pointer to the subtable | |
| 3207 | return subtable_ptr(subentry); | |
| 2922 | 3208 | } |
| 2923 | 3209 | |
| 2924 | 3210 | |
| 2925 | /*------------------------------------------------- | |
| 2926 | subtable_close - stop access to a subtable | |
| 2927 | -------------------------------------------------*/ | |
| 3211 | //------------------------------------------------- | |
| 3212 | // subtable_close - stop access to a subtable | |
| 3213 | //------------------------------------------------- | |
| 2928 | 3214 | |
| 2929 | ||
| 3215 | ||
| 2930 | 3216 | { |
| 2931 | / | |
| 3217 | // defer any merging until we run out of tables | |
| 2932 | 3218 | } |
| 2933 | 3219 | |
| 2934 | 3220 | |
| 3221 | //------------------------------------------------- | |
| 3222 | // handler_name - return friendly string | |
| 3223 | // description of a handler | |
| 3224 | //------------------------------------------------- | |
| 2935 | 3225 | |
| 2936 | /*************************************************************************** | |
| 2937 | DIRECT MEMORY RANGES | |
| 2938 | ***************************************************************************/ | |
| 2939 | ||
| 2940 | /*------------------------------------------------- | |
| 2941 | direct_range_find - find a byte address in | |
| 2942 | a range | |
| 2943 | -------------------------------------------------*/ | |
| 2944 | ||
| 2945 | static direct_range *direct_range_find(address_space *space, offs_t byteaddress, UINT8 *entry) | |
| 3226 | const char *address_table::handler_name(UINT8 entry) const | |
| 2946 | 3227 | { |
| 2947 | direct_range **rangelistptr; | |
| 2948 | direct_range **rangeptr; | |
| 2949 | direct_range *range; | |
| 2950 | ||
| 2951 | /* determine which entry */ | |
| 2952 | byteaddress &= space->bytemask; | |
| 2953 | *entry = space->read.table[LEVEL1_INDEX(byteaddress)]; | |
| 2954 | if (*entry >= SUBTABLE_BASE) | |
| 2955 | *entry = space->read.table[LEVEL2_INDEX(*entry, byteaddress)]; | |
| 2956 | rangelistptr = &space->direct.rangelist[*entry]; | |
| 2957 | ||
| 2958 | /* scan our table */ | |
| 2959 | for (rangeptr = rangelistptr; *rangeptr != NULL; rangeptr = &(*rangeptr)->next) | |
| 2960 | if (byteaddress >= (*rangeptr)->bytestart && byteaddress <= (*rangeptr)->byteend) | |
| 2961 | { | |
| 2962 | /* found a match; move us to the head of the list if we're not already there */ | |
| 2963 | range = *rangeptr; | |
| 2964 | if (range != *rangelistptr) | |
| 2965 | { | |
| 2966 | *rangeptr = range->next; | |
| 2967 | range->next = *rangelistptr; | |
| 2968 | *rangelistptr = range; | |
| 2969 | } | |
| 2970 | return range; | |
| 2971 | } | |
| 2972 | ||
| 2973 | /* didn't find out; allocate a new one */ | |
| 2974 | range = space->direct.freerangelist; | |
| 2975 | if (range != NULL) | |
| 2976 | space->direct.freerangelist = range->next; | |
| 2977 | else | |
| 2978 | range = auto_alloc(space->machine, direct_range); | |
| 2979 | ||
| 2980 | /* fill in the range */ | |
| 2981 | table_derive_range(&space->read, byteaddress, &range->bytestart, &range->byteend); | |
| 2982 | range->next = *rangelistptr; | |
| 2983 | *rangelistptr = range; | |
| 2984 | ||
| 2985 | return range; | |
| 2986 | } | |
| 2987 | ||
| 2988 | ||
| 2989 | /*------------------------------------------------- | |
| 2990 | direct_range_remove_intersecting - remove | |
| 2991 | all cached ranges that intersect the given | |
| 2992 | address range | |
| 2993 | -------------------------------------------------*/ | |
| 2994 | ||
| 2995 | static void direct_range_remove_intersecting(address_space *space, offs_t bytestart, offs_t byteend) | |
| 2996 | { | |
| 2997 | int entry; | |
| 2998 | ||
| 2999 | /* loop over all entries */ | |
| 3000 | for (entry = 0; entry < ARRAY_LENGTH(space->read.handlers); entry++) | |
| 3001 | { | |
| 3002 | direct_range **rangeptr, **nextrangeptr; | |
| 3003 | ||
| 3004 | /* loop over all ranges in this entry's list */ | |
| 3005 | for (nextrangeptr = rangeptr = &space->direct.rangelist[entry]; *rangeptr != NULL; rangeptr = nextrangeptr) | |
| 3006 | { | |
| 3007 | /* if we intersect, remove and add to the free range list */ | |
| 3008 | if (bytestart <= (*rangeptr)->byteend && byteend >= (*rangeptr)->bytestart) | |
| 3009 | { | |
| 3010 | direct_range *range = *rangeptr; | |
| 3011 | *rangeptr = range->next; | |
| 3012 | range->next = space->direct.freerangelist; | |
| 3013 | space->direct.freerangelist = range; | |
| 3014 | } | |
| 3015 | ||
| 3016 | /* otherwise advance to the next in the list */ | |
| 3017 | else | |
| 3018 | nextrangeptr = &(*rangeptr)->next; | |
| 3019 | } | |
| 3020 | } | |
| 3021 | } | |
| 3022 | ||
| 3023 | ||
| 3024 | ||
| 3025 | /*************************************************************************** | |
| 3026 | MEMORY BLOCK ALLOCATION | |
| 3027 | ***************************************************************************/ | |
| 3028 | ||
| 3029 | /*------------------------------------------------- | |
| 3030 | block_allocate - allocate a single | |
| 3031 | memory block of data | |
| 3032 | -------------------------------------------------*/ | |
| 3033 | ||
| 3034 | static void *block_allocate(const address_space *space, offs_t bytestart, offs_t byteend, void *memory) | |
| 3035 | { | |
| 3036 | memory_private *memdata = space->machine->memory_data; | |
| 3037 | int allocatemem = (memory == NULL); | |
| 3038 | memory_block *block; | |
| 3039 | size_t bytestoalloc; | |
| 3040 | const region_info *region; | |
| 3041 | ||
| 3042 | VPRINTF(("block_allocate('%s',%s,%08X,%08X,%p)\n", space->cpu->tag(), space->name, bytestart, byteend, memory)); | |
| 3043 | ||
| 3044 | /* determine how much memory to allocate for this */ | |
| 3045 | bytestoalloc = sizeof(*block); | |
| 3046 | if (allocatemem) | |
| 3047 | bytestoalloc += byteend - bytestart + 1; | |
| 3048 | ||
| 3049 | /* allocate and clear the memory */ | |
| 3050 | block = (memory_block *)auto_alloc_array_clear(space->machine, UINT8, bytestoalloc); | |
| 3051 | if (allocatemem) | |
| 3052 | memory = block + 1; | |
| 3053 | ||
| 3054 | /* register for saving, but only if we're not part of a memory region */ | |
| 3055 | for (region = space->machine->m_regionlist.first(); region != NULL; region = region->next()) | |
| 3056 | { | |
| 3057 | if ((UINT8 *)memory >= region->base() && ((UINT8 *)memory + (byteend - bytestart + 1)) < region->end()) | |
| 3058 | { | |
| 3059 | VPRINTF(("skipping save of this memory block as it is covered by a memory region\n")); | |
| 3060 | break; | |
| 3061 | } | |
| 3062 | } | |
| 3063 | ||
| 3064 | /* if we didn't find a match, register */ | |
| 3065 | if (region == NULL) | |
| 3066 | { | |
| 3067 | int bytes_per_element = space->dbits/8; | |
| 3068 | char name[256]; | |
| 3069 | ||
| 3070 | sprintf(name, "%08x-%08x", bytestart, byteend); | |
| 3071 | state_save_register_memory(space->machine, "memory", space->cpu->tag(), space->spacenum, name, memory, bytes_per_element, (UINT32)(byteend - bytestart + 1) / bytes_per_element, __FILE__, __LINE__); | |
| 3072 | } | |
| 3073 | ||
| 3074 | /* fill in the tracking block */ | |
| 3075 | block->space = space; | |
| 3076 | block->isallocated = allocatemem; | |
| 3077 | block->bytestart = bytestart; | |
| 3078 | block->byteend = byteend; | |
| 3079 | block->data = (UINT8 *)memory; | |
| 3080 | ||
| 3081 | /* attach us to the head of the list */ | |
| 3082 | block->next = memdata->memory_block_list; | |
| 3083 | memdata->memory_block_list = block; | |
| 3084 | ||
| 3085 | return memory; | |
| 3086 | } | |
| 3087 | ||
| 3088 | ||
| 3089 | /*------------------------------------------------- | |
| 3090 | block_assign_intersecting - find all | |
| 3091 | intersecting blocks and assign their pointers | |
| 3092 | -------------------------------------------------*/ | |
| 3093 | ||
| 3094 | static address_map_entry *block_assign_intersecting(address_space *space, offs_t bytestart, offs_t byteend, UINT8 *base) | |
| 3095 | { | |
| 3096 | memory_private *memdata = space->machine->memory_data; | |
| 3097 | address_map_entry *entry, *unassigned = NULL; | |
| 3098 | ||
| 3099 | /* loop over the adjusted map and assign memory to any blocks we can */ | |
| 3100 | for (entry = space->map->m_entrylist; entry != NULL; entry = entry->m_next) | |
| 3101 | { | |
| 3102 | /* if we haven't assigned this block yet, see if we have a mapped shared pointer for it */ | |
| 3103 | if (entry->m_memory == NULL && entry->m_share != NULL) | |
| 3104 | { | |
| 3105 | void *shareptr = memdata->sharemap.find(entry->m_share); | |
| 3106 | if (shareptr != UNMAPPED_SHARE_PTR) | |
| 3107 | { | |
| 3108 | entry->m_memory = shareptr; | |
| 3109 | VPRINTF(("memory range %08X-%08X -> shared_ptr '%s' [%p]\n", entry->m_addrstart, entry->m_addrend, entry->m_share, entry->m_memory)); | |
| 3110 | } | |
| 3111 | } | |
| 3112 | ||
| 3113 | /* otherwise, look for a match in this block */ | |
| 3114 | if (entry->m_memory == NULL && entry->m_bytestart >= bytestart && entry->m_byteend <= byteend) | |
| 3115 | { | |
| 3116 | entry->m_memory = base + (entry->m_bytestart - bytestart); | |
| 3117 | VPRINTF(("memory range %08X-%08X -> found in block from %08X-%08X [%p]\n", entry->m_addrstart, entry->m_addrend, bytestart, byteend, entry->m_memory)); | |
| 3118 | } | |
| 3119 | ||
| 3120 | /* if we're the first match on a shared pointer, assign it now */ | |
| 3121 | if (entry->m_memory != NULL && entry->m_share != NULL) | |
| 3122 | { | |
| 3123 | void *shareptr = memdata->sharemap.find(entry->m_share); | |
| 3124 | if (shareptr == UNMAPPED_SHARE_PTR) | |
| 3125 | memdata->sharemap.add(entry->m_share, entry->m_memory, TRUE); | |
| 3126 | } | |
| 3127 | ||
| 3128 | /* keep track of the first unassigned entry */ | |
| 3129 | if (entry->m_memory == NULL && unassigned == NULL && space_needs_backing_store(space, entry)) | |
| 3130 | unassigned = entry; | |
| 3131 | } | |
| 3132 | ||
| 3133 | return unassigned; | |
| 3134 | } | |
| 3135 | ||
| 3136 | ||
| 3137 | ||
| 3138 | /*************************************************************************** | |
| 3139 | INTERNAL HANDLERS | |
| 3140 | ***************************************************************************/ | |
| 3141 | ||
| 3142 | /*------------------------------------------------- | |
| 3143 | unmapped memory handlers | |
| 3144 | -------------------------------------------------*/ | |
| 3145 | ||
| 3146 | static READ8_HANDLER( unmap_read8 ) | |
| 3147 | { | |
| 3148 | if (space->log_unmap && !space->debugger_access) logerror("%s: unmapped %s memory byte read from %s\n", cpuexec_describe_context(space->machine), space->name, core_i64_hex_format(memory_byte_to_address(space, offset), space->addrchars)); | |
| 3149 | return space->unmap; | |
| 3150 | } | |
| 3151 | static READ16_HANDLER( unmap_read16 ) | |
| 3152 | { | |
| 3153 | if (space->log_unmap && !space->debugger_access) logerror("%s: unmapped %s memory word read from %s & %04X\n", cpuexec_describe_context(space->machine), space->name, core_i64_hex_format(memory_byte_to_address(space, offset*2), space->addrchars), mem_mask); | |
| 3154 | return space->unmap; | |
| 3155 | } | |
| 3156 | static READ32_HANDLER( unmap_read32 ) | |
| 3157 | { | |
| 3158 | if (space->log_unmap && !space->debugger_access) logerror("%s: unmapped %s memory dword read from %s & %08X\n", cpuexec_describe_context(space->machine), space->name, core_i64_hex_format(memory_byte_to_address(space, offset*4), space->addrchars), mem_mask); | |
| 3159 | return space->unmap; | |
| 3160 | } | |
| 3161 | static READ64_HANDLER( unmap_read64 ) | |
| 3162 | { | |
| 3163 | if (space->log_unmap && !space->debugger_access) logerror("%s: unmapped %s memory qword read from %s & %s\n", cpuexec_describe_context(space->machine), space->name, core_i64_hex_format(memory_byte_to_address(space, offset*8), space->addrchars), core_i64_hex_format(mem_mask, 16)); | |
| 3164 | return space->unmap; | |
| 3165 | } | |
| 3166 | ||
| 3167 | static WRITE8_HANDLER( unmap_write8 ) | |
| 3168 | { | |
| 3169 | if (space->log_unmap && !space->debugger_access) logerror("%s: unmapped %s memory byte write to %s = %02X\n", cpuexec_describe_context(space->machine), space->name, core_i64_hex_format(memory_byte_to_address(space, offset), space->addrchars), data); | |
| 3170 | } | |
| 3171 | static WRITE16_HANDLER( unmap_write16 ) | |
| 3172 | { | |
| 3173 | if (space->log_unmap && !space->debugger_access) logerror("%s: unmapped %s memory word write to %s = %04X & %04X\n", cpuexec_describe_context(space->machine), space->name, core_i64_hex_format(memory_byte_to_address(space, offset*2), space->addrchars), data, mem_mask); | |
| 3174 | } | |
| 3175 | static WRITE32_HANDLER( unmap_write32 ) | |
| 3176 | { | |
| 3177 | if (space->log_unmap && !space->debugger_access) logerror("%s: unmapped %s memory dword write to %s = %08X & %08X\n", cpuexec_describe_context(space->machine), space->name, core_i64_hex_format(memory_byte_to_address(space, offset*4), space->addrchars), data, mem_mask); | |
| 3178 | } | |
| 3179 | static WRITE64_HANDLER( unmap_write64 ) | |
| 3180 | { | |
| 3181 | if (space->log_unmap && !space->debugger_access) logerror("%s: unmapped %s memory qword write to %s = %s & %s\n", cpuexec_describe_context(space->machine), space->name, core_i64_hex_format(memory_byte_to_address(space, offset*8), space->addrchars), core_i64_hex_format(data, 16), core_i64_hex_format(mem_mask, 16)); | |
| 3182 | } | |
| 3183 | ||
| 3184 | ||
| 3185 | /*------------------------------------------------- | |
| 3186 | no-op memory handlers | |
| 3187 | -------------------------------------------------*/ | |
| 3188 | ||
| 3189 | static READ8_HANDLER( nop_read8 ) { return space->unmap; } | |
| 3190 | static READ16_HANDLER( nop_read16 ) { return space->unmap; } | |
| 3191 | static READ32_HANDLER( nop_read32 ) { return space->unmap; } | |
| 3192 | static READ64_HANDLER( nop_read64 ) { return space->unmap; } | |
| 3193 | ||
| 3194 | static WRITE8_HANDLER( nop_write8 ) { } | |
| 3195 | static WRITE16_HANDLER( nop_write16 ) { } | |
| 3196 | static WRITE32_HANDLER( nop_write32 ) { } | |
| 3197 | static WRITE64_HANDLER( nop_write64 ) { } | |
| 3198 | ||
| 3199 | ||
| 3200 | /*------------------------------------------------- | |
| 3201 | watchpoint memory handlers | |
| 3202 | -------------------------------------------------*/ | |
| 3203 | ||
| 3204 | static READ8_HANDLER( watchpoint_read8 ) | |
| 3205 | { | |
| 3206 | address_space *spacerw = (address_space *)space; | |
| 3207 | UINT8 *oldtable = spacerw->readlookup; | |
| 3208 | UINT8 result; | |
| 3209 | ||
| 3210 | spacerw->cpu->debug()->memory_read_hook(*spacerw, offset, 0xff); | |
| 3211 | spacerw->readlookup = space->read.table; | |
| 3212 | result = read_byte_generic(spacerw, offset); | |
| 3213 | spacerw->readlookup = oldtable; | |
| 3214 | return result; | |
| 3215 | } | |
| 3216 | ||
| 3217 | static READ16_HANDLER( watchpoint_read16 ) | |
| 3218 | { | |
| 3219 | address_space *spacerw = (address_space *)space; | |
| 3220 | UINT8 *oldtable = spacerw->readlookup; | |
| 3221 | UINT16 result; | |
| 3222 | ||
| 3223 | spacerw->cpu->debug()->memory_read_hook(*spacerw, offset << 1, mem_mask); | |
| 3224 | spacerw->readlookup = spacerw->read.table; | |
| 3225 | result = read_word_generic(spacerw, offset << 1, mem_mask); | |
| 3226 | spacerw->readlookup = oldtable; | |
| 3227 | return result; | |
| 3228 | } | |
| 3229 | ||
| 3230 | static READ32_HANDLER( watchpoint_read32 ) | |
| 3231 | { | |
| 3232 | address_space *spacerw = (address_space *)space; | |
| 3233 | UINT8 *oldtable = spacerw->readlookup; | |
| 3234 | UINT32 result; | |
| 3235 | ||
| 3236 | spacerw->cpu->debug()->memory_read_hook(*spacerw, offset << 2, mem_mask); | |
| 3237 | spacerw->readlookup = spacerw->read.table; | |
| 3238 | result = read_dword_generic(spacerw, offset << 2, mem_mask); | |
| 3239 | spacerw->readlookup = oldtable; | |
| 3240 | return result; | |
| 3241 | } | |
| 3242 | ||
| 3243 | static READ64_HANDLER( watchpoint_read64 ) | |
| 3244 | { | |
| 3245 | address_space *spacerw = (address_space *)space; | |
| 3246 | UINT8 *oldtable = spacerw->readlookup; | |
| 3247 | UINT64 result; | |
| 3248 | ||
| 3249 | spacerw->cpu->debug()->memory_read_hook(*spacerw, offset << 3, mem_mask); | |
| 3250 | spacerw->readlookup = spacerw->read.table; | |
| 3251 | result = read_qword_generic(spacerw, offset << 3, mem_mask); | |
| 3252 | spacerw->readlookup = oldtable; | |
| 3253 | return result; | |
| 3254 | } | |
| 3255 | ||
| 3256 | static WRITE8_HANDLER( watchpoint_write8 ) | |
| 3257 | { | |
| 3258 | address_space *spacerw = (address_space *)space; | |
| 3259 | UINT8 *oldtable = spacerw->writelookup; | |
| 3260 | ||
| 3261 | spacerw->cpu->debug()->memory_write_hook(*spacerw, offset, data, 0xff); | |
| 3262 | spacerw->writelookup = spacerw->write.table; | |
| 3263 | write_byte_generic(spacerw, offset, data); | |
| 3264 | spacerw->writelookup = oldtable; | |
| 3265 | } | |
| 3266 | ||
| 3267 | static WRITE16_HANDLER( watchpoint_write16 ) | |
| 3268 | { | |
| 3269 | address_space *spacerw = (address_space *)space; | |
| 3270 | UINT8 *oldtable = spacerw->writelookup; | |
| 3271 | ||
| 3272 | spacerw->cpu->debug()->memory_write_hook(*spacerw, offset << 1, data, mem_mask); | |
| 3273 | spacerw->writelookup = spacerw->write.table; | |
| 3274 | write_word_generic(spacerw, offset << 1, data, mem_mask); | |
| 3275 | spacerw->writelookup = oldtable; | |
| 3276 | } | |
| 3277 | ||
| 3278 | static WRITE32_HANDLER( watchpoint_write32 ) | |
| 3279 | { | |
| 3280 | address_space *spacerw = (address_space *)space; | |
| 3281 | UINT8 *oldtable = spacerw->writelookup; | |
| 3282 | ||
| 3283 | spacerw->cpu->debug()->memory_write_hook(*spacerw, offset << 2, data, mem_mask); | |
| 3284 | spacerw->writelookup = spacerw->write.table; | |
| 3285 | write_dword_generic(spacerw, offset << 2, data, mem_mask); | |
| 3286 | spacerw->writelookup = oldtable; | |
| 3287 | } | |
| 3288 | ||
| 3289 | static WRITE64_HANDLER( watchpoint_write64 ) | |
| 3290 | { | |
| 3291 | address_space *spacerw = (address_space *)space; | |
| 3292 | UINT8 *oldtable = spacerw->writelookup; | |
| 3293 | ||
| 3294 | spacerw->cpu->debug()->memory_write_hook(*spacerw, offset << 3, data, mem_mask); | |
| 3295 | spacerw->writelookup = spacerw->write.table; | |
| 3296 | write_qword_generic(spacerw, offset << 3, data, mem_mask); | |
| 3297 | spacerw->writelookup = oldtable; | |
| 3298 | } | |
| 3299 | ||
| 3300 | ||
| 3301 | /*------------------------------------------------- | |
| 3302 | get_static_handler - returns points to static | |
| 3303 | memory handlers | |
| 3304 | -------------------------------------------------*/ | |
| 3305 | ||
| 3306 | static genf *get_static_handler(int handlerbits, int readorwrite, int which) | |
| 3307 | { | |
| 3308 | static const struct | |
| 3309 | { | |
| 3310 | UINT8 handlerbits; | |
| 3311 | UINT8 handlernum; | |
| 3312 | genf * read; | |
| 3313 | genf * write; | |
| 3314 | } static_handler_list[] = | |
| 3315 | { | |
| 3316 | { 8, STATIC_UNMAP, (genf *)unmap_read8, (genf *)unmap_write8 }, | |
| 3317 | { 8, STATIC_NOP, (genf *)nop_read8, (genf *)nop_write8 }, | |
| 3318 | { 8, STATIC_WATCHPOINT, (genf *)watchpoint_read8, (genf *)watchpoint_write8 }, | |
| 3319 | ||
| 3320 | { 16, STATIC_UNMAP, (genf *)unmap_read16, (genf *)unmap_write16 }, | |
| 3321 | { 16, STATIC_NOP, (genf *)nop_read16, (genf *)nop_write16 }, | |
| 3322 | { 16, STATIC_WATCHPOINT, (genf *)watchpoint_read16, (genf *)watchpoint_write16 }, | |
| 3323 | ||
| 3324 | { 32, STATIC_UNMAP, (genf *)unmap_read32, (genf *)unmap_write32 }, | |
| 3325 | { 32, STATIC_NOP, (genf *)nop_read32, (genf *)nop_write32 }, | |
| 3326 | { 32, STATIC_WATCHPOINT, (genf *)watchpoint_read32, (genf *)watchpoint_write32 }, | |
| 3327 | ||
| 3328 | { 64, STATIC_UNMAP, (genf *)unmap_read64, (genf *)unmap_write64 }, | |
| 3329 | { 64, STATIC_NOP, (genf *)nop_read64, (genf *)nop_write64 }, | |
| 3330 | { 64, STATIC_WATCHPOINT, (genf *)watchpoint_read64, (genf *)watchpoint_write64 }, | |
| 3331 | }; | |
| 3332 | int tablenum; | |
| 3333 | ||
| 3334 | for (tablenum = 0; tablenum < sizeof(static_handler_list) / sizeof(static_handler_list[0]); tablenum++) | |
| 3335 | if (static_handler_list[tablenum].handlerbits == handlerbits && static_handler_list[tablenum].handlernum == which) | |
| 3336 | return readorwrite ? static_handler_list[tablenum].write : static_handler_list[tablenum].read; | |
| 3337 | ||
| 3338 | return NULL; | |
| 3339 | } | |
| 3340 | ||
| 3341 | ||
| 3342 | ||
| 3343 | /*************************************************************************** | |
| 3344 | DEBUGGING | |
| 3345 | ***************************************************************************/ | |
| 3346 | ||
| 3347 | /*------------------------------------------------- | |
| 3348 | handler_to_string - return friendly string | |
| 3349 | description of a handler | |
| 3350 | -------------------------------------------------*/ | |
| 3351 | ||
| 3352 | static const char *handler_to_string(const address_space *space, const address_table *table, UINT8 entry) | |
| 3353 | { | |
| 3354 | 3228 | static const char *const strings[] = |
| 3355 | 3229 | { |
| 3356 | 3230 | "invalid", "bank 1", "bank 2", "bank 3", |
| r8806 | r8807 | |
| 3387 | 3261 | "rom", "nop", "unmapped", "watchpoint" |
| 3388 | 3262 | }; |
| 3389 | 3263 | |
| 3390 | / | |
| 3264 | // banks have names | |
| 3391 | 3265 | if (entry >= STATIC_BANK1 && entry <= STATIC_BANKMAX) |
| 3392 | { | |
| 3393 | bank_info *info; | |
| 3394 | for (info = space->machine->memory_data->banklist; info != NULL; info = info->next) | |
| 3395 | if (info->index == entry) | |
| 3396 | return info->name; | |
| 3397 | } | |
| 3266 | for (memory_bank *info = m_space.m_machine.memory_data->banklist.first(); info != NULL; info = info->next()) | |
| 3267 | if (info->index() == entry) | |
| 3268 | return info->name(); | |
| 3398 | 3269 | |
| 3399 | /* constant strings for lower entries */ | |
| 3400 | if (entry < STATIC_COUNT) | |
| 3270 | // constant strings for lower entries | |
| 3271 | if (entry < ARRAY_LENGTH(strings)) | |
| 3401 | 3272 | return strings[entry]; |
| 3273 | else if (handler(entry).name() != NULL) | |
| 3274 | return handler(entry).name(); | |
| 3402 | 3275 | else |
| 3403 | return | |
| 3276 | return | |
| 3404 | 3277 | } |
| 3405 | 3278 | |
| 3406 | 3279 | |
| 3407 | /*------------------------------------------------- | |
| 3408 | dump_map - dump the contents of a single | |
| 3409 | address space | |
| 3410 | -------------------------------------------------*/ | |
| 3280 | //------------------------------------------------- | |
| 3281 | // address_table_read - constructor | |
| 3282 | //------------------------------------------------- | |
| 3411 | 3283 | |
| 3412 | static void dump_map(FILE *file, const address_space *space, const address_table *table) | |
| 3284 | address_table_read::address_table_read(address_space &space, bool large) | |
| 3285 | : address_table(space, large) | |
| 3413 | 3286 | { |
| 3414 | offs_t byteaddress, bytestart, byteend; | |
| 3415 | ||
| 3416 | /* dump generic information */ | |
| 3417 | fprintf(file, " Address bits = %d\n", space->abits); | |
| 3418 | fprintf(file, " Data bits = %d\n", space->dbits); | |
| 3419 | fprintf(file, " L1 bits = %d\n", LEVEL1_BITS); | |
| 3420 | fprintf(file, " L2 bits = %d\n", LEVEL2_BITS); | |
| 3421 | fprintf(file, " Address mask = %X\n", space->bytemask); | |
| 3422 | fprintf(file, "\n"); | |
| 3423 | ||
| 3424 | /* iterate over addresses */ | |
| 3425 | for (byteaddress = 0; byteaddress <= space->bytemask; byteaddress = byteend + 1) | |
| 3287 | // allocate handlers for each entry, prepopulating the bankptrs for banks | |
| 3288 | for (int entrynum = 0; entrynum < ARRAY_LENGTH(m_handlers); entrynum++) | |
| 3426 | 3289 | { |
| 3427 | UINT8 entry = table_derive_range(table, byteaddress, &bytestart, &byteend); | |
| 3428 | fprintf(file, "%08X-%08X = %02X: %s [offset=%08X]\n", | |
| 3429 | bytestart, byteend, entry, handler_to_string(space, table, entry), table->handlers[entry]->bytestart); | |
| 3290 | UINT8 **bankptr = (entrynum >= STATIC_BANK1 && entrynum <= STATIC_BANKMAX) ? &space.m_machine.memory_data->bank_ptr[entrynum] : NULL; | |
| 3291 | m_handlers[entrynum] = auto_alloc(&space.m_machine, handler_entry_read(space.data_width(), space.endianness(), bankptr)); | |
| 3430 | 3292 | } |
| 3431 | } | |
| 3432 | 3293 | |
| 3294 | // we have to allocate different object types based on the data bus width | |
| 3295 | switch (space.data_width()) | |
| 3296 | { | |
| 3297 | // 8-bit case | |
| 3298 | case 8: | |
| 3299 | m_handlers[STATIC_UNMAP]->set_delegate(read8_delegate_create(address_table_read, unmap_r<UINT8>, *this)); | |
| 3300 | m_handlers[STATIC_NOP]->set_delegate(read8_delegate_create(address_table_read, nop_r<UINT8>, *this)); | |
| 3301 | m_handlers[STATIC_WATCHPOINT]->set_delegate(read8_delegate_create(address_table_read, watchpoint_r<UINT8>, *this)); | |
| 3302 | break; | |
| 3433 | 3303 | |
| 3434 | /*------------------------------------------------- | |
| 3435 | mem_dump - internal memory dump | |
| 3436 | -------------------------------------------------*/ | |
| 3304 | // 16-bit case | |
| 3305 | case 16: | |
| 3306 | m_handlers[STATIC_UNMAP]->set_delegate(read16_delegate_create(address_table_read, unmap_r<UINT16>, *this)); | |
| 3307 | m_handlers[STATIC_NOP]->set_delegate(read16_delegate_create(address_table_read, nop_r<UINT16>, *this)); | |
| 3308 | m_handlers[STATIC_WATCHPOINT]->set_delegate(read16_delegate_create(address_table_read, watchpoint_r<UINT16>, *this)); | |
| 3309 | break; | |
| 3437 | 3310 | |
| 3438 | static void mem_dump(running_machine *machine) | |
| 3439 | { | |
| 3440 | FILE *file; | |
| 3311 | // 32-bit case | |
| 3312 | case 32: | |
| 3313 | m_handlers[STATIC_UNMAP]->set_delegate(read32_delegate_create(address_table_read, unmap_r<UINT32>, *this)); | |
| 3314 | m_handlers[STATIC_NOP]->set_delegate(read32_delegate_create(address_table_read, nop_r<UINT32>, *this)); | |
| 3315 | m_handlers[STATIC_WATCHPOINT]->set_delegate(read32_delegate_create(address_table_read, watchpoint_r<UINT32>, *this)); | |
| 3316 | break; | |
| 3441 | 3317 | |
| 3442 | if (MEM_DUMP) | |
| 3443 | { | |
| 3444 | file = fopen("memdump.log", "w"); | |
| 3445 | if (file) | |
| 3446 | { | |
| 3447 | memory_dump(machine, file); | |
| 3448 | fclose(file); | |
| 3449 | } | |
| 3318 | // 64-bit case | |
| 3319 | case 64: | |
| 3320 | m_handlers[STATIC_UNMAP]->set_delegate(read64_delegate_create(address_table_read, unmap_r<UINT64>, *this)); | |
| 3321 | m_handlers[STATIC_NOP]->set_delegate(read64_delegate_create(address_table_read, nop_r<UINT64>, *this)); | |
| 3322 | m_handlers[STATIC_WATCHPOINT]->set_delegate(read64_delegate_create(address_table_read, watchpoint_r<UINT64>, *this)); | |
| 3323 | break; | |
| 3450 | 3324 | } |
| 3325 | ||
| 3326 | // reset the byte masks on the special handlers to open up the full address space for proper reporting | |
| 3327 | m_handlers[STATIC_UNMAP]->configure(0, space.bytemask(), ~0); | |
| 3328 | m_handlers[STATIC_NOP]->configure(0, space.bytemask(), ~0); | |
| 3329 | m_handlers[STATIC_WATCHPOINT]->configure(0, space.bytemask(), ~0); | |
| 3451 | 3330 | } |
| 3452 | 3331 | |
| 3453 | 3332 | |
| 3333 | //------------------------------------------------- | |
| 3334 | // address_table_read - destructor | |
| 3335 | //------------------------------------------------- | |
| 3454 | 3336 | |
| 3455 | /*************************************************************************** | |
| 3456 | INPUT PORT READ HANDLERS | |
| 3457 | ***************************************************************************/ | |
| 3458 | ||
| 3459 | /*------------------------------------------------- | |
| 3460 | input port handlers | |
| 3461 | -------------------------------------------------*/ | |
| 3462 | ||
| 3463 | static UINT8 input_port_read8(const input_port_config *port, offs_t offset) | |
| 3337 | address_table_read::~address_table_read() | |
| 3464 | 3338 | { |
| 3465 | return input_port_read_direct(port); | |
| 3339 | for (int handnum = 0; handnum < ARRAY_LENGTH(m_handlers); handnum++) | |
| 3340 | auto_free(&m_space.m_machine, m_handlers[handnum]); | |
| 3466 | 3341 | } |
| 3467 | 3342 | |
| 3468 | static UINT16 input_port_read16(const input_port_config *port, offs_t offset, UINT16 mem_mask) | |
| 3469 | { | |
| 3470 | return input_port_read_direct(port); | |
| 3471 | } | |
| 3472 | 3343 | |
| 3473 | static UINT32 input_port_read32(const input_port_config *port, offs_t offset, UINT32 mem_mask) | |
| 3344 | //------------------------------------------------- | |
| 3345 | // handler - return the generic handler entry for | |
| 3346 | // this index | |
| 3347 | //------------------------------------------------- | |
| 3348 | ||
| 3349 | handler_entry &address_table_read::handler(UINT32 index) const | |
| 3474 | 3350 | { |
| 3475 | return input_port_read_direct(port); | |
| 3351 | assert(index < ARRAY_LENGTH(m_handlers)); | |
| 3352 | return *m_handlers[index]; | |
| 3476 | 3353 | } |
| 3477 | 3354 | |
| 3478 | static UINT64 input_port_read64(const input_port_config *port, offs_t offset, UINT64 mem_mask) | |
| 3355 | ||
| 3356 | //------------------------------------------------- | |
| 3357 | // address_table_write - constructor | |
| 3358 | //------------------------------------------------- | |
| 3359 | ||
| 3360 | address_table_write::address_table_write(address_space &space, bool large) | |
| 3361 | : address_table(space, large) | |
| 3479 | 3362 | { |
| 3480 | return input_port_read_direct(port); | |
| 3481 | } | |
| 3363 | // allocate handlers for each entry, prepopulating the bankptrs for banks | |
| 3364 | for (int entrynum = 0; entrynum < ARRAY_LENGTH(m_handlers); entrynum++) | |
| 3365 | { | |
| 3366 | UINT8 **bankptr = (entrynum >= STATIC_BANK1 && entrynum <= STATIC_BANKMAX) ? &space.m_machine.memory_data->bank_ptr[entrynum] : NULL; | |
| 3367 | m_handlers[entrynum] = auto_alloc(&space.m_machine, handler_entry_write(space.data_width(), space.endianness(), bankptr)); | |
| 3368 | } | |
| 3482 | 3369 | |
| 3370 | // we have to allocate different object types based on the data bus width | |
| 3371 | switch (space.data_width()) | |
| 3372 | { | |
| 3373 | // 8-bit case | |
| 3374 | case 8: | |
| 3375 | m_handlers[STATIC_UNMAP]->set_delegate(write8_delegate_create(address_table_write, unmap_w<UINT8>, *this)); | |
| 3376 | m_handlers[STATIC_NOP]->set_delegate(write8_delegate_create(address_table_write, nop_w<UINT8>, *this)); | |
| 3377 | m_handlers[STATIC_WATCHPOINT]->set_delegate(write8_delegate_create(address_table_write, watchpoint_w<UINT8>, *this)); | |
| 3378 | break; | |
| 3483 | 3379 | |
| 3380 | // 16-bit case | |
| 3381 | case 16: | |
| 3382 | m_handlers[STATIC_UNMAP]->set_delegate(write16_delegate_create(address_table_write, unmap_w<UINT16>, *this)); | |
| 3383 | m_handlers[STATIC_NOP]->set_delegate(write16_delegate_create(address_table_write, nop_w<UINT16>, *this)); | |
| 3384 | m_handlers[STATIC_WATCHPOINT]->set_delegate(write16_delegate_create(address_table_write, watchpoint_w<UINT16>, *this)); | |
| 3385 | break; | |
| 3484 | 3386 | |
| 3485 | /*------------------------------------------------- | |
| 3486 | output port handlers | |
| 3487 | -------------------------------------------------*/ | |
| 3387 | // 32-bit case | |
| 3388 | case 32: | |
| 3389 | m_handlers[STATIC_UNMAP]->set_delegate(write32_delegate_create(address_table_write, unmap_w<UINT32>, *this)); | |
| 3390 | m_handlers[STATIC_NOP]->set_delegate(write32_delegate_create(address_table_write, nop_w<UINT32>, *this)); | |
| 3391 | m_handlers[STATIC_WATCHPOINT]->set_delegate(write32_delegate_create(address_table_write, watchpoint_w<UINT32>, *this)); | |
| 3392 | break; | |
| 3488 | 3393 | |
| 3489 | static void input_port_write8(const input_port_config *port, offs_t offset, UINT8 data) | |
| 3490 | { | |
| 3491 | input_port_write_direct(port, data, 0xff); | |
| 3492 | } | |
| 3394 | // 64-bit case | |
| 3395 | case 64: | |
| 3396 | m_handlers[STATIC_UNMAP]->set_delegate(write64_delegate_create(address_table_write, unmap_w<UINT64>, *this)); | |
| 3397 | m_handlers[STATIC_NOP]->set_delegate(write64_delegate_create(address_table_write, nop_w<UINT64>, *this)); | |
| 3398 | m_handlers[STATIC_WATCHPOINT]->set_delegate(write64_delegate_create(address_table_write, watchpoint_w<UINT64>, *this)); | |
| 3399 | break; | |
| 3400 | } | |
| 3493 | 3401 | |
| 3494 | static void input_port_write16(const input_port_config *port, offs_t offset, UINT16 data, UINT16 mem_mask) | |
| 3495 | { | |
| 3496 | input_port_write_direct(port, data, mem_mask); | |
| 3402 | // reset the byte masks on the special handlers to open up the full address space for proper reporting | |
| 3403 | m_handlers[STATIC_UNMAP]->configure(0, space.bytemask(), ~0); | |
| 3404 | m_handlers[STATIC_NOP]->configure(0, space.bytemask(), ~0); | |
| 3405 | m_handlers[STATIC_WATCHPOINT]->configure(0, space.bytemask(), ~0); | |
| 3497 | 3406 | } |
| 3498 | 3407 | |
| 3499 | static void input_port_write32(const input_port_config *port, offs_t offset, UINT32 data, UINT32 mem_mask) | |
| 3408 | ||
| 3409 | //------------------------------------------------- | |
| 3410 | // address_table_write - destructor | |
| 3411 | //------------------------------------------------- | |
| 3412 | ||
| 3413 | address_table_write::~address_table_write() | |
| 3500 | 3414 | { |
| 3501 | input_port_write_direct(port, data, mem_mask); | |
| 3415 | for (int handnum = 0; handnum < ARRAY_LENGTH(m_handlers); handnum++) | |
| 3416 | auto_free(&m_space.m_machine, m_handlers[handnum]); | |
| 3502 | 3417 | } |
| 3503 | 3418 | |
| 3504 | static void input_port_write64(const input_port_config *port, offs_t offset, UINT64 data, UINT64 mem_mask) | |
| 3419 | ||
| 3420 | //------------------------------------------------- | |
| 3421 | // handler - return the generic handler entry for | |
| 3422 | // this index | |
| 3423 | //------------------------------------------------- | |
| 3424 | ||
| 3425 | handler_entry &address_table_write::handler(UINT32 index) const | |
| 3505 | 3426 | { |
| 3506 | input_port_write_direct(port, data, mem_mask); | |
| 3427 | assert(index < ARRAY_LENGTH(m_handlers)); | |
| 3428 | return *m_handlers[index]; | |
| 3507 | 3429 | } |
| 3508 | 3430 | |
| 3509 | 3431 | |
| 3510 | 3432 | |
| 3511 | /*************************************************************************** | |
| 3512 | STUB HANDLERS THAT MAP TO BYTE READS | |
| 3513 | ***************************************************************************/ | |
| 3433 | //************************************************************************** | |
| 3434 | // DIRECT MEMORY RANGES | |
| 3435 | //************************************************************************** | |
| 3514 | 3436 | |
| 3515 | /*------------------------------------------------- | |
| 3516 | stub_read8_from_16 - return a 16-bit | |
| 3517 | value combined from one or more byte accesses | |
| 3518 | -------------------------------------------------*/ | |
| 3437 | //------------------------------------------------- | |
| 3438 | // direct_read_data - constructor | |
| 3439 | //------------------------------------------------- | |
| 3519 | 3440 | |
| 3520 | static READ16_HANDLER( stub_read8_from_16 ) | |
| 3441 | direct_read_data::direct_read_data(address_space &space) | |
| 3442 | : m_space(space), | |
| 3443 | m_raw(NULL), | |
| 3444 | m_decrypted(NULL), | |
| 3445 | m_bytemask(space.bytemask()), | |
| 3446 | m_bytestart(1), | |
| 3447 | m_byteend(0), | |
| 3448 | m_entry(STATIC_UNMAP) | |
| 3521 | 3449 | { |
| 3522 | const handler_data *handler = (const handler_data *)space; | |
| 3523 | const UINT8 *subshift = handler->subshift; | |
| 3524 | int subunits = handler->subunits; | |
| 3525 | UINT16 result = 0; | |
| 3526 | ||
| 3527 | offset *= subunits; | |
| 3528 | while (subunits-- != 0) | |
| 3529 | { | |
| 3530 | int shift = *subshift++; | |
| 3531 | if ((UINT8)(mem_mask >> shift) != 0) | |
| 3532 | result |= (*handler->subhandler.read.shandler8)((const address_space *)handler->subobject, offset) << shift; | |
| 3533 | offset++; | |
| 3534 | } | |
| 3535 | return result; | |
| 3536 | 3450 | } |
| 3451 | ||
| 3537 | 3452 | |
| 3453 | //------------------------------------------------- | |
| 3454 | // ~direct_read_data - destructor | |
| 3455 | //------------------------------------------------- | |
| 3538 | 3456 | |
| 3539 | /*------------------------------------------------- | |
| 3540 | stub_read8_from_32 - return a 32-bit | |
| 3541 | value combined from one or more byte accesses | |
| 3542 | -------------------------------------------------*/ | |
| 3543 | ||
| 3544 | static READ32_HANDLER( stub_read8_from_32 ) | |
| 3457 | direct_read_data::~direct_read_data() | |
| 3545 | 3458 | { |
| 3546 | const handler_data *handler = (const handler_data *)space; | |
| 3547 | const UINT8 *subshift = handler->subshift; | |
| 3548 | int subunits = handler->subunits; | |
| 3549 | UINT32 result = 0; | |
| 3550 | ||
| 3551 | offset *= subunits; | |
| 3552 | while (subunits-- != 0) | |
| 3553 | { | |
| 3554 | int shift = *subshift++; | |
| 3555 | if ((UINT8)(mem_mask >> shift) != 0) | |
| 3556 | result |= (*handler->subhandler.read.shandler8)((const address_space *)handler->subobject, offset) << shift; | |
| 3557 | offset++; | |
| 3558 | } | |
| 3559 | return result; | |
| 3560 | 3459 | } |
| 3561 | 3460 | |
| 3562 | 3461 | |
| 3563 | /*------------------------------------------------- | |
| 3564 | stub_read8_from_64 - return a 64-bit | |
| 3565 | value combined from one or more byte accesses | |
| 3566 | -------------------------------------------------*/ | |
| 3462 | //------------------------------------------------- | |
| 3463 | // set_direct_region - called by device cores to | |
| 3464 | // update the opcode base for the given address | |
| 3465 | //------------------------------------------------- | |
| 3567 | 3466 | |
| 3568 | ||
| 3467 | bool direct_read_data::set_direct | |
| 3569 | 3468 | { |
| 3570 | const handler_data *handler = (const handler_data *)space; | |
| 3571 | const UINT8 *subshift = handler->subshift; | |
| 3572 | int subunits = handler->subunits; | |
| 3573 | UINT64 result = 0; | |
| 3469 | // allow overrides | |
| 3470 | offs_t overrideaddress = byteaddress; | |
| 3471 | if (!m_directupdate.isnull()) | |
| 3472 | { | |
| 3473 | overrideaddress = m_directupdate(*this, overrideaddress); | |
| 3474 | if (overrideaddress == ~0) | |
| 3475 | return true; | |
| 3574 | 3476 | |
| 3575 | offset *= subunits; | |
| 3576 | while (subunits-- != 0) | |
| 3577 | { | |
| 3578 | int shift = *subshift++; | |
| 3579 | if ((UINT8)(mem_mask >> shift) != 0) | |
| 3580 | result |= (UINT64)(*handler->subhandler.read.shandler8)((const address_space *)handler->subobject, offset) << shift; | |
| 3581 | offset++; | |
| 3477 | byteaddress = overrideaddress; | |
| 3582 | 3478 | } |
| 3583 | return result; | |
| 3584 | } | |
| 3585 | 3479 | |
| 3480 | // remove the masked bits (we'll put them back later) | |
| 3481 | offs_t maskedbits = overrideaddress & ~m_bytemask; | |
| 3586 | 3482 | |
| 3587 | /*------------------------------------------------- | |
| 3588 | stub_read16_from_32 - return a 32-bit | |
| 3589 | value combined from one or more word accesses | |
| 3590 | -------------------------------------------------*/ | |
| 3483 | // find or allocate a matching range | |
| 3484 | direct_range *range = find_range(overrideaddress, m_entry); | |
| 3591 | 3485 | |
| 3592 | static READ32_HANDLER( stub_read16_from_32 ) | |
| 3593 | { | |
| 3594 | const handler_data *handler = (const handler_data *)space; | |
| 3595 | const UINT8 *subshift = handler->subshift; | |
| 3596 | int subunits = handler->subunits; | |
| 3597 | UINT32 result = 0; | |
| 3598 | ||
| 3599 | offset *= subunits; | |
| 3600 | while (subunits-- != 0) | |
| 3486 | // if we don't map to a bank, return FALSE | |
| 3487 | if (m_entry < STATIC_BANK1 || m_entry >= STATIC_RAM) | |
| 3601 | 3488 | { |
| 3602 | int shift = *subshift++; | |
| 3603 | if ((UINT16)(mem_mask >> shift) != 0) | |
| 3604 | result |= (*handler->subhandler.read.shandler16)((const address_space *)handler->subobject, offset, mem_mask >> shift) << shift; | |
| 3605 | offset++; | |
| 3489 | // ensure future updates to land here as well until we get back into a bank | |
| 3490 | m_byteend = 0; | |
| 3491 | m_bytestart = 1; | |
| 3492 | return false; | |
| 3606 | 3493 | } |
| 3607 | return result; | |
| 3494 | ||
| 3495 | // if no decrypted opcodes, point to the same base | |
| 3496 | UINT8 *base = m_space.m_machine.memory_data->bank_ptr[m_entry]; | |
| 3497 | UINT8 *based = m_space.m_machine.memory_data->bankd_ptr[m_entry]; | |
| 3498 | if (based == NULL) | |
| 3499 | based = base; | |
| 3500 | ||
| 3501 | // compute the adjusted base | |
| 3502 | const handler_entry_read &handler = m_space.read().handler_read(m_entry); | |
| 3503 | m_bytemask = handler.bytemask(); | |
| 3504 | m_raw = base - (handler.bytestart() & m_bytemask); | |
| 3505 | m_decrypted = based - (handler.bytestart() & m_bytemask); | |
| 3506 | m_bytestart = maskedbits | range->m_bytestart; | |
| 3507 | m_byteend = maskedbits | range->m_byteend; | |
| 3508 | return true; | |
| 3608 | 3509 | } |
| 3609 | 3510 | |
| 3610 | 3511 | |
| 3611 | /*------------------------------------------------- | |
| 3612 | stub_read16_from_64 - return a 64-bit | |
| 3613 | value combined from one or more word accesses | |
| 3614 | -------------------------------------------------*/ | |
| 3512 | //------------------------------------------------- | |
| 3513 | // find_range - find a byte address in a range | |
| 3514 | //------------------------------------------------- | |
| 3615 | 3515 | |
| 3616 | ||
| 3516 | direct_read_data::direct | |
| 3617 | 3517 | { |
| 3618 | const handler_data *handler = (const handler_data *)space; | |
| 3619 | const UINT8 *subshift = handler->subshift; | |
| 3620 | int subunits = handler->subunits; | |
| 3621 | UINT64 result = 0; | |
| 3518 | // determine which entry | |
| 3519 | byteaddress &= m_space.m_bytemask; | |
| 3520 | entry = m_space.read().lookup_live(byteaddress); | |
| 3622 | 3521 | |
| 3623 | offset *= subunits; | |
| 3624 | while (subunits-- != 0) | |
| 3625 | { | |
| 3626 | int shift = *subshift++; | |
| 3627 | if ((UINT16)(mem_mask >> shift) != 0) | |
| 3628 | result |= (UINT64)(*handler->subhandler.read.shandler16)((const address_space *)handler->subobject, offset, mem_mask >> shift) << shift; | |
| 3629 | offset++; | |
| 3630 | } | |
| 3631 | return result; | |
| 3632 | } | |
| 3522 | // scan our table | |
| 3523 | for (direct_range *range = m_rangelist[entry].first(); range != NULL; range = range->next()) | |
| 3524 | if (byteaddress >= range->m_bytestart && byteaddress <= range->m_byteend) | |
| 3525 | return range; | |
| 3633 | 3526 | |
| 3527 | // didn't find out; allocate a new one | |
| 3528 | direct_range *range = m_freerangelist.first(); | |
| 3529 | if (range != NULL) | |
| 3530 | m_freerangelist.detach(*range); | |
| 3531 | else | |
| 3532 | range = auto_alloc(&m_space.m_machine, direct_range); | |
| 3634 | 3533 | |
| 3635 | /*------------------------------------------------- | |
| 3636 | stub_read32_from_64 - return a 64-bit | |
| 3637 | value combined from one or more dword accesses | |
| 3638 | -------------------------------------------------*/ | |
| 3534 | // fill in the range | |
| 3535 | m_space.read().derive_range(byteaddress, range->m_bytestart, range->m_byteend); | |
| 3536 | m_rangelist[entry].prepend(*range); | |
| 3639 | 3537 | |
| 3640 | static READ64_HANDLER( stub_read32_from_64 ) | |
| 3641 | { | |
| 3642 | const handler_data *handler = (const handler_data *)space; | |
| 3643 | const UINT8 *subshift = handler->subshift; | |
| 3644 | int subunits = handler->subunits; | |
| 3645 | UINT64 result = 0; | |
| 3646 | ||
| 3647 | offset *= subunits; | |
| 3648 | while (subunits-- != 0) | |
| 3649 | { | |
| 3650 | int shift = *subshift++; | |
| 3651 | if ((UINT32)(mem_mask >> shift) != 0) | |
| 3652 | result |= (UINT64)(*handler->subhandler.read.shandler32)((const address_space *)handler->subobject, offset, mem_mask >> shift) << shift; | |
| 3653 | offset++; | |
| 3654 | } | |
| 3655 | return result; | |
| 3538 | return range; | |
| 3656 | 3539 | } |
| 3657 | 3540 | |
| 3658 | 3541 | |
| 3542 | //------------------------------------------------- | |
| 3543 | // remove_intersecting_ranges - remove all cached | |
| 3544 | // ranges that intersect the given address range | |
| 3545 | //------------------------------------------------- | |
| 3659 | 3546 | |
| 3660 | /*************************************************************************** | |
| 3661 | STUB HANDLERS THAT MAP TO BYTE WRITES | |
| 3662 | ***************************************************************************/ | |
| 3663 | ||
| 3664 | /*------------------------------------------------- | |
| 3665 | stub_write8_from_16 - convert a 16-bit | |
| 3666 | write to one or more byte accesses | |
| 3667 | -------------------------------------------------*/ | |
| 3668 | ||
| 3669 | static WRITE16_HANDLER( stub_write8_from_16 ) | |
| 3547 | void direct_read_data::remove_intersecting_ranges(offs_t bytestart, offs_t byteend) | |
| 3670 | 3548 | { |
| 3671 | const handler_data *handler = (const handler_data *)space; | |
| 3672 | const UINT8 *subshift = handler->subshift; | |
| 3673 | int subunits = handler->subunits; | |
| 3549 | // loop over all entries | |
| 3550 | for (int entry = 0; entry < ARRAY_LENGTH(m_rangelist); entry++) | |
| 3551 | { | |
| 3552 | // loop over all ranges in this entry's list | |
| 3553 | direct_range *nextrange; | |
| 3554 | for (direct_range *range = m_rangelist[entry].first(); range != NULL; range = nextrange) | |
| 3555 | { | |
| 3556 | nextrange = range->next(); | |
| 3674 | 3557 | |
| 3675 | offset *= subunits; | |
| 3676 | while (subunits-- != 0) | |
| 3677 | { | |
| 3678 | int shift = *subshift++; | |
| 3679 | if ((UINT8)(mem_mask >> shift) != 0) | |
| 3680 | (*handler->subhandler.write.shandler8)((const address_space *)handler->subobject, offset, data >> shift); | |
| 3681 | offset++; | |
| 3558 | // if we intersect, remove and add to the free range list | |
| 3559 | if (bytestart <= range->m_byteend && byteend >= range->m_bytestart) | |
| 3560 | { | |
| 3561 | m_rangelist[entry].detach(*range); | |
| 3562 | m_freerangelist.prepend(*range); | |
| 3563 | } | |
| 3564 | } | |
| 3682 | 3565 | } |
| 3683 | 3566 | } |
| 3684 | 3567 | |
| 3685 | 3568 | |
| 3686 | /*------------------------------------------------- | |
| 3687 | stub_write8_from_32 - convert a 32-bit | |
| 3688 | write to one or more byte accesses | |
| 3689 | -------------------------------------------------*/ | |
| 3569 | //------------------------------------------------- | |
| 3570 | // set_direct_update - set a custom direct range | |
| 3571 | // update callback | |
| 3572 | //------------------------------------------------- | |
| 3690 | 3573 | |
| 3691 | ||
| 3574 | direct_update_delegate direct | |
| 3692 | 3575 | { |
| 3693 | const handler_data *handler = (const handler_data *)space; | |
| 3694 | const UINT8 *subshift = handler->subshift; | |
| 3695 | int subunits = handler->subunits; | |
| 3696 | ||
| 3697 | offset *= subunits; | |
| 3698 | while (subunits-- != 0) | |
| 3699 | { | |
| 3700 | int shift = *subshift++; | |
| 3701 | if ((UINT8)(mem_mask >> shift) != 0) | |
| 3702 | (*handler->subhandler.write.shandler8)((const address_space *)handler->subobject, offset, data >> shift); | |
| 3703 | offset++; | |
| 3704 | } | |
| 3576 | direct_update_delegate old = m_directupdate; | |
| 3577 | m_directupdate = function; | |
| 3578 | return old; | |
| 3705 | 3579 | } |
| 3706 | 3580 | |
| 3707 | 3581 | |
| 3708 | /*------------------------------------------------- | |
| 3709 | stub_write8_from_64 - convert a 64-bit | |
| 3710 | write to one or more byte accesses | |
| 3711 | -------------------------------------------------*/ | |
| 3582 | //------------------------------------------------- | |
| 3583 | // explicit_configure - explicitly configure | |
| 3584 | // the start/end/mask and the pointers from | |
| 3585 | // within a custom callback | |
| 3586 | //------------------------------------------------- | |
| 3712 | 3587 | |
| 3713 | ||
| 3588 | void direct_read_data::explicit | |
| 3714 | 3589 | { |
| 3715 | const handler_data *handler = (const handler_data *)space; | |
| 3716 | const UINT8 *subshift = handler->subshift; | |
| 3717 | int subunits = handler->subunits; | |
| 3718 | ||
| 3719 | offset *= subunits; | |
| 3720 | while (subunits-- != 0) | |
| 3721 | { | |
| 3722 | int shift = *subshift++; | |
| 3723 | if ((UINT8)(mem_mask >> shift) != 0) | |
| 3724 | (*handler->subhandler.write.shandler8)((const address_space *)handler->subobject, offset, data >> shift); | |
| 3725 | offset++; | |
| 3726 | } | |
| 3590 | m_bytestart = bytestart; | |
| 3591 | m_byteend = byteend; | |
| 3592 | m_bytemask = bytemask; | |
| 3593 | m_raw = reinterpret_cast<UINT8 *>(raw); | |
| 3594 | m_decrypted = reinterpret_cast<UINT8 *>((decrypted == NULL) ? raw : decrypted); | |
| 3595 | m_raw -= bytestart & bytemask; | |
| 3596 | m_decrypted -= bytestart & bytemask; | |
| 3727 | 3597 | } |
| 3728 | 3598 | |
| 3729 | 3599 | |
| 3730 | /*------------------------------------------------- | |
| 3731 | stub_write16_from_32 - convert a 32-bit | |
| 3732 | write to one or more word accesses | |
| 3733 | -------------------------------------------------*/ | |
| 3734 | 3600 | |
| 3735 | static WRITE32_HANDLER( stub_write16_from_32 ) | |
| 3736 | { | |
| 3737 | const handler_data *handler = (const handler_data *)space; | |
| 3738 | const UINT8 *subshift = handler->subshift; | |
| 3739 | int subunits = handler->subunits; | |
| 3601 | //************************************************************************** | |
| 3602 | // MEMORY BLOCK | |
| 3603 | //************************************************************************** | |
| 3740 | 3604 | |
| 3741 | offset *= subunits; | |
| 3742 | while (subunits-- != 0) | |
| 3743 | { | |
| 3744 | int shift = *subshift++; | |
| 3745 | if ((UINT16)(mem_mask >> shift) != 0) | |
| 3746 | (*handler->subhandler.write.shandler16)((const address_space *)handler->subobject, offset, data >> shift, mem_mask >> shift); | |
| 3747 | offset++; | |
| 3748 | } | |
| 3749 | } | |
| 3605 | //------------------------------------------------- | |
| 3606 | // memory_block - constructor | |
| 3607 | //------------------------------------------------- | |
| 3750 | 3608 | |
| 3609 | memory_block::memory_block(address_space &space, offs_t bytestart, offs_t byteend, void *memory) | |
| 3610 | : m_next(NULL), | |
| 3611 | m_machine(space.m_machine), | |
| 3612 | m_space(space), | |
| 3613 | m_isallocated(memory == NULL), | |
| 3614 | m_bytestart(bytestart), | |
| 3615 | m_byteend(byteend), | |
| 3616 | m_data((memory != NULL) ? reinterpret_cast<UINT8 *>(memory) : auto_alloc_array_clear(&space.m_machine, UINT8, byteend + 1 - bytestart)) | |
| 3617 | { | |
| 3618 | VPRINTF(("block_allocate('%s',%s,%08X,%08X,%p)\n", space.device().tag(), space.name(), bytestart, byteend, memory)); | |
| 3751 | 3619 | |
| 3752 | /*------------------------------------------------- | |
| 3753 | stub_write16_from_64 - convert a 64-bit | |
| 3754 | write to one or more word accesses | |
| 3755 | -------------------------------------------------*/ | |
| 3620 | // register for saving, but only if we're not part of a memory region | |
| 3621 | const region_info *region; | |
| 3622 | for (region = space.m_machine.m_regionlist.first(); region != NULL; region = region->next()) | |
| 3623 | if (m_data >= region->base() && (m_data + (byteend - bytestart + 1)) < region->end()) | |
| 3624 | { | |
| 3625 | VPRINTF(("skipping save of this memory block as it is covered by a memory region\n")); | |
| 3626 | break; | |
| 3627 | } | |
| 3756 | 3628 | |
| 3757 | static WRITE64_HANDLER( stub_write16_from_64 ) | |
| 3758 | { | |
| 3759 | const handler_data *handler = (const handler_data *)space; | |
| 3760 | const UINT8 *subshift = handler->subshift; | |
| 3761 | int subunits = handler->subunits; | |
| 3762 | ||
| 3763 | offset *= subunits; | |
| 3764 | while (subunits-- != 0) | |
| 3629 | // if we didn't find a match, register | |
| 3630 | if (region == NULL) | |
| 3765 | 3631 | { |
| 3766 | int shift = *subshift++; | |
| 3767 | if ((UINT16)(mem_mask >> shift) != 0) | |
| 3768 | (*handler->subhandler.write.shandler16)((const address_space *)handler->subobject, offset, data >> shift, mem_mask >> shift); | |
| 3769 | offset++; | |
| 3632 | int bytes_per_element = space.data_width() / 8; | |
| 3633 | astring name; | |
| 3634 | name.printf("%08x-%08x", bytestart, byteend); | |
| 3635 | state_save_register_memory(&space.m_machine, "memory", space.device().tag(), space.spacenum(), name, m_data, bytes_per_element, (UINT32)(byteend + 1 - bytestart) / bytes_per_element, __FILE__, __LINE__); | |
| 3770 | 3636 | } |
| 3771 | 3637 | } |
| 3772 | 3638 | |
| 3773 | 3639 | |
| 3774 | /*------------------------------------------------- | |
| 3775 | stub_write32_from_64 - convert a 64-bit | |
| 3776 | write to one or more word accesses | |
| 3777 | -------------------------------------------------*/ | |
| 3640 | //------------------------------------------------- | |
| 3641 | // memory_block - destructor | |
| 3642 | //------------------------------------------------- | |
| 3778 | 3643 | |
| 3779 | ||
| 3644 | m | |
| 3780 | 3645 | { |
| 3781 | const handler_data *handler = (const handler_data *)space; | |
| 3782 | const UINT8 *subshift = handler->subshift; | |
| 3783 | int subunits = handler->subunits; | |
| 3784 | ||
| 3785 | offset *= subunits; | |
| 3786 | while (subunits-- != 0) | |
| 3787 | { | |
| 3788 | int shift = *subshift++; | |
| 3789 | if ((UINT32)(mem_mask >> shift) != 0) | |
| 3790 | (*handler->subhandler.write.shandler32)((const address_space *)handler->subobject, offset, data >> shift, mem_mask >> shift); | |
| 3791 | offset++; | |
| 3792 | } | |
| 3646 | if (m_isallocated) | |
| 3647 | auto_free(&m_machine, m_data); | |
| 3793 | 3648 | } |
| 3794 | 3649 | |
| 3795 | 3650 | |
| 3796 | 3651 | |
| 3797 | /*************************************************************************** | |
| 3798 | STUB ACCESSORS | |
| 3799 | ***************************************************************************/ | |
| 3652 | //************************************************************************** | |
| 3653 | // MEMORY BANK | |
| 3654 | //************************************************************************** | |
| 3800 | 3655 | |
| 3801 | /*------------------------------------------------- | |
| 3802 | get_stub_handler - return the appropriate | |
| 3803 | stub handler | |
| 3804 | -------------------------------------------------*/ | |
| 3656 | //------------------------------------------------- | |
| 3657 | // memory_bank - constructor | |
| 3658 | //------------------------------------------------- | |
| 3805 | 3659 | |
| 3806 | static memory_handler get_stub_handler(read_or_write readorwrite, int spacedbits, int handlerdbits) | |
| 3660 | memory_bank::memory_bank(address_space &space, int index, offs_t bytestart, offs_t byteend, const char *tag) | |
| 3661 | : m_next(NULL), | |
| 3662 | m_machine(space.m_machine), | |
| 3663 | m_baseptr(&space.m_machine.memory_data->bank_ptr[index]), | |
| 3664 | m_basedptr(&space.m_machine.memory_data->bankd_ptr[index]), | |
| 3665 | m_index(index), | |
| 3666 | m_anonymous(tag == NULL), | |
| 3667 | m_bytestart(bytestart), | |
| 3668 | m_byteend(byteend), | |
| 3669 | m_curentry(BANK_ENTRY_UNSPECIFIED), | |
| 3670 | m_entry(NULL), | |
| 3671 | m_entry_count(0) | |
| 3807 | 3672 | { |
| 3808 | memory_handler result = { 0 }; | |
| 3809 | ||
| 3810 | /* read stubs */ | |
| 3811 | if (readorwrite == ROW_READ) | |
| 3673 | // generate an internal tag if we don't have one | |
| 3674 | if (tag == NULL) | |
| 3812 | 3675 | { |
| 3813 | /* 16-bit read stubs */ | |
| 3814 | if (spacedbits == 16) | |
| 3815 | { | |
| 3816 | if (handlerdbits == 8) | |
| 3817 | result.read.shandler16 = stub_read8_from_16; | |
| 3818 | } | |
| 3819 | ||
| 3820 | /* 32-bit read stubs */ | |
| 3821 | else if (spacedbits == 32) | |
| 3822 | { | |
| 3823 | if (handlerdbits == 8) | |
| 3824 | result.read.shandler32 = stub_read8_from_32; | |
| 3825 | else if (handlerdbits == 16) | |
| 3826 | result.read.shandler32 = stub_read16_from_32; | |
| 3827 | } | |
| 3828 | ||
| 3829 | /* 64-bit read stubs */ | |
| 3830 | else if (spacedbits == 64) | |
| 3831 | { | |
| 3832 | if (handlerdbits == 8) | |
| 3833 | result.read.shandler64 = stub_read8_from_64; | |
| 3834 | else if (handlerdbits == 16) | |
| 3835 | result.read.shandler64 = stub_read16_from_64; | |
| 3836 | else if (handlerdbits == 32) | |
| 3837 | result.read.shandler64 = stub_read32_from_64; | |
| 3838 | } | |
| 3676 | m_tag.printf("~%d~", index); | |
| 3677 | m_name.printf("Internal bank #%d", index); | |
| 3839 | 3678 | } |
| 3840 | ||
| 3841 | /* write stubs */ | |
| 3842 | else if (readorwrite == ROW_WRITE) | |
| 3679 | else | |
| 3843 | 3680 | { |
| 3844 | /* 16-bit write stubs */ | |
| 3845 | if (spacedbits == 16) | |
| 3846 | { | |
| 3847 | if (handlerdbits == 8) | |
| 3848 | result.write.shandler16 = stub_write8_from_16; | |
| 3849 | } | |
| 3850 | ||
| 3851 | /* 32-bit write stubs */ | |
| 3852 | else if (spacedbits == 32) | |
| 3853 | { | |
| 3854 | if (handlerdbits == 8) | |
| 3855 | result.write.shandler32 = stub_write8_from_32; | |
| 3856 | else if (handlerdbits == 16) | |
| 3857 | result.write.shandler32 = stub_write16_from_32; | |
| 3858 | } | |
| 3859 | ||
| 3860 | /* 64-bit write stubs */ | |
| 3861 | else if (spacedbits == 64) | |
| 3862 | { | |
| 3863 | if (handlerdbits == 8) | |
| 3864 | result.write.shandler64 = stub_write8_from_64; | |
| 3865 | else if (handlerdbits == 16) | |
| 3866 | result.write.shandler64 = stub_write16_from_64; | |
| 3867 | else if (handlerdbits == 32) | |
| 3868 | result.write.shandler64 = stub_write32_from_64; | |
| 3869 | } | |
| 3681 | m_tag.cpy(tag); | |
| 3682 | m_name.printf("Bank '%s'", tag); | |
| 3870 | 3683 | } |
| 3871 | 3684 | |
| 3872 | assert(result.read.generic != NULL); | |
| 3873 | return result; | |
| 3685 | if (!m_anonymous && state_save_registration_allowed(&space.m_machine)) | |
| 3686 | state_save_register_item(&space.m_machine, "memory", m_tag, 0, m_curentry); | |
| 3874 | 3687 | } |
| 3875 | 3688 | |
| 3876 | 3689 | |
| 3690 | //------------------------------------------------- | |
| 3691 | // memory_bank - destructor | |
| 3692 | //------------------------------------------------- | |
| 3877 | 3693 | |
| 3878 | /*************************************************************************** | |
| 3879 | 8-BIT READ HANDLERS | |
| 3880 | ***************************************************************************/ | |
| 3881 | ||
| 3882 | UINT8 memory_read_byte_8le(const address_space *space, offs_t address) | |
| 3694 | memory_bank::~memory_bank() | |
| 3883 | 3695 | { |
| 3884 | | |
| 3696 | | |
| 3885 | 3697 | } |
| 3886 | 3698 | |
| 3887 | UINT8 memory_read_byte_8be(const address_space *space, offs_t address) | |
| 3888 | { | |
| 3889 | return read_byte_generic(space, address); | |
| 3890 | } | |
| 3891 | 3699 | |
| 3892 | UINT16 memory_read_word_8le(const address_space *space, offs_t address) | |
| 3893 | { | |
| 3894 | UINT16 result = memory_read_byte_8le(space, address + 0) << 0; | |
| 3895 | return result | (memory_read_byte_8le(space, address + 1) << 8); | |
| 3896 | } | |
| 3700 | //------------------------------------------------- | |
| 3701 | // references_space - walk the list of references | |
| 3702 | // to find a match against the provided space | |
| 3703 | // and read/write | |
| 3704 | //------------------------------------------------- | |
| 3897 | 3705 | |
| 3898 | ||
| 3706 | bool | |
| 3899 | 3707 | { |
| 3900 | UINT16 result = 0; | |
| 3901 | if (mask & 0x00ff) result |= memory_read_byte_8le(space, address + 0) << 0; | |
| 3902 | if (mask & 0xff00) result |= memory_read_byte_8le(space, address + 1) << 8; | |
| 3903 | return result; | |
| 3708 | for (bank_reference *ref = m_reflist.first(); ref != NULL; ref = ref->next()) | |
| 3709 | if (ref->matches(space, readorwrite)) | |
| 3710 | return true; | |
| 3711 | return false; | |
| 3904 | 3712 | } |
| 3905 | 3713 | |
| 3906 | UINT16 memory_read_word_8be(const address_space *space, offs_t address) | |
| 3907 | { | |
| 3908 | UINT16 result = memory_read_byte_8be(space, address + 0) << 8; | |
| 3909 | return result | (memory_read_byte_8be(space, address + 1) << 0); | |
| 3910 | } | |
| 3911 | 3714 | |
| 3912 | UINT16 memory_read_word_masked_8be(const address_space *space, offs_t address, UINT16 mask) | |
| 3913 | { | |
| 3914 | UINT16 result = 0; | |
| 3915 | if (mask & 0xff00) result |= memory_read_byte_8be(space, address + 0) << 8; | |
| 3916 | if (mask & 0x00ff) result |= memory_read_byte_8be(space, address + 1) << 0; | |
| 3917 | return result; | |
| 3918 | } | |
| 3715 | //------------------------------------------------- | |
| 3716 | // add_reference - add a new reference to the | |
| 3717 | // given space | |
| 3718 | //------------------------------------------------- | |
| 3919 | 3719 | |
| 3920 | ||
| 3720 | void | |
| 3921 | 3721 | { |
| 3922 | UINT32 result = memory_read_word_8le(space, address + 0) << 0; | |
| 3923 | return result | (memory_read_word_8le(space, address + 2) << 16); | |
| 3722 | // if we already have a reference, skip it | |
| 3723 | if (references_space(space, readorwrite)) | |
| 3724 | return; | |
| 3725 | m_reflist.append(*auto_alloc(&space.m_machine, bank_reference(space, readorwrite))); | |
| 3924 | 3726 | } |
| 3925 | 3727 | |
| 3926 | UINT32 memory_read_dword_masked_8le(const address_space *space, offs_t address, UINT32 mask) | |
| 3927 | { | |
| 3928 | UINT32 result = 0; | |
| 3929 | if (mask & 0x0000ffff) result |= memory_read_word_masked_8le(space, address + 0, mask >> 0) << 0; | |
| 3930 | if (mask & 0xffff0000) result |= memory_read_word_masked_8le(space, address + 2, mask >> 16) << 16; | |
| 3931 | return result; | |
| 3932 | } | |
| 3933 | 3728 | |
| 3934 | UINT32 memory_read_dword_8be(const address_space *space, offs_t address) | |
| 3935 | { | |
| 3936 | UINT32 result = memory_read_word_8be(space, address + 0) << 16; | |
| 3937 | return result | (memory_read_word_8be(space, address + 2) << 0); | |
| 3938 | } | |
| 3729 | //------------------------------------------------- | |
| 3730 | // invalidate_references - force updates on all | |
| 3731 | // referencing address spaces | |
| 3732 | //------------------------------------------------- | |
| 3939 | 3733 | |
| 3940 | ||
| 3734 | void | |
| 3941 | 3735 | { |
| 3942 | UINT32 result = 0; | |
| 3943 | if (mask & 0xffff0000) result |= memory_read_word_masked_8be(space, address + 0, mask >> 16) << 16; | |
| 3944 | if (mask & 0x0000ffff) result |= memory_read_word_masked_8be(space, address + 2, mask >> 0) << 0; | |
| 3945 | return result; | |
| 3736 | // invalidate all the direct references to any referenced address spaces | |
| 3737 | for (bank_reference *ref = m_reflist.first(); ref != NULL; ref = ref->next()) | |
| 3738 | ref->space().direct().force_update(); | |
| 3946 | 3739 | } |
| 3947 | 3740 | |
| 3948 | UINT64 memory_read_qword_8le(const address_space *space, offs_t address) | |
| 3949 | { | |
| 3950 | UINT64 result = (UINT64)memory_read_dword_8le(space, address + 0) << 0; | |
| 3951 | return result | ((UINT64)memory_read_dword_8le(space, address + 4) << 32); | |
| 3952 | } | |
| 3953 | 3741 | |
| 3954 | UINT64 memory_read_qword_masked_8le(const address_space *space, offs_t address, UINT64 mask) | |
| 3955 | { | |
| 3956 | UINT64 result = 0; | |
| 3957 | if (mask & U64(0x00000000ffffffff)) result |= (UINT64)memory_read_dword_masked_8le(space, address + 0, mask >> 0) << 0; | |
| 3958 | if (mask & U64(0xffffffff00000000)) result |= (UINT64)memory_read_dword_masked_8le(space, address + 4, mask >> 32) << 32; | |
| 3959 | return result; | |
| 3960 | } | |
| 3742 | //------------------------------------------------- | |
| 3743 | // set_base - set the bank base explicitly | |
| 3744 | //------------------------------------------------- | |
| 3961 | 3745 | |
| 3962 | ||
| 3746 | void | |
| 3963 | 3747 | { |
| 3964 | UINT64 result = (UINT64)memory_read_dword_8be(space, address + 0) << 32; | |
| 3965 | return result | ((UINT64)memory_read_dword_8be(space, address + 4) << 0); | |
| 3966 | } | |
| 3748 | // NULL is not an option | |
| 3749 | if (base == NULL) | |
| 3750 | throw emu_fatalerror("memory_bank::set_base called NULL base"); | |
| 3967 | 3751 | |
| 3968 | UINT64 memory_read_qword_masked_8be(const address_space *space, offs_t address, UINT64 mask) | |
| 3969 | { | |
| 3970 | UINT64 result = 0; | |
| 3971 | if (mask & U64(0xffffffff00000000)) result |= (UINT64)memory_read_dword_masked_8be(space, address + 0, mask >> 32) << 32; | |
| 3972 | if (mask & U64(0x00000000ffffffff)) result |= (UINT64)memory_read_dword_masked_8be(space, address + 4, mask >> 0) << 0; | |
| 3973 | return result; | |
| 3752 | // set the base and invalidate any referencing spaces | |
| 3753 | *m_baseptr = reinterpret_cast<UINT8 *>(base); | |
| 3754 | invalidate_references(); | |
| 3974 | 3755 | } |
| 3975 | 3756 | |
| 3976 | 3757 | |
| 3758 | //------------------------------------------------- | |
| 3759 | // set_base_decrypted - set the decrypted base | |
| 3760 | // explicitly | |
| 3761 | //------------------------------------------------- | |
| 3977 | 3762 | |
| 3978 | /*************************************************************************** | |
| 3979 | 8-BIT WRITE HANDLERS | |
| 3980 | ***************************************************************************/ | |
| 3981 | ||
| 3982 | void memory_write_byte_8le(const address_space *space, offs_t address, UINT8 data) | |
| 3763 | void memory_bank::set_base_decrypted(void *base) | |
| 3983 | 3764 | { |
| 3984 | write_byte_generic(space, address, data); | |
| 3985 | } | |
| 3765 | // NULL is not an option | |
| 3766 | if (base == NULL) | |
| 3767 | throw emu_fatalerror("memory_bank::set_base called NULL base"); | |
| 3986 | 3768 | |
| 3987 | void memory_write_byte_8be(const address_space *space, offs_t address, UINT8 data) | |
| 3988 | { | |
| 3989 | write_byte_generic(space, address, data); | |
| 3769 | // set the base and invalidate any referencing spaces | |
| 3770 | *m_basedptr = reinterpret_cast<UINT8 *>(base); | |
| 3771 | invalidate_references(); | |
| 3990 | 3772 | } |
| 3991 | 3773 | |
| 3992 | void memory_write_word_8le(const address_space *space, offs_t address, UINT16 data) | |
| 3993 | { | |
| 3994 | memory_write_byte_8le(space, address + 0, data >> 0); | |
| 3995 | memory_write_byte_8le(space, address + 1, data >> 8); | |
| 3996 | } | |
| 3997 | 3774 | |
| 3998 | void memory_write_word_masked_8le(const address_space *space, offs_t address, UINT16 data, UINT16 mask) | |
| 3999 | { | |
| 4000 | if (mask & 0x00ff) memory_write_byte_8le(space, address + 0, data >> 0); | |
| 4001 | if (mask & 0xff00) memory_write_byte_8le(space, address + 1, data >> 8); | |
| 4002 | } | |
| 3775 | //------------------------------------------------- | |
| 3776 | // set_entry - set the base to a pre-configured | |
| 3777 | // entry | |
| 3778 | //------------------------------------------------- | |
| 4003 | 3779 | |
| 4004 | void memory_ | |
| 3780 | void memory_ | |
| 4005 | 3781 | { |
| 4006 | memory_write_byte_8be(space, address + 0, data >> 8); | |
| 4007 | memory_write_byte_8be(space, address + 1, data >> 0); | |
| 4008 | } | |
| 3782 | // validate | |
| 3783 | if (m_anonymous) | |
| 3784 | throw emu_fatalerror("memory_bank::set_entry called for anonymous bank"); | |
| 3785 | if (entrynum < 0 || entrynum >= m_entry_count) | |
| 3786 | throw emu_fatalerror("memory_bank::set_entry called with out-of-range entry %d", entrynum); | |
| 3787 | if (m_entry[entrynum].m_raw == NULL) | |
| 3788 | throw emu_fatalerror("memory_bank::set_entry called for bank '%s' with invalid bank entry %d", m_tag.cstr(), entrynum); | |
| 4009 | 3789 | |
| 4010 | void memory_write_word_masked_8be(const address_space *space, offs_t address, UINT16 data, UINT16 mask) | |
| 4011 | { | |
| 4012 | if (mask & 0xff00) memory_write_byte_8be(space, address + 0, data >> 8); | |
| 4013 | if (mask & 0x00ff) memory_write_byte_8be(space, address + 1, data >> 0); | |
| 4014 | } | |
| 3790 | // set both raw and decrypted values | |
| 3791 | m_curentry = entrynum; | |
| 3792 | *m_baseptr = m_entry[entrynum].m_raw; | |
| 3793 | *m_basedptr = m_entry[entrynum].m_decrypted; | |
| 4015 | 3794 | |
| 4016 | void memory_write_dword_8le(const address_space *space, offs_t address, UINT32 data) | |
| 4017 | { | |
| 4018 | memory_write_word_8le(space, address + 0, data >> 0); | |
| 4019 | memory_write_word_8le(space, address + 2, data >> 16); | |
| 3795 | // invalidate referencing spaces | |
| 3796 | invalidate_references(); | |
| 4020 | 3797 | } |
| 4021 | 3798 | |
| 4022 | void memory_write_dword_masked_8le(const address_space *space, offs_t address, UINT32 data, UINT32 mask) | |
| 4023 | { | |
| 4024 | if (mask & 0x0000ffff) memory_write_word_masked_8le(space, address + 0, data >> 0, mask >> 0); | |
| 4025 | if (mask & 0xffff0000) memory_write_word_masked_8le(space, address + 2, data >> 16, mask >> 16); | |
| 4026 | } | |
| 4027 | 3799 | |
| 4028 | void memory_write_dword_8be(const address_space *space, offs_t address, UINT32 data) | |
| 4029 | { | |
| 4030 | memory_write_word_8be(space, address + 0, data >> 16); | |
| 4031 | memory_write_word_8be(space, address + 2, data >> 0); | |
| 4032 | } | |
| 3800 | //------------------------------------------------- | |
| 3801 | // expand_entries - expand the allocated array | |
| 3802 | // of entries | |
| 3803 | //------------------------------------------------- | |
| 4033 | 3804 | |
| 4034 | void memory_ | |
| 3805 | void memory_b | |
| 4035 | 3806 | { |
| 4036 | if (mask & 0xffff0000) memory_write_word_masked_8be(space, address + 0, data >> 16, mask >> 16); | |
| 4037 | if (mask & 0x0000ffff) memory_write_word_masked_8be(space, address + 2, data >> 0, mask >> 0); | |
| 4038 | } | |
| 3807 | int newcount = entrynum + 1; | |
| 3808 | ||
| 3809 | // allocate a new array and copy from the old one; zero out the new entries | |
| 3810 | bank_entry *newentry = auto_alloc_array(&m_machine, bank_entry, newcount); | |
| 3811 | memcpy(newentry, m_entry, sizeof(m_entry[0]) * m_entry_count); | |
| 3812 | memset(&newentry[m_entry_count], 0, (newcount - m_entry_count) * sizeof(m_entry[0])); | |
| 4039 | 3813 | |
| 4040 | void memory_write_qword_8le(const address_space *space, offs_t address, UINT64 data) | |
| 4041 | { | |
| 4042 | memory_write_dword_8le(space, address + 0, data >> 0); | |
| 4043 | memory_write_dword_8le(space, address + 4, data >> 32); | |
| 3814 | // free the old array and set the updated values | |
| 3815 | auto_free(&m_machine, m_entry); | |
| 3816 | m_entry = newentry; | |
| 3817 | m_entry_count = newcount; | |
| 4044 | 3818 | } |
| 4045 | 3819 | |
| 4046 | void memory_write_qword_masked_8le(const address_space *space, offs_t address, UINT64 data, UINT64 mask) | |
| 4047 | { | |
| 4048 | if (mask & U64(0x00000000ffffffff)) memory_write_dword_masked_8le(space, address + 0, data >> 0, mask >> 0); | |
| 4049 | if (mask & U64(0xffffffff00000000)) memory_write_dword_masked_8le(space, address + 4, data >> 32, mask >> 32); | |
| 4050 | } | |
| 4051 | 3820 | |
| 4052 | void memory_write_qword_8be(const address_space *space, offs_t address, UINT64 data) | |
| 4053 | { | |
| 4054 | memory_write_dword_8be(space, address + 0, data >> 32); | |
| 4055 | memory_write_dword_8be(space, address + 4, data >> 0); | |
| 4056 | } | |
| 3821 | //------------------------------------------------- | |
| 3822 | // configure - configure an entry | |
| 3823 | //------------------------------------------------- | |
| 4057 | 3824 | |
| 4058 | void memory_ | |
| 3825 | void memory_b | |
| 4059 | 3826 | { |
| 4060 | if (mask & U64(0xffffffff00000000)) memory_write_dword_masked_8be(space, address + 0, data >> 32, mask >> 32); | |
| 4061 | if (mask & U64(0x00000000ffffffff)) memory_write_dword_masked_8be(space, address + 4, data >> 0, mask >> 0); | |
| 4062 | } | |
| 3827 | // must be positive | |
| 3828 | if (entrynum < 0) | |
| 3829 | throw emu_fatalerror("memory_bank::configure called with out-of-range entry %d", entrynum); | |
| 4063 | 3830 | |
| 3831 | // if we haven't allocated this many entries yet, expand our array | |
| 3832 | if (entrynum >= m_entry_count) | |
| 3833 | expand_entries(entrynum); | |
| 4064 | 3834 | |
| 3835 | // set the entry | |
| 3836 | m_entry[entrynum].m_raw = reinterpret_cast<UINT8 *>(base); | |
| 4065 | 3837 | |
| 4066 | /*************************************************************************** | |
| 4067 | 16-BIT READ HANDLERS | |
| 4068 | ***************************************************************************/ | |
| 4069 | ||
| 4070 | UINT8 memory_read_byte_16le(const address_space *space, offs_t address) | |
| 4071 | { | |
| 4072 | UINT32 shift = (address & 1) * 8; | |
| 4073 | return read_word_generic(space, address, 0xff << shift) >> shift; | |
| 3838 | // if the bank base is not configured, and we're the first entry, set us up | |
| 3839 | if (*m_baseptr == NULL && entrynum == 0) | |
| 3840 | *m_baseptr = m_entry[entrynum].m_raw; | |
| 4074 | 3841 | } |
| 4075 | 3842 | |
| 4076 | UINT8 memory_read_byte_16be(const address_space *space, offs_t address) | |
| 4077 | { | |
| 4078 | UINT32 shift = (~address & 1) * 8; | |
| 4079 | return read_word_generic(space, address, 0xff << shift) >> shift; | |
| 4080 | } | |
| 4081 | 3843 | |
| 4082 | UINT16 memory_read_word_16le(const address_space *space, offs_t address) | |
| 4083 | { | |
| 4084 | return read_word_generic(space, address, 0xffff); | |
| 4085 | } | |
| 3844 | //------------------------------------------------- | |
| 3845 | // configure_decrypted - configure a decrypted | |
| 3846 | // entry | |
| 3847 | //------------------------------------------------- | |
| 4086 | 3848 | |
| 4087 | ||
| 3849 | void | |
| 4088 | 3850 | { |
| 4089 | return read_word_generic(space, address, mask); | |
| 4090 | } | |
| 3851 | // must be positive | |
| 3852 | if (entrynum < 0) | |
| 3853 | throw emu_fatalerror("memory_bank::configure called with out-of-range entry %d", entrynum); | |
| 4091 | 3854 | |
| 4092 | UINT16 memory_read_word_16be(const address_space *space, offs_t address) | |
| 4093 | { | |
| 4094 | return read_word_generic(space, address, 0xffff); | |
| 4095 | } | |
| 3855 | // if we haven't allocated this many entries yet, expand our array | |
| 3856 | if (entrynum >= m_entry_count) | |
| 3857 | expand_entries(entrynum); | |
| 4096 | 3858 | |
| 4097 | UINT16 memory_read_word_masked_16be(const address_space *space, offs_t address, UINT16 mask) | |
| 4098 | { | |
| 4099 | return read_word_generic(space, address, mask); | |
| 4100 | } | |
| 3859 | // set the entry | |
| 3860 | m_entry[entrynum].m_decrypted = reinterpret_cast<UINT8 *>(base); | |
| 4101 | 3861 | |
| 4102 | UINT32 memory_read_dword_16le(const address_space *space, offs_t address) | |
| 4103 | { | |
| 4104 | UINT32 result = memory_read_word_16le(space, address + 0) << 0; | |
| 4105 | return result | (memory_read_word_16le(space, address + 2) << 16); | |
| 3862 | // if the bank base is not configured, and we're the first entry, set us up | |
| 3863 | if (*m_basedptr == NULL && entrynum == 0) | |
| 3864 | *m_basedptr = m_entry[entrynum].m_decrypted; | |
| 4106 | 3865 | } |
| 4107 | 3866 | |
| 4108 | UINT32 memory_read_dword_masked_16le(const address_space *space, offs_t address, UINT32 mask) | |
| 4109 | { | |
| 4110 | UINT32 result = 0; | |
| 4111 | if (mask & 0x0000ffff) result |= memory_read_word_masked_16le(space, address + 0, mask >> 0) << 0; | |
| 4112 | if (mask & 0xffff0000) result |= memory_read_word_masked_16le(space, address + 2, mask >> 16) << 16; | |
| 4113 | return result; | |
| 4114 | } | |
| 4115 | 3867 | |
| 4116 | UINT32 memory_read_dword_16be(const address_space *space, offs_t address) | |
| 4117 | { | |
| 4118 | UINT32 result = memory_read_word_16be(space, address + 0) << 16; | |
| 4119 | return result | (memory_read_word_16be(space, address + 2) << 0); | |
| 4120 | } | |
| 4121 | 3868 | |
| 4122 | UINT32 memory_read_dword_masked_16be(const address_space *space, offs_t address, UINT32 mask) | |
| 4123 | { | |
| 4124 | UINT32 result = 0; | |
| 4125 | if (mask & 0xffff0000) result |= memory_read_word_masked_16be(space, address + 0, mask >> 16) << 16; | |
| 4126 | if (mask & 0x0000ffff) result |= memory_read_word_masked_16be(space, address + 2, mask >> 0) << 0; | |
| 4127 | return result; | |
| 4128 | } | |
| 3869 | //************************************************************************** | |
| 3870 | // HANDLER ENTRY | |
| 3871 | //************************************************************************** | |
| 4129 | 3872 | |
| 4130 | UINT64 memory_read_qword_16le(const address_space *space, offs_t address) | |
| 3873 | //------------------------------------------------- | |
| 3874 | // handler_entry - constructor | |
| 3875 | //------------------------------------------------- | |
| 3876 | ||
| 3877 | handler_entry::handler_entry(UINT8 width, endianness_t endianness, UINT8 **rambaseptr) | |
| 3878 | : m_populated(false), | |
| 3879 | m_datawidth(width), | |
| 3880 | m_endianness(endianness), | |
| 3881 | m_bytestart(0), | |
| 3882 | m_byteend(0), | |
| 3883 | m_bytemask(~0), | |
| 3884 | m_rambaseptr(rambaseptr), | |
| 3885 | m_subunits(0) | |
| 4131 | 3886 | { |
| 4132 | UINT64 result = (UINT64)memory_read_dword_16le(space, address + 0) << 0; | |
| 4133 | return result | ((UINT64)memory_read_dword_16le(space, address + 4) << 32); | |
| 4134 | 3887 | } |
| 4135 | 3888 | |
| 4136 | UINT64 memory_read_qword_masked_16le(const address_space *space, offs_t address, UINT64 mask) | |
| 3889 | ||
| 3890 | //------------------------------------------------- | |
| 3891 | // ~handler_entry - destructor | |
| 3892 | //------------------------------------------------- | |
| 3893 | ||
| 3894 | handler_entry::~handler_entry() | |
| 4137 | 3895 | { |
| 4138 | UINT64 result = 0; | |
| 4139 | if (mask & U64(0x00000000ffffffff)) result |= (UINT64)memory_read_dword_masked_16le(space, address + 0, mask >> 0) << 0; | |
| 4140 | if (mask & U64(0xffffffff00000000)) result |= (UINT64)memory_read_dword_masked_16le(space, address + 4, mask >> 32) << 32; | |
| 4141 | return result; | |
| 4142 | 3896 | } |
| 4143 | 3897 | |
| 4144 | UINT64 memory_read_qword_16be(const address_space *space, offs_t address) | |
| 3898 | ||
| 3899 | //------------------------------------------------- | |
| 3900 | // configure_subunits - configure the subunits | |
| 3901 | // and subshift array to represent the provided | |
| 3902 | // mask | |
| 3903 | //------------------------------------------------- | |
| 3904 | ||
| 3905 | void handler_entry::configure_subunits(UINT64 handlermask, int handlerbits) | |
| 4145 | 3906 | { |
| 4146 | UINT64 result = (UINT64)memory_read_dword_16be(space, address + 0) << 32; | |
| 4147 | return result | ((UINT64)memory_read_dword_16be(space, address + 4) << 0); | |
| 4148 | } | |
| 3907 | UINT64 unitmask = ((UINT64)1 << handlerbits) - 1; | |
| 3908 | assert(handlermask != 0); | |
| 4149 | 3909 | |
| 4150 | UINT64 memory_read_qword_masked_16be(const address_space *space, offs_t address, UINT64 mask) | |
| 4151 | { | |
| 4152 | UINT64 result = 0; | |
| 4153 | if (mask & U64(0xffffffff00000000)) result |= (UINT64)memory_read_dword_masked_16be(space, address + 0, mask >> 32) << 32; | |
| 4154 | if (mask & U64(0x00000000ffffffff)) result |= (UINT64)memory_read_dword_masked_16be(space, address + 4, mask >> 0) << 0; | |
| 4155 | return result; | |
| 3910 | // compute the maximum possible subunits | |
| 3911 | int maxunits = m_datawidth / handlerbits; | |
| 3912 | assert(maxunits > 1); | |
| 3913 | assert(maxunits < ARRAY_LENGTH(m_subshift)); | |
| 3914 | ||
| 3915 | // walk the handlermask to find out how many we have | |
| 3916 | m_subunits = 0; | |
| 3917 | for (int unitnum = 0; unitnum < maxunits; unitnum++) | |
| 3918 | { | |
| 3919 | UINT64 scanmask = unitmask << (unitnum * handlerbits); | |
| 3920 | assert((handlermask & scanmask) == 0 || (handlermask & scanmask) == scanmask); | |
| 3921 | if ((handlermask & scanmask) != 0) | |
| 3922 | m_subunits++; | |
| 3923 | } | |
| 3924 | ||
| 3925 | // then fill in the shifts based on the endianness | |
| 3926 | if (m_endianness == ENDIANNESS_LITTLE) | |
| 3927 | { | |
| 3928 | UINT8 *unitshift = &m_subshift[0]; | |
| 3929 | for (int unitnum = 0; unitnum < maxunits; unitnum++) | |
| 3930 | if ((handlermask & (unitmask << (unitnum * handlerbits))) != 0) | |
| 3931 | *unitshift++ = unitnum * handlerbits; | |
| 3932 | } | |
| 3933 | else | |
| 3934 | { | |
| 3935 | UINT8 *unitshift = &m_subshift[m_subunits]; | |
| 3936 | for (int unitnum = 0; unitnum < maxunits; unitnum++) | |
| 3937 | if ((handlermask & (unitmask << (unitnum * handlerbits))) != 0) | |
| 3938 | *--unitshift = unitnum * handlerbits; | |
| 3939 | } | |
| 4156 | 3940 | } |
| 4157 | 3941 | |
| 4158 | 3942 | |
| 4159 | 3943 | |
| 4160 | /*************************************************************************** | |
| 4161 | 16-BIT WRITE HANDLERS | |
| 4162 | ***************************************************************************/ | |
| 3944 | //************************************************************************** | |
| 3945 | // HANDLER ENTRY READ | |
| 3946 | //************************************************************************** | |
| 4163 | 3947 | |
| 4164 | void memory_write_byte_16le(const address_space *space, offs_t address, UINT8 data) | |
| 4165 | { | |
| 4166 | UINT32 shift = (address & 1) * 8; | |
| 4167 | write_word_generic(space, address, data << shift, 0xff << shift); | |
| 4168 | } | |
| 3948 | //------------------------------------------------- | |
| 3949 | // name - return the handler name, from the | |
| 3950 | // appropriately-sized delegate | |
| 3951 | //------------------------------------------------- | |
| 4169 | 3952 | |
| 4170 | ||
| 3953 | ||
| 4171 | 3954 | { |
| 4172 | UINT32 shift = (~address & 1) * 8; | |
| 4173 | write_word_generic(space, address, data << shift, 0xff << shift); | |
| 3955 | switch (m_datawidth) | |
| 3956 | { | |
| 3957 | case 8: return m_read8.name(); | |
| 3958 | case 16: return m_read16.name(); | |
| 3959 | case 32: return m_read32.name(); | |
| 3960 | case 64: return m_read64.name(); | |
| 3961 | } | |
| 3962 | return NULL; | |
| 4174 | 3963 | } |
| 4175 | 3964 | |
| 4176 | void memory_write_word_16le(const address_space *space, offs_t address, UINT16 data) | |
| 4177 | { | |
| 4178 | write_word_generic(space, address, data, 0xffff); | |
| 4179 | } | |
| 4180 | 3965 | |
| 4181 | void memory_write_word_masked_16le(const address_space *space, offs_t address, UINT16 data, UINT16 mask) | |
| 4182 | { | |
| 4183 | write_word_generic(space, address, data, mask); | |
| 4184 | } | |
| 3966 | //------------------------------------------------- | |
| 3967 | // set_delegate - set an 8-bit delegate, and | |
| 3968 | // configure a stub if necessary | |
| 3969 | //------------------------------------------------- | |
| 4185 | 3970 | |
| 4186 | void | |
| 3971 | void handle | |
| 4187 | 3972 | { |
| 4188 | write_word_generic(space, address, data, 0xffff); | |
| 4189 | } | |
| 3973 | // error if no object | |
| 3974 | if (!delegate.has_object()) | |
| 3975 | throw emu_fatalerror("Attempted to install delegate '%s' without a bound object", delegate.name()); | |
| 4190 | 3976 | |
| 4191 | void memory_write_word_masked_16be(const address_space *space, offs_t address, UINT16 data, UINT16 mask) | |
| 4192 | { | |
| 4193 | write_word_generic(space, address, data, mask); | |
| 3977 | // make sure this is a valid size | |
| 3978 | assert(m_datawidth >= 8); | |
| 3979 | m_read8 = delegate; | |
| 3980 | ||
| 3981 | // if mismatched bus width, configure a stub | |
| 3982 | if (m_datawidth != 8) | |
| 3983 | { | |
| 3984 | configure_subunits(mask, 8); | |
| 3985 | if (m_datawidth == 16) | |
| 3986 | set_delegate(read16_delegate(read16_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_16_from_8>(delegate.name()), *this)); | |
| 3987 | else if (m_datawidth == 32) | |
| 3988 | set_delegate(read32_delegate(read32_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_32_from_8>(delegate.name()), *this)); | |
| 3989 | else if (m_datawidth == 64) | |
| 3990 | set_delegate(read64_delegate(read64_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_64_from_8>(delegate.name()), *this)); | |
| 3991 | } | |
| 4194 | 3992 | } |
| 4195 | 3993 | |
| 4196 | void memory_write_dword_16le(const address_space *space, offs_t address, UINT32 data) | |
| 4197 | { | |
| 4198 | memory_write_word_16le(space, address + 0, data >> 0); | |
| 4199 | memory_write_word_16le(space, address + 2, data >> 16); | |
| 4200 | } | |
| 4201 | 3994 | |
| 4202 | void memory_write_dword_masked_16le(const address_space *space, offs_t address, UINT32 data, UINT32 mask) | |
| 4203 | { | |
| 4204 | if (mask & 0x0000ffff) memory_write_word_masked_16le(space, address + 0, data >> 0, mask >> 0); | |
| 4205 | if (mask & 0xffff0000) memory_write_word_masked_16le(space, address + 2, data >> 16, mask >> 16); | |
| 4206 | } | |
| 3995 | //------------------------------------------------- | |
| 3996 | // set_delegate - set a 16-bit delegate, and | |
| 3997 | // configure a stub if necessary | |
| 3998 | //------------------------------------------------- | |
| 4207 | 3999 | |
| 4208 | void | |
| 4000 | void handle | |
| 4209 | 4001 | { |
| 4210 | memory_write_word_16be(space, address + 0, data >> 16); | |
| 4211 | memory_write_word_16be(space, address + 2, data >> 0); | |
| 4212 | } | |
| 4002 | // error if no object | |
| 4003 | if (!delegate.has_object()) | |
| 4004 | throw emu_fatalerror("Attempted to install delegate '%s' without a bound object", delegate.name()); | |
| 4213 | 4005 | |
| 4214 | void memory_write_dword_masked_16be(const address_space *space, offs_t address, UINT32 data, UINT32 mask) | |
| 4215 | { | |
| 4216 | if (mask & 0xffff0000) memory_write_word_masked_16be(space, address + 0, data >> 16, mask >> 16); | |
| 4217 | if (mask & 0x0000ffff) memory_write_word_masked_16be(space, address + 2, data >> 0, mask >> 0); | |
| 4218 | } | |
| 4006 | // make sure this is a valid size | |
| 4007 | assert(m_datawidth >= 16); | |
| 4008 | m_read16 = delegate; | |
| 4219 | 4009 | |
| 4220 | void memory_write_qword_16le(const address_space *space, offs_t address, UINT64 data) | |
| 4221 | { | |
| 4222 | memory_write_dword_16le(space, address + 0, data >> 0); | |
| 4223 | memory_write_dword_16le(space, address + 4, data >> 32); | |
| 4010 | // if mismatched bus width, configure a stub | |
| 4011 | if (m_datawidth != 16) | |
| 4012 | { | |
| 4013 | configure_subunits(mask, 16); | |
| 4014 | if (m_datawidth == 32) | |
| 4015 | set_delegate(read32_delegate(read32_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_32_from_16>(delegate.name()), *this)); | |
| 4016 | else if (m_datawidth == 64) | |
| 4017 | set_delegate(read64_delegate(read64_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_64_from_16>(delegate.name()), *this)); | |
| 4018 | } | |
| 4224 | 4019 | } |
| 4225 | 4020 | |
| 4226 | void memory_write_qword_masked_16le(const address_space *space, offs_t address, UINT64 data, UINT64 mask) | |
| 4227 | { | |
| 4228 | if (mask & U64(0x00000000ffffffff)) memory_write_dword_masked_16le(space, address + 0, data >> 0, mask >> 0); | |
| 4229 | if (mask & U64(0xffffffff00000000)) memory_write_dword_masked_16le(space, address + 4, data >> 32, mask >> 32); | |
| 4230 | } | |
| 4231 | 4021 | |
| 4232 | void memory_write_qword_16be(const address_space *space, offs_t address, UINT64 data) | |
| 4022 | //------------------------------------------------- | |
| 4023 | // set_delegate - set a 32-bit delegate, and | |
| 4024 | // configure a stub if necessary | |
| 4025 | //------------------------------------------------- | |
| 4026 | ||
| 4027 | void handler_entry_read::set_delegate(read32_delegate delegate, UINT64 mask) | |
| 4233 | 4028 | { |
| 4234 | memory_write_dword_16be(space, address + 0, data >> 32); | |
| 4235 | memory_write_dword_16be(space, address + 4, data >> 0); | |
| 4236 | } | |
| 4029 | // error if no object | |
| 4030 | if (!delegate.has_object()) | |
| 4031 | throw emu_fatalerror("Attempted to install delegate '%s' without a bound object", delegate.name()); | |
| 4237 | 4032 | |
| 4238 | void memory_write_qword_masked_16be(const address_space *space, offs_t address, UINT64 data, UINT64 mask) | |
| 4239 | { | |
| 4240 | if (mask & U64(0xffffffff00000000)) memory_write_dword_masked_16be(space, address + 0, data >> 32, mask >> 32); | |
| 4241 | if (mask & U64(0x00000000ffffffff)) memory_write_dword_masked_16be(space, address + 4, data >> 0, mask >> 0); | |
| 4033 | // make sure this is a valid size | |
| 4034 | assert(m_datawidth >= 32); | |
| 4035 | m_read32 = delegate; | |
| 4036 | ||
| 4037 | // if mismatched bus width, configure a stub | |
| 4038 | if (m_datawidth != 32) | |
| 4039 | { | |
| 4040 | configure_subunits(mask, 16); | |
| 4041 | if (m_datawidth == 64) | |
| 4042 | set_delegate(read64_delegate(read64_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_64_from_32>(delegate.name()), *this)); | |
| 4043 | } | |
| 4242 | 4044 | } |
| 4243 | 4045 | |
| 4244 | 4046 | |
| 4047 | //------------------------------------------------- | |
| 4048 | // set_delegate - set a 64-bit delegate | |
| 4049 | //------------------------------------------------- | |
| 4245 | 4050 | |
| 4246 | /*************************************************************************** | |
| 4247 | 32-BIT READ HANDLERS | |
| 4248 | ***************************************************************************/ | |
| 4249 | ||
| 4250 | UINT8 memory_read_byte_32le(const address_space *space, offs_t address) | |
| 4051 | void handler_entry_read::set_delegate(read64_delegate delegate, UINT64 mask) | |
| 4251 | 4052 | { |
| 4252 | UINT32 shift = (address & 3) * 8; | |
| 4253 | return read_dword_generic(space, address, 0xff << shift) >> shift; | |
| 4254 | } | |
| 4053 | // error if no object | |
| 4054 | if (!delegate.has_object()) | |
| 4055 | throw emu_fatalerror("Attempted to install delegate '%s' without a bound object", delegate.name()); | |
| 4255 | 4056 | |
| 4256 | UINT8 memory_read_byte_32be(const address_space *space, offs_t address) | |
| 4257 | { | |
| 4258 | UINT32 shift = (~address & 3) * 8; | |
| 4259 | return read_dword_generic(space, address, 0xff << shift) >> shift; | |
| 4057 | // make sure this is a valid size | |
| 4058 | assert(m_datawidth >= 64); | |
| 4059 | m_read64 = delegate; | |
| 4260 | 4060 | } |
| 4261 | 4061 | |
| 4262 | UINT16 memory_read_word_32le(const address_space *space, offs_t address) | |
| 4062 | ||
| 4063 | //------------------------------------------------- | |
| 4064 | // set_legacy_func - configure a legacy address | |
| 4065 | // space stub of the appropriate size | |
| 4066 | //------------------------------------------------- | |
| 4067 | ||
| 4068 | void handler_entry_read::set_legacy_func(address_space &space, read8_space_func func, const char *name, UINT64 mask) | |
| 4263 | 4069 | { |
| 4264 | UINT32 shift = (address & 2) * 8; | |
| 4265 | return read_dword_generic(space, address, 0xffff << shift) >> shift; | |
| 4070 | m_legacy_handler.space8 = func; | |
| 4071 | m_legacy_object.space = &space; | |
| 4072 | set_delegate(read8_delegate(read8_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_legacy>(name), *this), mask); | |
| 4266 | 4073 | } |
| 4267 | 4074 | |
| 4268 | ||
| 4075 | void | |
| 4269 | 4076 | { |
| 4270 | UINT32 shift = (address & 2) * 8; | |
| 4271 | return read_dword_generic(space, address, mask << shift) >> shift; | |
| 4077 | m_legacy_handler.space16 = func; | |
| 4078 | m_legacy_object.space = &space; | |
| 4079 | set_delegate(read16_delegate(read16_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_legacy>(name), *this), mask); | |
| 4272 | 4080 | } |
| 4273 | 4081 | |
| 4274 | ||
| 4082 | void | |
| 4275 | 4083 | { |
| 4276 | UINT32 shift = (~address & 2) * 8; | |
| 4277 | return read_dword_generic(space, address, 0xffff << shift) >> shift; | |
| 4084 | m_legacy_handler.space32 = func; | |
| 4085 | m_legacy_object.space = &space; | |
| 4086 | set_delegate(read32_delegate(read32_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_legacy>(name), *this), mask); | |
| 4278 | 4087 | } |
| 4279 | 4088 | |
| 4280 | ||
| 4089 | void | |
| 4281 | 4090 | { |
| 4282 | UINT32 shift = (~address & 2) * 8; | |
| 4283 | return read_dword_generic(space, address, mask << shift) >> shift; | |
| 4091 | m_legacy_handler.space64 = func; | |
| 4092 | m_legacy_object.space = &space; | |
| 4093 | set_delegate(read64_delegate(read64_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_legacy>(name), *this), mask); | |
| 4284 | 4094 | } |
| 4285 | 4095 | |
| 4286 | UINT32 memory_read_dword_32le(const address_space *space, offs_t address) | |
| 4096 | ||
| 4097 | //------------------------------------------------- | |
| 4098 | // set_legacy_func - configure a legacy device | |
| 4099 | // stub of the appropriate size | |
| 4100 | //------------------------------------------------- | |
| 4101 | ||
| 4102 | void handler_entry_read::set_legacy_func(device_t &device, read8_device_func func, const char *name, UINT64 mask) | |
| 4287 | 4103 | { |
| 4288 | return read_dword_generic(space, address, 0xffffffff); | |
| 4104 | m_legacy_handler.device8 = func; | |
| 4105 | m_legacy_object.device = &device; | |
| 4106 | set_delegate(read8_delegate(read8_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_legacy>(name), *this), mask); | |
| 4289 | 4107 | } |
| 4290 | 4108 | |
| 4291 | ||
| 4109 | void | |
| 4292 | 4110 | { |
| 4293 | return read_dword_generic(space, address, mask); | |
| 4111 | m_legacy_handler.device16 = func; | |
| 4112 | m_legacy_object.device = &device; | |
| 4113 | set_delegate(read16_delegate(read16_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_legacy>(name), *this), mask); | |
| 4294 | 4114 | } |
| 4295 | 4115 | |
| 4296 | ||
| 4116 | void | |
| 4297 | 4117 | { |
| 4298 | return read_dword_generic(space, address, 0xffffffff); | |
| 4118 | m_legacy_handler.device32 = func; | |
| 4119 | m_legacy_object.device = &device; | |
| 4120 | set_delegate(read32_delegate(read32_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_legacy>(name), *this), mask); | |
| 4299 | 4121 | } |
| 4300 | 4122 | |
| 4301 | ||
| 4123 | void | |
| 4302 | 4124 | { |
| 4303 | return read_dword_generic(space, address, mask); | |
| 4125 | m_legacy_handler.device64 = func; | |
| 4126 | m_legacy_object.device = &device; | |
| 4127 | set_delegate(read64_delegate(read64_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_legacy>(name), *this), mask); | |
| 4304 | 4128 | } |
| 4305 | 4129 | |
| 4306 | UINT64 memory_read_qword_32le(const address_space *space, offs_t address) | |
| 4130 | ||
| 4131 | //------------------------------------------------- | |
| 4132 | // set_ioport - configure an I/O port read stub | |
| 4133 | // of the appropriate size | |
| 4134 | //------------------------------------------------- | |
| 4135 | ||
| 4136 | void handler_entry_read::set_ioport(const input_port_config &ioport) | |
| 4307 | 4137 | { |
| 4308 | UINT64 result = (UINT64)memory_read_dword_32le(space, address + 0) << 0; | |
| 4309 | return result | ((UINT64)memory_read_dword_32le(space, address + 4) << 32); | |
| 4138 | m_ioport = &ioport; | |
| 4139 | if (m_datawidth == 8) | |
| 4140 | set_delegate(read8_delegate(read8_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_ioport<UINT8> >(ioport.tag), *this)); | |
| 4141 | else if (m_datawidth == 16) | |
| 4142 | set_delegate(read16_delegate(read16_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_ioport<UINT16> >(ioport.tag), *this)); | |
| 4143 | else if (m_datawidth == 32) | |
| 4144 | set_delegate(read32_delegate(read32_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_ioport<UINT32> >(ioport.tag), *this)); | |
| 4145 | else if (m_datawidth == 64) | |
| 4146 | set_delegate(read64_delegate(read64_proto_delegate::_create_member<handler_entry_read, &handler_entry_read::read_stub_ioport<UINT64> >(ioport.tag), *this)); | |
| 4310 | 4147 | } |
| 4311 | 4148 | |
| 4312 | UINT64 memory_read_qword_masked_32le(const address_space *space, offs_t address, UINT64 mask) | |
| 4149 | ||
| 4150 | //------------------------------------------------- | |
| 4151 | // read_stub_16_from_8 - construct a 16-bit read | |
| 4152 | // from 8-bit sources | |
| 4153 | //------------------------------------------------- | |
| 4154 | ||
| 4155 | UINT16 handler_entry_read::read_stub_16_from_8(address_space &space, offs_t offset, UINT16 mask) | |
| 4313 | 4156 | { |
| 4314 | UINT64 result = 0; | |
| 4315 | if (mask & U64(0x00000000ffffffff)) result |= (UINT64)memory_read_dword_masked_32le(space, address + 0, mask >> 0) << 0; | |
| 4316 | if (mask & U64(0xffffffff00000000)) result |= (UINT64)memory_read_dword_masked_32le(space, address + 4, mask >> 32) << 32; | |
| 4157 | UINT16 result = 0; | |
| 4158 | for (int index = 0; index < m_subunits; index++) | |
| 4159 | { | |
| 4160 | int shift = m_subshift[index]; | |
| 4161 | UINT8 mask8 = mask >> shift; | |
| 4162 | if (mask8 != 0) | |
| 4163 | result |= m_read8(space, offset * m_subunits + index, mask8) << shift; | |
| 4164 | } | |
| 4317 | 4165 | return result; |
| 4318 | 4166 | } |
| 4319 | 4167 | |
| 4320 | UINT64 memory_read_qword_32be(const address_space *space, offs_t address) | |
| 4168 | ||
| 4169 | //------------------------------------------------- | |
| 4170 | // read_stub_32_from_8 - construct a 32-bit read | |
| 4171 | // from 8-bit sources | |
| 4172 | //------------------------------------------------- | |
| 4173 | ||
| 4174 | UINT32 handler_entry_read::read_stub_32_from_8(address_space &space, offs_t offset, UINT32 mask) | |
| 4321 | 4175 | { |
| 4322 | UINT64 result = (UINT64)memory_read_dword_32be(space, address + 0) << 32; | |
| 4323 | return result | ((UINT64)memory_read_dword_32be(space, address + 4) << 0); | |
| 4176 | UINT32 result = 0; | |
| 4177 | for (int index = 0; index < m_subunits; index++) | |
| 4178 | { | |
| 4179 | int shift = m_subshift[index]; | |
| 4180 | UINT8 mask8 = mask >> shift; | |
| 4181 | if (mask8 != 0) | |
| 4182 | result |= m_read8(space, offset * m_subunits + index, mask8) << shift; | |
| 4183 | } | |
| 4184 | return result; | |
| 4324 | 4185 | } |
| 4325 | 4186 | |
| 4326 | UINT64 memory_read_qword_masked_32be(const address_space *space, offs_t address, UINT64 mask) | |
| 4187 | ||
| 4188 | //------------------------------------------------- | |
| 4189 | // read_stub_64_from_8 - construct a 64-bit read | |
| 4190 | // from 8-bit sources | |
| 4191 | //------------------------------------------------- | |
| 4192 | ||
| 4193 | UINT64 handler_entry_read::read_stub_64_from_8(address_space &space, offs_t offset, UINT64 mask) | |
| 4327 | 4194 | { |
| 4328 | 4195 | UINT64 result = 0; |
| 4329 | if (mask & U64(0xffffffff00000000)) result |= (UINT64)memory_read_dword_masked_32be(space, address + 0, mask >> 32) << 32; | |
| 4330 | if (mask & U64(0x00000000ffffffff)) result |= (UINT64)memory_read_dword_masked_32be(space, address + 4, mask >> 0) << 0; | |
| 4196 | for (int index = 0; index < m_subunits; index++) | |
| 4197 | { | |
| 4198 | int shift = m_subshift[index]; | |
| 4199 | UINT8 mask8 = mask >> shift; | |
| 4200 | if (mask8 != 0) | |
| 4201 | result |= (UINT64)m_read8(space, offset * m_subunits + index, mask8) << shift; | |
| 4202 | } | |
| 4331 | 4203 | return result; |
| 4332 | 4204 | } |
| 4333 | 4205 | |
| 4334 | 4206 | |
| 4207 | //------------------------------------------------- | |
| 4208 | // read_stub_32_from_16 - construct a 32-bit read | |
| 4209 | // from 16-bit sources | |
| 4210 | //------------------------------------------------- | |
| 4335 | 4211 | |
| 4336 | /*************************************************************************** | |
| 4337 | 32-BIT WRITE HANDLERS | |
| 4338 | ***************************************************************************/ | |
| 4339 | ||
| 4340 | void memory_write_byte_32le(const address_space *space, offs_t address, UINT8 data) | |
| 4212 | UINT32 handler_entry_read::read_stub_32_from_16(address_space &space, offs_t offset, UINT32 mask) | |
| 4341 | 4213 | { |
| 4342 | UINT32 shift = (address & 3) * 8; | |
| 4343 | write_dword_generic(space, address, data << shift, 0xff << shift); | |
| 4214 | UINT32 result = 0; | |
| 4215 | for (int index = 0; index < m_subunits; index++) | |
| 4216 | { | |
| 4217 | int shift = m_subshift[index]; | |
| 4218 | UINT16 mask16 = mask >> shift; | |
| 4219 | if (mask16 != 0) | |
| 4220 | result |= m_read16(space, offset * m_subunits + index, mask16) << shift; | |
| 4221 | } | |
| 4222 | return result; | |
| 4344 | 4223 | } |
| 4345 | 4224 | |
| 4346 | void memory_write_byte_32be(const address_space *space, offs_t address, UINT8 data) | |
| 4347 | { | |
| 4348 | UINT32 shift = (~address & 3) * 8; | |
| 4349 | write_dword_generic(space, address, data << shift, 0xff << shift); | |
| 4350 | } | |
| 4351 | 4225 | |
| 4352 | void memory_write_word_32le(const address_space *space, offs_t address, UINT16 data) | |
| 4353 | { | |
| 4354 | UINT32 shift = (address & 2) * 8; | |
| 4355 | write_dword_generic(space, address, data << shift, 0xffff << shift); | |
| 4356 | } | |
| 4226 | //------------------------------------------------- | |
| 4227 | // read_stub_64_from_16 - construct a 64-bit read | |
| 4228 | // from 16-bit sources | |
| 4229 | //------------------------------------------------- | |
| 4357 | 4230 | |
| 4358 | ||
| 4231 | UINT64 handle | |
| 4359 | 4232 | { |
| 4360 | UINT32 shift = (address & 2) * 8; | |
| 4361 | write_dword_generic(space, address, data << shift, mask << shift); | |
| 4233 | UINT64 result = 0; | |
| 4234 | for (int index = 0; index < m_subunits; index++) | |
| 4235 | { | |
| 4236 | int shift = m_subshift[index]; | |
| 4237 | UINT16 mask16 = mask >> shift; | |
| 4238 | if (mask16 != 0) | |
| 4239 | result |= (UINT64)m_read16(space, offset * m_subunits + index, mask16) << shift; | |
| 4240 | } | |
| 4241 | return result; | |
| 4362 | 4242 | } |
| 4363 | 4243 | |
| 4364 | void memory_write_word_32be(const address_space *space, offs_t address, UINT16 data) | |
| 4365 | { | |
| 4366 | UINT32 shift = (~address & 2) * 8; | |
| 4367 | write_dword_generic(space, address, data << shift, 0xffff << shift); | |
| 4368 | } | |
| 4369 | 4244 | |
| 4370 | void memory_write_word_masked_32be(const address_space *space, offs_t address, UINT16 data, UINT16 mask) | |
| 4371 | { | |
| 4372 | UINT32 shift = (~address & 2) * 8; | |
| 4373 | write_dword_generic(space, address, data << shift, mask << shift); | |
| 4374 | } | |
| 4245 | //------------------------------------------------- | |
| 4246 | // read_stub_64_from_32 - construct a 64-bit read | |
| 4247 | // from 32-bit sources | |
| 4248 | //------------------------------------------------- | |
| 4375 | 4249 | |
| 4376 | ||
| 4250 | UINT64 handle | |
| 4377 | 4251 | { |
| 4378 | write_dword_generic(space, address, data, 0xffffffff); | |
| 4252 | UINT64 result = 0; | |
| 4253 | for (int index = 0; index < m_subunits; index++) | |
| 4254 | { | |
| 4255 | int shift = m_subshift[index]; | |
| 4256 | UINT32 mask32 = mask >> shift; | |
| 4257 | if (mask32 != 0) | |
| 4258 | result |= (UINT64)m_read32(space, offset * m_subunits + index, mask32) << shift; | |
| 4259 | } | |
| 4260 | return result; | |
| 4379 | 4261 | } |
| 4380 | 4262 | |
| 4381 | void memory_write_dword_masked_32le(const address_space *space, offs_t address, UINT32 data, UINT32 mask) | |
| 4382 | { | |
| 4383 | write_dword_generic(space, address, data, mask); | |
| 4384 | } | |
| 4385 | 4263 | |
| 4386 | void memory_write_dword_32be(const address_space *space, offs_t address, UINT32 data) | |
| 4387 | { | |
| 4388 | write_dword_generic(space, address, data, 0xffffffff); | |
| 4389 | } | |
| 4264 | //------------------------------------------------- | |
| 4265 | // read_stub_legacy - perform a read using legacy | |
| 4266 | // handler callbacks | |
| 4267 | //------------------------------------------------- | |
| 4390 | 4268 | |
| 4391 | ||
| 4269 | UINT8 handle | |
| 4392 | 4270 | { |
| 4393 | | |
| 4271 | | |
| 4394 | 4272 | } |
| 4395 | 4273 | |
| 4396 | ||
| 4274 | UINT16 handle | |
| 4397 | 4275 | { |
| 4398 | memory_write_dword_32le(space, address + 0, data >> 0); | |
| 4399 | memory_write_dword_32le(space, address + 4, data >> 32); | |
| 4276 | return m_legacy_handler.space16(m_legacy_object.space, offset, mask); | |
| 4400 | 4277 | } |
| 4401 | 4278 | |
| 4402 | ||
| 4279 | UINT32 handle | |
| 4403 | 4280 | { |
| 4404 | if (mask & U64(0x00000000ffffffff)) memory_write_dword_masked_32le(space, address + 0, data >> 0, mask >> 0); | |
| 4405 | if (mask & U64(0xffffffff00000000)) memory_write_dword_masked_32le(space, address + 4, data >> 32, mask >> 32); | |
| 4281 | return m_legacy_handler.space32(m_legacy_object.space, offset, mask); | |
| 4406 | 4282 | } |
| 4407 | 4283 | |
| 4408 | ||
| 4284 | UINT64 handle | |
| 4409 | 4285 | { |
| 4410 | memory_write_dword_32be(space, address + 0, data >> 32); | |
| 4411 | memory_write_dword_32be(space, address + 4, data >> 0); | |
| 4286 | return m_legacy_handler.space64(m_legacy_object.space, offset, mask); | |
| 4412 | 4287 | } |
| 4413 | 4288 | |
| 4414 | void memory_write_qword_masked_32be(const address_space *space, offs_t address, UINT64 data, UINT64 mask) | |
| 4415 | { | |
| 4416 | if (mask & U64(0xffffffff00000000)) memory_write_dword_masked_32be(space, address + 0, data >> 32, mask >> 32); | |
| 4417 | if (mask & U64(0x00000000ffffffff)) memory_write_dword_masked_32be(space, address + 4, data >> 0, mask >> 0); | |
| 4418 | } | |
| 4419 | 4289 | |
| 4420 | 4290 | |
| 4291 | //************************************************************************** | |
| 4292 | // HANDLER ENTRY WRITE | |
| 4293 | //************************************************************************** | |
| 4421 | 4294 | |
| 4422 | /*************************************************************************** | |
| 4423 | 64-BIT READ HANDLERS | |
| 4424 | ***************************************************************************/ | |
| 4295 | //------------------------------------------------- | |
| 4296 | // name - return the handler name, from the | |
| 4297 | // appropriately-sized delegate | |
| 4298 | //------------------------------------------------- | |
| 4425 | 4299 | |
| 4426 | ||
| 4300 | ||
| 4427 | 4301 | { |
| 4428 | UINT32 shift = (address & 7) * 8; | |
| 4429 | return read_qword_generic(space, address, (UINT64)0xff << shift) >> shift; | |
| 4302 | switch (m_datawidth) | |
| 4303 | { | |
| 4304 | case 8: return m_write8.name(); | |
| 4305 | case 16: return m_write16.name(); | |
| 4306 | case 32: return m_write32.name(); | |
| 4307 | case 64: return m_write64.name(); | |
| 4308 | } | |
| 4309 | return NULL; | |
| 4430 | 4310 | } |
| 4431 | 4311 | |
| 4432 | UINT8 memory_read_byte_64be(const address_space *space, offs_t address) | |
| 4433 | { | |
| 4434 | UINT32 shift = (~address & 7) * 8; | |
| 4435 | return read_qword_generic(space, address, (UINT64)0xff << shift) >> shift; | |
| 4436 | } | |
| 4437 | 4312 | |
| 4438 | UINT16 memory_read_word_64le(const address_space *space, offs_t address) | |
| 4313 | //------------------------------------------------- | |
| 4314 | // set_delegate - set an 8-bit delegate, and | |
| 4315 | // configure a stub if necessary | |
| 4316 | //------------------------------------------------- | |
| 4317 | ||
| 4318 | void handler_entry_write::set_delegate(write8_delegate delegate, UINT64 mask) | |
| 4439 | 4319 | { |
| 4440 | UINT32 shift = (address & 6) * 8; | |
| 4441 | return read_qword_generic(space, address, (UINT64)0xffff << shift) >> shift; | |
| 4320 | assert(m_datawidth >= 8); | |
| 4321 | m_write8 = delegate; | |
| 4322 | ||
| 4323 | // if mismatched bus width, configure a stub | |
| 4324 | if (m_datawidth != 8) | |
| 4325 | { | |
| 4326 | configure_subunits(mask, 8); | |
| 4327 | if (m_datawidth == 16) | |
| 4328 | set_delegate(write16_delegate(write16_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_16_from_8>(delegate.name()), *this)); | |
| 4329 | else if (m_datawidth == 32) | |
| 4330 | set_delegate(write32_delegate(write32_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_32_from_8>(delegate.name()), *this)); | |
| 4331 | else if (m_datawidth == 64) | |
| 4332 | set_delegate(write64_delegate(write64_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_64_from_8>(delegate.name()), *this)); | |
| 4333 | } | |
| 4442 | 4334 | } |
| 4443 | 4335 | |
| 4444 | UINT16 memory_read_word_masked_64le(const address_space *space, offs_t address, UINT16 mask) | |
| 4336 | ||
| 4337 | //------------------------------------------------- | |
| 4338 | // set_delegate - set a 16-bit delegate, and | |
| 4339 | // configure a stub if necessary | |
| 4340 | //------------------------------------------------- | |
| 4341 | ||
| 4342 | void handler_entry_write::set_delegate(write16_delegate delegate, UINT64 mask) | |
| 4445 | 4343 | { |
| 4446 | UINT32 shift = (address & 6) * 8; | |
| 4447 | return read_qword_generic(space, address, (UINT64)mask << shift) >> shift; | |
| 4344 | assert(m_datawidth >= 16); | |
| 4345 | m_write16 = delegate; | |
| 4346 | ||
| 4347 | // if mismatched bus width, configure a stub | |
| 4348 | if (m_datawidth != 16) | |
| 4349 | { | |
| 4350 | configure_subunits(mask, 16); | |
| 4351 | if (m_datawidth == 32) | |
| 4352 | set_delegate(write32_delegate(write32_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_32_from_16>(delegate.name()), *this)); | |
| 4353 | else if (m_datawidth == 64) | |
| 4354 | set_delegate(write64_delegate(write64_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_64_from_16>(delegate.name()), *this)); | |
| 4355 | } | |
| 4448 | 4356 | } |
| 4449 | 4357 | |
| 4450 | UINT16 memory_read_word_64be(const address_space *space, offs_t address) | |
| 4358 | ||
| 4359 | //------------------------------------------------- | |
| 4360 | // set_delegate - set a 32-bit delegate, and | |
| 4361 | // configure a stub if necessary | |
| 4362 | //------------------------------------------------- | |
| 4363 | ||
| 4364 | void handler_entry_write::set_delegate(write32_delegate delegate, UINT64 mask) | |
| 4451 | 4365 | { |
| 4452 | UINT32 shift = (~address & 6) * 8; | |
| 4453 | return read_qword_generic(space, address, (UINT64)0xffff << shift) >> shift; | |
| 4366 | assert(m_datawidth >= 32); | |
| 4367 | m_write32 = delegate; | |
| 4368 | ||
| 4369 | // if mismatched bus width, configure a stub | |
| 4370 | if (m_datawidth != 32) | |
| 4371 | { | |
| 4372 | configure_subunits(mask, 16); | |
| 4373 | if (m_datawidth == 64) | |
| 4374 | set_delegate(write64_delegate(write64_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_64_from_32>(delegate.name()), *this)); | |
| 4375 | } | |
| 4454 | 4376 | } |
| 4455 | 4377 | |
| 4456 | UINT16 memory_read_word_masked_64be(const address_space *space, offs_t address, UINT16 mask) | |
| 4378 | ||
| 4379 | //------------------------------------------------- | |
| 4380 | // set_delegate - set a 64-bit delegate | |
| 4381 | //------------------------------------------------- | |
| 4382 | ||
| 4383 | void handler_entry_write::set_delegate(write64_delegate delegate, UINT64 mask) | |
| 4457 | 4384 | { |
| 4458 | UINT32 shift = (~address & 6) * 8; | |
| 4459 | return read_qword_generic(space, address, (UINT64)mask << shift) >> shift; | |
| 4385 | assert(m_datawidth >= 64); | |
| 4386 | m_write64 = delegate; | |
| 4460 | 4387 | } |
| 4461 | 4388 | |
| 4462 | UINT32 memory_read_dword_64le(const address_space *space, offs_t address) | |
| 4389 | ||
| 4390 | //------------------------------------------------- | |
| 4391 | // set_legacy_func - configure a legacy address | |
| 4392 | // space stub of the appropriate size | |
| 4393 | //------------------------------------------------- | |
| 4394 | ||
| 4395 | void handler_entry_write::set_legacy_func(address_space &space, write8_space_func func, const char *name, UINT64 mask) | |
| 4463 | 4396 | { |
| 4464 | UINT32 shift = (address & 4) * 8; | |
| 4465 | return read_qword_generic(space, address, (UINT64)0xffffffff << shift) >> shift; | |
| 4397 | m_legacy_handler.space8 = func; | |
| 4398 | m_legacy_object.space = &space; | |
| 4399 | set_delegate(write8_delegate(write8_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_legacy>(name), *this), mask); | |
| 4466 | 4400 | } |
| 4467 | 4401 | |
| 4468 | ||
| 4402 | void | |
| 4469 | 4403 | { |
| 4470 | UINT32 shift = (address & 4) * 8; | |
| 4471 | return read_qword_generic(space, address, (UINT64)mask << shift) >> shift; | |
| 4404 | m_legacy_handler.space16 = func; | |
| 4405 | m_legacy_object.space = &space; | |
| 4406 | set_delegate(write16_delegate(write16_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_legacy>(name), *this), mask); | |
| 4472 | 4407 | } |
| 4473 | 4408 | |
| 4474 | ||
| 4409 | void | |
| 4475 | 4410 | { |
| 4476 | UINT32 shift = (~address & 4) * 8; | |
| 4477 | return read_qword_generic(space, address, (UINT64)0xffffffff << shift) >> shift; | |
| 4411 | m_legacy_handler.space32 = func; | |
| 4412 | m_legacy_object.space = &space; | |
| 4413 | set_delegate(write32_delegate(write32_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_legacy>(name), *this), mask); | |
| 4478 | 4414 | } |
| 4479 | 4415 | |
| 4480 | ||
| 4416 | void | |
| 4481 | 4417 | { |
| 4482 | UINT32 shift = (~address & 4) * 8; | |
| 4483 | return read_qword_generic(space, address, (UINT64)mask << shift) >> shift; | |
| 4418 | m_legacy_handler.space64 = func; | |
| 4419 | m_legacy_object.space = &space; | |
| 4420 | set_delegate(write64_delegate(write64_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_legacy>(name), *this), mask); | |
| 4484 | 4421 | } |
| 4485 | 4422 | |
| 4486 | UINT64 memory_read_qword_64le(const address_space *space, offs_t address) | |
| 4423 | ||
| 4424 | //------------------------------------------------- | |
| 4425 | // set_legacy_func - configure a legacy device | |
| 4426 | // stub of the appropriate size | |
| 4427 | //------------------------------------------------- | |
| 4428 | ||
| 4429 | void handler_entry_write::set_legacy_func(device_t &device, write8_device_func func, const char *name, UINT64 mask) | |
| 4487 | 4430 | { |
| 4488 | return read_qword_generic(space, address, U64(0xffffffffffffffff)); | |
| 4431 | m_legacy_handler.device8 = func; | |
| 4432 | m_legacy_object.device = &device; | |
| 4433 | set_delegate(write8_delegate(write8_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_legacy>(name), *this), mask); | |
| 4489 | 4434 | } |
| 4490 | 4435 | |
| 4491 | ||
| 4436 | void | |
| 4492 | 4437 | { |
| 4493 | return read_qword_generic(space, address, mask); | |
| 4438 | m_legacy_handler.device16 = func; | |
| 4439 | m_legacy_object.device = &device; | |
| 4440 | set_delegate(write16_delegate(write16_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_legacy>(name), *this), mask); | |
| 4494 | 4441 | } |
| 4495 | 4442 | |
| 4496 | ||
| 4443 | void | |
| 4497 | 4444 | { |
| 4498 | return read_qword_generic(space, address, U64(0xffffffffffffffff)); | |
| 4445 | m_legacy_handler.device32 = func; | |
| 4446 | m_legacy_object.device = &device; | |
| 4447 | set_delegate(write32_delegate(write32_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_legacy>(name), *this), mask); | |
| 4499 | 4448 | } |
| 4500 | 4449 | |
| 4501 | ||
| 4450 | void | |
| 4502 | 4451 | { |
| 4503 | return read_qword_generic(space, address, mask); | |
| 4452 | m_legacy_handler.device64 = func; | |
| 4453 | m_legacy_object.device = &device; | |
| 4454 | set_delegate(write64_delegate(write64_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_legacy>(name), *this), mask); | |
| 4504 | 4455 | } |
| 4505 | 4456 | |
| 4506 | 4457 | |
| 4458 | //------------------------------------------------- | |
| 4459 | // set_ioport - configure an I/O port read stub | |
| 4460 | // of the appropriate size | |
| 4461 | //------------------------------------------------- | |
| 4507 | 4462 | |
| 4508 | /*************************************************************************** | |
| 4509 | 64-BIT WRITE HANDLERS | |
| 4510 | ***************************************************************************/ | |
| 4511 | ||
| 4512 | void memory_write_byte_64le(const address_space *space, offs_t address, UINT8 data) | |
| 4463 | void handler_entry_write::set_ioport(const input_port_config &ioport) | |
| 4513 | 4464 | { |
| 4514 | UINT32 shift = (address & 7) * 8; | |
| 4515 | write_qword_generic(space, address, (UINT64)data << shift, (UINT64)0xff << shift); | |
| 4465 | m_ioport = &ioport; | |
| 4466 | if (m_datawidth == 8) | |
| 4467 | set_delegate(write8_delegate(write8_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_ioport<UINT8> >(ioport.tag), *this)); | |
| 4468 | else if (m_datawidth == 16) | |
| 4469 | set_delegate(write16_delegate(write16_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_ioport<UINT16> >(ioport.tag), *this)); | |
| 4470 | else if (m_datawidth == 32) | |
| 4471 | set_delegate(write32_delegate(write32_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_ioport<UINT32> >(ioport.tag), *this)); | |
| 4472 | else if (m_datawidth == 64) | |
| 4473 | set_delegate(write64_delegate(write64_proto_delegate::_create_member<handler_entry_write, &handler_entry_write::write_stub_ioport<UINT64> >(ioport.tag), *this)); | |
| 4516 | 4474 | } |
| 4517 | 4475 | |
| 4518 | void memory_write_byte_64be(const address_space *space, offs_t address, UINT8 data) | |
| 4519 | { | |
| 4520 | UINT32 shift = (~address & 7) * 8; | |
| 4521 | write_qword_generic(space, address, (UINT64)data << shift, (UINT64)0xff << shift); | |
| 4522 | } | |
| 4523 | 4476 | |
| 4524 | void memory_write_word_64le(const address_space *space, offs_t address, UINT16 data) | |
| 4525 | { | |
| 4526 | UINT32 shift = (address & 6) * 8; | |
| 4527 | write_qword_generic(space, address, (UINT64)data << shift, (UINT64)0xffff << shift); | |
| 4528 | } | |
| 4477 | //------------------------------------------------- | |
| 4478 | // write_stub_16_from_8 - construct a 16-bit write | |
| 4479 | // from 8-bit sources | |
| 4480 | //------------------------------------------------- | |
| 4529 | 4481 | |
| 4530 | void | |
| 4482 | void handle | |
| 4531 | 4483 | { |
| 4532 | UINT32 shift = (address & 6) * 8; | |
| 4533 | write_qword_generic(space, address, (UINT64)data << shift, (UINT64)mask << shift); | |
| 4484 | for (int index = 0; index < m_subunits; index++) | |
| 4485 | { | |
| 4486 | int shift = m_subshift[index]; | |
| 4487 | UINT8 mask8 = mask >> shift; | |
| 4488 | if (mask8 != 0) | |
| 4489 | m_write8(space, offset * m_subunits + index, data >> shift, mask8); | |
| 4490 | } | |
| 4534 | 4491 | } |
| 4535 | 4492 | |
| 4536 | void memory_write_word_64be(const address_space *space, offs_t address, UINT16 data) | |
| 4537 | { | |
| 4538 | UINT32 shift = (~address & 6) * 8; | |
| 4539 | write_qword_generic(space, address, (UINT64)data << shift, (UINT64)0xffff << shift); | |
| 4540 | } | |
| 4541 | 4493 | |
| 4542 | void memory_write_word_masked_64be(const address_space *space, offs_t address, UINT16 data, UINT16 mask) | |
| 4494 | //------------------------------------------------- | |
| 4495 | // write_stub_32_from_8 - construct a 32-bit write | |
| 4496 | // from 8-bit sources | |
| 4497 | //------------------------------------------------- | |
| 4498 | ||
| 4499 | void handler_entry_write::write_stub_32_from_8(address_space &space, offs_t offset, UINT32 data, UINT32 mask) | |
| 4543 | 4500 | { |
| 4544 | UINT32 shift = (~address & 6) * 8; | |
| 4545 | write_qword_generic(space, address, (UINT64)data << shift, (UINT64)mask << shift); | |
| 4501 | for (int index = 0; index < m_subunits; index++) | |
| 4502 | { | |
| 4503 | int shift = m_subshift[index]; | |
| 4504 | UINT8 mask8 = mask >> shift; | |
| 4505 | if (mask8 != 0) | |
| 4506 | m_write8(space, offset * m_subunits + index, data >> shift, mask8); | |
| 4507 | } | |
| 4546 | 4508 | } |
| 4547 | 4509 | |
| 4548 | void memory_write_dword_64le(const address_space *space, offs_t address, UINT32 data) | |
| 4510 | ||
| 4511 | //------------------------------------------------- | |
| 4512 | // write_stub_64_from_8 - construct a 64-bit write | |
| 4513 | // from 8-bit sources | |
| 4514 | //------------------------------------------------- | |
| 4515 | ||
| 4516 | void handler_entry_write::write_stub_64_from_8(address_space &space, offs_t offset, UINT64 data, UINT64 mask) | |
| 4549 | 4517 | { |
| 4550 | UINT32 shift = (address & 4) * 8; | |
| 4551 | write_qword_generic(space, address, (UINT64)data << shift, (UINT64)0xffffffff << shift); | |
| 4518 | for (int index = 0; index < m_subunits; index++) | |
| 4519 | { | |
| 4520 | int shift = m_subshift[index]; | |
| 4521 | UINT8 mask8 = mask >> shift; | |
| 4522 | if (mask8 != 0) | |
| 4523 | m_write8(space, offset * m_subunits + index, data >> shift, mask8); | |
| 4524 | } | |
| 4552 | 4525 | } |
| 4553 | 4526 | |
| 4554 | void memory_write_dword_masked_64le(const address_space *space, offs_t address, UINT32 data, UINT32 mask) | |
| 4527 | ||
| 4528 | //------------------------------------------------- | |
| 4529 | // write_stub_32_from_16 - construct a 32-bit | |
| 4530 | // write from 16-bit sources | |
| 4531 | //------------------------------------------------- | |
| 4532 | ||
| 4533 | void handler_entry_write::write_stub_32_from_16(address_space &space, offs_t offset, UINT32 data, UINT32 mask) | |
| 4555 | 4534 | { |
| 4556 | UINT32 shift = (address & 4) * 8; | |
| 4557 | write_qword_generic(space, address, (UINT64)data << shift, (UINT64)mask << shift); | |
| 4535 | for (int index = 0; index < m_subunits; index++) | |
| 4536 | { | |
| 4537 | int shift = m_subshift[index]; | |
| 4538 | UINT16 mask16 = mask >> shift; | |
| 4539 | if (mask16 != 0) | |
| 4540 | m_write16(space, offset * m_subunits + index, data >> shift, mask16); | |
| 4541 | } | |
| 4558 | 4542 | } |
| 4559 | 4543 | |
| 4560 | void memory_write_dword_64be(const address_space *space, offs_t address, UINT32 data) | |
| 4544 | ||
| 4545 | //------------------------------------------------- | |
| 4546 | // write_stub_64_from_16 - construct a 64-bit | |
| 4547 | // write from 16-bit sources | |
| 4548 | //------------------------------------------------- | |
| 4549 | ||
| 4550 | void handler_entry_write::write_stub_64_from_16(address_space &space, offs_t offset, UINT64 data, UINT64 mask) | |
| 4561 | 4551 | { |
| 4562 | UINT32 shift = (~address & 4) * 8; | |
| 4563 | write_qword_generic(space, address, (UINT64)data << shift, (UINT64)0xffffffff << shift); | |
| 4552 | for (int index = 0; index < m_subunits; index++) | |
| 4553 | { | |
| 4554 | int shift = m_subshift[index]; | |
| 4555 | UINT16 mask16 = mask >> shift; | |
| 4556 | if (mask16 != 0) | |
| 4557 | m_write16(space, offset * m_subunits + index, data >> shift, mask16); | |
| 4558 | } | |
| 4564 | 4559 | } |
| 4565 | 4560 | |
| 4566 | void memory_write_dword_masked_64be(const address_space *space, offs_t address, UINT32 data, UINT32 mask) | |
| 4561 | ||
| 4562 | //------------------------------------------------- | |
| 4563 | // write_stub_64_from_32 - construct a 64-bit | |
| 4564 | // write from 32-bit sources | |
| 4565 | //------------------------------------------------- | |
| 4566 | ||
| 4567 | void handler_entry_write::write_stub_64_from_32(address_space &space, offs_t offset, UINT64 data, UINT64 mask) | |
| 4567 | 4568 | { |
| 4568 | UINT32 shift = (~address & 4) * 8; | |
| 4569 | write_qword_generic(space, address, (UINT64)data << shift, (UINT64)mask << shift); | |
| 4569 | for (int index = 0; index < m_subunits; index++) | |
| 4570 | { | |
| 4571 | int shift = m_subshift[index]; | |
| 4572 | UINT32 mask32 = mask >> shift; | |
| 4573 | if (mask32 != 0) | |
| 4574 | m_write32(space, offset * m_subunits + index, data >> shift, mask32); | |
| 4575 | } | |
| 4570 | 4576 | } |
| 4571 | 4577 | |
| 4572 | void memory_write_qword_64le(const address_space *space, offs_t address, UINT64 data) | |
| 4578 | ||
| 4579 | //------------------------------------------------- | |
| 4580 | // write_stub_legacy - perform a write using | |
| 4581 | // legacy handler callbacks | |
| 4582 | //------------------------------------------------- | |
| 4583 | ||
| 4584 | void handler_entry_write::write_stub_legacy(address_space &space, offs_t offset, UINT8 data, UINT8 mask) | |
| 4573 | 4585 | { |
| 4574 | | |
| 4586 | m_l | |
| 4575 | 4587 | } |
| 4576 | 4588 | |
| 4577 | void | |
| 4589 | void handle | |
| 4578 | 4590 | { |
| 4579 | | |
| 4591 | m_l | |
| 4580 | 4592 | } |
| 4581 | 4593 | |
| 4582 | void | |
| 4594 | void handle | |
| 4583 | 4595 | { |
| 4584 | | |
| 4596 | m_l | |
| 4585 | 4597 | } |
| 4586 | 4598 | |
| 4587 | void | |
| 4599 | void handle | |
| 4588 | 4600 | { |
| 4589 | | |
| 4601 | m_l | |
| 4590 | 4602 | } |
| r8806 | r8807 | |
|---|---|---|
| 45 | 45 | $(EMUOBJ)/config.o \ |
| 46 | 46 | $(EMUOBJ)/crsshair.o \ |
| 47 | 47 | $(EMUOBJ)/debugger.o \ |
| 48 | $(EMUOBJ)/delegate.o \ | |
| 48 | 49 | $(EMUOBJ)/devcb.o \ |
| 49 | 50 | $(EMUOBJ)/devcpu.o \ |
| 50 | 51 | $(EMUOBJ)/devimage.o \ |
| r8806 | r8807 | |
|---|---|---|
| 4 | 4 | |
| 5 | 5 | Functions which handle device memory accesses. |
| 6 | 6 | |
| 7 | Copyright Nicola Salmoria and the MAME Team. | |
| 8 | Visit http://mamedev.org for licensing and usage restrictions. | |
| 7 | **************************************************************************** | |
| 9 | 8 | |
| 9 | Copyright Aaron Giles | |
| 10 | All rights reserved. | |
| 11 | ||
| 12 | Redistribution and use in source and binary forms, with or without | |
| 13 | modification, are permitted provided that the following conditions are | |
| 14 | met: | |
| 15 | ||
| 16 | * Redistributions of source code must retain the above copyright | |
| 17 | notice, this list of conditions and the following disclaimer. | |
| 18 | * Redistributions in binary form must reproduce the above copyright | |
| 19 | notice, this list of conditions and the following disclaimer in | |
| 20 | the documentation and/or other materials provided with the | |
| 21 | distribution. | |
| 22 | * Neither the name 'MAME' nor the names of its contributors may be | |
| 23 | used to endorse or promote products derived from this software | |
| 24 | without specific prior written permission. | |
| 25 | ||
| 26 | THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR | |
| 27 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 28 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| 29 | DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, | |
| 30 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 31 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| 32 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 33 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
| 34 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | |
| 35 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
| 36 | POSSIBILITY OF SUCH DAMAGE. | |
| 37 | ||
| 10 | 38 | ***************************************************************************/ |
| 11 | 39 | |
| 12 | 40 | #pragma once |
| r8806 | r8807 | |
| 20 | 48 | |
| 21 | 49 | |
| 22 | 50 | |
| 23 | /*************************************************************************** | |
| 24 | CONSTANTS | |
| 25 | ***************************************************************************/ | |
| 51 | //************************************************************************** | |
| 52 | // CONSTANTS | |
| 53 | //************************************************************************** | |
| 26 | 54 | |
| 27 | / | |
| 55 | // address spaces | |
| 28 | 56 | enum |
| 29 | 57 | { |
| 30 | ADDRESS_SPACE_0, /* first address space */ | |
| 31 | ADDRESS_SPACE_1, /* second address space */ | |
| 32 | ADDRESS_SPACE_2, /* third address space */ | |
| 33 | ADDRESS_SPACE_3, /* fourth address space */ | |
| 34 | ADDRESS_SPACES /* maximum number of address spaces */ | |
| 58 | ADDRESS_SPACE_0, // first address space | |
| 59 | ADDRESS_SPACE_1, // second address space | |
| 60 | ADDRESS_SPACE_2, // third address space | |
| 61 | ADDRESS_SPACE_3, // fourth address space | |
| 62 | ADDRESS_SPACES // maximum number of address spaces | |
| 35 | 63 | }; |
| 36 | 64 | |
| 65 | // read or write constants | |
| 66 | enum read_or_write | |
| 67 | { | |
| 68 | ROW_READ = 1, | |
| 69 | ROW_WRITE = 2, | |
| 70 | ROW_READWRITE = 3 | |
| 71 | }; | |
| 37 | 72 | |
| 38 | 73 | |
| 39 | /*************************************************************************** | |
| 40 | TYPE DEFINITIONS | |
| 41 | ***************************************************************************/ | |
| 42 | 74 | |
| 43 | /* referenced types from other classes */ | |
| 75 | //************************************************************************** | |
| 76 | // TYPE DEFINITIONS | |
| 77 | //************************************************************************** | |
| 78 | ||
| 79 | // referenced types from other classes | |
| 80 | class device_memory_interface; | |
| 44 | 81 | class device_config; |
| 45 | 82 | class device_t; |
| 46 | class address_map; | |
| 47 | 83 | struct game_driver; |
| 48 | 84 | |
| 85 | // forward declarations of classes defined here | |
| 86 | class address_map; | |
| 87 | class address_map_entry; | |
| 88 | class memory_bank; | |
| 89 | class direct_read_data; | |
| 90 | class address_space; | |
| 91 | class address_table; | |
| 92 | class address_table_read; | |
| 93 | class address_table_write; | |
| 49 | 94 | |
| 50 | /* handler_data and subtable_data are opaque types used to hold information about a particular handler */ | |
| 51 | typedef struct _handler_data handler_data; | |
| 52 | typedef struct _subtable_data subtable_data; | |
| 53 | 95 | |
| 54 | /* direct_range is an opaque type used to track ranges for direct access */ | |
| 55 | typedef struct _direct_range direct_range; | |
| 56 | ||
| 57 | /* forward-declare the address_space structure */ | |
| 58 | typedef struct _address_space address_space; | |
| 59 | ||
| 60 | ||
| 61 | /* offsets and addresses are 32-bit (for now...) */ | |
| 96 | // offsets and addresses are 32-bit (for now...) | |
| 62 | 97 | typedef UINT32 offs_t; |
| 63 | 98 | |
| 99 | // address map constructors are functions that build up an address_map | |
| 100 | typedef void (*address_map_constructor)(address_map &map, const device_config &devconfig); | |
| 64 | 101 | |
| 65 | /* direct_read_data contains state data for direct read access */ | |
| 66 | typedef struct _direct_read_data direct_read_data; | |
| 67 | struct _direct_read_data | |
| 68 | { | |
| 69 | UINT8 * raw; /* direct access data pointer (raw) */ | |
| 70 | UINT8 * decrypted; /* direct access data pointer (decrypted) */ | |
| 71 | offs_t bytemask; /* byte address mask */ | |
| 72 | offs_t bytestart; /* minimum valid byte address */ | |
| 73 | offs_t byteend; /* maximum valid byte address */ | |
| 74 | UINT8 entry; /* live entry */ | |
| 75 | direct_range * rangelist[256]; /* list of ranges for each entry */ | |
| 76 | direct_range * freerangelist; /* list of recycled range entries */ | |
| 77 | }; | |
| 78 | 102 | |
| 103 | // legacy space read/write handlers | |
| 104 | typedef UINT8 (*read8_space_func) (ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset); | |
| 105 | typedef void (*write8_space_func) (ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 data); | |
| 106 | typedef UINT16 (*read16_space_func) (ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 mem_mask); | |
| 107 | typedef void (*write16_space_func)(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 data, ATTR_UNUSED UINT16 mem_mask); | |
| 108 | typedef UINT32 (*read32_space_func) (ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 mem_mask); | |
| 109 | typedef void (*write32_space_func)(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 data, ATTR_UNUSED UINT32 mem_mask); | |
| 110 | typedef UINT64 (*read64_space_func) (ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 mem_mask); | |
| 111 | typedef void (*write64_space_func)(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 data, ATTR_UNUSED UINT64 mem_mask); | |
| 79 | 112 | |
| 80 | /* direct region update handler */ | |
| 81 | typedef offs_t (*direct_update_func) (ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t address, ATTR_UNUSED direct_read_data *direct); | |
| 82 | ||
| 83 | ||
| 84 | /* space read/write handlers */ | |
| 85 | typedef UINT8 (*read8_space_func) (ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t offset); | |
| 86 | typedef void (*write8_space_func) (ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 data); | |
| 87 | typedef UINT16 (*read16_space_func) (ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 mem_mask); | |
| 88 | typedef void (*write16_space_func)(ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 data, ATTR_UNUSED UINT16 mem_mask); | |
| 89 | typedef UINT32 (*read32_space_func) (ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 mem_mask); | |
| 90 | typedef void (*write32_space_func)(ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 data, ATTR_UNUSED UINT32 mem_mask); | |
| 91 | typedef UINT64 (*read64_space_func) (ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 mem_mask); | |
| 92 | typedef void (*write64_space_func)(ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 data, ATTR_UNUSED UINT64 mem_mask); | |
| 93 | ||
| 94 | ||
| 95 | /* device read/write handlers */ | |
| 113 | // legacy device read/write handlers | |
| 96 | 114 | typedef UINT8 (*read8_device_func) (ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset); |
| 97 | 115 | typedef void (*write8_device_func) (ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 data); |
| 98 | 116 | typedef UINT16 (*read16_device_func) (ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 mem_mask); |
| r8806 | r8807 | |
| 103 | 121 | typedef void (*write64_device_func)(ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 data, ATTR_UNUSED UINT64 mem_mask); |
| 104 | 122 | |
| 105 | 123 | |
| 106 | /* data_accessors is a struct with accessors of all flavors */ | |
| 107 | typedef struct _data_accessors data_accessors; | |
| 108 | struct _data_accessors | |
| 124 | // struct with function pointers for accessors; use is generally discouraged unless necessary | |
| 125 | struct data_accessors | |
| 109 | 126 | { |
| 110 | UINT8 (*read_byte)(const address_space *space, offs_t byteaddress); | |
| 111 | UINT16 (*read_word)(const address_space *space, offs_t byteaddress); | |
| 112 | UINT16 (*read_word_masked)(const address_space *space, offs_t byteaddress, UINT16 mask); | |
| 113 | UINT32 (*read_dword)(const address_space *space, offs_t byteaddress); | |
| 114 | UINT32 (*read_dword_masked)(const address_space *space, offs_t byteaddress, UINT32 mask); | |
| 115 | UINT64 (*read_qword)(const address_space *space, offs_t byteaddress); | |
| 116 | UINT64 (*read_qword_masked)(const address_space *space, offs_t byteaddress, UINT64 mask); | |
| 127 | UINT8 (*read_byte)(address_space *space, offs_t byteaddress); | |
| 128 | UINT16 (*read_word)(address_space *space, offs_t byteaddress); | |
| 129 | UINT16 (*read_word_masked)(address_space *space, offs_t byteaddress, UINT16 mask); | |
| 130 | UINT32 (*read_dword)(address_space *space, offs_t byteaddress); | |
| 131 | UINT32 (*read_dword_masked)(address_space *space, offs_t byteaddress, UINT32 mask); | |
| 132 | UINT64 (*read_qword)(address_space *space, offs_t byteaddress); | |
| 133 | UINT64 (*read_qword_masked)(address_space *space, offs_t byteaddress, UINT64 mask); | |
| 117 | 134 | |
| 118 | void (*write_byte)(const address_space *space, offs_t byteaddress, UINT8 data); | |
| 119 | void (*write_word)(const address_space *space, offs_t byteaddress, UINT16 data); | |
| 120 | void (*write_word_masked)(const address_space *space, offs_t byteaddress, UINT16 data, UINT16 mask); | |
| 121 | void (*write_dword)(const address_space *space, offs_t byteaddress, UINT32 data); | |
| 122 | void (*write_dword_masked)(const address_space *space, offs_t byteaddress, UINT32 data, UINT32 mask); | |
| 123 | void (*write_qword)(const address_space *space, offs_t byteaddress, UINT64 data); | |
| 124 | void (*write_qword_masked)(const address_space *space, offs_t byteaddress, UINT64 data, UINT64 mask); | |
| 135 | void (*write_byte)(address_space *space, offs_t byteaddress, UINT8 data); | |
| 136 | void (*write_word)(address_space *space, offs_t byteaddress, UINT16 data); | |
| 137 | void (*write_word_masked)(address_space *space, offs_t byteaddress, UINT16 data, UINT16 mask); | |
| 138 | void (*write_dword)(address_space *space, offs_t byteaddress, UINT32 data); | |
| 139 | void (*write_dword_masked)(address_space *space, offs_t byteaddress, UINT32 data, UINT32 mask); | |
| 140 | void (*write_qword)(address_space *space, offs_t byteaddress, UINT64 data); | |
| 141 | void (*write_qword_masked)(address_space *space, offs_t byteaddress, UINT64 data, UINT64 mask); | |
| 125 | 142 | }; |
| 126 | 143 | |
| 127 | 144 | |
| 128 | /* address_table contains information about read/write accesses within an address space */ | |
| 129 | typedef struct _address_table address_table; | |
| 130 | struct _address_table | |
| 145 | // ======================> direct_update_delegate | |
| 146 | ||
| 147 | // direct region update handler | |
| 148 | typedef proto_delegate_2param<offs_t, direct_read_data &, offs_t> direct_update_proto_delegate; | |
| 149 | typedef delegate_2param<offs_t, direct_read_data &, offs_t> direct_update_delegate; | |
| 150 | ||
| 151 | #define direct_update_delegate_create(_Class, _Method, _Object) direct_update_delegate(direct_update_proto_delegate::_create_member<_Class, &_Class::_Method>(#_Class "::" #_Method), _Object) | |
| 152 | #define direct_update_delegate_create_static(_Function, _Object) direct_update_delegate(direct_update_proto_delegate::_create_static<running_machine, &_Function>(#_Function), _Object) | |
| 153 | ||
| 154 | ||
| 155 | // ======================> read_delegate | |
| 156 | ||
| 157 | // declare proto-delegates for each width | |
| 158 | typedef proto_delegate_3param<UINT8, address_space &, offs_t, UINT8> read8_proto_delegate; | |
| 159 | typedef proto_delegate_3param<UINT16, address_space &, offs_t, UINT16> read16_proto_delegate; | |
| 160 | typedef proto_delegate_3param<UINT32, address_space &, offs_t, UINT32> read32_proto_delegate; | |
| 161 | typedef proto_delegate_3param<UINT64, address_space &, offs_t, UINT64> read64_proto_delegate; | |
| 162 | ||
| 163 | // declare delegates for each width | |
| 164 | typedef delegate_3param<UINT8, address_space &, offs_t, UINT8> read8_delegate; | |
| 165 | typedef delegate_3param<UINT16, address_space &, offs_t, UINT16> read16_delegate; | |
| 166 | typedef delegate_3param<UINT32, address_space &, offs_t, UINT32> read32_delegate; | |
| 167 | typedef delegate_3param<UINT64, address_space &, offs_t, UINT64> read64_delegate; | |
| 168 | ||
| 169 | // macros for creating read proto-delegates | |
| 170 | #define read8_proto_delegate_create(_Class, _Method) read8_proto_delegate::_create_member<_Class, &_Class::_Method>(#_Class "::" #_Method) | |
| 171 | #define read16_proto_delegate_create(_Class, _Method) read16_proto_delegate::_create_member<_Class, &_Class::_Method>(#_Class "::" #_Method) | |
| 172 | #define read32_proto_delegate_create(_Class, _Method) read32_proto_delegate::_create_member<_Class, &_Class::_Method>(#_Class "::" #_Method) | |
| 173 | #define read64_proto_delegate_create(_Class, _Method) read64_proto_delegate::_create_member<_Class, &_Class::_Method>(#_Class "::" #_Method) | |
| 174 | ||
| 175 | // macros for creating read delegates, bound to the provided object | |
| 176 | #define read8_delegate_create(_Class, _Method, _Object) read8_delegate(read8_proto_delegate_create(_Class, _Method), _Object) | |
| 177 | #define read16_delegate_create(_Class, _Method, _Object) read16_delegate(read16_proto_delegate_create(_Class, _Method), _Object) | |
| 178 | #define read32_delegate_create(_Class, _Method, _Object) read32_delegate(read32_proto_delegate_create(_Class, _Method), _Object) | |
| 179 | #define read64_delegate_create(_Class, _Method, _Object) read64_delegate(read64_proto_delegate_create(_Class, _Method), _Object) | |
| 180 | ||
| 181 | ||
| 182 | // ======================> write_delegate | |
| 183 | ||
| 184 | // declare proto-delegates for each width | |
| 185 | typedef proto_delegate_4param<void, address_space &, offs_t, UINT8, UINT8> write8_proto_delegate; | |
| 186 | typedef proto_delegate_4param<void, address_space &, offs_t, UINT16, UINT16> write16_proto_delegate; | |
| 187 | typedef proto_delegate_4param<void, address_space &, offs_t, UINT32, UINT32> write32_proto_delegate; | |
| 188 | typedef proto_delegate_4param<void, address_space &, offs_t, UINT64, UINT64> write64_proto_delegate; | |
| 189 | ||
| 190 | // declare delegates for each width | |
| 191 | typedef delegate_4param<void, address_space &, offs_t, UINT8, UINT8> write8_delegate; | |
| 192 | typedef delegate_4param<void, address_space &, offs_t, UINT16, UINT16> write16_delegate; | |
| 193 | typedef delegate_4param<void, address_space &, offs_t, UINT32, UINT32> write32_delegate; | |
| 194 | typedef delegate_4param<void, address_space &, offs_t, UINT64, UINT64> write64_delegate; | |
| 195 | ||
| 196 | // macros for creating write proto-delegates | |
| 197 | #define write8_proto_delegate_create(_Class, _Method) write8_proto_delegate::_create_member<_Class, &_Class::_Method>(#_Class "::" #_Method) | |
| 198 | #define write16_proto_delegate_create(_Class, _Method) write16_proto_delegate::_create_member<_Class, &_Class::_Method>(#_Class "::" #_Method) | |
| 199 | #define write32_proto_delegate_create(_Class, _Method) write32_proto_delegate::_create_member<_Class, &_Class::_Method>(#_Class "::" #_Method) | |
| 200 | #define write64_proto_delegate_create(_Class, _Method) write64_proto_delegate::_create_member<_Class, &_Class::_Method>(#_Class "::" #_Method) | |
| 201 | ||
| 202 | // macros for creating write delegates, bound to the provided object | |
| 203 | #define write8_delegate_create(_Class, _Method, _Object) write8_delegate(write8_proto_delegate::_create_member<_Class, &_Class::_Method>(#_Class "::" #_Method), _Object) | |
| 204 | #define write16_delegate_create(_Class, _Method, _Object) write16_delegate(write16_proto_delegate::_create_member<_Class, &_Class::_Method>(#_Class "::" #_Method), _Object) | |
| 205 | #define write32_delegate_create(_Class, _Method, _Object) write32_delegate(write32_proto_delegate::_create_member<_Class, &_Class::_Method>(#_Class "::" #_Method), _Object) | |
| 206 | #define write64_delegate_create(_Class, _Method, _Object) write64_delegate(write64_proto_delegate::_create_member<_Class, &_Class::_Method>(#_Class "::" #_Method), _Object) | |
| 207 | ||
| 208 | ||
| 209 | // ======================> direct_read_data | |
| 210 | ||
| 211 | // direct_read_data contains state data for direct read access | |
| 212 | class direct_read_data | |
| 131 | 213 | { |
| 132 | UINT8 * table; /* pointer to base of table */ | |
| 133 | UINT8 subtable_alloc; /* number of subtables allocated */ | |
| 134 | subtable_data * subtable; /* info about each subtable */ | |
| 135 | handler_data * handlers[256]; /* array of user-installed handlers */ | |
| 136 | running_machine * machine; /* pointer back to the machine */ | |
| 214 | friend class address_table; | |
| 215 | ||
| 216 | public: | |
| 217 | // direct_range is an internal class that is part of a list of start/end ranges | |
| 218 | class direct_range | |
| 219 | { | |
| 220 | public: | |
| 221 | // construction | |
| 222 | direct_range() | |
| 223 | : m_next(NULL), | |
| 224 | m_bytestart(0), | |
| 225 | m_byteend(~0) { } | |
| 226 | ||
| 227 | // getters | |
| 228 | direct_range *next() const { return m_next; } | |
| 229 | ||
| 230 | // internal state | |
| 231 | direct_range * m_next; // pointer to the next range in the list | |
| 232 | offs_t m_bytestart; // starting byte offset of the range | |
| 233 | offs_t m_byteend; // ending byte offset of the range | |
| 234 | }; | |
| 235 | ||
| 236 | // construction/destruction | |
| 237 | direct_read_data(address_space &space); | |
| 238 | ~direct_read_data(); | |
| 239 | ||
| 240 | // getters | |
| 241 | address_space &space() const { return m_space; } | |
| 242 | UINT8 *raw() const { return m_raw; } | |
| 243 | UINT8 *decrypted() const { return m_decrypted; } | |
| 244 | ||
| 245 | // see if an address is within bounds, or attempt to update it if not | |
| 246 | bool address_is_valid(offs_t byteaddress) { return EXPECTED(byteaddress >= m_bytestart && byteaddress <= m_byteend) || set_direct_region(byteaddress); } | |
| 247 | ||
| 248 | // force a recomputation on the next read | |
| 249 | void force_update() { m_byteend = 0; m_bytestart = 1; } | |
| 250 | void force_update(UINT8 if_match) { if (m_entry == if_match) force_update(); } | |
| 251 | ||
| 252 | // custom update callbacks and configuration | |
| 253 | direct_update_delegate set_direct_update(direct_update_delegate function); | |
| 254 | void explicit_configure(offs_t bytestart, offs_t byteend, offs_t bytemask, void *raw, void *decrypted = NULL); | |
| 255 | ||
| 256 | // accessor methods for reading raw data | |
| 257 | void *read_raw_ptr(offs_t byteaddress); | |
| 258 | UINT8 read_raw_byte(offs_t byteaddress); | |
| 259 | UINT16 read_raw_word(offs_t byteaddress); | |
| 260 | UINT32 read_raw_dword(offs_t byteaddress); | |
| 261 | UINT64 read_raw_qword(offs_t byteaddress); | |
| 262 | ||
| 263 | // accessor methods for reading decrypted data | |
| 264 | void *read_decrypted_ptr(offs_t byteaddress); | |
| 265 | UINT8 read_decrypted_byte(offs_t byteaddress); | |
| 266 | UINT16 read_decrypted_word(offs_t byteaddress); | |
| 267 | UINT32 read_decrypted_dword(offs_t byteaddress); | |
| 268 | UINT64 read_decrypted_qword(offs_t byteaddress); | |
| 269 | ||
| 270 | private: | |
| 271 | // internal helpers | |
| 272 | bool set_direct_region(offs_t &byteaddress); | |
| 273 | direct_range *find_range(offs_t byteaddress, UINT8 &entry); | |
| 274 | void remove_intersecting_ranges(offs_t bytestart, offs_t byteend); | |
| 275 | ||
| 276 | // internal state | |
| 277 | address_space & m_space; | |
| 278 | UINT8 * m_raw; // direct access data pointer (raw) | |
| 279 | UINT8 * m_decrypted; // direct access data pointer (decrypted) | |
| 280 | offs_t m_bytemask; // byte address mask | |
| 281 | offs_t m_bytestart; // minimum valid byte address | |
| 282 | offs_t m_byteend; // maximum valid byte address | |
| 283 | UINT8 m_entry; // live entry | |
| 284 | simple_list<direct_range> m_rangelist[256]; // list of ranges for each entry | |
| 285 | simple_list<direct_range> m_freerangelist; // list of recycled range entries | |
| 286 | direct_update_delegate m_directupdate; // fast direct-access update callback | |
| 137 | 287 | }; |
| 138 | 288 | |
| 139 | 289 | |
| 140 | /* address_space holds live information about an address space */ | |
| 141 | /* Declared above: typedef struct _address_space address_space; */ | |
| 142 | struct _address_space | |
| 290 | // ======================> address_space_config | |
| 291 | ||
| 292 | // describes an address space and provides basic functions to map addresses to bytes | |
| 293 | class address_space_config | |
| 143 | 294 | { |
| 144 | address_space * next; /* next address space in the global list */ | |
| 145 | running_machine * machine; /* reference to the owning machine */ | |
| 146 | device_t * cpu; /* reference to the owning device */ | |
| 147 | const device_config * devconfig; /* pointer to the owning device's config */ | |
| 148 | address_map * map; /* original memory map */ | |
| 149 | const char * name; /* friendly name of the address space */ | |
| 150 | UINT8 * readlookup; /* live lookup table for reads */ | |
| 151 | UINT8 * writelookup; /* live lookup table for writes */ | |
| 152 | data_accessors accessors; /* data access handlers */ | |
| 153 | direct_read_data direct; /* fast direct-access read info */ | |
| 154 | direct_update_func directupdate; /* fast direct-access update callback */ | |
| 155 | UINT64 unmap; /* unmapped value */ | |
| 156 | offs_t addrmask; /* physical address mask */ | |
| 157 | offs_t bytemask; /* byte-converted physical address mask */ | |
| 158 | offs_t logaddrmask; /* logical address mask */ | |
| 159 | offs_t logbytemask; /* byte-converted logical address mask */ | |
| 160 | UINT8 spacenum; /* address space index */ | |
| 161 | endianness_t endianness; /* endianness of this space */ | |
| 162 | INT8 ashift; /* address shift */ | |
| 163 | UINT8 abits; /* address bits */ | |
| 164 | UINT8 dbits; /* data bits */ | |
| 165 | UINT8 addrchars; /* number of characters to use for physical addresses */ | |
| 166 | UINT8 logaddrchars; /* number of characters to use for logical addresses */ | |
| 167 | UINT8 debugger_access; /* treat accesses as coming from the debugger */ | |
| 168 | UINT8 log_unmap; /* log unmapped accesses in this space? */ | |
| 169 | address_table read; /* memory read lookup table */ | |
| 170 | address_table write; /* memory write lookup table */ | |
| 295 | public: | |
| 296 | // construction/destruction | |
| 297 | address_space_config(); | |
| 298 | address_space_config(const char *name, endianness_t endian, UINT8 datawidth, UINT8 addrwidth, INT8 addrshift = 0, address_map_constructor internal = NULL, address_map_constructor defmap = NULL); | |
| 299 | address_space_config(const char *name, endianness_t endian, UINT8 datawidth, UINT8 addrwidth, INT8 addrshift, UINT8 logwidth, UINT8 pageshift, address_map_constructor internal = NULL, address_map_constructor defmap = NULL); | |
| 300 | ||
| 301 | // getters | |
| 302 | const char *name() const { return m_name; } | |
| 303 | endianness_t endianness() const { return m_endianness; } | |
| 304 | int data_width() const { return m_databus_width; } | |
| 305 | int addr_width() const { return m_addrbus_width; } | |
| 306 | ||
| 307 | // address-to-byte conversion helpers | |
| 308 | inline offs_t addr2byte(offs_t address) const { return (m_addrbus_shift < 0) ? (address << -m_addrbus_shift) : (address >> m_addrbus_shift); } | |
| 309 | inline offs_t addr2byte_end(offs_t address) const { return (m_addrbus_shift < 0) ? ((address << -m_addrbus_shift) | ((1 << -m_addrbus_shift) - 1)) : (address >> m_addrbus_shift); } | |
| 310 | inline offs_t byte2addr(offs_t address) const { return (m_addrbus_shift > 0) ? (address << m_addrbus_shift) : (address >> -m_addrbus_shift); } | |
| 311 | inline offs_t byte2addr_end(offs_t address) const { return (m_addrbus_shift > 0) ? ((address << m_addrbus_shift) | ((1 << -m_addrbus_shift) - 1)) : (address >> -m_addrbus_shift); } | |
| 312 | ||
| 313 | // state | |
| 314 | const char * m_name; | |
| 315 | endianness_t m_endianness; | |
| 316 | UINT8 m_databus_width; | |
| 317 | UINT8 m_addrbus_width; | |
| 318 | INT8 m_addrbus_shift; | |
| 319 | UINT8 m_logaddr_width; | |
| 320 | UINT8 m_page_shift; | |
| 321 | address_map_constructor m_internal_map; | |
| 322 | address_map_constructor m_default_map; | |
| 171 | 323 | }; |
| 172 | 324 | |
| 173 | 325 | |
| 326 | // ======================> address_space | |
| 174 | 327 | |
| 175 | /*************************************************************************** | |
| 176 | MACROS | |
| 177 | ***************************************************************************/ | |
| 328 | // address_space holds live information about an address space | |
| 329 | class address_space : public bindable_object | |
| 330 | { | |
| 331 | friend class address_table; | |
| 332 | friend class address_table_read; | |
| 333 | friend class address_table_write; | |
| 334 | friend class direct_read_data; | |
| 335 | friend class simple_list<address_space>; | |
| 336 | friend resource_pool_object<address_space>::~resource_pool_object(); | |
| 178 | 337 | |
| 179 | /* opcode base adjustment handler function macro */ | |
| 180 | #define DIRECT_UPDATE_HANDLER(name) offs_t name(ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t address, direct_read_data *direct) | |
| 338 | protected: | |
| 339 | // construction/destruction | |
| 340 | address_space(device_memory_interface &memory, int spacenum, bool large); | |
| 341 | ~address_space(); | |
| 181 | 342 | |
| 343 | public: | |
| 344 | // public allocator | |
| 345 | static address_space &allocate(running_machine &machine, const address_space_config &config, device_memory_interface &memory, int spacenum); | |
| 182 | 346 | |
| 183 | /* space read/write handler function macros */ | |
| 184 | #define READ8_HANDLER(name) UINT8 name(ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t offset) | |
| 185 | #define WRITE8_HANDLER(name) void name(ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 data) | |
| 186 | #define READ16_HANDLER(name) UINT16 name(ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 mem_mask) | |
| 187 | #define WRITE16_HANDLER(name) void name(ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 data, ATTR_UNUSED UINT16 mem_mask) | |
| 188 | #define READ32_HANDLER(name) UINT32 name(ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 mem_mask) | |
| 189 | #define WRITE32_HANDLER(name) void name(ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 data, ATTR_UNUSED UINT32 mem_mask) | |
| 190 | #define READ64_HANDLER(name) UINT64 name(ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 mem_mask) | |
| 191 | #define WRITE64_HANDLER(name) void name(ATTR_UNUSED const address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 data, ATTR_UNUSED UINT64 mem_mask) | |
| 347 | // getters | |
| 348 | address_space *next() const { return m_next; } | |
| 349 | device_t &device() const { return m_device; } | |
| 350 | const char *name() const { return m_name; } | |
| 351 | int spacenum() const { return m_spacenum; } | |
| 352 | address_map *map() const { return m_map; } | |
| 192 | 353 | |
| 354 | direct_read_data &direct() const { return const_cast<direct_read_data &>(m_direct); } | |
| 193 | 355 | |
| 194 | /* device read/write handler function macros */ | |
| 356 | int data_width() const { return m_config.data_width(); } | |
| 357 | int addr_width() const { return m_config.addr_width(); } | |
| 358 | endianness_t endianness() const { return m_config.endianness(); } | |
| 359 | UINT64 unmap() const { return m_unmap; } | |
| 360 | ||
| 361 | offs_t addrmask() const { return m_addrmask; } | |
| 362 | offs_t bytemask() const { return m_bytemask; } | |
| 363 | UINT8 addrchars() const { return m_addrchars; } | |
| 364 | offs_t logaddrmask() const { return m_logaddrmask; } | |
| 365 | offs_t logbytemask() const { return m_logbytemask; } | |
| 366 | UINT8 logaddrchars() const { return m_logaddrchars; } | |
| 367 | ||
| 368 | // debug helpers | |
| 369 | const char *get_handler_string(read_or_write readorwrite, offs_t byteaddress); | |
| 370 | bool debugger_access() const { return m_debugger_access; } | |
| 371 | void set_debugger_access(bool debugger) { m_debugger_access = debugger; } | |
| 372 | bool log_unmap() const { return m_log_unmap; } | |
| 373 | void set_log_unmap(bool log) { m_log_unmap = log; } | |
| 374 | void dump_map(FILE *file, read_or_write readorwrite); | |
| 375 | ||
| 376 | // watchpoint enablers | |
| 377 | virtual void enable_read_watchpoints(bool enable = true) = 0; | |
| 378 | virtual void enable_write_watchpoints(bool enable = true) = 0; | |
| 379 | ||
| 380 | // general accessors | |
| 381 | virtual void accessors(data_accessors &accessors) const = 0; | |
| 382 | virtual void *get_read_ptr(offs_t byteaddress) = 0; | |
| 383 | virtual void *get_write_ptr(offs_t byteaddress) = 0; | |
| 384 | ||
| 385 | // read accessors | |
| 386 | virtual UINT8 read_byte(offs_t byteaddress) = 0; | |
| 387 | virtual UINT16 read_word(offs_t byteaddress, UINT16 mask = 0xffff) = 0; | |
| 388 | virtual UINT32 read_dword(offs_t byteaddress, UINT32 mask = 0xffffffff) = 0; | |
| 389 | virtual UINT64 read_qword(offs_t byteaddress, UINT64 mask = U64(0xffffffffffffffff)) = 0; | |
| 390 | ||
| 391 | // write accessors | |
| 392 | virtual void write_byte(offs_t byteaddress, UINT8 data) = 0; | |
| 393 | virtual void write_word(offs_t byteaddress, UINT16 data, UINT16 mask = 0xffff) = 0; | |
| 394 | virtual void write_dword(offs_t byteaddress, UINT32 data, UINT32 mask = 0xffffffff) = 0; | |
| 395 | virtual void write_qword(offs_t byteaddress, UINT64 data, UINT64 mask = U64(0xffffffffffffffff)) = 0; | |
| 396 | ||
| 397 | // address-to-byte conversion helpers | |
| 398 | offs_t address_to_byte(offs_t address) const { return m_config.addr2byte(address); } | |
| 399 | offs_t address_to_byte_end(offs_t address) const { return m_config.addr2byte_end(address); } | |
| 400 | offs_t byte_to_address(offs_t address) const { return m_config.byte2addr(address); } | |
| 401 | offs_t byte_to_address_end(offs_t address) const { return m_config.byte2addr_end(address); } | |
| 402 | ||
| 403 | // decryption | |
| 404 | void set_decrypted_region(offs_t addrstart, offs_t addrend, void *base); | |
| 405 | ||
| 406 | // direct access | |
| 407 | direct_update_delegate set_direct_update_handler(direct_update_delegate function) { return m_direct.set_direct_update(function); } | |
| 408 | bool set_direct_region(offs_t &byteaddress); | |
| 409 | ||
| 410 | // static handler installation | |
| 411 | void unmap(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read_or_write readorwrite, bool quiet); | |
| 412 | void install_port(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, const char *rtag, const char *wtag); | |
| 413 | void install_bank(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, const char *rtag, const char *wtag); | |
| 414 | void *install_ram(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read_or_write readorwrite, void *baseptr = NULL); | |
| 415 | ||
| 416 | // install new-style delegate handlers | |
| 417 | UINT8 *install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_delegate rhandler, UINT64 unitmask = 0); | |
| 418 | UINT8 *install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write8_delegate whandler, UINT64 unitmask = 0); | |
| 419 | UINT8 *install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_delegate rhandler, write8_delegate whandler, UINT64 unitmask = 0); | |
| 420 | UINT16 *install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_delegate rhandler, UINT64 unitmask = 0); | |
| 421 | UINT16 *install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write16_delegate whandler, UINT64 unitmask = 0); | |
| 422 | UINT16 *install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_delegate rhandler, write16_delegate whandler, UINT64 unitmask = 0); | |
| 423 | UINT32 *install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_delegate rhandler, UINT64 unitmask = 0); | |
| 424 | UINT32 *install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write32_delegate whandler, UINT64 unitmask = 0); | |
| 425 | UINT32 *install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_delegate rhandler, write32_delegate whandler, UINT64 unitmask = 0); | |
| 426 | UINT64 *install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_delegate rhandler, UINT64 unitmask = 0); | |
| 427 | UINT64 *install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write64_delegate whandler, UINT64 unitmask = 0); | |
| 428 | UINT64 *install_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_delegate rhandler, write64_delegate whandler, UINT64 unitmask = 0); | |
| 429 | ||
| 430 | // install legacy address space handlers | |
| 431 | UINT8 *install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_space_func rhandler, const char *rname, UINT64 unitmask = 0); | |
| 432 | UINT8 *install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write8_space_func whandler, const char *wname, UINT64 unitmask = 0); | |
| 433 | UINT8 *install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_space_func rhandler, const char *rname, write8_space_func whandler, const char *wname, UINT64 unitmask = 0); | |
| 434 | UINT16 *install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_space_func rhandler, const char *rname, UINT64 unitmask = 0); | |
| 435 | UINT16 *install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write16_space_func whandler, const char *wname, UINT64 unitmask = 0); | |
| 436 | UINT16 *install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_space_func rhandler, const char *rname, write16_space_func whandler, const char *wname, UINT64 unitmask = 0); | |
| 437 | UINT32 *install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_space_func rhandler, const char *rname, UINT64 unitmask = 0); | |
| 438 | UINT32 *install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write32_space_func whandler, const char *wname, UINT64 unitmask = 0); | |
| 439 | UINT32 *install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_space_func rhandler, const char *rname, write32_space_func whandler, const char *wname, UINT64 unitmask = 0); | |
| 440 | UINT64 *install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_space_func rhandler, const char *rname, UINT64 unitmask = 0); | |
| 441 | UINT64 *install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write64_space_func whandler, const char *wname, UINT64 unitmask = 0); | |
| 442 | UINT64 *install_legacy_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_space_func rhandler, const char *rname, write64_space_func whandler, const char *wname, UINT64 unitmask = 0); | |
| 443 | ||
| 444 | // install legacy device handlers | |
| 445 | UINT8 *install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_device_func rhandler, const char *rname, UINT64 unitmask = 0); | |
| 446 | UINT8 *install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write8_device_func whandler, const char *wname, UINT64 unitmask = 0); | |
| 447 | UINT8 *install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_device_func rhandler, const char *rname, write8_device_func whandler, const char *wname, UINT64 unitmask = 0); | |
| 448 | UINT16 *install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_device_func rhandler, const char *rname, UINT64 unitmask = 0); | |
| 449 | UINT16 *install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write16_device_func whandler, const char *wname, UINT64 unitmask = 0); | |
| 450 | UINT16 *install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_device_func rhandler, const char *rname, write16_device_func whandler, const char *wname, UINT64 unitmask = 0); | |
| 451 | UINT32 *install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_device_func rhandler, const char *rname, UINT64 unitmask = 0); | |
| 452 | UINT32 *install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write32_device_func whandler, const char *wname, UINT64 unitmask = 0); | |
| 453 | UINT32 *install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_device_func rhandler, const char *rname, write32_device_func whandler, const char *wname, UINT64 unitmask = 0); | |
| 454 | UINT64 *install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_device_func rhandler, const char *rname, UINT64 unitmask = 0); | |
| 455 | UINT64 *install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, write64_device_func whandler, const char *wname, UINT64 unitmask = 0); | |
| 456 | UINT64 *install_legacy_handler(device_t &device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_device_func rhandler, const char *rname, write64_device_func whandler, const char *wname, UINT64 unitmask = 0); | |
| 457 | ||
| 458 | // setup | |
| 459 | void prepare_map(); | |
| 460 | void populate_from_map(); | |
| 461 | void allocate_memory(); | |
| 462 | void locate_memory(); | |
| 463 | ||
| 464 | private: | |
| 465 | // internal helpers | |
| 466 | virtual address_table_read &read() = 0; | |
| 467 | virtual address_table_write &write() = 0; | |
| 468 | void populate_map_entry(const address_map_entry &entry, read_or_write readorwrite); | |
| 469 | void bind_and_install_handler(const address_map_entry &entry, read_or_write readorwrite, device_t *device); | |
| 470 | void adjust_addresses(offs_t &start, offs_t &end, offs_t &mask, offs_t &mirror); | |
| 471 | void *find_backing_memory(offs_t addrstart, offs_t addrend); | |
| 472 | bool needs_backing_store(const address_map_entry *entry); | |
| 473 | memory_bank &bank_find_or_allocate(const char *tag, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read_or_write readorwrite); | |
| 474 | address_map_entry *block_assign_intersecting(offs_t bytestart, offs_t byteend, UINT8 *base); | |
| 475 | ||
| 476 | public: | |
| 477 | // public state (eventually will go away) | |
| 478 | running_machine * machine; // kept for backwards compatibility | |
| 479 | device_t * cpu; // kept for backwards compatibility | |
| 480 | running_machine & m_machine; // reference to the owning machine | |
| 481 | ||
| 482 | protected: | |
| 483 | // private state | |
| 484 | address_space * m_next; // next address space in the global list | |
| 485 | const address_space_config &m_config; // configuration of this space | |
| 486 | device_t & m_device; // reference to the owning device | |
| 487 | address_map * m_map; // original memory map | |
| 488 | offs_t m_addrmask; // physical address mask | |
| 489 | offs_t m_bytemask; // byte-converted physical address mask | |
| 490 | offs_t m_logaddrmask; // logical address mask | |
| 491 | offs_t m_logbytemask; // byte-converted logical address mask | |
| 492 | UINT64 m_unmap; // unmapped value | |
| 493 | UINT8 m_spacenum; // address space index | |
| 494 | bool m_debugger_access; // treat accesses as coming from the debugger | |
| 495 | bool m_log_unmap; // log unmapped accesses in this space? | |
| 496 | direct_read_data & m_direct; // fast direct-access read info | |
| 497 | const char * m_name; // friendly name of the address space | |
| 498 | UINT8 m_addrchars; // number of characters to use for physical addresses | |
| 499 | UINT8 m_logaddrchars; // number of characters to use for logical addresses | |
| 500 | }; | |
| 501 | ||
| 502 | ||
| 503 | ||
| 504 | //************************************************************************** | |
| 505 | // MACROS | |
| 506 | //************************************************************************** | |
| 507 | ||
| 508 | // opcode base adjustment handler function macro | |
| 509 | #define DIRECT_UPDATE_MEMBER(name) offs_t name(ATTR_UNUSED direct_read_data &direct, ATTR_UNUSED offs_t address) | |
| 510 | #define DIRECT_UPDATE_HANDLER(name) offs_t name(ATTR_UNUSED running_machine *machine, ATTR_UNUSED direct_read_data &direct, ATTR_UNUSED offs_t address) | |
| 511 | ||
| 512 | ||
| 513 | // space read/write handler function macros | |
| 514 | #define READ8_HANDLER(name) UINT8 name(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset) | |
| 515 | #define WRITE8_HANDLER(name) void name(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 data) | |
| 516 | #define READ16_HANDLER(name) UINT16 name(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 mem_mask) | |
| 517 | #define WRITE16_HANDLER(name) void name(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 data, ATTR_UNUSED UINT16 mem_mask) | |
| 518 | #define READ32_HANDLER(name) UINT32 name(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 mem_mask) | |
| 519 | #define WRITE32_HANDLER(name) void name(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 data, ATTR_UNUSED UINT32 mem_mask) | |
| 520 | #define READ64_HANDLER(name) UINT64 name(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 mem_mask) | |
| 521 | #define WRITE64_HANDLER(name) void name(ATTR_UNUSED address_space *space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 data, ATTR_UNUSED UINT64 mem_mask) | |
| 522 | ||
| 523 | ||
| 524 | // device read/write handler function macros | |
| 195 | 525 | #define READ8_DEVICE_HANDLER(name) UINT8 name(ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset) |
| 196 | 526 | #define WRITE8_DEVICE_HANDLER(name) void name(ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 data) |
| 197 | 527 | #define READ16_DEVICE_HANDLER(name) UINT16 name(ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 mem_mask) |
| r8806 | r8807 | |
| 202 | 532 | #define WRITE64_DEVICE_HANDLER(name) void name(ATTR_UNUSED device_t *device, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 data, ATTR_UNUSED UINT64 mem_mask) |
| 203 | 533 | |
| 204 | 534 | |
| 205 | /* helper macro for merging data with the memory mask */ | |
| 535 | // space read/write handler function macros | |
| 536 | #define READ8_MEMBER(name) UINT8 name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 mem_mask) | |
| 537 | #define WRITE8_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 data, ATTR_UNUSED UINT8 mem_mask) | |
| 538 | #define READ16_MEMBER(name) UINT16 name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 mem_mask) | |
| 539 | #define WRITE16_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 data, ATTR_UNUSED UINT16 mem_mask) | |
| 540 | #define READ32_MEMBER(name) UINT32 name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 mem_mask) | |
| 541 | #define WRITE32_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 data, ATTR_UNUSED UINT32 mem_mask) | |
| 542 | #define READ64_MEMBER(name) UINT64 name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 mem_mask) | |
| 543 | #define WRITE64_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 data, ATTR_UNUSED UINT64 mem_mask) | |
| 544 | ||
| 545 | #define DECLARE_READ8_MEMBER(name) UINT8 name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 mem_mask = 0xff) | |
| 546 | #define DECLARE_WRITE8_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT8 data, ATTR_UNUSED UINT8 mem_mask = 0xff) | |
| 547 | #define DECLARE_READ16_MEMBER(name) UINT16 name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 mem_mask = 0xffff) | |
| 548 | #define DECLARE_WRITE16_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT16 data, ATTR_UNUSED UINT16 mem_mask = 0xffff) | |
| 549 | #define DECLARE_READ32_MEMBER(name) UINT32 name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 mem_mask = 0xffffffff) | |
| 550 | #define DECLARE_WRITE32_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT32 data, ATTR_UNUSED UINT32 mem_mask = 0xffffffff) | |
| 551 | #define DECLARE_READ64_MEMBER(name) UINT64 name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 mem_mask = U64(0xffffffffffffffff)) | |
| 552 | #define DECLARE_WRITE64_MEMBER(name) void name(ATTR_UNUSED address_space &space, ATTR_UNUSED offs_t offset, ATTR_UNUSED UINT64 data, ATTR_UNUSED UINT64 mem_mask = U64(0xffffffffffffffff)) | |
| 553 | ||
| 554 | ||
| 555 | // helper macro for merging data with the memory mask | |
| 206 | 556 | #define COMBINE_DATA(varptr) (*(varptr) = (*(varptr) & ~mem_mask) | (data & mem_mask)) |
| 207 | 557 | |
| 208 | 558 | #define ACCESSING_BITS_0_7 ((mem_mask & 0x000000ff) != 0) |
| r8806 | r8807 | |
| 223 | 573 | #define ACCESSING_BITS_32_63 ((mem_mask & U64(0xffffffff00000000)) != 0) |
| 224 | 574 | |
| 225 | 575 | |
| 226 | /* opcode range safety check */ | |
| 227 | #define memory_address_outside_direct_region(S,A) ((UNEXPECTED((A) < (S)->direct.bytestart) || UNEXPECTED((A) > (S)->direct.byteend))) | |
| 576 | // macros for accessing bytes and words within larger chunks | |
| 228 | 577 | |
| 578 | // read/write a byte to a 16-bit space | |
| 579 | #define BYTE_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)) | |
| 580 | #define BYTE_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,1)) | |
| 229 | 581 | |
| 230 | /* wrappers for dynamic read handler installation */ | |
| 582 | // read/write a byte to a 32-bit space | |
| 583 | #define BYTE4_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(3,0)) | |
| 584 | #define BYTE4_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,3)) | |
| 585 | ||
| 586 | // read/write a word to a 32-bit space | |
| 587 | #define WORD_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(2,0)) | |
| 588 | #define WORD_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,2)) | |
| 589 | ||
| 590 | // read/write a byte to a 64-bit space | |
| 591 | #define BYTE8_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(7,0)) | |
| 592 | #define BYTE8_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,7)) | |
| 593 | ||
| 594 | // read/write a word to a 64-bit space | |
| 595 | #define WORD2_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(6,0)) | |
| 596 | #define WORD2_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,6)) | |
| 597 | ||
| 598 | // read/write a dword to a 64-bit space | |
| 599 | #define DWORD_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(4,0)) | |
| 600 | #define DWORD_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,4)) | |
| 601 | ||
| 602 | ||
| 603 | // wrappers for dynamic read handler installation | |
| 231 | 604 | #define memory_install_read8_handler(space, start, end, mask, mirror, rhandler) \ |
| 232 | | |
| 605 | c | |
| 233 | 606 | #define memory_install_read16_handler(space, start, end, mask, mirror, rhandler) \ |
| 234 | | |
| 607 | c | |
| 235 | 608 | #define memory_install_read32_handler(space, start, end, mask, mirror, rhandler) \ |
| 236 | | |
| 609 | c | |
| 237 | 610 | #define memory_install_read64_handler(space, start, end, mask, mirror, rhandler) \ |
| 238 | | |
| 611 | c | |
| 239 | 612 | |
| 240 | 613 | #define memory_install_read8_device_handler(space, device, start, end, mask, mirror, rhandler) \ |
| 241 | | |
| 614 | c | |
| 242 | 615 | #define memory_install_read16_device_handler(space, device, start, end, mask, mirror, rhandler) \ |
| 243 | | |
| 616 | c | |
| 244 | 617 | #define memory_install_read32_device_handler(space, device, start, end, mask, mirror, rhandler) \ |
| 245 | | |
| 618 | c | |
| 246 | 619 | #define memory_install_read64_device_handler(space, device, start, end, mask, mirror, rhandler) \ |
| 247 | | |
| 620 | c | |
| 248 | 621 | |
| 249 | 622 | #define memory_install_read_port(space, start, end, mask, mirror, rtag) \ |
| 250 | | |
| 623 | c | |
| 251 | 624 | #define memory_install_read_bank(space, start, end, mask, mirror, rtag) \ |
| 252 | | |
| 625 | c | |
| 253 | 626 | #define memory_install_rom(space, start, end, mask, mirror, baseptr) \ |
| 254 | | |
| 627 | c | |
| 255 | 628 | #define memory_unmap_read(space, start, end, mask, mirror) \ |
| 256 | | |
| 629 | c | |
| 257 | 630 | #define memory_nop_read(space, start, end, mask, mirror) \ |
| 258 | | |
| 631 | c | |
| 259 | 632 | |
| 260 | / | |
| 633 | // wrappers for dynamic write handler installation | |
| 261 | 634 | #define memory_install_write8_handler(space, start, end, mask, mirror, whandler) \ |
| 262 | | |
| 635 | c | |
| 263 | 636 | #define memory_install_write16_handler(space, start, end, mask, mirror, whandler) \ |
| 264 | | |
| 637 | c | |
| 265 | 638 | #define memory_install_write32_handler(space, start, end, mask, mirror, whandler) \ |
| 266 | | |
| 639 | c | |
| 267 | 640 | #define memory_install_write64_handler(space, start, end, mask, mirror, whandler) \ |
| 268 | | |
| 641 | c | |
| 269 | 642 | |
| 270 | 643 | #define memory_install_write8_device_handler(space, device, start, end, mask, mirror, whandler) \ |
| 271 | | |
| 644 | c | |
| 272 | 645 | #define memory_install_write16_device_handler(space, device, start, end, mask, mirror, whandler) \ |
| 273 | | |
| 646 | c | |
| 274 | 647 | #define memory_install_write32_device_handler(space, device, start, end, mask, mirror, whandler) \ |
| 275 | | |
| 648 | c | |
| 276 | 649 | #define memory_install_write64_device_handler(space, device, start, end, mask, mirror, whandler) \ |
| 277 | | |
| 650 | c | |
| 278 | 651 | |
| 279 | 652 | #define memory_install_write_port(space, start, end, mask, mirror, wtag) \ |
| 280 | | |
| 653 | c | |
| 281 | 654 | #define memory_install_write_bank(space, start, end, mask, mirror, wtag) \ |
| 282 | | |
| 655 | c | |
| 283 | 656 | #define memory_install_writeonly(space, start, end, mask, mirror, baseptr) \ |
| 284 | | |
| 657 | c | |
| 285 | 658 | #define memory_unmap_write(space, start, end, mask, mirror) \ |
| 286 | | |
| 659 | c | |
| 287 | 660 | #define memory_nop_write(space, start, end, mask, mirror) \ |
| 288 | | |
| 661 | c | |
| 289 | 662 | |
| 290 | / | |
| 663 | // wrappers for dynamic read/write handler installation | |
| 291 | 664 | #define memory_install_readwrite8_handler(space, start, end, mask, mirror, rhandler, whandler) \ |
| 292 | | |
| 665 | c | |
| 293 | 666 | #define memory_install_readwrite16_handler(space, start, end, mask, mirror, rhandler, whandler) \ |
| 294 | | |
| 667 | c | |
| 295 | 668 | #define memory_install_readwrite32_handler(space, start, end, mask, mirror, rhandler, whandler) \ |
| 296 | | |
| 669 | c | |
| 297 | 670 | #define memory_install_readwrite64_handler(space, start, end, mask, mirror, rhandler, whandler) \ |
| 298 | | |
| 671 | c | |
| 299 | 672 | |
| 300 | 673 | #define memory_install_readwrite8_device_handler(space, device, start, end, mask, mirror, rhandler, whandler) \ |
| 301 | | |
| 674 | c | |
| 302 | 675 | #define memory_install_readwrite16_device_handler(space, device, start, end, mask, mirror, rhandler, whandler) \ |
| 303 | | |
| 676 | c | |
| 304 | 677 | #define memory_install_readwrite32_device_handler(space, device, start, end, mask, mirror, rhandler, whandler) \ |
| 305 | | |
| 678 | c | |
| 306 | 679 | #define memory_install_readwrite64_device_handler(space, device, start, end, mask, mirror, rhandler, whandler) \ |
| 307 | | |
| 680 | c | |
| 308 | 681 | |
| 309 | 682 | #define memory_install_readwrite_port(space, start, end, mask, mirror, rtag, wtag) \ |
| 310 | | |
| 683 | c | |
| 311 | 684 | #define memory_install_readwrite_bank(space, start, end, mask, mirror, tag) \ |
| 312 | | |
| 685 | c | |
| 313 | 686 | #define memory_install_ram(space, start, end, mask, mirror, baseptr) \ |
| 314 | | |
| 687 | c | |
| 315 | 688 | #define memory_unmap_readwrite(space, start, end, mask, mirror) \ |
| 316 | | |
| 689 | c | |
| 317 | 690 | #define memory_nop_readwrite(space, start, end, mask, mirror) \ |
| 318 | | |
| 691 | c | |
| 319 | 692 | |
| 320 | 693 | |
| 321 | /* macros for accessing bytes and words within larger chunks */ | |
| 322 | 694 | |
| 323 | /* read/write a byte to a 16-bit space */ | |
| 324 | #define BYTE_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)) | |
| 325 | #define BYTE_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,1)) | |
| 695 | //************************************************************************** | |
| 696 | // GLOBAL VARIABLES | |
| 697 | //************************************************************************** | |
| 326 | 698 | |
| 327 | /* read/write a byte to a 32-bit space */ | |
| 328 | #define BYTE4_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(3,0)) | |
| 329 | #define BYTE4_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,3)) | |
| 330 | ||
| 331 | /* read/write a word to a 32-bit space */ | |
| 332 | #define WORD_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(2,0)) | |
| 333 | #define WORD_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,2)) | |
| 334 | ||
| 335 | /* read/write a byte to a 64-bit space */ | |
| 336 | #define BYTE8_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(7,0)) | |
| 337 | #define BYTE8_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,7)) | |
| 338 | ||
| 339 | /* read/write a word to a 64-bit space */ | |
| 340 | #define WORD2_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(6,0)) | |
| 341 | #define WORD2_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,6)) | |
| 342 | ||
| 343 | /* read/write a dword to a 64-bit space */ | |
| 344 | #define DWORD_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(4,0)) | |
| 345 | #define DWORD_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,4)) | |
| 346 | ||
| 347 | ||
| 348 | ||
| 349 | /*************************************************************************** | |
| 350 | GLOBAL VARIABLES | |
| 351 | ***************************************************************************/ | |
| 352 | ||
| 353 | 699 | extern const char *const address_space_names[ADDRESS_SPACES]; |
| 354 | 700 | |
| 355 | 701 | |
| 356 | 702 | |
| 357 | /*************************************************************************** | |
| 358 | FUNCTION PROTOTYPES FOR CORE MEMORY FUNCTIONS | |
| 359 | ***************************************************************************/ | |
| 703 | //************************************************************************** | |
| 704 | // FUNCTION PROTOTYPES FOR CORE MEMORY FUNCTIONS | |
| 705 | //************************************************************************** | |
| 360 | 706 | |
| 361 | ||
| 362 | /* ----- core system operations ----- */ | |
| 363 | ||
| 364 | /* initialize the memory system */ | |
| 707 | // initialize the memory system | |
| 365 | 708 | void memory_init(running_machine *machine); |
| 366 | 709 | |
| 367 | ||
| 368 | ||
| 369 | /* ----- direct access control ----- */ | |
| 370 | ||
| 371 | /* registers an address range as having a decrypted data pointer */ | |
| 372 | void memory_set_decrypted_region(const address_space *space, offs_t addrstart, offs_t addrend, void *base) ATTR_NONNULL(1, 4); | |
| 373 | ||
| 374 | /* register a handler for opcode base changes on a given device */ | |
| 375 | direct_update_func memory_set_direct_update_handler(const address_space *space, direct_update_func function) ATTR_NONNULL(1); | |
| 376 | ||
| 377 | /* called by device cores to update the opcode base for the given address */ | |
| 378 | int memory_set_direct_region(const address_space *space, offs_t *byteaddress) ATTR_NONNULL(1, 2); | |
| 379 | ||
| 380 | /* return a pointer the memory byte provided in the given address space, or NULL if it is not mapped to a bank */ | |
| 381 | void *memory_get_read_ptr(const address_space *space, offs_t byteaddress) ATTR_NONNULL(1); | |
| 382 | ||
| 383 | /* return a pointer the memory byte provided in the given address space, or NULL if it is not mapped to a writeable bank */ | |
| 384 | void *memory_get_write_ptr(const address_space *space, offs_t byteaddress) ATTR_NONNULL(1); | |
| 385 | ||
| 386 | ||
| 387 | ||
| 388 | /* ----- memory banking ----- */ | |
| 389 | ||
| 390 | /* configure the addresses for a bank */ | |
| 710 | // configure the addresses for a bank | |
| 391 | 711 | void memory_configure_bank(running_machine *machine, const char *tag, int startentry, int numentries, void *base, offs_t stride) ATTR_NONNULL(1, 5); |
| 392 | 712 | |
| 393 | / | |
| 713 | // configure the decrypted addresses for a bank | |
| 394 | 714 | void memory_configure_bank_decrypted(running_machine *machine, const char *tag, int startentry, int numentries, void *base, offs_t stride) ATTR_NONNULL(1, 5); |
| 395 | 715 | |
| 396 | / | |
| 716 | // select one pre-configured entry to be the new bank base | |
| 397 | 717 | void memory_set_bank(running_machine *machine, const char *tag, int entrynum) ATTR_NONNULL(1); |
| 398 | 718 | |
| 399 | / | |
| 719 | // return the currently selected bank | |
| 400 | 720 | int memory_get_bank(running_machine *machine, const char *tag) ATTR_NONNULL(1); |
| 401 | 721 | |
| 402 | / | |
| 722 | // set the absolute address of a bank base | |
| 403 | 723 | void memory_set_bankptr(running_machine *machine, const char *tag, void *base) ATTR_NONNULL(1, 3); |
| 404 | 724 | |
| 405 | ||
| 406 | ||
| 407 | /* ----- dynamic address space mapping ----- */ | |
| 408 | ||
| 409 | /* install a new 8-bit memory handler into the given address space, returning a pointer to the memory backing it, if present */ | |
| 410 | UINT8 *_memory_install_handler8(const address_space *space, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_space_func rhandler, const char *rhandler_name, write8_space_func whandler, const char *whandler_name, int handlerunitmask) ATTR_NONNULL(1); | |
| 411 | ||
| 412 | /* same as above but explicitly for 16-bit handlers */ | |
| 413 | UINT16 *_memory_install_handler16(const address_space *space, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_space_func rhandler, const char *rhandler_name, write16_space_func whandler, const char *whandler_name, int handlerunitmask) ATTR_NONNULL(1); | |
| 414 | ||
| 415 | /* same as above but explicitly for 32-bit handlers */ | |
| 416 | UINT32 *_memory_install_handler32(const address_space *space, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_space_func rhandler, const char *rhandler_name, write32_space_func whandler, const char *whandler_name, int handlerunitmask) ATTR_NONNULL(1); | |
| 417 | ||
| 418 | /* same as above but explicitly for 64-bit handlers */ | |
| 419 | UINT64 *_memory_install_handler64(const address_space *space, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_space_func rhandler, const char *rhandler_name, write64_space_func whandler, const char *whandler_name, int handlerunitmask) ATTR_NONNULL(1); | |
| 420 | ||
| 421 | /* install a new 8-bit device memory handler into the given address space, returning a pointer to the memory backing it, if present */ | |
| 422 | UINT8 *_memory_install_device_handler8(const address_space *space, device_t *device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read8_device_func rhandler, const char *rhandler_name, write8_device_func whandler, const char *whandler_name, int handlerunitmask) ATTR_NONNULL(1, 2); | |
| 423 | ||
| 424 | /* same as above but explicitly for 16-bit handlers */ | |
| 425 | UINT16 *_memory_install_device_handler16(const address_space *space, device_t *device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read16_device_func rhandler, const char *rhandler_name, write16_device_func whandler, const char *whandler_name, int handlerunitmask) ATTR_NONNULL(1, 2); | |
| 426 | ||
| 427 | /* same as above but explicitly for 32-bit handlers */ | |
| 428 | UINT32 *_memory_install_device_handler32(const address_space *space, device_t *device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read32_device_func rhandler, const char *rhandler_name, write32_device_func whandler, const char *whandler_name, int handlerunitmask) ATTR_NONNULL(1, 2); | |
| 429 | ||
| 430 | /* same as above but explicitly for 64-bit handlers */ | |
| 431 | UINT64 *_memory_install_device_handler64(const address_space *space, device_t *device, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, read64_device_func rhandler, const char *rhandler_name, write64_device_func whandler, const char *whandler_name, int handlerunitmask) ATTR_NONNULL(1, 2); | |
| 432 | ||
| 433 | /* install a new port into the given address space */ | |
| 434 | void _memory_install_port(const address_space *space, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, const char *rtag, const char *wtag) ATTR_NONNULL(1); | |
| 435 | ||
| 436 | /* install a new bank into the given address space */ | |
| 437 | void _memory_install_bank(const address_space *space, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, const char *rtag, const char *wtag) ATTR_NONNULL(1); | |
| 438 | ||
| 439 | /* install a simple fixed RAM region into the given address space */ | |
| 440 | void *_memory_install_ram(const address_space *space, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, UINT8 install_read, UINT8 install_write, void *baseptr) ATTR_NONNULL(1); | |
| 441 | ||
| 442 | /* unmap a section of address space */ | |
| 443 | void _memory_unmap(const address_space *space, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, UINT8 unmap_read, UINT8 unmap_write, UINT8 quiet) ATTR_NONNULL(1); | |
| 444 | ||
| 445 | ||
| 446 | ||
| 447 | /* ----- debugger helpers ----- */ | |
| 448 | ||
| 449 | /* return a string describing the handler at a particular offset */ | |
| 450 | const char *memory_get_handler_string(const address_space *space, int read0_or_write1, offs_t byteaddress); | |
| 451 | ||
| 452 | /* enable/disable read watchpoint tracking for a given address space */ | |
| 453 | void memory_enable_read_watchpoints(const address_space *space, int enable); | |
| 454 | ||
| 455 | /* enable/disable write watchpoint tracking for a given address space */ | |
| 456 | void memory_enable_write_watchpoints(const address_space *space, int enable); | |
| 457 | ||
| 458 | /* control whether subsequent accesses are treated as coming from the debugger */ | |
| 459 | void memory_set_debugger_access(const address_space *space, int debugger); | |
| 460 | ||
| 461 | /* sets whether unmapped memory accesses should be logged or not */ | |
| 462 | void memory_set_log_unmap(const address_space *space, int log); | |
| 463 | ||
| 464 | /* gets whether unmapped memory accesses are being logged or not */ | |
| 465 | int memory_get_log_unmap(const address_space *space); | |
| 466 | ||
| 467 | /* dump the internal memory tables to the given file */ | |
| 725 | // dump the internal memory tables to the given file | |
| 468 | 726 | void memory_dump(running_machine *machine, FILE *file); |
| 469 | 727 | |
| 470 | 728 | |
| 471 | 729 | |
| 472 | /*************************************************************************** | |
| 473 | INLINE FUNCTIONS | |
| 474 | ***************************************************************************/ | |
| 730 | //************************************************************************** | |
| 731 | // INLINE FUNCTIONS | |
| 732 | //************************************************************************** | |
| 475 | 733 | |
| 476 | /*------------------------------------------------- | |
| 477 | memory_address_to_byte - convert an address in | |
| 478 | the specified address space to a byte offset | |
| 479 | -------------------------------------------------*/ | |
| 734 | //------------------------------------------------- | |
| 735 | // read_raw_ptr - return a pointer to valid RAM | |
| 736 | // referenced by the address, or NULL if no RAM | |
| 737 | // backing that address | |
| 738 | //------------------------------------------------- | |
| 480 | 739 | |
| 481 | ||
| 740 | inline void | |
| 482 | 741 | { |
| 483 | return (space->ashift < 0) ? (address << -space->ashift) : (address >> space->ashift); | |
| 742 | if (address_is_valid(byteaddress)) | |
| 743 | return &m_raw[byteaddress & m_bytemask]; | |
| 744 | return NULL; | |
| 484 | 745 | } |
| 485 | 746 | |
| 486 | ||
| 487 | /*------------------------------------------------- | |
| 488 | memory_address_to_byte_end - convert an address | |
| 489 | in the specified address space to a byte | |
| 490 | offset specifying the last byte covered by | |
| 491 | the address | |
| 492 | -------------------------------------------------*/ | |
| 493 | ||
| 494 | INLINE offs_t memory_address_to_byte_end(const address_space *space, offs_t address) | |
| 747 | inline void *direct_read_data::read_decrypted_ptr(offs_t byteaddress) | |
| 495 | 748 | { |
| 496 | return (space->ashift < 0) ? ((address << -space->ashift) | ((1 << -space->ashift) - 1)) : (address >> space->ashift); | |
| 749 | if (address_is_valid(byteaddress)) | |
| 750 | return &m_decrypted[byteaddress & m_bytemask]; | |
| 751 | return NULL; | |
| 497 | 752 | } |
| 498 | 753 | |
| 499 | 754 | |
| 500 | /*------------------------------------------------- | |
| 501 | memory_byte_to_address - convert a byte offset | |
| 502 | to an address in the specified address space | |
| 503 | -------------------------------------------------*/ | |
| 755 | //------------------------------------------------- | |
| 756 | // read_raw_byte - read a byte via the | |
| 757 | // direct_read_data class | |
| 758 | //------------------------------------------------- | |
| 504 | 759 | |
| 505 | IN | |
| 760 | inline UINT8 | |
| 506 | 761 | { |
| 507 | return (space->ashift < 0) ? (address >> -space->ashift) : (address << space->ashift); | |
| 762 | if (address_is_valid(byteaddress)) | |
| 763 | return m_raw[byteaddress & m_bytemask]; | |
| 764 | return m_space.read_byte(byteaddress); | |
| 508 | 765 | } |
| 509 | ||
| 510 | ||
| 511 | /*------------------------------------------------- | |
| 512 | memory_byte_to_address_end - convert a byte | |
| 513 | offset to an address in the specified address | |
| 514 | space specifying the last address covered by | |
| 515 | the byte | |
| 516 | -------------------------------------------------*/ | |
| 517 | ||
| 518 | INLINE offs_t memory_byte_to_address_end(const address_space *space, offs_t address) | |
| 766 | ||
| 767 | inline UINT8 direct_read_data::read_decrypted_byte(offs_t byteaddress) | |
| 519 | 768 | { |
| 520 | return (space->ashift < 0) ? (address >> -space->ashift) : ((address << space->ashift) | ((1 << space->ashift) - 1)); | |
| 769 | if (address_is_valid(byteaddress)) | |
| 770 | return m_decrypted[byteaddress & m_bytemask]; | |
| 771 | return m_space.read_byte(byteaddress); | |
| 521 | 772 | } |
| 773 | ||
| 522 | 774 | |
| 775 | //------------------------------------------------- | |
| 776 | // read_raw_word - read a word via the | |
| 777 | // direct_read_data class | |
| 778 | //------------------------------------------------- | |
| 523 | 779 | |
| 524 | /*------------------------------------------------- | |
| 525 | memory_read_byte/word/dword/qword - read a | |
| 526 | value from the specified address space | |
| 527 | -------------------------------------------------*/ | |
| 528 | ||
| 529 | INLINE UINT8 memory_read_byte(const address_space *space, offs_t byteaddress) | |
| 780 | inline UINT16 direct_read_data::read_raw_word(offs_t byteaddress) | |
| 530 | 781 | { |
| 531 | return (*space->accessors.read_byte)(space, byteaddress); | |
| 782 | if (address_is_valid(byteaddress)) | |
| 783 | return *reinterpret_cast<UINT16 *>(&m_raw[byteaddress & m_bytemask]); | |
| 784 | return m_space.read_word(byteaddress); | |
| 532 | 785 | } |
| 533 | ||
| 534 | INLINE UINT16 memory_read_word(const address_space *space, offs_t byteaddress) | |
| 786 | ||
| 787 | inline UINT16 direct_read_data::read_decrypted_word(offs_t byteaddress) | |
| 535 | 788 | { |
| 536 | return (*space->accessors.read_word)(space, byteaddress); | |
| 789 | if (address_is_valid(byteaddress)) | |
| 790 | return *reinterpret_cast<UINT16 *>(&m_decrypted[byteaddress & m_bytemask]); | |
| 791 | return m_space.read_word(byteaddress); | |
| 537 | 792 | } |
| 793 | ||
| 538 | 794 | |
| 539 | INLINE UINT16 memory_read_word_masked(const address_space *space, offs_t byteaddress, UINT16 mask) | |
| 540 | { | |
| 541 | return (*space->accessors.read_word_masked)(space, byteaddress, mask); | |
| 542 | } | |
| 795 | //------------------------------------------------- | |
| 796 | // read_raw_dword - read a dword via the | |
| 797 | // direct_read_data class | |
| 798 | //------------------------------------------------- | |
| 543 | 799 | |
| 544 | ||
| 800 | inline UINT32 di | |
| 545 | 801 | { |
| 546 | return (*space->accessors.read_dword)(space, byteaddress); | |
| 802 | if (address_is_valid(byteaddress)) | |
| 803 | return *reinterpret_cast<UINT32 *>(&m_raw[byteaddress & m_bytemask]); | |
| 804 | return m_space.read_dword(byteaddress); | |
| 547 | 805 | } |
| 548 | ||
| 549 | INLINE UINT32 memory_read_dword_masked(const address_space *space, offs_t byteaddress, UINT32 mask) | |
| 806 | ||
| 807 | inline UINT32 direct_read_data::read_decrypted_dword(offs_t byteaddress) | |
| 550 | 808 | { |
| 551 | return (*space->accessors.read_dword_masked)(space, byteaddress, mask); | |
| 809 | if (address_is_valid(byteaddress)) | |
| 810 | return *reinterpret_cast<UINT32 *>(&m_decrypted[byteaddress & m_bytemask]); | |
| 811 | return m_space.read_dword(byteaddress); | |
| 552 | 812 | } |
| 813 | ||
| 553 | 814 | |
| 554 | INLINE UINT64 memory_read_qword(const address_space *space, offs_t byteaddress) | |
| 555 | { | |
| 556 | return (*space->accessors.read_qword)(space, byteaddress); | |
| 557 | } | |
| 815 | //------------------------------------------------- | |
| 816 | // read_raw_qword - read a qword via the | |
| 817 | // direct_read_data class | |
| 818 | //------------------------------------------------- | |
| 558 | 819 | |
| 559 | ||
| 820 | inline UINT64 di | |
| 560 | 821 | { |
| 561 | return (*space->accessors.read_qword_masked)(space, byteaddress, mask); | |
| 822 | if (address_is_valid(byteaddress)) | |
| 823 | return *reinterpret_cast<UINT64 *>(&m_raw[byteaddress & m_bytemask]); | |
| 824 | return m_space.read_qword(byteaddress); | |
| 562 | 825 | } |
| 563 | ||
| 564 | ||
| 565 | /*------------------------------------------------- | |
| 566 | memory_write_byte/word/dword/qword - write a | |
| 567 | value to the specified address space | |
| 568 | -------------------------------------------------*/ | |
| 569 | ||
| 570 | INLINE void memory_write_byte(const address_space *space, offs_t byteaddress, UINT8 data) | |
| 826 | ||
| 827 | inline UINT64 direct_read_data::read_decrypted_qword(offs_t byteaddress) | |
| 571 | 828 | { |
| 572 | (*space->accessors.write_byte)(space, byteaddress, data); | |
| 829 | if (address_is_valid(byteaddress)) | |
| 830 | return *reinterpret_cast<UINT64 *>(&m_decrypted[byteaddress & m_bytemask]); | |
| 831 | return m_space.read_qword(byteaddress); | |
| 573 | 832 | } |
| 833 | ||
| 574 | 834 | |
| 575 | INLINE void memory_write_word(const address_space *space, offs_t byteaddress, UINT16 data) | |
| 576 | { | |
| 577 | (*space->accessors.write_word)(space, byteaddress, data); | |
| 578 | } | |
| 579 | 835 | |
| 580 | INLINE void memory_write_word_masked(const address_space *space, offs_t byteaddress, UINT16 data, UINT16 mask) | |
| 581 | { | |
| 582 | (*space->accessors.write_word_masked)(space, byteaddress, data, mask); | |
| 583 | } | |
| 584 | 836 | |
| 585 | INLINE void memory_write_dword(const address_space *space, offs_t byteaddress, UINT32 data) | |
| 586 | { | |
| 587 | (*space->accessors.write_dword)(space, byteaddress, data); | |
| 588 | } | |
| 837 | //************************************************************************** | |
| 838 | // LEGACY FUNCTIONS TO REMOVE | |
| 839 | //************************************************************************** | |
| 589 | 840 | |
| 590 | INLINE void memory_write_dword_masked(const address_space *space, offs_t byteaddress, UINT32 data, UINT32 mask) | |
| 591 | { | |
| 592 | (*space->accessors.write_dword_masked)(space, byteaddress, data, mask); | |
| 593 | } | |
| 841 | static inline void *memory_raw_read_ptr(address_space *space, offs_t byteaddress) { return space->direct().read_raw_ptr(byteaddress); } | |
| 842 | static inline UINT8 memory_raw_read_byte(address_space *space, offs_t byteaddress) { return space->direct().read_raw_byte(byteaddress); } | |
| 843 | static inline UINT16 memory_raw_read_word(address_space *space, offs_t byteaddress) { return space->direct().read_raw_word(byteaddress); } | |
| 844 | static inline UINT32 memory_raw_read_dword(address_space *space, offs_t byteaddress) { return space->direct().read_raw_dword(byteaddress); } | |
| 845 | static inline UINT64 memory_raw_read_qword(address_space *space, offs_t byteaddress) { return space->direct().read_raw_qword(byteaddress); } | |
| 594 | 846 | |
| 595 | INLINE void memory_write_qword(const address_space *space, offs_t byteaddress, UINT64 data) | |
| 596 | { | |
| 597 | (*space->accessors.write_qword)(space, byteaddress, data); | |
| 598 | } | |
| 847 | static inline void *memory_decrypted_read_ptr(address_space *space, offs_t byteaddress) { return space->direct().read_decrypted_ptr(byteaddress); } | |
| 848 | static inline UINT8 memory_decrypted_read_byte(address_space *space, offs_t byteaddress) { return space->direct().read_decrypted_byte(byteaddress); } | |
| 849 | static inline UINT16 memory_decrypted_read_word(address_space *space, offs_t byteaddress) { return space->direct().read_decrypted_word(byteaddress); } | |
| 850 | static inline UINT32 memory_decrypted_read_dword(address_space *space, offs_t byteaddress) { return space->direct().read_decrypted_dword(byteaddress); } | |
| 851 | static inline UINT64 memory_decrypted_read_qword(address_space *space, offs_t byteaddress) { return space->direct().read_decrypted_qword(byteaddress); } | |
| 599 | 852 | |
| 600 | INLINE void memory_write_qword_masked(const address_space *space, offs_t byteaddress, UINT64 data, UINT64 mask) | |
| 601 | { | |
| 602 | (*space->accessors.write_qword_masked)(space, byteaddress, data, mask); | |
| 603 | } | |
| 604 | 853 | |
| 605 | 854 | |
| 606 | /*------------------------------------------------- | |
| 607 | memory_decrypted_read_byte/word/dword/qword - | |
| 608 | read a value from the specified address space | |
| 609 | using the direct addressing mechanism and | |
| 610 | the decrypted base pointer | |
| 611 | -------------------------------------------------*/ | |
| 612 | 855 | |
| 613 | ||
| 856 | static inline void | |
| 614 | 857 | { |
| 615 | if (!memory_address_outside_direct_region(space, byteaddress) || memory_set_direct_region(space, &byteaddress)) | |
| 616 | return &space->direct.decrypted[byteaddress & space->direct.bytemask]; | |
| 617 | return NULL; | |
| 858 | const_cast<address_space *>(space)->set_decrypted_region(addrstart, addrend, base); | |
| 618 | 859 | } |
| 619 | 860 | |
| 620 | ||
| 861 | static inline void *memory_ge | |
| 621 | 862 | { |
| 622 | if (!memory_address_outside_direct_region(space, byteaddress) || memory_set_direct_region(space, &byteaddress)) | |
| 623 | return space->direct.decrypted[byteaddress & space->direct.bytemask]; | |
| 624 | return memory_read_byte(space, byteaddress); | |
| 863 | return const_cast<address_space *>(space)->get_read_ptr(byteaddress); | |
| 625 | 864 | } |
| 626 | 865 | |
| 627 | ||
| 866 | static inline void *memory_ge | |
| 628 | 867 | { |
| 629 | if (!memory_address_outside_direct_region(space, byteaddress) || memory_set_direct_region(space, &byteaddress)) | |
| 630 | return *(UINT16 *)&space->direct.decrypted[byteaddress & space->direct.bytemask]; | |
| 631 | return memory_read_word(space, byteaddress); | |
| 868 | return const_cast<address_space *>(space)->get_write_ptr(byteaddress); | |
| 632 | 869 | } |
| 633 | 870 | |
| 634 | ||
| 871 | static inline const char *memory_ge | |
| 635 | 872 | { |
| 636 | if (!memory_address_outside_direct_region(space, byteaddress) || memory_set_direct_region(space, &byteaddress)) | |
| 637 | return *(UINT32 *)&space->direct.decrypted[byteaddress & space->direct.bytemask]; | |
| 638 | return memory_read_dword(space, byteaddress); | |
| 873 | return const_cast<address_space *>(space)->get_handler_string(readorwrite, byteaddress); | |
| 639 | 874 | } |
| 640 | 875 | |
| 641 | ||
| 876 | static inline void memory_ | |
| 642 | 877 | { |
| 643 | if (!memory_address_outside_direct_region(space, byteaddress) || memory_set_direct_region(space, &byteaddress)) | |
| 644 | return *(UINT64 *)&space->direct.decrypted[byteaddress & space->direct.bytemask]; | |
| 645 | return memory_read_qword(space, byteaddress); | |
| 878 | const_cast<address_space *>(space)->enable_read_watchpoints(enable); | |
| 646 | 879 | } |
| 647 | 880 | |
| 648 | ||
| 649 | /*------------------------------------------------- | |
| 650 | memory_raw_read_byte/word/dword/qword - | |
| 651 | read a value from the specified address space | |
| 652 | using the direct addressing mechanism and | |
| 653 | the raw base pointer | |
| 654 | -------------------------------------------------*/ | |
| 655 | ||
| 656 | INLINE void *memory_raw_read_ptr(const address_space *space, offs_t byteaddress) | |
| 881 | static inline void memory_enable_write_watchpoints(address_space *space, bool enable) | |
| 657 | 882 | { |
| 658 | if (!memory_address_outside_direct_region(space, byteaddress) || memory_set_direct_region(space, &byteaddress)) | |
| 659 | return &space->direct.raw[byteaddress & space->direct.bytemask]; | |
| 660 | return NULL; | |
| 883 | const_cast<address_space *>(space)->enable_write_watchpoints(enable); | |
| 661 | 884 | } |
| 662 | 885 | |
| 663 | ||
| 886 | static inline void memory_s | |
| 664 | 887 | { |
| 665 | if (!memory_address_outside_direct_region(space, byteaddress) || memory_set_direct_region(space, &byteaddress)) | |
| 666 | return space->direct.raw[byteaddress & space->direct.bytemask]; | |
| 667 | return memory_read_byte(space, byteaddress); | |
| 888 | const_cast<address_space *>(space)->set_debugger_access(debugger); | |
| 668 | 889 | } |
| 669 | 890 | |
| 670 | ||
| 891 | static inline void memory_s | |
| 671 | 892 | { |
| 672 | if (!memory_address_outside_direct_region(space, byteaddress) || memory_set_direct_region(space, &byteaddress)) | |
| 673 | return *(UINT16 *)&space->direct.raw[byteaddress & space->direct.bytemask]; | |
| 674 | return memory_read_word(space, byteaddress); | |
| 893 | const_cast<address_space *>(space)->set_log_unmap(log); | |
| 675 | 894 | } |
| 676 | 895 | |
| 677 | ||
| 896 | static inline bool memory_g | |
| 678 | 897 | { |
| 679 | if (!memory_address_outside_direct_region(space, byteaddress) || memory_set_direct_region(space, &byteaddress)) | |
| 680 | return *(UINT32 *)&space->direct.raw[byteaddress & space->direct.bytemask]; | |
| 681 | return memory_read_dword(space, byteaddress); | |
| 898 | return space->log_unmap(); | |
| 682 | 899 | } |
| 683 | 900 | |
| 684 | INLINE UINT64 memory_raw_read_qword(const address_space *space, offs_t byteaddress) | |
| 685 | { | |
| 686 | if (!memory_address_outside_direct_region(space, byteaddress) || memory_set_direct_region(space, &byteaddress)) | |
| 687 | return *(UINT64 *)&space->direct.raw[byteaddress & space->direct.bytemask]; | |
| 688 | return memory_read_qword(space, byteaddress); | |
| 689 | } | |
| 690 | 901 | |
| 691 | ||
| 692 | ||
| 693 | /*************************************************************************** | |
| 694 | FUNCTION PROTOTYPES FOR CORE READ/WRITE ROUTINES | |
| 695 | ***************************************************************************/ | |
| 696 | ||
| 697 | /* declare generic address space handlers */ | |
| 698 | UINT8 memory_read_byte_8le(const address_space *space, offs_t address); | |
| 699 | UINT16 memory_read_word_8le(const address_space *space, offs_t address); | |
| 700 | UINT16 memory_read_word_masked_8le(const address_space *space, offs_t address, UINT16 mask); | |
| 701 | UINT32 memory_read_dword_8le(const address_space *space, offs_t address); | |
| 702 | UINT32 memory_read_dword_masked_8le(const address_space *space, offs_t address, UINT32 mask); | |
| 703 | UINT64 memory_read_qword_8le(const address_space *space, offs_t address); | |
| 704 | UINT64 memory_read_qword_masked_8le(const address_space *space, offs_t address, UINT64 mask); | |
| 705 | void memory_write_byte_8le(const address_space *space, offs_t address, UINT8 data); | |
| 706 | void memory_write_word_8le(const address_space *space, offs_t address, UINT16 data); | |
| 707 | void memory_write_word_masked_8le(const address_space *space, offs_t address, UINT16 data, UINT16 mask); | |
| 708 | void memory_write_dword_8le(const address_space *space, offs_t address, UINT32 data); | |
| 709 | void memory_write_dword_masked_8le(const address_space *space, offs_t address, UINT32 data, UINT32 mask); | |
| 710 | void memory_write_qword_8le(const address_space *space, offs_t address, UINT64 data); | |
| 711 | void memory_write_qword_masked_8le(const address_space *space, offs_t address, UINT64 data, UINT64 mask); | |
| 712 | ||
| 713 | UINT8 memory_read_byte_8be(const address_space *space, offs_t address); | |
| 714 | UINT16 memory_read_word_8be(const address_space *space, offs_t address); | |
| 715 | UINT16 memory_read_word_masked_8be(const address_space *space, offs_t address, UINT16 mask); | |
| 716 | UINT32 memory_read_dword_8be(const address_space *space, offs_t address); | |
| 717 | UINT32 memory_read_dword_masked_8be(const address_space *space, offs_t address, UINT32 mask); | |
| 718 | UINT64 memory_read_qword_8be(const address_space *space, offs_t address); | |
| 719 | UINT64 memory_read_qword_masked_8be(const address_space *space, offs_t address, UINT64 mask); | |
| 720 | void memory_write_byte_8be(const address_space *space, offs_t address, UINT8 data); | |
| 721 | void memory_write_word_8be(const address_space *space, offs_t address, UINT16 data); | |
| 722 | void memory_write_word_masked_8be(const address_space *space, offs_t address, UINT16 data, UINT16 mask); | |
| 723 | void memory_write_dword_8be(const address_space *space, offs_t address, UINT32 data); | |
| 724 | void memory_write_dword_masked_8be(const address_space *space, offs_t address, UINT32 data, UINT32 mask); | |
| 725 | void memory_write_qword_8be(const address_space *space, offs_t address, UINT64 data); | |
| 726 | void memory_write_qword_masked_8be(const address_space *space, offs_t address, UINT64 data, UINT64 mask); | |
| 727 | ||
| 728 | UINT8 memory_read_byte_16le(const address_space *space, offs_t address); | |
| 729 | UINT16 memory_read_word_16le(const address_space *space, offs_t address); | |
| 730 | UINT16 memory_read_word_masked_16le(const address_space *space, offs_t address, UINT16 mask); | |
| 731 | UINT32 memory_read_dword_16le(const address_space *space, offs_t address); | |
| 732 | UINT32 memory_read_dword_masked_16le(const address_space *space, offs_t address, UINT32 mask); | |
| 733 | UINT64 memory_read_qword_16le(const address_space *space, offs_t address); | |
| 734 | UINT64 memory_read_qword_masked_16le(const address_space *space, offs_t address, UINT64 mask); | |
| 735 | void memory_write_byte_16le(const address_space *space, offs_t address, UINT8 data); | |
| 736 | void memory_write_word_16le(const address_space *space, offs_t address, UINT16 data); | |
| 737 | void memory_write_word_masked_16le(const address_space *space, offs_t address, UINT16 data, UINT16 mask); | |
| 738 | void memory_write_dword_16le(const address_space *space, offs_t address, UINT32 data); | |
| 739 | void memory_write_dword_masked_16le(const address_space *space, offs_t address, UINT32 data, UINT32 mask); | |
| 740 | void memory_write_qword_16le(const address_space *space, offs_t address, UINT64 data); | |
| 741 | void memory_write_qword_masked_16le(const address_space *space, offs_t address, UINT64 data, UINT64 mask); | |
| 742 | ||
| 743 | UINT8 memory_read_byte_16be(const address_space *space, offs_t address); | |
| 744 | UINT16 memory_read_word_16be(const address_space *space, offs_t address); | |
| 745 | UINT16 memory_read_word_masked_16be(const address_space *space, offs_t address, UINT16 mask); | |
| 746 | UINT32 memory_read_dword_16be(const address_space *space, offs_t address); | |
| 747 | UINT32 memory_read_dword_masked_16be(const address_space *space, offs_t address, UINT32 mask); | |
| 748 | UINT64 memory_read_qword_16be(const address_space *space, offs_t address); | |
| 749 | UINT64 memory_read_qword_masked_16be(const address_space *space, offs_t address, UINT64 mask); | |
| 750 | void memory_write_byte_16be(const address_space *space, offs_t address, UINT8 data); | |
| 751 | void memory_write_word_16be(const address_space *space, offs_t address, UINT16 data); | |
| 752 | void memory_write_word_masked_16be(const address_space *space, offs_t address, UINT16 data, UINT16 mask); | |
| 753 | void memory_write_dword_16be(const address_space *space, offs_t address, UINT32 data); | |
| 754 | void memory_write_dword_masked_16be(const address_space *space, offs_t address, UINT32 data, UINT32 mask); | |
| 755 | void memory_write_qword_16be(const address_space *space, offs_t address, UINT64 data); | |
| 756 | void memory_write_qword_masked_16be(const address_space *space, offs_t address, UINT64 data, UINT64 mask); | |
| 757 | ||
| 758 | UINT8 memory_read_byte_32le(const address_space *space, offs_t address); | |
| 759 | UINT16 memory_read_word_32le(const address_space *space, offs_t address); | |
| 760 | UINT16 memory_read_word_masked_32le(const address_space *space, offs_t address, UINT16 mask); | |
| 761 | UINT32 memory_read_dword_32le(const address_space *space, offs_t address); | |
| 762 | UINT32 memory_read_dword_masked_32le(const address_space *space, offs_t address, UINT32 mask); | |
| 763 | UINT64 memory_read_qword_32le(const address_space *space, offs_t address); | |
| 764 | UINT64 memory_read_qword_masked_32le(const address_space *space, offs_t address, UINT64 mask); | |
| 765 | void memory_write_byte_32le(const address_space *space, offs_t address, UINT8 data); | |
| 766 | void memory_write_word_32le(const address_space *space, offs_t address, UINT16 data); | |
| 767 | void memory_write_word_masked_32le(const address_space *space, offs_t address, UINT16 data, UINT16 mask); | |
| 768 | void memory_write_dword_32le(const address_space *space, offs_t address, UINT32 data); | |
| 769 | void memory_write_dword_masked_32le(const address_space *space, offs_t address, UINT32 data, UINT32 mask); | |
| 770 | void memory_write_qword_32le(const address_space *space, offs_t address, UINT64 data); | |
| 771 | void memory_write_qword_masked_32le(const address_space *space, offs_t address, UINT64 data, UINT64 mask); | |
| 772 | ||
| 773 | UINT8 memory_read_byte_32be(const address_space *space, offs_t address); | |
| 774 | UINT16 memory_read_word_32be(const address_space *space, offs_t address); | |
| 775 | UINT16 memory_read_word_masked_32be(const address_space *space, offs_t address, UINT16 mask); | |
| 776 | UINT32 memory_read_dword_32be(const address_space *space, offs_t address); | |
| 777 | UINT32 memory_read_dword_masked_32be(const address_space *space, offs_t address, UINT32 mask); | |
| 778 | UINT64 memory_read_qword_32be(const address_space *space, offs_t address); | |
| 779 | UINT64 memory_read_qword_masked_32be(const address_space *space, offs_t address, UINT64 mask); | |
| 780 | void memory_write_byte_32be(const address_space *space, offs_t address, UINT8 data); | |
| 781 | void memory_write_word_32be(const address_space *space, offs_t address, UINT16 data); | |
| 782 | void memory_write_word_masked_32be(const address_space *space, offs_t address, UINT16 data, UINT16 mask); | |
| 783 | void memory_write_dword_32be(const address_space *space, offs_t address, UINT32 data); | |
| 784 | void memory_write_dword_masked_32be(const address_space *space, offs_t address, UINT32 data, UINT32 mask); | |
| 785 | void memory_write_qword_32be(const address_space *space, offs_t address, UINT64 data); | |
| 786 | void memory_write_qword_masked_32be(const address_space *space, offs_t address, UINT64 data, UINT64 mask); | |
| 787 | ||
| 788 | UINT8 memory_read_byte_64le(const address_space *space, offs_t address); | |
| 789 | UINT16 memory_read_word_64le(const address_space *space, offs_t address); | |
| 790 | UINT16 memory_read_word_masked_64le(const address_space *space, offs_t address, UINT16 mask); | |
| 791 | UINT32 memory_read_dword_64le(const address_space *space, offs_t address); | |
| 792 | UINT32 memory_read_dword_masked_64le(const address_space *space, offs_t address, UINT32 mask); | |
| 793 | UINT64 memory_read_qword_64le(const address_space *space, offs_t address); | |
| 794 | UINT64 memory_read_qword_masked_64le(const address_space *space, offs_t address, UINT64 mask); | |
| 795 | void memory_write_byte_64le(const address_space *space, offs_t address, UINT8 data); | |
| 796 | void memory_write_word_64le(const address_space *space, offs_t address, UINT16 data); | |
| 797 | void memory_write_word_masked_64le(const address_space *space, offs_t address, UINT16 data, UINT16 mask); | |
| 798 | void memory_write_dword_64le(const address_space *space, offs_t address, UINT32 data); | |
| 799 | void memory_write_dword_masked_64le(const address_space *space, offs_t address, UINT32 data, UINT32 mask); | |
| 800 | void memory_write_qword_64le(const address_space *space, offs_t address, UINT64 data); | |
| 801 | void memory_write_qword_masked_64le(const address_space *space, offs_t address, UINT64 data, UINT64 mask); | |
| 802 | ||
| 803 | UINT8 memory_read_byte_64be(const address_space *space, offs_t address); | |
| 804 | UINT16 memory_read_word_64be(const address_space *space, offs_t address); | |
| 805 | UINT16 memory_read_word_masked_64be(const address_space *space, offs_t address, UINT16 mask); | |
| 806 | UINT32 memory_read_dword_64be(const address_space *space, offs_t address); | |
| 807 | UINT32 memory_read_dword_masked_64be(const address_space *space, offs_t address, UINT32 mask); | |
| 808 | UINT64 memory_read_qword_64be(const address_space *space, offs_t address); | |
| 809 | UINT64 memory_read_qword_masked_64be(const address_space *space, offs_t address, UINT64 mask); | |
| 810 | void memory_write_byte_64be(const address_space *space, offs_t address, UINT8 data); | |
| 811 | void memory_write_word_64be(const address_space *space, offs_t address, UINT16 data); | |
| 812 | void memory_write_word_masked_64be(const address_space *space, offs_t address, UINT16 data, UINT16 mask); | |
| 813 | void memory_write_dword_64be(const address_space *space, offs_t address, UINT32 data); | |
| 814 | void memory_write_dword_masked_64be(const address_space *space, offs_t address, UINT32 data, UINT32 mask); | |
| 815 | void memory_write_qword_64be(const address_space *space, offs_t address, UINT64 data); | |
| 816 | void memory_write_qword_masked_64be(const address_space *space, offs_t address, UINT64 data, UINT64 mask); | |
| 817 | ||
| 818 | 902 | #endif /* __MEMORY_H__ */ |
| r8806 | r8807 | |
|---|---|---|
| 126 | 126 | UINT8 verify_only; |
| 127 | 127 | |
| 128 | 128 | UINT8 dma_active; |
| 129 | | |
| 129 | | |
| 130 | 130 | UINT8 dma_address_xor; |
| 131 | 131 | UINT8 dma_last_buffer; |
| 132 | 132 | offs_t dma_address; |
| r8806 | r8807 | |
| 693 | 693 | } |
| 694 | 694 | |
| 695 | 695 | /* fetch the address */ |
| 696 | ide->dma_address = memory_read_byte(ide->dma_space, ide->dma_descriptor++ ^ ide->dma_address_xor); | |
| 697 | ide->dma_address |= memory_read_byte(ide->dma_space, ide->dma_descriptor++ ^ ide->dma_address_xor) << 8; | |
| 698 | ide->dma_address |= memory_read_byte(ide->dma_space, ide->dma_descriptor++ ^ ide->dma_address_xor) << 16; | |
| 699 | ide->dma_address |= memory_read_byte(ide->dma_space, ide->dma_descriptor++ ^ ide->dma_address_xor) << 24; | |
| 696 | ide->dma_address = ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor); | |
| 697 | ide->dma_address |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 8; | |
| 698 | ide->dma_address |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 16; | |
| 699 | ide->dma_address |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 24; | |
| 700 | 700 | ide->dma_address &= 0xfffffffe; |
| 701 | 701 | |
| 702 | 702 | /* fetch the length */ |
| 703 | ide->dma_bytes_left = memory_read_byte(ide->dma_space, ide->dma_descriptor++ ^ ide->dma_address_xor); | |
| 704 | ide->dma_bytes_left |= memory_read_byte(ide->dma_space, ide->dma_descriptor++ ^ ide->dma_address_xor) << 8; | |
| 705 | ide->dma_bytes_left |= memory_read_byte(ide->dma_space, ide->dma_descriptor++ ^ ide->dma_address_xor) << 16; | |
| 706 | ide->dma_bytes_left |= memory_read_byte(ide->dma_space, ide->dma_descriptor++ ^ ide->dma_address_xor) << 24; | |
| 703 | ide->dma_bytes_left = ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor); | |
| 704 | ide->dma_bytes_left |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 8; | |
| 705 | ide->dma_bytes_left |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 16; | |
| 706 | ide->dma_bytes_left |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 24; | |
| 707 | 707 | ide->dma_last_buffer = (ide->dma_bytes_left >> 31) & 1; |
| 708 | 708 | ide->dma_bytes_left &= 0xfffe; |
| 709 | 709 | if (ide->dma_bytes_left == 0) |
| r8806 | r8807 | |
| 713 | 713 | } |
| 714 | 714 | |
| 715 | 715 | /* write the next byte */ |
| 716 | | |
| 716 | | |
| 717 | 717 | ide->dma_bytes_left--; |
| 718 | 718 | } |
| 719 | 719 | } |
| r8806 | r8807 | |
| 897 | 897 | } |
| 898 | 898 | |
| 899 | 899 | /* fetch the address */ |
| 900 | ide->dma_address = memory_read_byte(ide->dma_space, ide->dma_descriptor++ ^ ide->dma_address_xor); | |
| 901 | ide->dma_address |= memory_read_byte(ide->dma_space, ide->dma_descriptor++ ^ ide->dma_address_xor) << 8; | |
| 902 | ide->dma_address |= memory_read_byte(ide->dma_space, ide->dma_descriptor++ ^ ide->dma_address_xor) << 16; | |
| 903 | ide->dma_address |= memory_read_byte(ide->dma_space, ide->dma_descriptor++ ^ ide->dma_address_xor) << 24; | |
| 900 | ide->dma_address = ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor); | |
| 901 | ide->dma_address |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 8; | |
| 902 | ide->dma_address |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 16; | |
| 903 | ide->dma_address |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 24; | |
| 904 | 904 | ide->dma_address &= 0xfffffffe; |
| 905 | 905 | |
| 906 | 906 | /* fetch the length */ |
| 907 | ide->dma_bytes_left = memory_read_byte(ide->dma_space, ide->dma_descriptor++ ^ ide->dma_address_xor); | |
| 908 | ide->dma_bytes_left |= memory_read_byte(ide->dma_space, ide->dma_descriptor++ ^ ide->dma_address_xor) << 8; | |
| 909 | ide->dma_bytes_left |= memory_read_byte(ide->dma_space, ide->dma_descriptor++ ^ ide->dma_address_xor) << 16; | |
| 910 | ide->dma_bytes_left |= memory_read_byte(ide->dma_space, ide->dma_descriptor++ ^ ide->dma_address_xor) << 24; | |
| 907 | ide->dma_bytes_left = ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor); | |
| 908 | ide->dma_bytes_left |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 8; | |
| 909 | ide->dma_bytes_left |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 16; | |
| 910 | ide->dma_bytes_left |= ide->dma_space->read_byte(ide->dma_descriptor++ ^ ide->dma_address_xor) << 24; | |
| 911 | 911 | ide->dma_last_buffer = (ide->dma_bytes_left >> 31) & 1; |
| 912 | 912 | ide->dma_bytes_left &= 0xfffe; |
| 913 | 913 | if (ide->dma_bytes_left == 0) |
| r8806 | r8807 | |
| 917 | 917 | } |
| 918 | 918 | |
| 919 | 919 | /* read the next byte */ |
| 920 | *data++ = | |
| 920 | *data++ = | |
| 921 | 921 | ide->dma_bytes_left--; |
| 922 | 922 | } |
| 923 | 923 | } |
| r8806 | r8807 | |
| 1819 | 1819 | ide->dma_space = memory->space(config->bmspace); |
| 1820 | 1820 | if (ide->dma_space == NULL) |
| 1821 | 1821 | throw emu_fatalerror("IDE controller '%s' bus master target '%s' does not have specified space %d!", device->tag(), config->bmcpu, config->bmspace); |
| 1822 | ide->dma_address_xor = (ide->dma_space->endianness == ENDIANNESS_LITTLE) ? 0 : 3; | |
| 1822 | ide->dma_address_xor = (ide->dma_space->endianness() == ENDIANNESS_LITTLE) ? 0 : 3; | |
| 1823 | 1823 | } |
| 1824 | 1824 | |
| 1825 | 1825 | /* get and copy the geometry */ |
| r8806 | r8807 | |
|---|---|---|
| 816 | 816 | -------------------------------------------------*/ |
| 817 | 817 | |
| 818 | 818 | WRITE8_HANDLER( watchdog_reset_w ) { watchdog_reset(space->machine); } |
| 819 | READ8_HANDLER( watchdog_reset_r ) { watchdog_reset(space->machine); return space->unmap; } | |
| 819 | READ8_HANDLER( watchdog_reset_r ) { watchdog_reset(space->machine); return space->unmap(); } | |
| 820 | 820 | |
| 821 | 821 | |
| 822 | 822 | /*------------------------------------------------- |
| r8806 | r8807 | |
| 824 | 824 | -------------------------------------------------*/ |
| 825 | 825 | |
| 826 | 826 | WRITE16_HANDLER( watchdog_reset16_w ) { watchdog_reset(space->machine); } |
| 827 | READ16_HANDLER( watchdog_reset16_r ) { watchdog_reset(space->machine); return space->unmap; } | |
| 827 | READ16_HANDLER( watchdog_reset16_r ) { watchdog_reset(space->machine); return space->unmap(); } | |
| 828 | 828 | |
| 829 | 829 | |
| 830 | 830 | /*------------------------------------------------- |
| r8806 | r8807 | |
| 832 | 832 | -------------------------------------------------*/ |
| 833 | 833 | |
| 834 | 834 | WRITE32_HANDLER( watchdog_reset32_w ) { watchdog_reset(space->machine); } |
| 835 | READ32_HANDLER( watchdog_reset32_r ) { watchdog_reset(space->machine); return space->unmap; } | |
| 835 | READ32_HANDLER( watchdog_reset32_r ) { watchdog_reset(space->machine); return space->unmap(); } | |
| 836 | 836 | |
| 837 | 837 | |
| 838 | 838 |
| r8806 | r8807 | |
|---|---|---|
| 11 | 11 | #include "emu.h" |
| 12 | 12 | #include "machine/tmp68301.h" |
| 13 | 13 | |
| 14 | UINT16 | |
| 14 | static UINT16 | |
| 15 | 15 | |
| 16 | 16 | static UINT8 tmp68301_IE[3]; // 3 External Interrupt Lines |
| 17 | 17 | static emu_timer *tmp68301_timer[3]; // 3 Timers |
| r8806 | r8807 | |
| 155 | 155 | } |
| 156 | 156 | } |
| 157 | 157 | |
| 158 | READ16_HANDLER( tmp68301_regs_r ) | |
| 159 | { | |
| 160 | return tmp68301_regs[offset]; | |
| 161 | } | |
| 162 | ||
| 158 | 163 | WRITE16_HANDLER( tmp68301_regs_w ) |
| 159 | 164 | { |
| 160 | 165 | COMBINE_DATA(&tmp68301_regs[offset]); |
| r8806 | r8807 | |
|---|---|---|
| 6 | 6 | MACHINE_RESET( tmp68301 ); |
| 7 | 7 | |
| 8 | 8 | // Hardware Registers |
| 9 | ||
| 9 | READ | |
| 10 | 10 | WRITE16_HANDLER( tmp68301_regs_w ); |
| 11 | 11 | |
| 12 | 12 | // Interrupts |
| r8806 | r8807 | |
|---|---|---|
| 233 | 233 | UINT16 default_value = 0xff; |
| 234 | 234 | for( offs_t offs = 0; offs < i2cmem_bytes; offs++ ) |
| 235 | 235 | { |
| 236 | m | |
| 236 | m | |
| 237 | 237 | } |
| 238 | 238 | |
| 239 | 239 | /* populate from a memory region if present */ |
| r8806 | r8807 | |
| 251 | 251 | |
| 252 | 252 | for( offs_t offs = 0; offs < i2cmem_bytes; offs++ ) |
| 253 | 253 | { |
| 254 | m | |
| 254 | m | |
| 255 | 255 | } |
| 256 | 256 | } |
| 257 | 257 | } |
| r8806 | r8807 | |
| 271 | 271 | |
| 272 | 272 | for( offs_t offs = 0; offs < i2cmem_bytes; offs++ ) |
| 273 | 273 | { |
| 274 | m | |
| 274 | m | |
| 275 | 275 | } |
| 276 | 276 | |
| 277 | 277 | auto_free( &m_machine, buffer ); |
| r8806 | r8807 | |
| 289 | 289 | |
| 290 | 290 | for( offs_t offs = 0; offs < i2cmem_bytes; offs++ ) |
| 291 | 291 | { |
| 292 | buffer[ offs ] = m | |
| 292 | buffer[ offs ] = m | |
| 293 | 293 | } |
| 294 | 294 | |
| 295 | 295 | mame_fwrite( &file, buffer, i2cmem_bytes ); |
| r8806 | r8807 | |
| 384 | 384 | } |
| 385 | 385 | } |
| 386 | 386 | |
| 387 | ||
| 388 | 387 | WRITE_LINE_DEVICE_HANDLER( i2cmem_scl_write ) |
| 389 | 388 | { |
| 390 | 389 | downcast<i2cmem_device *>( device )->set_scl_line( state ); |
| r8806 | r8807 | |
| 465 | 464 | |
| 466 | 465 | for( int i = 0; i < m_page_size; i++ ) |
| 467 | 466 | { |
| 468 | m | |
| 467 | m | |
| 469 | 468 | } |
| 470 | 469 | |
| 471 | 470 | m_page_offset = 0; |
| r8806 | r8807 | |
| 476 | 475 | int offset = data_offset(); |
| 477 | 476 | |
| 478 | 477 | verboselog( this, 1, "data[ %04x ] <- %02x\n", offset, m_shift ); |
| 479 | m | |
| 478 | m | |
| 480 | 479 | |
| 481 | 480 | m_byteaddr++; |
| 482 | 481 | } |
| r8806 | r8807 | |
| 509 | 508 | { |
| 510 | 509 | int offset = data_offset(); |
| 511 | 510 | |
| 512 | m_shift = m | |
| 511 | m_shift = m | |
| 513 | 512 | verboselog( this, 1, "data[ %04x ] -> %02x\n", offset, m_shift ); |
| 514 | 513 | m_byteaddr++; |
| 515 | 514 | } |
| r8806 | r8807 | |
|---|---|---|
| 155 | 155 | UINT16 default_value = 0xff; |
| 156 | 156 | for( offs_t offs = 0; offs < AT28C16_TOTAL_BYTES; offs++ ) |
| 157 | 157 | { |
| 158 | m | |
| 158 | m | |
| 159 | 159 | } |
| 160 | 160 | |
| 161 | 161 | /* populate from a memory region if present */ |
| r8806 | r8807 | |
| 173 | 173 | |
| 174 | 174 | for( offs_t offs = 0; offs < AT28C16_DATA_BYTES; offs++ ) |
| 175 | 175 | { |
| 176 | m | |
| 176 | m | |
| 177 | 177 | } |
| 178 | 178 | } |
| 179 | 179 | } |
| r8806 | r8807 | |
| 192 | 192 | |
| 193 | 193 | for( offs_t offs = 0; offs < AT28C16_TOTAL_BYTES; offs++ ) |
| 194 | 194 | { |
| 195 | m | |
| 195 | m | |
| 196 | 196 | } |
| 197 | 197 | |
| 198 | 198 | auto_free( &m_machine, buffer ); |
| r8806 | r8807 | |
| 209 | 209 | |
| 210 | 210 | for( offs_t offs = 0; offs < AT28C16_TOTAL_BYTES; offs++ ) |
| 211 | 211 | { |
| 212 | buffer[ offs ] = m | |
| 212 | buffer[ offs ] = m | |
| 213 | 213 | } |
| 214 | 214 | |
| 215 | 215 | mame_fwrite( &file, buffer, AT28C16_TOTAL_BYTES ); |
| r8806 | r8807 | |
| 241 | 241 | { |
| 242 | 242 | for( offs_t offs = 0; offs < AT28C16_TOTAL_BYTES; offs++ ) |
| 243 | 243 | { |
| 244 | m | |
| 244 | m | |
| 245 | 245 | } |
| 246 | 246 | |
| 247 | 247 | m_last_write = 0xff; |
| r8806 | r8807 | |
| 256 | 256 | } |
| 257 | 257 | |
| 258 | 258 | // logerror( "%s: AT28C16: write( %04x, %02x )\n", cpuexec_describe_context(machine), offset, data ); |
| 259 | if( m_last_write < 0 && m | |
| 259 | if( m_last_write < 0 && m | |
| 260 | 260 | { |
| 261 | m | |
| 261 | m | |
| 262 | 262 | m_last_write = data; |
| 263 | 263 | timer_adjust_oneshot( m_write_timer, ATTOTIME_IN_USEC( 200 ), 0 ); |
| 264 | 264 | } |
| r8806 | r8807 | |
| 286 | 286 | offset += AT28C16_ID_BYTES; |
| 287 | 287 | } |
| 288 | 288 | |
| 289 | UINT8 data = m | |
| 289 | UINT8 data = m | |
| 290 | 290 | // logerror( "%s: AT28C16: read( %04x ) data %02x\n", cpuexec_describe_context(machine), offset, data ); |
| 291 | 291 | return data; |
| 292 | 292 | } |
| r8806 | r8807 | |
|---|---|---|
| 83 | 83 | if (latch8->has_read) |
| 84 | 84 | { |
| 85 | 85 | /* temporary hack until all relevant systems are devices */ |
| 86 | | |
| 86 | | |
| 87 | 87 | int i; |
| 88 | 88 | for (i=0; i<8; i++) |
| 89 | 89 | { |
| r8806 | r8807 | |
|---|---|---|
| 239 | 239 | default_value = m_config.m_default_value; |
| 240 | 240 | for (offs_t offs = 0; offs < eeprom_length; offs++) |
| 241 | 241 | if (m_config.m_data_bits == 8) |
| 242 | m | |
| 242 | m | |
| 243 | 243 | else |
| 244 | m | |
| 244 | m | |
| 245 | 245 | |
| 246 | 246 | /* handle hard-coded data from the driver */ |
| 247 | 247 | if (m_config.m_default_data != NULL) |
| 248 | 248 | for (offs_t offs = 0; offs < m_config.m_default_data_size; offs++) |
| 249 | m | |
| 249 | m | |
| 250 | 250 | |
| 251 | 251 | /* populate from a memory region if present */ |
| 252 | 252 | if (m_region != NULL) |
| r8806 | r8807 | |
| 260 | 260 | |
| 261 | 261 | for (offs_t offs = 0; offs < eeprom_length; offs++) |
| 262 | 262 | if (m_config.m_data_bits == 8) |
| 263 | m | |
| 263 | m | |
| 264 | 264 | else |
| 265 | m | |
| 265 | m | |
| 266 | 266 | } |
| 267 | 267 | } |
| 268 | 268 | |
| r8806 | r8807 | |
| 280 | 280 | UINT8 *buffer = auto_alloc_array(&m_machine, UINT8, eeprom_bytes); |
| 281 | 281 | mame_fread(&file, buffer, eeprom_bytes); |
| 282 | 282 | for (offs_t offs = 0; offs < eeprom_bytes; offs++) |
| 283 | m | |
| 283 | m | |
| 284 | 284 | auto_free(&m_machine, buffer); |
| 285 | 285 | } |
| 286 | 286 | |
| r8806 | r8807 | |
| 297 | 297 | |
| 298 | 298 | UINT8 *buffer = auto_alloc_array(&m_machine, UINT8, eeprom_bytes); |
| 299 | 299 | for (offs_t offs = 0; offs < eeprom_bytes; offs++) |
| 300 | buffer[offs] = m | |
| 300 | buffer[offs] = m | |
| 301 | 301 | mame_fwrite(&file, buffer, eeprom_bytes); |
| 302 | 302 | auto_free(&m_machine, buffer); |
| 303 | 303 | } |
| r8806 | r8807 | |
| 391 | 391 | { |
| 392 | 392 | m_read_address = (m_read_address + 1) & ((1 << m_config.m_address_bits) - 1); |
| 393 | 393 | if (m_config.m_data_bits == 16) |
| 394 | m_data_bits = m | |
| 394 | m_data_bits = m | |
| 395 | 395 | else |
| 396 | m_data_bits = m | |
| 396 | m_data_bits = m | |
| 397 | 397 | m_clock_count = 0; |
| 398 | 398 | logerror("EEPROM read %04x from address %02x\n",m_data_bits,m_read_address); |
| 399 | 399 | } |
| r8806 | r8807 | |
| 439 | 439 | if (m_serial_buffer[i] == '1') address |= 1; |
| 440 | 440 | } |
| 441 | 441 | if (m_config.m_data_bits == 16) |
| 442 | m_data_bits = m | |
| 442 | m_data_bits = m | |
| 443 | 443 | else |
| 444 | m_data_bits = m | |
| 444 | m_data_bits = m | |
| 445 | 445 | m_read_address = address; |
| 446 | 446 | m_clock_count = 0; |
| 447 | 447 | m_sending = 1; |
| r8806 | r8807 | |
| 463 | 463 | if (m_locked == 0) |
| 464 | 464 | { |
| 465 | 465 | if (m_config.m_data_bits == 16) |
| 466 | m | |
| 466 | m | |
| 467 | 467 | else |
| 468 | m | |
| 468 | m | |
| 469 | 469 | } |
| 470 | 470 | else |
| 471 | 471 | logerror("Error: EEPROM is m_locked\n"); |
| r8806 | r8807 | |
| 492 | 492 | if (m_locked == 0) |
| 493 | 493 | { |
| 494 | 494 | if (m_config.m_data_bits == 16) |
| 495 | m | |
| 495 | m | |
| 496 | 496 | else |
| 497 | m | |
| 497 | m | |
| 498 | 498 | } |
| 499 | 499 | else |
| 500 | 500 | logerror("Error: EEPROM is m_locked\n"); |
| r8806 | r8807 | |
|---|---|---|
| 355 | 355 | // COMMON TEMPLATES |
| 356 | 356 | //************************************************************************** |
| 357 | 357 | |
| 358 | // ======================> simple_list | |
| 359 | ||
| 358 | 360 | template<class T> |
| 361 | class simple_list | |
| 362 | { | |
| 363 | DISABLE_COPYING(simple_list); | |
| 364 | ||
| 365 | T *m_head; | |
| 366 | T *m_tail; | |
| 367 | resource_pool &m_pool; | |
| 368 | int m_count; | |
| 369 | ||
| 370 | public: | |
| 371 | simple_list(resource_pool &pool = global_resource_pool) : | |
| 372 | m_head(NULL), | |
| 373 | m_tail(NULL), | |
| 374 | m_pool(pool), | |
| 375 | m_count(0) { } | |
| 376 | ||
| 377 | virtual ~simple_list() { reset(); } | |
| 378 | ||
| 379 | T *first() const { return m_head; } | |
| 380 | T *last() const { return m_tail; } | |
| 381 | int count() const { return m_count; } | |
| 382 | ||
| 383 | void reset() { while (m_head != NULL) remove(*m_head); } | |
| 384 | ||
| 385 | int index(T *object) const | |
| 386 | { | |
| 387 | int num = 0; | |
| 388 | for (T *cur = m_head; cur != NULL; cur = cur->m_next) | |
| 389 | if (cur == object) | |
| 390 | return num; | |
| 391 | else | |
| 392 | num++; | |
| 393 | return -1; | |
| 394 | } | |
| 395 | ||
| 396 | T &prepend(T &object) | |
| 397 | { | |
| 398 | object.m_next = m_head; | |
| 399 | m_head = &object; | |
| 400 | if (m_tail == NULL) | |
| 401 | m_tail = m_head; | |
| 402 | m_count++; | |
| 403 | return object; | |
| 404 | } | |
| 405 | ||
| 406 | T &append(T &object) | |
| 407 | { | |
| 408 | object.m_next = NULL; | |
| 409 | if (m_tail != NULL) | |
| 410 | m_tail = m_tail->m_next = &object; | |
| 411 | else | |
| 412 | m_tail = m_head = &object; | |
| 413 | m_count++; | |
| 414 | return object; | |
| 415 | } | |
| 416 | ||
| 417 | void detach(T &object) | |
| 418 | { | |
| 419 | T *prev = NULL; | |
| 420 | for (T *cur = m_head; cur != NULL; prev = cur, cur = cur->m_next) | |
| 421 | if (cur == &object) | |
| 422 | { | |
| 423 | if (prev != NULL) | |
| 424 | prev->m_next = object.m_next; | |
| 425 | else | |
| 426 | m_head = object.m_next; | |
| 427 | if (m_tail == &object) | |
| 428 | m_tail = prev; | |
| 429 | m_count--; | |
| 430 | return; | |
| 431 | } | |
| 432 | } | |
| 433 | ||
| 434 | void remove(T &object) | |
| 435 | { | |
| 436 | detach(object); | |
| 437 | pool_free(m_pool, &object); | |
| 438 | } | |
| 439 | ||
| 440 | T *find(int index) const | |
| 441 | { | |
| 442 | for (T *cur = m_head; cur != NULL; cur = cur->m_next) | |
| 443 | if (index-- == 0) | |
| 444 | return cur; | |
| 445 | return NULL; | |
| 446 | } | |
| 447 | }; | |
| 448 | ||
| 449 | ||
| 450 | // ======================> tagged_list | |
| 451 | ||
| 452 | template<class T> | |
| 359 | 453 | class tagged_list |
| 360 | 454 | { |
| 361 | 455 | DISABLE_COPYING(tagged_list); |
| r8806 | r8807 | |
|---|---|---|
| 41 | 41 | |
| 42 | 42 | |
| 43 | 43 | //************************************************************************** |
| 44 | // | |
| 44 | // | |
| 45 | 45 | //************************************************************************** |
| 46 | 46 | |
| 47 | // maps a full 64-bit mask down to an 8-bit byte mask | |
| 48 | #define UNITMASK8(x) \ | |
| 49 | ((((UINT64)(x) >> (63-7)) & 0x80) | \ | |
| 50 | (((UINT64)(x) >> (55-6)) & 0x40) | \ | |
| 51 | (((UINT64)(x) >> (47-5)) & 0x20) | \ | |
| 52 | (((UINT64)(x) >> (39-4)) & 0x10) | \ | |
| 53 | (((UINT64)(x) >> (31-3)) & 0x08) | \ | |
| 54 | (((UINT64)(x) >> (23-2)) & 0x04) | \ | |
| 55 | (((UINT64)(x) >> (15-1)) & 0x02) | \ | |
| 56 | (((UINT64)(x) >> ( 7-0)) & 0x01)) | |
| 47 | //------------------------------------------------- | |
| 48 | // set_tag - set the appropriate tag for a device | |
| 49 | //------------------------------------------------- | |
| 57 | 50 | |
| 58 | // maps a full 64-bit mask down to a 4-bit word mask | |
| 59 | #define UNITMASK16(x) \ | |
| 60 | ((((UINT64)(x) >> (63-3)) & 0x08) | \ | |
| 61 | (((UINT64)(x) >> (47-2)) & 0x04) | \ | |
| 62 | (((UINT64)(x) >> (31-1)) & 0x02) | \ | |
| 63 | (((UINT64)(x) >> (15-0)) & 0x01)) | |
| 51 | inline void map_handler_data::set_tag(const device_config &devconfig, const char *tag) | |
| 52 | { | |
| 53 | if (tag == NULL) | |
| 54 | m_tag = NULL; | |
| 55 | else if (strcmp(tag, DEVICE_SELF) == 0) | |
| 56 | m_tag = devconfig.tag(); | |
| 57 | else | |
| 58 | m_tag = devconfig.siblingtag(m_derived_tag, tag); | |
| 59 | } | |
| 64 | 60 | |
| 65 | // maps a full 64-bit mask down to a 2-bit dword mask | |
| 66 | #define UNITMASK32(x) \ | |
| 67 | ((((UINT64)(x) >> (63-1)) & 0x02) | \ | |
| 68 | (((UINT64)(x) >> (31-0)) & 0x01)) | |
| 69 | 61 | |
| 70 | 62 | |
| 71 | ||
| 72 | 63 | //************************************************************************** |
| 73 | 64 | // ADDRESS MAP ENTRY |
| 74 | 65 | //************************************************************************** |
| r8806 | r8807 | |
| 93 | 84 | m_gensizeptroffs_plus1(0), |
| 94 | 85 | m_region(NULL), |
| 95 | 86 | m_rgnoffs(0), |
| 87 | m_rspace8(NULL), | |
| 88 | m_rspace16(NULL), | |
| 89 | m_rspace32(NULL), | |
| 90 | m_rspace64(NULL), | |
| 91 | m_rdevice8(NULL), | |
| 92 | m_rdevice16(NULL), | |
| 93 | m_rdevice32(NULL), | |
| 94 | m_rdevice64(NULL), | |
| 95 | m_wspace8(NULL), | |
| 96 | m_wspace16(NULL), | |
| 97 | m_wspace32(NULL), | |
| 98 | m_wspace64(NULL), | |
| 99 | m_wdevice8(NULL), | |
| 100 | m_wdevice16(NULL), | |
| 101 | m_wdevice32(NULL), | |
| 102 | m_wdevice64(NULL), | |
| 96 | 103 | m_memory(NULL), |
| 97 | 104 | m_bytestart(0), |
| 98 | 105 | m_byteend(0), |
| r8806 | r8807 | |
| 121 | 128 | |
| 122 | 129 | void address_map_entry::set_read_port(const device_config &devconfig, const char *tag) |
| 123 | 130 | { |
| 124 | m_read.type = AMH_PORT; | |
| 125 | m_read.tag = devconfig.siblingtag(m_read.derived_tag, tag); | |
| 131 | m_read.m_type = AMH_PORT; | |
| 132 | m_read.set_tag(devconfig, tag); | |
| 126 | 133 | } |
| 127 | 134 | |
| 128 | 135 | |
| r8806 | r8807 | |
| 133 | 140 | |
| 134 | 141 | void address_map_entry::set_write_port(const device_config &devconfig, const char *tag) |
| 135 | 142 | { |
| 136 | m_write.type = AMH_PORT; | |
| 137 | m_write.tag = devconfig.siblingtag(m_write.derived_tag, tag); | |
| 143 | m_write.m_type = AMH_PORT; | |
| 144 | m_write.set_tag(devconfig, tag); | |
| 138 | 145 | } |
| 139 | 146 | |
| 140 | 147 | |
| r8806 | r8807 | |
| 145 | 152 | |
| 146 | 153 | void address_map_entry::set_readwrite_port(const device_config &devconfig, const char *tag) |
| 147 | 154 | { |
| 148 | m_read.type = AMH_PORT; | |
| 149 | m_read.tag = devconfig.siblingtag(m_read.derived_tag, tag); | |
| 150 | m_write.type = AMH_PORT; | |
| 151 | m_write.tag = devconfig.siblingtag(m_write.derived_tag, tag); | |
| 155 | m_read.m_type = AMH_PORT; | |
| 156 | m_read.set_tag(devconfig, tag); | |
| 157 | m_write.m_type = AMH_PORT; | |
| 158 | m_write.set_tag(devconfig, tag); | |
| 152 | 159 | } |
| 153 | 160 | |
| 154 | 161 | |
| r8806 | r8807 | |
| 159 | 166 | |
| 160 | 167 | void address_map_entry::set_read_bank(const device_config &devconfig, const char *tag) |
| 161 | 168 | { |
| 162 | m_read.type = AMH_BANK; | |
| 163 | m_read.tag = devconfig.siblingtag(m_read.derived_tag, tag); | |
| 169 | m_read.m_type = AMH_BANK; | |
| 170 | m_read.set_tag(devconfig, tag); | |
| 164 | 171 | } |
| 165 | 172 | |
| 166 | 173 | |
| r8806 | r8807 | |
| 171 | 178 | |
| 172 | 179 | void address_map_entry::set_write_bank(const device_config &devconfig, const char *tag) |
| 173 | 180 | { |
| 174 | m_write.type = AMH_BANK; | |
| 175 | m_write.tag = devconfig.siblingtag(m_write.derived_tag, tag); | |
| 181 | m_write.m_type = AMH_BANK; | |
| 182 | m_write.set_tag(devconfig, tag); | |
| 176 | 183 | } |
| 177 | 184 | |
| 178 | 185 | |
| r8806 | r8807 | |
| 183 | 190 | |
| 184 | 191 | void address_map_entry::set_readwrite_bank(const device_config &devconfig, const char *tag) |
| 185 | 192 | { |
| 186 | m_read.type = AMH_BANK; | |
| 187 | m_read.tag = devconfig.siblingtag(m_read.derived_tag, tag); | |
| 188 | m_write.type = AMH_BANK; | |
| 189 | m_write.tag = devconfig.siblingtag(m_write.derived_tag, tag); | |
| 193 | m_read.m_type = AMH_BANK; | |
| 194 | m_read.set_tag(devconfig, tag); | |
| 195 | m_write.m_type = AMH_BANK; | |
| 196 | m_write.set_tag(devconfig, tag); | |
| 190 | 197 | } |
| 191 | 198 | |
| 192 | 199 | |
| r8806 | r8807 | |
| 197 | 204 | |
| 198 | 205 | void address_map_entry::internal_set_handler(read8_space_func func, const char *string, UINT64 unitmask) |
| 199 | 206 | { |
| 207 | assert(func != NULL); | |
| 200 | 208 | assert(unitmask_is_appropriate(8, unitmask, string)); |
| 201 | m_read.type = AMH_HANDLER; | |
| 202 | m_read.bits = (unitmask == 0) ? 0 : 8; | |
| 203 | m_read.mask = UNITMASK8(unitmask); | |
| 204 | m_read.handler.read.shandler8 = func; | |
| 205 | m_read.name = string; | |
| 209 | m_read.m_type = AMH_LEGACY_SPACE_HANDLER; | |
| 210 | m_read.m_bits = 8; | |
| 211 | m_read.m_mask = unitmask; | |
| 212 | m_read.m_name = string; | |
| 213 | m_rspace8 = func; | |
| 206 | 214 | } |
| 207 | 215 | |
| 208 | 216 | |
| 209 | 217 | void address_map_entry::internal_set_handler(write8_space_func func, const char *string, UINT64 unitmask) |
| 210 | 218 | { |
| 219 | assert(func != NULL); | |
| 211 | 220 | assert(unitmask_is_appropriate(8, unitmask, string)); |
| 212 | m_write.type = AMH_HANDLER; | |
| 213 | m_write.bits = (unitmask == 0) ? 0 : 8; | |
| 214 | m_write.mask = UNITMASK8(unitmask); | |
| 215 | m_write.handler.write.shandler8 = func; | |
| 216 | m_write.name = string; | |
| 221 | m_write.m_type = AMH_LEGACY_SPACE_HANDLER; | |
| 222 | m_write.m_bits = 8; | |
| 223 | m_write.m_mask = unitmask; | |
| 224 | m_write.m_name = string; | |
| 225 | m_wspace8 = func; | |
| 217 | 226 | } |
| 218 | 227 | |
| 219 | 228 | |
| r8806 | r8807 | |
| 226 | 235 | |
| 227 | 236 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, read8_device_func func, const char *string, UINT64 unitmask) |
| 228 | 237 | { |
| 238 | assert(func != NULL); | |
| 229 | 239 | assert(unitmask_is_appropriate(8, unitmask, string)); |
| 230 | m_read.type = AMH_DEVICE_HANDLER; | |
| 231 | m_read.bits = (unitmask == 0) ? 0 : 8; | |
| 232 | m_read.mask = UNITMASK8(unitmask); | |
| 233 | m_read.handler.read.dhandler8 = func; | |
| 234 | m_read.name = string; | |
| 235 | m_read.tag = devconfig.siblingtag(m_read.derived_tag, tag); | |
| 240 | m_read.m_type = AMH_LEGACY_DEVICE_HANDLER; | |
| 241 | m_read.m_bits = 8; | |
| 242 | m_read.m_mask = unitmask; | |
| 243 | m_read.m_name = string; | |
| 244 | m_read.set_tag(devconfig, tag); | |
| 245 | m_rdevice8 = func; | |
| 236 | 246 | } |
| 237 | 247 | |
| 238 | 248 | |
| 239 | 249 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, write8_device_func func, const char *string, UINT64 unitmask) |
| 240 | 250 | { |
| 251 | assert(func != NULL); | |
| 241 | 252 | assert(unitmask_is_appropriate(8, unitmask, string)); |
| 242 | m_write.type = AMH_DEVICE_HANDLER; | |
| 243 | m_write.bits = (unitmask == 0) ? 0 : 8; | |
| 244 | m_write.mask = UNITMASK8(unitmask); | |
| 245 | m_write.handler.write.dhandler8 = func; | |
| 246 | m_write.name = string; | |
| 247 | m_write.tag = devconfig.siblingtag(m_write.derived_tag, tag); | |
| 253 | m_write.m_type = AMH_LEGACY_DEVICE_HANDLER; | |
| 254 | m_write.m_bits = 8; | |
| 255 | m_write.m_mask = unitmask; | |
| 256 | m_write.m_name = string; | |
| 257 | m_write.set_tag(devconfig, tag); | |
| 258 | m_wdevice8 = func; | |
| 248 | 259 | } |
| 249 | 260 | |
| 250 | 261 | |
| r8806 | r8807 | |
| 255 | 266 | } |
| 256 | 267 | |
| 257 | 268 | |
| 269 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, read8_proto_delegate func, UINT64 unitmask) | |
| 270 | { | |
| 271 | assert(!func.isnull()); | |
| 272 | assert(unitmask_is_appropriate(8, unitmask, func.name())); | |
| 273 | m_read.m_type = (tag == NULL) ? AMH_DRIVER_DELEGATE : AMH_DEVICE_DELEGATE; | |
| 274 | m_read.m_bits = 8; | |
| 275 | m_read.m_mask = unitmask; | |
| 276 | m_read.m_name = func.name(); | |
| 277 | m_read.set_tag(devconfig, tag); | |
| 278 | m_rproto8 = func; | |
| 279 | } | |
| 280 | ||
| 281 | ||
| 282 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, write8_proto_delegate func, UINT64 unitmask) | |
| 283 | { | |
| 284 | assert(!func.isnull()); | |
| 285 | assert(unitmask_is_appropriate(8, unitmask, func.name())); | |
| 286 | m_write.m_type = (tag == NULL) ? AMH_DRIVER_DELEGATE : AMH_DEVICE_DELEGATE;; | |
| 287 | m_write.m_bits = 8; | |
| 288 | m_write.m_mask = unitmask; | |
| 289 | m_write.m_name = func.name(); | |
| 290 | m_write.set_tag(devconfig, tag); | |
| 291 | m_wproto8 = func; | |
| 292 | } | |
| 293 | ||
| 294 | ||
| 295 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, read8_proto_delegate rfunc, write8_proto_delegate wfunc, UINT64 unitmask) | |
| 296 | { | |
| 297 | internal_set_handler(devconfig, tag, rfunc, unitmask); | |
| 298 | internal_set_handler(devconfig, tag, wfunc, unitmask); | |
| 299 | } | |
| 300 | ||
| 301 | ||
| 258 | 302 | //------------------------------------------------- |
| 259 | 303 | // internal_set_handler - handler setters for |
| 260 | 304 | // 16-bit read/write handlers |
| r8806 | r8807 | |
| 262 | 306 | |
| 263 | 307 | void address_map_entry::internal_set_handler(read16_space_func func, const char *string, UINT64 unitmask) |
| 264 | 308 | { |
| 309 | assert(func != NULL); | |
| 265 | 310 | assert(unitmask_is_appropriate(16, unitmask, string)); |
| 266 | m_read.type = AMH_HANDLER; | |
| 267 | m_read.bits = (unitmask == 0) ? 0 : 16; | |
| 268 | m_read.mask = UNITMASK16(unitmask); | |
| 269 | m_read.handler.read.shandler16 = func; | |
| 270 | m_read.name = string; | |
| 311 | m_read.m_type = AMH_LEGACY_SPACE_HANDLER; | |
| 312 | m_read.m_bits = 16; | |
| 313 | m_read.m_mask = unitmask; | |
| 314 | m_read.m_name = string; | |
| 315 | m_rspace16 = func; | |
| 271 | 316 | } |
| 272 | 317 | |
| 273 | 318 | |
| 274 | 319 | void address_map_entry::internal_set_handler(write16_space_func func, const char *string, UINT64 unitmask) |
| 275 | 320 | { |
| 321 | assert(func != NULL); | |
| 276 | 322 | assert(unitmask_is_appropriate(16, unitmask, string)); |
| 277 | m_write.type = AMH_HANDLER; | |
| 278 | m_write.bits = (unitmask == 0) ? 0 : 16; | |
| 279 | m_write.mask = UNITMASK16(unitmask); | |
| 280 | m_write.handler.write.shandler16 = func; | |
| 281 | m_write.name = string; | |
| 323 | m_write.m_type = AMH_LEGACY_SPACE_HANDLER; | |
| 324 | m_write.m_bits = 16; | |
| 325 | m_write.m_mask = unitmask; | |
| 326 | m_write.m_name = string; | |
| 327 | m_wspace16 = func; | |
| 282 | 328 | } |
| 283 | 329 | |
| 284 | 330 | |
| r8806 | r8807 | |
| 291 | 337 | |
| 292 | 338 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, read16_device_func func, const char *string, UINT64 unitmask) |
| 293 | 339 | { |
| 340 | assert(func != NULL); | |
| 294 | 341 | assert(unitmask_is_appropriate(16, unitmask, string)); |
| 295 | m_read.type = AMH_DEVICE_HANDLER; | |
| 296 | m_read.bits = (unitmask == 0) ? 0 : 16; | |
| 297 | m_read.mask = UNITMASK16(unitmask); | |
| 298 | m_read.handler.read.dhandler16 = func; | |
| 299 | m_read.name = string; | |
| 300 | m_read.tag = devconfig.siblingtag(m_read.derived_tag, tag); | |
| 342 | m_read.m_type = AMH_LEGACY_DEVICE_HANDLER; | |
| 343 | m_read.m_bits = 16; | |
| 344 | m_read.m_mask = unitmask; | |
| 345 | m_read.m_name = string; | |
| 346 | m_read.set_tag(devconfig, tag); | |
| 347 | m_rdevice16 = func; | |
| 301 | 348 | } |
| 302 | 349 | |
| 303 | 350 | |
| 304 | 351 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, write16_device_func func, const char *string, UINT64 unitmask) |
| 305 | 352 | { |
| 353 | assert(func != NULL); | |
| 306 | 354 | assert(unitmask_is_appropriate(16, unitmask, string)); |
| 307 | m_write.type = AMH_DEVICE_HANDLER; | |
| 308 | m_write.bits = (unitmask == 0) ? 0 : 16; | |
| 309 | m_write.mask = UNITMASK16(unitmask); | |
| 310 | m_write.handler.write.dhandler16 = func; | |
| 311 | m_write.name = string; | |
| 312 | m_write.tag = devconfig.siblingtag(m_write.derived_tag, tag); | |
| 355 | m_write.m_type = AMH_LEGACY_DEVICE_HANDLER; | |
| 356 | m_write.m_bits = 16; | |
| 357 | m_write.m_mask = unitmask; | |
| 358 | m_write.m_name = string; | |
| 359 | m_write.set_tag(devconfig, tag); | |
| 360 | m_wdevice16 = func; | |
| 313 | 361 | } |
| 314 | 362 | |
| 315 | 363 | |
| r8806 | r8807 | |
| 320 | 368 | } |
| 321 | 369 | |
| 322 | 370 | |
| 371 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, read16_proto_delegate func, UINT64 unitmask) | |
| 372 | { | |
| 373 | assert(!func.isnull()); | |
| 374 | assert(unitmask_is_appropriate(16, unitmask, func.name())); | |
| 375 | m_read.m_type = (tag == NULL) ? AMH_DRIVER_DELEGATE : AMH_DEVICE_DELEGATE;; | |
| 376 | m_read.m_bits = 16; | |
| 377 | m_read.m_mask = unitmask; | |
| 378 | m_read.m_name = func.name(); | |
| 379 | m_read.set_tag(devconfig, tag); | |
| 380 | m_rproto16 = func; | |
| 381 | } | |
| 382 | ||
| 383 | ||
| 384 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, write16_proto_delegate func, UINT64 unitmask) | |
| 385 | { | |
| 386 | assert(!func.isnull()); | |
| 387 | assert(unitmask_is_appropriate(16, unitmask, func.name())); | |
| 388 | m_write.m_type = (tag == NULL) ? AMH_DRIVER_DELEGATE : AMH_DEVICE_DELEGATE;; | |
| 389 | m_write.m_bits = 16; | |
| 390 | m_write.m_mask = unitmask; | |
| 391 | m_write.m_name = func.name(); | |
| 392 | m_write.set_tag(devconfig, tag); | |
| 393 | m_wproto16 = func; | |
| 394 | } | |
| 395 | ||
| 396 | ||
| 397 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, read16_proto_delegate rfunc, write16_proto_delegate wfunc, UINT64 unitmask) | |
| 398 | { | |
| 399 | internal_set_handler(devconfig, tag, rfunc, unitmask); | |
| 400 | internal_set_handler(devconfig, tag, wfunc, unitmask); | |
| 401 | } | |
| 402 | ||
| 403 | ||
| 323 | 404 | //------------------------------------------------- |
| 324 | 405 | // internal_set_handler - handler setters for |
| 325 | 406 | // 32-bit read/write handlers |
| r8806 | r8807 | |
| 327 | 408 | |
| 328 | 409 | void address_map_entry::internal_set_handler(read32_space_func func, const char *string, UINT64 unitmask) |
| 329 | 410 | { |
| 411 | assert(func != NULL); | |
| 330 | 412 | assert(unitmask_is_appropriate(32, unitmask, string)); |
| 331 | m_read.type = AMH_HANDLER; | |
| 332 | m_read.bits = (unitmask == 0) ? 0 : 32; | |
| 333 | m_read.mask = UNITMASK32(unitmask); | |
| 334 | m_read.handler.read.shandler32 = func; | |
| 335 | m_read.name = string; | |
| 413 | m_read.m_type = AMH_LEGACY_SPACE_HANDLER; | |
| 414 | m_read.m_bits = 32; | |
| 415 | m_read.m_mask = unitmask; | |
| 416 | m_read.m_name = string; | |
| 417 | m_rspace32 = func; | |
| 336 | 418 | } |
| 337 | 419 | |
| 338 | 420 | |
| 339 | 421 | void address_map_entry::internal_set_handler(write32_space_func func, const char *string, UINT64 unitmask) |
| 340 | 422 | { |
| 423 | assert(func != NULL); | |
| 341 | 424 | assert(unitmask_is_appropriate(32, unitmask, string)); |
| 342 | m_write.type = AMH_HANDLER; | |
| 343 | m_write.bits = (unitmask == 0) ? 0 : 32; | |
| 344 | m_write.mask = UNITMASK32(unitmask); | |
| 345 | m_write.handler.write.shandler32 = func; | |
| 346 | m_write.name = string; | |
| 425 | m_write.m_type = AMH_LEGACY_SPACE_HANDLER; | |
| 426 | m_write.m_bits = 32; | |
| 427 | m_write.m_mask = unitmask; | |
| 428 | m_write.m_name = string; | |
| 429 | m_wspace32 = func; | |
| 347 | 430 | } |
| 348 | 431 | |
| 349 | 432 | |
| r8806 | r8807 | |
| 356 | 439 | |
| 357 | 440 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, read32_device_func func, const char *string, UINT64 unitmask) |
| 358 | 441 | { |
| 442 | assert(func != NULL); | |
| 359 | 443 | assert(unitmask_is_appropriate(32, unitmask, string)); |
| 360 | m_read.type = AMH_DEVICE_HANDLER; | |
| 361 | m_read.bits = (unitmask == 0) ? 0 : 32; | |
| 362 | m_read.mask = UNITMASK32(unitmask); | |
| 363 | m_read.handler.read.dhandler32 = func; | |
| 364 | m_read.name = string; | |
| 365 | m_read.tag = devconfig.siblingtag(m_read.derived_tag, tag); | |
| 444 | m_read.m_type = AMH_LEGACY_DEVICE_HANDLER; | |
| 445 | m_read.m_bits = 32; | |
| 446 | m_read.m_mask = unitmask; | |
| 447 | m_read.m_name = string; | |
| 448 | m_read.set_tag(devconfig, tag); | |
| 449 | m_rdevice32 = func; | |
| 366 | 450 | } |
| 367 | 451 | |
| 368 | 452 | |
| 369 | 453 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, write32_device_func func, const char *string, UINT64 unitmask) |
| 370 | 454 | { |
| 455 | assert(func != NULL); | |
| 371 | 456 | assert(unitmask_is_appropriate(32, unitmask, string)); |
| 372 | m_write.type = AMH_DEVICE_HANDLER; | |
| 373 | m_write.bits = (unitmask == 0) ? 0 : 32; | |
| 374 | m_write.mask = UNITMASK32(unitmask); | |
| 375 | m_write.handler.write.dhandler32 = func; | |
| 376 | m_write.name = string; | |
| 377 | m_write.tag = devconfig.siblingtag(m_write.derived_tag, tag); | |
| 457 | m_write.m_type = AMH_LEGACY_DEVICE_HANDLER; | |
| 458 | m_write.m_bits = 32; | |
| 459 | m_write.m_mask = unitmask; | |
| 460 | m_write.m_name = string; | |
| 461 | m_write.set_tag(devconfig, tag); | |
| 462 | m_wdevice32 = func; | |
| 378 | 463 | } |
| 379 | 464 | |
| 380 | 465 | |
| r8806 | r8807 | |
| 385 | 470 | } |
| 386 | 471 | |
| 387 | 472 | |
| 473 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, read32_proto_delegate func, UINT64 unitmask) | |
| 474 | { | |
| 475 | assert(!func.isnull()); | |
| 476 | assert(unitmask_is_appropriate(32, unitmask, func.name())); | |
| 477 | m_read.m_type = (tag == NULL) ? AMH_DRIVER_DELEGATE : AMH_DEVICE_DELEGATE;; | |
| 478 | m_read.m_bits = 32; | |
| 479 | m_read.m_mask = unitmask; | |
| 480 | m_read.m_name = func.name(); | |
| 481 | m_read.set_tag(devconfig, tag); | |
| 482 | m_rproto32 = func; | |
| 483 | } | |
| 484 | ||
| 485 | ||
| 486 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, write32_proto_delegate func, UINT64 unitmask) | |
| 487 | { | |
| 488 | assert(!func.isnull()); | |
| 489 | assert(unitmask_is_appropriate(32, unitmask, func.name())); | |
| 490 | m_write.m_type = (tag == NULL) ? AMH_DRIVER_DELEGATE : AMH_DEVICE_DELEGATE;; | |
| 491 | m_write.m_bits = 32; | |
| 492 | m_write.m_mask = unitmask; | |
| 493 | m_write.m_name = func.name(); | |
| 494 | m_write.set_tag(devconfig, tag); | |
| 495 | m_wproto32 = func; | |
| 496 | } | |
| 497 | ||
| 498 | ||
| 499 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, read32_proto_delegate rfunc, write32_proto_delegate wfunc, UINT64 unitmask) | |
| 500 | { | |
| 501 | internal_set_handler(devconfig, tag, rfunc, unitmask); | |
| 502 | internal_set_handler(devconfig, tag, wfunc, unitmask); | |
| 503 | } | |
| 504 | ||
| 505 | ||
| 388 | 506 | //------------------------------------------------- |
| 389 | 507 | // internal_set_handler - handler setters for |
| 390 | 508 | // 64-bit read/write handlers |
| r8806 | r8807 | |
| 392 | 510 | |
| 393 | 511 | void address_map_entry::internal_set_handler(read64_space_func func, const char *string, UINT64 unitmask) |
| 394 | 512 | { |
| 513 | assert(func != NULL); | |
| 395 | 514 | assert(unitmask_is_appropriate(64, unitmask, string)); |
| 396 | m_read.type = AMH_HANDLER; | |
| 397 | m_read.bits = (unitmask == 0) ? 0 : 64; | |
| 398 | m_read.mask = 0; | |
| 399 | m_read.handler.read.shandler64 = func; | |
| 400 | m_read.name = string; | |
| 515 | m_read.m_type = AMH_LEGACY_SPACE_HANDLER; | |
| 516 | m_read.m_bits = 64; | |
| 517 | m_read.m_mask = 0; | |
| 518 | m_read.m_name = string; | |
| 519 | m_rspace64 = func; | |
| 401 | 520 | } |
| 402 | 521 | |
| 403 | 522 | |
| 404 | 523 | void address_map_entry::internal_set_handler(write64_space_func func, const char *string, UINT64 unitmask) |
| 405 | 524 | { |
| 525 | assert(func != NULL); | |
| 406 | 526 | assert(unitmask_is_appropriate(64, unitmask, string)); |
| 407 | m_write.type = AMH_HANDLER; | |
| 408 | m_write.bits = (unitmask == 0) ? 0 : 64; | |
| 409 | m_write.mask = 0; | |
| 410 | m_write.handler.write.shandler64 = func; | |
| 411 | m_write.name = string; | |
| 527 | m_write.m_type = AMH_LEGACY_SPACE_HANDLER; | |
| 528 | m_write.m_bits = 64; | |
| 529 | m_write.m_mask = 0; | |
| 530 | m_write.m_name = string; | |
| 531 | m_wspace64 = func; | |
| 412 | 532 | } |
| 413 | 533 | |
| 414 | 534 | |
| r8806 | r8807 | |
| 421 | 541 | |
| 422 | 542 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, read64_device_func func, const char *string, UINT64 unitmask) |
| 423 | 543 | { |
| 544 | assert(func != NULL); | |
| 424 | 545 | assert(unitmask_is_appropriate(64, unitmask, string)); |
| 425 | m_read.type = AMH_DEVICE_HANDLER; | |
| 426 | m_read.bits = (unitmask == 0) ? 0 : 64; | |
| 427 | m_read.mask = 0; | |
| 428 | m_read.handler.read.dhandler64 = func; | |
| 429 | m_read.name = string; | |
| 430 | m_read.tag = devconfig.siblingtag(m_read.derived_tag, tag); | |
| 546 | m_read.m_type = AMH_LEGACY_DEVICE_HANDLER; | |
| 547 | m_read.m_bits = 64; | |
| 548 | m_read.m_mask = 0; | |
| 549 | m_read.m_name = string; | |
| 550 | m_read.set_tag(devconfig, tag); | |
| 551 | m_rdevice64 = func; | |
| 431 | 552 | } |
| 432 | 553 | |
| 433 | 554 | |
| 434 | 555 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, write64_device_func func, const char *string, UINT64 unitmask) |
| 435 | 556 | { |
| 557 | assert(func != NULL); | |
| 436 | 558 | assert(unitmask_is_appropriate(64, unitmask, string)); |
| 437 | m_write.type = AMH_DEVICE_HANDLER; | |
| 438 | m_write.bits = (unitmask == 0) ? 0 : 64; | |
| 439 | m_write.mask = 0; | |
| 440 | m_write.handler.write.dhandler64 = func; | |
| 441 | m_write.name = string; | |
| 442 | m_write.tag = devconfig.siblingtag(m_write.derived_tag, tag); | |
| 559 | m_write.m_type = AMH_LEGACY_DEVICE_HANDLER; | |
| 560 | m_write.m_bits = 64; | |
| 561 | m_write.m_mask = 0; | |
| 562 | m_write.m_name = string; | |
| 563 | m_write.set_tag(devconfig, tag); | |
| 564 | m_wdevice64 = func; | |
| 443 | 565 | } |
| 444 | 566 | |
| 445 | 567 | |
| r8806 | r8807 | |
| 450 | 572 | } |
| 451 | 573 | |
| 452 | 574 | |
| 575 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, read64_proto_delegate func, UINT64 unitmask) | |
| 576 | { | |
| 577 | assert(!func.isnull()); | |
| 578 | assert(unitmask_is_appropriate(64, unitmask, func.name())); | |
| 579 | m_read.m_type = (tag == NULL) ? AMH_DRIVER_DELEGATE : AMH_DEVICE_DELEGATE;; | |
| 580 | m_read.m_bits = 64; | |
| 581 | m_read.m_mask = 0; | |
| 582 | m_read.m_name = func.name(); | |
| 583 | m_read.set_tag(devconfig, tag); | |
| 584 | m_rproto64 = func; | |
| 585 | } | |
| 586 | ||
| 587 | ||
| 588 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, write64_proto_delegate func, UINT64 unitmask) | |
| 589 | { | |
| 590 | assert(!func.isnull()); | |
| 591 | assert(unitmask_is_appropriate(64, unitmask, func.name())); | |
| 592 | m_write.m_type = (tag == NULL) ? AMH_DRIVER_DELEGATE : AMH_DEVICE_DELEGATE;; | |
| 593 | m_write.m_bits = 64; | |
| 594 | m_write.m_mask = 0; | |
| 595 | m_write.m_name = func.name(); | |
| 596 | m_write.set_tag(devconfig, tag); | |
| 597 | m_wproto64 = func; | |
| 598 | } | |
| 599 | ||
| 600 | ||
| 601 | void address_map_entry::internal_set_handler(const device_config &devconfig, const char *tag, read64_proto_delegate rfunc, write64_proto_delegate wfunc, UINT64 unitmask) | |
| 602 | { | |
| 603 | internal_set_handler(devconfig, tag, rfunc, unitmask); | |
| 604 | internal_set_handler(devconfig, tag, wfunc, unitmask); | |
| 605 | } | |
| 606 | ||
| 607 | ||
| 453 | 608 | //------------------------------------------------- |
| 454 | 609 | // unitmask_is_appropriate - verify that the |
| 455 | 610 | // provided unitmask is valid and expected |
| r8806 | r8807 | |
| 540 | 695 | : m_spacenum(spacenum), |
| 541 | 696 | m_databits(0xff), |
| 542 | 697 | m_unmapval(0), |
| 543 | m_globalmask(0), | |
| 544 | m_entrylist(NULL), | |
| 545 | m_tailptr(&m_entrylist) | |
| 698 | m_globalmask(0) | |
| 546 | 699 | { |
| 547 | 700 | // get our memory interface |
| 548 | 701 | const device_config_memory_interface *memintf; |
| r8806 | r8807 | |
| 574 | 727 | |
| 575 | 728 | address_map::~address_map() |
| 576 | 729 | { |
| 577 | // free all entries */ | |
| 578 | while (m_entrylist != NULL) | |
| 579 | { | |
| 580 | address_map_entry *entry = m_entrylist; | |
| 581 | m_entrylist = entry->m_next; | |
| 582 | global_free(entry); | |
| 583 | } | |
| 584 | 730 | } |
| 585 | 731 | |
| 586 | 732 | |
| r8806 | r8807 | |
| 621 | 767 | address_map_entry8 *address_map::add(offs_t start, offs_t end, address_map_entry8 *ptr) |
| 622 | 768 | { |
| 623 | 769 | ptr = global_alloc(address_map_entry8(*this, start, end)); |
| 624 | *m_tailptr = ptr; | |
| 625 | m_tailptr = &ptr->m_next; | |
| 770 | m_entrylist.append(*ptr); | |
| 626 | 771 | return ptr; |
| 627 | 772 | } |
| 628 | 773 | |
| r8806 | r8807 | |
| 630 | 775 | address_map_entry16 *address_map::add(offs_t start, offs_t end, address_map_entry16 *ptr) |
| 631 | 776 | { |
| 632 | 777 | ptr = global_alloc(address_map_entry16(*this, start, end)); |
| 633 | *m_tailptr = ptr; | |
| 634 | m_tailptr = &ptr->m_next; | |
| 778 | m_entrylist.append(*ptr); | |
| 635 | 779 | return ptr; |
| 636 | 780 | } |
| 637 | 781 | |
| r8806 | r8807 | |
| 639 | 783 | address_map_entry32 *address_map::add(offs_t start, offs_t end, address_map_entry32 *ptr) |
| 640 | 784 | { |
| 641 | 785 | ptr = global_alloc(address_map_entry32(*this, start, end)); |
| 642 | *m_tailptr = ptr; | |
| 643 | m_tailptr = &ptr->m_next; | |
| 786 | m_entrylist.append(*ptr); | |
| 644 | 787 | return ptr; |
| 645 | 788 | } |
| 646 | 789 | |
| r8806 | r8807 | |
| 648 | 791 | address_map_entry64 *address_map::add(offs_t start, offs_t end, address_map_entry64 *ptr) |
| 649 | 792 | { |
| 650 | 793 | ptr = global_alloc(address_map_entry64(*this, start, end)); |
| 651 | *m_tailptr = ptr; | |
| 652 | m_tailptr = &ptr->m_next; | |
| 794 | m_entrylist.append(*ptr); | |
| 653 | 795 | return ptr; |
| 654 | 796 | } |
| 655 | ||
| 656 | ||
| 657 | ||
| 658 | #if 0 | |
| 659 | ||
| 660 | // old code for reference | |
| 661 | ||
| 662 | /*************************************************************************** | |
| 663 | ADDRESS MAP HELPERS | |
| 664 | ***************************************************************************/ | |
| 665 | ||
| 666 | /*------------------------------------------------- | |
| 667 | map_detokenize - detokenize an array of | |
| 668 | address map tokens | |
| 669 | -------------------------------------------------*/ | |
| 670 | ||
| 671 | #define check_map(field) do { \ | |
| 672 | if (map->field != 0 && map->field != tmap.field) \ | |
| 673 | fatalerror("%s: %s included a mismatched address map (%s %d) for an existing map with %s %d!\n", driver->source_file, driver->name, #field, tmap.field, #field, map->field); \ | |
| 674 | } while (0) | |
| 675 | ||
| 676 | #define check_entry_handler(row) do { \ | |
| 677 | if (entry->row.type != AMH_NONE) \ | |
| 678 | fatalerror("%s: %s AM_RANGE(0x%x, 0x%x) %s handler already set!\n", driver->source_file, driver->name, entry->addrstart, entry->addrend, #row); \ | |
| 679 | } while (0) | |
| 680 | ||
| 681 | #define check_entry_field(field) do { \ | |
| 682 | if (entry->field != 0) \ | |
| 683 | fatalerror("%s: %s AM_RANGE(0x%x, 0x%x) setting %s already set!\n", driver->source_file, driver->name, entry->addrstart, entry->addrend, #field); \ | |
| 684 | } while (0) | |
| 685 | ||
| 686 | static void map_detokenize(memory_private *memdata, address_map *map, const game_driver *driver, const device_config *devconfig, const addrmap_token *tokens) | |
| 687 | { | |
| 688 | address_map_entry **firstentryptr; | |
| 689 | address_map_entry **entryptr; | |
| 690 | address_map_entry *entry; | |
| 691 | address_map tmap = {0}; | |
| 692 | UINT32 entrytype; | |
| 693 | int maptype; | |
| 694 | ||
| 695 | /* check the first token */ | |
| 696 | TOKEN_GET_UINT32_UNPACK3(tokens, entrytype, 8, tmap.spacenum, 8, tmap.databits, 8); | |
| 697 | if (entrytype != ADDRMAP_TOKEN_START) | |
| 698 | fatalerror("%s: %s Address map missing ADDRMAP_TOKEN_START!\n", driver->source_file, driver->name); | |
| 699 | if (tmap.spacenum >= ADDRESS_SPACES) | |
| 700 | fatalerror("%s: %s Invalid address space %d for memory map!\n", driver->source_file, driver->name, tmap.spacenum); | |
| 701 | if (tmap.databits != 8 && tmap.databits != 16 && tmap.databits != 32 && tmap.databits != 64) | |
| 702 | fatalerror("%s: %s Invalid data bits %d for memory map!\n", driver->source_file, driver->name, tmap.databits); | |
| 703 | check_map(spacenum); | |
| 704 | check_map(databits); | |
| 705 | ||
| 706 | /* fill in the map values */ | |
| 707 | map->spacenum = tmap.spacenum; | |
| 708 | map->databits = tmap.databits; | |
| 709 | ||
| 710 | /* find the end of the list */ | |
| 711 | for (entryptr = &map->entrylist; *entryptr != NULL; entryptr = &(*entryptr)->next) ; | |
| 712 | firstentryptr = entryptr; | |
| 713 | entry = NULL; | |
| 714 | ||
| 715 | /* loop over tokens until we hit the end */ | |
| 716 | while (entrytype != ADDRMAP_TOKEN_END) | |
| 717 | { | |
| 718 | /* unpack the token from the first entry */ | |
| 719 | TOKEN_GET_UINT32_UNPACK1(tokens, entrytype, 8); | |
| 720 | switch (entrytype) | |
| 721 | { | |
| 722 | /* end */ | |
| 723 | case ADDRMAP_TOKEN_END: | |
| 724 | break; | |
| 725 | ||
| 726 | /* including */ | |
| 727 | case ADDRMAP_TOKEN_INCLUDE: | |
| 728 | map_detokenize(memdata, map, driver, devconfig, TOKEN_GET_PTR(tokens, tokenptr)); | |
| 729 | for (entryptr = &map->entrylist; *entryptr != NULL; entryptr = &(*entryptr)->next) ; | |
| 730 | entry = NULL; | |
| 731 | break; | |
| 732 | ||
| 733 | /* global flags */ | |
| 734 | case ADDRMAP_TOKEN_GLOBAL_MASK: | |
| 735 | TOKEN_UNGET_UINT32(tokens); | |
| 736 | TOKEN_GET_UINT64_UNPACK2(tokens, entrytype, 8, tmap.globalmask, 32); | |
| 737 | check_map(globalmask); | |
| 738 | map->globalmask = tmap.globalmask; | |
| 739 | break; | |
| 740 | ||
| 741 | case ADDRMAP_TOKEN_UNMAP_VALUE: | |
| 742 | TOKEN_UNGET_UINT32(tokens); | |
| 743 | TOKEN_GET_UINT32_UNPACK2(tokens, entrytype, 8, tmap.unmapval, 1); | |
| 744 | check_map(unmapval); | |
| 745 | map->unmapval = tmap.unmapval; | |
| 746 | break; | |
| 747 | ||
| 748 | /* start a new range */ | |
| 749 | case ADDRMAP_TOKEN_RANGE: | |
| 750 | entry = *entryptr = global_alloc_clear(address_map_entry); | |
| 751 | entryptr = &entry->next; | |
| 752 | TOKEN_GET_UINT64_UNPACK2(tokens, entry->addrstart, 32, entry->addrend, 32); | |
| 753 | break; | |
| 754 | ||
| 755 | case ADDRMAP_TOKEN_MASK: | |
| 756 | check_entry_field(addrmask); | |
| 757 | TOKEN_UNGET_UINT32(tokens); | |
| 758 | TOKEN_GET_UINT64_UNPACK2(tokens, entrytype, 8, entry->addrmask, 32); | |
| 759 | break; | |
| 760 | ||
| 761 | case ADDRMAP_TOKEN_MIRROR: | |
| 762 | check_entry_field(addrmirror); | |
| 763 | TOKEN_UNGET_UINT32(tokens); | |
| 764 | TOKEN_GET_UINT64_UNPACK2(tokens, entrytype, 8, entry->addrmirror, 32); | |
| 765 | if (entry->addrmirror != 0) | |
| 766 | { | |
| 767 | entry->addrstart &= ~entry->addrmirror; | |
| 768 | entry->addrend &= ~entry->addrmirror; | |
| 769 | } | |
| 770 | break; | |
| 771 | ||
| 772 | case ADDRMAP_TOKEN_READ: | |
| 773 | check_entry_handler(read); | |
| 774 | TOKEN_UNGET_UINT32(tokens); | |
| 775 | TOKEN_GET_UINT32_UNPACK4(tokens, entrytype, 8, maptype, 8, entry->read.bits, 8, entry->read.mask, 8); | |
| 776 | entry->read.type = (map_handler_type)maptype; | |
| 777 | if (entry->read.type == AMH_HANDLER || entry->read.type == AMH_DEVICE_HANDLER) | |
| 778 | { | |
| 779 | entry->read.handler.read = TOKEN_GET_PTR(tokens, read); | |
| 780 | entry->read.name = TOKEN_GET_STRING(tokens); | |
| 781 | } | |
| 782 | if (entry->read.type == AMH_DEVICE_HANDLER || entry->read.type == AMH_PORT || entry->read.type == AMH_BANK) | |
| 783 | entry->read.tag = devconfig->siblingtag(entry->read.derived_tag, TOKEN_GET_STRING(tokens)); | |
| 784 | break; | |
| 785 | ||
| 786 | case ADDRMAP_TOKEN_WRITE: | |
| 787 | check_entry_handler(write); | |
| 788 | TOKEN_UNGET_UINT32(tokens); | |
| 789 | TOKEN_GET_UINT32_UNPACK4(tokens, entrytype, 8, maptype, 8, entry->write.bits, 8, entry->write.mask, 8); | |
| 790 | entry->write.type = (map_handler_type)maptype; | |
| 791 | if (entry->write.type == AMH_HANDLER || entry->write.type == AMH_DEVICE_HANDLER) | |
| 792 | { | |
| 793 | entry->write.handler.write = TOKEN_GET_PTR(tokens, write); | |
| 794 | entry->write.name = TOKEN_GET_STRING(tokens); | |
| 795 | } | |
| 796 | if (entry->write.type == AMH_DEVICE_HANDLER || entry->write.type == AMH_PORT || entry->write.type == AMH_BANK) | |
| 797 | entry->write.tag = devconfig->siblingtag(entry->write.derived_tag, TOKEN_GET_STRING(tokens)); | |
| 798 | break; | |
| 799 | ||
| 800 | case ADDRMAP_TOKEN_READWRITE: | |
| 801 | check_entry_handler(read); | |
| 802 | check_entry_handler(write); | |
| 803 | TOKEN_UNGET_UINT32(tokens); | |
| 804 | TOKEN_GET_UINT32_UNPACK4(tokens, entrytype, 8, maptype, 8, entry->read.bits, 8, entry->read.mask, 8); | |
| 805 | entry->write.type = entry->read.type = (map_handler_type)maptype; | |
| 806 | entry->write.bits = entry->read.bits; | |
| 807 | entry->write.mask = entry->read.mask; | |
| 808 | if (entry->read.type == AMH_HANDLER || entry->read.type == AMH_DEVICE_HANDLER) | |
| 809 | { | |
| 810 | entry->read.handler.read = TOKEN_GET_PTR(tokens, read); | |
| 811 | entry->read.name = TOKEN_GET_STRING(tokens); | |
| 812 | entry->write.handler.write = TOKEN_GET_PTR(tokens, write); | |
| 813 | entry->write.name = TOKEN_GET_STRING(tokens); | |
| 814 | } | |
| 815 | if (entry->read.type == AMH_DEVICE_HANDLER || entry->read.type == AMH_PORT || entry->read.type == AMH_BANK) | |
| 816 | { | |
| 817 | const char *basetag = TOKEN_GET_STRING(tokens); | |
| 818 | entry->read.tag = devconfig->siblingtag(entry->read.derived_tag, basetag); | |
| 819 | entry->write.tag = devconfig->siblingtag(entry->write.derived_tag, basetag); | |
| 820 | } | |
| 821 | break; | |
| 822 | ||
| 823 | case ADDRMAP_TOKEN_REGION: | |
| 824 | check_entry_field(region); | |
| 825 | TOKEN_UNGET_UINT32(tokens); | |
| 826 | TOKEN_GET_UINT64_UNPACK2(tokens, entrytype, 8, entry->rgnoffs, 32); | |
| 827 | entry->region = devconfig->siblingtag(entry->region_string, TOKEN_GET_STRING(tokens)); | |
| 828 | break; | |
| 829 | ||
| 830 | case ADDRMAP_TOKEN_SHARE: | |
| 831 | check_entry_field(share); | |
| 832 | entry->share = TOKEN_GET_STRING(tokens); | |
| 833 | if (memdata != NULL) | |
| 834 | memdata->sharemap.add(entry->share, UNMAPPED_SHARE_PTR, FALSE); | |
| 835 | break; | |
| 836 | ||
| 837 | case ADDRMAP_TOKEN_BASEPTR: | |
| 838 | check_entry_field(baseptr); | |
| 839 | entry->baseptr = (void **)TOKEN_GET_PTR(tokens, voidptr); | |
| 840 | break; | |
| 841 | ||
| 842 | case ADDRMAP_TOKEN_BASE_MEMBER: | |
| 843 | check_entry_field(baseptroffs_plus1); | |
| 844 | TOKEN_UNGET_UINT32(tokens); | |
| 845 | TOKEN_GET_UINT32_UNPACK2(tokens, entrytype, 8, entry->baseptroffs_plus1, 24); | |
| 846 | entry->baseptroffs_plus1++; | |
| 847 | break; | |
| 848 | ||
| 849 | case ADDRMAP_TOKEN_BASE_GENERIC: | |
| 850 | check_entry_field(genbaseptroffs_plus1); | |
| 851 | TOKEN_UNGET_UINT32(tokens); | |
| 852 | TOKEN_GET_UINT32_UNPACK2(tokens, entrytype, 8, entry->genbaseptroffs_plus1, 24); | |
| 853 | entry->genbaseptroffs_plus1++; | |
| 854 | break; | |
| 855 | ||
| 856 | case ADDRMAP_TOKEN_SIZEPTR: | |
| 857 | check_entry_field(sizeptr); | |
| 858 | entry->sizeptr = TOKEN_GET_PTR(tokens, sizeptr); | |
| 859 | break; | |
| 860 | ||
| 861 | case ADDRMAP_TOKEN_SIZE_MEMBER: | |
| 862 | check_entry_field(sizeptroffs_plus1); | |
| 863 | TOKEN_UNGET_UINT32(tokens); | |
| 864 | TOKEN_GET_UINT32_UNPACK2(tokens, entrytype, 8, entry->sizeptroffs_plus1, 24); | |
| 865 | entry->sizeptroffs_plus1++; | |
| 866 | break; | |
| 867 | ||
| 868 | case ADDRMAP_TOKEN_SIZE_GENERIC: | |
| 869 | check_entry_field(gensizeptroffs_plus1); | |
| 870 | TOKEN_UNGET_UINT32(tokens); | |
| 871 | TOKEN_GET_UINT32_UNPACK2(tokens, entrytype, 8, entry->gensizeptroffs_plus1, 24); | |
| 872 | entry->gensizeptroffs_plus1++; | |
| 873 | break; | |
| 874 | ||
| 875 | default: | |
| 876 | fatalerror("Invalid token %d in address map\n", entrytype); | |
| 877 | break; | |
| 878 | } | |
| 879 | } | |
| 880 | ||
| 881 | /* post-process to apply the global mask */ | |
| 882 | if (map->globalmask != 0) | |
| 883 | for (entry = map->entrylist; entry != NULL; entry = entry->next) | |
| 884 | { | |
| 885 | entry->addrstart &= map->globalmask; | |
| 886 | entry->addrend &= map->globalmask; | |
| 887 | entry->addrmask &= map->globalmask; | |
| 888 | } | |
| 889 | } | |
| 890 | ||
| 891 | #endif |
| r8806 | r8807 | |
|---|---|---|
| 60 | 60 | AMH_ROM, |
| 61 | 61 | AMH_NOP, |
| 62 | 62 | AMH_UNMAP, |
| 63 | AMH_HANDLER, | |
| 64 | AMH_DEVICE_HANDLER, | |
| 63 | AMH_DRIVER_DELEGATE, | |
| 64 | AMH_DEVICE_DELEGATE, | |
| 65 | AMH_LEGACY_SPACE_HANDLER, | |
| 66 | AMH_LEGACY_DEVICE_HANDLER, | |
| 65 | 67 | AMH_PORT, |
| 66 | 68 | AMH_BANK |
| 67 | 69 | }; |
| r8806 | r8807 | |
| 72 | 74 | // TYPE DEFINITIONS |
| 73 | 75 | //************************************************************************** |
| 74 | 76 | |
| 75 | // address map constructors are functions generated by tokens | |
| 76 | typedef void (*address_map_constructor)(address_map &map, const device_config &devconfig); | |
| 77 | ||
| 78 | ||
| 79 | // read_handler is a union of all the different read handler types | |
| 80 | union read_handler | |
| 81 | { | |
| 82 | genf * generic; // generic function pointer | |
| 83 | read8_space_func shandler8; // 8-bit space read handler | |
| 84 | read16_space_func shandler16; // 16-bit space read handler | |
| 85 | read32_space_func shandler32; // 32-bit space read handler | |
| 86 | read64_space_func shandler64; // 64-bit space read handler | |
| 87 | read8_device_func dhandler8; // 8-bit device read handler | |
| 88 | read16_device_func dhandler16; // 16-bit device read handler | |
| 89 | read32_device_func dhandler32; // 32-bit device read handler | |
| 90 | read64_device_func dhandler64; // 64-bit device read handler | |
| 91 | }; | |
| 92 | ||
| 93 | ||
| 94 | // write_handler is a union of all the different write handler types | |
| 95 | union write_handler | |
| 96 | { | |
| 97 | genf * generic; // generic function pointer | |
| 98 | write8_space_func shandler8; // 8-bit space write handler | |
| 99 | write16_space_func shandler16; // 16-bit space write handler | |
| 100 | write32_space_func shandler32; // 32-bit space write handler | |
| 101 | write64_space_func shandler64; // 64-bit space write handler | |
| 102 | write8_device_func dhandler8; // 8-bit device write handler | |
| 103 | write16_device_func dhandler16; // 16-bit device write handler | |
| 104 | write32_device_func dhandler32; // 32-bit device write handler | |
| 105 | write64_device_func dhandler64; // 64-bit device write handler | |
| 106 | }; | |
| 107 | ||
| 108 | ||
| 109 | // memory_handler is a union of all read and write handler types | |
| 110 | union memory_handler | |
| 111 | { | |
| 112 | genf * generic; // generic function pointer | |
| 113 | read_handler read; // read handler union | |
| 114 | write_handler write; // write handler union | |
| 115 | }; | |
| 116 | ||
| 117 | ||
| 118 | 77 | // address map handler data |
| 119 | 78 | class map_handler_data |
| 120 | 79 | { |
| 121 | 80 | public: |
| 122 | 81 | map_handler_data() |
| 123 | : type(AMH_NONE), | |
| 124 | bits(0), | |
| 125 | mask(0), | |
| 126 | name(NULL), | |
| 127 | tag(NULL) { handler.generic = NULL; } | |
| 82 | : m_type(AMH_NONE), | |
| 83 | m_bits(0), | |
| 84 | m_mask(0), | |
| 85 | m_name(NULL), | |
| 86 | m_tag(NULL) { } | |
| 128 | 87 | |
| 129 | map_handler_type type; // type of the handler | |
| 130 | UINT8 bits; // width of the handler in bits, or 0 for default | |
| 131 | UINT8 mask; // mask for which lanes apply | |
| 132 | memory_handler handler; // a memory handler | |
| 133 | const char * name; // name of the handler | |
| 134 | const char * tag; // tag pointing to a reference | |
| 135 | astring derived_tag; // string used to hold derived names | |
| 88 | map_handler_type m_type; // type of the handler | |
| 89 | UINT8 m_bits; // width of the handler in bits, or 0 for default | |
| 90 | UINT64 m_mask; // mask for which lanes apply | |
| 91 | const char * m_name; // name of the handler | |
| 92 | const char * m_tag; // tag pointing to a reference | |
| 93 | astring m_derived_tag; // string used to hold derived names | |
| 94 | ||
| 95 | void set_tag(const device_config &devconfig, const char *tag); | |
| 136 | 96 | }; |
| 137 | 97 | |
| 138 | 98 | |
| r8806 | r8807 | |
| 145 | 105 | public: |
| 146 | 106 | // construction/destruction |
| 147 | 107 | address_map_entry(address_map &map, offs_t start, offs_t end); |
| 108 | ||
| 109 | // getters | |
| 110 | address_map_entry *next() const { return m_next; } | |
| 148 | 111 | |
| 149 | 112 | // simple inline setters |
| 150 | 113 | void set_mirror(offs_t _mirror) { m_addrmirror = _mirror; } |
| 151 | void set_read_type(map_handler_type _type) { m_read.type = _type; } | |
| 152 | void set_write_type(map_handler_type _type) { m_write.type = _type; } | |
| 114 | void set_read_type(map_handler_type _type) { m_read.m_type = _type; } | |
| 115 | void set_write_type(map_handler_type _type) { m_write.m_type = _type; } | |
| 153 | 116 | void set_region(const char *tag, offs_t offset) { m_region = tag; m_rgnoffs = offset; } |
| 154 | 117 | void set_share(const char *tag) { m_share = tag; } |
| 155 | 118 | void set_sizeptr(size_t *_sizeptr) { m_sizeptr = _sizeptr; } |
| r8806 | r8807 | |
| 172 | 135 | void set_readwrite_bank(const device_config &devconfig, const char *tag); |
| 173 | 136 | |
| 174 | 137 | // public state |
| 175 | address_map_entry * m_next; // pointer to the next entry | |
| 176 | address_map & m_map; // reference to our owning map | |
| 177 | astring m_region_string; // string used to hold derived names | |
| 138 | address_map_entry * m_next; // pointer to the next entry | |
| 139 | address_map & m_map; // reference to our owning map | |
| 140 | astring m_region_string; // string used to hold derived names | |
| 178 | 141 | |
| 179 | offs_t m_addrstart; // start address | |
| 180 | offs_t m_addrend; // end address | |
| 181 | offs_t m_addrmirror; // mirror bits | |
| 182 | offs_t m_addrmask; // mask bits | |
| 183 | map_handler_data m_read; // data for read handler | |
| 184 | map_handler_data m_write; // data for write handler | |
| 185 | const char * m_share; // tag of a shared memory block | |
| 186 | void ** m_baseptr; // receives pointer to memory (optional) | |
| 187 | size_t * m_sizeptr; // receives size of area in bytes (optional) | |
| 188 | UINT32 m_baseptroffs_plus1; // offset of base pointer within driver_data, plus 1 | |
| 189 | UINT32 m_sizeptroffs_plus1; // offset of size pointer within driver_data, plus 1 | |
| 190 | UINT32 m_genbaseptroffs_plus1; // offset of base pointer within generic_pointers, plus 1 | |
| 191 | UINT32 m_gensizeptroffs_plus1; // offset of size pointer within generic_pointers, plus 1 | |
| 192 | const char * m_region; // tag of region containing the memory backing this entry | |
| 193 | offs_t m_rgnoffs; // offset within the region | |
| 142 | // basic information | |
| 143 | offs_t m_addrstart; // start address | |
| 144 | offs_t m_addrend; // end address | |
| 145 | offs_t m_addrmirror; // mirror bits | |
| 146 | offs_t m_addrmask; // mask bits | |
| 147 | map_handler_data m_read; // data for read handler | |
| 148 | map_handler_data m_write; // data for write handler | |
| 149 | const char * m_share; // tag of a shared memory block | |
| 150 | void ** m_baseptr; // receives pointer to memory (optional) | |
| 151 | size_t * m_sizeptr; // receives size of area in bytes (optional) | |
| 152 | UINT32 m_baseptroffs_plus1; // offset of base pointer within driver_data, plus 1 | |
| 153 | UINT32 m_sizeptroffs_plus1; // offset of size pointer within driver_data, plus 1 | |
| 154 | UINT32 m_genbaseptroffs_plus1; // offset of base pointer within generic_pointers, plus 1 | |
| 155 | UINT32 m_gensizeptroffs_plus1; // offset of size pointer within generic_pointers, plus 1 | |
| 156 | const char * m_region; // tag of region containing the memory backing this entry | |
| 157 | offs_t m_rgnoffs; // offset within the region | |
| 194 | 158 | |
| 195 | void * m_memory; // pointer to memory backing this entry | |
| 196 | offs_t m_bytestart; // byte-adjusted start address | |
| 197 | offs_t m_byteend; // byte-adjusted end address | |
| 198 | offs_t m_bytemirror; // byte-adjusted mirror bits | |
| 199 | offs_t m_bytemask; // byte-adjusted mask bits | |
| 159 | // handlers | |
| 160 | read8_proto_delegate m_rproto8; // 8-bit read proto-delegate | |
| 161 | read16_proto_delegate m_rproto16; // 16-bit read proto-delegate | |
| 162 | read32_proto_delegate m_rproto32; // 32-bit read proto-delegate | |
| 163 | read64_proto_delegate m_rproto64; // 64-bit read proto-delegate | |
| 164 | read8_space_func m_rspace8; // 8-bit legacy address space handler | |
| 165 | read16_space_func m_rspace16; // 16-bit legacy address space handler | |
| 166 | read32_space_func m_rspace32; // 32-bit legacy address space handler | |
| 167 | read64_space_func m_rspace64; // 64-bit legacy address space handler | |
| 168 | read8_device_func m_rdevice8; // 8-bit legacy device handler | |
| 169 | read16_device_func m_rdevice16; // 16-bit legacy device handler | |
| 170 | read32_device_func m_rdevice32; // 32-bit legacy device handler | |
| 171 | read64_device_func m_rdevice64; // 64-bit legacy device handler | |
| 172 | write8_proto_delegate m_wproto8; // 8-bit write proto-delegate | |
| 173 | write16_proto_delegate m_wproto16; // 16-bit write proto-delegate | |
| 174 | write32_proto_delegate m_wproto32; // 32-bit write proto-delegate | |
| 175 | write64_proto_delegate m_wproto64; // 64-bit write proto-delegate | |
| 176 | write8_space_func m_wspace8; // 8-bit legacy address space handler | |
| 177 | write16_space_func m_wspace16; // 16-bit legacy address space handler | |
| 178 | write32_space_func m_wspace32; // 32-bit legacy address space handler | |
| 179 | write64_space_func m_wspace64; // 64-bit legacy address space handler | |
| 180 | write8_device_func m_wdevice8; // 8-bit legacy device handler | |
| 181 | write16_device_func m_wdevice16; // 16-bit legacy device handler | |
| 182 | write32_device_func m_wdevice32; // 32-bit legacy device handler | |
| 183 | write64_device_func m_wdevice64; // 64-bit legacy device handler | |
| 200 | 184 | |
| 185 | // information used during processing | |
| 186 | void * m_memory; // pointer to memory backing this entry | |
| 187 | offs_t m_bytestart; // byte-adjusted start address | |
| 188 | offs_t m_byteend; // byte-adjusted end address | |
| 189 | offs_t m_bytemirror; // byte-adjusted mirror bits | |
| 190 | offs_t m_bytemask; // byte-adjusted mask bits | |
| 191 | ||
| 201 | 192 | protected: |
| 202 | 193 | // internal base pointer setting (derived classes provide typed versions) |
| 203 | 194 | void internal_set_baseptr(void **_baseptr) { m_baseptr = _baseptr; } |
| r8806 | r8807 | |
| 205 | 196 | // internal handler setters for 8-bit functions |
| 206 | 197 | void internal_set_handler(read8_space_func func, const char *string, UINT64 mask); |
| 207 | 198 | void internal_set_handler(write8_space_func func, const char *string, UINT64 mask); |
| 208 | void internal_set_handler(read8_space_func rfunc, const char *rstring,write8_space_func wfunc, const char *wstring, UINT64 mask); | |
| 199 | void internal_set_handler(read8_space_func rfunc, const char *rstring, write8_space_func wfunc, const char *wstring, UINT64 mask); | |
| 209 | 200 | void internal_set_handler(const device_config &devconfig, const char *tag, read8_device_func func, const char *string, UINT64 mask); |
| 210 | 201 | void internal_set_handler(const device_config &devconfig, const char *tag, write8_device_func func, const char *string, UINT64 mask); |
| 211 | 202 | void internal_set_handler(const device_config &devconfig, const char *tag, read8_device_func rfunc, const char *rstring, write8_device_func wfunc, const char *wstring, UINT64 mask); |
| 203 | void internal_set_handler(const device_config &devconfig, const char *tag, read8_proto_delegate func, UINT64 mask); | |
| 204 | void internal_set_handler(const device_config &devconfig, const char *tag, write8_proto_delegate func, UINT64 mask); | |
| 205 | void internal_set_handler(const device_config &devconfig, const char *tag, read8_proto_delegate rfunc, write8_proto_delegate wfunc, UINT64 mask); | |
| 212 | 206 | |
| 213 | 207 | // internal handler setters for 16-bit functions |
| 214 | 208 | void internal_set_handler(read16_space_func func, const char *string, UINT64 mask); |
| r8806 | r8807 | |
| 217 | 211 | void internal_set_handler(const device_config &devconfig, const char *tag, read16_device_func func, const char *string, UINT64 mask); |
| 218 | 212 | void internal_set_handler(const device_config &devconfig, const char *tag, write16_device_func func, const char *string, UINT64 mask); |
| 219 | 213 | void internal_set_handler(const device_config &devconfig, const char *tag, read16_device_func rfunc, const char *rstring, write16_device_func wfunc, const char *wstring, UINT64 mask); |
| 214 | void internal_set_handler(const device_config &devconfig, const char *tag, read16_proto_delegate func, UINT64 mask); | |
| 215 | void internal_set_handler(const device_config &devconfig, const char *tag, write16_proto_delegate func, UINT64 mask); | |
| 216 | void internal_set_handler(const device_config &devconfig, const char *tag, read16_proto_delegate rfunc, write16_proto_delegate wfunc, UINT64 mask); | |
| 220 | 217 | |
| 221 | 218 | // internal handler setters for 32-bit functions |
| 222 | 219 | void internal_set_handler(read32_space_func func, const char *string, UINT64 mask); |
| r8806 | r8807 | |
| 225 | 222 | void internal_set_handler(const device_config &devconfig, const char *tag, read32_device_func func, const char *string, UINT64 mask); |
| 226 | 223 | void internal_set_handler(const device_config &devconfig, const char *tag, write32_device_func func, const char *string, UINT64 mask); |
| 227 | 224 | void internal_set_handler(const device_config &devconfig, const char *tag, read32_device_func rfunc, const char *rstring, write32_device_func wfunc, const char *wstring, UINT64 mask); |
| 225 | void internal_set_handler(const device_config &devconfig, const char *tag, read32_proto_delegate func, UINT64 mask); | |
| 226 | void internal_set_handler(const device_config &devconfig, const char *tag, write32_proto_delegate func, UINT64 mask); | |
| 227 | void internal_set_handler(const device_config &devconfig, const char *tag, read32_proto_delegate rfunc, write32_proto_delegate wfunc, UINT64 mask); | |
| 228 | 228 | |
| 229 | 229 | // internal handler setters for 64-bit functions |
| 230 | 230 | void internal_set_handler(read64_space_func func, const char *string, UINT64 mask); |
| r8806 | r8807 | |
| 233 | 233 | void internal_set_handler(const device_config &devconfig, const char *tag, read64_device_func func, const char *string, UINT64 mask); |
| 234 | 234 | void internal_set_handler(const device_config &devconfig, const char *tag, write64_device_func func, const char *string, UINT64 mask); |
| 235 | 235 | void internal_set_handler(const device_config &devconfig, const char *tag, read64_device_func rfunc, const char *rstring, write64_device_func wfunc, const char *wstring, UINT64 mask); |
| 236 | void internal_set_handler(const device_config &devconfig, const char *tag, read64_proto_delegate func, UINT64 mask); | |
| 237 | void internal_set_handler(const device_config &devconfig, const char *tag, write64_proto_delegate func, UINT64 mask); | |
| 238 | void internal_set_handler(const device_config &devconfig, const char *tag, read64_proto_delegate rfunc, write64_proto_delegate wfunc, UINT64 mask); | |
| 236 | 239 | |
| 237 | 240 | private: |
| 238 | 241 | // helper functions |
| r8806 | r8807 | |
| 257 | 260 | void set_handler(const device_config &devconfig, const char *tag, read8_device_func func, const char *string) { internal_set_handler(devconfig, tag, func, string, 0); } |
| 258 | 261 | void set_handler(const device_config &devconfig, const char *tag, write8_device_func func, const char *string) { internal_set_handler(devconfig, tag, func, string, 0); } |
| 259 | 262 | void set_handler(const device_config &devconfig, const char *tag, read8_device_func rfunc, const char *rstring, write8_device_func wfunc, const char *wstring) { internal_set_handler(devconfig, tag, rfunc, rstring, wfunc, wstring, 0); } |
| 263 | void set_handler(const device_config &devconfig, const char *tag, read8_proto_delegate func) { internal_set_handler(devconfig, tag, func, 0); } | |
| 264 | void set_handler(const device_config &devconfig, const char *tag, write8_proto_delegate func) { internal_set_handler(devconfig, tag, func, 0); } | |
| 265 | void set_handler(const device_config &devconfig, const char *tag, read8_proto_delegate rfunc, write8_proto_delegate wfunc) { internal_set_handler(devconfig, tag, rfunc, wfunc, 0); } | |
| 260 | 266 | }; |
| 261 | 267 | |
| 262 | 268 | |
| r8806 | r8807 | |
| 277 | 283 | void set_handler(const device_config &devconfig, const char *tag, read16_device_func func, const char *string) { internal_set_handler(devconfig, tag, func, string, 0); } |
| 278 | 284 | void set_handler(const device_config &devconfig, const char *tag, write16_device_func func, const char *string) { internal_set_handler(devconfig, tag, func, string, 0); } |
| 279 | 285 | void set_handler(const device_config &devconfig, const char *tag, read16_device_func rfunc, const char *rstring, write16_device_func wfunc, const char *wstring) { internal_set_handler(devconfig, tag, rfunc, rstring, wfunc, wstring, 0); } |
| 286 | void set_handler(const device_config &devconfig, const char *tag, read16_proto_delegate func) { internal_set_handler(devconfig, tag, func, 0); } | |
| 287 | void set_handler(const device_config &devconfig, const char *tag, write16_proto_delegate func) { internal_set_handler(devconfig, tag, func, 0); } | |
| 288 | void set_handler(const device_config &devconfig, const char *tag, read16_proto_delegate rfunc, write16_proto_delegate wfunc) { internal_set_handler(devconfig, tag, rfunc, wfunc, 0); } | |
| 280 | 289 | |
| 281 | 290 | // 8-bit handlers |
| 282 | 291 | void set_handler(read8_space_func func, const char *string, UINT16 mask) { internal_set_handler(func, string, mask); } |
| r8806 | r8807 | |
| 285 | 294 | void set_handler(const device_config &devconfig, const char *tag, read8_device_func func, const char *string, UINT16 mask) { internal_set_handler(devconfig, tag, func, string, mask); } |
| 286 | 295 | void set_handler(const device_config &devconfig, const char *tag, write8_device_func func, const char *string, UINT16 mask) { internal_set_handler(devconfig, tag, func, string, mask); } |
| 287 | 296 | void set_handler(const device_config &devconfig, const char *tag, read8_device_func rfunc, const char *rstring, write8_device_func wfunc, const char *wstring, UINT16 mask) { internal_set_handler(devconfig, tag, rfunc, rstring, wfunc, wstring, mask); } |
| 297 | void set_handler(const device_config &devconfig, const char *tag, read8_proto_delegate func, UINT16 mask) { internal_set_handler(devconfig, tag, func, mask); } | |
| 298 | void set_handler(const device_config &devconfig, const char *tag, write8_proto_delegate func, UINT16 mask) { internal_set_handler(devconfig, tag, func, mask); } | |
| 299 | void set_handler(const device_config &devconfig, const char *tag, read8_proto_delegate rfunc, write8_proto_delegate wfunc, UINT16 mask) { internal_set_handler(devconfig, tag, rfunc, wfunc, mask); } | |
| 288 | 300 | }; |
| 289 | 301 | |
| 290 | 302 | |
| r8806 | r8807 | |
| 305 | 317 | void set_handler(const device_config &devconfig, const char *tag, read32_device_func func, const char *string) { internal_set_handler(devconfig, tag, func, string, 0); } |
| 306 | 318 | void set_handler(const device_config &devconfig, const char *tag, write32_device_func func, const char *string) { internal_set_handler(devconfig, tag, func, string, 0); } |
| 307 | 319 | void set_handler(const device_config &devconfig, const char *tag, read32_device_func rfunc, const char *rstring, write32_device_func wfunc, const char *wstring) { internal_set_handler(devconfig, tag, rfunc, rstring, wfunc, wstring, 0); } |
| 320 | void set_handler(const device_config &devconfig, const char *tag, read32_proto_delegate func) { internal_set_handler(devconfig, tag, func, 0); } | |
| 321 | void set_handler(const device_config &devconfig, const char *tag, write32_proto_delegate func) { internal_set_handler(devconfig, tag, func, 0); } | |
| 322 | void set_handler(const device_config &devconfig, const char *tag, read32_proto_delegate rfunc, write32_proto_delegate wfunc) { internal_set_handler(devconfig, tag, rfunc, wfunc, 0); } | |
| 308 | 323 | |
| 309 | 324 | // 16-bit handlers |
| 310 | 325 | void set_handler(read16_space_func func, const char *string, UINT32 mask) { internal_set_handler(func, string, mask); } |
| r8806 | r8807 | |
| 313 | 328 | void set_handler(const device_config &devconfig, const char *tag, read16_device_func func, const char *string, UINT32 mask) { internal_set_handler(devconfig, tag, func, string, mask); } |
| 314 | 329 | void set_handler(const device_config &devconfig, const char *tag, write16_device_func func, const char *string, UINT32 mask) { internal_set_handler(devconfig, tag, func, string, mask); } |
| 315 | 330 | void set_handler(const device_config &devconfig, const char *tag, read16_device_func rfunc, const char *rstring, write16_device_func wfunc, const char *wstring, UINT32 mask) { internal_set_handler(devconfig, tag, rfunc, rstring, wfunc, wstring, mask); } |
| 331 | void set_handler(const device_config &devconfig, const char *tag, read16_proto_delegate func, UINT32 mask) { internal_set_handler(devconfig, tag, func, mask); } | |
| 332 | void set_handler(const device_config &devconfig, const char *tag, write16_proto_delegate func, UINT32 mask) { internal_set_handler(devconfig, tag, func, mask); } | |
| 333 | void set_handler(const device_config &devconfig, const char *tag, read16_proto_delegate rfunc, write16_proto_delegate wfunc, UINT32 mask) { internal_set_handler(devconfig, tag, rfunc, wfunc, mask); } | |
| 316 | 334 | |
| 317 | 335 | // 8-bit handlers |
| 318 | 336 | void set_handler(read8_space_func func, const char *string, UINT32 mask) { internal_set_handler(func, string, mask); } |
| r8806 | r8807 | |
| 321 | 339 | void set_handler(const device_config &devconfig, const char *tag, read8_device_func func, const char *string, UINT32 mask) { internal_set_handler(devconfig, tag, func, string, mask); } |
| 322 | 340 | void set_handler(const device_config &devconfig, const char *tag, write8_device_func func, const char *string, UINT32 mask) { internal_set_handler(devconfig, tag, func, string, mask); } |
| 323 | 341 | void set_handler(const device_config &devconfig, const char *tag, read8_device_func rfunc, const char *rstring, write8_device_func wfunc, const char *wstring, UINT32 mask) { internal_set_handler(devconfig, tag, rfunc, rstring, wfunc, wstring, mask); } |
| 342 | void set_handler(const device_config &devconfig, const char *tag, read8_proto_delegate func, UINT32 mask) { internal_set_handler(devconfig, tag, func, mask); } | |
| 343 | void set_handler(const device_config &devconfig, const char *tag, write8_proto_delegate func, UINT32 mask) { internal_set_handler(devconfig, tag, func, mask); } | |
| 344 | void set_handler(const device_config &devconfig, const char *tag, read8_proto_delegate rfunc, write8_proto_delegate wfunc, UINT32 mask) { internal_set_handler(devconfig, tag, rfunc, wfunc, mask); } | |
| 324 | 345 | }; |
| 325 | 346 | |
| 326 | 347 | |
| r8806 | r8807 | |
| 341 | 362 | void set_handler(const device_config &devconfig, const char *tag, read64_device_func func, const char *string) { internal_set_handler(devconfig, tag, func, string, 0); } |
| 342 | 363 | void set_handler(const device_config &devconfig, const char *tag, write64_device_func func, const char *string) { internal_set_handler(devconfig, tag, func, string, 0); } |
| 343 | 364 | void set_handler(const device_config &devconfig, const char *tag, read64_device_func rfunc, const char *rstring, write64_device_func wfunc, const char *wstring) { internal_set_handler(devconfig, tag, rfunc, rstring, wfunc, wstring, 0); } |
| 365 | void set_handler(const device_config &devconfig, const char *tag, read64_proto_delegate func) { internal_set_handler(devconfig, tag, func, 0); } | |
| 366 | void set_handler(const device_config &devconfig, const char *tag, write64_proto_delegate func) { internal_set_handler(devconfig, tag, func, 0); } | |
| 367 | void set_handler(const device_config &devconfig, const char *tag, read64_proto_delegate rfunc, write64_proto_delegate wfunc) { internal_set_handler(devconfig, tag, rfunc, wfunc, 0); } | |
| 344 | 368 | |
| 345 | 369 | // 32-bit handlers |
| 346 | 370 | void set_handler(read32_space_func func, const char *string, UINT64 mask) { internal_set_handler(func, string, mask); } |
| r8806 | r8807 | |
| 349 | 373 | void set_handler(const device_config &devconfig, const char *tag, read32_device_func func, const char *string, UINT64 mask) { internal_set_handler(devconfig, tag, func, string, mask); } |
| 350 | 374 | void set_handler(const device_config &devconfig, const char *tag, write32_device_func func, const char *string, UINT64 mask) { internal_set_handler(devconfig, tag, func, string, mask); } |
| 351 | 375 | void set_handler(const device_config &devconfig, const char *tag, read32_device_func rfunc, const char *rstring, write32_device_func wfunc, const char *wstring, UINT64 mask) { internal_set_handler(devconfig, tag, rfunc, rstring, wfunc, wstring, mask); } |
| 376 | void set_handler(const device_config &devconfig, const char *tag, read32_proto_delegate func, UINT64 mask) { internal_set_handler(devconfig, tag, func, mask); } | |
| 377 | void set_handler(const device_config &devconfig, const char *tag, write32_proto_delegate func, UINT64 mask) { internal_set_handler(devconfig, tag, func, mask); } | |
| 378 | void set_handler(const device_config &devconfig, const char *tag, read32_proto_delegate rfunc, write32_proto_delegate wfunc, UINT64 mask) { internal_set_handler(devconfig, tag, rfunc, wfunc, mask); } | |
| 352 | 379 | |
| 353 | 380 | // 16-bit handlers |
| 354 | 381 | void set_handler(read16_space_func func, const char *string, UINT64 mask) { internal_set_handler(func, string, mask); } |
| r8806 | r8807 | |
| 357 | 384 | void set_handler(const device_config &devconfig, const char *tag, read16_device_func func, const char *string, UINT64 mask) { internal_set_handler(devconfig, tag, func, string, mask); } |
| 358 | 385 | void set_handler(const device_config &devconfig, const char *tag, write16_device_func func, const char *string, UINT64 mask) { internal_set_handler(devconfig, tag, func, string, mask); } |
| 359 | 386 | void set_handler(const device_config &devconfig, const char *tag, read16_device_func rfunc, const char *rstring, write16_device_func wfunc, const char *wstring, UINT64 mask) { internal_set_handler(devconfig, tag, rfunc, rstring, wfunc, wstring, mask); } |
| 387 | void set_handler(const device_config &devconfig, const char *tag, read16_proto_delegate func, UINT64 mask) { internal_set_handler(devconfig, tag, func, mask); } | |
| 388 | void set_handler(const device_config &devconfig, const char *tag, write16_proto_delegate func, UINT64 mask) { internal_set_handler(devconfig, tag, func, mask); } | |
| 389 | void set_handler(const device_config &devconfig, const char *tag, read16_proto_delegate rfunc, write16_proto_delegate wfunc, UINT64 mask) { internal_set_handler(devconfig, tag, rfunc, wfunc, mask); } | |
| 360 | 390 | |
| 361 | 391 | // 8-bit handlers |
| 362 | 392 | void set_handler(read8_space_func func, const char *string, UINT64 mask) { internal_set_handler(func, string, mask); } |
| r8806 | r8807 | |
| 365 | 395 | void set_handler(const device_config &devconfig, const char *tag, read8_device_func func, const char *string, UINT64 mask) { internal_set_handler(devconfig, tag, func, string, mask); } |
| 366 | 396 | void set_handler(const device_config &devconfig, const char *tag, write8_device_func func, const char *string, UINT64 mask) { internal_set_handler(devconfig, tag, func, string, mask); } |
| 367 | 397 | void set_handler(const device_config &devconfig, const char *tag, read8_device_func rfunc, const char *rstring, write8_device_func wfunc, const char *wstring, UINT64 mask) { internal_set_handler(devconfig, tag, rfunc, rstring, wfunc, wstring, mask); } |
| 398 | void set_handler(const device_config &devconfig, const char *tag, read8_proto_delegate func, UINT64 mask) { internal_set_handler(devconfig, tag, func, mask); } | |
| 399 | void set_handler(const device_config &devconfig, const char *tag, write8_proto_delegate func, UINT64 mask) { internal_set_handler(devconfig, tag, func, mask); } | |
| 400 | void set_handler(const device_config &devconfig, const char *tag, read8_proto_delegate rfunc, write8_proto_delegate wfunc, UINT64 mask) { internal_set_handler(devconfig, tag, rfunc, wfunc, mask); } | |
| 368 | 401 | }; |
| 369 | 402 | |
| 370 | 403 | |
| r8806 | r8807 | |
| 396 | 429 | UINT8 m_databits; // data bits represented by the map |
| 397 | 430 | UINT8 m_unmapval; // unmapped memory value |
| 398 | 431 | offs_t m_globalmask; // global mask |
| 399 | address_map_entry * m_entrylist; // list of entries | |
| 400 | ||
| 401 | private: | |
| 402 | // internal data | |
| 403 | address_map_entry ** m_tailptr; | |
| 432 | simple_list<address_map_entry> m_entrylist; // list of entries | |
| 404 | 433 | }; |
| 405 | 434 | |
| 406 | 435 | |
| r8806 | r8807 | |
| 419 | 448 | #define ADDRESS_MAP_START(_name, _space, _bits) \ |
| 420 | 449 | void ADDRESS_MAP_NAME(_name)(address_map &map, const device_config &devconfig) \ |
| 421 | 450 | { \ |
| 451 | typedef read##_bits##_proto_delegate read_proto_delegate; \ | |
| 452 | typedef write##_bits##_proto_delegate write_proto_delegate; \ | |
| 422 | 453 | address_map_entry##_bits *curentry = NULL; \ |
| 423 | 454 | (void)curentry; \ |
| 424 | 455 | map.configure(_space, _bits); \ |
| r8806 | r8807 | |
| 458 | 489 | curentry->set_mirror(_mirror); \ |
| 459 | 490 | |
| 460 | 491 | |
| 461 | // space reads | |
| 492 | // legacy space reads | |
| 462 | 493 | #define AM_READ(_handler) \ |
| 463 | 494 | curentry->set_handler(_handler, #_handler); \ |
| 464 | 495 | |
| r8806 | r8807 | |
| 472 | 503 | curentry->set_handler(_handler, #_handler, _unitmask); \ |
| 473 | 504 | |
| 474 | 505 | |
| 475 | // space writes | |
| 506 | // legacy space writes | |
| 476 | 507 | #define AM_WRITE(_handler) \ |
| 477 | 508 | curentry->set_handler(_handler, #_handler); \ |
| 478 | 509 | |
| r8806 | r8807 | |
| 486 | 517 | curentry->set_handler(_handler, #_handler, _unitmask); \ |
| 487 | 518 | |
| 488 | 519 | |
| 489 | // space reads/writes | |
| 520 | // legacy space reads/writes | |
| 490 | 521 | #define AM_READWRITE(_rhandler, _whandler) \ |
| 491 | 522 | curentry->set_handler(_rhandler, #_rhandler, _whandler, #_whandler); \ |
| 492 | 523 | |
| r8806 | r8807 | |
| 500 | 531 | curentry->set_handler(_rhandler, #_rhandler, _whandler, #_whandler, _unitmask); \ |
| 501 | 532 | |
| 502 | 533 | |
| 503 | // device reads | |
| 534 | // legacy device reads | |
| 504 | 535 | #define AM_DEVREAD(_tag, _handler) \ |
| 505 | 536 | curentry->set_handler(devconfig, _tag, _handler, #_handler); \ |
| 506 | 537 | |
| r8806 | r8807 | |
| 514 | 545 | curentry->set_handler(devconfig, _tag, _handler, #_handler, _unitmask); \ |
| 515 | 546 | |
| 516 | 547 | |
| 517 | // device writes | |
| 548 | // legacy device writes | |
| 518 | 549 | #define AM_DEVWRITE(_tag, _handler) \ |
| 519 | 550 | curentry->set_handler(devconfig, _tag, _handler, #_handler); \ |
| 520 | 551 | |
| r8806 | r8807 | |
| 528 | 559 | curentry->set_handler(devconfig, _tag, _handler, #_handler, _unitmask); \ |
| 529 | 560 | |
| 530 | 561 | |
| 531 | // device reads/writes | |
| 562 | // legacy device reads/writes | |
| 532 | 563 | #define AM_DEVREADWRITE(_tag, _rhandler, _whandler) \ |
| 533 | 564 | curentry->set_handler(devconfig, _tag, _rhandler, #_rhandler, _whandler, #_whandler); \ |
| 534 | 565 | |
| r8806 | r8807 | |
| 542 | 573 | curentry->set_handler(devconfig, _tag, _rhandler, #_rhandler, _whandler, #_whandler, _unitmask); \ |
| 543 | 574 | |
| 544 | 575 | |
| 576 | // driver data reads | |
| 577 | #define AM_READ_MEMBER(_class, _handler) \ | |
| 578 | curentry->set_handler(devconfig, NULL, read_proto_delegate::_create_member<_class, &_class::_handler>(#_class "::" #_handler)); \ | |
| 579 | ||
| 580 | #define AM_READ8_MEMBER(_class, _handler, _unitmask) \ | |
| 581 | curentry->set_handler(devconfig, NULL, read8_proto_delegate::_create_member<_class, &_class::_handler>(#_class "::" #_handler), _unitmask); \ | |
| 582 | ||
| 583 | #define AM_READ16_MEMBER(_class, _handler, _unitmask) \ | |
| 584 | curentry->set_handler(devconfig, NULL, read16_proto_delegate::_create_member<_class, &_class::_handler>(#_class "::" #_handler), _unitmask); \ | |
| 585 | ||
| 586 | #define AM_READ32_MEMBER(_class, _handler, _unitmask) \ | |
| 587 | curentry->set_handler(devconfig, NULL, read32_proto_delegate::_create_member<_class, &_class::_handler>(#_class "::" #_handler), _unitmask); \ | |
| 588 | ||
| 589 | ||
| 590 | // driver data writes | |
| 591 | #define AM_WRITE_MEMBER(_class, _handler) \ | |
| 592 | curentry->set_handler(devconfig, NULL, write_proto_delegate::_create_member<_class, &_class::_handler>(#_class "::" #_handler)); \ | |
| 593 | ||
| 594 | #define AM_WRITE8_MEMBER(_class, _handler, _unitmask) \ | |
| 595 | curentry->set_handler(devconfig, NULL, write8_proto_delegate::_create_member<_class, &_class::_handler>(#_class "::" #_handler), _unitmask); \ | |
| 596 | ||
| 597 | #define AM_WRITE16_MEMBER(_class, _handler, _unitmask) \ | |
| 598 | curentry->set_handler(devconfig, NULL, write16_proto_delegate::_create_member<_class, &_class::_handler>(#_class "::" #_handler), _unitmask); \ | |
| 599 | ||
| 600 | #define AM_WRITE32_MEMBER(_class, _handler, _unitmask) \ | |
| 601 | curentry->set_handler(devconfig, NULL, write32_proto_delegate::_create_member<_class, &_class::_handler>(#_class "::" #_handler), _unitmask); \ | |
| 602 | ||
| 603 | ||
| 604 | // driver data reads/writes | |
| 605 | #define AM_READWRITE_MEMBER(_class, _rhandler, _whandler) \ | |
| 606 | curentry->set_handler(devconfig, NULL, read_proto_delegate::_create_member<_class, &_class::_rhandler>(#_class "::" #_rhandler), write_proto_delegate::_create_member<_class, &_class::_whandler>(#_class "::" #_whandler)); \ | |
| 607 | ||
| 608 | #define AM_READWRITE8_MEMBER(_class, _rhandler, _whandler, _unitmask) \ | |
| 609 | curentry->set_handler(devconfig, NULL, read8_proto_delegate::_create_member<_class, &_class::_rhandler>(#_class "::" #_rhandler), write8_proto_delegate::_create_member<_class, &_class::_whandler>(#_class "::" #_whandler), _unitmask); \ | |
| 610 | ||
| 611 | #define AM_READWRITE16_MEMBER(_class, _rhandler, _whandler, _unitmask) \ | |
| 612 | curentry->set_handler(devconfig, NULL, read16_proto_delegate::_create_member<_class, &_class::_rhandler>(#_class "::" #_rhandler), write16_proto_delegate::_create_member<_class, &_class::_whandler>(#_class "::" #_whandler), _unitmask); \ | |
| 613 | ||
| 614 | #define AM_READWRITE32_MEMBER(_class, _rhandler, _whandler, _unitmask) \ | |
| 615 | curentry->set_handler(devconfig, NULL, read32_proto_delegate::_create_member<_class, &_class::_rhandler>(#_class "::" #_rhandler), write32_proto_delegate::_create_member<_class, &_class::_whandler>(#_class "::" #_whandler), _unitmask); \ | |
| 616 | ||
| 617 | ||
| 618 | // device reads | |
| 619 | #define AM_DEVREAD_MEMBER(_tag, _class, _handler) \ | |
| 620 | curentry->set_handler(devconfig, _tag, read_proto_delegate::_create_member<_class, &_class::_handler>(#_class "::" #_handler)); \ | |
| 621 | ||
| 622 | #define AM_DEVREAD8_MEMBER(_tag, _class, _handler, _unitmask) \ | |
| 623 | curentry->set_handler(devconfig, _tag, read8_proto_delegate::_create_member<_class, &_class::_handler>(#_class "::" #_handler), _unitmask); \ | |
| 624 | ||
| 625 | #define AM_DEVREAD16_MEMBER(_tag, _class, _handler, _unitmask) \ | |
| 626 | curentry->set_handler(devconfig, _tag, read16_proto_delegate::_create_member<_class, &_class::_handler>(#_class "::" #_handler), _unitmask); \ | |
| 627 | ||
| 628 | #define AM_DEVREAD32_MEMBER(_tag, _class, _handler, _unitmask) \ | |
| 629 | curentry->set_handler(devconfig, _tag, read32_proto_delegate::_create_member<_class, &_class::_handler>(#_class "::" #_handler), _unitmask); \ | |
| 630 | ||
| 631 | ||
| 632 | // device writes | |
| 633 | #define AM_DEVWRITE_MEMBER(_tag, _class, _handler) \ | |
| 634 | curentry->set_handler(devconfig, _tag, write_proto_delegate::_create_member<_class, &_class::_handler>(#_class "::" #_handler)); \ | |
| 635 | ||
| 636 | #define AM_DEVWRITE8_MEMBER(_tag, _class, _handler, _unitmask) \ | |
| 637 | curentry->set_handler(devconfig, _tag, write8_proto_delegate::_create_member<_class, &_class::_handler>(#_class "::" #_handler), _unitmask); \ | |
| 638 | ||
| 639 | #define AM_DEVWRITE16_MEMBER(_tag, _class, _handler, _unitmask) \ | |
| 640 | curentry->set_handler(devconfig, _tag, write16_proto_delegate::_create_member<_class, &_class::_handler>(#_class "::" #_handler), _unitmask); \ | |
| 641 | ||
| 642 | #define AM_DEVWRITE32_MEMBER(_tag, _class, _handler, _unitmask) \ | |
| 643 | curentry->set_handler(devconfig, _tag, write32_proto_delegate::_create_member<_class, &_class::_handler>(#_class "::" #_handler), _unitmask); \ | |
| 644 | ||
| 645 | ||
| 646 | // device reads/writes | |
| 647 | #define AM_DEVREADWRITE_MEMBER(_tag, _class, _rhandler, _whandler) \ | |
| 648 | curentry->set_handler(devconfig, _tag, read_proto_delegate::_create_member<_class, &_class::_rhandler>(#_class "::" #_rhandler), write_proto_delegate::_create_member<_class, &_class::_whandler>(#_class "::" #_whandler)); \ | |
| 649 | ||
| 650 | #define AM_DEVREADWRITE8_MEMBER(_tag, _class, _rhandler, _whandler, _unitmask) \ | |
| 651 | curentry->set_handler(devconfig, _tag, read8_proto_delegate::_create_member<_class, &_class::_rhandler>(#_class "::" #_rhandler), write8_proto_delegate::_create_member<_class, &_class::_whandler>(#_class "::" #_whandler), _unitmask); \ | |
| 652 | ||
| 653 | #define AM_DEVREADWRITE16_MEMBER(_tag, _class, _rhandler, _whandler, _unitmask) \ | |
| 654 | curentry->set_handler(devconfig, _tag, read16_proto_delegate::_create_member<_class, &_class::_rhandler>(#_class "::" #_rhandler), write16_proto_delegate::_create_member<_class, &_class::_whandler>(#_class "::" #_whandler), _unitmask); \ | |
| 655 | ||
| 656 | #define AM_DEVREADWRITE32_MEMBER(_tag, _class, _rhandler, _whandler, _unitmask) \ | |
| 657 | curentry->set_handler(devconfig, _tag, read32_proto_delegate::_create_member<_class, &_class::_rhandler>(#_class "::" #_rhandler), write32_proto_delegate::_create_member<_class, &_class::_whandler>(#_class "::" #_whandler), _unitmask); \ | |
| 658 | ||
| 659 | ||
| 545 | 660 | // special-case accesses |
| 546 | 661 | #define AM_ROM \ |
| 547 | 662 | curentry->set_read_type(AMH_ROM); \ |
| r8806 | r8807 | |
| 624 | 739 | #define AM_ROMBANK(_bank) AM_READ_BANK(_bank) |
| 625 | 740 | #define AM_RAMBANK(_bank) AM_READWRITE_BANK(_bank) |
| 626 | 741 | #define AM_RAM_READ(_read) AM_READ(_read) AM_WRITEONLY |
| 742 | #define AM_RAM_READ_MEMBER(_class, _read) AM_READ_MEMBER(_class, _read) AM_WRITEONLY | |
| 627 | 743 | #define AM_RAM_WRITE(_write) AM_READONLY AM_WRITE(_write) |
| 628 | #define AM_RAM_DEVREAD(_tag, _read) AM_DEVREAD(_tag, _read) AM_WRITEONLY | |
| 629 | #define AM_RAM_DEVWRITE(_tag, _write) AM_READONLY AM_DEVWRITE(_tag, _write) | |
| 744 | #define AM_RAM_WRITE_MEMBER(_class, _write) AM_READONLY AM_WRITE_MEMBER(_class, _write) | |
| 745 | #define AM_RAM_DEVREAD(_tag, _read) AM_DEVREAD(_tag, _read) AM_WRITEONLY | |
| 746 | #define AM_RAM_DEVREAD_MEMBER(_tag, _class, _read) AM_DEVREAD_MEMBER(_tag, _class, _read) AM_WRITEONLY | |
| 747 | #define AM_RAM_DEVWRITE(_tag, _write) AM_READONLY AM_DEVWRITE(_tag, _write) | |
| 748 | #define AM_RAM_DEVWRITE_MEMBER(_tag, _class, _write) AM_READONLY AM_DEVWRITE_MEMBER(_tag, _class, _write) | |
| 630 | 749 | |
| 631 | 750 | #define AM_BASE_SIZE_MEMBER(_struct, _base, _size) AM_BASE_MEMBER(_struct, _base) AM_SIZE_MEMBER(_struct, _size) |
| 632 | 751 | #define AM_BASE_SIZE_GENERIC(_member) AM_BASE_GENERIC(_member) AM_SIZE_GENERIC(_member) |
| 633 | 752 | |
| 634 | 753 | |
| 754 | ||
| 755 | //************************************************************************** | |
| 756 | // GLOBAL VARIABLES | |
| 757 | //************************************************************************** | |
| 758 | ||
| 759 | // use this to refer to the owning device when providing a device tag | |
| 760 | static const char DEVICE_SELF[] = ""; | |
| 761 | ||
| 762 | ||
| 635 | 763 | #endif /* __ADDRMAP_H__ */ |
| r0 | r8807 | |
|---|---|---|
| 1 | /*************************************************************************** | |
| 2 | ||
| 3 | delegate.c | |
| 4 | ||
| 5 | Templates and classes to enable delegates for callbacks. | |
| 6 | ||
| 7 | **************************************************************************** | |
| 8 | ||
| 9 | Copyright Aaron Giles | |
| 10 | All rights reserved. | |
| 11 | ||
| 12 | Redistribution and use in source and binary forms, with or without | |
| 13 | modification, are permitted provided that the following conditions are | |
| 14 | met: | |
| 15 | ||
| 16 | * Redistributions of source code must retain the above copyright | |
| 17 | notice, this list of conditions and the following disclaimer. | |
| 18 | * Redistributions in binary form must reproduce the above copyright | |
| 19 | notice, this list of conditions and the following disclaimer in | |
| 20 | the documentation and/or other materials provided with the | |
| 21 | distribution. | |
| 22 | * Neither the name 'MAME' nor the names of its contributors may be | |
| 23 | used to endorse or promote products derived from this software | |
| 24 | without specific prior written permission. | |
| 25 | ||
| 26 | THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR | |
| 27 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 28 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| 29 | DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, | |
| 30 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 31 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| 32 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 33 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
| 34 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | |
| 35 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
| 36 | POSSIBILITY OF SUCH DAMAGE. | |
| 37 | ||
| 38 | ***************************************************************************/ | |
| 39 | ||
| 40 | #include "emucore.h" | |
| 41 | #include "delegate.h" | |
| 42 | ||
| 43 | ||
| 44 | //************************************************************************** | |
| 45 | // BINDABLE OBJECT | |
| 46 | //************************************************************************** | |
| 47 | ||
| 48 | //------------------------------------------------- | |
| 49 | // bindable_object - constructor | |
| 50 | //------------------------------------------------- | |
| 51 | ||
| 52 | bindable_object::bindable_object() | |
| 53 | { | |
| 54 | } | |
| 55 | ||
| 56 | ||
| 57 | //------------------------------------------------- | |
| 58 | // ~bindable_object - destructor | |
| 59 | //------------------------------------------------- | |
| 60 | ||
| 61 | bindable_object::~bindable_object() | |
| 62 | { | |
| 63 | } | |
| 64 | ||
| 65 | ||
| 66 | ||
| 67 | //************************************************************************** | |
| 68 | // INTERNAL DELEGATE HELPERS | |
| 69 | //************************************************************************** | |
| 70 | ||
| 71 | #if (USE_DELEGATE_TYPE == DELEGATE_TYPE_INTERNAL) | |
| 72 | ||
| 73 | // NULL structure used in dummy constructor | |
| 74 | delegate_gcc_mfp_internal delegate_gcc_mfp_null; | |
| 75 | ||
| 76 | ||
| 77 | //------------------------------------------------- | |
| 78 | // delegate_convert_raw - given an object and | |
| 79 | // an raw function, adjust the object base and | |
| 80 | // return the actual final code pointer | |
| 81 | //------------------------------------------------- | |
| 82 | ||
| 83 | delegate_generic_function delegate_convert_raw(delegate_generic_class *&object, delegate_gcc_mfp_internal &mfp) | |
| 84 | { | |
| 85 | // apply the "this" delta to the object first | |
| 86 | object = reinterpret_cast<delegate_generic_class *>(reinterpret_cast<UINT8 *>(object) + mfp.this_delta); | |
| 87 | ||
| 88 | // if the low bit of the vtable index is clear, then it is just a raw function pointer | |
| 89 | if (!(mfp.u.vtable_index & 1)) | |
| 90 | return mfp.u.funcptr; | |
| 91 | ||
| 92 | // otherwise, it is the byte index into the vtable where the actual function lives | |
| 93 | UINT8 *vtable_base = *reinterpret_cast<UINT8 **>(object); | |
| 94 | return *reinterpret_cast<delegate_generic_function *>(vtable_base + mfp.u.vtable_index - 1); | |
| 95 | } | |
| 96 | ||
| 97 | #endif |
| r0 | r8807 | |
|---|---|---|
| 1 | /*************************************************************************** | |
| 2 | ||
| 3 | delegate.h | |
| 4 | ||
| 5 | Templates and classes to enable delegates for callbacks. | |
| 6 | ||
| 7 | **************************************************************************** | |
| 8 | ||
| 9 | Copyright Aaron Giles | |
| 10 | All rights reserved. | |
| 11 | ||
| 12 | Redistribution and use in source and binary forms, with or without | |
| 13 | modification, are permitted provided that the following conditions are | |
| 14 | met: | |
| 15 | ||
| 16 | * Redistributions of source code must retain the above copyright | |
| 17 | notice, this list of conditions and the following disclaimer. | |
| 18 | * Redistributions in binary form must reproduce the above copyright | |
| 19 | notice, this list of conditions and the following disclaimer in | |
| 20 | the documentation and/or other materials provided with the | |
| 21 | distribution. | |
| 22 | * Neither the name 'MAME' nor the names of its contributors may be | |
| 23 | used to endorse or promote products derived from this software | |
| 24 | without specific prior written permission. | |
| 25 | ||
| 26 | THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR | |
| 27 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 28 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| 29 | DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, | |
| 30 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 31 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| 32 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 33 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
| 34 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | |
| 35 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
| 36 | POSSIBILITY OF SUCH DAMAGE. | |
| 37 | ||
| 38 | **************************************************************************** | |
| 39 | ||
| 40 | There are many implementations of delegate-like functionality for | |
| 41 | C++ code, but none of them is a perfect drop-in fit for use in MAME. | |
| 42 | In order to be useful in MAME, we need the following properties: | |
| 43 | ||
| 44 | * No significant overhead; we want to use these for memory | |
| 45 | accessors, and memory accessor overhead is already the dominant | |
| 46 | performance aspect for most drivers. | |
| 47 | ||
| 48 | * Existing static functions need to be bound with an additional | |
| 49 | pointer parameter as the first argument. All existing | |
| 50 | implementations that allow static function binding assume the | |
| 51 | same signature as the member functions. | |
| 52 | ||
| 53 | * We must be able to bind the function separately from the | |
| 54 | object. This is to allow configurations to bind functions | |
| 55 | before the objects are created. | |
| 56 | ||
| 57 | Thus, the implementations below are based on existing works but are | |
| 58 | really a new implementation that is specific to MAME. | |
| 59 | ||
| 60 | -------------------------------------------------------------------- | |
| 61 | ||
| 62 | The "compatible" version of delegates is based on an implementation | |
| 63 | from Sergey Ryazanov, found here: | |
| 64 | ||
| 65 | http://www.codeproject.com/KB/cpp/ImpossiblyFastCppDelegate.aspx | |
| 66 | ||
| 67 | These delegates essentially generate a templated static stub function | |
| 68 | for each target function. The static function takes the first | |
| 69 | parameter, uses it as the object pointer, and calls through the | |
| 70 | member function. For static functions, the stub is compatible with | |
| 71 | the signature of a static function, so we just set the stub directly. | |
| 72 | ||
| 73 | Pros: | |
| 74 | * should work with any modern compiler | |
| 75 | * static bindings are just as fast as direct calls | |
| 76 | ||
| 77 | Cons: | |
| 78 | * lots of little stub functions generated | |
| 79 | * double-hops on member function calls means more overhead | |
| 80 | * calling through stub functions repackages parameters | |
| 81 | ||
| 82 | -------------------------------------------------------------------- | |
| 83 | ||
| 84 | The "internal" version of delegates makes use of the internal | |
| 85 | structure of member function pointers in order to convert them at | |
| 86 | binding time into simple static function pointers. This only works | |
| 87 | on platforms where object->func(p1, p2) is equivalent in calling | |
| 88 | convention to func(object, p1, p2). | |
| 89 | ||
| 90 | Most of the information on how this works comes from Don Clugston | |
| 91 | in this article: | |
| 92 | ||
| 93 | http://www.codeproject.com/KB/cpp/FastDelegate.aspx | |
| 94 | ||
| 95 | Pros: | |
| 96 | * as fast as a standard function call in static and member cases | |
| 97 | * no stub functions or double-hops needed | |
| 98 | ||
| 99 | Cons: | |
| 100 | * requires internal knowledge of the member function pointer | |
| 101 | * only works for GCC (for now; MSVC info is also readily available) | |
| 102 | ||
| 103 | ***************************************************************************/ | |
| 104 | ||
| 105 | #pragma once | |
| 106 | ||
| 107 | #ifndef __DELEGATE_H__ | |
| 108 | #define __DELEGATE_H__ | |
| 109 | ||
| 110 | ||
| 111 | //************************************************************************** | |
| 112 | // MACROS | |
| 113 | //************************************************************************** | |
| 114 | ||
| 115 | // types of delegates supported | |
| 116 | #define DELEGATE_TYPE_COMPATIBLE 0 | |
| 117 | #define DELEGATE_TYPE_INTERNAL 1 | |
| 118 | ||
| 119 | // select which one we will be using | |
| 120 | #if defined(__GNUC__) | |
| 121 | #define USE_DELEGATE_TYPE DELEGATE_TYPE_INTERNAL | |
| 122 | #else | |
| 123 | #define USE_DELEGATE_TYPE DELEGATE_TYPE_COMPATIBLE | |
| 124 | #endif | |
| 125 | ||
| 126 | // nicer macros to hide the template gobblety-gook and to pass the names | |
| 127 | #define create_member_name(_class, _member, _name) _create_member<_class, &_class::_member>(_name) | |
| 128 | #define create_member(_class, _member) _create_member<_class, &_class::_member>(#_class "::" #_member) | |
| 129 | #define create_static(_class, _func) _crate_static<_class, &_func>(#_func) | |
| 130 | ||
| 131 | ||
| 132 | ||
| 133 | //************************************************************************** | |
| 134 | // HELPER CLASSES | |
| 135 | //************************************************************************** | |
| 136 | ||
| 137 | // ======================> generic_class | |
| 138 | ||
| 139 | // define a dummy generic class that is just straight single-inheritance | |
| 140 | #ifdef _MSC_VER | |
| 141 | class __single_inheritance generic_class; | |
| 142 | class delegate_generic_class { }; | |
| 143 | #else | |
| 144 | class delegate_generic_class; | |
| 145 | #endif | |
| 146 | ||
| 147 | ||
| 148 | // ======================> bindable_object | |
| 149 | ||
| 150 | // define a bindable_object base class that must be at the root of any object | |
| 151 | // hierarchy which intends to do late binding | |
| 152 | class bindable_object | |
| 153 | { | |
| 154 | public: | |
| 155 | // virtual destructor to ensure this is a polymorphic class | |
| 156 | bindable_object(); | |
| 157 | virtual ~bindable_object(); | |
| 158 | }; | |
| 159 | ||
| 160 | // define a deferred cast helper function that does a proper dynamic_cast | |
| 161 | // from a bindable_object to the target class, and returns a delegate_generic_class | |
| 162 | template<class _TargetClass> | |
| 163 | static delegate_generic_class *deferred_cast(bindable_object &object) | |
| 164 | { | |
| 165 | return reinterpret_cast<delegate_generic_class *>(dynamic_cast<_TargetClass *>(&object)); | |
| 166 | } | |
| 167 | ||
| 168 | // we store pointers to these deferred casting helpers, so make a friendly type for it | |
| 169 | typedef delegate_generic_class *(*deferred_cast_func)(bindable_object &object); | |
| 170 | ||
| 171 | ||
| 172 | // ======================> delegate_base | |
| 173 | ||
| 174 | // simple base class for all delegates to derive from; it is explicitly | |
| 175 | // polymorphic so that a delegate_base * can be used as a lowest-common | |
| 176 | // denominator, and then downcast to the appropriate type with proper | |
| 177 | // type checking | |
| 178 | class delegate_base | |
| 179 | { | |
| 180 | public: | |
| 181 | delegate_base(deferred_cast_func caster, const char *name) | |
| 182 | : m_caster(caster), | |
| 183 | m_name(name) { } | |
| 184 | ||
| 185 | virtual ~delegate_base() { } | |
| 186 | ||
| 187 | // getters | |
| 188 | bool isnull() const { return (m_caster == NULL); } | |
| 189 | bool valid_target(bindable_object &object) const { return ((*m_caster)(object) != NULL); } | |
| 190 | const char *name() const { return m_name; } | |
| 191 | ||
| 192 | protected: | |
| 193 | deferred_cast_func m_caster; // pointer to helper function that does the cast | |
| 194 | const char * m_name; // name string | |
| 195 | }; | |
| 196 | ||
| 197 | ||
| 198 | ||
| 199 | //************************************************************************** | |
| 200 | // COMPATIBLE DELEGATES | |
| 201 | //************************************************************************** | |
| 202 | ||
| 203 | #if (USE_DELEGATE_TYPE == DELEGATE_TYPE_COMPATIBLE) | |
| 204 | ||
| 205 | // ======================> proto_delegate_0param | |
| 206 | ||
| 207 | template<typename _ReturnType> | |
| 208 | class proto_delegate_0param : public delegate_base | |
| 209 | { | |
| 210 | protected: | |
| 211 | // pointer to a static version of the function which takes the object as a first parameter | |
| 212 | typedef _ReturnType (*static_func)(delegate_generic_class *); | |
| 213 | ||
| 214 | public: | |
| 215 | // constructors | |
| 216 | proto_delegate_0param(static_func function = NULL, deferred_cast_func caster = NULL, const char *name = NULL) | |
| 217 | : delegate_base(caster, name), | |
| 218 | m_function(function) { } | |
| 219 | ||
| 220 | proto_delegate_0param(const proto_delegate_0param &proto) | |
| 221 | : delegate_base(proto.m_caster, proto.m_name), | |
| 222 | m_function(proto.m_function) { } | |
| 223 | ||
| 224 | // create a member function proto-delegate | |
| 225 | template<class _FunctionClass, _ReturnType (_FunctionClass::*_FunctionPtr)()> | |
| 226 | static proto_delegate_0param _create_member(const char *name = NULL) | |
| 227 | { | |
| 228 | return proto_delegate_0param(&method_stub<_FunctionClass, _FunctionPtr>, &deferred_cast<_FunctionClass>, name); | |
| 229 | } | |
| 230 | ||
| 231 | // create a static function proto-delegate | |
| 232 | template<class _FunctionClass, _ReturnType (*_FunctionPtr)(_FunctionClass *)> | |
| 233 | static proto_delegate_0param _create_static(const char *name = NULL) | |
| 234 | { | |
| 235 | return proto_delegate_0param(reinterpret_cast<static_func>(_FunctionPtr), &deferred_cast<_FunctionClass>, name); | |
| 236 | } | |
| 237 | ||
| 238 | // equality testing | |
| 239 | bool operator==(const proto_delegate_0param &rhs) const | |
| 240 | { | |
| 241 | return (m_function == rhs.m_function && m_caster == rhs.m_caster); | |
| 242 | } | |
| 243 | ||
| 244 | protected: | |
| 245 | // helper stub that calls the member function | |
| 246 | template<class _FunctionClass, _ReturnType (_FunctionClass::*_FunctionPtr)()> | |
| 247 | static _ReturnType method_stub(delegate_generic_class *object_ptr) | |
| 248 | { | |
| 249 | _FunctionClass *p = reinterpret_cast<_FunctionClass *>(object_ptr); | |
| 250 | return (p->*_FunctionPtr)(); | |
| 251 | } | |
| 252 | ||
| 253 | // internal state | |
| 254 | static_func m_function; // pointer to the stub or static function | |
| 255 | }; | |
| 256 | ||
| 257 | ||
| 258 | // ======================> delegate_0param | |
| 259 | ||
| 260 | template<typename _ReturnType> | |
| 261 | class delegate_0param : public proto_delegate_0param<_ReturnType> | |
| 262 | { | |
| 263 | typedef proto_delegate_0param<_ReturnType> proto_base; | |
| 264 | ||
| 265 | using delegate_base::m_caster; | |
| 266 | using proto_base::m_function; | |
| 267 | ||
| 268 | public: | |
| 269 | // constructors | |
| 270 | delegate_0param() | |
| 271 | : m_object(NULL) { } | |
| 272 | ||
| 273 | delegate_0param(proto_base proto) | |
| 274 | : proto_delegate_0param<_ReturnType>(proto), | |
| 275 | m_object(NULL) { } | |
| 276 | ||
| 277 | delegate_0param(proto_base proto, bindable_object &object) | |
| 278 | : proto_delegate_0param<_ReturnType>(proto), | |
| 279 | m_object((*m_caster)(object)) { } | |
| 280 | ||
| 281 | // bind the actual object | |
| 282 | void bind(bindable_object &object) { m_object = (*m_caster)(object); } | |
| 283 | ||
| 284 | // call the function | |
| 285 | _ReturnType operator()() const { return (*m_function)(m_object); } | |
| 286 | ||
| 287 | // testing | |
| 288 | bool has_object() const { return (m_object != NULL); } | |
| 289 | bool operator==(const delegate_0param &rhs) const { return (m_object == rhs.m_object && proto_base::operator==(rhs)); } | |
| 290 | ||
| 291 | protected: | |
| 292 | // internal state | |
| 293 | delegate_generic_class *m_object; // pointer to the post-cast object | |
| 294 | }; | |
| 295 | ||
| 296 | ||
| 297 | // ======================> proto_delegate_1param | |
| 298 | ||
| 299 | template<typename _ReturnType, typename _P1Type> | |
| 300 | class proto_delegate_1param : public delegate_base | |
| 301 | { | |
| 302 | protected: | |
| 303 | // pointer to a static version of the function which takes the object as a first parameter | |
| 304 | typedef _ReturnType (*static_func)(delegate_generic_class *, _P1Type); | |
| 305 | ||
| 306 | public: | |
| 307 | // constructors | |
| 308 | proto_delegate_1param(static_func function = NULL, deferred_cast_func caster = NULL, const char *name = NULL) | |
| 309 | : delegate_base(caster, name), | |
| 310 | m_function(function) { } | |
| 311 | ||
| 312 | proto_delegate_1param(const proto_delegate_1param &proto) | |
| 313 | : delegate_base(proto.m_caster, proto.m_name), | |
| 314 | m_function(proto.m_function) { } | |
| 315 | ||
| 316 | // create a member function proto-delegate | |
| 317 | template<class _FunctionClass, _ReturnType (_FunctionClass::*_FunctionPtr)(_P1Type)> | |
| 318 | static proto_delegate_1param _create_member(const char *name = NULL) | |
| 319 | { | |
| 320 | return proto_delegate_1param(&method_stub<_FunctionClass, _FunctionPtr>, &deferred_cast<_FunctionClass>, name); | |
| 321 | } | |
| 322 | ||
| 323 | // create a static function proto-delegate | |
| 324 | template<class _FunctionClass, _ReturnType (*_FunctionPtr)(_FunctionClass *, _P1Type)> | |
| 325 | static proto_delegate_1param _create_static(const char *name = NULL) | |
| 326 | { | |
| 327 | return proto_delegate_1param(reinterpret_cast<static_func>(_FunctionPtr), &deferred_cast<_FunctionClass>, name); | |
| 328 | } | |
| 329 | ||
| 330 | // equality testing | |
| 331 | bool operator==(const proto_delegate_1param &rhs) const | |
| 332 | { | |
| 333 | return (m_function == rhs.m_function && m_caster == rhs.m_caster); | |
| 334 | } | |
| 335 | ||
| 336 | protected: | |
| 337 | // helper stub that calls the member function | |
| 338 | template<class _FunctionClass, _ReturnType (_FunctionClass::*_FunctionPtr)(_P1Type)> | |
| 339 | static _ReturnType method_stub(delegate_generic_class *object_ptr, _P1Type p1) | |
| 340 | { | |
| 341 | _FunctionClass *p = reinterpret_cast<_FunctionClass *>(object_ptr); | |
| 342 | return (p->*_FunctionPtr)(p1); | |
| 343 | } | |
| 344 | ||
| 345 | // internal state | |
| 346 | static_func m_function; // pointer to the stub or static function | |
| 347 | }; | |
| 348 | ||
| 349 | ||
| 350 | // ======================> delegate_1param | |
| 351 | ||
| 352 | template<typename _ReturnType, typename _P1Type> | |
| 353 | class delegate_1param : public proto_delegate_1param<_ReturnType, _P1Type> | |
| 354 | { | |
| 355 | typedef proto_delegate_1param<_ReturnType, _P1Type> proto_base; | |
| 356 | ||
| 357 | using delegate_base::m_caster; | |
| 358 | using proto_base::m_function; | |
| 359 | ||
| 360 | public: | |
| 361 | // constructors | |
| 362 | delegate_1param() | |
| 363 | : m_object(NULL) { } | |
| 364 | ||
| 365 | delegate_1param(proto_delegate_1param<_ReturnType, _P1Type> proto) | |
| 366 | : proto_delegate_1param<_ReturnType, _P1Type>(proto), | |
| 367 | m_object(NULL) { } | |
| 368 | ||
| 369 | delegate_1param(proto_delegate_1param<_ReturnType, _P1Type> proto, bindable_object &object) | |
| 370 | : proto_delegate_1param<_ReturnType, _P1Type>(proto), | |
| 371 | m_object((*m_caster)(object)) { } | |
| 372 | ||
| 373 | // bind the actual object | |
| 374 | void bind(bindable_object &object) { m_object = (*m_caster)(object); } | |
| 375 | ||
| 376 | // call the function | |
| 377 | _ReturnType operator()(_P1Type p1) const { return (*m_function)(m_object, p1); } | |
| 378 | ||
| 379 | // testing | |
| 380 | bool has_object() const { return (m_object != NULL); } | |
| 381 | bool operator==(const delegate_1param &rhs) const { return (m_object == rhs.m_object && proto_base::operator==(rhs)); } | |
| 382 | ||
| 383 | protected: | |
| 384 | // internal state | |
| 385 | delegate_generic_class *m_object; // pointer to the post-cast object | |
| 386 | }; | |
| 387 | ||
| 388 | ||
| 389 | // ======================> proto_delegate_2param | |
| 390 | ||
| 391 | template<typename _ReturnType, typename _P1Type, typename _P2Type> | |
| 392 | class proto_delegate_2param : public delegate_base | |
| 393 | { | |
| 394 | protected: | |
| 395 | // pointer to a static version of the function which takes the object as a first parameter | |
| 396 | typedef _ReturnType (*static_func)(delegate_generic_class *, _P1Type, _P2Type); | |
| 397 | ||
| 398 | public: | |
| 399 | // constructors | |
| 400 | proto_delegate_2param(static_func function = NULL, deferred_cast_func caster = NULL, const char *name = NULL) | |
| 401 | : delegate_base(caster, name), | |
| 402 | m_function(function) { } | |
| 403 | ||
| 404 | proto_delegate_2param(const proto_delegate_2param &proto) | |
| 405 | : delegate_base(proto.m_caster, proto.m_name), | |
| 406 | m_function(proto.m_function) { } | |
| 407 | ||
| 408 | // create a member function proto-delegate | |
| 409 | template<class _FunctionClass, _ReturnType (_FunctionClass::*_FunctionPtr)(_P1Type, _P2Type)> | |
| 410 | static proto_delegate_2param _create_member(const char *name = NULL) | |
| 411 | { | |
| 412 | return proto_delegate_2param(&method_stub<_FunctionClass, _FunctionPtr>, &deferred_cast<_FunctionClass>, name); | |
| 413 | } | |
| 414 | ||
| 415 | // create a static function proto-delegate | |
| 416 | template<class _FunctionClass, _ReturnType (*_FunctionPtr)(_FunctionClass *, _P1Type, _P2Type)> | |
| 417 | static proto_delegate_2param _create_static(const char *name = NULL) | |
| 418 | { | |
| 419 | return proto_delegate_2param(reinterpret_cast<static_func>(_FunctionPtr), &deferred_cast<_FunctionClass>, name); | |
| 420 | } | |
| 421 | ||
| 422 | // equality testing | |
| 423 | bool operator==(const proto_delegate_2param &rhs) const | |
| 424 | { | |
| 425 | return (m_function == rhs.m_function && m_caster == rhs.m_caster); | |
| 426 | } | |
| 427 | ||
| 428 | protected: | |
| 429 | // helper stub that calls the member function | |
| 430 | template<class _FunctionClass, _ReturnType (_FunctionClass::*_FunctionPtr)(_P1Type, _P2Type)> | |
| 431 | static _ReturnType method_stub(delegate_generic_class *object_ptr, _P1Type p1, _P2Type p2) | |
| 432 | { | |
| 433 | _FunctionClass *p = reinterpret_cast<_FunctionClass *>(object_ptr); | |
| 434 | return (p->*_FunctionPtr)(p1, p2); | |
| 435 | } | |
| 436 | ||
| 437 | // internal state | |
| 438 | static_func m_function; // pointer to the stub or static function | |
| 439 | }; | |
| 440 | ||
| 441 | ||
| 442 | // ======================> delegate_2param | |
| 443 | ||
| 444 | template<typename _ReturnType, typename _P1Type, typename _P2Type> | |
| 445 | class delegate_2param : public proto_delegate_2param<_ReturnType, _P1Type, _P2Type> | |
| 446 | { | |
| 447 | typedef proto_delegate_2param<_ReturnType, _P1Type, _P2Type> proto_base; | |
| 448 | ||
| 449 | using delegate_base::m_caster; | |
| 450 | using proto_base::m_function; | |
| 451 | ||
| 452 | public: | |
| 453 | // constructors | |
| 454 | delegate_2param() | |
| 455 | : m_object(NULL) { } | |
| 456 | ||
| 457 | delegate_2param(proto_delegate_2param<_ReturnType, _P1Type, _P2Type> proto) | |
| 458 | : proto_delegate_2param<_ReturnType, _P1Type, _P2Type>(proto), | |
| 459 | m_object(NULL) { } | |
| 460 | ||
| 461 | delegate_2param(proto_delegate_2param<_ReturnType, _P1Type, _P2Type> proto, bindable_object &object) | |
| 462 | : proto_delegate_2param<_ReturnType, _P1Type, _P2Type>(proto), | |
| 463 | m_object((*m_caster)(object)) { } | |
| 464 | ||
| 465 | // bind the actual object | |
| 466 | void bind(bindable_object &object) { m_object = (*m_caster)(object); } | |
| 467 | ||
| 468 | // call the function | |
| 469 | _ReturnType operator()(_P1Type p1, _P2Type p2) const { return (*m_function)(m_object, p1, p2); } | |
| 470 | ||
| 471 | // testing | |
| 472 | bool has_object() const { return (m_object != NULL); } | |
| 473 | bool operator==(const delegate_2param &rhs) const { return (m_object == rhs.m_object && proto_base::operator==(rhs)); } | |
| 474 | ||
| 475 | protected: | |
| 476 | // internal state | |
| 477 | delegate_generic_class *m_object; // pointer to the post-cast object | |
| 478 | }; | |
| 479 | ||
| 480 | ||
| 481 | // ======================> proto_delegate_3param | |
| 482 | ||
| 483 | template<typename _ReturnType, typename _P1Type, typename _P2Type, typename _P3Type> | |
| 484 | class proto_delegate_3param : public delegate_base | |
| 485 | { | |
| 486 | protected: | |
| 487 | // pointer to a static version of the function which takes the object as a first parameter | |
| 488 | typedef _ReturnType (*static_func)(delegate_generic_class *, _P1Type, _P2Type, _P3Type); | |
| 489 | ||
| 490 | public: | |
| 491 | // constructors | |
| 492 | proto_delegate_3param(static_func function = NULL, deferred_cast_func caster = NULL, const char *name = NULL) | |
| 493 | : delegate_base(caster, name), | |
| 494 | m_function(function) { } | |
| 495 | ||
| 496 | proto_delegate_3param(const proto_delegate_3param &proto) | |
| 497 | : delegate_base(proto.m_caster, proto.m_name), | |
| 498 | m_function(proto.m_function) { } | |
| 499 | ||
| 500 | // create a member function proto-delegate | |
| 501 | template<class _FunctionClass, _ReturnType (_FunctionClass::*_FunctionPtr)(_P1Type, _P2Type, _P3Type)> | |
| 502 | static proto_delegate_3param _create_member(const char *name = NULL) | |
| 503 | { | |
| 504 | return proto_delegate_3param(&method_stub<_FunctionClass, _FunctionPtr>, &deferred_cast<_FunctionClass>, name); | |
| 505 | } | |
| 506 | ||
| 507 | // create a static function proto-delegate | |
| 508 | template<class _FunctionClass, _ReturnType (*_FunctionPtr)(_FunctionClass *, _P1Type, _P2Type, _P3Type)> | |
| 509 | static proto_delegate_3param _create_static(const char *name = NULL) | |
| 510 | { | |
| 511 | return proto_delegate_3param(reinterpret_cast<static_func>(_FunctionPtr), &deferred_cast<_FunctionClass>, name); | |
| 512 | } | |
| 513 | ||
| 514 | // equality testing | |
| 515 | bool operator==(const proto_delegate_3param &rhs) const | |
| 516 | { | |
| 517 | return (m_function == rhs.m_function && m_caster == rhs.m_caster); | |
| 518 | } | |
| 519 | ||
| 520 | protected: | |
| 521 | // helper stub that calls the member function | |
| 522 | template<class _FunctionClass, _ReturnType (_FunctionClass::*_FunctionPtr)(_P1Type, _P2Type, _P3Type)> | |
| 523 | static _ReturnType method_stub(delegate_generic_class *object_ptr, _P1Type p1, _P2Type p2, _P3Type p3) | |
| 524 | { | |
| 525 | _FunctionClass *p = reinterpret_cast<_FunctionClass *>(object_ptr); | |
| 526 | return (p->*_FunctionPtr)(p1, p2, p3); | |
| 527 | } | |
| 528 | ||
| 529 | // internal state | |
| 530 | static_func m_function; // pointer to the stub or static function | |
| 531 | }; | |
| 532 | ||
| 533 | ||
| 534 | // ======================> delegate_3param | |
| 535 | ||
| 536 | template<typename _ReturnType, typename _P1Type, typename _P2Type, typename _P3Type> | |
| 537 | class delegate_3param : public proto_delegate_3param<_ReturnType, _P1Type, _P2Type, _P3Type> | |
| 538 | { | |
| 539 | typedef proto_delegate_3param<_ReturnType, _P1Type, _P2Type, _P3Type> proto_base; | |
| 540 | ||
| 541 | using delegate_base::m_caster; | |
| 542 | using proto_base::m_function; | |
| 543 | ||
| 544 | public: | |
| 545 | // constructors | |
| 546 | delegate_3param() | |
| 547 | : m_object(NULL) { } | |
| 548 | ||
| 549 | delegate_3param(proto_delegate_3param<_ReturnType, _P1Type, _P2Type, _P3Type> proto) | |
| 550 | : proto_delegate_3param<_ReturnType, _P1Type, _P2Type, _P3Type>(proto), | |
| 551 | m_object(NULL) { } | |
| 552 | ||
| 553 | delegate_3param(proto_delegate_3param<_ReturnType, _P1Type, _P2Type, _P3Type> proto, bindable_object &object) | |
| 554 | : proto_delegate_3param<_ReturnType, _P1Type, _P2Type, _P3Type>(proto), | |
| 555 | m_object((*m_caster)(object)) { } | |
| 556 | ||
| 557 | // bind the actual object | |
| 558 | void bind(bindable_object &object) { m_object = (*m_caster)(object); } | |
| 559 | ||
| 560 | // call the function | |
| 561 | _ReturnType operator()(_P1Type p1, _P2Type p2, _P3Type p3) const { return (*m_function)(m_object, p1, p2, p3); } | |
| 562 | ||
| 563 | // testing | |
| 564 | bool has_object() const { return (m_object != NULL); } | |
| 565 | bool operator==(const delegate_3param &rhs) const { return (m_object == rhs.m_object && proto_base::operator==(rhs)); } | |
| 566 | ||
| 567 | protected: | |
| 568 | // internal state | |
| 569 | delegate_generic_class *m_object; // pointer to the post-cast object | |
| 570 | }; | |
| 571 | ||
| 572 | ||
| 573 | // ======================> proto_delegate_4param | |
| 574 | ||
| 575 | template<typename _ReturnType, typename _P1Type, typename _P2Type, typename _P3Type, typename _P4Type> | |
| 576 | class proto_delegate_4param : public delegate_base | |
| 577 | { | |
| 578 | protected: | |
| 579 | // pointer to a static version of the function which takes the object as a first parameter | |
| 580 | typedef _ReturnType (*static_func)(delegate_generic_class *, _P1Type, _P2Type, _P3Type, _P4Type); | |
| 581 | ||
| 582 | public: | |
| 583 | // constructors | |
| 584 | proto_delegate_4param(static_func function = NULL, deferred_cast_func caster = NULL, const char *name = NULL) | |
| 585 | : delegate_base(caster, name), | |
| 586 | m_function(function) { } | |
| 587 | ||
| 588 | proto_delegate_4param(const proto_delegate_4param &proto) | |
| 589 | : delegate_base(proto.m_caster, proto.m_name), | |
| 590 | m_function(proto.m_function) { } | |
| 591 | ||
| 592 | // create a member function proto-delegate | |
| 593 | template<class _FunctionClass, _ReturnType (_FunctionClass::*_FunctionPtr)(_P1Type, _P2Type, _P3Type, _P4Type)> | |
| 594 | static proto_delegate_4param _create_member(const char *name = NULL) | |
| 595 | { | |
| 596 | return proto_delegate_4param(&method_stub<_FunctionClass, _FunctionPtr>, &deferred_cast<_FunctionClass>, name); | |
| 597 | } | |
| 598 | ||
| 599 | // create a static function proto-delegate | |
| 600 | template<class _FunctionClass, _ReturnType (*_FunctionPtr)(_FunctionClass *, _P1Type, _P2Type, _P3Type, _P4Type)> | |
| 601 | static proto_delegate_4param _create_static(const char *name = NULL) | |
| 602 | { | |
| 603 | return proto_delegate_4param(reinterpret_cast<static_func>(_FunctionPtr), &deferred_cast<_FunctionClass>, name); | |
| 604 | } | |
| 605 | ||
| 606 | // equality testing | |
| 607 | bool operator==(const proto_delegate_4param &rhs) const | |
| 608 | { | |
| 609 | return (m_function == rhs.m_function && m_caster == rhs.m_caster); | |
| 610 | } | |
| 611 | ||
| 612 | protected: | |
| 613 | // helper stub that calls the member function | |
| 614 | template<class _FunctionClass, _ReturnType (_FunctionClass::*_FunctionPtr)(_P1Type, _P2Type, _P3Type, _P4Type)> | |
| 615 | static _ReturnType method_stub(delegate_generic_class *object_ptr, _P1Type p1, _P2Type p2, _P3Type p3, _P4Type p4) | |
| 616 | { | |
| 617 | _FunctionClass *p = reinterpret_cast<_FunctionClass *>(object_ptr); | |
| 618 | return (p->*_FunctionPtr)(p1, p2, p3, p4); | |
| 619 | } | |
| 620 | ||
| 621 | // internal state | |
| 622 | static_func m_function; // pointer to the stub or static function | |
| 623 | }; | |
| 624 | ||
| 625 | ||
| 626 | // ======================> delegate_4param | |
| 627 | ||
| 628 | template<typename _ReturnType, typename _P1Type, typename _P2Type, typename _P3Type, typename _P4Type> | |
| 629 | class delegate_4param : public proto_delegate_4param<_ReturnType, _P1Type, _P2Type, _P3Type, _P4Type> | |
| 630 | { | |
| 631 | typedef proto_delegate_4param<_ReturnType, _P1Type, _P2Type, _P3Type, _P4Type> proto_base; | |
| 632 | ||
| 633 | using delegate_base::m_caster; | |
| 634 | using proto_base::m_function; | |
| 635 | ||
| 636 | public: | |
| 637 | // constructors | |
| 638 | delegate_4param() | |
| 639 | : m_object(NULL) { } | |
| 640 | ||
| 641 | delegate_4param(proto_delegate_4param<_ReturnType, _P1Type, _P2Type, _P3Type, _P4Type> proto) | |
| 642 | : proto_delegate_4param<_ReturnType, _P1Type, _P2Type, _P3Type, _P4Type>(proto), | |
| 643 | m_object(NULL) { } | |
| 644 | ||
| 645 | delegate_4param(proto_delegate_4param<_ReturnType, _P1Type, _P2Type, _P3Type, _P4Type> proto, bindable_object &object) | |
| 646 | : proto_delegate_4param<_ReturnType, _P1Type, _P2Type, _P3Type, _P4Type>(proto), | |
| 647 | m_object((*m_caster)(object)) { } | |
| 648 | ||
| 649 | // bind the actual object | |
| 650 | void bind(bindable_object &object) { m_object = (*m_caster)(object); } | |
| 651 | ||
| 652 | // call the function | |
| 653 | _ReturnType operator()(_P1Type p1, _P2Type p2, _P3Type p3, _P4Type p4) const { return (*m_function)(m_object, p1, p2, p3, p4); } | |
| 654 | ||
| 655 | // testing | |
| 656 | bool has_object() const { return (m_object != NULL); } | |
| 657 | bool operator==(const delegate_4param &rhs) const { return (m_object == rhs.m_object && proto_base::operator==(rhs)); } | |
| 658 | ||
| 659 | protected: | |
| 660 | // internal state | |
| 661 | delegate_generic_class *m_object; // pointer to the post-cast object | |
| 662 | }; | |
| 663 | ||
| 664 | ||
| 665 | #endif | |
| 666 | ||
| 667 | ||
| 668 | //************************************************************************** | |
| 669 | // GCC DELEGATES | |
| 670 | //************************************************************************** | |
| 671 | ||
| 672 | #if (USE_DELEGATE_TYPE == DELEGATE_TYPE_INTERNAL) | |
| 673 | ||
| 674 | // a generic function pointer type and a generic member function pointer type | |
| 675 | typedef void (*delegate_generic_function)(); | |
| 676 | ||
| 677 | // struct describing the contents of a member function pointer | |
| 678 | struct delegate_gcc_mfp_internal | |
| 679 | { | |
| 680 | union // first item can be one of two things: | |
| 681 | { | |
| 682 | delegate_generic_function funcptr; // if even, it's a pointer to the function | |
| 683 | FPTR vtable_index; // if odd, it's the byte offset into the vtable | |
| 684 | } u; | |
| 685 | int this_delta; // delta to apply to the 'this' pointer | |
| 686 | }; | |
| 687 | ||
| 688 | // helper function | |
| 689 | delegate_generic_function delegate_convert_raw(delegate_generic_class *&object, delegate_gcc_mfp_internal &mfp); | |
| 690 | ||
| 691 | // global dummy extern | |
| 692 | extern delegate_gcc_mfp_internal delegate_gcc_mfp_null; | |
| 693 | ||
| 694 | ||
| 695 | // ======================> proto_delegate_0param | |
| 696 | ||
| 697 | template<typename _ReturnType> | |
| 698 | class proto_delegate_0param : public delegate_base | |
| 699 | { | |
| 700 | protected: | |
| 701 | // pointer to a static function which takes the object as a first parameter | |
| 702 | typedef _ReturnType (*static_func)(delegate_generic_class *); | |
| 703 | ||
| 704 | public: | |
| 705 | // constructors | |
| 706 | proto_delegate_0param(delegate_gcc_mfp_internal &mfp = delegate_gcc_mfp_null, static_func function = NULL, deferred_cast_func caster = NULL, const char *name = NULL) | |
| 707 | : delegate_base(caster, name), | |
| 708 | m_function(function), | |
| 709 | m_rawfunction(mfp) { } | |
| 710 | ||
| 711 | proto_delegate_0param(const proto_delegate_0param &proto) | |
| 712 | : delegate_base(proto.m_caster, proto.m_name), | |
| 713 | m_function(proto.m_function), | |
| 714 | m_rawfunction(proto.m_rawfunction) { } | |
| 715 | ||
| 716 | // create a member function proto-delegate | |
| 717 | template<class _FunctionClass, _ReturnType (_FunctionClass::*_FunctionPtr)()> | |
| 718 | static proto_delegate_0param _create_member(const char *name = NULL) | |
| 719 | { | |
| 720 | union | |
| 721 | { | |
| 722 | _ReturnType (_FunctionClass::*mfp)(); | |
| 723 | delegate_gcc_mfp_internal internal; | |
| 724 | } tempunion; | |
| 725 | tempunion.mfp = _FunctionPtr; | |
| 726 | return proto_delegate_0param(tempunion.internal, NULL, &deferred_cast<_FunctionClass>, name); | |
| 727 | } | |
| 728 | ||
| 729 | // create a static function proto-delegate | |
| 730 | template<class _FunctionClass, _ReturnType (*_FunctionPtr)(_FunctionClass *)> | |
| 731 | static proto_delegate_0param _create_static(const char *name = NULL) | |
| 732 | { | |
| 733 | return proto_delegate_0param(delegate_gcc_mfp_null, reinterpret_cast<static_func>(_FunctionPtr), &deferred_cast<_FunctionClass>, name); | |
| 734 | } | |
| 735 | ||
| 736 | // equality testing | |
| 737 | bool operator==(const proto_delegate_0param &rhs) const | |
| 738 | { | |
| 739 | return (m_function == rhs.m_function && m_caster == rhs.m_caster && | |
| 740 | m_rawfunction.u.funcptr == rhs.m_rawfunction.u.funcptr && | |
| 741 | m_rawfunction.this_delta == rhs.m_rawfunction.this_delta); | |
| 742 | } | |
| 743 | ||
| 744 | protected: | |
| 745 | // internal state | |
| 746 | static_func m_function; // generic static function pointer | |
| 747 | delegate_gcc_mfp_internal m_rawfunction; // raw member function definition | |
| 748 | }; | |
| 749 | ||
| 750 | ||
| 751 | // ======================> delegate_0param | |
| 752 | ||
| 753 | template<typename _ReturnType> | |
| 754 | class delegate_0param : public proto_delegate_0param<_ReturnType> | |
| 755 | { | |
| 756 | typedef _ReturnType (*static_func)(delegate_generic_class *); | |
| 757 | typedef proto_delegate_0param<_ReturnType> proto_base; | |
| 758 | ||
| 759 | using delegate_base::m_caster; | |
| 760 | using proto_base::m_function; | |
| 761 | using proto_base::m_rawfunction; | |
| 762 | ||
| 763 | public: | |
| 764 | // constructors | |
| 765 | delegate_0param() | |
| 766 | : m_object(NULL) { } | |
| 767 | ||
| 768 | delegate_0param(proto_base proto) | |
| 769 | : proto_delegate_0param<_ReturnType>(proto), | |
| 770 | m_object(NULL) { } | |
| 771 | ||
| 772 | delegate_0param(proto_base proto, bindable_object &object) | |
| 773 | : proto_delegate_0param<_ReturnType>(proto), | |
| 774 | m_object(NULL) { bind(object); } | |
| 775 | ||
| 776 | // bind the actual object | |
| 777 | void bind(bindable_object &object) | |
| 778 | { | |
| 779 | m_object = (*m_caster)(object); | |
| 780 | if (m_rawfunction.u.funcptr != NULL) | |
| 781 | m_function = reinterpret_cast<static_func>(delegate_convert_raw(m_object, m_rawfunction)); | |
| 782 | } | |
| 783 | ||
| 784 | // call the function | |
| 785 | _ReturnType operator()() const { return (*m_function)(m_object); } | |
| 786 | ||
| 787 | // testing | |
| 788 | bool has_object() const { return (m_object != NULL); } | |
| 789 | bool operator==(const delegate_0param &rhs) const { return (m_object == rhs.m_object && proto_base::operator==(rhs)); } | |
| 790 | ||
| 791 | protected: | |
| 792 | // internal state | |
| 793 | delegate_generic_class *m_object; // pointer to the post-cast object | |
| 794 | }; | |
| 795 | ||
| 796 | ||
| 797 | // ======================> proto_delegate_1param | |
| 798 | ||
| 799 | template<typename _ReturnType, typename _P1Type> | |
| 800 | class proto_delegate_1param : public delegate_base | |
| 801 | { | |
| 802 | protected: | |
| 803 | // pointer to a static function which takes the object as a first parameter | |
| 804 | typedef _ReturnType (*static_func)(delegate_generic_class *, _P1Type); | |
| 805 | ||
| 806 | public: | |
| 807 | // constructors | |
| 808 | proto_delegate_1param(delegate_gcc_mfp_internal &mfp = delegate_gcc_mfp_null, static_func function = NULL, deferred_cast_func caster = NULL, const char *name = NULL) | |
| 809 | : delegate_base(caster, name), | |
| 810 | m_function(function), | |
| 811 | m_rawfunction(mfp) { } | |
| 812 | ||
| 813 | proto_delegate_1param(const proto_delegate_1param &proto) | |
| 814 | : delegate_base(proto.m_caster, proto.m_name), | |
| 815 | m_function(proto.m_function), | |
| 816 | m_rawfunction(proto.m_rawfunction) { } | |
| 817 | ||
| 818 | // create a member function proto-delegate | |
| 819 | template<class _FunctionClass, _ReturnType (_FunctionClass::*_FunctionPtr)(_P1Type)> | |
| 820 | static proto_delegate_1param _create_member(const char *name = NULL) | |
| 821 | { | |
| 822 | union | |
| 823 | { | |
| 824 | _ReturnType (_FunctionClass::*mfp)(_P1Type); | |
| 825 | delegate_gcc_mfp_internal internal; | |
| 826 | } tempunion; | |
| 827 | tempunion.mfp = _FunctionPtr; | |
| 828 | return proto_delegate_1param(tempunion.internal, NULL, &deferred_cast<_FunctionClass>, name); | |
| 829 | } | |
| 830 | ||
| 831 | // create a static function proto-delegate | |
| 832 | template<class _FunctionClass, _ReturnType (*_FunctionPtr)(_FunctionClass *, _P1Type)> | |
| 833 | static proto_delegate_1param _create_static(const char *name = NULL) | |
| 834 | { | |
| 835 | return proto_delegate_1param(delegate_gcc_mfp_null, reinterpret_cast<static_func>(_FunctionPtr), &deferred_cast<_FunctionClass>, name); | |
| 836 | } | |
| 837 | ||
| 838 | // equality testing | |
| 839 | bool operator==(const proto_delegate_1param &rhs) const | |
| 840 | { | |
| 841 | return (m_function == rhs.m_function && m_caster == rhs.m_caster && | |
| 842 | m_rawfunction.u.funcptr == rhs.m_rawfunction.u.funcptr && | |
| 843 | m_rawfunction.this_delta == rhs.m_rawfunction.this_delta); | |
| 844 | } | |
| 845 | ||
| 846 | protected: | |
| 847 | // internal state | |
| 848 | static_func m_function; // generic static function pointer | |
| 849 | delegate_gcc_mfp_internal m_rawfunction; // raw member function definition | |
| 850 | }; | |
| 851 | ||
| 852 | ||
| 853 | // ======================> delegate_1param | |
| 854 | ||
| 855 | template<typename _ReturnType, typename _P1Type> | |
| 856 | class delegate_1param : public proto_delegate_1param<_ReturnType, _P1Type> | |
| 857 | { | |
| 858 | typedef _ReturnType (*static_func)(delegate_generic_class *, _P1Type); | |
| 859 | typedef proto_delegate_1param<_ReturnType, _P1Type> proto_base; | |
| 860 | ||
| 861 | using delegate_base::m_caster; | |
| 862 | using proto_base::m_function; | |
| 863 | using proto_base::m_rawfunction; | |
| 864 | ||
| 865 | public: | |
| 866 | // constructors | |
| 867 | delegate_1param() | |
| 868 | : m_object(NULL) { } | |
| 869 | ||
| 870 | delegate_1param(proto_base proto) | |
| 871 | : proto_delegate_1param<_ReturnType, _P1Type>(proto), | |
| 872 | m_object(NULL) { } | |
| 873 | ||
| 874 | delegate_1param(proto_base proto, bindable_object &object) | |
| 875 | : proto_delegate_1param<_ReturnType, _P1Type>(proto), | |
| 876 | m_object(NULL) { bind(object); } | |
| 877 | ||
| 878 | // bind the actual object | |
| 879 | void bind(bindable_object &object) | |
| 880 | { | |
| 881 | m_object = (*m_caster)(object); | |
| 882 | if (m_rawfunction.u.funcptr != NULL) | |
| 883 | m_function = reinterpret_cast<static_func>(delegate_convert_raw(m_object, m_rawfunction)); | |
| 884 | } | |
| 885 | ||
| 886 | // call the function | |
| 887 | _ReturnType operator()(_P1Type p1) const { return (*m_function)(m_object, p1); } | |
| 888 | ||
| 889 | // testing | |
| 890 | bool has_object() const { return (m_object != NULL); } | |
| 891 | bool operator==(const delegate_1param &rhs) const { return (m_object == rhs.m_object && proto_base::operator==(rhs)); } | |
| 892 | ||
| 893 | protected: | |
| 894 | // internal state | |
| 895 | delegate_generic_class *m_object; // pointer to the post-cast object | |
| 896 | }; | |
| 897 | ||
| 898 | ||
| 899 | // ======================> proto_delegate_2param | |
| 900 | ||
| 901 | template<typename _ReturnType, typename _P1Type, typename _P2Type> | |
| 902 | class proto_delegate_2param : public delegate_base | |
| 903 | { | |
| 904 | protected: | |
| 905 | // pointer to a static function which takes the object as a first parameter | |
| 906 | typedef _ReturnType (*static_func)(delegate_generic_class *, _P1Type, _P2Type); | |
| 907 | ||
| 908 | public: | |
| 909 | // constructors | |
| 910 | proto_delegate_2param(delegate_gcc_mfp_internal &mfp = delegate_gcc_mfp_null, static_func function = NULL, deferred_cast_func caster = NULL, const char *name = NULL) | |
| 911 | : delegate_base(caster, name), | |
| 912 | m_function(function), | |
| 913 | m_rawfunction(mfp) { } | |
| 914 | ||
| 915 | proto_delegate_2param(const proto_delegate_2param &proto) | |
| 916 | : delegate_base(proto.m_caster, proto.m_name), | |
| 917 | m_function(proto.m_function), | |
| 918 | m_rawfunction(proto.m_rawfunction) { } | |
| 919 | ||
| 920 | // create a member function proto-delegate | |
| 921 | template<class _FunctionClass, _ReturnType (_FunctionClass::*_FunctionPtr)(_P1Type, _P2Type)> | |
| 922 | static proto_delegate_2param _create_member(const char *name = NULL) | |
| 923 | { | |
| 924 | union | |
| 925 | { | |
| 926 | _ReturnType (_FunctionClass::*mfp)(_P1Type, _P2Type); | |
| 927 | delegate_gcc_mfp_internal internal; | |
| 928 | } tempunion; | |
| 929 | tempunion.mfp = _FunctionPtr; | |
| 930 | return proto_delegate_2param(tempunion.internal, NULL, &deferred_cast<_FunctionClass>, name); | |
| 931 | } | |
| 932 | ||
| 933 | // create a static function proto-delegate | |
| 934 | template<class _FunctionClass, _ReturnType (*_FunctionPtr)(_FunctionClass *, _P1Type, _P2Type)> | |
| 935 | static proto_delegate_2param _create_static(const char *name = NULL) | |
| 936 | { | |
| 937 | return proto_delegate_2param(delegate_gcc_mfp_null, reinterpret_cast<static_func>(_FunctionPtr), &deferred_cast<_FunctionClass>, name); | |
| 938 | } | |
| 939 | ||
| 940 | // equality testing | |
| 941 | bool operator==(const proto_delegate_2param &rhs) const | |
| 942 | { | |
| 943 | return (m_function == rhs.m_function && m_caster == rhs.m_caster && | |
| 944 | m_rawfunction.u.funcptr == rhs.m_rawfunction.u.funcptr && | |
| 945 | m_rawfunction.this_delta == rhs.m_rawfunction.this_delta); | |
| 946 | } | |
| 947 | ||
| 948 | protected: | |
| 949 | // internal state | |
| 950 | static_func m_function; // generic static function pointer | |
| 951 | delegate_gcc_mfp_internal m_rawfunction; // raw member function definition | |
| 952 | }; | |
| 953 | ||
| 954 | ||
| 955 | // ======================> delegate_2param | |
| 956 | ||
| 957 | template<typename _ReturnType, typename _P1Type, typename _P2Type> | |
| 958 | class delegate_2param : public proto_delegate_2param<_ReturnType, _P1Type, _P2Type> | |
| 959 | { | |
| 960 | typedef _ReturnType (*static_func)(delegate_generic_class *, _P1Type, _P2Type); | |
| 961 | typedef proto_delegate_2param<_ReturnType, _P1Type, _P2Type> proto_base; | |
| 962 | ||
| 963 | using delegate_base::m_caster; | |
| 964 | using proto_base::m_function; | |
| 965 | using proto_base::m_rawfunction; | |
| 966 | ||
| 967 | public: | |
| 968 | // constructors | |
| 969 | delegate_2param() | |
| 970 | : m_object(NULL) { } | |
| 971 | ||
| 972 | delegate_2param(proto_base proto) | |
| 973 | : proto_delegate_2param<_ReturnType, _P1Type, _P2Type>(proto), | |
| 974 | m_object(NULL) { } | |
| 975 | ||
| 976 | delegate_2param(proto_base proto, bindable_object &object) | |
| 977 | : proto_delegate_2param<_ReturnType, _P1Type, _P2Type>(proto), | |
| 978 | m_object(NULL) { bind(object); } | |
| 979 | ||
| 980 | // bind the actual object | |
| 981 | void bind(bindable_object &object) | |
| 982 | { | |
| 983 | m_object = (*m_caster)(object); | |
| 984 | if (m_rawfunction.u.funcptr != NULL) | |
| 985 | m_function = reinterpret_cast<static_func>(delegate_convert_raw(m_object, m_rawfunction)); | |
| 986 | } | |
| 987 | ||
| 988 | // call the function | |
| 989 | _ReturnType operator()(_P1Type p1, _P2Type p2) const { return (*m_function)(m_object, p1, p2); } | |
| 990 | ||
| 991 | // testing | |
| 992 | bool has_object() const { return (m_object != NULL); } | |
| 993 | bool operator==(const delegate_2param &rhs) const { return (m_object == rhs.m_object && proto_base::operator==(rhs)); } | |
| 994 | ||
| 995 | protected: | |
| 996 | // internal state | |
| 997 | delegate_generic_class *m_object; // pointer to the post-cast object | |
| 998 | }; | |
| 999 | ||
| 1000 | ||
| 1001 | // ======================> proto_delegate_3param | |
| 1002 | ||
| 1003 | template<typename _ReturnType, typename _P1Type, typename _P2Type, typename _P3Type> | |
| 1004 | class proto_delegate_3param : public delegate_base | |
| 1005 | { | |
| 1006 | protected: | |
| 1007 | // pointer to a static function which takes the object as a first parameter | |
| 1008 | typedef _ReturnType (*static_func)(delegate_generic_class *, _P1Type, _P2Type, _P3Type); | |
| 1009 | ||
| 1010 | public: | |
| 1011 | // constructors | |
| 1012 | proto_delegate_3param(delegate_gcc_mfp_internal &mfp = delegate_gcc_mfp_null, static_func function = NULL, deferred_cast_func caster = NULL, const char *name = NULL) | |
| 1013 | : delegate_base(caster, name), | |
| 1014 | m_function(function), | |
| 1015 | m_rawfunction(mfp) { } | |
| 1016 | ||
| 1017 | proto_delegate_3param(const proto_delegate_3param &proto) | |
| 1018 | : delegate_base(proto.m_caster, proto.m_name), | |
| 1019 | m_function(proto.m_function), | |
| 1020 | m_rawfunction(proto.m_rawfunction) { } | |
| 1021 | ||
| 1022 | // create a member function proto-delegate | |
| 1023 | template<class _FunctionClass, _ReturnType (_FunctionClass::*_FunctionPtr)(_P1Type, _P2Type, _P3Type)> | |
| 1024 | static proto_delegate_3param _create_member(const char *name = NULL) | |
| 1025 | { | |
| 1026 | union | |
| 1027 | { | |
| 1028 | _ReturnType (_FunctionClass::*mfp)(_P1Type, _P2Type, _P3Type); | |
| 1029 | delegate_gcc_mfp_internal internal; | |
| 1030 | } tempunion; | |
| 1031 | tempunion.mfp = _FunctionPtr; | |
| 1032 | return proto_delegate_3param(tempunion.internal, NULL, &deferred_cast<_FunctionClass>, name); | |
| 1033 | } | |
| 1034 | ||
| 1035 | // create a static function proto-delegate | |
| 1036 | template<class _FunctionClass, _ReturnType (*_FunctionPtr)(_FunctionClass *, _P1Type, _P2Type, _P3Type)> | |
| 1037 | static proto_delegate_3param _create_static(const char *name = NULL) | |
| 1038 | { | |
| 1039 | return proto_delegate_3param(delegate_gcc_mfp_null, reinterpret_cast<static_func>(_FunctionPtr), &deferred_cast<_FunctionClass>, name); | |
| 1040 | } | |
| 1041 | ||
| 1042 | // equality testing | |
| 1043 | bool operator==(const proto_delegate_3param &rhs) const | |
| 1044 | { | |
| 1045 | return (m_function == rhs.m_function && m_caster == rhs.m_caster && | |
| 1046 | m_rawfunction.u.funcptr == rhs.m_rawfunction.u.funcptr && | |
| 1047 | m_rawfunction.this_delta == rhs.m_rawfunction.this_delta); | |
| 1048 | } | |
| 1049 | ||
| 1050 | protected: | |
| 1051 | // internal state | |
| 1052 | static_func m_function; // generic static function pointer | |
| 1053 | delegate_gcc_mfp_internal m_rawfunction; // raw member function definition | |
| 1054 | }; | |
| 1055 | ||
| 1056 | ||
| 1057 | // ======================> delegate_3param | |
| 1058 | ||
| 1059 | template<typename _ReturnType, typename _P1Type, typename _P2Type, typename _P3Type> | |
| 1060 | class delegate_3param : public proto_delegate_3param<_ReturnType, _P1Type, _P2Type, _P3Type> | |
| 1061 | { | |
| 1062 | typedef _ReturnType (*static_func)(delegate_generic_class *, _P1Type, _P2Type, _P3Type); | |
| 1063 | typedef proto_delegate_3param<_ReturnType, _P1Type, _P2Type, _P3Type> proto_base; | |
| 1064 | ||
| 1065 | using delegate_base::m_caster; | |
| 1066 | using proto_base::m_function; | |
| 1067 | using proto_base::m_rawfunction; | |
| 1068 | ||
| 1069 | public: | |
| 1070 | // constructors | |
| 1071 | delegate_3param() | |
| 1072 | : m_object(NULL) { } | |
| 1073 | ||
| 1074 | delegate_3param(proto_base proto) | |
| 1075 | : proto_delegate_3param<_ReturnType, _P1Type, _P2Type, _P3Type>(proto), | |
| 1076 | m_object(NULL) { } | |
| 1077 | ||
| 1078 | delegate_3param(proto_base proto, bindable_object &object) | |
| 1079 | : proto_delegate_3param<_ReturnType, _P1Type, _P2Type, _P3Type>(proto), | |
| 1080 | m_object(NULL) { bind(object); } | |
| 1081 | ||
| 1082 | // bind the actual object | |
| 1083 | void bind(bindable_object &object) | |
| 1084 | { | |
| 1085 | m_object = (*m_caster)(object); | |
| 1086 | if (m_rawfunction.u.funcptr != NULL) | |
| 1087 | m_function = reinterpret_cast<static_func>(delegate_convert_raw(m_object, m_rawfunction)); | |
| 1088 | } | |
| 1089 | ||
| 1090 | // call the function | |
| 1091 | _ReturnType operator()(_P1Type p1, _P2Type p2, _P3Type p3) const { return (*m_function)(m_object, p1, p2, p3); } | |
| 1092 | ||
| 1093 | // testing | |
| 1094 | bool has_object() const { return (m_object != NULL); } | |
| 1095 | bool operator==(const delegate_3param &rhs) const { return (m_object == rhs.m_object && proto_base::operator==(rhs)); } | |
| 1096 | ||
| 1097 | protected: | |
| 1098 | // internal state | |
| 1099 | delegate_generic_class *m_object; // pointer to the post-cast object | |
| 1100 | }; | |
| 1101 | ||
| 1102 | ||
| 1103 | // ======================> proto_delegate_4param | |
| 1104 | ||
| 1105 | template<typename _ReturnType, typename _P1Type, typename _P2Type, typename _P3Type, typename _P4Type> | |
| 1106 | class proto_delegate_4param : public delegate_base | |
| 1107 | { | |
| 1108 | protected: | |
| 1109 | // pointer to a static function which takes the object as a first parameter | |
| 1110 | typedef _ReturnType (*static_func)(delegate_generic_class *, _P1Type, _P2Type, _P3Type, _P4Type); | |
| 1111 | ||
| 1112 | public: | |
| 1113 | // constructors | |
| 1114 | proto_delegate_4param(delegate_gcc_mfp_internal &mfp = delegate_gcc_mfp_null, static_func function = NULL, deferred_cast_func caster = NULL, const char *name = NULL) | |
| 1115 | : delegate_base(caster, name), | |
| 1116 | m_function(function), | |
| 1117 | m_rawfunction(mfp) { } | |
| 1118 | ||
| 1119 | proto_delegate_4param(const proto_delegate_4param &proto) | |
| 1120 | : delegate_base(proto.m_caster, proto.m_name), | |
| 1121 | m_function(proto.m_function), | |
| 1122 | m_rawfunction(proto.m_rawfunction) { } | |
| 1123 | ||
| 1124 | // create a member function proto-delegate | |
| 1125 | template<class _FunctionClass, _ReturnType (_FunctionClass::*_FunctionPtr)(_P1Type, _P2Type, _P3Type, _P4Type)> | |
| 1126 | static proto_delegate_4param _create_member(const char *name = NULL) | |
| 1127 | { | |
| 1128 | union | |
| 1129 | { | |
| 1130 | _ReturnType (_FunctionClass::*mfp)(_P1Type, _P2Type, _P3Type, _P4Type); | |
| 1131 | delegate_gcc_mfp_internal internal; | |
| 1132 | } tempunion; | |
| 1133 | tempunion.mfp = _FunctionPtr; | |
| 1134 | return proto_delegate_4param(tempunion.internal, NULL, &deferred_cast<_FunctionClass>, name); | |
| 1135 | } | |
| 1136 | ||
| 1137 | // create a static function proto-delegate | |
| 1138 | template<class _FunctionClass, _ReturnType (*_FunctionPtr)(_FunctionClass *, _P1Type, _P2Type, _P3Type, _P4Type)> | |
| 1139 | static proto_delegate_4param _create_static(const char *name = NULL) | |
| 1140 | { | |
| 1141 | return proto_delegate_4param(delegate_gcc_mfp_null, reinterpret_cast<static_func>(_FunctionPtr), &deferred_cast<_FunctionClass>, name); | |
| 1142 | } | |
| 1143 | ||
| 1144 | // equality testing | |
| 1145 | bool operator==(const proto_delegate_4param &rhs) const | |
| 1146 | { | |
| 1147 | return (m_function == rhs.m_function && m_caster == rhs.m_caster && | |
| 1148 | m_rawfunction.u.funcptr == rhs.m_rawfunction.u.funcptr && | |
| 1149 | m_rawfunction.this_delta == rhs.m_rawfunction.this_delta); | |
| 1150 | } | |
| 1151 | ||
| 1152 | protected: | |
| 1153 | // internal state | |
| 1154 | static_func m_function; // generic static function pointer | |
| 1155 | delegate_gcc_mfp_internal m_rawfunction; // raw member function definition | |
| 1156 | }; | |
| 1157 | ||
| 1158 | ||
| 1159 | // ======================> delegate_4param | |
| 1160 | ||
| 1161 | template<typename _ReturnType, typename _P1Type, typename _P2Type, typename _P3Type, typename _P4Type> | |
| 1162 | class delegate_4param : public proto_delegate_4param<_ReturnType, _P1Type, _P2Type, _P3Type, _P4Type> | |
| 1163 | { | |
| 1164 | typedef _ReturnType (*static_func)(delegate_generic_class *, _P1Type, _P2Type, _P3Type, _P4Type); | |
| 1165 | typedef proto_delegate_4param<_ReturnType, _P1Type, _P2Type, _P3Type, _P4Type> proto_base; | |
| 1166 | ||
| 1167 | using delegate_base::m_caster; | |
| 1168 | using proto_base::m_function; | |
| 1169 | using proto_base::m_rawfunction; | |
| 1170 | ||
| 1171 | public: | |
| 1172 | // constructors | |
| 1173 | delegate_4param() | |
| 1174 | : m_object(NULL) { } | |
| 1175 | ||
| 1176 | delegate_4param(proto_base proto) | |
| 1177 | : proto_delegate_4param<_ReturnType, _P1Type, _P2Type, _P3Type, _P4Type>(proto), | |
| 1178 | m_object(NULL) { } | |
| 1179 | ||
| 1180 | delegate_4param(proto_base proto, bindable_object &object) | |
| 1181 | : proto_delegate_4param<_ReturnType, _P1Type, _P2Type, _P3Type, _P4Type>(proto), | |
| 1182 | m_object(NULL) { bind(object); } | |
| 1183 | ||
| 1184 | // bind the actual object | |
| 1185 | void bind(bindable_object &object) | |
| 1186 | { | |
| 1187 | m_object = (*m_caster)(object); | |
| 1188 | if (m_rawfunction.u.funcptr != NULL) | |
| 1189 | m_function = reinterpret_cast<static_func>(delegate_convert_raw(m_object, m_rawfunction)); | |
| 1190 | } | |
| 1191 | ||
| 1192 | // call the function | |
| 1193 | _ReturnType operator()(_P1Type p1, _P2Type p2, _P3Type p3, _P4Type p4) const { return (*m_function)(m_object, p1, p2, p3, p4); } | |
| 1194 | ||
| 1195 | // testing | |
| 1196 | bool has_object() const { return (m_object != NULL); } | |
| 1197 | bool operator==(const delegate_4param &rhs) const { return (m_object == rhs.m_object && proto_base::operator==(rhs)); } | |
| 1198 | ||
| 1199 | protected: | |
| 1200 | // internal state | |
| 1201 | delegate_generic_class *m_object; // pointer to the post-cast object | |
| 1202 | }; | |
| 1203 | ||
| 1204 | ||
| 1205 | ||
| 1206 | #endif | |
| 1207 | ||
| 1208 | ||
| 1209 | #endif /* __DELEGATE_H__ */ |
| r8806 | r8807 | |
|---|---|---|
| 191 | 191 | ::address_map *map = global_alloc(::address_map(*devconfig, spacenum)); |
| 192 | 192 | |
| 193 | 193 | // if this is an empty map, just skip it |
| 194 | if (map->m_entrylist == NULL) | |
| 194 | if (map->m_entrylist.first() == NULL) | |
| 195 | 195 | { |
| 196 | 196 | global_free(map); |
| 197 | 197 | continue; |
| r8806 | r8807 | |
| 210 | 210 | } |
| 211 | 211 | |
| 212 | 212 | // loop over entries and look for errors |
| 213 | for (address_map_entry *entry = map->m_entrylist; entry != NULL; entry = entry-> | |
| 213 | for (address_map_entry *entry = map->m_entrylist.first(); entry != NULL; entry = entry-> | |
| 214 | 214 | { |
| 215 | 215 | UINT32 bytestart = spaceconfig->addr2byte(entry->m_addrstart); |
| 216 | 216 | UINT32 byteend = spaceconfig->addr2byte_end(entry->m_addrend); |
| r8806 | r8807 | |
| 219 | 219 | if (!detected_overlap) |
| 220 | 220 | { |
| 221 | 221 | address_map_entry *scan; |
| 222 | for (scan = map->m_entrylist; scan != entry; scan = scan-> | |
| 222 | for (scan = map->m_entrylist.first(); scan != entry; scan = scan-> | |
| 223 | 223 | if (entry->m_addrstart <= scan->m_addrend && entry->m_addrend >= scan->m_addrstart && |
| 224 | ((entry->m_read.type != AMH_NONE && scan->m_read.type != AMH_NONE) || | |
| 225 | (entry->m_write.type != AMH_NONE && scan->m_write.type != AMH_NONE))) | |
| 224 | ((entry->m_read.m_type != AMH_NONE && scan->m_read.m_type != AMH_NONE) || | |
| 225 | (entry->m_write.m_type != AMH_NONE && scan->m_write.m_type != AMH_NONE))) | |
| 226 | 226 | { |
| 227 | mame_printf_warning("%s: %s '%s' %s space has overlapping memory (%X-%X,%d,%d) vs (%X-%X,%d,%d)\n", driver.source_file, driver.name, devconfig->tag(), spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_read.type, entry->m_write.type, scan->m_addrstart, scan->m_addrend, scan->m_read.type, scan->m_write.type); | |
| 227 | mame_printf_warning("%s: %s '%s' %s space has overlapping memory (%X-%X,%d,%d) vs (%X-%X,%d,%d)\n", driver.source_file, driver.name, devconfig->tag(), spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_read.m_type, entry->m_write.m_type, scan->m_addrstart, scan->m_addrend, scan->m_read.m_type, scan->m_write.m_type); | |
| 228 | 228 | detected_overlap = true; |
| 229 | 229 | break; |
| 230 | 230 | } |
| r8806 | r8807 | |
| 245 | 245 | } |
| 246 | 246 | |
| 247 | 247 | // if this is a program space, auto-assign implicit ROM entries |
| 248 | if (entry->m_read.type == AMH_ROM && entry->m_region == NULL) | |
| 248 | if (entry->m_read.m_type == AMH_ROM && entry->m_region == NULL) | |
| 249 | 249 | { |
| 250 | 250 | entry->m_region = devconfig->tag(); |
| 251 | 251 | entry->m_rgnoffs = entry->m_addrstart; |
| r8806 | r8807 | |
| 287 | 287 | } |
| 288 | 288 | |
| 289 | 289 | // make sure all devices exist |
| 290 | if ((entry->m_read.type == AMH_DEVICE_HANDLER && entry->m_read.tag != NULL && m_machine_config.m_devicelist.find(entry->m_read.tag) == NULL) || | |
| 291 | (entry->m_write.type == AMH_DEVICE_HANDLER && entry->m_write.tag != NULL && m_machine_config.m_devicelist.find(entry->m_write.tag) == NULL)) | |
| 290 | if ((entry->m_read.m_type == AMH_LEGACY_DEVICE_HANDLER && entry->m_read.m_tag != NULL && m_machine_config.m_devicelist.find(entry->m_read.m_tag) == NULL) || | |
| 291 | (entry->m_write.m_type == AMH_LEGACY_DEVICE_HANDLER && entry->m_write.m_tag != NULL && m_machine_config.m_devicelist.find(entry->m_write.m_tag) == NULL)) | |
| 292 | 292 | { |
| 293 | mame_printf_error("%s: %s device '%s' %s space memory map entry references nonexistant device '%s'\n", driver.source_file, driver.name, devconfig->tag(), spaceconfig->m_name, entry->m_write.tag); | |
| 293 | mame_printf_error("%s: %s device '%s' %s space memory map entry references nonexistant device '%s'\n", driver.source_file, driver.name, devconfig->tag(), spaceconfig->m_name, entry->m_write.m_tag); | |
| 294 | 294 | error = true; |
| 295 | 295 | } |
| 296 | 296 | |
| 297 | 297 | // make sure ports exist |
| 298 | // if ((entry->m_read.type == AMH_PORT && entry->m_read.tag != NULL && portlist.find(entry->m_read.tag) == NULL) || | |
| 299 | // (entry->m_write.type == AMH_PORT && entry->m_write.tag != NULL && portlist.find(entry->m_write.tag) == NULL)) | |
| 298 | // if ((entry->m_read.m_type == AMH_PORT && entry->m_read.m_tag != NULL && portlist.find(entry->m_read.m_tag) == NULL) || | |
| 299 | // (entry->m_write.m_type == AMH_PORT && entry->m_write.m_tag != NULL && portlist.find(entry->m_write.m_tag) == NULL)) | |
| 300 | 300 | // { |
| 301 | 301 | // mame_printf_error("%s: %s device '%s' %s space memory map entry references nonexistant port tag '%s'\n", driver.source_file, driver.name, devconfig->tag(), spaceconfig->m_name, entry->m_read.tag); |
| 302 | 302 | // error = true; |
| 303 | 303 | // } |
| 304 | 304 | |
| 305 | 305 | // validate bank and share tags |
| 306 | if (entry->m_read.type == AMH_BANK && !validate_tag(&driver, "bank", entry->m_read.tag)) | |
| 306 | if (entry->m_read.m_type == AMH_BANK && !validate_tag(&driver, "bank", entry->m_read.m_tag)) | |
| 307 | 307 | error = true ; |
| 308 | if (entry->m_write.type == AMH_BANK && !validate_tag(&driver, "bank", entry->m_write.tag)) | |
| 308 | if (entry->m_write.m_type == AMH_BANK && !validate_tag(&driver, "bank", entry->m_write.m_tag)) | |
| 309 | 309 | error = true; |
| 310 | 310 | if (entry->m_share != NULL && !validate_tag(&driver, "share", entry->m_share)) |
| 311 | 311 | error = true; |
| r8806 | r8807 | |
| 350 | 350 | // to a device |
| 351 | 351 | //------------------------------------------------- |
| 352 | 352 | |
| 353 | void device_memory_interface::set_address_space(int spacenum, | |
| 353 | void device_memory_interface::set_address_space(int spacenum, | |
| 354 | 354 | { |
| 355 | 355 | assert(spacenum < ARRAY_LENGTH(m_addrspace)); |
| 356 | m_addrspace[spacenum] = space; | |
| 356 | m_addrspace[spacenum] = &space; | |
| 357 | 357 | } |
| 358 | 358 | |
| 359 | 359 |
| r8806 | r8807 | |
|---|---|---|
| 100 | 100 | // TYPE DEFINITIONS |
| 101 | 101 | //************************************************************************** |
| 102 | 102 | |
| 103 | // ======================> address_space_config | |
| 104 | ||
| 105 | class address_space_config | |
| 106 | { | |
| 107 | public: | |
| 108 | address_space_config(); | |
| 109 | address_space_config(const char *name, endianness_t endian, UINT8 datawidth, UINT8 addrwidth, INT8 addrshift = 0, address_map_constructor internal = NULL, address_map_constructor defmap = NULL); | |
| 110 | address_space_config(const char *name, endianness_t endian, UINT8 datawidth, UINT8 addrwidth, INT8 addrshift, UINT8 logwidth, UINT8 pageshift, address_map_constructor internal = NULL, address_map_constructor defmap = NULL); | |
| 111 | ||
| 112 | inline offs_t addr2byte(offs_t address) const | |
| 113 | { | |
| 114 | return (m_addrbus_shift < 0) ? (address << -m_addrbus_shift) : (address >> m_addrbus_shift); | |
| 115 | } | |
| 116 | ||
| 117 | inline offs_t addr2byte_end(offs_t address) const | |
| 118 | { | |
| 119 | return (m_addrbus_shift < 0) ? ((address << -m_addrbus_shift) | ((1 << -m_addrbus_shift) - 1)) : (address >> m_addrbus_shift); | |
| 120 | } | |
| 121 | ||
| 122 | inline offs_t byte2addr(offs_t address) const | |
| 123 | { | |
| 124 | return (m_addrbus_shift > 0) ? (address << m_addrbus_shift) : (address >> -m_addrbus_shift); | |
| 125 | } | |
| 126 | ||
| 127 | inline offs_t byte2addr_end(offs_t address) const | |
| 128 | { | |
| 129 | return (m_addrbus_shift > 0) ? ((address << m_addrbus_shift) | ((1 << -m_addrbus_shift) - 1)) : (address >> -m_addrbus_shift); | |
| 130 | } | |
| 131 | ||
| 132 | const char * m_name; | |
| 133 | endianness_t m_endianness; | |
| 134 | UINT8 m_databus_width; | |
| 135 | UINT8 m_addrbus_width; | |
| 136 | INT8 m_addrbus_shift; | |
| 137 | UINT8 m_logaddr_width; | |
| 138 | UINT8 m_page_shift; | |
| 139 | address_map_constructor m_internal_map; | |
| 140 | address_map_constructor m_default_map; | |
| 141 | }; | |
| 142 | ||
| 143 | ||
| 144 | ||
| 145 | 103 | // ======================> device_config_memory_interface |
| 146 | 104 | |
| 147 | 105 | // class representing interface-specific configuration state |
| r8806 | r8807 | |
| 187 | 145 | |
| 188 | 146 | // basic information getters |
| 189 | 147 | const address_space_config *space_config(int spacenum = 0) const { return m_memory_config.space_config(spacenum); } |
| 190 | const address_space *space(int index = 0) const { return m_addrspace[index]; } | |
| 191 | const address_space *space(device_space index) const { return m_addrspace[static_cast<int>(index)]; } | |
| 148 | address_space *space(int index = 0) const { return m_addrspace[index]; } | |
| 149 | address_space *space(device_space index) const { return m_addrspace[static_cast<int>(index)]; } | |
| 192 | 150 | |
| 193 | 151 | // address space accessors |
| 194 | void set_address_space(int spacenum, | |
| 152 | void set_address_space(int spacenum, | |
| 195 | 153 | |
| 196 | 154 | // address translation |
| 197 | 155 | bool translate(int spacenum, int intention, offs_t &address) { return memory_translate(spacenum, intention, address); } |
| r8806 | r8807 | |
| 212 | 170 | |
| 213 | 171 | // configuration |
| 214 | 172 | const device_config_memory_interface &m_memory_config; // reference to our device_config_execute_interface |
| 215 | | |
| 173 | | |
| 216 | 174 | }; |
| 217 | 175 | |
| 218 | 176 | |
| r8806 | r8807 | |
| 240 | 198 | // given address space on this device |
| 241 | 199 | //------------------------------------------------- |
| 242 | 200 | |
| 243 | inline | |
| 201 | inline | |
| 244 | 202 | { |
| 245 | 203 | return device_memory(device)->space(spacenum); |
| 246 | 204 | } |
| r8806 | r8807 | |
|---|---|---|
| 88 | 88 | image->message("%s: Unexpected EOF while writing byte to %04X", pgmname, (unsigned) j); |
| 89 | 89 | return IMAGE_INIT_FAIL; |
| 90 | 90 | } |
| 91 | | |
| 91 | | |
| 92 | 92 | } |
| 93 | 93 | |
| 94 | 94 | return IMAGE_INIT_PASS; |
| r8806 | r8807 | |
|---|---|---|
| 171 | 171 | void (*inta_callback)(running_machine *machine, int state); |
| 172 | 172 | void (*intb_callback)(running_machine *machine, int state); |
| 173 | 173 | |
| 174 | | |
| 174 | | |
| 175 | 175 | |
| 176 | 176 | } ti99_peb_state; |
| 177 | 177 |
| r8806 | r8807 | |
|---|---|---|
| 194 | 194 | } |
| 195 | 195 | else |
| 196 | 196 | { |
| 197 | sample = | |
| 197 | sample = | |
| 198 | 198 | } |
| 199 | 199 | if (((unsigned)svision_dma.pos) & 1) |
| 200 | 200 | s = (sample & 0xf); |
| r8806 | r8807 | |
|---|---|---|
| 158 | 158 | or uninstall write handlers |
| 159 | 159 | -------------------------------------------------*/ |
| 160 | 160 | |
| 161 | void vp550_install_write_handlers(running_device *device, | |
| 161 | void vp550_install_write_handlers(running_device *device, | |
| 162 | 162 | { |
| 163 | 163 | vp550_t *vp550 = get_safe_token(device); |
| 164 | 164 | |
| r8806 | r8807 | |
| 187 | 187 | or uninstall write handlers |
| 188 | 188 | -------------------------------------------------*/ |
| 189 | 189 | |
| 190 | void vp551_install_write_handlers(running_device *device, | |
| 190 | void vp551_install_write_handlers(running_device *device, | |
| 191 | 191 | { |
| 192 | 192 | } |
| 193 | 193 |
| r8806 | r8807 | |
|---|---|---|
| 38 | 38 | WRITE_LINE_DEVICE_HANDLER( vp550_sc1_w ) ATTR_NONNULL(1); |
| 39 | 39 | |
| 40 | 40 | /* install write handlers */ |
| 41 | void vp550_install_write_handlers(running_device *device, const address_space *program, int enabled) ATTR_NONNULL(1) ATTR_NONNULL(2); | |
| 42 | void vp551_install_write_handlers(running_device *device, const address_space *program, int enabled) ATTR_NONNULL(1) ATTR_NONNULL(2); | |
| 41 | void vp550_install_write_handlers(running_device *device, address_space *program, int enabled) ATTR_NONNULL(1) ATTR_NONNULL(2); | |
| 42 | void vp551_install_write_handlers(running_device *device, address_space *program, int enabled) ATTR_NONNULL(1) ATTR_NONNULL(2); | |
| 43 | 43 | |
| 44 | 44 | #endif /* __VP550__ */ |
| r8806 | r8807 | |
|---|---|---|
| 72 | 72 | or uninstall write handlers |
| 73 | 73 | -------------------------------------------------*/ |
| 74 | 74 | |
| 75 | void vp595_install_write_handlers(running_device *device, | |
| 75 | void vp595_install_write_handlers(running_device *device, | |
| 76 | 76 | { |
| 77 | 77 | vp595_t *vp595 = get_safe_token(device); |
| 78 | 78 |
| r8806 | r8807 | |
|---|---|---|
| 30 | 30 | WRITE_LINE_DEVICE_HANDLER( vp595_q_w ) ATTR_NONNULL(1); |
| 31 | 31 | |
| 32 | 32 | /* install write handlers */ |
| 33 | void vp595_install_write_handlers(running_device *device, | |
| 33 | void vp595_install_write_handlers(running_device *device, | |
| 34 | 34 | |
| 35 | 35 | #endif /* __VP595__ */ |
| r8806 | r8807 | |
|---|---|---|
| 283 | 283 | |
| 284 | 284 | static void UpdateBanks(running_machine *machine, int first, int last) |
| 285 | 285 | { |
| 286 | const address_space *space_0 = cputag_get_address_space(machine, MAINCPU_TAG, ADDRESS_SPACE_PROGRAM); | |
| 287 | const address_space *space_1 = cputag_get_address_space(machine, DMACPU_TAG, ADDRESS_SPACE_PROGRAM); | |
| 286 | address_space *space_0 = cputag_get_address_space(machine, MAINCPU_TAG, ADDRESS_SPACE_PROGRAM); | |
| 287 | address_space *space_1 = cputag_get_address_space(machine, DMACPU_TAG, ADDRESS_SPACE_PROGRAM); | |
| 288 | 288 | int Page; |
| 289 | 289 | UINT8 *readbank; |
| 290 | 290 | write8_space_func writebank; |
| r8806 | r8807 | |
|---|---|---|
| 1158 | 1158 | { |
| 1159 | 1159 | if ((parallel_drum.wfb >= 1) && (parallel_drum.wfb <= 22)) |
| 1160 | 1160 | { |
| 1161 | drum_write(parallel_drum.wfb-1, dc, (signed) | |
| 1161 | drum_write(parallel_drum.wfb-1, dc, (signed) | |
| 1162 | 1162 | } |
| 1163 | 1163 | |
| 1164 | 1164 | if ((parallel_drum.rfb >= 1) && (parallel_drum.rfb <= 22)) |
| 1165 | 1165 | { |
| 1166 | | |
| 1166 | | |
| 1167 | 1167 | } |
| 1168 | 1168 | |
| 1169 | 1169 | parallel_drum.wc = (parallel_drum.wc+1) & 07777; |
| r8806 | r8807 | |
| 1435 | 1435 | cpu_set_reg(device, PDP1_MA, cpu_get_reg(device, PDP1_PC)); |
| 1436 | 1436 | cpu_set_reg(device, PDP1_IR, LAC); /* this instruction is actually executed */ |
| 1437 | 1437 | |
| 1438 | cpu_set_reg(device, PDP1_MB, (signed) | |
| 1438 | cpu_set_reg(device, PDP1_MB, (signed) | |
| 1439 | 1439 | cpu_set_reg(device, PDP1_AC, cpu_get_reg(device, PDP1_MB)); |
| 1440 | 1440 | } |
| 1441 | 1441 | if (control_transitions & pdp1_deposit) |
| r8806 | r8807 | |
| 1447 | 1447 | cpu_set_reg(device, PDP1_IR, DAC); /* this instruction is actually executed */ |
| 1448 | 1448 | |
| 1449 | 1449 | cpu_set_reg(device, PDP1_MB, cpu_get_reg(device, PDP1_AC)); |
| 1450 | | |
| 1450 | | |
| 1451 | 1451 | } |
| 1452 | 1452 | if (control_transitions & pdp1_read_in) |
| 1453 | 1453 | { /* set cpu to read instructions from perforated tape */ |
| r8806 | r8807 | |
|---|---|---|
| 325 | 325 | |
| 326 | 326 | MACHINE_START( xegs ) |
| 327 | 327 | { |
| 328 | | |
| 328 | | |
| 329 | 329 | UINT8 *cart = memory_region(space->machine, "user1"); |
| 330 | 330 | UINT8 *cpu = memory_region(space->machine, "maincpu"); |
| 331 | 331 |
| r8806 | r8807 | |
|---|---|---|
| 738 | 738 | |
| 739 | 739 | */ |
| 740 | 740 | |
| 741 | static UINT8 memory_read_byte(address_space *space, offs_t address) { return space->read_byte(address); } | |
| 742 | static void memory_write_byte(address_space *space, offs_t address, UINT8 data) { space->write_byte(address, data); } | |
| 743 | ||
| 741 | 744 | static Z80DMA_INTERFACE( dma_intf ) |
| 742 | 745 | { |
| 743 | 746 | DEVCB_CPU_INPUT_LINE(Z80_TAG, INPUT_LINE_HALT), |
| r8806 | r8807 | |
|---|---|---|
| 752 | 752 | { |
| 753 | 753 | int i; |
| 754 | 754 | int nce2_enable = 1; |
| 755 | | |
| 755 | | |
| 756 | 756 | |
| 757 | 757 | hp48_io_addr = 0x100000; |
| 758 | 758 |
| r8806 | r8807 | |
|---|---|---|
| 338 | 338 | { |
| 339 | 339 | UINT16 bank; |
| 340 | 340 | UINT8 page; |
| 341 | | |
| 341 | | |
| 342 | 342 | |
| 343 | 343 | if (LOG_MEMORY) |
| 344 | 344 | { |
| r8806 | r8807 | |
| 622 | 622 | |
| 623 | 623 | addr = apple3_get_indexed_addr(space->machine,offset); |
| 624 | 624 | if (!addr) |
| 625 | result = | |
| 625 | result = space->r | |
| 626 | 626 | else if (addr != (UINT8 *) ~0) |
| 627 | 627 | result = *addr; |
| 628 | 628 | else |
| r8806 | r8807 | |
| 638 | 638 | |
| 639 | 639 | addr = apple3_get_indexed_addr(space->machine,offset); |
| 640 | 640 | if (!addr) |
| 641 | | |
| 641 | space-> | |
| 642 | 642 | else if (addr != (UINT8 *) ~0) |
| 643 | 643 | *addr = data; |
| 644 | 644 | } |
| 645 | 645 | |
| 646 | 646 | |
| 647 | 647 | |
| 648 | ||
| 648 | ||
| 649 | 649 | { |
| 650 | 650 | UINT8 *opptr; |
| 651 | 651 | |
| 652 | 652 | if ((address & 0xFF00) == 0x0000) |
| 653 | 653 | { |
| 654 | opptr = apple3_get_zpa_addr(space->machine,address); | |
| 655 | direct->bytemask = ~0; | |
| 656 | direct->raw = direct->decrypted = opptr - address; | |
| 657 | direct->bytestart = address; | |
| 658 | direct->byteend = address; | |
| 654 | opptr = apple3_get_zpa_addr(machine,address); | |
| 655 | direct.explicit_configure(address, address, ~0, opptr - address); | |
| 659 | 656 | address = ~0; |
| 660 | 657 | } |
| 661 | 658 | return address; |
| r8806 | r8807 | |
| 727 | 724 | via_1_irq = 0; |
| 728 | 725 | apple3_update_memory(machine); |
| 729 | 726 | |
| 730 | | |
| 727 | | |
| 731 | 728 | } |
| r8806 | r8807 | |
|---|---|---|
| 256 | 256 | if (offset <= 0x0ffff) |
| 257 | 257 | result = c64_memory[offset]; |
| 258 | 258 | else |
| 259 | result = | |
| 259 | result = space->r | |
| 260 | 260 | return result; |
| 261 | 261 | } |
| 262 | 262 | |
| r8806 | r8807 | |
| 265 | 265 | if (offset <= 0x0ffff) |
| 266 | 266 | c64_memory[offset] = data; |
| 267 | 267 | else |
| 268 | | |
| 268 | space-> | |
| 269 | 269 | } |
| 270 | 270 | |
| 271 | 271 | static struct { |
| r8806 | r8807 | |
| 303 | 303 | PAIR pair, src, dst, len; |
| 304 | 304 | UINT8 cmd, fill; |
| 305 | 305 | int i; |
| 306 | | |
| 306 | | |
| 307 | 307 | |
| 308 | 308 | switch (offset & 3) |
| 309 | 309 | { |
| r8806 | r8807 | |
|---|---|---|
| 174 | 174 | |
| 175 | 175 | INTERRUPT_GEN( mbee_interrupt ) |
| 176 | 176 | { |
| 177 | | |
| 177 | | |
| 178 | 178 | /* once per frame, pulse the PIO B bit 7 */ |
| 179 | 179 | mbee_vsync = 1; |
| 180 | 180 | |
| r8806 | r8807 | |
| 184 | 184 | |
| 185 | 185 | z80pio_astb_w( mbee_z80pio, centronics_busy_r(mbee_printer)); /* signal int when not busy (L->H) */ |
| 186 | 186 | |
| 187 | | |
| 187 | space-> | |
| 188 | 188 | } |
| 189 | 189 | |
| 190 | 190 | /*********************************************************** |
| r8806 | r8807 | |
| 199 | 199 | Z80BIN_EXECUTE( mbee ) |
| 200 | 200 | { |
| 201 | 201 | running_device *cpu = machine->device("maincpu"); |
| 202 | | |
| 202 | | |
| 203 | 203 | |
| 204 | | |
| 204 | space-> | |
| 205 | 205 | |
| 206 | 206 | if (autorun) |
| 207 | 207 | { |
| 208 | | |
| 208 | space-> | |
| 209 | 209 | cpu_set_reg(cpu, STATE_GENPC, execute_address); |
| 210 | 210 | } |
| 211 | 211 | else |
| 212 | 212 | { |
| 213 | | |
| 213 | space-> | |
| 214 | 214 | } |
| 215 | 215 | } |
| 216 | 216 | |
| 217 | 217 | QUICKLOAD_LOAD( mbee ) |
| 218 | 218 | { |
| 219 | 219 | running_device *cpu = image.device().machine->device("maincpu"); |
| 220 | | |
| 220 | | |
| 221 | 221 | UINT16 i, j; |
| 222 | 222 | UINT8 data, sw = input_port_read(image.device().machine, "CONFIG") & 1; /* reading the dipswitch: 1 = autorun */ |
| 223 | 223 | |
| r8806 | r8807 | |
| 235 | 235 | } |
| 236 | 236 | |
| 237 | 237 | if ((j < mbee_size) || (j > 0xefff)) |
| 238 | | |
| 238 | space-> | |
| 239 | 239 | else |
| 240 | 240 | { |
| 241 | 241 | image.message("Not enough memory in this microbee"); |
| r8806 | r8807 | |
| 245 | 245 | |
| 246 | 246 | if (sw) |
| 247 | 247 | { |
| 248 | | |
| 248 | space-> | |
| 249 | 249 | cpu_set_reg(cpu, STATE_GENPC, 0x801e); |
| 250 | 250 | } |
| 251 | 251 | else |
| 252 | | |
| 252 | space-> | |
| 253 | 253 | } |
| 254 | 254 | else if (!mame_stricmp(image.filetype(), "com")) |
| 255 | 255 | { |
| r8806 | r8807 | |
| 265 | 265 | } |
| 266 | 266 | |
| 267 | 267 | if ((j < mbee_size) || (j > 0xefff)) |
| 268 | | |
| 268 | space-> | |
| 269 | 269 | else |
| 270 | 270 | { |
| 271 | 271 | image.message("Not enough memory in this microbee"); |
| r8806 | r8807 | |
|---|---|---|
| 30 | 30 | |
| 31 | 31 | static void msx_cpu_setbank (running_machine *machine, int page, UINT8 *mem) |
| 32 | 32 | { |
| 33 | | |
| 33 | | |
| 34 | 34 | switch (page) |
| 35 | 35 | { |
| 36 | 36 | case 1: |
| r8806 | r8807 | |
| 402 | 402 | |
| 403 | 403 | MSX_SLOT_WRITE(konami_scc) |
| 404 | 404 | { |
| 405 | | |
| 405 | | |
| 406 | 406 | if (addr >= 0x5000 && addr < 0x5800) |
| 407 | 407 | { |
| 408 | 408 | state->banks[0] = val & state->bank_mask; |
| r8806 | r8807 | |
| 1300 | 1300 | |
| 1301 | 1301 | MSX_SLOT_MAP(diskrom) |
| 1302 | 1302 | { |
| 1303 | | |
| 1303 | | |
| 1304 | 1304 | switch (page) |
| 1305 | 1305 | { |
| 1306 | 1306 | case 0: |
| r8806 | r8807 | |
| 1425 | 1425 | |
| 1426 | 1426 | MSX_SLOT_MAP(diskrom2) |
| 1427 | 1427 | { |
| 1428 | | |
| 1428 | | |
| 1429 | 1429 | switch (page) |
| 1430 | 1430 | { |
| 1431 | 1431 | case 0: |
| r8806 | r8807 | |
| 1696 | 1696 | |
| 1697 | 1697 | MSX_SLOT_WRITE(fmpac) |
| 1698 | 1698 | { |
| 1699 | | |
| 1699 | | |
| 1700 | 1700 | int i, data; |
| 1701 | 1701 | |
| 1702 | 1702 | if (addr >= 0x4000 && addr < 0x6000 && state->cart.fmpac.sram_support) |
| r8806 | r8807 | |
| 2255 | 2255 | |
| 2256 | 2256 | MSX_SLOT_MAP(soundcartridge) |
| 2257 | 2257 | { |
| 2258 | | |
| 2258 | | |
| 2259 | 2259 | switch (page) |
| 2260 | 2260 | { |
| 2261 | 2261 | case 0: |
| r8806 | r8807 | |
| 2289 | 2289 | |
| 2290 | 2290 | MSX_SLOT_WRITE(soundcartridge) |
| 2291 | 2291 | { |
| 2292 | | |
| 2292 | | |
| 2293 | 2293 | int i; |
| 2294 | 2294 | |
| 2295 | 2295 | if (addr < 0x4000) |
| r8806 | r8807 | |
|---|---|---|
| 1442 | 1442 | |
| 1443 | 1443 | static TIMER_CALLBACK( pokemini_prc_counter_callback ) |
| 1444 | 1444 | { |
| 1445 | | |
| 1445 | | |
| 1446 | 1446 | prc.count++; |
| 1447 | 1447 | |
| 1448 | 1448 | /* Check for overflow */ |
| r8806 | r8807 | |
| 1466 | 1466 | UINT8 tile = pokemini_ram[ 0x360 + ( y * prc.map_size_x ) + x ]; |
| 1467 | 1467 | int i; |
| 1468 | 1468 | for( i = 0; i < 8; i++ ) { |
| 1469 | pokemini_ram[ ( y * 96 ) + ( x * 8 ) + i ] = | |
| 1469 | pokemini_ram[ ( y * 96 ) + ( x * 8 ) + i ] = space->r | |
| 1470 | 1470 | } |
| 1471 | 1471 | } |
| 1472 | 1472 | } |
| r8806 | r8807 | |
| 1497 | 1497 | int rel_x = ( spr_flag & 0x01 ) ? 15 - i : i; |
| 1498 | 1498 | UINT32 s = spr_base + ( ( rel_x & 0x08 ) << 2 ) + ( rel_x & 0x07 ); |
| 1499 | 1499 | |
| 1500 | mask = ~ ( memory_read_byte( space, s ) | ( memory_read_byte( space, s + 8 ) << 8 ) ); | |
| 1501 | gfx = memory_read_byte( space, s + 16 ) | ( memory_read_byte( space, s + 24 ) << 8 ); | |
| 1500 | mask = ~ ( space->read_byte( s ) | ( space->read_byte( s + 8 ) << 8 ) ); | |
| 1501 | gfx = space->read_byte( s + 16 ) | ( space->read_byte( s + 24 ) << 8 ); | |
| 1502 | 1502 | |
| 1503 | 1503 | /* Are the colors inverted? */ |
| 1504 | 1504 | if ( spr_flag & 0x04 ) |
| r8806 | r8807 | |
|---|---|---|
| 119 | 119 | |
| 120 | 120 | MACHINE_START( pc1350 ) |
| 121 | 121 | { |
| 122 | | |
| 122 | | |
| 123 | 123 | |
| 124 | 124 | timer_set(machine, ATTOTIME_IN_SEC(1), NULL, 0, pc1350_power_up); |
| 125 | 125 |
| r8806 | r8807 | |
|---|---|---|
| 780 | 780 | } |
| 781 | 781 | else |
| 782 | 782 | { |
| 783 | | |
| 783 | | |
| 784 | 784 | |
| 785 | 785 | /* data block - need to cap the maximum length of the block */ |
| 786 | 786 | block_length = MIN(block_length, length - position); |
| r8806 | r8807 | |
| 788 | 788 | /* read the block into memory */ |
| 789 | 789 | for (i = 0; i < block_length; i++) |
| 790 | 790 | { |
| 791 | | |
| 791 | space-> | |
| 792 | 792 | } |
| 793 | 793 | |
| 794 | 794 | /* and advance */ |
| r8806 | r8807 | |
| 2033 | 2033 | }; |
| 2034 | 2034 | |
| 2035 | 2035 | /* We need to init these vars from the sam, as this may be called from outside the sam callbacks */ |
| 2036 | | |
| 2036 | | |
| 2037 | 2037 | coco_state *state = machine->driver_data<coco_state>(); |
| 2038 | 2038 | UINT8 memsize = sam6883_memorysize(state->sam); |
| 2039 | 2039 | UINT8 maptype = sam6883_maptype(state->sam); |
| r8806 | r8807 | |
| 2373 | 2373 | { 0xfe00, 0xfeff } |
| 2374 | 2374 | }; |
| 2375 | 2375 | |
| 2376 | | |
| 2376 | | |
| 2377 | 2377 | int i, offset; |
| 2378 | 2378 | UINT8 *readbank; |
| 2379 | 2379 | UINT8 *cart_rom = memory_region(machine, "cart"); |
| r8806 | r8807 | |
|---|---|---|
| 206 | 206 | |
| 207 | 207 | static void gb_init(running_machine *machine) |
| 208 | 208 | { |
| 209 | | |
| 209 | | |
| 210 | 210 | |
| 211 | 211 | /* Initialize the memory banks */ |
| 212 | 212 | gb_driver_data.MBC1Mode = 0; |
| r8806 | r8807 | |
|---|---|---|
| 540 | 540 | if (! (hdc.w[1] & w1_transfer_inhibit)) |
| 541 | 541 | for (i=0; i<real_word_count; i++) |
| 542 | 542 | { |
| 543 | | |
| 543 | | |
| 544 | 544 | dma_address = (dma_address + 2) & 0x1ffffe; |
| 545 | 545 | } |
| 546 | 546 | |
| r8806 | r8807 | |
| 695 | 695 | if (! (hdc.w[1] & w1_transfer_inhibit)) |
| 696 | 696 | for (i=0; i<bytes_read; i+=2) |
| 697 | 697 | { |
| 698 | | |
| 698 | | |
| 699 | 699 | dma_address = (dma_address + 2) & 0x1ffffe; |
| 700 | 700 | } |
| 701 | 701 | |
| r8806 | r8807 | |
| 791 | 791 | /* DMA */ |
| 792 | 792 | for (i=0; (i<byte_count) && (i<hdc.d[dsk_sel].bytes_per_sector); i+=2) |
| 793 | 793 | { |
| 794 | word = | |
| 794 | word = | |
| 795 | 795 | buffer[i] = word >> 8; |
| 796 | 796 | buffer[i+1] = word & 0xff; |
| 797 | 797 | |
| r8806 | r8807 | |
| 898 | 898 | if (! (hdc.w[1] & w1_transfer_inhibit)) |
| 899 | 899 | for (i=0; i<real_word_count; i++) |
| 900 | 900 | { |
| 901 | | |
| 901 | | |
| 902 | 902 | dma_address = (dma_address + 2) & 0x1ffffe; |
| 903 | 903 | } |
| 904 | 904 |
| r8806 | r8807 | |
|---|---|---|
| 138 | 138 | i8257_hlda_w(device, state); |
| 139 | 139 | } |
| 140 | 140 | |
| 141 | static UINT8 memory_read_byte(address_space *space, offs_t address) { return space->read_byte(address); } | |
| 142 | static void memory_write_byte(address_space *space, offs_t address, UINT8 data) { space->write_byte(address, data); } | |
| 143 | ||
| 141 | 144 | I8257_INTERFACE( radio86_dma ) |
| 142 | 145 | { |
| 143 | 146 | DEVCB_LINE(hrq_w), |
| r8806 | r8807 | |
| 164 | 167 | |
| 165 | 168 | READ8_HANDLER (radio_io_r ) |
| 166 | 169 | { |
| 167 | return | |
| 170 | return | |
| 168 | 171 | } |
| 169 | 172 | |
| 170 | 173 | WRITE8_HANDLER(radio_io_w ) |
| 171 | 174 | { |
| 172 | | |
| 175 | | |
| 173 | 176 | } |
| 174 | 177 | |
| 175 | 178 | MACHINE_RESET( radio86 ) |
| r8806 | r8807 | |
|---|---|---|
| 43 | 43 | static void b2m_set_bank(running_machine *machine,int bank) |
| 44 | 44 | { |
| 45 | 45 | UINT8 *rom; |
| 46 | | |
| 46 | | |
| 47 | 47 | |
| 48 | 48 | memory_install_write_bank(space, 0x0000, 0x27ff, 0, 0, "bank1"); |
| 49 | 49 | memory_install_write_bank(space, 0x2800, 0x2fff, 0, 0, "bank2"); |
| r8806 | r8807 | |
|---|---|---|
| 170 | 170 | { |
| 171 | 171 | running_device *via_0 = machine->device("via6522_0"); |
| 172 | 172 | running_device *ram = machine->device("messram"); |
| 173 | | |
| 173 | | |
| 174 | 174 | |
| 175 | 175 | /* Init RAM */ |
| 176 | 176 | memory_install_ram(space, 0x0000, messram_get_size(ram) - 1, 0, 0, messram_get_ptr(ram)); |
| r8806 | r8807 | |
|---|---|---|
| 530 | 530 | |
| 531 | 531 | static void to7_update_cart_bank(running_machine *machine) |
| 532 | 532 | { |
| 533 | | |
| 533 | | |
| 534 | 534 | int bank = 0; |
| 535 | 535 | if ( thom_cart_nb_banks ) |
| 536 | 536 | { |
| r8806 | r8807 | |
| 1557 | 1557 | |
| 1558 | 1558 | MACHINE_START ( to7 ) |
| 1559 | 1559 | { |
| 1560 | | |
| 1560 | | |
| 1561 | 1561 | UINT8* mem = memory_region(machine, "maincpu"); |
| 1562 | 1562 | |
| 1563 | 1563 | LOG (( "to7: machine start called\n" )); |
| r8806 | r8807 | |
| 1638 | 1638 | static void to770_update_ram_bank(running_machine *machine) |
| 1639 | 1639 | { |
| 1640 | 1640 | running_device *sys_pia = machine->device( THOM_PIA_SYS ); |
| 1641 | | |
| 1641 | | |
| 1642 | 1642 | UINT8 portb = pia6821_get_port_b_z_mask( sys_pia ); |
| 1643 | 1643 | int bank; |
| 1644 | 1644 | |
| r8806 | r8807 | |
| 2062 | 2062 | |
| 2063 | 2063 | static void mo5_update_cart_bank(running_machine *machine) |
| 2064 | 2064 | { |
| 2065 | | |
| 2065 | | |
| 2066 | 2066 | int rom_is_ram = mo5_reg_cart & 4; |
| 2067 | 2067 | int bank = 0; |
| 2068 | 2068 | |
| r8806 | r8807 | |
| 2427 | 2427 | |
| 2428 | 2428 | static void to9_update_cart_bank(running_machine *machine) |
| 2429 | 2429 | { |
| 2430 | | |
| 2430 | | |
| 2431 | 2431 | int bank = 0; |
| 2432 | 2432 | int slot = ( mc6846_get_output_port(machine->device("mc6846")) >> 4 ) & 3; /* bits 4-5: ROM bank */ |
| 2433 | 2433 | |
| r8806 | r8807 | |
| 2511 | 2511 | static void to9_update_ram_bank (running_machine *machine) |
| 2512 | 2512 | { |
| 2513 | 2513 | running_device *sys_pia = machine->device( THOM_PIA_SYS ); |
| 2514 | | |
| 2514 | | |
| 2515 | 2515 | UINT8 port = mc6846_get_output_port(machine->device("mc6846")); |
| 2516 | 2516 | UINT8 portb = pia6821_get_port_b_z_mask( sys_pia ); |
| 2517 | 2517 | UINT8 disk = ((port >> 2) & 1) | ((port >> 5) & 2); /* bits 6,2: RAM bank */ |
| r8806 | r8807 | |
| 3569 | 3569 | static void to8_update_ram_bank (running_machine *machine) |
| 3570 | 3570 | { |
| 3571 | 3571 | running_device *sys_pia = machine->device( THOM_PIA_SYS ); |
| 3572 | | |
| 3572 | | |
| 3573 | 3573 | UINT8 bank = 0; |
| 3574 | 3574 | |
| 3575 | 3575 | if ( to8_reg_sys1 & 0x10 ) |
| r8806 | r8807 | |
| 3639 | 3639 | |
| 3640 | 3640 | static void to8_update_cart_bank (running_machine *machine) |
| 3641 | 3641 | { |
| 3642 | | |
| 3642 | | |
| 3643 | 3643 | int bank = 0; |
| 3644 | 3644 | |
| 3645 | 3645 | /* reset bank switch */ |
| r8806 | r8807 | |
| 4405 | 4405 | static void mo6_update_cart_bank (running_machine *machine) |
| 4406 | 4406 | { |
| 4407 | 4407 | running_device *sys_pia = machine->device( THOM_PIA_SYS ); |
| 4408 | | |
| 4408 | | |
| 4409 | 4409 | int b = (pia6821_get_output_a( sys_pia ) >> 5) & 1; |
| 4410 | 4410 | int bank = 0; |
| 4411 | 4411 |
| r8806 | r8807 | |
|---|---|---|
| 39 | 39 | |
| 40 | 40 | static void pmd851_update_memory(running_machine *machine) |
| 41 | 41 | { |
| 42 | | |
| 42 | | |
| 43 | 43 | |
| 44 | 44 | if (pmd85_startup_mem_map) |
| 45 | 45 | { |
| r8806 | r8807 | |
| 82 | 82 | |
| 83 | 83 | static void pmd852a_update_memory(running_machine *machine) |
| 84 | 84 | { |
| 85 | | |
| 85 | | |
| 86 | 86 | |
| 87 | 87 | if (pmd85_startup_mem_map) |
| 88 | 88 | { |
| r8806 | r8807 | |
| 154 | 154 | |
| 155 | 155 | static void alfa_update_memory(running_machine *machine) |
| 156 | 156 | { |
| 157 | | |
| 157 | | |
| 158 | 158 | |
| 159 | 159 | if (pmd85_startup_mem_map) |
| 160 | 160 | { |
| r8806 | r8807 | |
| 186 | 186 | |
| 187 | 187 | static void mato_update_memory(running_machine *machine) |
| 188 | 188 | { |
| 189 | | |
| 189 | | |
| 190 | 190 | |
| 191 | 191 | if (pmd85_startup_mem_map) |
| 192 | 192 | { |
| r8806 | r8807 | |
| 210 | 210 | |
| 211 | 211 | static void c2717_update_memory(running_machine *machine) |
| 212 | 212 | { |
| 213 | | |
| 213 | | |
| 214 | 214 | |
| 215 | 215 | UINT8 *mem = memory_region(machine, "maincpu"); |
| 216 | 216 | if (pmd85_startup_mem_map) |
| r8806 | r8807 | |
| 848 | 848 | machine->schedule_soft_reset(); |
| 849 | 849 | } |
| 850 | 850 | |
| 851 | ||
| 851 | ||
| 852 | 852 | { |
| 853 | if (input_port_read(space->machine, "RESET") & 0x01) | |
| 854 | timer_set(space->machine, ATTOTIME_IN_USEC(10), NULL, 0, pmd_reset); | |
| 853 | if (input_port_read(machine, "RESET") & 0x01) | |
| 854 | timer_set(machine, ATTOTIME_IN_USEC(10), NULL, 0, pmd_reset); | |
| 855 | 855 | return address; |
| 856 | 856 | } |
| 857 | 857 | |
| r8806 | r8807 | |
| 945 | 945 | |
| 946 | 946 | timer_set(machine, attotime_zero, NULL, 0, setup_machine_state); |
| 947 | 947 | |
| 948 | | |
| 948 | | |
| 949 | 949 | } |
| r8806 | r8807 | |
|---|---|---|
| 1106 | 1106 | |
| 1107 | 1107 | c128_bankswitch_64(device->machine, 0); |
| 1108 | 1108 | |
| 1109 | c64_memory[0x000] = memory_read_byte( cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM), 0 ); | |
| 1110 | c64_memory[0x001] = memory_read_byte( cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM), 1 ); | |
| 1109 | c64_memory[0x000] = cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM)->read_byte(0); | |
| 1110 | c64_memory[0x001] = cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM)->read_byte(1); | |
| 1111 | ||
| 1111 | 1112 | } |
| 1112 | 1113 | |
| 1113 | 1114 | UINT8 c128_m6510_port_read( running_device *device, UINT8 direction ) |
| r8806 | r8807 | |
|---|---|---|
| 295 | 295 | { |
| 296 | 296 | vic1112_t *vic1112 = get_safe_token(device); |
| 297 | 297 | const vic1112_config *config = get_safe_config(device); |
| 298 | | |
| 298 | | |
| 299 | 299 | |
| 300 | 300 | /* find devices */ |
| 301 | 301 | vic1112->via0 = device->subdevice(M6522_0_TAG); |
| r8806 | r8807 | |
|---|---|---|
| 116 | 116 | // single byte or word transfer |
| 117 | 117 | running_device* device = (running_device*)ptr; |
| 118 | 118 | upd71071_t* dmac = (upd71071_t*)downcast<legacy_device_base *>(device)->token(); |
| 119 | | |
| 119 | | |
| 120 | 120 | int channel = param; |
| 121 | 121 | UINT16 data = 0; // data to transfer |
| 122 | 122 | |
| r8806 | r8807 | |
| 127 | 127 | case 0x04: // I/O -> memory |
| 128 | 128 | if(dmac->intf->dma_read[channel]) |
| 129 | 129 | data = dmac->intf->dma_read[channel](device->machine); |
| 130 | | |
| 130 | space-> | |
| 131 | 131 | if(dmac->reg.mode_control[channel] & 0x20) // Address direction |
| 132 | 132 | dmac->reg.address_current[channel]--; |
| 133 | 133 | else |
| r8806 | r8807 | |
| 145 | 145 | dmac->reg.count_current[channel]--; |
| 146 | 146 | break; |
| 147 | 147 | case 0x08: // memory -> I/O |
| 148 | data = | |
| 148 | data = space->r | |
| 149 | 149 | if(dmac->intf->dma_read[channel]) |
| 150 | 150 | dmac->intf->dma_write[channel](device->machine,data); |
| 151 | 151 | if(dmac->reg.mode_control[channel] & 0x20) // Address direction |
| r8806 | r8807 | |
|---|---|---|
| 451 | 451 | |
| 452 | 452 | MACHINE_RESET( c16 ) |
| 453 | 453 | { |
| 454 | | |
| 454 | | |
| 455 | 455 | c16_state *state = machine->driver_data<c16_state>(); |
| 456 | 456 | |
| 457 | 457 | memset(state->keyline, 0xff, ARRAY_LENGTH(state->keyline)); |
| r8806 | r8807 | |
| 508 | 508 | |
| 509 | 509 | static TIMER_CALLBACK( c16_sidhack_tick ) |
| 510 | 510 | { |
| 511 | | |
| 511 | | |
| 512 | 512 | c16_state *state = space->machine->driver_data<c16_state>(); |
| 513 | 513 | |
| 514 | 514 | if (input_port_read_safe(machine, "SID", 0x00) & 0x02) |
| r8806 | r8807 | |
| 528 | 528 | static TIMER_CALLBACK( c16_sidcard_tick ) |
| 529 | 529 | { |
| 530 | 530 | c16_state *state = machine->driver_data<c16_state>(); |
| 531 | | |
| 531 | | |
| 532 | 532 | |
| 533 | 533 | if (input_port_read_safe(machine, "SID", 0x00) & 0x01) |
| 534 | 534 | memory_install_readwrite8_device_handler(space, state->sid, 0xfe80, 0xfe9f, 0, 0, sid6581_r, sid6581_w); |
| r8806 | r8807 | |
|---|---|---|
| 161 | 161 | /* this port is also used to read printer data */ |
| 162 | 162 | static READ8_DEVICE_HANDLER ( oric_via_in_a_func ) |
| 163 | 163 | { |
| 164 | | |
| 164 | | |
| 165 | 165 | |
| 166 | 166 | /*logerror("port a read\r\n"); */ |
| 167 | 167 | |
| r8806 | r8807 | |
| 463 | 463 | static void oric_install_apple2_interface(running_machine *machine) |
| 464 | 464 | { |
| 465 | 465 | running_device *fdc = machine->device("fdc"); |
| 466 | | |
| 466 | | |
| 467 | 467 | |
| 468 | 468 | if (oric_is_telestrat) |
| 469 | 469 | return; |
| r8806 | r8807 | |
| 481 | 481 | static void oric_enable_memory(running_machine *machine, int low, int high, int rd, int wr) |
| 482 | 482 | { |
| 483 | 483 | int i; |
| 484 | | |
| 484 | | |
| 485 | 485 | |
| 486 | 486 | if (oric_is_telestrat) |
| 487 | 487 | return; |
| r8806 | r8807 | |
| 585 | 585 | static void oric_install_apple2_v2_interface(running_machine *machine) |
| 586 | 586 | { |
| 587 | 587 | running_device *fdc = machine->device("fdc"); |
| 588 | | |
| 588 | | |
| 589 | 589 | |
| 590 | 590 | memory_install_read8_handler(space, 0x0300, 0x030f, 0, 0, oric_IO_r); |
| 591 | 591 | memory_install_read8_device_handler(space, fdc, 0x0310, 0x031f, 0, 0, applefdc_r); |
| r8806 | r8807 | |
| 788 | 788 | |
| 789 | 789 | static void oric_install_jasmin_interface(running_machine *machine) |
| 790 | 790 | { |
| 791 | | |
| 791 | | |
| 792 | 792 | /* romdis */ |
| 793 | 793 | port_3fb_w = 1; |
| 794 | 794 | oric_jasmin_set_mem_0x0c000(machine); |
| r8806 | r8807 | |
| 1010 | 1010 | |
| 1011 | 1011 | static void oric_install_microdisc_interface(running_machine *machine) |
| 1012 | 1012 | { |
| 1013 | | |
| 1013 | | |
| 1014 | 1014 | |
| 1015 | 1015 | memory_install_read8_handler(space, 0x0300, 0x030f, 0, 0, oric_IO_r); |
| 1016 | 1016 | memory_install_read8_handler(space, 0x0310, 0x031f, 0, 0, oric_microdisc_r); |
| r8806 | r8807 | |
| 1084 | 1084 | MACHINE_RESET( oric ) |
| 1085 | 1085 | { |
| 1086 | 1086 | int disc_interface_id = input_port_read(machine, "FLOPPY") & 0x07; |
| 1087 | | |
| 1087 | | |
| 1088 | 1088 | if (oric_is_telestrat) |
| 1089 | 1089 | return; |
| 1090 | 1090 | |
| r8806 | r8807 | |
| 1294 | 1294 | |
| 1295 | 1295 | static void telestrat_refresh_mem(running_machine *machine) |
| 1296 | 1296 | { |
| 1297 | | |
| 1297 | | |
| 1298 | 1298 | |
| 1299 | 1299 | struct telestrat_mem_block *mem_block = &telestrat_blocks[telestrat_bank_selection]; |
| 1300 | 1300 |
| r8806 | r8807 | |
|---|---|---|
| 168 | 168 | |
| 169 | 169 | static void init_at_common(running_machine *machine, const struct kbdc8042_interface *at8042) |
| 170 | 170 | { |
| 171 | | |
| 171 | | |
| 172 | 172 | mess_init_pc_common(machine, PCCOMMON_KEYBOARD_AT, at_set_keyb_int, at_set_irq_line); |
| 173 | 173 | mc146818_init(machine, MC146818_STANDARD); |
| 174 | 174 | soundblaster_config(&soundblaster); |
| r8806 | r8807 | |
| 268 | 268 | offs_t page_offset = (((offs_t) dma_offset[0][dma_channel]) << 16) |
| 269 | 269 | & 0xFF0000; |
| 270 | 270 | |
| 271 | result = | |
| 271 | result = space->r | |
| 272 | 272 | return result; |
| 273 | 273 | } |
| 274 | 274 | |
| r8806 | r8807 | |
| 278 | 278 | offs_t page_offset = (((offs_t) dma_offset[0][dma_channel]) << 16) |
| 279 | 279 | & 0xFF0000; |
| 280 | 280 | |
| 281 | | |
| 281 | space-> | |
| 282 | 282 | } |
| 283 | 283 | |
| 284 | 284 |
| r8806 | r8807 | |
|---|---|---|
| 178 | 178 | |
| 179 | 179 | MACHINE_RESET( vector06 ) |
| 180 | 180 | { |
| 181 | | |
| 181 | | |
| 182 | 182 | |
| 183 | 183 | cpu_set_irq_callback(machine->device("maincpu"), vector06_irq_callback); |
| 184 | 184 | memory_install_read_bank (space, 0x0000, 0x7fff, 0, 0, "bank1"); |
| r8806 | r8807 | |
|---|---|---|
| 37 | 37 | static void usbsm_cru_w(running_machine *machine, int offset, int data); |
| 38 | 38 | static READ8_HANDLER(usbsm_mem_r); |
| 39 | 39 | static WRITE8_HANDLER(usbsm_mem_w); |
| 40 | static UINT16 usbsm_mem_16_r(const address_space* space,offs_t offset); | |
| 41 | static void usbsm_mem_16_w(const address_space* space,offs_t offset, UINT16 data); | |
| 40 | static UINT16 usbsm_mem_16_r(address_space* space,offs_t offset); | |
| 41 | static void usbsm_mem_16_w(address_space* space,offs_t offset, UINT16 data); | |
| 42 | 42 | |
| 43 | 43 | /* pointer to the SRAM area */ |
| 44 | 44 | static UINT16 *ti99_usbsm_RAM; |
| r8806 | r8807 | |
| 224 | 224 | /* |
| 225 | 225 | demultiplexed read in USB-SmartMedia DSR space |
| 226 | 226 | */ |
| 227 | static UINT16 usbsm_mem_16_r( | |
| 227 | static UINT16 usbsm_mem_16_r( | |
| 228 | 228 | { |
| 229 | 229 | UINT16 reply = 0; |
| 230 | 230 | running_device *smartmedia =space->machine->device("smartmedia"); |
| r8806 | r8807 | |
| 258 | 258 | /* |
| 259 | 259 | demultiplexed write in USB-SmartMedia DSR space |
| 260 | 260 | */ |
| 261 | static void usbsm_mem_16_w( | |
| 261 | static void usbsm_mem_16_w( | |
| 262 | 262 | { |
| 263 | 263 | running_device *smartmedia =space->machine->device("smartmedia"); |
| 264 | 264 | if (offset < 0x800) |
| r8806 | r8807 | |
|---|---|---|
| 279 | 279 | { |
| 280 | 280 | UINT8 bank_select; |
| 281 | 281 | UINT8 segment_select; |
| 282 | | |
| 282 | | |
| 283 | 283 | |
| 284 | 284 | bank_select = (orionz80_dispatcher & 0x0c) >> 2; |
| 285 | 285 | segment_select = orionz80_dispatcher & 0x03; |
| r8806 | r8807 | |
| 339 | 339 | |
| 340 | 340 | MACHINE_RESET ( orionz80 ) |
| 341 | 341 | { |
| 342 | | |
| 342 | | |
| 343 | 343 | |
| 344 | 344 | memory_unmap_write(space, 0x0000, 0x3fff, 0, 0); |
| 345 | 345 | memory_install_write_bank(space, 0x4000, 0xefff, 0, 0, "bank2"); |
| r8806 | r8807 | |
| 430 | 430 | |
| 431 | 431 | static void orionpro_bank_switch(running_machine *machine) |
| 432 | 432 | { |
| 433 | | |
| 433 | | |
| 434 | 434 | int page = orionpro_page & 7; // we have only 8 pages |
| 435 | 435 | int is128 = (orionpro_dispatcher & 0x80) ? 1 : 0; |
| 436 | 436 | if (is128==1) |
| r8806 | r8807 | |
|---|---|---|
| 318 | 318 | if ( fdc->fdc_status[drive].mfm[cur_pos-2] == ( ( sync >> 8 ) & 0xff ) && |
| 319 | 319 | fdc->fdc_status[drive].mfm[cur_pos-1] == ( sync & 0xff ) ) |
| 320 | 320 | { |
| 321 | | |
| 321 | | |
| 322 | 322 | |
| 323 | 323 | amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKSYN, 0xffff); |
| 324 | 324 | } |
| r8806 | r8807 | |
| 362 | 362 | { |
| 363 | 363 | if ( fdc->fdc_status[drive].len > 0 ) |
| 364 | 364 | { |
| 365 | | |
| 365 | | |
| 366 | 366 | |
| 367 | 367 | logerror("Write to disk unsupported yet\n" ); |
| 368 | 368 | |
| r8806 | r8807 | |
| 399 | 399 | |
| 400 | 400 | if ( fdc->fdc_status[drive].len <= 0 ) |
| 401 | 401 | { |
| 402 | | |
| 402 | | |
| 403 | 403 | |
| 404 | 404 | amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKBLK, 0xffff); |
| 405 | 405 | } |
| r8806 | r8807 | |
| 432 | 432 | } |
| 433 | 433 | |
| 434 | 434 | if ( drive == -1 ) { |
| 435 | | |
| 435 | | |
| 436 | 436 | |
| 437 | 437 | logerror("Disk DMA started with no drive selected!\n" ); |
| 438 | 438 | amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKBLK, 0xffff); |
| r8806 | r8807 | |
|---|---|---|
| 76 | 76 | |
| 77 | 77 | static void a7800_driver_init(running_machine *machine, int ispal, int lines) |
| 78 | 78 | { |
| 79 | | |
| 79 | | |
| 80 | 80 | ROM = memory_region(machine, "maincpu"); |
| 81 | 81 | a7800_ispal = ispal; |
| 82 | 82 | a7800_lines = lines; |
| r8806 | r8807 | |
| 109 | 109 | MACHINE_RESET( a7800 ) |
| 110 | 110 | { |
| 111 | 111 | UINT8 *memory; |
| 112 | | |
| 112 | | |
| 113 | 113 | |
| 114 | 114 | a7800_ctrl_lock = 0; |
| 115 | 115 | a7800_ctrl_reg = 0; |
| r8806 | r8807 | |
|---|---|---|
| 235 | 235 | if (sscanf((char *)line, "%x %x %x %x %x %x %x %x %x %x\010\010\n", |
| 236 | 236 | &addr, &b0, &b1, &b2, &b3, &b4, &b5, &b6, &b7, &dummy) == 10) |
| 237 | 237 | { |
| 238 | memory_write_byte(cputag_get_address_space(image.device().machine,"maincpu",ADDRESS_SPACE_PROGRAM), addr++, b0); | |
| 239 | memory_write_byte(cputag_get_address_space(image.device().machine,"maincpu",ADDRESS_SPACE_PROGRAM), addr++, b1); | |
| 240 | memory_write_byte(cputag_get_address_space(image.device().machine,"maincpu",ADDRESS_SPACE_PROGRAM), addr++, b2); | |
| 241 | memory_write_byte(cputag_get_address_space(image.device().machine,"maincpu",ADDRESS_SPACE_PROGRAM), addr++, b3); | |
| 242 | memory_write_byte(cputag_get_address_space(image.device().machine,"maincpu",ADDRESS_SPACE_PROGRAM), addr++, b4); | |
| 243 | memory_write_byte(cputag_get_address_space(image.device().machine,"maincpu",ADDRESS_SPACE_PROGRAM), addr++, b5); | |
| 244 | memory_write_byte(cputag_get_address_space(image.device().machine,"maincpu",ADDRESS_SPACE_PROGRAM), addr++, b6); | |
| 245 | memory_write_byte(cputag_get_address_space(image.device().machine,"maincpu",ADDRESS_SPACE_PROGRAM), addr++, b7); | |
| 238 | cputag_get_address_space(image.device().machine,"maincpu",ADDRESS_SPACE_PROGRAM)->write_byte(addr++, b0); | |
| 239 | cputag_get_address_space(image.device().machine,"maincpu",ADDRESS_SPACE_PROGRAM)->write_byte(addr++, b1); | |
| 240 | cputag_get_address_space(image.device().machine,"maincpu",ADDRESS_SPACE_PROGRAM)->write_byte(addr++, b2); | |
| 241 | cputag_get_address_space(image.device().machine,"maincpu",ADDRESS_SPACE_PROGRAM)->write_byte(addr++, b3); | |
| 242 | cputag_get_address_space(image.device().machine,"maincpu",ADDRESS_SPACE_PROGRAM)->write_byte(addr++, b4); | |
| 243 | cputag_get_address_space(image.device().machine,"maincpu",ADDRESS_SPACE_PROGRAM)->write_byte(addr++, b5); | |
| 244 | cputag_get_address_space(image.device().machine,"maincpu",ADDRESS_SPACE_PROGRAM)->write_byte(addr++, b6); | |
| 245 | cputag_get_address_space(image.device().machine,"maincpu",ADDRESS_SPACE_PROGRAM)->write_byte(addr++, b7); | |
| 246 | 246 | } |
| 247 | 247 | } |
| 248 | 248 |
| r8806 | r8807 | |
|---|---|---|
| 518 | 518 | { |
| 519 | 519 | UINT8 *dst = memory_region(machine, "gfx2"); |
| 520 | 520 | int i; |
| 521 | | |
| 521 | | |
| 522 | 522 | |
| 523 | 523 | for (i = 0; i < 256; i++) |
| 524 | 524 | { |
| r8806 | r8807 | |
|---|---|---|
| 220 | 220 | } |
| 221 | 221 | |
| 222 | 222 | |
| 223 | ||
| 223 | ||
| 224 | 224 | { |
| 225 | 225 | if ( ( address & 0xF000 ) == 0x2000 ) |
| 226 | 226 | { |
| 227 | 227 | if ( ! osborne1.bank2_enabled ) |
| 228 | 228 | { |
| 229 | direct->bytemask = 0x0fff; | |
| 230 | direct->decrypted = messram_get_ptr(space->machine->device("messram")) + 0x2000; | |
| 231 | direct->raw = messram_get_ptr(space->machine->device("messram")) + 0x2000; | |
| 232 | direct->bytestart = 0x2000; | |
| 233 | direct->byteend = 0x2fff; | |
| 229 | direct.explicit_configure(0x2000, 0x2fff, 0x0fff, messram_get_ptr(machine->device("messram")) + 0x2000); | |
| 234 | 230 | return ~0; |
| 235 | 231 | } |
| 236 | 232 | } |
| r8806 | r8807 | |
| 350 | 346 | |
| 351 | 347 | static TIMER_CALLBACK(osborne1_video_callback) |
| 352 | 348 | { |
| 353 | | |
| 349 | | |
| 354 | 350 | running_device *speaker = space->machine->device("beep"); |
| 355 | 351 | running_device *pia_1 = space->machine->device("pia_1"); |
| 356 | 352 | int y = machine->primary_screen->vpos(); |
| r8806 | r8807 | |
| 452 | 448 | MACHINE_RESET( osborne1 ) |
| 453 | 449 | { |
| 454 | 450 | int drive; |
| 455 | | |
| 451 | | |
| 456 | 452 | /* Initialize memory configuration */ |
| 457 | 453 | osborne1_bankswitch_w( space, 0x00, 0 ); |
| 458 | 454 | |
| r8806 | r8807 | |
| 471 | 467 | floppy_install_load_proc(floppy_get_device(machine, drive), osborne1_load_proc); |
| 472 | 468 | } |
| 473 | 469 | |
| 474 | | |
| 470 | space-> | |
| 475 | 471 | } |
| 476 | 472 | |
| 477 | 473 | |
| r8806 | r8807 | |
| 577 | 573 | { |
| 578 | 574 | /* Enable ROM and I/O when IRQ is acknowledged */ |
| 579 | 575 | UINT8 old_bankswitch = osborne1.bankswitch; |
| 580 | | |
| 576 | | |
| 581 | 577 | |
| 582 | 578 | osborne1_bankswitch_w( space, 0, 0 ); |
| 583 | 579 | osborne1.bankswitch = old_bankswitch; |
| r8806 | r8807 | |
|---|---|---|
| 1365 | 1365 | |
| 1366 | 1366 | |
| 1367 | 1367 | /* used to setup computer if a snapshot was specified */ |
| 1368 | ||
| 1368 | ||
| 1369 | 1369 | { |
| 1370 | 1370 | int pc; |
| 1371 | 1371 | |
| 1372 | pc = cpu_get_pc( | |
| 1372 | pc = cpu_get_pc( | |
| 1373 | 1373 | |
| 1374 | 1374 | /* there are two places where CALL &0065 can be found |
| 1375 | 1375 | in the multiface rom. At this address there is a RET. |
| r8806 | r8807 | |
| 1398 | 1398 | multiface_flags &= ~(MULTIFACE_VISIBLE|MULTIFACE_STOP_BUTTON_PRESSED); |
| 1399 | 1399 | |
| 1400 | 1400 | /* clear op base override */ |
| 1401 | | |
| 1401 | //cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM)->set_direct_update_handler(NULL | |
| 1402 | 1402 | } |
| 1403 | 1403 | |
| 1404 | 1404 | return pc; |
| r8806 | r8807 | |
| 1490 | 1490 | cputag_set_input_line(machine, "maincpu", INPUT_LINE_NMI, PULSE_LINE); |
| 1491 | 1491 | |
| 1492 | 1492 | /* initialise 0065 override to monitor calls to 0065 */ |
| 1493 | | |
| 1493 | | |
| 1494 | 1494 | } |
| 1495 | 1495 | |
| 1496 | 1496 | } |
| r8806 | r8807 | |
| 1654 | 1654 | } |
| 1655 | 1655 | else // CPC+/GX4000 |
| 1656 | 1656 | { |
| 1657 | | |
| 1657 | | |
| 1658 | 1658 | |
| 1659 | 1659 | if ( asic.enabled && ( asic.rmr2 & 0x18 ) == 0x18 ) |
| 1660 | 1660 | { |
| r8806 | r8807 | |
| 2592 | 2592 | /* load CPCEMU style snapshots */ |
| 2593 | 2593 | static void amstrad_handle_snapshot(running_machine *machine, unsigned char *pSnapshot) |
| 2594 | 2594 | { |
| 2595 | | |
| 2595 | | |
| 2596 | 2596 | running_device *mc6845 = space->machine->device("mc6845" ); |
| 2597 | 2597 | running_device *ay8910 = machine->device("ay"); |
| 2598 | 2598 | int RegData; |
| r8806 | r8807 | |
| 2863 | 2863 | static unsigned char amstrad_Psg_FunctionSelected; |
| 2864 | 2864 | static void update_psg(running_machine *machine) |
| 2865 | 2865 | { |
| 2866 | | |
| 2866 | | |
| 2867 | 2867 | running_device *ay8910 = machine->device("ay"); |
| 2868 | 2868 | |
| 2869 | 2869 | if(aleste_mode & 0x20) // RTC selected |
| r8806 | r8807 | |
| 3227 | 3227 | |
| 3228 | 3228 | static void amstrad_common_init(running_machine *machine) |
| 3229 | 3229 | { |
| 3230 | | |
| 3230 | | |
| 3231 | 3231 | |
| 3232 | 3232 | aleste_mode = 0; |
| 3233 | 3233 |
| r8806 | r8807 | |
|---|---|---|
| 97 | 97 | static sms_driver_data sms_state; |
| 98 | 98 | |
| 99 | 99 | |
| 100 | static void setup_rom( | |
| 100 | static void setup_rom( | |
| 101 | 101 | |
| 102 | 102 | |
| 103 | 103 | static TIMER_CALLBACK( rapid_fire_callback ) |
| r8806 | r8807 | |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | 266 | |
| 267 | static void sms_get_inputs( | |
| 267 | static void sms_get_inputs( | |
| 268 | 268 | { |
| 269 | 269 | UINT8 data = 0x00; |
| 270 | 270 | UINT32 cpu_cycles = downcast<cpu_device *>(space->cpu)->total_cycles(); |
| r8806 | r8807 | |
| 978 | 978 | } |
| 979 | 979 | |
| 980 | 980 | |
| 981 | static void setup_rom( | |
| 981 | static void setup_rom( | |
| 982 | 982 | { |
| 983 | 983 | running_machine *machine = space->machine; |
| 984 | 984 | |
| r8806 | r8807 | |
| 1417 | 1417 | /* Terebi Oekaki (TV Draw) is a SG1000 game with special input device which is compatible with SG1000 Mark III */ |
| 1418 | 1418 | if ((detect_tvdraw(sms_state.cartridge[index].ROM)) && sms_state.is_region_japan) |
| 1419 | 1419 | { |
| 1420 | | |
| 1420 | | |
| 1421 | 1421 | memory_install_write8_handler(program, 0x6000, 0x6000, 0, 0, &sms_tvdraw_axis_w); |
| 1422 | 1422 | memory_install_read8_handler(program, 0x8000, 0x8000, 0, 0, &sms_tvdraw_status_r); |
| 1423 | 1423 | memory_install_read8_handler(program, 0xa000, 0xa000, 0, 0, &sms_tvdraw_data_r); |
| r8806 | r8807 | |
| 1502 | 1502 | |
| 1503 | 1503 | MACHINE_RESET( sms ) |
| 1504 | 1504 | { |
| 1505 | | |
| 1505 | | |
| 1506 | 1506 | running_device *smsvdp = machine->device("sms_vdp"); |
| 1507 | 1507 | |
| 1508 | 1508 | sms_state.ctrl_reg = 0xff; |
| r8806 | r8807 | |
|---|---|---|
| 261 | 261 | |
| 262 | 262 | SNAPSHOT_LOAD( poly88 ) |
| 263 | 263 | { |
| 264 | | |
| 264 | | |
| 265 | 265 | UINT8* data= auto_alloc_array(image.device().machine, UINT8, snapshot_size); |
| 266 | 266 | UINT16 recordNum; |
| 267 | 267 | UINT16 recordLen; |
| r8806 | r8807 | |
|---|---|---|
| 916 | 916 | } |
| 917 | 917 | |
| 918 | 918 | |
| 919 | static void mmc1_set_wram( | |
| 919 | static void mmc1_set_wram( | |
| 920 | 920 | { |
| 921 | 921 | running_machine *machine = space->machine; |
| 922 | 922 | nes_state *state = machine->driver_data<nes_state>(); |
| r8806 | r8807 | |
| 988 | 988 | } |
| 989 | 989 | } |
| 990 | 990 | |
| 991 | static void mmc1_set_prg_wram( | |
| 991 | static void mmc1_set_prg_wram( | |
| 992 | 992 | { |
| 993 | 993 | mmc1_set_prg(space->machine); |
| 994 | 994 | mmc1_set_wram(space, board); |
| r8806 | r8807 | |
| 1008 | 1008 | chr8(machine, (state->mmc_reg[1] & 0x1f) >> 1, state->mmc_chr_source); |
| 1009 | 1009 | } |
| 1010 | 1010 | |
| 1011 | static void common_sxrom_write_handler( | |
| 1011 | static void common_sxrom_write_handler( | |
| 1012 | 1012 | { |
| 1013 | 1013 | running_machine *machine = space->machine; |
| 1014 | 1014 | nes_state *state = machine->driver_data<nes_state>(); |
| r8806 | r8807 | |
| 1205 | 1205 | |
| 1206 | 1206 | *************************************************************/ |
| 1207 | 1207 | |
| 1208 | static void mmc3_set_wram( | |
| 1208 | static void mmc3_set_wram( | |
| 1209 | 1209 | { |
| 1210 | 1210 | running_machine *machine = space->machine; |
| 1211 | 1211 | nes_state *state = machine->driver_data<nes_state>(); |
| r8806 | r8807 | |
| 4401 | 4401 | LOG_MMC(("agci_50282_w, offset: %04x, data: %02x\n", offset, data)); |
| 4402 | 4402 | |
| 4403 | 4403 | offset += 0x8000; |
| 4404 | data |= ( | |
| 4404 | data |= (space->r | |
| 4405 | 4405 | |
| 4406 | 4406 | chr8(space->machine, data >> 4, CHRROM); |
| 4407 | 4407 | prg32(space->machine, data); |
| r8806 | r8807 | |
| 6436 | 6436 | |
| 6437 | 6437 | *************************************************************/ |
| 6438 | 6438 | |
| 6439 | static void common_s8259_write_handler( | |
| 6439 | static void common_s8259_write_handler( | |
| 6440 | 6440 | { |
| 6441 | 6441 | nes_state *state = space->machine->driver_data<nes_state>(); |
| 6442 | 6442 | UINT8 bank_helper1, bank_helper2, shift, add1, add2, add3; |
| r8806 | r8807 | |
| 8589 | 8589 | if (!state->mmc_reg[3] && offset > 0x1000) |
| 8590 | 8590 | { |
| 8591 | 8591 | state->mmc_reg[3] = 1; |
| 8592 | | |
| 8592 | space-> | |
| 8593 | 8593 | } |
| 8594 | 8594 | } |
| 8595 | 8595 |
| r8806 | r8807 | |
|---|---|---|
| 111 | 111 | |
| 112 | 112 | MACHINE_RESET( llc2 ) |
| 113 | 113 | { |
| 114 | | |
| 114 | | |
| 115 | 115 | |
| 116 | 116 | memory_unmap_write(space, 0x0000, 0x3fff, 0, 0); |
| 117 | 117 | memory_set_bankptr(machine, "bank1", memory_region(machine, "maincpu")); |
| r8806 | r8807 | |
| 129 | 129 | |
| 130 | 130 | WRITE8_HANDLER( llc2_rom_disable_w ) |
| 131 | 131 | { |
| 132 | | |
| 132 | | |
| 133 | 133 | |
| 134 | 134 | memory_install_write_bank(mem_space, 0x0000, 0xbfff, 0, 0, "bank1"); |
| 135 | 135 | memory_set_bankptr(space->machine, "bank1", messram_get_ptr(space->machine->device("messram"))); |
| r8806 | r8807 | |
| 148 | 148 | WRITE8_HANDLER( llc2_basic_enable_w ) |
| 149 | 149 | { |
| 150 | 150 | |
| 151 | | |
| 151 | | |
| 152 | 152 | if (data & 0x02) { |
| 153 | 153 | memory_unmap_write(mem_space, 0x4000, 0x5fff, 0, 0); |
| 154 | 154 | memory_set_bankptr(space->machine, "bank2", memory_region(space->machine, "maincpu") + 0x10000); |
| r8806 | r8807 | |
|---|---|---|
| 22 | 22 | MEMORY BANKING |
| 23 | 23 | ***************************************************************************/ |
| 24 | 24 | |
| 25 | static void samcoupe_update_bank( | |
| 25 | static void samcoupe_update_bank( | |
| 26 | 26 | { |
| 27 | 27 | char bank[10]; |
| 28 | 28 | sprintf(bank,"bank%d",bank_num); |
| r8806 | r8807 | |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | 44 | |
| 45 | static void samcoupe_install_ext_mem( | |
| 45 | static void samcoupe_install_ext_mem( | |
| 46 | 46 | { |
| 47 | 47 | coupe_asic *asic = space->machine->driver_data<coupe_asic>(); |
| 48 | 48 | UINT8 *mem; |
| r8806 | r8807 | |
| 65 | 65 | } |
| 66 | 66 | |
| 67 | 67 | |
| 68 | void samcoupe_update_memory( | |
| 68 | void samcoupe_update_memory( | |
| 69 | 69 | { |
| 70 | 70 | coupe_asic *asic = space->machine->driver_data<coupe_asic>(); |
| 71 | 71 | const int PAGE_MASK = ((messram_get_size(space->machine->device("messram")) & 0xfffff) / 0x4000) - 1; |
| r8806 | r8807 | |
| 139 | 139 | |
| 140 | 140 | WRITE8_HANDLER( samcoupe_ext_mem_w ) |
| 141 | 141 | { |
| 142 | | |
| 142 | | |
| 143 | 143 | coupe_asic *asic = space->machine->driver_data<coupe_asic>(); |
| 144 | 144 | |
| 145 | 145 | if (offset & 1) |
| r8806 | r8807 | |
| 242 | 242 | |
| 243 | 243 | MACHINE_RESET( samcoupe ) |
| 244 | 244 | { |
| 245 | const address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); | |
| 246 | const address_space *spaceio = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_IO); | |
| 245 | address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); | |
| 246 | address_space *spaceio = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_IO); | |
| 247 | 247 | coupe_asic *asic = machine->driver_data<coupe_asic>(); |
| 248 | 248 | |
| 249 | 249 | /* initialize asic */ |
| r8806 | r8807 | |
|---|---|---|
| 198 | 198 | {FLOPPY_0, FLOPPY_1, FLOPPY_2, FLOPPY_3} |
| 199 | 199 | }; |
| 200 | 200 | |
| 201 | static UINT8 fdc_r( | |
| 201 | static UINT8 fdc_r( | |
| 202 | 202 | { |
| 203 | 203 | comx35_state *state = space->machine->driver_data<comx35_state>(); |
| 204 | 204 | running_device *fdc = space->machine->device(WD1770_TAG); |
| r8806 | r8807 | |
| 217 | 217 | return data; |
| 218 | 218 | } |
| 219 | 219 | |
| 220 | static void fdc_w( | |
| 220 | static void fdc_w( | |
| 221 | 221 | { |
| 222 | 222 | running_device *fdc = space->machine->device(WD1770_TAG); |
| 223 | 223 | /* |
| r8806 | r8807 | |
| 383 | 383 | static void set_active_bank(running_machine *machine) |
| 384 | 384 | { |
| 385 | 385 | comx35_state *state = machine->driver_data<comx35_state>(); |
| 386 | | |
| 386 | | |
| 387 | 387 | int bank = state->bank; |
| 388 | 388 | |
| 389 | 389 | switch (state->bank) |
| r8806 | r8807 | |
| 568 | 568 | state->cdp1802_mode = CDP1802_MODE_RUN; |
| 569 | 569 | } |
| 570 | 570 | |
| 571 | ||
| 571 | ||
| 572 | 572 | { |
| 573 | 573 | if (address >= 0x0dd0 && address <= 0x0ddf) |
| 574 | 574 | { |
| 575 | if (dos_card_active( | |
| 575 | if (dos_card_active( | |
| 576 | 576 | { |
| 577 | 577 | // read opcode from DOS ROM |
| 578 | direct | |
| 578 | direct. | |
| 579 | 579 | return ~0; |
| 580 | 580 | } |
| 581 | 581 | } |
| r8806 | r8807 | |
| 591 | 591 | MACHINE_START( comx35p ) |
| 592 | 592 | { |
| 593 | 593 | comx35_state *state = machine->driver_data<comx35_state>(); |
| 594 | | |
| 594 | | |
| 595 | 595 | |
| 596 | 596 | /* opbase handling for DOS Card */ |
| 597 | 597 | |
| 598 | | |
| 598 | pr | |
| 599 | 599 | |
| 600 | 600 | /* BASIC ROM banking */ |
| 601 | 601 |
| r8806 | r8807 | |
|---|---|---|
| 263 | 263 | d0 Select bit 0 */ |
| 264 | 264 | |
| 265 | 265 | /* get address space instead of io space */ |
| 266 | | |
| 266 | | |
| 267 | 267 | |
| 268 | 268 | trs80_mode = (trs80_mode & 0x73) | (data & 0x8c); |
| 269 | 269 | |
| r8806 | r8807 | |
| 401 | 401 | d0 Video banking exists yes/no (1=not banked) */ |
| 402 | 402 | |
| 403 | 403 | /* get address space instead of io space */ |
| 404 | | |
| 404 | | |
| 405 | 405 | |
| 406 | 406 | trs80_model4 &= 0xf7; |
| 407 | 407 | trs80_model4 |= (data << 3); |
| r8806 | r8807 | |
| 610 | 610 | d0 inverse video (entire screen) */ |
| 611 | 611 | |
| 612 | 612 | /* get address space instead of io space */ |
| 613 | | |
| 613 | | |
| 614 | 614 | |
| 615 | 615 | trs80_mode = (trs80_mode & 0x87) | ((data & 0x0f) << 3); |
| 616 | 616 | |
| r8806 | r8807 | |
| 912 | 912 | |
| 913 | 913 | MACHINE_RESET( trs80m4 ) |
| 914 | 914 | { |
| 915 | | |
| 915 | | |
| 916 | 916 | cassette_data = 0; |
| 917 | 917 | |
| 918 | 918 | memory_install_read_bank (mem, 0x0000, 0x0fff, 0, 0, "bank1"); |
| r8806 | r8807 | |
| 940 | 940 | |
| 941 | 941 | MACHINE_RESET( lnw80 ) |
| 942 | 942 | { |
| 943 | | |
| 943 | | |
| 944 | 944 | cassette_data = 0; |
| 945 | 945 | trs80_reg_load = 1; |
| 946 | 946 | lnw80_fe_w(space, 0, 0); |
| r8806 | r8807 | |
|---|---|---|
| 47 | 47 | |
| 48 | 48 | static void primo_update_memory(running_machine *machine) |
| 49 | 49 | { |
| 50 | | |
| 50 | | |
| 51 | 51 | switch (primo_port_FD & 0x03) |
| 52 | 52 | { |
| 53 | 53 | case 0x00: /* Original ROM */ |
| r8806 | r8807 | |
| 301 | 301 | /* memory */ |
| 302 | 302 | |
| 303 | 303 | for (i=0; i<0xc000; i++) |
| 304 | | |
| 304 | | |
| 305 | 305 | } |
| 306 | 306 | |
| 307 | 307 | SNAPSHOT_LOAD( primo ) |
| r8806 | r8807 | |
| 347 | 347 | start_addr = quickload_data[2] + quickload_data[3]*256; |
| 348 | 348 | |
| 349 | 349 | for (i=4; i<quickload_size; i++) |
| 350 | | |
| 350 | | |
| 351 | 351 | |
| 352 | 352 | cpu_set_reg(machine->device("maincpu"), Z80_PC, start_addr); |
| 353 | 353 |
| r8806 | r8807 | |
|---|---|---|
| 101 | 101 | |
| 102 | 102 | static void update_ti83p_memory (running_machine *machine) |
| 103 | 103 | { |
| 104 | | |
| 104 | | |
| 105 | 105 | |
| 106 | 106 | if (ti8x_memory_page_1 & 0x40) |
| 107 | 107 | { |
| r8806 | r8807 | |
| 162 | 162 | |
| 163 | 163 | static void update_ti86_memory (running_machine *machine) |
| 164 | 164 | { |
| 165 | | |
| 165 | | |
| 166 | 166 | |
| 167 | 167 | if (ti8x_memory_page_1 & 0x40) |
| 168 | 168 | { |
| r8806 | r8807 | |
| 194 | 194 | |
| 195 | 195 | MACHINE_START( ti81 ) |
| 196 | 196 | { |
| 197 | | |
| 197 | | |
| 198 | 198 | UINT8 *mem = memory_region(machine, "maincpu"); |
| 199 | 199 | |
| 200 | 200 | ti85_timer_interrupt_mask = 0; |
| r8806 | r8807 | |
| 228 | 228 | |
| 229 | 229 | MACHINE_START( ti82 ) |
| 230 | 230 | { |
| 231 | | |
| 231 | | |
| 232 | 232 | UINT8 *mem = memory_region(machine, "maincpu"); |
| 233 | 233 | |
| 234 | 234 | ti85_timer_interrupt_mask = 0; |
| r8806 | r8807 | |
| 269 | 269 | |
| 270 | 270 | MACHINE_START( ti85 ) |
| 271 | 271 | { |
| 272 | | |
| 272 | | |
| 273 | 273 | UINT8 *mem = memory_region(machine, "maincpu"); |
| 274 | 274 | |
| 275 | 275 | ti85_timer_interrupt_mask = 0; |
| r8806 | r8807 | |
| 311 | 311 | |
| 312 | 312 | MACHINE_START( ti83p ) |
| 313 | 313 | { |
| 314 | | |
| 314 | | |
| 315 | 315 | UINT8 *mem = memory_region(machine, "maincpu"); |
| 316 | 316 | |
| 317 | 317 | ti85_timer_interrupt_mask = 0; |
| r8806 | r8807 | |
| 363 | 363 | |
| 364 | 364 | MACHINE_START( ti86 ) |
| 365 | 365 | { |
| 366 | | |
| 366 | | |
| 367 | 367 | UINT8 *mem = memory_region(machine, "maincpu"); |
| 368 | 368 | |
| 369 | 369 | ti85_timer_interrupt_mask = 0; |
| r8806 | r8807 | |
| 882 | 882 | |
| 883 | 883 | static void ti85_setup_snapshot (running_machine *machine, UINT8 * data) |
| 884 | 884 | { |
| 885 | | |
| 885 | | |
| 886 | 886 | int i; |
| 887 | 887 | unsigned char lo,hi; |
| 888 | 888 | unsigned char * hdw = data + 0x8000 + 0x94; |
| r8806 | r8807 | |
| 891 | 891 | |
| 892 | 892 | /* Memory dump */ |
| 893 | 893 | for (i = 0; i < 0x8000; i++) |
| 894 | | |
| 894 | space-> | |
| 895 | 895 | |
| 896 | 896 | ti85_keypad_mask = hdw[0x00]&0x7f; |
| 897 | 897 |
| r8806 | r8807 | |
|---|---|---|
| 157 | 157 | |
| 158 | 158 | DRIVER_INIT( galaxy ) |
| 159 | 159 | { |
| 160 | | |
| 160 | | |
| 161 | 161 | memory_install_readwrite_bank( space, 0x2800, 0x2800 + messram_get_size(machine->device("messram")) - 1, 0, 0, "bank1"); |
| 162 | 162 | memory_set_bankptr(machine, "bank1", messram_get_ptr(machine->device("messram"))); |
| 163 | 163 | |
| r8806 | r8807 | |
| 173 | 173 | |
| 174 | 174 | MACHINE_RESET( galaxy ) |
| 175 | 175 | { |
| 176 | | |
| 176 | | |
| 177 | 177 | |
| 178 | 178 | /* ROM 2 enable/disable */ |
| 179 | 179 | if (input_port_read(machine, "ROM2")) { |
| r8806 | r8807 | |
| 198 | 198 | MACHINE_RESET( galaxyp ) |
| 199 | 199 | { |
| 200 | 200 | UINT8 *ROM = memory_region(machine, "maincpu"); |
| 201 | | |
| 201 | | |
| 202 | 202 | |
| 203 | 203 | cpu_set_irq_callback(machine->device("maincpu"), galaxy_irq_callback); |
| 204 | 204 |
| r8806 | r8807 | |
|---|---|---|
| 723 | 723 | c1551->bit_timer = timer_alloc(device->machine, bit_tick, (void *)device); |
| 724 | 724 | |
| 725 | 725 | /* map TPI1 to host CPU memory space */ |
| 726 | | |
| 726 | | |
| 727 | 727 | UINT32 start_address = c1551->address ? 0xfec0 : 0xfef0; |
| 728 | 728 | |
| 729 | 729 | memory_install_readwrite8_device_handler(program, c1551->tpi1, start_address, start_address + 7, 0, 0, tpi6525_r, tpi6525_w); |
| r8806 | r8807 | |
|---|---|---|
| 259 | 259 | |
| 260 | 260 | MACHINE_RESET( wswan ) |
| 261 | 261 | { |
| 262 | | |
| 262 | | |
| 263 | 263 | |
| 264 | 264 | /* Intialize ports */ |
| 265 | 265 | memcpy( ws_portram, ws_portram_init, 256 ); |
| r8806 | r8807 | |
| 728 | 728 | length = ws_portram[0x46] + (ws_portram[0x47] << 8); |
| 729 | 729 | for( ; length > 0; length-- ) |
| 730 | 730 | { |
| 731 | | |
| 731 | space-> | |
| 732 | 732 | src++; |
| 733 | 733 | dst++; |
| 734 | 734 | } |
| r8806 | r8807 | |
| 1485 | 1485 | /* Handle Sound DMA */ |
| 1486 | 1486 | if ( ( sound_dma.enable & 0x88 ) == 0x80 ) |
| 1487 | 1487 | { |
| 1488 | | |
| 1488 | | |
| 1489 | 1489 | /* TODO: Output sound DMA byte */ |
| 1490 | wswan_port_w( space, 0x89, | |
| 1490 | wswan_port_w( space, 0x89, space->r | |
| 1491 | 1491 | sound_dma.size--; |
| 1492 | 1492 | sound_dma.source = ( sound_dma.source + 1 ) & 0x0FFFFF; |
| 1493 | 1493 | if ( sound_dma.size == 0 ) |
| r8806 | r8807 | |
|---|---|---|
| 31 | 31 | |
| 32 | 32 | if (data & 0x40) |
| 33 | 33 | { |
| 34 | | |
| 34 | space-> | |
| 35 | 35 | RAM[offset | 0xc000] = data; |
| 36 | 36 | } |
| 37 | 37 | else |
| 38 | 38 | { |
| 39 | | |
| 39 | space-> | |
| 40 | 40 | RAM[offset | 0xc000] = 0; |
| 41 | 41 | } |
| 42 | 42 | } |
| r8806 | r8807 | |
| 50 | 50 | |
| 51 | 51 | DRIVER_INIT ( zx ) |
| 52 | 52 | { |
| 53 | | |
| 53 | | |
| 54 | 54 | |
| 55 | 55 | memory_install_read_bank(space, 0x4000, 0x4000 + messram_get_size(machine->device("messram")) - 1, 0, 0, "bank1"); |
| 56 | 56 | memory_install_write8_handler(space, 0x4000, 0x4000 + messram_get_size(machine->device("messram")) - 1, 0, 0, zx_ram_w); |
| 57 | 57 | memory_set_bankptr(machine, "bank1", memory_region(machine, "maincpu") + 0x4000); |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | ||
| 60 | ||
| 61 | 61 | { |
| 62 | 62 | if (address & 0xc000) |
| 63 | zx_ula_r( | |
| 63 | zx_ula_r( | |
| 64 | 64 | return address; |
| 65 | 65 | } |
| 66 | 66 | |
| 67 | ||
| 67 | ||
| 68 | 68 | { |
| 69 | 69 | if (address & 0xc000) |
| 70 | zx_ula_r( | |
| 70 | zx_ula_r( | |
| 71 | 71 | return address; |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | ||
| 74 | ||
| 75 | 75 | { |
| 76 | 76 | if (address & 0xc000) |
| 77 | zx_ula_r( | |
| 77 | zx_ula_r( | |
| 78 | 78 | return address; |
| 79 | 79 | } |
| 80 | 80 | |
| 81 | 81 | MACHINE_RESET ( zx80 ) |
| 82 | 82 | { |
| 83 | | |
| 83 | | |
| 84 | 84 | zx_tape_bit = 0x80; |
| 85 | 85 | } |
| 86 | 86 | |
| 87 | 87 | MACHINE_RESET ( pow3000 ) |
| 88 | 88 | { |
| 89 | | |
| 89 | | |
| 90 | 90 | zx_tape_bit = 0x80; |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | 93 | MACHINE_RESET ( pc8300 ) |
| 94 | 94 | { |
| 95 | | |
| 95 | | |
| 96 | 96 | zx_tape_bit = 0x80; |
| 97 | 97 | } |
| 98 | 98 |
| r8806 | r8807 | |
|---|---|---|
| 202 | 202 | /* |
| 203 | 203 | * Handle NMI delay for single step instruction |
| 204 | 204 | */ |
| 205 | ||
| 205 | ||
| 206 | 206 | { |
| 207 | 207 | nmi_delay_counter--; |
| 208 | 208 | |
| 209 | 209 | if (!nmi_delay_counter) |
| 210 | 210 | { |
| 211 | memory_set_direct_update_handler( space, NULL ); | |
| 212 | cputag_set_input_line(space->machine, "z80ne", INPUT_LINE_NMI, PULSE_LINE); | |
| 211 | //cputag_get_address_space(machine, "z80ne", ADDRESS_SPACE_PROGRAM)->set_direct_update_handler(NULL); | |
| 212 | cputag_set_input_line(machine, "z80ne", INPUT_LINE_NMI, PULSE_LINE); | |
| 213 | 213 | } |
| 214 | 214 | return address; |
| 215 | 215 | } |
| r8806 | r8807 | |
| 218 | 218 | * Handle delayed ROM/RAM banking at RESET |
| 219 | 219 | * after the first reset_delay_counter bytes have been read from ROM, switch the RAM back in |
| 220 | 220 | */ |
| 221 | ||
| 221 | ||
| 222 | 222 | { |
| 223 | address_space *space = cputag_get_address_space(machine, "z80ne", ADDRESS_SPACE_PROGRAM); | |
| 223 | 224 | /* |
| 224 | 225 | * TODO: when debugger is active, his memory access causes this callback |
| 225 | 226 | * |
| 226 | 227 | */ |
| 227 | if(!space->debugger_access) | |
| 228 | if(!space->debugger_access()) | |
| 228 | 229 | reset_delay_counter--; |
| 229 | 230 | |
| 230 | 231 | if (!reset_delay_counter) |
| 231 | 232 | { |
| 232 | 233 | /* remove this callback */ |
| 233 | | |
| 234 | //cputag_get_address_space(machine, "z80ne", ADDRESS_SPACE_PROGRAM)->set_direct_update_handler( | |
| 234 | 235 | /* and switch to RAM bank at address 0x0000 */ |
| 235 | 236 | memory_set_bank( space->machine, "bank1", 0 ); /* RAM at 0x0000 (bank 1) */ |
| 236 | 237 | } |
| r8806 | r8807 | |
| 246 | 247 | |
| 247 | 248 | static void reset_lx382_banking(running_machine *machine) |
| 248 | 249 | { |
| 249 | | |
| 250 | | |
| 250 | 251 | |
| 251 | 252 | /* switch to ROM bank at address 0x0000 */ |
| 252 | 253 | memory_set_bank(machine, "bank1", 1); |
| r8806 | r8807 | |
| 254 | 255 | |
| 255 | 256 | /* after the first 3 bytes have been read from ROM, switch the RAM back in */ |
| 256 | 257 | reset_delay_counter = 2; |
| 257 | | |
| 258 | space-> | |
| 258 | 259 | } |
| 259 | 260 | |
| 260 | 261 | static void reset_lx390_banking(running_machine *machine) |
| 261 | 262 | { |
| 262 | | |
| 263 | | |
| 263 | 264 | reset_delay_counter = 0; |
| 264 | 265 | |
| 265 | 266 | switch (input_port_read(machine, "CONFIG") & 0x07) { |
| r8806 | r8807 | |
| 272 | 273 | memory_set_bank(machine, "bank4", 0); /* RAM at 0xF000 */ |
| 273 | 274 | /* after the first 3 bytes have been read from ROM, switch the RAM back in */ |
| 274 | 275 | reset_delay_counter = 2; |
| 275 | | |
| 276 | space-> | |
| 276 | 277 | break; |
| 277 | 278 | case 0x02: /* EP548 16k BASIC */ |
| 278 | 279 | if (VERBOSE) |
| r8806 | r8807 | |
| 281 | 282 | memory_set_bank(machine, "bank2", 1); /* ep548 at 0x0400-0x3FFF */ |
| 282 | 283 | memory_set_bank(machine, "bank3", 0); /* RAM at 0x8000 */ |
| 283 | 284 | memory_set_bank(machine, "bank4", 0); /* RAM at 0xF000 */ |
| 284 | | |
| 285 | //cputag_get_address_space(machine, "z80ne", ADDRESS_SPACE_PROGRAM)->set_direct_update_handler( | |
| 285 | 286 | break; |
| 286 | 287 | case 0x03: /* EP390 Boot Loader for 5.5k floppy BASIC */ |
| 287 | 288 | if (VERBOSE) |
| r8806 | r8807 | |
| 290 | 291 | memory_set_bank(machine, "bank2", 0); /* RAM at 0x0400-0x3FFF */ |
| 291 | 292 | memory_set_bank(machine, "bank3", 0); /* RAM at 0x8000 */ |
| 292 | 293 | memory_set_bank(machine, "bank4", 1); /* ep390 at 0xF000 */ |
| 293 | | |
| 294 | //cputag_get_address_space(machine, "z80ne", ADDRESS_SPACE_PROGRAM)->set_direct_update_handler( | |
| 294 | 295 | break; |
| 295 | 296 | case 0x04: /* EP1390 Boot Loader for NE DOS 1.0/1.5 */ |
| 296 | 297 | if (VERBOSE) |
| r8806 | r8807 | |
| 299 | 300 | memory_set_bank(machine, "bank2", 0); /* RAM at 0x0400-0x3FFF */ |
| 300 | 301 | memory_set_bank(machine, "bank3", 0); /* RAM at 0x8000 */ |
| 301 | 302 | memory_set_bank(machine, "bank4", 2); /* ep1390 at 0xF000 */ |
| 302 | | |
| 303 | //cputag_get_address_space(machine, "z80ne", ADDRESS_SPACE_PROGRAM)->set_direct_update_handler( | |
| 303 | 304 | break; |
| 304 | 305 | case 0x05: /* EP2390 Boot Loader for NE DOS G.1 */ |
| 305 | 306 | if (VERBOSE) |
| r8806 | r8807 | |
| 308 | 309 | memory_set_bank(machine, "bank2", 0); /* RAM at 0x0400-0x3FFF */ |
| 309 | 310 | memory_set_bank(machine, "bank3", 0); /* RAM at 0x8000 */ |
| 310 | 311 | memory_set_bank(machine, "bank4", 3); /* ep2390 at 0xF000 */ |
| 311 | | |
| 312 | //cputag_get_address_space(machine, "z80ne", ADDRESS_SPACE_PROGRAM)->set_direct_update_handler( | |
| 312 | 313 | break; |
| 313 | 314 | } |
| 314 | 315 | |
| r8806 | r8807 | |
| 320 | 321 | static MACHINE_RESET(z80ne_base) |
| 321 | 322 | { |
| 322 | 323 | int i; |
| 323 | | |
| 324 | | |
| 324 | 325 | |
| 325 | 326 | LOG(("In MACHINE_RESET z80ne_base\n")); |
| 326 | 327 | |
| r8806 | r8807 | |
| 512 | 513 | else |
| 513 | 514 | /* after writing to port 0xF8 and the first ~M1 cycles strike a NMI for single step execution */ |
| 514 | 515 | nmi_delay_counter = 1; |
| 515 | ||
| 516 | ||
| 516 | 517 | } |
| 517 | 518 | |
| 518 | 519 |
| r8806 | r8807 | |
|---|---|---|
| 1578 | 1578 | |
| 1579 | 1579 | |
| 1580 | 1580 | |
| 1581 | ||
| 1581 | ||
| 1582 | 1582 | { |
| 1583 | 1583 | UINT8 *opptr = NULL; |
| 1584 | 1584 | int slot; |
| r8806 | r8807 | |
| 1587 | 1587 | { |
| 1588 | 1588 | if ((apple2gs_shadow & 0x40) && ((address & 0xF00000) == 0x000000)) |
| 1589 | 1589 | { |
| 1590 | opptr = &messram_get_ptr( | |
| 1590 | opptr = &messram_get_ptr( | |
| 1591 | 1591 | } |
| 1592 | 1592 | else if ((address & 0x000F00) == 0x000000) |
| 1593 | 1593 | { |
| 1594 | 1594 | if (((address & 0xFF) >= 0x71) && ((address & 0xFF) <= 0x7F)) |
| 1595 | opptr = apple2gs_getslotmem( | |
| 1595 | opptr = apple2gs_getslotmem( | |
| 1596 | 1596 | } |
| 1597 | 1597 | else |
| 1598 | 1598 | { |
| 1599 | 1599 | slot = (address & 0x000F00) / 0x100; |
| 1600 | 1600 | |
| 1601 | 1601 | if ((slot > 7) || ((apple2gs_sltromsel & (1 << slot)) == 0)) |
| 1602 | opptr = apple2gs_getslotmem( | |
| 1602 | opptr = apple2gs_getslotmem( | |
| 1603 | 1603 | } |
| 1604 | 1604 | |
| 1605 | 1605 | if (opptr != NULL) |
| 1606 | 1606 | { |
| 1607 | direct->bytemask = ~0; | |
| 1608 | direct->raw = direct->decrypted = opptr - address; | |
| 1609 | direct->bytestart = address; | |
| 1610 | direct->byteend = address; | |
| 1607 | direct.explicit_configure(address, address, ~0, opptr - address); | |
| 1608 | ||
| 1611 | 1609 | address = ~0; |
| 1612 | 1610 | } |
| 1613 | 1611 | } |
| r8806 | r8807 | |
| 1654 | 1652 | |
| 1655 | 1653 | static void apple2gs_setup_memory(running_machine *machine) |
| 1656 | 1654 | { |
| 1657 | | |
| 1655 | | |
| 1658 | 1656 | offs_t begin, end; |
| 1659 | 1657 | apple2_memmap_config cfg; |
| 1660 | 1658 | |
| r8806 | r8807 | |
| 1691 | 1689 | memory_install_write8_handler(space, 0xe0c000, 0xe0cfff, 0, 0, apple2gs_E0Cxxx_w); |
| 1692 | 1690 | memory_install_read8_handler(space, 0xe1c000, 0xe1cfff, 0, 0, apple2gs_E1Cxxx_r); |
| 1693 | 1691 | memory_install_write8_handler(space, 0xe1c000, 0xe1cfff, 0, 0, apple2gs_E1Cxxx_w); |
| 1694 | memory_set_direct_update_handler(space, apple2gs_opbase); | |
| 1692 | space->set_direct_update_handler(direct_update_delegate_create_static(apple2gs_opbase, *machine)); | |
| 1693 | ||
| 1695 | 1694 | |
| 1696 | 1695 | /* install aux memory writes (for shadowing) */ |
| 1697 | 1696 | memory_install_write8_handler(space, 0x010400, 0x0107FF, 0, 0, apple2gs_aux0400_w); |
| r8806 | r8807 | |
| 1715 | 1714 | |
| 1716 | 1715 | static READ8_HANDLER( apple2gs_read_vector ) |
| 1717 | 1716 | { |
| 1718 | return | |
| 1717 | return space->r | |
| 1719 | 1718 | } |
| 1720 | 1719 | |
| 1721 | 1720 | MACHINE_RESET( apple2gs ) |
| r8806 | r8807 | |
|---|---|---|
| 195 | 195 | static void mac_install_memory(running_machine *machine, offs_t memory_begin, offs_t memory_end, |
| 196 | 196 | offs_t memory_size, void *memory_data, int is_rom, const char *bank) |
| 197 | 197 | { |
| 198 | | |
| 198 | | |
| 199 | 199 | offs_t memory_mask; |
| 200 | 200 | |
| 201 | 201 | memory_size = MIN(memory_size, (memory_end + 1 - memory_begin)); |
| r8806 | r8807 | |
| 2753 | 2753 | } |
| 2754 | 2754 | |
| 2755 | 2755 | |
| 2756 | ||
| 2756 | ||
| 2757 | 2757 | { |
| 2758 | mac_state *mac = | |
| 2758 | mac_state *mac = | |
| 2759 | 2759 | |
| 2760 | 2760 | if (mac->mac_overlay != -1) |
| 2761 | 2761 | { |
| r8806 | r8807 | |
| 2763 | 2763 | { |
| 2764 | 2764 | if ((address >= 0x900000) && (address <= 0x9fffff)) |
| 2765 | 2765 | { |
| 2766 | set_memory_overlay( | |
| 2766 | set_memory_overlay( | |
| 2767 | 2767 | mac->mac_overlay = -1; |
| 2768 | 2768 | } |
| 2769 | 2769 | } |
| r8806 | r8807 | |
| 2771 | 2771 | { |
| 2772 | 2772 | if ((address >= 0x400000) && (address <= 0x4fffff)) |
| 2773 | 2773 | { |
| 2774 | set_memory_overlay( | |
| 2774 | set_memory_overlay( | |
| 2775 | 2775 | mac->mac_overlay = -1; |
| 2776 | 2776 | } |
| 2777 | 2777 | } |
| r8806 | r8807 | |
| 2779 | 2779 | { |
| 2780 | 2780 | if ((address >= 0xa00000) && (address <= 0xafffff)) |
| 2781 | 2781 | { |
| 2782 | set_memory_overlay( | |
| 2782 | set_memory_overlay( | |
| 2783 | 2783 | mac->mac_overlay = -1; |
| 2784 | 2784 | } |
| 2785 | 2785 | } |
| r8806 | r8807 | |
| 2787 | 2787 | { |
| 2788 | 2788 | if ((address >= 0x40000000) && (address <= 0x4fffffff)) |
| 2789 | 2789 | { |
| 2790 | set_memory_overlay( | |
| 2790 | set_memory_overlay( | |
| 2791 | 2791 | mac->mac_overlay = -1; |
| 2792 | 2792 | } |
| 2793 | 2793 | } |
| r8806 | r8807 | |
| 2834 | 2834 | (model == MODEL_MAC_LC_II) || (model == MODEL_MAC_LC_III) || ((mac->mac_model >= MODEL_MAC_II) && (mac->mac_model <= MODEL_MAC_SE30)) || |
| 2835 | 2835 | (model == MODEL_MAC_PORTABLE) || (model == MODEL_MAC_PB100)) |
| 2836 | 2836 | { |
| 2837 | | |
| 2837 | | |
| 2838 | 2838 | } |
| 2839 | 2839 | |
| 2840 | 2840 | /* setup keyboard */ |
| r8806 | r8807 | |
|---|---|---|
| 39 | 39 | /* TODO: Fix me properly! changing all cpus???? */ |
| 40 | 40 | for (bool gotone = machine->config->m_devicelist.first(cpu); gotone; gotone = cpu->typenext()) |
| 41 | 41 | { |
| 42 | | |
| 42 | | |
| 43 | 43 | |
| 44 | 44 | /* first clear everything out */ |
| 45 | 45 | memory_nop_read(space, 0x00000000, 0x3FFFFFFF, 0, 0); |
| r8806 | r8807 | |
| 70 | 70 | /* TODO: Fix me properly! changing all cpus??? */ |
| 71 | 71 | for (bool gotone = machine->config->m_devicelist.first(cpu); gotone; gotone = cpu->typenext()) |
| 72 | 72 | { |
| 73 | | |
| 73 | | |
| 74 | 74 | |
| 75 | 75 | memory_install_read64_handler(space, begin, end, |
| 76 | 76 | 0, 0, (read64_space_func) (FPTR)(bank + mpc105->bank_base)); |
| r8806 | r8807 | |
|---|---|---|
| 357 | 357 | /* DMA */ |
| 358 | 358 | for (i=0; i<bytes_read; i+=2) |
| 359 | 359 | { |
| 360 | | |
| 360 | | |
| 361 | 361 | dma_address = (dma_address + 2) & 0x1ffffe; |
| 362 | 362 | } |
| 363 | 363 |
| r8806 | r8807 | |
|---|---|---|
| 388 | 388 | |
| 389 | 389 | static void dmac_install(running_machine *machine, offs_t base) |
| 390 | 390 | { |
| 391 | | |
| 391 | | |
| 392 | 392 | memory_install_read16_handler(space, base, base + 0xFFFF, 0, 0, amiga_dmac_r); |
| 393 | 393 | memory_install_write16_handler(space, base, base + 0xFFFF, 0, 0, amiga_dmac_w); |
| 394 | 394 | } |
| 395 | 395 | |
| 396 | 396 | static void dmac_uninstall(running_machine *machine, offs_t base) |
| 397 | 397 | { |
| 398 | | |
| 398 | | |
| 399 | 399 | memory_unmap_readwrite(space, base, base + 0xFFFF, 0, 0); |
| 400 | 400 | } |
| 401 | 401 |
| r8806 | r8807 | |
|---|---|---|
| 36 | 36 | static void init_nes_core( running_machine *machine ) |
| 37 | 37 | { |
| 38 | 38 | nes_state *state = machine->driver_data<nes_state>(); |
| 39 | | |
| 39 | | |
| 40 | 40 | static const char *const bank_names[] = { "bank1", "bank2", "bank3", "bank4" }; |
| 41 | 41 | int prg_banks = (state->prg_chunks == 1) ? (2 * 2) : (state->prg_chunks * 2); |
| 42 | 42 | int i; |
| r8806 | r8807 | |
|---|---|---|
| 149 | 149 | |
| 150 | 150 | READ8_HANDLER( mz800_bank_0_r ) |
| 151 | 151 | { |
| 152 | | |
| 152 | | |
| 153 | 153 | mz_state *mz = space->machine->driver_data<mz_state>(); |
| 154 | 154 | |
| 155 | 155 | /* switch in cgrom */ |
| r8806 | r8807 | |
| 189 | 189 | |
| 190 | 190 | WRITE8_HANDLER( mz700_bank_0_w ) |
| 191 | 191 | { |
| 192 | | |
| 192 | | |
| 193 | 193 | |
| 194 | 194 | memory_install_readwrite_bank(spc, 0x0000, 0x0fff, 0, 0, "bank1"); |
| 195 | 195 | memory_set_bankptr(space->machine, "bank1", messram_get_ptr(space->machine->device("messram"))); |
| r8806 | r8807 | |
| 197 | 197 | |
| 198 | 198 | WRITE8_HANDLER( mz800_bank_0_w ) |
| 199 | 199 | { |
| 200 | | |
| 200 | | |
| 201 | 201 | |
| 202 | 202 | memory_install_readwrite_bank(spc, 0x0000, 0x7fff, 0, 0, "bank1"); |
| 203 | 203 | memory_set_bankptr(space->machine, "bank1", messram_get_ptr(space->machine->device("messram"))); |
| r8806 | r8807 | |
| 205 | 205 | |
| 206 | 206 | READ8_HANDLER( mz800_bank_1_r ) |
| 207 | 207 | { |
| 208 | | |
| 208 | | |
| 209 | 209 | mz_state *mz = space->machine->driver_data<mz_state>(); |
| 210 | 210 | |
| 211 | 211 | /* switch in ram from 0x1000 to 0x1fff */ |
| r8806 | r8807 | |
| 230 | 230 | |
| 231 | 231 | WRITE8_HANDLER( mz700_bank_1_w ) |
| 232 | 232 | { |
| 233 | | |
| 233 | | |
| 234 | 234 | mz_state *mz = space->machine->driver_data<mz_state>(); |
| 235 | 235 | |
| 236 | 236 | if (mz->mz700_mode) |
| r8806 | r8807 | |
| 257 | 257 | |
| 258 | 258 | WRITE8_HANDLER( mz700_bank_2_w ) |
| 259 | 259 | { |
| 260 | | |
| 260 | | |
| 261 | 261 | |
| 262 | 262 | memory_install_read_bank(spc, 0x0000, 0x0fff, 0, 0, "bank1"); |
| 263 | 263 | memory_nop_write(spc, 0x0000, 0x0fff, 0, 0); |
| r8806 | r8807 | |
| 266 | 266 | |
| 267 | 267 | WRITE8_HANDLER( mz700_bank_3_w ) |
| 268 | 268 | { |
| 269 | | |
| 269 | | |
| 270 | 270 | mz_state *mz = space->machine->driver_data<mz_state>(); |
| 271 | 271 | |
| 272 | 272 | if (mz->mz700_mode) |
| r8806 | r8807 | |
| 313 | 313 | |
| 314 | 314 | WRITE8_HANDLER( mz700_bank_4_w ) |
| 315 | 315 | { |
| 316 | | |
| 316 | | |
| 317 | 317 | mz_state *mz = space->machine->driver_data<mz_state>(); |
| 318 | 318 | |
| 319 | 319 | if (mz->mz700_mode) |
| r8806 | r8807 | |
| 370 | 370 | |
| 371 | 371 | WRITE8_HANDLER( mz700_bank_5_w ) |
| 372 | 372 | { |
| 373 | | |
| 373 | | |
| 374 | 374 | mz_state *mz = space->machine->driver_data<mz_state>(); |
| 375 | 375 | |
| 376 | 376 | if (mz->mz700_mode) |
| r8806 | r8807 | |
|---|---|---|
| 353 | 353 | } |
| 354 | 354 | } |
| 355 | 355 | |
| 356 | extern UINT8 *gce_vectorram; | |
| 357 | extern size_t gce_vectorram_size; | |
| 356 | 358 | |
| 357 | 359 | DRIVER_INIT(vectrex) |
| 358 | 360 | { |
| r8806 | r8807 | |
| 367 | 369 | * the first level of Minestorm are not evenly distributed. |
| 368 | 370 | */ |
| 369 | 371 | |
| 370 | memset(vectorram, 0xff, vectorram_size); | |
| 372 | memset(gce_vectorram, 0xff, gce_vectorram_size); | |
| 371 | 373 | } |
| r8806 | r8807 | |
|---|---|---|
| 941 | 941 | } |
| 942 | 942 | |
| 943 | 943 | |
| 944 | ||
| 944 | ||
| 945 | 945 | { |
| 946 | 946 | /* upper 7 bits -> segment # */ |
| 947 | 947 | int segment = (address >> 17) & 0x7f; |
| r8806 | r8807 | |
| 966 | 966 | } |
| 967 | 967 | else |
| 968 | 968 | { /* system ROMs */ |
| 969 | direct->bytemask = 0xffffff; | |
| 970 | direct->raw = direct->decrypted = lisa_rom_ptr - (address & 0xffc000); | |
| 971 | direct->bytestart = (address & 0xffc000); | |
| 972 | direct->byteend = (address & 0xffc000) + 0x003fff; | |
| 969 | direct.explicit_configure((address & 0xffc000), (address & 0xffc000) + 0x003fff, 0xffffff, lisa_rom_ptr - (address & 0xffc000)); | |
| 973 | 970 | /*logerror("ROM (setup mode)\n");*/ |
| 974 | 971 | } |
| 975 | 972 | |
| r8806 | r8807 | |
| 978 | 975 | |
| 979 | 976 | } |
| 980 | 977 | |
| 981 | if (cpu_get_reg( | |
| 978 | if (cpu_get_reg( | |
| 982 | 979 | /* supervisor mode -> force register file 0 */ |
| 983 | 980 | the_seg = 0; |
| 984 | 981 | |
| r8806 | r8807 | |
| 998 | 995 | /* out of segment limits : bus error */ |
| 999 | 996 | logerror("illegal opbase address%lX\n", (long) address); |
| 1000 | 997 | } |
| 1001 | direct->bytemask = 0xffffff; | |
| 1002 | direct->raw = direct->decrypted = lisa_ram_ptr + mapped_address - address; | |
| 1003 | direct->bytestart = (address & 0xffc000); | |
| 1004 | direct->byteend = (address & 0xffc000) + 0x003fff; | |
| 998 | direct.explicit_configure((address & 0xffc000), (address & 0xffc000) + 0x003fff, 0xffffff, lisa_ram_ptr + mapped_address - address); | |
| 1005 | 999 | /*logerror("RAM\n");*/ |
| 1006 | 1000 | break; |
| 1007 | 1001 | |
| r8806 | r8807 | |
| 1014 | 1008 | break; |
| 1015 | 1009 | |
| 1016 | 1010 | case special_IO: |
| 1017 | direct->bytemask = 0xffffff; | |
| 1018 | direct->raw = direct->decrypted = lisa_rom_ptr + (mapped_address & 0x003fff) - address; | |
| 1019 | direct->bytestart = (address & 0xffc000); | |
| 1020 | direct->byteend = (address & 0xffc000) + 0x003fff; | |
| 1011 | direct.explicit_configure((address & 0xffc000), (address & 0xffc000) + 0x003fff, 0xffffff, lisa_rom_ptr + (mapped_address & 0x003fff) - address); | |
| 1021 | 1012 | /*logerror("ROM\n");*/ |
| 1022 | 1013 | break; |
| 1023 | 1014 | } |
| r8806 | r8807 | |
| 1029 | 1020 | return -1; |
| 1030 | 1021 | } |
| 1031 | 1022 | |
| 1032 | ||
| 1023 | ||
| 1033 | 1024 | { |
| 1034 | 1025 | /* 8kb of address space -> wraparound */ |
| 1035 | 1026 | return (address & 0x1fff); |
| r8806 | r8807 | |
| 1156 | 1147 | |
| 1157 | 1148 | videoROM_ptr = memory_region(machine, "gfx1"); |
| 1158 | 1149 | |
| 1159 | memory_set_direct_update_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), lisa_OPbaseoverride); | |
| 1160 | memory_set_direct_update_handler(cputag_get_address_space(machine, "fdccpu", ADDRESS_SPACE_PROGRAM), lisa_fdc_OPbaseoverride); | |
| 1150 | cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM)->set_direct_update_handler(direct_update_delegate_create_static(lisa_OPbaseoverride, *machine)); | |
| 1151 | cputag_get_address_space(machine, "fdccpu", ADDRESS_SPACE_PROGRAM)->set_direct_update_handler(direct_update_delegate_create_static(lisa_fdc_OPbaseoverride, *machine)); | |
| 1161 | 1152 | |
| 1162 | 1153 | m68k_set_reset_callback(machine->device("maincpu"), /*lisa_reset_instr_callback*/NULL); |
| 1163 | 1154 |
| r8806 | r8807 | |
|---|---|---|
| 189 | 189 | */ |
| 190 | 190 | static WRITE8_DEVICE_HANDLER( sym1_via2_a_w ) |
| 191 | 191 | { |
| 192 | | |
| 192 | | |
| 193 | 193 | |
| 194 | 194 | logerror("SYM1 VIA2 W 0x%02x\n", data); |
| 195 | 195 |
| r8806 | r8807 | |
|---|---|---|
| 55 | 55 | |
| 56 | 56 | MACHINE_RESET( cgenie ) |
| 57 | 57 | { |
| 58 | | |
| 58 | | |
| 59 | 59 | running_device *ay8910 = machine->device("ay8910"); |
| 60 | 60 | UINT8 *ROM = memory_region(machine, "maincpu"); |
| 61 | 61 | |
| r8806 | r8807 | |
| 132 | 132 | |
| 133 | 133 | MACHINE_START( cgenie ) |
| 134 | 134 | { |
| 135 | | |
| 135 | | |
| 136 | 136 | UINT8 *gfx = memory_region(machine, "gfx2"); |
| 137 | 137 | int i; |
| 138 | 138 |
| r8806 | r8807 | |
|---|---|---|
| 55 | 55 | d0 drive A */ |
| 56 | 56 | |
| 57 | 57 | /* get address space */ |
| 58 | | |
| 58 | | |
| 59 | 59 | |
| 60 | 60 | if (data & 0x80) |
| 61 | 61 | { |
| r8806 | r8807 | |
| 168 | 168 | d0 drive A */ |
| 169 | 169 | |
| 170 | 170 | /* get address space */ |
| 171 | | |
| 171 | | |
| 172 | 172 | |
| 173 | 173 | if (data & 0x80) |
| 174 | 174 | { |
| r8806 | r8807 | |
| 380 | 380 | |
| 381 | 381 | MACHINE_RESET( kaypro2x ) |
| 382 | 382 | { |
| 383 | | |
| 383 | | |
| 384 | 384 | kaypro2x_system_port_w(space, 0, 0x80); |
| 385 | 385 | MACHINE_RESET_CALL(kay_kbd); |
| 386 | 386 | } |
| r8806 | r8807 | |
| 424 | 424 | |
| 425 | 425 | QUICKLOAD_LOAD( kaypro2x ) |
| 426 | 426 | { |
| 427 | | |
| 427 | | |
| 428 | 428 | running_device *cpu = image.device().machine->device("maincpu"); |
| 429 | 429 | UINT8 *RAM = memory_region(image.device().machine, "rambank"); |
| 430 | 430 | UINT16 i; |
| r8806 | r8807 | |
|---|---|---|
| 15 | 15 | typedef struct _i82439tx_state i82439tx_state; |
| 16 | 16 | struct _i82439tx_state |
| 17 | 17 | { |
| 18 | | |
| 18 | | |
| 19 | 19 | UINT8 *rom; |
| 20 | 20 | |
| 21 | 21 | UINT32 regs[8]; |
| r8806 | r8807 | |
|---|---|---|
| 46 | 46 | machine->schedule_soft_reset(); |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | ||
| 49 | ||
| 50 | 50 | { |
| 51 | if (input_port_read(space->machine, "RESET") & 0x01) | |
| 52 | timer_set(space->machine, ATTOTIME_IN_USEC(10), NULL, 0, lviv_reset); | |
| 51 | if (input_port_read(machine, "RESET") & 0x01) | |
| 52 | timer_set(machine, ATTOTIME_IN_USEC(10), NULL, 0, lviv_reset); | |
| 53 | 53 | return address; |
| 54 | 54 | } |
| 55 | 55 | |
| r8806 | r8807 | |
| 163 | 163 | |
| 164 | 164 | WRITE8_HANDLER ( lviv_io_w ) |
| 165 | 165 | { |
| 166 | | |
| 166 | | |
| 167 | 167 | if (startup_mem_map) |
| 168 | 168 | { |
| 169 | 169 | startup_mem_map = 0; |
| r8806 | r8807 | |
| 221 | 221 | |
| 222 | 222 | MACHINE_RESET( lviv ) |
| 223 | 223 | { |
| 224 | const address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); | |
| 225 | memory_set_direct_update_handler(space, lviv_directoverride); | |
| 224 | address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); | |
| 225 | space->set_direct_update_handler(direct_update_delegate_create_static(lviv_directoverride, *machine)); | |
| 226 | 226 | |
| 227 | 227 | lviv_video_ram = messram_get_ptr(machine->device("messram")) + 0xc000; |
| 228 | 228 |
| r8806 | r8807 | |
|---|---|---|
| 350 | 350 | |
| 351 | 351 | Z80BIN_EXECUTE( exidy ) |
| 352 | 352 | { |
| 353 | | |
| 353 | | |
| 354 | 354 | |
| 355 | if ((execute_address >= 0xc000) && (execute_address <= 0xdfff) && ( | |
| 355 | if ((execute_address >= 0xc000) && (execute_address <= 0xdfff) && (space->r | |
| 356 | 356 | return; /* can't run a program if the cartridge isn't in */ |
| 357 | 357 | |
| 358 | 358 | /* Since Exidy Basic is by Microsoft, it needs some preprocessing before it can be run. |
| r8806 | r8807 | |
| 374 | 374 | }; |
| 375 | 375 | |
| 376 | 376 | for (i = 0; i < ARRAY_LENGTH(data); i++) |
| 377 | | |
| 377 | space-> | |
| 378 | 378 | |
| 379 | 379 | if (!autorun) |
| 380 | | |
| 380 | space-> | |
| 381 | 381 | |
| 382 | 382 | /* tell BASIC where program ends */ |
| 383 | memory_write_byte(space, 0x1b7, (end_address >> 0) & 0xff); | |
| 384 | memory_write_byte(space, 0x1b8, (end_address >> 8) & 0xff); | |
| 383 | space->write_byte(0x1b7, (end_address >> 0) & 0xff); | |
| 384 | space->write_byte(0x1b8, (end_address >> 8) & 0xff); | |
| 385 | 385 | |
| 386 | 386 | if ((execute_address != 0xc858) && autorun) |
| 387 | | |
| 387 | space-> | |
| 388 | 388 | |
| 389 | 389 | cpu_set_reg(machine->device("maincpu"), STATE_GENPC, 0xf01f); |
| 390 | 390 | } |
| r8806 | r8807 | |
| 449 | 449 | |
| 450 | 450 | MACHINE_RESET( exidy ) |
| 451 | 451 | { |
| 452 | | |
| 452 | | |
| 453 | 453 | |
| 454 | 454 | /* Initialize cassette interface */ |
| 455 | 455 | cass_data.output.length = 0; |
| r8806 | r8807 | |
|---|---|---|
| 311 | 311 | |
| 312 | 312 | void pc8801_update_bank(running_machine *machine) |
| 313 | 313 | { |
| 314 | | |
| 314 | | |
| 315 | 315 | char *ext_r,*ext_w; |
| 316 | 316 | |
| 317 | 317 | select_extmem(&ext_r,&ext_w,NULL); |
| r8806 | r8807 | |
|---|---|---|
| 124 | 124 | |
| 125 | 125 | static void partner_iomap_bank(running_machine *machine,UINT8 *rom) |
| 126 | 126 | { |
| 127 | | |
| 127 | | |
| 128 | 128 | switch(partner_win_mem_page) { |
| 129 | 129 | case 2 : |
| 130 | 130 | // FDD |
| r8806 | r8807 | |
| 141 | 141 | } |
| 142 | 142 | static void partner_bank_switch(running_machine *machine) |
| 143 | 143 | { |
| 144 | | |
| 144 | | |
| 145 | 145 | UINT8 *rom = memory_region(machine, "maincpu"); |
| 146 | 146 | |
| 147 | 147 | memory_install_write_bank(space, 0x0000, 0x07ff, 0, 0, "bank1"); |
| r8806 | r8807 | |
| 363 | 363 | i8257_hlda_w(device, state); |
| 364 | 364 | } |
| 365 | 365 | |
| 366 | static UINT8 memory_read_byte(address_space *space, offs_t address) { return space->read_byte(address); } | |
| 367 | static void memory_write_byte(address_space *space, offs_t address, UINT8 data) { space->write_byte(address, data); } | |
| 368 | ||
| 366 | 369 | I8257_INTERFACE( partner_dma ) |
| 367 | 370 | { |
| 368 | 371 | DEVCB_LINE(hrq_w), |
| r8806 | r8807 | |
|---|---|---|
| 145 | 145 | |
| 146 | 146 | DRIVER_INIT( apple1 ) |
| 147 | 147 | { |
| 148 | | |
| 148 | | |
| 149 | 149 | /* Set up the handlers for MESS's dynamically-sized RAM. */ |
| 150 | 150 | memory_install_readwrite_bank(space,0x0000, messram_get_size(machine->device("messram")) - 1, 0, 0, "bank1"); |
| 151 | 151 | memory_set_bankptr(machine,"bank1", messram_get_ptr(machine->device("messram"))); |
| r8806 | r8807 | |
| 257 | 257 | for (addr = start_addr, snapptr = snapbuf + SNAP_HEADER_LEN; |
| 258 | 258 | addr <= end_addr; |
| 259 | 259 | addr++, snapptr++) |
| 260 | memory_write_byte(cputag_get_address_space(image.device().machine, "maincpu", ADDRESS_SPACE_PROGRAM), addr, *snapptr); | |
| 260 | cputag_get_address_space(image.device().machine, "maincpu", ADDRESS_SPACE_PROGRAM)->write_byte(addr, *snapptr); | |
| 261 | ||
| 261 | 262 | |
| 262 | 263 | return IMAGE_INIT_PASS; |
| 263 | 264 | } |
| r8806 | r8807 | |
| 520 | 521 | always comes from the corresponding cassette ROM location |
| 521 | 522 | in $C100-$C17F. */ |
| 522 | 523 | |
| 523 | return | |
| 524 | return space->r | |
| 524 | 525 | } |
| 525 | 526 | else |
| 526 | 527 | { |
| r8806 | r8807 | |
| 538 | 539 | because it can cause tape header bits on real cassette |
| 539 | 540 | images to be misread as data bits.) */ |
| 540 | 541 | if (cassette_input(cassette_device_image(space->machine)) > 0.0) |
| 541 | return | |
| 542 | return space->r | |
| 542 | 543 | else |
| 543 | return | |
| 544 | return space->r | |
| 544 | 545 | } |
| 545 | 546 | } |
| 546 | 547 |
| r8806 | r8807 | |
|---|---|---|
| 44 | 44 | |
| 45 | 45 | |
| 46 | 46 | static void Mise_A_Jour_Etat(int Adresse, int Value ); |
| 47 | static void Update_Sound( | |
| 47 | static void Update_Sound( | |
| 48 | 48 | |
| 49 | 49 | static running_device *cassette_device_image(running_machine *machine); |
| 50 | 50 | |
| r8806 | r8807 | |
| 555 | 555 | ValMixer = 0; |
| 556 | 556 | } |
| 557 | 557 | |
| 558 | void Update_Sound( | |
| 558 | void Update_Sound( | |
| 559 | 559 | { |
| 560 | 560 | /* keep device*/ |
| 561 | 561 | running_device *sn76477 = space->machine->device("sn76477"); |
| r8806 | r8807 | |
|---|---|---|
| 571 | 571 | |
| 572 | 572 | static void bebox_map_vga_memory(running_machine *machine, offs_t begin, offs_t end, read8_space_func rh, write8_space_func wh) |
| 573 | 573 | { |
| 574 | | |
| 574 | | |
| 575 | 575 | |
| 576 | 576 | memory_nop_readwrite(space, 0xC00A0000, 0xC00BFFFF, 0, 0); |
| 577 | 577 | |
| r8806 | r8807 | |
| 711 | 711 | { |
| 712 | 712 | offs_t page_offset = (((offs_t) dma_offset[0][dma_channel]) << 16) |
| 713 | 713 | & 0x7FFF0000; |
| 714 | return | |
| 714 | return space->r | |
| 715 | 715 | } |
| 716 | 716 | |
| 717 | 717 | |
| r8806 | r8807 | |
| 719 | 719 | { |
| 720 | 720 | offs_t page_offset = (((offs_t) dma_offset[0][dma_channel]) << 16) |
| 721 | 721 | & 0x7FFF0000; |
| 722 | | |
| 722 | space-> | |
| 723 | 723 | } |
| 724 | 724 | |
| 725 | 725 | |
| r8806 | r8807 | |
| 945 | 945 | static UINT32 scsi53c810_fetch(running_machine *machine, UINT32 dsp) |
| 946 | 946 | { |
| 947 | 947 | UINT32 result; |
| 948 | result = | |
| 948 | result = | |
| 949 | 949 | return BYTE_REVERSE32(result); |
| 950 | 950 | } |
| 951 | 951 | |
| r8806 | r8807 | |
| 1011 | 1011 | /* brutal ugly hack; at some point the PCI code should be handling this stuff */ |
| 1012 | 1012 | if (scsi53c810_data[5] != 0xFFFFFFF0) |
| 1013 | 1013 | { |
| 1014 | | |
| 1014 | | |
| 1015 | 1015 | |
| 1016 | 1016 | addr = (scsi53c810_data[5] | 0xC0000000) & ~0xFF; |
| 1017 | 1017 | memory_install_read64_handler(space, addr, addr + 0xFF, 0, 0, scsi53c810_r); |
| r8806 | r8807 | |
| 1089 | 1089 | |
| 1090 | 1090 | DRIVER_INIT( bebox ) |
| 1091 | 1091 | { |
| 1092 | const address_space *space_0 = cputag_get_address_space(machine, "ppc1", ADDRESS_SPACE_PROGRAM); | |
| 1093 | const address_space *space_1 = cputag_get_address_space(machine, "ppc2", ADDRESS_SPACE_PROGRAM); | |
| 1092 | address_space *space_0 = cputag_get_address_space(machine, "ppc1", ADDRESS_SPACE_PROGRAM); | |
| 1093 | address_space *space_1 = cputag_get_address_space(machine, "ppc2", ADDRESS_SPACE_PROGRAM); | |
| 1094 | 1094 | offs_t vram_begin; |
| 1095 | 1095 | offs_t vram_end; |
| 1096 | 1096 |
| r8806 | r8807 | |
|---|---|---|
| 73 | 73 | |
| 74 | 74 | */ |
| 75 | 75 | |
| 76 | | |
| 76 | | |
| 77 | 77 | running_device *messram = machine->device("messram"); |
| 78 | 78 | |
| 79 | 79 | // UINT8 cbm_mode = data >> 7 & 0x01; |
| r8806 | r8807 | |
| 362 | 362 | |
| 363 | 363 | SNAPSHOT_LOAD( mtx ) |
| 364 | 364 | { |
| 365 | | |
| 365 | | |
| 366 | 366 | |
| 367 | 367 | UINT8 header[18]; |
| 368 | 368 | UINT16 addr; |
| r8806 | r8807 | |
|---|---|---|
| 164 | 164 | |
| 165 | 165 | static void specimx_set_bank(running_machine *machine, int i,int data) |
| 166 | 166 | { |
| 167 | | |
| 167 | | |
| 168 | 168 | memory_install_write_bank(space, 0xc000, 0xffbf, 0, 0, "bank3"); |
| 169 | 169 | memory_install_write_bank(space, 0xffc0, 0xffdf, 0, 0, "bank4"); |
| 170 | 170 | memory_set_bankptr(machine, "bank4", messram_get_ptr(machine->device("messram")) + 0xffc0); |
| r8806 | r8807 | |
| 307 | 307 | UINT8 bank3 = ((RR_register >> 4) & 3); |
| 308 | 308 | UINT8 bank4 = ((RR_register >> 6) & 3); |
| 309 | 309 | UINT8 *mem = memory_region(machine, "maincpu"); |
| 310 | | |
| 310 | | |
| 311 | 311 | |
| 312 | 312 | memory_install_write_bank(space, 0x0000, 0x3fff, 0, 0, "bank1"); |
| 313 | 313 | memory_install_write_bank(space, 0x4000, 0x8fff, 0, 0, "bank2"); |
| r8806 | r8807 | |
|---|---|---|
| 40 | 40 | DIRECT_UPDATE_HANDLER( jupiter_opbaseoverride ) |
| 41 | 41 | { |
| 42 | 42 | UINT16 loop,tmpword; |
| 43 | address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); | |
| 43 | 44 | |
| 44 | 45 | if (address == 0x059d) |
| 45 | 46 | { |
| 46 | 47 | if (jupiter_data_type == JUPITER_ACE) |
| 47 | 48 | { |
| 48 | 49 | for (loop = 0; loop < 0x6000; loop++) |
| 49 | | |
| 50 | space-> | |
| 50 | 51 | } |
| 51 | 52 | else if (jupiter_data_type == JUPITER_TAP) |
| 52 | 53 | { |
| 53 | 54 | |
| 54 | 55 | for (loop = 0; loop < jupiter_tape.dat_len; loop++) |
| 55 | | |
| 56 | space-> | |
| 56 | 57 | |
| 57 | | |
| 58 | space-> | |
| 58 | 59 | |
| 59 | 60 | for (loop = 0; loop < 8; loop++) |
| 60 | memory_write_byte(space, loop + 0x3c31, jupiter_tape.hdr_vars[loop]); | |
| 61 | memory_write_byte(space, 0x3c39, 0x00); | |
| 62 | memory_write_byte(space, 0x3c3a, 0x00); | |
| 61 | space->write_byte(loop + 0x3c31, jupiter_tape.hdr_vars[loop]); | |
| 62 | space->write_byte(0x3c39, 0x00); | |
| 63 | space->write_byte(0x3c3a, 0x00); | |
| 63 | 64 | |
| 64 | tmpword = | |
| 65 | tmpword = space->r | |
| 65 | 66 | |
| 66 | memory_write_byte(space, 0x3c3b, tmpword & 0xff); | |
| 67 | memory_write_byte(space, 0x3c3c, (tmpword >> 8) & 0xff); | |
| 67 | space->write_byte(0x3c3b, tmpword & 0xff); | |
| 68 | space->write_byte(0x3c3c, (tmpword >> 8) & 0xff); | |
| 68 | 69 | |
| 69 | | |
| 70 | space-> | |
| 70 | 71 | |
| 71 | memory_write_byte(space, 0x3c4c, jupiter_tape.hdr_3c4c); | |
| 72 | memory_write_byte(space, 0x3c4d, jupiter_tape.hdr_3c4d); | |
| 72 | space->write_byte(0x3c4c, jupiter_tape.hdr_3c4c); | |
| 73 | space->write_byte(0x3c4d, jupiter_tape.hdr_3c4d); | |
| 73 | 74 | |
| 74 | if (! | |
| 75 | if (!space->r | |
| 75 | 76 | { |
| 76 | memory_write_byte(space, 0x3c57, 0x49); | |
| 77 | memory_write_byte(space, 0x3c58, 0x3c); | |
| 77 | space->write_byte(0x3c57, 0x49); | |
| 78 | space->write_byte(0x3c58, 0x3c); | |
| 78 | 79 | } |
| 79 | 80 | } |
| 80 | 81 | } |
| r8806 | r8807 | |
| 83 | 84 | |
| 84 | 85 | MACHINE_START( jupiter ) |
| 85 | 86 | { |
| 86 | | |
| 87 | | |
| 87 | 88 | |
| 88 | 89 | logerror("jupiter_init\r\n"); |
| 89 | 90 | logerror("data: %p\n", jupiter_data); |
| 90 | 91 | |
| 91 | 92 | if (jupiter_data) |
| 92 | 93 | { |
| 93 | logerror("data: %p. type: %d.\n", jupiter_data, jupiter_data_type); | |
| 94 | memory_set_direct_update_handler(space, jupiter_opbaseoverride); | |
| 94 | logerror("data: %p. type: %d.\n", jupiter_data, jupiter_data_type); | |
| 95 | space->set_direct_update_handler(direct_update_delegate_create_static(jupiter_opbaseoverride, *machine)); | |
| 96 | ||
| 95 | 97 | } |
| 96 | 98 | |
| 97 | 99 | machine->add_notifier(MACHINE_NOTIFY_EXIT, jupiter_machine_stop); |
| r8806 | r8807 | |
|---|---|---|
| 790 | 790 | static void drq_callback(running_machine *machine, int which) |
| 791 | 791 | { |
| 792 | 792 | struct dma_state *dma = &i186.dma[which]; |
| 793 | const address_space *memory_space = cpu_get_address_space(machine->device(MAINCPU_TAG), ADDRESS_SPACE_PROGRAM); | |
| 794 | const address_space *io_space = cpu_get_address_space(machine->device(MAINCPU_TAG), ADDRESS_SPACE_IO); | |
| 793 | address_space *memory_space = cpu_get_address_space(machine->device(MAINCPU_TAG), ADDRESS_SPACE_PROGRAM); | |
| 794 | address_space *io_space = cpu_get_address_space(machine->device(MAINCPU_TAG), ADDRESS_SPACE_IO); | |
| 795 | 795 | |
| 796 | const address_space *src_space; | |
| 797 | const address_space *dest_space; | |
| 796 | address_space *src_space; | |
| 797 | address_space *dest_space; | |
| 798 | 798 | |
| 799 | 799 | UINT16 dma_word; |
| 800 | 800 | UINT8 dma_byte; |
| r8806 | r8807 | |
| 824 | 824 | // Do the transfer |
| 825 | 825 | if(dma->control & BYTE_WORD) |
| 826 | 826 | { |
| 827 | dma_word=memory_read_word(src_space,dma->source); | |
| 828 | memory_write_word(dest_space,dma->dest,dma_word); | |
| 827 | dma_word=src_space->read_word(dma->source); | |
| 828 | dest_space->write_word(dma->dest,dma_word); | |
| 829 | 829 | incdec_size=2; |
| 830 | 830 | } |
| 831 | 831 | else |
| 832 | 832 | { |
| 833 | dma_byte=memory_read_byte(src_space,dma->source); | |
| 834 | memory_write_byte(dest_space,dma->dest,dma_byte); | |
| 833 | dma_byte=src_space->read_byte(dma->source); | |
| 834 | dest_space->write_byte(dma->dest,dma_byte); | |
| 835 | 835 | incdec_size=1; |
| 836 | 836 | } |
| 837 | 837 | |
| r8806 | r8807 | |
| 1405 | 1405 | |
| 1406 | 1406 | static int instruction_hook(device_t &device, offs_t curpc) |
| 1407 | 1407 | { |
| 1408 | | |
| 1408 | | |
| 1409 | 1409 | UINT8 *addr_ptr; |
| 1410 | 1410 | |
| 1411 | 1411 | addr_ptr = (UINT8*)memory_get_read_ptr(space,curpc); |
| r8806 | r8807 | |
| 1746 | 1746 | logerror("=======================================================================\n"); |
| 1747 | 1747 | } |
| 1748 | 1748 | |
| 1749 | void *get_dssi_ptr( | |
| 1749 | void *get_dssi_ptr( | |
| 1750 | 1750 | { |
| 1751 | 1751 | int addr; |
| 1752 | 1752 | |
| r8806 | r8807 | |
| 1758 | 1758 | |
| 1759 | 1759 | static void decode_dssi_f_fill_area(running_device *device,UINT16 ds, UINT16 si) |
| 1760 | 1760 | { |
| 1761 | | |
| 1761 | | |
| 1762 | 1762 | |
| 1763 | 1763 | UINT16 *addr_ptr; |
| 1764 | 1764 | t_area_params *area_params; |
| r8806 | r8807 | |
| 1788 | 1788 | |
| 1789 | 1789 | static void decode_dssi_f_plot_character_string(running_device *device,UINT16 ds, UINT16 si) |
| 1790 | 1790 | { |
| 1791 | | |
| 1791 | | |
| 1792 | 1792 | |
| 1793 | 1793 | UINT8 *char_ptr; |
| 1794 | 1794 | t_plot_string_params *plot_string_params; |
| r8806 | r8807 | |
| 1814 | 1814 | |
| 1815 | 1815 | static void decode_dssi_f_set_new_clt(running_device *device,UINT16 ds, UINT16 si) |
| 1816 | 1816 | { |
| 1817 | | |
| 1817 | | |
| 1818 | 1818 | UINT16 *new_colours; |
| 1819 | 1819 | int colour; |
| 1820 | 1820 | new_colours=(UINT16 *)get_dssi_ptr(space,ds,si); |
| r8806 | r8807 | |
| 1828 | 1828 | |
| 1829 | 1829 | static void decode_dssi_f_plonk_char(running_device *device,UINT16 ds, UINT16 si) |
| 1830 | 1830 | { |
| 1831 | | |
| 1831 | | |
| 1832 | 1832 | UINT16 *params; |
| 1833 | 1833 | params=(UINT16 *)get_dssi_ptr(space,ds,si); |
| 1834 | 1834 | |
| r8806 | r8807 | |
| 1839 | 1839 | |
| 1840 | 1840 | static void decode_dssi_f_rw_sectors(running_device *device,UINT16 ds, UINT16 si) |
| 1841 | 1841 | { |
| 1842 | | |
| 1842 | | |
| 1843 | 1843 | UINT16 *params; |
| 1844 | 1844 | int param_no; |
| 1845 | 1845 | |
| r8806 | r8807 | |
| 1942 | 1942 | |
| 1943 | 1943 | static void nimbus_bank_memory(running_machine *machine) |
| 1944 | 1944 | { |
| 1945 | | |
| 1945 | | |
| 1946 | 1946 | int ramsize = messram_get_size(machine->device("messram")); |
| 1947 | 1947 | int ramblock = 0; |
| 1948 | 1948 | int blockno; |
| r8806 | r8807 | |
|---|---|---|
| 73 | 73 | static READ8_HANDLER( tf20_rom_disable ) |
| 74 | 74 | { |
| 75 | 75 | tf20_state *tf20 = get_safe_token(space->cpu->owner()); |
| 76 | | |
| 76 | | |
| 77 | 77 | |
| 78 | 78 | /* switch in ram */ |
| 79 | 79 | memory_install_ram(prg, 0x0000, 0x7fff, 0, 0, messram_get_ptr(tf20->ram)); |
| r8806 | r8807 | |
| 327 | 327 | { |
| 328 | 328 | tf20_state *tf20 = get_safe_token(device); |
| 329 | 329 | running_device *cpu = device->subdevice("tf20"); |
| 330 | | |
| 330 | | |
| 331 | 331 | |
| 332 | 332 | cpu_set_irq_callback(cpu, tf20_irq_ack); |
| 333 | 333 | |
| r8806 | r8807 | |
| 351 | 351 | static DEVICE_RESET( tf20 ) |
| 352 | 352 | { |
| 353 | 353 | running_device *cpu = device->subdevice("tf20"); |
| 354 | | |
| 354 | | |
| 355 | 355 | |
| 356 | 356 | /* enable rom */ |
| 357 | 357 | memory_install_rom(prg, 0x0000, 0x07ff, 0, 0x7800, cpu->region()->base()); |
| r8806 | r8807 | |
|---|---|---|
| 85 | 85 | static void pp01_set_memory(running_machine *machine,UINT8 block, UINT8 data) |
| 86 | 86 | { |
| 87 | 87 | UINT8 *mem = memory_region(machine, "maincpu"); |
| 88 | | |
| 88 | | |
| 89 | 89 | UINT16 startaddr = block*0x1000; |
| 90 | 90 | UINT16 endaddr = ((block+1)*0x1000)-1; |
| 91 | 91 | UINT8 blocknum = block + 1; |
| r8806 | r8807 | |
|---|---|---|
| 504 | 504 | static int snes_find_addon_chip( running_machine *machine ) |
| 505 | 505 | { |
| 506 | 506 | snes_state *state = machine->driver_data<snes_state>(); |
| 507 | | |
| 507 | | |
| 508 | 508 | int supported_type = 1; |
| 509 | 509 | |
| 510 | 510 | /* Info mostly taken from http://snesemu.black-ship.net/misc/-from%20nsrt.edgeemu.com-chipinfo.htm */ |
| r8806 | r8807 | |
| 630 | 630 | static void snes_cart_log_info( running_machine *machine, int total_blocks, int supported ) |
| 631 | 631 | { |
| 632 | 632 | snes_state *state = machine->driver_data<snes_state>(); |
| 633 | | |
| 633 | | |
| 634 | 634 | char title[21], rom_id[4], company_id[2]; |
| 635 | 635 | int i, company, has_ram = 0, has_sram = 0; |
| 636 | 636 | |
| r8806 | r8807 | |
| 707 | 707 | int supported_type = 1, i, j; |
| 708 | 708 | running_machine *machine = image.device().machine; |
| 709 | 709 | snes_state *state = machine->driver_data<snes_state>(); |
| 710 | | |
| 710 | | |
| 711 | 711 | int total_blocks, read_blocks, has_bsx_slot = 0, st_bios = 0; |
| 712 | 712 | UINT32 offset, int_header_offs; |
| 713 | 713 | UINT8 *ROM = memory_region(image.device().machine, "cart"); |
| r8806 | r8807 | |
|---|---|---|
| 112 | 112 | |
| 113 | 113 | void apple2_update_memory(running_machine *machine) |
| 114 | 114 | { |
| 115 | | |
| 115 | | |
| 116 | 116 | int i, bank; |
| 117 | 117 | char rbank[10], wbank[10]; |
| 118 | 118 | int full_update = 0; |
| r8806 | r8807 | |
| 340 | 340 | |
| 341 | 341 | READ8_HANDLER(apple2_c0xx_r) |
| 342 | 342 | { |
| 343 | if(!space->debugger_access) | |
| 343 | if(!space->debugger_access()) | |
| 344 | 344 | { |
| 345 | 345 | static const read8_space_func handlers[] = |
| 346 | 346 | { |
| r8806 | r8807 | |
| 581 | 581 | static READ8_HANDLER(apple2_cfff_r) |
| 582 | 582 | { |
| 583 | 583 | // debugger guard |
| 584 | if(!space->debugger_access) | |
| 584 | if(!space->debugger_access()) | |
| 585 | 585 | { |
| 586 | 586 | a2_cnxx_slot = -1; |
| 587 | 587 | apple2_update_memory(space->machine); |
| r8806 | r8807 | |
| 1125 | 1125 | { |
| 1126 | 1126 | UINT8 result = 0; |
| 1127 | 1127 | |
| 1128 | if(!space->debugger_access) | |
| 1128 | if(!space->debugger_access()) | |
| 1129 | 1129 | { |
| 1130 | 1130 | /* Read the keyboard data and strobe */ |
| 1131 | 1131 | profiler_mark_start(PROFILER_C00X); |
| r8806 | r8807 | |
| 1176 | 1176 | { |
| 1177 | 1177 | UINT8 result = apple2_getfloatingbusvalue(space->machine) & 0x7F; |
| 1178 | 1178 | |
| 1179 | if(!space->debugger_access) | |
| 1179 | if(!space->debugger_access()) | |
| 1180 | 1180 | { |
| 1181 | 1181 | profiler_mark_start(PROFILER_C01X); |
| 1182 | 1182 | |
| r8806 | r8807 | |
| 1229 | 1229 | |
| 1230 | 1230 | READ8_HANDLER( apple2_c02x_r ) |
| 1231 | 1231 | { |
| 1232 | if(!space->debugger_access) | |
| 1232 | if(!space->debugger_access()) | |
| 1233 | 1233 | { |
| 1234 | 1234 | apple2_c02x_w(space, offset, 0); |
| 1235 | 1235 | } |
| r8806 | r8807 | |
| 1260 | 1260 | |
| 1261 | 1261 | READ8_HANDLER ( apple2_c03x_r ) |
| 1262 | 1262 | { |
| 1263 | if(!space->debugger_access) | |
| 1263 | if(!space->debugger_access()) | |
| 1264 | 1264 | { |
| 1265 | 1265 | if (!offset) |
| 1266 | 1266 | { |
| r8806 | r8807 | |
| 1299 | 1299 | |
| 1300 | 1300 | READ8_HANDLER ( apple2_c05x_r ) |
| 1301 | 1301 | { |
| 1302 | if(!space->debugger_access) | |
| 1302 | if(!space->debugger_access()) | |
| 1303 | 1303 | { |
| 1304 | 1304 | UINT32 mask; |
| 1305 | 1305 | |
| r8806 | r8807 | |
| 1340 | 1340 | READ8_HANDLER ( apple2_c06x_r ) |
| 1341 | 1341 | { |
| 1342 | 1342 | int result = 0; |
| 1343 | if(!space->debugger_access) | |
| 1343 | if(!space->debugger_access()) | |
| 1344 | 1344 | { |
| 1345 | 1345 | switch (offset & 0x0F) |
| 1346 | 1346 | { |
| r8806 | r8807 | |
| 1394 | 1394 | |
| 1395 | 1395 | READ8_HANDLER ( apple2_c07x_r ) |
| 1396 | 1396 | { |
| 1397 | if(!space->debugger_access) | |
| 1397 | if(!space->debugger_access()) | |
| 1398 | 1398 | { |
| 1399 | 1399 | double x_calibration = attotime_to_double(ATTOTIME_IN_USEC(12)); |
| 1400 | 1400 | double y_calibration = attotime_to_double(ATTOTIME_IN_USEC(13)); |
| r8806 | r8807 | |
|---|---|---|
| 607 | 607 | if (!ultimax) |
| 608 | 608 | c64_bankswitch(device->machine, 0); |
| 609 | 609 | |
| 610 | c64_memory[0x000] = memory_read_byte(cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM), 0); | |
| 611 | c64_memory[0x001] = memory_read_byte(cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM), 1); | |
| 610 | c64_memory[0x000] = cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM)->read_byte(0); | |
| 611 | c64_memory[0x001] = cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM)->read_byte(1); | |
| 612 | ||
| 612 | 613 | } |
| 613 | 614 | |
| 614 | 615 | UINT8 c64_m6510_port_read( running_device *device, UINT8 direction ) |
| r8806 | r8807 | |
| 1545 | 1546 | |
| 1546 | 1547 | static void setup_c64_custom_mappers(running_machine *machine) |
| 1547 | 1548 | { |
| 1548 | | |
| 1549 | | |
| 1549 | 1550 | |
| 1550 | 1551 | switch (c64_mapper) |
| 1551 | 1552 | { |
| r8806 | r8807 | |
|---|---|---|
| 231 | 231 | |
| 232 | 232 | static void dma_transfer_start(running_device* device, int channel, int dir) |
| 233 | 233 | { |
| 234 | | |
| 234 | | |
| 235 | 235 | hd63450_t* dmac = (hd63450_t*)downcast<legacy_device_base *>(device)->token(); |
| 236 | 236 | dmac->in_progress[channel] = 1; |
| 237 | 237 | dmac->reg[channel].csr &= ~0xe0; |
| r8806 | r8807 | |
| 239 | 239 | dmac->reg[channel].csr &= ~0x30; // Reset Error and Normal termination bits |
| 240 | 240 | if((dmac->reg[channel].ocr & 0x0c) != 0x00) // Array chain or Link array chain |
| 241 | 241 | { |
| 242 | dmac->reg[channel].mar = memory_read_word(space,dmac->reg[channel].bar) << 16; | |
| 243 | dmac->reg[channel].mar |= memory_read_word(space,dmac->reg[channel].bar+2); | |
| 244 | dmac->reg[channel].mtc = memory_read_word(space,dmac->reg[channel].bar+4); | |
| 242 | dmac->reg[channel].mar = space->read_word(dmac->reg[channel].bar) << 16; | |
| 243 | dmac->reg[channel].mar |= space->read_word(dmac->reg[channel].bar+2); | |
| 244 | dmac->reg[channel].mtc = space->read_word(dmac->reg[channel].bar+4); | |
| 245 | 245 | if(dmac->reg[channel].btc > 0) |
| 246 | 246 | dmac->reg[channel].btc--; |
| 247 | 247 | } |
| r8806 | r8807 | |
| 308 | 308 | |
| 309 | 309 | void hd63450_single_transfer(running_device* device, int x) |
| 310 | 310 | { |
| 311 | | |
| 311 | | |
| 312 | 312 | int data; |
| 313 | 313 | int datasize = 1; |
| 314 | 314 | hd63450_t* dmac = (hd63450_t*)downcast<legacy_device_base *>(device)->token(); |
| r8806 | r8807 | |
| 322 | 322 | data = dmac->intf->dma_read[x](device->machine,dmac->reg[x].mar); |
| 323 | 323 | if(data == -1) |
| 324 | 324 | return; // not ready to recieve data |
| 325 | | |
| 325 | space-> | |
| 326 | 326 | datasize = 1; |
| 327 | 327 | } |
| 328 | 328 | else |
| r8806 | r8807 | |
| 330 | 330 | switch(dmac->reg[x].ocr & 0x30) // operation size |
| 331 | 331 | { |
| 332 | 332 | case 0x00: // 8 bit |
| 333 | data = memory_read_byte(space,dmac->reg[x].dar); // read from device address | |
| 334 | memory_write_byte(space,dmac->reg[x].mar, data); // write to memory address | |
| 333 | data = space->read_byte(dmac->reg[x].dar); // read from device address | |
| 334 | space->write_byte(dmac->reg[x].mar, data); // write to memory address | |
| 335 | 335 | datasize = 1; |
| 336 | 336 | break; |
| 337 | 337 | case 0x10: // 16 bit |
| 338 | data = memory_read_word(space,dmac->reg[x].dar); // read from device address | |
| 339 | memory_write_word(space,dmac->reg[x].mar, data); // write to memory address | |
| 338 | data = space->read_word(dmac->reg[x].dar); // read from device address | |
| 339 | space->write_word(dmac->reg[x].mar, data); // write to memory address | |
| 340 | 340 | datasize = 2; |
| 341 | 341 | break; |
| 342 | 342 | case 0x20: // 32 bit |
| 343 | data = memory_read_word(space,dmac->reg[x].dar) << 16; // read from device address | |
| 344 | data |= memory_read_word(space,dmac->reg[x].dar+2); | |
| 345 | memory_write_word(space,dmac->reg[x].mar, (data & 0xffff0000) >> 16); // write to memory address | |
| 346 | memory_write_word(space,dmac->reg[x].mar+2, data & 0x0000ffff); | |
| 343 | data = space->read_word(dmac->reg[x].dar) << 16; // read from device address | |
| 344 | data |= space->read_word(dmac->reg[x].dar+2); | |
| 345 | space->write_word(dmac->reg[x].mar, (data & 0xffff0000) >> 16); // write to memory address | |
| 346 | space->write_word(dmac->reg[x].mar+2, data & 0x0000ffff); | |
| 347 | 347 | datasize = 4; |
| 348 | 348 | break; |
| 349 | 349 | case 0x30: // 8 bit packed (?) |
| 350 | data = memory_read_byte(space,dmac->reg[x].dar); // read from device address | |
| 351 | memory_write_byte(space,dmac->reg[x].mar, data); // write to memory address | |
| 350 | data = space->read_byte(dmac->reg[x].dar); // read from device address | |
| 351 | space->write_byte(dmac->reg[x].mar, data); // write to memory address | |
| 352 | 352 | datasize = 1; |
| 353 | 353 | break; |
| 354 | 354 | } |
| r8806 | r8807 | |
| 359 | 359 | { |
| 360 | 360 | if(dmac->intf->dma_write[x]) |
| 361 | 361 | { |
| 362 | data = | |
| 362 | data = space->r | |
| 363 | 363 | dmac->intf->dma_write[x](device->machine, dmac->reg[x].mar,data); |
| 364 | 364 | datasize = 1; |
| 365 | 365 | } |
| r8806 | r8807 | |
| 368 | 368 | switch(dmac->reg[x].ocr & 0x30) // operation size |
| 369 | 369 | { |
| 370 | 370 | case 0x00: // 8 bit |
| 371 | data = memory_read_byte(space,dmac->reg[x].mar); // read from memory address | |
| 372 | memory_write_byte(space,dmac->reg[x].dar, data); // write to device address | |
| 371 | data = space->read_byte(dmac->reg[x].mar); // read from memory address | |
| 372 | space->write_byte(dmac->reg[x].dar, data); // write to device address | |
| 373 | 373 | datasize = 1; |
| 374 | 374 | break; |
| 375 | 375 | case 0x10: // 16 bit |
| 376 | data = memory_read_word(space,dmac->reg[x].mar); // read from memory address | |
| 377 | memory_write_word(space,dmac->reg[x].dar, data); // write to device address | |
| 376 | data = space->read_word(dmac->reg[x].mar); // read from memory address | |
| 377 | space->write_word(dmac->reg[x].dar, data); // write to device address | |
| 378 | 378 | datasize = 2; |
| 379 | 379 | break; |
| 380 | 380 | case 0x20: // 32 bit |
| 381 | data = memory_read_word(space,dmac->reg[x].mar) << 16; // read from memory address | |
| 382 | data |= memory_read_word(space,dmac->reg[x].mar+2); // read from memory address | |
| 383 | memory_write_word(space,dmac->reg[x].dar, (data & 0xffff0000) >> 16); // write to device address | |
| 384 | memory_write_word(space,dmac->reg[x].dar+2, data & 0x0000ffff); // write to device address | |
| 381 | data = space->read_word(dmac->reg[x].mar) << 16; // read from memory address | |
| 382 | data |= space->read_word(dmac->reg[x].mar+2); // read from memory address | |
| 383 | space->write_word(dmac->reg[x].dar, (data & 0xffff0000) >> 16); // write to device address | |
| 384 | space->write_word(dmac->reg[x].dar+2, data & 0x0000ffff); // write to device address | |
| 385 | 385 | datasize = 4; |
| 386 | 386 | break; |
| 387 | 387 | case 0x30: // 8 bit packed (?) |
| 388 | data = memory_read_byte(space,dmac->reg[x].mar); // read from memory address | |
| 389 | memory_write_byte(space,dmac->reg[x].dar, data); // write to device address | |
| 388 | data = space->read_byte(dmac->reg[x].mar); // read from memory address | |
| 389 | space->write_byte(dmac->reg[x].dar, data); // write to device address | |
| 390 | 390 | datasize = 1; |
| 391 | 391 | break; |
| 392 | 392 | } |
| r8806 | r8807 | |
| 418 | 418 | { |
| 419 | 419 | dmac->reg[x].btc--; |
| 420 | 420 | dmac->reg[x].bar+=6; |
| 421 | dmac->reg[x].mar = memory_read_word(space,dmac->reg[x].bar) << 16; | |
| 422 | dmac->reg[x].mar |= memory_read_word(space,dmac->reg[x].bar+2); | |
| 423 | dmac->reg[x].mtc = memory_read_word(space,dmac->reg[x].bar+4); | |
| 421 | dmac->reg[x].mar = space->read_word(dmac->reg[x].bar) << 16; | |
| 422 | dmac->reg[x].mar |= space->read_word(dmac->reg[x].bar+2); | |
| 423 | dmac->reg[x].mtc = space->read_word(dmac->reg[x].bar+4); | |
| 424 | 424 | return; |
| 425 | 425 | } |
| 426 | 426 | timer_adjust_oneshot(dmac->timer[x], attotime_zero, 0); |
| r8806 | r8807 | |
|---|---|---|
| 105 | 105 | offs_t page_offset = (((offs_t) st->dma_offset[0][st->dma_channel]) << 16) |
| 106 | 106 | & 0x0F0000; |
| 107 | 107 | |
| 108 | result = | |
| 108 | result = space->r | |
| 109 | 109 | return result; |
| 110 | 110 | } |
| 111 | 111 | |
| r8806 | r8807 | |
| 116 | 116 | offs_t page_offset = (((offs_t) st->dma_offset[0][st->dma_channel]) << 16) |
| 117 | 117 | & 0x0F0000; |
| 118 | 118 | |
| 119 | | |
| 119 | space-> | |
| 120 | 120 | } |
| 121 | 121 | |
| 122 | 122 | |
| r8806 | r8807 | |
| 1222 | 1222 | |
| 1223 | 1223 | DRIVER_INIT( pc200 ) |
| 1224 | 1224 | { |
| 1225 | | |
| 1225 | | |
| 1226 | 1226 | UINT8 *gfx = &memory_region(machine, "gfx1")[0x8000]; |
| 1227 | 1227 | int i; |
| 1228 | 1228 | |
| r8806 | r8807 | |
| 1239 | 1239 | |
| 1240 | 1240 | DRIVER_INIT( ppc512 ) |
| 1241 | 1241 | { |
| 1242 | | |
| 1242 | | |
| 1243 | 1243 | UINT8 *gfx = &memory_region(machine, "gfx1")[0x8000]; |
| 1244 | 1244 | int i; |
| 1245 | 1245 | |
| r8806 | r8807 | |
| 1256 | 1256 | } |
| 1257 | 1257 | DRIVER_INIT( pc1512 ) |
| 1258 | 1258 | { |
| 1259 | const address_space *space = cpu_get_address_space( machine->firstcpu, ADDRESS_SPACE_PROGRAM ); | |
| 1260 | const address_space *io_space = cpu_get_address_space( machine->firstcpu, ADDRESS_SPACE_IO ); | |
| 1259 | address_space *space = cpu_get_address_space( machine->firstcpu, ADDRESS_SPACE_PROGRAM ); | |
| 1260 | address_space *io_space = cpu_get_address_space( machine->firstcpu, ADDRESS_SPACE_IO ); | |
| 1261 | 1261 | UINT8 *gfx = &memory_region(machine, "gfx1")[0x8000]; |
| 1262 | 1262 | int i; |
| 1263 | 1263 | |
| r8806 | r8807 | |
| 1298 | 1298 | |
| 1299 | 1299 | DRIVER_INIT( pc1640 ) |
| 1300 | 1300 | { |
| 1301 | | |
| 1301 | | |
| 1302 | 1302 | |
| 1303 | 1303 | memory_install_read16_handler(io_space, 0x278, 0x27b, 0, 0, pc1640_16le_port278_r ); |
| 1304 | 1304 | memory_install_read16_handler(io_space, 0x4278, 0x427b, 0, 0, pc1640_16le_port4278_r ); |
| r8806 | r8807 | |
|---|---|---|
| 33 | 33 | MACHINE_RESET( pecom ) |
| 34 | 34 | { |
| 35 | 35 | UINT8 *rom = memory_region(machine, "maincpu"); |
| 36 | | |
| 36 | | |
| 37 | 37 | |
| 38 | 38 | pecom_state *state = machine->driver_data<pecom_state>(); |
| 39 | 39 | |
| r8806 | r8807 | |
| 59 | 59 | WRITE8_HANDLER( pecom_bank_w ) |
| 60 | 60 | { |
| 61 | 61 | running_device *cdp1869 = space->machine->device(CDP1869_TAG); |
| 62 | | |
| 62 | | |
| 63 | 63 | UINT8 *rom = memory_region(space->machine, "maincpu"); |
| 64 | 64 | memory_install_write_bank(cputag_get_address_space(space->machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x0000, 0x3fff, 0, 0, "bank1"); |
| 65 | 65 | memory_set_bankptr(space->machine, "bank1", messram_get_ptr(space->machine->device("messram")) + 0x0000); |
| r8806 | r8807 | |
|---|---|---|
| 417 | 417 | */ |
| 418 | 418 | MACHINE_RESET( ti99 ) |
| 419 | 419 | { |
| 420 | | |
| 420 | | |
| 421 | 421 | /*console_GROMs.data_ptr = memory_region(machine, region_grom);*/ |
| 422 | 422 | console_GROMs.addr = 0; |
| 423 | 423 | console_GROMs.buf = 0; |
| r8806 | r8807 | |
| 1805 | 1805 | |
| 1806 | 1806 | static void ti99_TIxram_init(running_machine *machine) |
| 1807 | 1807 | { |
| 1808 | | |
| 1808 | | |
| 1809 | 1809 | |
| 1810 | 1810 | memory_install_read16_handler(space, 0x2000, 0x3fff, 0, 0, ti99_TIxramlow_r); |
| 1811 | 1811 | memory_install_write16_handler(space, 0x2000, 0x3fff, 0, 0, ti99_TIxramlow_w); |
| r8806 | r8807 | |
| 1882 | 1882 | { |
| 1883 | 1883 | int i; |
| 1884 | 1884 | |
| 1885 | | |
| 1885 | | |
| 1886 | 1886 | |
| 1887 | 1887 | memory_install_read16_handler(space, 0x2000, 0x3fff, 0, 0, ti99_sAMSxramlow_r); |
| 1888 | 1888 | memory_install_write16_handler(space, 0x2000, 0x3fff, 0, 0, ti99_sAMSxramlow_w); |
| r8806 | r8807 | |
| 1994 | 1994 | /* set up myarc handlers, and set initial state */ |
| 1995 | 1995 | static void ti99_myarcxram_init(running_machine *machine) |
| 1996 | 1996 | { |
| 1997 | | |
| 1997 | | |
| 1998 | 1998 | |
| 1999 | 1999 | memory_install_read16_handler(space, 0x2000, 0x3fff, 0, 0, ti99_myarcxramlow_r); |
| 2000 | 2000 | memory_install_write16_handler(space, 0x2000, 0x3fff, 0, 0, ti99_myarcxramlow_w); |
| r8806 | r8807 | |
| 3185 | 3185 | */ |
| 3186 | 3186 | MACHINE_RESET( ti99_4p ) |
| 3187 | 3187 | { |
| 3188 | | |
| 3188 | | |
| 3189 | 3189 | |
| 3190 | 3190 | UINT8* mem = memory_region(machine, "maincpu"); |
| 3191 | 3191 |
| r8806 | r8807 | |
|---|---|---|
| 239 | 239 | |
| 240 | 240 | static void pk8020_set_bank(running_machine *machine,UINT8 data) |
| 241 | 241 | { |
| 242 | | |
| 242 | | |
| 243 | 243 | switch(data & 0x1F) { |
| 244 | 244 | case 0x00 : |
| 245 | 245 | { |
| r8806 | r8807 | |
|---|---|---|
| 218 | 218 | */ |
| 219 | 219 | |
| 220 | 220 | |
| 221 | ||
| 221 | ||
| 222 | 222 | { |
| 223 | UINT8 *ram = memory_region( | |
| 223 | UINT8 *ram = memory_region( | |
| 224 | 224 | if (vdusel == 0) |
| 225 | 225 | { |
| 226 | 226 | // not in shadow ram mode so just read normal ram |
| 227 | memory_set_bankptr( | |
| 227 | memory_set_bankptr( | |
| 228 | 228 | } |
| 229 | 229 | else |
| 230 | 230 | { |
| 231 | if (vdudriverset( | |
| 231 | if (vdudriverset( | |
| 232 | 232 | { |
| 233 | 233 | // if VDUDriver set then read from shadow ram |
| 234 | memory_set_bankptr( | |
| 234 | memory_set_bankptr( | |
| 235 | 235 | } |
| 236 | 236 | else |
| 237 | 237 | { |
| 238 | 238 | // else read from normal ram |
| 239 | memory_set_bankptr( | |
| 239 | memory_set_bankptr( | |
| 240 | 240 | } |
| 241 | 241 | } |
| 242 | 242 | return address; |
| r8806 | r8807 | |
| 478 | 478 | } |
| 479 | 479 | |
| 480 | 480 | |
| 481 | ||
| 481 | ||
| 482 | 482 | { |
| 483 | 483 | if (ACCCON_X) |
| 484 | 484 | { |
| 485 | memory_set_bankptr( | |
| 485 | memory_set_bankptr( | |
| 486 | 486 | } |
| 487 | 487 | else |
| 488 | 488 | { |
| 489 | if (ACCCON_E && bbcm_vdudriverset( | |
| 489 | if (ACCCON_E && bbcm_vdudriverset( | |
| 490 | 490 | { |
| 491 | memory_set_bankptr( | |
| 491 | memory_set_bankptr( | |
| 492 | 492 | } |
| 493 | 493 | else |
| 494 | 494 | { |
| 495 | memory_set_bankptr( | |
| 495 | memory_set_bankptr( | |
| 496 | 496 | } |
| 497 | 497 | } |
| 498 | 498 | |
| r8806 | r8807 | |
| 886 | 886 | |
| 887 | 887 | |
| 888 | 888 | |
| 889 | static int bbc_keyboard( | |
| 889 | static int bbc_keyboard( | |
| 890 | 890 | { |
| 891 | 891 | int bit; |
| 892 | 892 | int row; |
| r8806 | r8807 | |
| 945 | 945 | |
| 946 | 946 | |
| 947 | 947 | /* This the BBC Masters Real Time Clock and NVRam IC */ |
| 948 | static void MC146818_set( | |
| 948 | static void MC146818_set( | |
| 949 | 949 | { |
| 950 | 950 | logerror ("146181 WR=%d DS=%d AS=%d CE=%d \n",MC146818_WR,MC146818_DS,MC146818_AS,MC146818_CE); |
| 951 | 951 | |
| r8806 | r8807 | |
| 979 | 979 | |
| 980 | 980 | static WRITE8_DEVICE_HANDLER( bbcb_via_system_write_porta ) |
| 981 | 981 | { |
| 982 | | |
| 982 | | |
| 983 | 983 | //logerror("SYSTEM write porta %d\n",data); |
| 984 | 984 | |
| 985 | 985 | via_system_porta = data; |
| r8806 | r8807 | |
| 999 | 999 | |
| 1000 | 1000 | static WRITE8_DEVICE_HANDLER( bbcb_via_system_write_portb ) |
| 1001 | 1001 | { |
| 1002 | | |
| 1002 | | |
| 1003 | 1003 | int bit, value; |
| 1004 | 1004 | bit = data & 0x07; |
| 1005 | 1005 | value = (data >> 3) & 0x01; |
| r8806 | r8807 | |
| 2139 | 2139 | { |
| 2140 | 2140 | mc6850_clock = 0; |
| 2141 | 2141 | |
| 2142 | | |
| 2142 | | |
| 2143 | 2143 | |
| 2144 | 2144 | /* bank 6 is the paged ROMs from b000 to bfff */ |
| 2145 | 2145 | memory_configure_bank(machine, "bank6", 0, 16, memory_region(machine, "user1") + 0x3000, 1<<14); |
| r8806 | r8807 | |
| 2165 | 2165 | { |
| 2166 | 2166 | mc6850_clock = 0; |
| 2167 | 2167 | |
| 2168 | | |
| 2168 | | |
| 2169 | 2169 | |
| 2170 | 2170 | /* bank 5 is the paged ROMs from 9000 to bfff */ |
| 2171 | 2171 | memory_configure_bank(machine, "bank5", 0, 16, memory_region(machine, "user1")+0x01000, 1<<14); |
| r8806 | r8807 | |
|---|---|---|
| 163 | 163 | |
| 164 | 164 | logerror("interface ram w: %04x %02x\n",addr,data); |
| 165 | 165 | |
| 166 | | |
| 166 | space-> | |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | 169 | READ8_HANDLER(kc85_disc_interface_ram_r) |
| r8806 | r8807 | |
| 175 | 175 | |
| 176 | 176 | logerror("interface ram r: %04x\n",addr); |
| 177 | 177 | |
| 178 | return | |
| 178 | return space->r | |
| 179 | 179 | } |
| 180 | 180 | |
| 181 | 181 | /* 4-bit latch used to reset disc interface etc */ |
| r8806 | r8807 | |
| 1117 | 1117 | |
| 1118 | 1118 | static void kc85_4_update_0x08000(running_machine *machine) |
| 1119 | 1119 | { |
| 1120 | | |
| 1120 | | |
| 1121 | 1121 | unsigned char *ram_page; |
| 1122 | 1122 | |
| 1123 | 1123 | if (kc85_pio_data[1] & (1<<5)) |
| r8806 | r8807 | |
| 1184 | 1184 | /* update status of memory area 0x0000-0x03fff */ |
| 1185 | 1185 | static void kc85_4_update_0x00000(running_machine *machine) |
| 1186 | 1186 | { |
| 1187 | | |
| 1187 | | |
| 1188 | 1188 | |
| 1189 | 1189 | /* access ram? */ |
| 1190 | 1190 | if (kc85_pio_data[0] & (1<<1)) |
| r8806 | r8807 | |
| 1226 | 1226 | /* update status of memory area 0x4000-0x07fff */ |
| 1227 | 1227 | static void kc85_4_update_0x04000(running_machine *machine) |
| 1228 | 1228 | { |
| 1229 | | |
| 1229 | | |
| 1230 | 1230 | |
| 1231 | 1231 | /* access ram? */ |
| 1232 | 1232 | if (kc85_86_data & (1<<0)) |
| r8806 | r8807 | |
| 1273 | 1273 | /* update memory address 0x0c000-0x0e000 */ |
| 1274 | 1274 | static void kc85_4_update_0x0c000(running_machine *machine) |
| 1275 | 1275 | { |
| 1276 | | |
| 1276 | | |
| 1277 | 1277 | |
| 1278 | 1278 | if (kc85_86_data & (1<<7)) |
| 1279 | 1279 | { |
| r8806 | r8807 | |
| 1312 | 1312 | /* update memory address 0x0e000-0x0ffff */ |
| 1313 | 1313 | static void kc85_4_update_0x0e000(running_machine *machine) |
| 1314 | 1314 | { |
| 1315 | | |
| 1315 | | |
| 1316 | 1316 | if (kc85_pio_data[0] & (1<<0)) |
| 1317 | 1317 | { |
| 1318 | 1318 | /* enable CAOS rom in memory range 0x0e000-0x0ffff */ |
| r8806 | r8807 | |
| 1424 | 1424 | /* update memory region 0x0c000-0x0e000 */ |
| 1425 | 1425 | static void kc85_3_update_0x0c000(running_machine *machine) |
| 1426 | 1426 | { |
| 1427 | | |
| 1427 | | |
| 1428 | 1428 | |
| 1429 | 1429 | if (kc85_pio_data[0] & (1<<7)) |
| 1430 | 1430 | { |
| r8806 | r8807 | |
| 1445 | 1445 | /* update memory address 0x0e000-0x0ffff */ |
| 1446 | 1446 | static void kc85_3_update_0x0e000(running_machine *machine) |
| 1447 | 1447 | { |
| 1448 | | |
| 1448 | | |
| 1449 | 1449 | |
| 1450 | 1450 | if (kc85_pio_data[0] & (1<<0)) |
| 1451 | 1451 | { |
| r8806 | r8807 | |
| 1467 | 1467 | for write operations */ |
| 1468 | 1468 | static void kc85_3_update_0x00000(running_machine *machine) |
| 1469 | 1469 | { |
| 1470 | | |
| 1470 | | |
| 1471 | 1471 | |
| 1472 | 1472 | /* access ram? */ |
| 1473 | 1473 | if (kc85_pio_data[0] & (1<<1)) |
| r8806 | r8807 | |
| 1511 | 1511 | /* SMH_BANK(3) is used for read, SMH_BANK(8) is used for write */ |
| 1512 | 1512 | static void kc85_3_update_0x08000(running_machine *machine) |
| 1513 | 1513 | { |
| 1514 | | |
| 1514 | | |
| 1515 | 1515 | unsigned char *ram_page; |
| 1516 | 1516 | |
| 1517 | 1517 | if (kc85_pio_data[0] & (1<<2)) |
| r8806 | r8807 | |
| 1629 | 1629 | } |
| 1630 | 1630 | |
| 1631 | 1631 | #if 0 |
| 1632 | ||
| 1632 | ||
| 1633 | 1633 | { |
| 1634 | 1634 | memory_set_direct_update_handler(0,0); |
| 1635 | 1635 | |
| r8806 | r8807 | |
| 1639 | 1639 | } |
| 1640 | 1640 | |
| 1641 | 1641 | |
| 1642 | ||
| 1642 | ||
| 1643 | 1643 | { |
| 1644 | 1644 | memory_set_direct_update_handler(0,0); |
| 1645 | 1645 |
| r8806 | r8807 | |
|---|---|---|
| 19 | 19 | { |
| 20 | 20 | int x,y,j,b; |
| 21 | 21 | UINT8 *gfx = memory_region(screen->machine, "gfx1"); |
| 22 | | |
| 22 | | |
| 23 | 23 | |
| 24 | 24 | for(y = 0; y < 25; y++ ) |
| 25 | 25 | { |
| 26 | 26 | for(x = 0; x < 40; x++ ) |
| 27 | 27 | { |
| 28 | int code = | |
| 28 | int code = space->r | |
| 29 | 29 | for(j = 0; j < 8; j++ ) |
| 30 | 30 | { |
| 31 | 31 | for(b = 0; b < 8; b++ ) |
| r8806 | r8807 | |
| 42 | 42 | { |
| 43 | 43 | int x,y,j,b; |
| 44 | 44 | UINT8 *gfx = memory_region(screen->machine, "gfx1"); |
| 45 | | |
| 45 | | |
| 46 | 46 | |
| 47 | 47 | for(y = 0; y < 25; y++ ) |
| 48 | 48 | { |
| 49 | 49 | for(x = 0; x < 80; x++ ) |
| 50 | 50 | { |
| 51 | int code = | |
| 51 | int code = space->r | |
| 52 | 52 | for(j = 0; j < 8; j++ ) |
| 53 | 53 | { |
| 54 | 54 | for(b = 0; b < 8; b++ ) |
| r8806 | r8807 | |
|---|---|---|
| 130 | 130 | data >>= 1 |
| 131 | 131 | |
| 132 | 132 | #define draw_quart \ |
| 133 | UINT8 data = | |
| 133 | UINT8 data = space->r | |
| 134 | 134 | draw_pixel; draw_pixel; draw_pixel; draw_pixel; |
| 135 | 135 | |
| 136 | 136 | |
| 137 | 137 | VIDEO_UPDATE ( hp48 ) |
| 138 | 138 | { |
| 139 | | |
| 139 | | |
| 140 | 140 | int x, y, xp, i, addr; |
| 141 | 141 | int display = HP48_IO_4(0) >> 3; /* 1=on, 0=off */ |
| 142 | 142 | int left_margin = HP48_IO_4(0) & 7; /* 0..7 pixels for main bitmap */ |
| r8806 | r8807 | |
|---|---|---|
| 41 | 41 | |
| 42 | 42 | void apple3_write_charmem(running_machine *machine) |
| 43 | 43 | { |
| 44 | | |
| 44 | | |
| 45 | 45 | static const UINT32 screen_hole_map[] = |
| 46 | 46 | { |
| 47 | 47 | 0x478, 0x4f8, 0x578, 0x5f8, 0x678, 0x6f8, 0x778, 0x7f8 |
| r8806 | r8807 | |
| 53 | 53 | { |
| 54 | 54 | for (j = 0; j < 4; j++) |
| 55 | 55 | { |
| 56 | addr = 0x7f & memory_read_byte(space, screen_hole_map[i] + 0x400 + j + 0); | |
| 57 | val = memory_read_byte(space, screen_hole_map[i] + j + 0); | |
| 56 | addr = 0x7f & space->read_byte(screen_hole_map[i] + 0x400 + j + 0); | |
| 57 | val = space->read_byte(screen_hole_map[i] + j + 0); | |
| 58 | 58 | char_mem[((addr * 8) + ((i & 3) * 2) + 0) & 0x3ff] = val; |
| 59 | 59 | |
| 60 | addr = 0x7f & memory_read_byte(space, screen_hole_map[i] + 0x400 + j + 4); | |
| 61 | val = memory_read_byte(space, screen_hole_map[i] + j + 4); | |
| 60 | addr = 0x7f & space->read_byte(screen_hole_map[i] + 0x400 + j + 4); | |
| 61 | val = space->read_byte(screen_hole_map[i] + j + 4); | |
| 62 | 62 | char_mem[((addr * 8) + ((i & 3) * 2) + 1) & 0x3ff] = val; |
| 63 | 63 | } |
| 64 | 64 | } |
| r8806 | r8807 | |
|---|---|---|
| 550 | 550 | |
| 551 | 551 | static void vga_cpu_interface(running_machine *machine) |
| 552 | 552 | { |
| 553 | | |
| 553 | | |
| 554 | 554 | static int sequencer, gc; |
| 555 | 555 | read8_space_func read_handler; |
| 556 | 556 | write8_space_func write_handler; |
| r8806 | r8807 | |
| 1174 | 1174 | void pc_vga_init(running_machine *machine, const struct pc_vga_interface *vga_intf, const struct pc_svga_interface *svga_intf) |
| 1175 | 1175 | { |
| 1176 | 1176 | int i, j, k, mask, buswidth; |
| 1177 | | |
| 1177 | | |
| 1178 | 1178 | |
| 1179 | 1179 | memset(&vga, 0, sizeof(vga)); |
| 1180 | 1180 |
| r8806 | r8807 | |
|---|---|---|
| 334 | 334 | /* |
| 335 | 335 | CRU interface write |
| 336 | 336 | */ |
| 337 | static void vdt911_cru_w( | |
| 337 | static void vdt911_cru_w( | |
| 338 | 338 | { |
| 339 | 339 | offset &= 0xf; |
| 340 | 340 |
| r8806 | r8807 | |
|---|---|---|
| 59 | 59 | |
| 60 | 60 | VIDEO_UPDATE( dai ) |
| 61 | 61 | { |
| 62 | | |
| 62 | | |
| 63 | 63 | int i, j, k, l; |
| 64 | 64 | |
| 65 | 65 | UINT8* char_rom = memory_region(screen->machine, "gfx1"); |
| r8806 | r8807 | |
| 103 | 103 | |
| 104 | 104 | while (current_scan_line < dai_scan_lines) |
| 105 | 105 | { |
| 106 | mode = memory_read_byte(space, current_video_memory_address--); | |
| 107 | colour = memory_read_byte(space, current_video_memory_address--); | |
| 106 | mode = space->read_byte(current_video_memory_address--); | |
| 107 | colour = space->read_byte(current_video_memory_address--); | |
| 108 | 108 | line_repeat_count = mode & 0x0f; |
| 109 | 109 | horizontal_resolution = (mode & 0x30) >> 4; |
| 110 | 110 | display_mode = (mode & 0xc0) >> 6; |
| r8806 | r8807 | |
| 124 | 124 | switch (unit_mode) |
| 125 | 125 | { |
| 126 | 126 | case 0: |
| 127 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 128 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 127 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 128 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 129 | 129 | |
| 130 | 130 | for (i=0; i<11; i++) |
| 131 | 131 | { |
| r8806 | r8807 | |
| 144 | 144 | case 1: |
| 145 | 145 | for (i=0; i<11; i++) |
| 146 | 146 | { |
| 147 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 148 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 147 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 148 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 149 | 149 | for (j=0; j<=line_repeat_count; j++) |
| 150 | 150 | { |
| 151 | 151 | for (k=0; k<8; k++) |
| r8806 | r8807 | |
| 164 | 164 | switch (unit_mode) |
| 165 | 165 | { |
| 166 | 166 | case 0: |
| 167 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 168 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 167 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 168 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 169 | 169 | for (i=0; i<22; i++) |
| 170 | 170 | { |
| 171 | 171 | for (j=0; j<=line_repeat_count; j++) |
| r8806 | r8807 | |
| 183 | 183 | case 1: |
| 184 | 184 | for (i=0; i<22; i++) |
| 185 | 185 | { |
| 186 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 187 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 186 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 187 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 188 | 188 | for (j=0; j<=line_repeat_count; j++) |
| 189 | 189 | { |
| 190 | 190 | for (k=0; k<8; k++) |
| r8806 | r8807 | |
| 203 | 203 | switch (unit_mode) |
| 204 | 204 | { |
| 205 | 205 | case 0: |
| 206 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 207 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 206 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 207 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 208 | 208 | for (i=0; i<44; i++) |
| 209 | 209 | { |
| 210 | 210 | for (j=0; j<=line_repeat_count; j++) |
| r8806 | r8807 | |
| 221 | 221 | case 1: |
| 222 | 222 | for (i=0; i<44; i++) |
| 223 | 223 | { |
| 224 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 225 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 224 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 225 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 226 | 226 | for (j=0; j<=line_repeat_count; j++) |
| 227 | 227 | { |
| 228 | 228 | for (k=0; k<8; k++) |
| r8806 | r8807 | |
| 241 | 241 | switch (unit_mode) |
| 242 | 242 | { |
| 243 | 243 | case 0: |
| 244 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 245 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 244 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 245 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 246 | 246 | for (i=0; i<66; i++) |
| 247 | 247 | { |
| 248 | 248 | for (j=0; j<=line_repeat_count; j++) |
| r8806 | r8807 | |
| 259 | 259 | case 1: |
| 260 | 260 | for (i=0; i<66; i++) |
| 261 | 261 | { |
| 262 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 263 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 262 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 263 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 264 | 264 | for (j=0; j<=line_repeat_count; j++) |
| 265 | 265 | { |
| 266 | 266 | for (k=0; k<8; k++) |
| r8806 | r8807 | |
| 285 | 285 | switch (unit_mode) |
| 286 | 286 | { |
| 287 | 287 | case 0: |
| 288 | current_data_1 = memory_read_byte(space, current_video_memory_address); | |
| 289 | current_data_2 = memory_read_byte(space, current_video_memory_address-3); | |
| 288 | current_data_1 = space->read_byte(current_video_memory_address); | |
| 289 | current_data_2 = space->read_byte(current_video_memory_address-3); | |
| 290 | 290 | current_video_memory_address-=2; |
| 291 | 291 | for (i=0; i<11; i++) |
| 292 | 292 | { |
| r8806 | r8807 | |
| 305 | 305 | case 1: |
| 306 | 306 | for (i=0; i<11; i++) |
| 307 | 307 | { |
| 308 | current_data_1 = memory_read_byte(space, current_video_memory_address); | |
| 309 | current_data_2 = memory_read_byte(space, current_video_memory_address-3); | |
| 308 | current_data_1 = space->read_byte(current_video_memory_address); | |
| 309 | current_data_2 = space->read_byte(current_video_memory_address-3); | |
| 310 | 310 | current_video_memory_address-=2; |
| 311 | 311 | for (j=0; j<=line_repeat_count; j++) |
| 312 | 312 | { |
| r8806 | r8807 | |
| 326 | 326 | switch (unit_mode) |
| 327 | 327 | { |
| 328 | 328 | case 0: |
| 329 | current_data_1 = memory_read_byte(space, current_video_memory_address); | |
| 330 | current_data_2 = memory_read_byte(space, current_video_memory_address-3); | |
| 329 | current_data_1 = space->read_byte(current_video_memory_address); | |
| 330 | current_data_2 = space->read_byte(current_video_memory_address-3); | |
| 331 | 331 | current_video_memory_address-=2; |
| 332 | 332 | for (i=0; i<22; i++) |
| 333 | 333 | { |
| r8806 | r8807 | |
| 346 | 346 | case 1: |
| 347 | 347 | for (i=0; i<22; i++) |
| 348 | 348 | { |
| 349 | current_data_1 = memory_read_byte(space, current_video_memory_address); | |
| 350 | current_data_2 = memory_read_byte(space, current_video_memory_address-3); | |
| 349 | current_data_1 = space->read_byte(current_video_memory_address); | |
| 350 | current_data_2 = space->read_byte(current_video_memory_address-3); | |
| 351 | 351 | current_video_memory_address-=2; |
| 352 | 352 | for (j=0; j<=line_repeat_count; j++) |
| 353 | 353 | { |
| r8806 | r8807 | |
| 367 | 367 | switch (unit_mode) |
| 368 | 368 | { |
| 369 | 369 | case 0: |
| 370 | current_data_1 = memory_read_byte(space, current_video_memory_address); | |
| 371 | current_data_2 = memory_read_byte(space, current_video_memory_address-3); | |
| 370 | current_data_1 = space->read_byte(current_video_memory_address); | |
| 371 | current_data_2 = space->read_byte(current_video_memory_address-3); | |
| 372 | 372 | current_video_memory_address-=2; |
| 373 | 373 | for (i=0; i<44; i++) |
| 374 | 374 | { |
| r8806 | r8807 | |
| 386 | 386 | case 1: |
| 387 | 387 | for (i=0; i<44; i++) |
| 388 | 388 | { |
| 389 | current_data_1 = memory_read_byte(space, current_video_memory_address); | |
| 390 | current_data_2 = memory_read_byte(space, current_video_memory_address-3); | |
| 389 | current_data_1 = space->read_byte(current_video_memory_address); | |
| 390 | current_data_2 = space->read_byte(current_video_memory_address-3); | |
| 391 | 391 | current_video_memory_address-=2; |
| 392 | 392 | for (j=0; j<=line_repeat_count; j++) |
| 393 | 393 | { |
| r8806 | r8807 | |
| 406 | 406 | switch (unit_mode) |
| 407 | 407 | { |
| 408 | 408 | case 0: |
| 409 | current_data_1 = memory_read_byte(space, current_video_memory_address); | |
| 410 | current_data_2 = memory_read_byte(space, current_video_memory_address-3); | |
| 409 | current_data_1 = space->read_byte(current_video_memory_address); | |
| 410 | current_data_2 = space->read_byte(current_video_memory_address-3); | |
| 411 | 411 | current_video_memory_address-=2; |
| 412 | 412 | for (i=0; i<66; i++) |
| 413 | 413 | { |
| r8806 | r8807 | |
| 425 | 425 | case 1: |
| 426 | 426 | for (i=0; i<66; i++) |
| 427 | 427 | { |
| 428 | current_data_1 = memory_read_byte(space, current_video_memory_address); | |
| 429 | current_data_2 = memory_read_byte(space, current_video_memory_address-3); | |
| 428 | current_data_1 = space->read_byte(current_video_memory_address); | |
| 429 | current_data_2 = space->read_byte(current_video_memory_address-3); | |
| 430 | 430 | current_video_memory_address-=2; |
| 431 | 431 | for (j=0; j<=line_repeat_count; j++) |
| 432 | 432 | { |
| r8806 | r8807 | |
| 451 | 451 | switch (unit_mode) |
| 452 | 452 | { |
| 453 | 453 | case 0: |
| 454 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 455 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 454 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 455 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 456 | 456 | |
| 457 | 457 | for (i=0; i<11; i++) |
| 458 | 458 | { |
| r8806 | r8807 | |
| 471 | 471 | case 1: |
| 472 | 472 | for (i=0; i<11; i++) |
| 473 | 473 | { |
| 474 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 475 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 474 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 475 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 476 | 476 | for (j=0; j<=line_repeat_count; j++) |
| 477 | 477 | { |
| 478 | 478 | for (k=0; k<8; k++) |
| r8806 | r8807 | |
| 491 | 491 | switch (unit_mode) |
| 492 | 492 | { |
| 493 | 493 | case 0: |
| 494 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 495 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 494 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 495 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 496 | 496 | for (i=0; i<22; i++) |
| 497 | 497 | { |
| 498 | 498 | for (j=0; j<=line_repeat_count; j++) |
| r8806 | r8807 | |
| 510 | 510 | case 1: |
| 511 | 511 | for (i=0; i<22; i++) |
| 512 | 512 | { |
| 513 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 514 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 513 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 514 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 515 | 515 | for (j=0; j<=line_repeat_count; j++) |
| 516 | 516 | { |
| 517 | 517 | for (k=0; k<8; k++) |
| r8806 | r8807 | |
| 530 | 530 | switch (unit_mode) |
| 531 | 531 | { |
| 532 | 532 | case 0: |
| 533 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 534 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 533 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 534 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 535 | 535 | for (i=0; i<44; i++) |
| 536 | 536 | { |
| 537 | 537 | for (j=0; j<=line_repeat_count; j++) |
| r8806 | r8807 | |
| 548 | 548 | case 1: |
| 549 | 549 | for (i=0; i<44; i++) |
| 550 | 550 | { |
| 551 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 552 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 551 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 552 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 553 | 553 | for (j=0; j<=line_repeat_count; j++) |
| 554 | 554 | { |
| 555 | 555 | for (k=0; k<8; k++) |
| r8806 | r8807 | |
| 568 | 568 | switch (unit_mode) |
| 569 | 569 | { |
| 570 | 570 | case 0: |
| 571 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 572 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 571 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 572 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 573 | 573 | for (i=0; i<66; i++) |
| 574 | 574 | { |
| 575 | 575 | for (j=0; j<=line_repeat_count; j++) |
| r8806 | r8807 | |
| 586 | 586 | case 1: |
| 587 | 587 | for (i=0; i<66; i++) |
| 588 | 588 | { |
| 589 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 590 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 589 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 590 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 591 | 591 | for (j=0; j<=line_repeat_count; j++) |
| 592 | 592 | { |
| 593 | 593 | for (k=0; k<8; k++) |
| r8806 | r8807 | |
| 611 | 611 | switch (unit_mode) |
| 612 | 612 | { |
| 613 | 613 | case 0: |
| 614 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 615 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 614 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 615 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 616 | 616 | for (i=0; i<11; i++) |
| 617 | 617 | { |
| 618 | 618 | for (j=0; j<=line_repeat_count; j++) |
| r8806 | r8807 | |
| 630 | 630 | case 1: |
| 631 | 631 | for (i=0; i<11; i++) |
| 632 | 632 | { |
| 633 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 634 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 633 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 634 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 635 | 635 | for (j=0; j<=line_repeat_count; j++) |
| 636 | 636 | { |
| 637 | 637 | for (k=0; k<8; k++) |
| r8806 | r8807 | |
| 650 | 650 | switch (unit_mode) |
| 651 | 651 | { |
| 652 | 652 | case 0: |
| 653 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 654 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 653 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 654 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 655 | 655 | for (i=0; i<22; i++) |
| 656 | 656 | { |
| 657 | 657 | for (j=0; j<=line_repeat_count; j++) |
| r8806 | r8807 | |
| 669 | 669 | case 1: |
| 670 | 670 | for (i=0; i<22; i++) |
| 671 | 671 | { |
| 672 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 673 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 672 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 673 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 674 | 674 | for (j=0; j<=line_repeat_count; j++) |
| 675 | 675 | { |
| 676 | 676 | for (k=0; k<8; k++) |
| r8806 | r8807 | |
| 689 | 689 | switch (unit_mode) |
| 690 | 690 | { |
| 691 | 691 | case 0: |
| 692 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 693 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 692 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 693 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 694 | 694 | for (i=0; i<44; i++) |
| 695 | 695 | { |
| 696 | 696 | for (j=0; j<=line_repeat_count; j++) |
| r8806 | r8807 | |
| 707 | 707 | case 1: |
| 708 | 708 | for (i=0; i<44; i++) |
| 709 | 709 | { |
| 710 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 711 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 710 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 711 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 712 | 712 | for (j=0; j<=line_repeat_count; j++) |
| 713 | 713 | { |
| 714 | 714 | for (k=0; k<8; k++) |
| r8806 | r8807 | |
| 726 | 726 | switch (unit_mode) |
| 727 | 727 | { |
| 728 | 728 | case 0: |
| 729 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 730 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 729 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 730 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 731 | 731 | for (i=0; i<66; i++) |
| 732 | 732 | { |
| 733 | 733 | for (j=0; j<=line_repeat_count; j++) |
| r8806 | r8807 | |
| 744 | 744 | case 1: |
| 745 | 745 | for (i=0; i<66; i++) |
| 746 | 746 | { |
| 747 | current_data_1 = memory_read_byte(space, current_video_memory_address--); | |
| 748 | current_data_2 = memory_read_byte(space, current_video_memory_address--); | |
| 747 | current_data_1 = space->read_byte(current_video_memory_address--); | |
| 748 | current_data_2 = space->read_byte(current_video_memory_address--); | |
| 749 | 749 | for (j=0; j<=line_repeat_count; j++) |
| 750 | 750 | { |
| 751 | 751 | for (k=0; k<8; k++) |
| r8806 | r8807 | |
|---|---|---|
| 29 | 29 | VIDEO_UPDATE( ac1 ) |
| 30 | 30 | { |
| 31 | 31 | int x,y; |
| 32 | | |
| 32 | | |
| 33 | 33 | |
| 34 | 34 | for(y = 0; y < 16; y++ ) |
| 35 | 35 | { |
| 36 | 36 | for(x = 0; x < 64; x++ ) |
| 37 | 37 | { |
| 38 | int code = | |
| 38 | int code = space->r | |
| 39 | 39 | drawgfx_opaque(bitmap, NULL, screen->machine->gfx[0], code , 0, 0,0, 63*6-x*6,15*8-y*8); |
| 40 | 40 | } |
| 41 | 41 | } |
| r8806 | r8807 | |
| 45 | 45 | VIDEO_UPDATE( ac1_32 ) |
| 46 | 46 | { |
| 47 | 47 | int x,y; |
| 48 | | |
| 48 | | |
| 49 | 49 | |
| 50 | 50 | for(y = 0; y < 32; y++ ) |
| 51 | 51 | { |
| 52 | 52 | for(x = 0; x < 64; x++ ) |
| 53 | 53 | { |
| 54 | int code = | |
| 54 | int code = space->r | |
| 55 | 55 | drawgfx_opaque(bitmap, NULL, screen->machine->gfx[0], code , 0, 0,0, 63*6-x*6,31*8-y*8); |
| 56 | 56 | } |
| 57 | 57 | } |
| r8806 | r8807 | |
|---|---|---|
| 1301 | 1301 | { |
| 1302 | 1302 | int i; |
| 1303 | 1303 | int vram_size = 0x2000; |
| 1304 | | |
| 1304 | | |
| 1305 | 1305 | emu_timer *old_timer = gb_lcd.lcd_timer; |
| 1306 | 1306 | |
| 1307 | 1307 | memset( &gb_lcd, 0, sizeof(gb_lcd) ); |
| r8806 | r8807 | |
| 1410 | 1410 | static void gbc_hdma(running_machine *machine, UINT16 length) |
| 1411 | 1411 | { |
| 1412 | 1412 | UINT16 src, dst; |
| 1413 | | |
| 1413 | | |
| 1414 | 1414 | |
| 1415 | 1415 | src = ((UINT16)HDMA1 << 8) | (HDMA2 & 0xF0); |
| 1416 | 1416 | dst = ((UINT16)(HDMA3 & 0x1F) << 8) | (HDMA4 & 0xF0); |
| 1417 | 1417 | dst |= 0x8000; |
| 1418 | 1418 | while( length > 0 ) |
| 1419 | 1419 | { |
| 1420 | | |
| 1420 | space-> | |
| 1421 | 1421 | length--; |
| 1422 | 1422 | } |
| 1423 | 1423 | HDMA1 = src >> 8; |
| r8806 | r8807 | |
| 2173 | 2173 | UINT8 *P = gb_lcd.gb_oam->base(); |
| 2174 | 2174 | offset = (UINT16) data << 8; |
| 2175 | 2175 | for (data = 0; data < 0xA0; data++) |
| 2176 | *P++ = | |
| 2176 | *P++ = space->r | |
| 2177 | 2177 | } |
| 2178 | 2178 | return; |
| 2179 | 2179 | case 0x07: /* BGP - Background Palette */ |
| r8806 | r8807 | |
|---|---|---|
| 30 | 30 | VIDEO_UPDATE( kramermc ) |
| 31 | 31 | { |
| 32 | 32 | int x,y; |
| 33 | | |
| 33 | | |
| 34 | 34 | |
| 35 | 35 | for(y = 0; y < 16; y++ ) |
| 36 | 36 | { |
| 37 | 37 | for(x = 0; x < 64; x++ ) |
| 38 | 38 | { |
| 39 | int code = | |
| 39 | int code = space->r | |
| 40 | 40 | drawgfx_opaque(bitmap, NULL, screen->machine->gfx[0], code , 0, 0,0, x*8,y*8); |
| 41 | 41 | } |
| 42 | 42 | } |
| r8806 | r8807 | |
|---|---|---|
| 119 | 119 | { |
| 120 | 120 | atarist_state *state = machine->driver_data<atarist_state>(); |
| 121 | 121 | |
| 122 | const address_space *program = cputag_get_address_space(machine, M68000_TAG, ADDRESS_SPACE_PROGRAM); | |
| 123 | UINT16 data = memory_read_word_16be(program, state->shifter_ofs); | |
| 122 | address_space *program = cputag_get_address_space(machine, M68000_TAG, ADDRESS_SPACE_PROGRAM); | |
| 123 | UINT16 data = program->read_word(state->shifter_ofs); | |
| 124 | 124 | |
| 125 | 125 | state->shifter_ir[state->shifter_bitplane] = data; |
| 126 | 126 | state->shifter_bitplane++; |
| r8806 | r8807 | |
| 421 | 421 | { |
| 422 | 422 | atarist_state *state = machine->driver_data<atarist_state>(); |
| 423 | 423 | |
| 424 | const address_space *program = cputag_get_address_space(machine, M68000_TAG, ADDRESS_SPACE_PROGRAM); | |
| 425 | UINT16 data = memory_read_word_16be(program, state->blitter_src); | |
| 424 | address_space *program = cputag_get_address_space(machine, M68000_TAG, ADDRESS_SPACE_PROGRAM); | |
| 425 | UINT16 data = program->read_word(state->blitter_src); | |
| 426 | 426 | |
| 427 | 427 | if (state->blitter_src_inc_x < 0) |
| 428 | 428 | { |
| r8806 | r8807 | |
| 464 | 464 | static void atarist_blitter_op(running_machine *machine, UINT16 s, UINT32 dstaddr, UINT16 mask) |
| 465 | 465 | { |
| 466 | 466 | atarist_state *state = machine->driver_data<atarist_state>(); |
| 467 | | |
| 467 | | |
| 468 | 468 | |
| 469 | UINT16 d = | |
| 469 | UINT16 d = pr | |
| 470 | 470 | UINT16 result = 0; |
| 471 | 471 | |
| 472 | 472 | if (state->blitter_op & 0x08) result = (~s & ~d); |
| r8806 | r8807 | |
| 474 | 474 | if (state->blitter_op & 0x02) result |= (s & ~d); |
| 475 | 475 | if (state->blitter_op & 0x01) result |= (s & d); |
| 476 | 476 | |
| 477 | | |
| 477 | pr | |
| 478 | 478 | } |
| 479 | 479 | |
| 480 | 480 | static TIMER_CALLBACK( atarist_blitter_tick ) |
| r8806 | r8807 | |
|---|---|---|
| 121 | 121 | { |
| 122 | 122 | /* attribute */ |
| 123 | 123 | int attribute = c & 0x03f; |
| 124 | | |
| 124 | | |
| 125 | 125 | |
| 126 | 126 | switch ((attribute>>3) & 0x03) |
| 127 | 127 | { |
| r8806 | r8807 | |
| 299 | 299 | } |
| 300 | 300 | |
| 301 | 301 | /* fetch data */ |
| 302 | c = RAM ? RAM[read_addr] : | |
| 302 | c = RAM ? RAM[read_addr] : | |
| 303 | 303 | |
| 304 | 304 | /* if bits 6 and 5 are zero, the byte contains a serial attribute */ |
| 305 | 305 | if ((c & ((1 << 6) | (1 << 5))) == 0) |
| r8806 | r8807 | |
|---|---|---|
| 979 | 979 | static void draw_graphics_line(running_device *device, bitmap_t *bitmap, UINT32 addr, int y, int wd) |
| 980 | 980 | { |
| 981 | 981 | upd7220_t *upd7220 = get_safe_token(device); |
| 982 | | |
| 982 | | |
| 983 | 983 | int sx; |
| 984 | 984 | |
| 985 | 985 | for (sx = 0; sx < upd7220->aw; sx++) |
| r8806 | r8807 | |
|---|---|---|
| 20 | 20 | UINT8 code1, code2; |
| 21 | 21 | UINT8 col; |
| 22 | 22 | int y, x, b; |
| 23 | | |
| 23 | | |
| 24 | 24 | |
| 25 | 25 | // draw image |
| 26 | 26 | for (y = 0; y < 200; y++) |
| 27 | 27 | { |
| 28 | 28 | for (x = 0; x < 40; x++) |
| 29 | 29 | { |
| 30 | code1 = memory_read_byte(space, 0xe000 + x + y * 40); | |
| 31 | code2 = memory_read_byte(space, 0xc000 + x + y * 40); | |
| 30 | code1 = space->read_byte(0xe000 + x + y * 40); | |
| 31 | code2 = space->read_byte(0xc000 + x + y * 40); | |
| 32 | 32 | for (b = 0; b < 8; b++) |
| 33 | 33 | { |
| 34 | 34 | col = ((code1 >> b) & 0x01); |
| r8806 | r8807 | |
|---|---|---|
| 101 | 101 | VIDEO_START( pc_mda ) |
| 102 | 102 | { |
| 103 | 103 | int buswidth; |
| 104 | | |
| 104 | | |
| 105 | 105 | |
| 106 | 106 | buswidth = device_memory(machine->firstcpu)->space_config(AS_PROGRAM)->m_databus_width; |
| 107 | 107 | switch(buswidth) |
| r8806 | r8807 | |
| 453 | 453 | static VIDEO_START( pc_hercules ) |
| 454 | 454 | { |
| 455 | 455 | int buswidth; |
| 456 | | |
| 456 | | |
| 457 | 457 | |
| 458 | 458 | buswidth = device_memory(machine->firstcpu)->space_config(AS_PROGRAM)->m_databus_width; |
| 459 | 459 | switch(buswidth) |
| r8806 | r8807 | |
|---|---|---|
| 28 | 28 | |
| 29 | 29 | #define TRIGGER_HSYNC 64717 |
| 30 | 30 | |
| 31 | #define READ_MEM(x) | |
| 31 | #define READ_MEM(x) space->r | |
| 32 | 32 | |
| 33 | 33 | /*static unsigned char *ROM; */ |
| 34 | 34 | |
| r8806 | r8807 | |
| 106 | 106 | |
| 107 | 107 | static void maria_draw_scanline(running_machine *machine) |
| 108 | 108 | { |
| 109 | | |
| 109 | | |
| 110 | 110 | unsigned int graph_adr,data_addr; |
| 111 | 111 | int width,hpos,pal,mode,ind; |
| 112 | 112 | unsigned int dl; |
| r8806 | r8807 | |
| 340 | 340 | { |
| 341 | 341 | int frame_scanline; |
| 342 | 342 | UINT8 *ROM = memory_region(device->machine, "maincpu"); |
| 343 | | |
| 343 | | |
| 344 | 344 | |
| 345 | 345 | maria_scanline++; |
| 346 | 346 |
| r8806 | r8807 | |
|---|---|---|
| 21 | 21 | { |
| 22 | 22 | newbrain_state *state = machine->driver_data<newbrain_state>(); |
| 23 | 23 | |
| 24 | | |
| 24 | | |
| 25 | 25 | |
| 26 | 26 | int y, sx; |
| 27 | 27 | int columns = (state->tvctl & NEWBRAIN_VIDEO_80L) ? 80 : 40; |
| r8806 | r8807 | |
| 42 | 42 | { |
| 43 | 43 | int bit; |
| 44 | 44 | |
| 45 | UINT8 videoram_data = | |
| 45 | UINT8 videoram_data = pr | |
| 46 | 46 | UINT8 charrom_data; |
| 47 | 47 | |
| 48 | 48 | if (gr) |
| r8806 | r8807 | |
|---|---|---|
| 680 | 680 | |
| 681 | 681 | VIDEO_START( pc_aga ) |
| 682 | 682 | { |
| 683 | | |
| 683 | | |
| 684 | 684 | int buswidth = device_memory(machine->firstcpu)->space_config(AS_PROGRAM)->m_databus_width; |
| 685 | 685 | |
| 686 | 686 | switch(buswidth) |
| r8806 | r8807 | |
| 714 | 714 | |
| 715 | 715 | VIDEO_START( pc200 ) |
| 716 | 716 | { |
| 717 | | |
| 717 | | |
| 718 | 718 | int buswidth; |
| 719 | 719 | |
| 720 | 720 | VIDEO_START_CALL(pc_aga); |
| r8806 | r8807 | |
|---|---|---|
| 458 | 458 | static VIDEO_START( pc_cga ) |
| 459 | 459 | { |
| 460 | 460 | int buswidth; |
| 461 | const address_space *space = cpu_get_address_space(machine->firstcpu, ADDRESS_SPACE_PROGRAM); | |
| 462 | const address_space *spaceio = cpu_get_address_space(machine->firstcpu, ADDRESS_SPACE_IO); | |
| 461 | address_space *space = cpu_get_address_space(machine->firstcpu, ADDRESS_SPACE_PROGRAM); | |
| 462 | address_space *spaceio = cpu_get_address_space(machine->firstcpu, ADDRESS_SPACE_IO); | |
| 463 | 463 | |
| 464 | 464 | /* Changed video RAM size to full 32k, for cards which support the |
| 465 | 465 | * Plantronics chipset. |
| r8806 | r8807 | |
| 1284 | 1284 | case 0x0f: |
| 1285 | 1285 | // Not sure if some all CGA cards have ability to upload char definition |
| 1286 | 1286 | UINT8 buswidth = device_memory(space->machine->firstcpu)->space_config(AS_PROGRAM)->m_databus_width; |
| 1287 | | |
| 1287 | | |
| 1288 | 1288 | cga.p3df = data; |
| 1289 | 1289 | if (data & 1) { |
| 1290 | 1290 | switch(buswidth) |
| r8806 | r8807 | |
|---|---|---|
| 609 | 609 | static VIDEO_START( pc_ega ) |
| 610 | 610 | { |
| 611 | 611 | int buswidth; |
| 612 | const address_space *space = cpu_get_address_space(machine->firstcpu, ADDRESS_SPACE_PROGRAM); | |
| 613 | const address_space *spaceio = cpu_get_address_space(machine->firstcpu, ADDRESS_SPACE_IO); | |
| 612 | address_space *space = cpu_get_address_space(machine->firstcpu, ADDRESS_SPACE_PROGRAM); | |
| 613 | address_space *spaceio = cpu_get_address_space(machine->firstcpu, ADDRESS_SPACE_IO); | |
| 614 | 614 | |
| 615 | 615 | buswidth = device_memory(machine->firstcpu)->space_config(AS_PROGRAM)->m_databus_width; |
| 616 | 616 | switch(buswidth) |
| r8806 | r8807 | |
|---|---|---|
| 41 | 41 | VIDEO_UPDATE( mz80k ) |
| 42 | 42 | { |
| 43 | 43 | int x,y; |
| 44 | | |
| 44 | | |
| 45 | 45 | mz80k_vertical = mz80k_vertical ? 0 : 1; |
| 46 | 46 | mz80k_cursor_cnt++; |
| 47 | 47 | if (mz80k_cursor_cnt==64) mz80k_cursor_cnt = 0; |
| r8806 | r8807 | |
| 50 | 50 | { |
| 51 | 51 | for(x = 0; x < 40; x++ ) |
| 52 | 52 | { |
| 53 | int code = | |
| 53 | int code = space->r | |
| 54 | 54 | drawgfx_opaque(bitmap, NULL, screen->machine->gfx[0], code , 0, 0,0, x*8,y*8); |
| 55 | 55 | } |
| 56 | 56 | } |
| r8806 | r8807 | |
|---|---|---|
| 185 | 185 | |
| 186 | 186 | VIDEO_UPDATE( ti85 ) |
| 187 | 187 | { |
| 188 | | |
| 188 | | |
| 189 | 189 | int x,y,b; |
| 190 | 190 | int brightnes; |
| 191 | 191 | int lcdmem; |
| r8806 | r8807 | |
| 205 | 205 | |
| 206 | 206 | for (y=0; y<ti_screen_y_size; y++) |
| 207 | 207 | for (x=0; x<ti_screen_x_size; x++) |
| 208 | *(ti85_frames+(ti_number_of_frames-1)*ti_video_memory_size+y*ti_screen_x_size+x) = | |
| 208 | *(ti85_frames+(ti_number_of_frames-1)*ti_video_memory_size+y*ti_screen_x_size+x) = space->r | |
| 209 | 209 | |
| 210 | 210 | for (y=0; y<ti_screen_y_size; y++) |
| 211 | 211 | for (x=0; x<ti_screen_x_size; x++) |
| r8806 | r8807 | |
|---|---|---|
| 60 | 60 | typedef struct _hd61830_t hd61830_t; |
| 61 | 61 | struct _hd61830_t |
| 62 | 62 | { |
| 63 | | |
| 63 | | |
| 64 | 64 | |
| 65 | 65 | int bf; /* busy flag */ |
| 66 | 66 | |
| r8806 | r8807 | |
| 169 | 169 | |
| 170 | 170 | if (LOG) logerror("HD61380 '%s' Display Data Read %02x\n", device->tag(), hd61830->dor); |
| 171 | 171 | |
| 172 | hd61830->dor = | |
| 172 | hd61830->dor = | |
| 173 | 173 | |
| 174 | 174 | hd61830->cac++; |
| 175 | 175 | |
| r8806 | r8807 | |
| 257 | 257 | break; |
| 258 | 258 | |
| 259 | 259 | case HD61830_INSTRUCTION_DISPLAY_DATA_WRITE: |
| 260 | | |
| 260 | | |
| 261 | 261 | |
| 262 | 262 | if (LOG) logerror("HD61380 '%s' Display Data Write %02x -> %04x row %u col %u\n", device->tag(), data, hd61830->cac, hd61830->cac / 40, hd61830->cac % 40); |
| 263 | 263 | |
| r8806 | r8807 | |
| 267 | 267 | case HD61830_INSTRUCTION_CLEAR_BIT: |
| 268 | 268 | { |
| 269 | 269 | int nb = data & 0x07; |
| 270 | UINT8 data_ = | |
| 270 | UINT8 data_ = | |
| 271 | 271 | |
| 272 | 272 | data_ &= ~(2 << nb); |
| 273 | 273 | |
| 274 | 274 | if (LOG) logerror("HD61380 '%s' Clear Bit %u at %04x\n", device->tag(), nb + 1, hd61830->cac); |
| 275 | 275 | |
| 276 | | |
| 276 | | |
| 277 | 277 | |
| 278 | 278 | hd61830->cac++; |
| 279 | 279 | } |
| r8806 | r8807 | |
| 282 | 282 | case HD61830_INSTRUCTION_SET_BIT: |
| 283 | 283 | { |
| 284 | 284 | int nb = data & 0x07; |
| 285 | UINT8 data_ = | |
| 285 | UINT8 data_ = | |
| 286 | 286 | |
| 287 | 287 | data_ |= 2 << nb; |
| 288 | 288 | |
| 289 | 289 | if (LOG) logerror("HD61380 '%s' Set Bit %u at %04x\n", device->tag(), nb + 1, hd61830->cac); |
| 290 | 290 | |
| 291 | | |
| 291 | | |
| 292 | 292 | |
| 293 | 293 | hd61830->cac++; |
| 294 | 294 | } |
| r8806 | r8807 | |
| 314 | 314 | |
| 315 | 315 | for (sx = 0; sx < hd61830->hn; sx++) |
| 316 | 316 | { |
| 317 | UINT8 data = | |
| 317 | UINT8 data = | |
| 318 | 318 | |
| 319 | 319 | for (x = 0; x < hd61830->hp; x++) |
| 320 | 320 | { |
| r8806 | r8807 | |
| 383 | 383 | for(int y = 0; y < 8; y++) |
| 384 | 384 | for(int x = 0; x < hd61830->hn; x++) |
| 385 | 385 | { |
| 386 | UINT8 char_code = | |
| 386 | UINT8 char_code = | |
| 387 | 387 | |
| 388 | 388 | if (hd61830->cac == y * hd61830->hn + x) |
| 389 | 389 | { |
| r8806 | r8807 | |
|---|---|---|
| 20 | 20 | |
| 21 | 21 | static TIMER_CALLBACK( gal_video ) |
| 22 | 22 | { |
| 23 | | |
| 23 | | |
| 24 | 24 | int y, x; |
| 25 | 25 | if (galaxy_interrupts_enabled == TRUE) |
| 26 | 26 | { |
| r8806 | r8807 | |
| 43 | 43 | } |
| 44 | 44 | else |
| 45 | 45 | { |
| 46 | code = | |
| 46 | code = space->r | |
| 47 | 47 | code += (code & 0x80) >> 1; |
| 48 | 48 | code = gfx[(code & 0x7f) +(dat << 7 )] ^ 0xff; |
| 49 | 49 | first = 0; |
| r8806 | r8807 | |
| 72 | 72 | } |
| 73 | 73 | else |
| 74 | 74 | { |
| 75 | code = | |
| 75 | code = space->r | |
| 76 | 76 | first = 0; |
| 77 | 77 | } |
| 78 | 78 | y = gal_cnt / 48 - 2; |
| r8806 | r8807 | |
| 85 | 85 | } |
| 86 | 86 | if ((x / 8 >= 11) && (x / 8 < 44)) |
| 87 | 87 | { |
| 88 | code = | |
| 88 | code = space->r | |
| 89 | 89 | } |
| 90 | 90 | else |
| 91 | 91 | { |
| r8806 | r8807 | |
|---|---|---|
| 133 | 133 | |
| 134 | 134 | }; |
| 135 | 135 | |
| 136 | void towns_update_video_banks( | |
| 136 | void towns_update_video_banks( | |
| 137 | 137 | |
| 138 | 138 | INTERRUPT_GEN( towns_vsync_irq ); |
| 139 | 139 | VIDEO_START( towns ); |
| r8806 | r8807 | |
|---|---|---|
| 66 | 66 | |
| 67 | 67 | /*----------- defined in machine/samcoupe.c -----------*/ |
| 68 | 68 | |
| 69 | void samcoupe_update_memory( | |
| 69 | void samcoupe_update_memory( | |
| 70 | 70 | UINT8 samcoupe_mouse_r(running_machine *machine); |
| 71 | 71 | |
| 72 | 72 | WRITE8_HANDLER( samcoupe_ext_mem_w ); |
| r8806 | r8807 | |
|---|---|---|
| 217 | 217 | static void microtan_snapshot_copy(running_machine *machine, UINT8 *snapshot_buff, int snapshot_size) |
| 218 | 218 | { |
| 219 | 219 | UINT8 *RAM = memory_region(machine, "maincpu"); |
| 220 | | |
| 220 | | |
| 221 | 221 | running_device *via_0 = machine->device("via6522_0"); |
| 222 | 222 | running_device *via_1 = machine->device("via6522_1"); |
| 223 | 223 | running_device *ay8910 = machine->device("ay8910.1"); |
| r8806 | r8807 | |
|---|---|---|
| 15 | 15 | UINT32 bytesread; |
| 16 | 16 | UINT16 address = 0; |
| 17 | 17 | int i; |
| 18 | | |
| 18 | | |
| 19 | 19 | |
| 20 | 20 | if (!file_type) |
| 21 | 21 | goto error; |
| r8806 | r8807 | |
| 64 | 64 | goto error; |
| 65 | 65 | |
| 66 | 66 | for (i = 0; i < snapshot_size; i++) |
| 67 | | |
| 67 | space-> | |
| 68 | 68 | |
| 69 | 69 | cbm_sethiaddress(image.device().machine, address + snapshot_size); |
| 70 | 70 | free(data); |
| r8806 | r8807 | |
| 78 | 78 | |
| 79 | 79 | static void cbm_quick_sethiaddress( running_machine *machine, UINT16 hiaddress ) |
| 80 | 80 | { |
| 81 | | |
| 81 | | |
| 82 | 82 | |
| 83 | memory_write_byte(space, 0x31, hiaddress & 0xff); | |
| 84 | memory_write_byte(space, 0x2f, hiaddress & 0xff); | |
| 85 | memory_write_byte(space, 0x2d, hiaddress & 0xff); | |
| 86 | memory_write_byte(space, 0x32, hiaddress >> 8); | |
| 87 | memory_write_byte(space, 0x30, hiaddress >> 8); | |
| 88 | memory_write_byte(space, 0x2e, hiaddress >> 8); | |
| 83 | space->write_byte(0x31, hiaddress & 0xff); | |
| 84 | space->write_byte(0x2f, hiaddress & 0xff); | |
| 85 | space->write_byte(0x2d, hiaddress & 0xff); | |
| 86 | space->write_byte(0x32, hiaddress >> 8); | |
| 87 | space->write_byte(0x30, hiaddress >> 8); | |
| 88 | space->write_byte(0x2e, hiaddress >> 8); | |
| 89 | 89 | } |
| 90 | 90 | |
| 91 | 91 | QUICKLOAD_LOAD( cbm_c16 ) |
| r8806 | r8807 | |
| 105 | 105 | |
| 106 | 106 | static void cbm_pet_quick_sethiaddress( running_machine *machine, UINT16 hiaddress ) |
| 107 | 107 | { |
| 108 | | |
| 108 | | |
| 109 | 109 | |
| 110 | memory_write_byte(space, 0x2e, hiaddress & 0xff); | |
| 111 | memory_write_byte(space, 0x2c, hiaddress & 0xff); | |
| 112 | memory_write_byte(space, 0x2a, hiaddress & 0xff); | |
| 113 | memory_write_byte(space, 0x2f, hiaddress >> 8); | |
| 114 | memory_write_byte(space, 0x2d, hiaddress >> 8); | |
| 115 | memory_write_byte(space, 0x2b, hiaddress >> 8); | |
| 110 | space->write_byte(0x2e, hiaddress & 0xff); | |
| 111 | space->write_byte(0x2c, hiaddress & 0xff); | |
| 112 | space->write_byte(0x2a, hiaddress & 0xff); | |
| 113 | space->write_byte(0x2f, hiaddress >> 8); | |
| 114 | space->write_byte(0x2d, hiaddress >> 8); | |
| 115 | space->write_byte(0x2b, hiaddress >> 8); | |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | 118 | QUICKLOAD_LOAD( cbm_pet ) |
| r8806 | r8807 | |
| 122 | 122 | |
| 123 | 123 | static void cbm_pet1_quick_sethiaddress(running_machine *machine, UINT16 hiaddress) |
| 124 | 124 | { |
| 125 | | |
| 125 | | |
| 126 | 126 | |
| 127 | memory_write_byte(space, 0x80, hiaddress & 0xff); | |
| 128 | memory_write_byte(space, 0x7e, hiaddress & 0xff); | |
| 129 | memory_write_byte(space, 0x7c, hiaddress & 0xff); | |
| 130 | memory_write_byte(space, 0x81, hiaddress >> 8); | |
| 131 | memory_write_byte(space, 0x7f, hiaddress >> 8); | |
| 132 | memory_write_byte(space, 0x7d, hiaddress >> 8); | |
| 127 | space->write_byte(0x80, hiaddress & 0xff); | |
| 128 | space->write_byte(0x7e, hiaddress & 0xff); | |
| 129 | space->write_byte(0x7c, hiaddress & 0xff); | |
| 130 | space->write_byte(0x81, hiaddress >> 8); | |
| 131 | space->write_byte(0x7f, hiaddress >> 8); | |
| 132 | space->write_byte(0x7d, hiaddress >> 8); | |
| 133 | 133 | } |
| 134 | 134 | |
| 135 | 135 | QUICKLOAD_LOAD( cbm_pet1 ) |
| r8806 | r8807 | |
| 139 | 139 | |
| 140 | 140 | static void cbmb_quick_sethiaddress(running_machine *machine, UINT16 hiaddress) |
| 141 | 141 | { |
| 142 | | |
| 142 | | |
| 143 | 143 | |
| 144 | memory_write_byte(space, 0xf0046, hiaddress & 0xff); | |
| 145 | memory_write_byte(space, 0xf0047, hiaddress >> 8); | |
| 144 | space->write_byte(0xf0046, hiaddress & 0xff); | |
| 145 | space->write_byte(0xf0047, hiaddress >> 8); | |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | 148 | QUICKLOAD_LOAD( cbmb ) |
| r8806 | r8807 | |
| 157 | 157 | |
| 158 | 158 | static void cbm_c65_quick_sethiaddress( running_machine *machine, UINT16 hiaddress ) |
| 159 | 159 | { |
| 160 | | |
| 160 | | |
| 161 | 161 | |
| 162 | memory_write_byte(space, 0x82, hiaddress & 0xff); | |
| 163 | memory_write_byte(space, 0x83, hiaddress >> 8); | |
| 162 | space->write_byte(0x82, hiaddress & 0xff); | |
| 163 | space->write_byte(0x83, hiaddress >> 8); | |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | 166 | QUICKLOAD_LOAD( cbm_c65 ) |
| r8806 | r8807 | |
|---|---|---|
| 278 | 278 | UINT16 start, size, data, status; |
| 279 | 279 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 280 | 280 | running_device *cpu = machine->device("maincpu"); |
| 281 | | |
| 281 | | |
| 282 | 282 | |
| 283 | 283 | if (snapsize == SP_NEW_SIZE_16K || snapsize == SP_NEW_SIZE_48K) |
| 284 | 284 | { |
| r8806 | r8807 | |
| 373 | 373 | /* Memory dump */ |
| 374 | 374 | logerror("Loading %04X bytes of RAM at %04X\n", size, start); |
| 375 | 375 | for (i = 0; i < size; i++) |
| 376 | | |
| 376 | space-> | |
| 377 | 377 | |
| 378 | 378 | /* Set border color */ |
| 379 | 379 | data = snapdata[SP_OFFSET + 34] & 0x07; |
| r8806 | r8807 | |
| 480 | 480 | UINT16 data, addr; |
| 481 | 481 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 482 | 482 | running_device *cpu = machine->device("maincpu"); |
| 483 | | |
| 483 | | |
| 484 | 484 | |
| 485 | 485 | if ((snapsize != SNA48_SIZE) && (state->port_7ffd_data == -1)) |
| 486 | 486 | { |
| r8806 | r8807 | |
| 566 | 566 | /* Memory dump */ |
| 567 | 567 | logerror("Loading %04X bytes of RAM at %04X\n", 3*SPECTRUM_BANK, BASE_RAM); |
| 568 | 568 | for (i = 0; i < 3*SPECTRUM_BANK; i++) |
| 569 | | |
| 569 | space-> | |
| 570 | 570 | |
| 571 | 571 | /* Get PC from stack */ |
| 572 | 572 | addr = cpu_get_reg(cpu, Z80_SP); |
| r8806 | r8807 | |
| 576 | 576 | else |
| 577 | 577 | logerror("Fetching PC from the stack at SP:%04X\n", addr); |
| 578 | 578 | |
| 579 | data = ( | |
| 579 | data = (space->r | |
| 580 | 580 | LOAD_REG(cpu, Z80_PC, data); |
| 581 | 581 | |
| 582 | 582 | #if 0 |
| 583 | memory_write_byte(space, addr + 0, 0); // It's been reported that zeroing these locations fixes the loading | |
| 584 | memory_write_byte(space, addr + 1, 0); // of a few images that were snapshot at a "wrong" instant | |
| 583 | space->write_byte(addr + 0, 0); // It's been reported that zeroing these locations fixes the loading | |
| 584 | space->write_byte(addr + 1, 0); // of a few images that were snapshot at a "wrong" instant | |
| 585 | 585 | #endif |
| 586 | 586 | |
| 587 | 587 | addr += 2; |
| r8806 | r8807 | |
| 613 | 613 | logerror("Loading bank 2 from offset:0401B\n"); |
| 614 | 614 | logerror("Loading bank %d from offset:0801B\n", snapdata[SNA128_OFFSET + 2] & 0x07); |
| 615 | 615 | for (i = 0; i < 3*SPECTRUM_BANK; i++) |
| 616 | | |
| 616 | space-> | |
| 617 | 617 | |
| 618 | 618 | bank_offset = SNA48_SIZE + SNA128_HDR; |
| 619 | 619 | for (i = 0; i < 8; i++) |
| r8806 | r8807 | |
| 625 | 625 | state->port_7ffd_data += i; |
| 626 | 626 | spectrum_update_paging(machine); |
| 627 | 627 | for (j = 0; j < SPECTRUM_BANK; j++) |
| 628 | | |
| 628 | space-> | |
| 629 | 629 | bank_offset += SPECTRUM_BANK; |
| 630 | 630 | } |
| 631 | 631 | } |
| r8806 | r8807 | |
| 703 | 703 | UINT16 data; |
| 704 | 704 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 705 | 705 | running_device *cpu = machine->device("maincpu"); |
| 706 | | |
| 706 | | |
| 707 | 707 | |
| 708 | 708 | data = (snapdata[ACH_OFFSET + 0] << 8) | snapdata[ACH_OFFSET + 4]; |
| 709 | 709 | LOAD_REG(cpu, Z80_AF, data); |
| r8806 | r8807 | |
| 768 | 768 | /* Memory dump */ |
| 769 | 769 | logerror("Loading %04X bytes of RAM at %04X\n", 3*SPECTRUM_BANK, BASE_RAM); |
| 770 | 770 | for (i = 0; i < 3*SPECTRUM_BANK; i++) |
| 771 | | |
| 771 | space-> | |
| 772 | 772 | |
| 773 | 773 | /* Set border color */ |
| 774 | 774 | data = snapdata[ACH_OFFSET + 156] & 0x07; |
| r8806 | r8807 | |
| 838 | 838 | UINT16 addr, data; |
| 839 | 839 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 840 | 840 | running_device *cpu = machine->device("maincpu"); |
| 841 | | |
| 841 | | |
| 842 | 842 | |
| 843 | 843 | data = snapdata[PRG_OFFSET + 0]; |
| 844 | 844 | if (data != 0x05) |
| r8806 | r8807 | |
| 881 | 881 | /* Memory dump */ |
| 882 | 882 | logerror("Loading %04X bytes of RAM at %04X\n", 3*SPECTRUM_BANK, BASE_RAM); |
| 883 | 883 | for (i = 0; i < 3*SPECTRUM_BANK; i++) |
| 884 | | |
| 884 | space-> | |
| 885 | 885 | |
| 886 | 886 | addr = (snapdata[PRG_OFFSET + 241] << 8) | snapdata[PRG_OFFSET + 240]; |
| 887 | 887 | if (addr < BASE_RAM || addr > 4*SPECTRUM_BANK - 6) |
| r8806 | r8807 | |
| 889 | 889 | else |
| 890 | 890 | logerror("Fetching registers IFF1/2, R, AF and PC from the stack at SP:%04X\n", addr); |
| 891 | 891 | |
| 892 | data = | |
| 892 | data = space->r | |
| 893 | 893 | LOAD_REG(cpu, Z80_IFF1, BIT(data, 2)); |
| 894 | 894 | LOAD_REG(cpu, Z80_IFF2, BIT(data, 2)); |
| 895 | 895 | |
| r8806 | r8807 | |
| 897 | 897 | cputag_set_input_line(machine, "maincpu", INPUT_LINE_IRQ0, intr); |
| 898 | 898 | cputag_set_input_line(machine, "maincpu", INPUT_LINE_HALT, CLEAR_LINE); |
| 899 | 899 | |
| 900 | data = | |
| 900 | data = space->r | |
| 901 | 901 | LOAD_REG(cpu, Z80_R, data); |
| 902 | 902 | |
| 903 | data = ( | |
| 903 | data = (space->r | |
| 904 | 904 | LOAD_REG(cpu, Z80_AF, data); |
| 905 | 905 | |
| 906 | data = ( | |
| 906 | data = (space->r | |
| 907 | 907 | LOAD_REG(cpu, Z80_PC, data); |
| 908 | 908 | |
| 909 | 909 | #if 0 |
| 910 | memory_write_byte(space, addr + 0, 0); // It's been reported that zeroing these locations fixes the loading | |
| 911 | memory_write_byte(space, addr + 1, 0); // of a few images that were snapshot at a "wrong" instant | |
| 912 | memory_write_byte(space, addr + 2, 0); | |
| 913 | memory_write_byte(space, addr + 3, 0); | |
| 914 | memory_write_byte(space, addr + 4, 0); | |
| 915 | memory_write_byte(space, addr + 5, 0); | |
| 910 | space->write_byte(addr + 0, 0); // It's been reported that zeroing these locations fixes the loading | |
| 911 | space->write_byte(addr + 1, 0); // of a few images that were snapshot at a "wrong" instant | |
| 912 | space->write_byte(addr + 2, 0); | |
| 913 | space->write_byte(addr + 3, 0); | |
| 914 | space->write_byte(addr + 4, 0); | |
| 915 | space->write_byte(addr + 5, 0); | |
| 916 | 916 | #endif |
| 917 | 917 | |
| 918 | 918 | addr += 6; |
| r8806 | r8807 | |
| 920 | 920 | cpu_set_reg(cpu, Z80_SP, addr); |
| 921 | 921 | |
| 922 | 922 | /* Set border color */ |
| 923 | data = ( | |
| 923 | data = (space->r | |
| 924 | 924 | state->port_fe_data = (state->port_fe_data & 0xf8) | data; |
| 925 | 925 | EventList_Reset(); |
| 926 | 926 | border_set_last_color(data); |
| r8806 | r8807 | |
| 1010 | 1010 | UINT16 addr = 0, data; |
| 1011 | 1011 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 1012 | 1012 | running_device *cpu = machine->device("maincpu"); |
| 1013 | | |
| 1013 | | |
| 1014 | 1014 | |
| 1015 | 1015 | data = (snapdata[PLUSD_OFFSET + 15] << 8) | snapdata[PLUSD_OFFSET + 14]; |
| 1016 | 1016 | LOAD_REG(cpu, Z80_BC, data); |
| r8806 | r8807 | |
| 1053 | 1053 | /* Memory dump */ |
| 1054 | 1054 | logerror("Loading %04X bytes of RAM at %04X\n", 3*SPECTRUM_BANK, BASE_RAM); |
| 1055 | 1055 | for (i = 0; i < 3*SPECTRUM_BANK; i++) |
| 1056 | | |
| 1056 | space-> | |
| 1057 | 1057 | } |
| 1058 | 1058 | else |
| 1059 | 1059 | { |
| r8806 | r8807 | |
| 1079 | 1079 | }; |
| 1080 | 1080 | logerror("Loading bank %d from offset:%05X\n", i, PLUSD128_HDR + i*SPECTRUM_BANK); |
| 1081 | 1081 | for (j = 0; j < SPECTRUM_BANK; j++) |
| 1082 | | |
| 1082 | space-> | |
| 1083 | 1083 | } |
| 1084 | 1084 | state->port_7ffd_data = snapdata[PLUSD_OFFSET + 22]; |
| 1085 | 1085 | logerror ("Port 7FFD:%02X\n", state->port_7ffd_data); |
| r8806 | r8807 | |
| 1093 | 1093 | else |
| 1094 | 1094 | logerror("Fetching registers IFF1/2, R, AF and PC from the stack at SP:%04X\n", addr); |
| 1095 | 1095 | |
| 1096 | data = | |
| 1096 | data = space->r | |
| 1097 | 1097 | LOAD_REG(cpu, Z80_IFF1, BIT(data, 2)); |
| 1098 | 1098 | LOAD_REG(cpu, Z80_IFF2, BIT(data, 2)); |
| 1099 | 1099 | |
| r8806 | r8807 | |
| 1101 | 1101 | cputag_set_input_line(machine, "maincpu", INPUT_LINE_IRQ0, intr); |
| 1102 | 1102 | cputag_set_input_line(machine, "maincpu", INPUT_LINE_HALT, CLEAR_LINE); |
| 1103 | 1103 | |
| 1104 | data = | |
| 1104 | data = space->r | |
| 1105 | 1105 | LOAD_REG(cpu, Z80_R, data); |
| 1106 | 1106 | |
| 1107 | data = ( | |
| 1107 | data = (space->r | |
| 1108 | 1108 | LOAD_REG(cpu, Z80_AF, data); |
| 1109 | 1109 | |
| 1110 | data = ( | |
| 1110 | data = (space->r | |
| 1111 | 1111 | LOAD_REG(cpu, Z80_PC, data); |
| 1112 | 1112 | |
| 1113 | 1113 | #if 0 |
| 1114 | memory_write_byte(space, addr + 0, 0); // It's been reported that zeroing these locations fixes the loading | |
| 1115 | memory_write_byte(space, addr + 1, 0); // of a few images that were snapshot at a "wrong" instant | |
| 1116 | memory_write_byte(space, addr + 2, 0); | |
| 1117 | memory_write_byte(space, addr + 3, 0); | |
| 1118 | memory_write_byte(space, addr + 4, 0); | |
| 1119 | memory_write_byte(space, addr + 5, 0); | |
| 1114 | space->write_byte(addr + 0, 0); // It's been reported that zeroing these locations fixes the loading | |
| 1115 | space->write_byte(addr + 1, 0); // of a few images that were snapshot at a "wrong" instant | |
| 1116 | space->write_byte(addr + 2, 0); | |
| 1117 | space->write_byte(addr + 3, 0); | |
| 1118 | space->write_byte(addr + 4, 0); | |
| 1119 | space->write_byte(addr + 5, 0); | |
| 1120 | 1120 | #endif |
| 1121 | 1121 | |
| 1122 | 1122 | addr += 6; |
| r8806 | r8807 | |
| 1124 | 1124 | cpu_set_reg(cpu, Z80_SP, addr); |
| 1125 | 1125 | |
| 1126 | 1126 | /* Set border color */ |
| 1127 | data = ( | |
| 1127 | data = (space->r | |
| 1128 | 1128 | state->port_fe_data = (state->port_fe_data & 0xf8) | data; |
| 1129 | 1129 | EventList_Reset(); |
| 1130 | 1130 | border_set_last_color(data); |
| r8806 | r8807 | |
| 1180 | 1180 | UINT16 data; |
| 1181 | 1181 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 1182 | 1182 | running_device *cpu = machine->device("maincpu"); |
| 1183 | | |
| 1183 | | |
| 1184 | 1184 | |
| 1185 | 1185 | data = (snapdata[SEM_OFFSET + 1] << 8) | snapdata[SEM_OFFSET + 0]; |
| 1186 | 1186 | LOAD_REG(cpu, Z80_AF, data); |
| r8806 | r8807 | |
| 1243 | 1243 | /* Memory dump */ |
| 1244 | 1244 | logerror("Loading %04X bytes of RAM at %04X\n", 3*SPECTRUM_BANK, BASE_RAM); |
| 1245 | 1245 | for (i = 0; i < 3*SPECTRUM_BANK; i++) |
| 1246 | | |
| 1246 | space-> | |
| 1247 | 1247 | |
| 1248 | 1248 | /* Set border color */ |
| 1249 | data = ( | |
| 1249 | data = (space->r | |
| 1250 | 1250 | state->port_fe_data = (state->port_fe_data & 0xf8) | data; |
| 1251 | 1251 | EventList_Reset(); |
| 1252 | 1252 | border_set_last_color(data); |
| r8806 | r8807 | |
| 1301 | 1301 | UINT16 data; |
| 1302 | 1302 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 1303 | 1303 | running_device *cpu = machine->device("maincpu"); |
| 1304 | | |
| 1304 | | |
| 1305 | 1305 | |
| 1306 | 1306 | data = (snapdata[SIT_OFFSET + 7] << 8) | snapdata[SIT_OFFSET + 6]; |
| 1307 | 1307 | LOAD_REG(cpu, Z80_AF, data); |
| r8806 | r8807 | |
| 1364 | 1364 | logerror("Skipping the 16K ROM dump at offset:%04X\n", SIT_OFFSET + 28); |
| 1365 | 1365 | logerror("Loading %04X bytes of RAM at %04X\n", 3*SPECTRUM_BANK, BASE_RAM); |
| 1366 | 1366 | for (i = 0; i < 3*SPECTRUM_BANK; i++) |
| 1367 | | |
| 1367 | space-> | |
| 1368 | 1368 | |
| 1369 | 1369 | /* Set border color */ |
| 1370 | 1370 | data = snapdata[SIT_OFFSET + 27] & 0x07; |
| r8806 | r8807 | |
| 1433 | 1433 | UINT16 data, mode; |
| 1434 | 1434 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 1435 | 1435 | running_device *cpu = machine->device("maincpu"); |
| 1436 | | |
| 1436 | | |
| 1437 | 1437 | |
| 1438 | 1438 | logerror("Skipping last 132 bytes of the 16K ROM dump at offset:0000\n"); |
| 1439 | 1439 | |
| r8806 | r8807 | |
| 1510 | 1510 | /* Memory dump */ |
| 1511 | 1511 | logerror("Loading %04X bytes of RAM at %04X\n", 3*SPECTRUM_BANK, BASE_RAM); |
| 1512 | 1512 | for (i = 0; i < 3*SPECTRUM_BANK; i++) |
| 1513 | | |
| 1513 | space-> | |
| 1514 | 1514 | |
| 1515 | 1515 | /* Set border color */ |
| 1516 | data = ( | |
| 1516 | data = (space->r | |
| 1517 | 1517 | state->port_fe_data = (state->port_fe_data & 0xf8) | data; |
| 1518 | 1518 | EventList_Reset(); |
| 1519 | 1519 | border_set_last_color(data); |
| r8806 | r8807 | |
| 1567 | 1567 | UINT16 data; |
| 1568 | 1568 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 1569 | 1569 | running_device *cpu = machine->device("maincpu"); |
| 1570 | | |
| 1570 | | |
| 1571 | 1571 | |
| 1572 | 1572 | data = (snapdata[SNP_OFFSET + 1] << 8) | snapdata[SNP_OFFSET + 0]; |
| 1573 | 1573 | LOAD_REG(cpu, Z80_AF, data); |
| r8806 | r8807 | |
| 1630 | 1630 | /* Memory dump */ |
| 1631 | 1631 | logerror("Loading %04X bytes of RAM at %04X\n", 3*SPECTRUM_BANK, BASE_RAM); |
| 1632 | 1632 | for (i = 0; i < 3*SPECTRUM_BANK; i++) |
| 1633 | | |
| 1633 | space-> | |
| 1634 | 1634 | |
| 1635 | 1635 | /* Set border color */ |
| 1636 | 1636 | data = snapdata[SNP_OFFSET + 2] & 0x07; |
| r8806 | r8807 | |
| 1746 | 1746 | { |
| 1747 | 1747 | UINT8 counthi, countlo, compress, fill; |
| 1748 | 1748 | UINT16 block = 0, count, i, j, numbytes; |
| 1749 | | |
| 1749 | | |
| 1750 | 1750 | |
| 1751 | 1751 | i = SNX_HDR - 1; |
| 1752 | 1752 | numbytes = 0; |
| r8806 | r8807 | |
| 1776 | 1776 | fill = source[++i]; |
| 1777 | 1777 | logerror("Dest:%04X Filler:%02X\n", BASE_RAM + numbytes, fill); |
| 1778 | 1778 | for(j = 0; j < count; j++) |
| 1779 | | |
| 1779 | space-> | |
| 1780 | 1780 | numbytes += count; |
| 1781 | 1781 | } |
| 1782 | 1782 | else |
| r8806 | r8807 | |
| 1784 | 1784 | logerror("Dest:%04X\n", BASE_RAM + numbytes); |
| 1785 | 1785 | j = 0; |
| 1786 | 1786 | while (j < count) |
| 1787 | | |
| 1787 | space-> | |
| 1788 | 1788 | numbytes += count; |
| 1789 | 1789 | } |
| 1790 | 1790 | } |
| r8806 | r8807 | |
| 1796 | 1796 | UINT16 data, addr; |
| 1797 | 1797 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 1798 | 1798 | running_device *cpu = machine->device("maincpu"); |
| 1799 | | |
| 1799 | | |
| 1800 | 1800 | |
| 1801 | 1801 | data = (snapdata[SNX_OFFSET + 4] << 8) | snapdata[SNX_OFFSET + 5]; |
| 1802 | 1802 | if (data != 0x25) |
| r8806 | r8807 | |
| 1871 | 1871 | else |
| 1872 | 1872 | logerror("Fetching PC from the stack at SP:%04X\n", addr); |
| 1873 | 1873 | |
| 1874 | LOAD_REG(cpu, Z80_PC, ( | |
| 1874 | LOAD_REG(cpu, Z80_PC, (space->r | |
| 1875 | 1875 | |
| 1876 | 1876 | #if 0 |
| 1877 | memory_write_byte(space, addr + 0, 0); // It's been reported that zeroing these locations fixes the loading | |
| 1878 | memory_write_byte(space, addr + 1, 0); // of a few images that were snapshot at a "wrong" instant | |
| 1877 | space->write_byte(addr + 0, 0); // It's been reported that zeroing these locations fixes the loading | |
| 1878 | space->write_byte(addr + 1, 0); // of a few images that were snapshot at a "wrong" instant | |
| 1879 | 1879 | #endif |
| 1880 | 1880 | |
| 1881 | 1881 | addr += 2; |
| r8806 | r8807 | |
| 1952 | 1952 | UINT16 addr, data; |
| 1953 | 1953 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 1954 | 1954 | running_device *cpu = machine->device("maincpu"); |
| 1955 | | |
| 1955 | | |
| 1956 | 1956 | |
| 1957 | 1957 | if (state->port_7ffd_data == -1) |
| 1958 | 1958 | { |
| r8806 | r8807 | |
| 2043 | 2043 | }; |
| 2044 | 2044 | logerror("Loading bank %d from offset:%05X\n", banks[i], FRZ_HDR + i*SPECTRUM_BANK); |
| 2045 | 2045 | for (j = 0; j < SPECTRUM_BANK; j++) |
| 2046 | | |
| 2046 | space-> | |
| 2047 | 2047 | } |
| 2048 | 2048 | state->port_7ffd_data = snapdata[FRZ_OFFSET + 1]; |
| 2049 | 2049 | logerror ("Port 7FFD:%02X\n", state->port_7ffd_data); |
| r8806 | r8807 | |
| 2051 | 2051 | spectrum_update_paging(machine); |
| 2052 | 2052 | |
| 2053 | 2053 | /* Set border color */ |
| 2054 | data = ( | |
| 2054 | data = (space->r | |
| 2055 | 2055 | state->port_fe_data = (state->port_fe_data & 0xf8) | data; |
| 2056 | 2056 | EventList_Reset(); |
| 2057 | 2057 | border_set_last_color(data); |
| r8806 | r8807 | |
| 2065 | 2065 | { |
| 2066 | 2066 | UINT8 ch; |
| 2067 | 2067 | int i; |
| 2068 | | |
| 2068 | | |
| 2069 | 2069 | |
| 2070 | 2070 | do |
| 2071 | 2071 | { |
| r8806 | r8807 | |
| 2097 | 2097 | |
| 2098 | 2098 | for (i = 0; i < count; i++) |
| 2099 | 2099 | { |
| 2100 | | |
| 2100 | space-> | |
| 2101 | 2101 | dest++; |
| 2102 | 2102 | } |
| 2103 | 2103 | } |
| 2104 | 2104 | else |
| 2105 | 2105 | { |
| 2106 | 2106 | /* single 0x0ed */ |
| 2107 | | |
| 2107 | space-> | |
| 2108 | 2108 | dest++; |
| 2109 | 2109 | source++; |
| 2110 | 2110 | size--; |
| r8806 | r8807 | |
| 2113 | 2113 | else |
| 2114 | 2114 | { |
| 2115 | 2115 | /* not 0x0ed */ |
| 2116 | | |
| 2116 | space-> | |
| 2117 | 2117 | dest++; |
| 2118 | 2118 | source++; |
| 2119 | 2119 | size--; |
| r8806 | r8807 | |
| 2176 | 2176 | int i; |
| 2177 | 2177 | UINT8 lo, hi, data; |
| 2178 | 2178 | SPECTRUM_Z80_SNAPSHOT_TYPE z80_type; |
| 2179 | | |
| 2179 | | |
| 2180 | 2180 | |
| 2181 | 2181 | z80_type = spectrum_identify_z80(snapdata, snapsize); |
| 2182 | 2182 | |
| r8806 | r8807 | |
| 2315 | 2315 | { |
| 2316 | 2316 | logerror("Not compressed\n"); /* not compressed */ |
| 2317 | 2317 | for (i = 0; i < 49152; i++) |
| 2318 | | |
| 2318 | space-> | |
| 2319 | 2319 | } |
| 2320 | 2320 | else |
| 2321 | 2321 | { |
| r8806 | r8807 | |
| 2396 | 2396 | |
| 2397 | 2397 | /* not compressed */ |
| 2398 | 2398 | for (i = 0; i < 16384; i++) |
| 2399 | | |
| 2399 | space-> | |
| 2400 | 2400 | } |
| 2401 | 2401 | else |
| 2402 | 2402 | { |
| r8806 | r8807 | |
| 2504 | 2504 | void spectrum_setup_scr(running_machine *machine, UINT8 *quickdata, UINT32 quicksize) |
| 2505 | 2505 | { |
| 2506 | 2506 | int i; |
| 2507 | | |
| 2507 | | |
| 2508 | 2508 | |
| 2509 | 2509 | for (i = 0; i < quicksize; i++) |
| 2510 | | |
| 2510 | space-> | |
| 2511 | 2511 | |
| 2512 | 2512 | log_quickload(quicksize == SCR_SIZE ? "SCREEN$" : "SCREEN$ (Mono)", BASE_RAM, quicksize, 0, EXEC_NA); |
| 2513 | 2513 | } |
| r8806 | r8807 | |
| 2544 | 2544 | UINT8 data; |
| 2545 | 2545 | UINT16 start, len; |
| 2546 | 2546 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 2547 | | |
| 2547 | | |
| 2548 | 2548 | |
| 2549 | 2549 | start = (quickdata[RAW_OFFSET + 4] << 8) | quickdata[RAW_OFFSET + 3]; |
| 2550 | 2550 | len = (quickdata[RAW_OFFSET + 2] << 8) | quickdata[RAW_OFFSET + 1]; |
| 2551 | 2551 | |
| 2552 | 2552 | for (i = 0; i < len; i++) |
| 2553 | | |
| 2553 | space-> | |
| 2554 | 2554 | |
| 2555 | 2555 | /* Set border color */ |
| 2556 | data = ( | |
| 2556 | data = (space->r | |
| 2557 | 2557 | state->port_fe_data = (state->port_fe_data & 0xf8) | data; |
| 2558 | 2558 | EventList_Reset(); |
| 2559 | 2559 | border_set_last_color(data); |
| r8806 | r8807 | |
|---|---|---|
| 48 | 48 | |
| 49 | 49 | QUICKLOAD_LOAD( comx35_comx ) |
| 50 | 50 | { |
| 51 | | |
| 51 | | |
| 52 | 52 | |
| 53 | 53 | UINT8 header[16] = {0}; |
| 54 | 54 | int size = image.length(); |
| r8806 | r8807 | |
| 173 | 173 | image.fread( header, 2); |
| 174 | 174 | |
| 175 | 175 | array_length = pick_integer_be(header, 0, 2); |
| 176 | start_array = ( | |
| 176 | start_array = (pr | |
| 177 | 177 | end_array = start_array + (size - 7); |
| 178 | 178 | |
| 179 | memory_write_byte(program, 0x4299, end_array >> 8); | |
| 180 | memory_write_byte(program, 0x429a, end_array & 0xff); | |
| 179 | program->write_byte(0x4299, end_array >> 8); | |
| 180 | program->write_byte(0x429a, end_array & 0xff); | |
| 181 | 181 | |
| 182 | 182 | start_string = start_array + array_length; |
| 183 | 183 | |
| 184 | memory_write_byte(program, 0x4292, start_string >> 8); | |
| 185 | memory_write_byte(program, 0x4293, start_string & 0xff); | |
| 184 | program->write_byte(0x4292, start_string >> 8); | |
| 185 | program->write_byte(0x4293, start_string & 0xff); | |
| 186 | 186 | |
| 187 | 187 | image_fread_memory(image, start_array, size); |
| 188 | 188 | } |
| r8806 | r8807 | |
|---|---|---|
| 35 | 35 | |
| 36 | 36 | QUICKLOAD_LOAD( trs80_cmd ) |
| 37 | 37 | { |
| 38 | | |
| 38 | | |
| 39 | 39 | |
| 40 | 40 | UINT8 type, length; |
| 41 | 41 | UINT8 data[0x100]; |
| r8806 | r8807 | |
|---|---|---|
| 262 | 262 | { |
| 263 | 263 | /* enable RAM */ |
| 264 | 264 | |
| 265 | | |
| 265 | | |
| 266 | 266 | |
| 267 | 267 | memory_set_bank(space->machine, "bank1", VIP_BANK_RAM); |
| 268 | 268 | |
| r8806 | r8807 | |
| 677 | 677 | { |
| 678 | 678 | vip_state *state = machine->driver_data<vip_state>(); |
| 679 | 679 | |
| 680 | const address_space *program = cputag_get_address_space(machine, CDP1802_TAG, ADDRESS_SPACE_PROGRAM); | |
| 681 | const address_space *io = cputag_get_address_space(machine, CDP1802_TAG, ADDRESS_SPACE_IO); | |
| 680 | address_space *program = cputag_get_address_space(machine, CDP1802_TAG, ADDRESS_SPACE_PROGRAM); | |
| 681 | address_space *io = cputag_get_address_space(machine, CDP1802_TAG, ADDRESS_SPACE_IO); | |
| 682 | 682 | |
| 683 | 683 | /* reset auxiliary chips */ |
| 684 | 684 | state->cdp1861->reset(); |
| r8806 | r8807 | |
|---|---|---|
| 275 | 275 | static MACHINE_START( elf2 ) |
| 276 | 276 | { |
| 277 | 277 | elf2_state *state = machine->driver_data<elf2_state>(); |
| 278 | | |
| 278 | | |
| 279 | 279 | |
| 280 | 280 | /* find devices */ |
| 281 | 281 | state->cdp1861 = machine->device(CDP1861_TAG); |
| r8806 | r8807 | |
|---|---|---|
| 39 | 39 | |
| 40 | 40 | static MACHINE_RESET(vt520) |
| 41 | 41 | { |
| 42 | | |
| 42 | | |
| 43 | 43 | UINT8 *rom = memory_region(machine, "maincpu"); |
| 44 | 44 | memory_unmap_write(space, 0x0000, 0xffff, 0, 0); |
| 45 | 45 | memory_set_bankptr(machine, "bank1", rom + 0x70000); |
| r8806 | r8807 | |
|---|---|---|
| 81 | 81 | |
| 82 | 82 | static void pc8401a_bankswitch(running_machine *machine, UINT8 data) |
| 83 | 83 | { |
| 84 | | |
| 84 | | |
| 85 | 85 | |
| 86 | 86 | int rombank = data & 0x03; |
| 87 | 87 | int ram0000 = (data >> 2) & 0x03; |
| r8806 | r8807 | |
|---|---|---|
| 35 | 35 | static void mc1000_bankswitch(running_machine *machine) |
| 36 | 36 | { |
| 37 | 37 | mc1000_state *state = machine->driver_data<mc1000_state>(); |
| 38 | | |
| 38 | | |
| 39 | 39 | |
| 40 | 40 | /* MC6845 video RAM */ |
| 41 | 41 | memory_set_bank(machine, "bank2", state->mc6845_bank); |
| r8806 | r8807 | |
| 320 | 320 | static MACHINE_START( mc1000 ) |
| 321 | 321 | { |
| 322 | 322 | mc1000_state *state = machine->driver_data<mc1000_state>(); |
| 323 | | |
| 323 | | |
| 324 | 324 | |
| 325 | 325 | /* find devices */ |
| 326 | 326 | state->mc6845 = machine->device(MC6845_TAG); |
| r8806 | r8807 | |
| 467 | 467 | |
| 468 | 468 | /* Driver Initialization */ |
| 469 | 469 | |
| 470 | ||
| 470 | ||
| 471 | 471 | { |
| 472 | mc1000_state *state = | |
| 472 | mc1000_state *state = | |
| 473 | 473 | |
| 474 | 474 | if (state->rom0000) |
| 475 | 475 | { |
| 476 | 476 | if (address >= 0xc000) |
| 477 | 477 | { |
| 478 | memory_set_bank( | |
| 478 | memory_set_bank( | |
| 479 | 479 | state->rom0000 = 0; |
| 480 | 480 | } |
| 481 | 481 | } |
| r8806 | r8807 | |
| 485 | 485 | |
| 486 | 486 | static DRIVER_INIT( mc1000 ) |
| 487 | 487 | { |
| 488 | | |
| 488 | | |
| 489 | 489 | } |
| 490 | 490 | |
| 491 | 491 | /* System Drivers */ |
| r8806 | r8807 | |
|---|---|---|
| 1897 | 1897 | |
| 1898 | 1898 | static TIMER_CALLBACK(keyboard_callback) |
| 1899 | 1899 | { |
| 1900 | | |
| 1900 | | |
| 1901 | 1901 | UINT32 key1 = input_port_read(machine,"key1"); |
| 1902 | 1902 | UINT32 key2 = input_port_read(machine,"key2"); |
| 1903 | 1903 | UINT32 key3 = input_port_read(machine,"key3"); |
| r8806 | r8807 | |
|---|---|---|
| 194 | 194 | |
| 195 | 195 | static MACHINE_RESET(spc1000) |
| 196 | 196 | { |
| 197 | | |
| 197 | | |
| 198 | 198 | |
| 199 | 199 | memory_install_read_bank(space, 0x0000, 0x7fff, 0, 0, "bank1"); |
| 200 | 200 | memory_install_read_bank(space, 0x8000, 0xffff, 0, 0, "bank3"); |
| r8806 | r8807 | |
|---|---|---|
| 159 | 159 | static void vii_blit(running_machine *machine, bitmap_t *bitmap, const rectangle *cliprect, UINT32 xoff, UINT32 yoff, UINT32 attr, UINT32 ctrl, UINT32 bitmap_addr, UINT16 tile) |
| 160 | 160 | { |
| 161 | 161 | vii_state *state = machine->driver_data<vii_state>(); |
| 162 | | |
| 162 | | |
| 163 | 163 | |
| 164 | 164 | UINT32 h = 8 << ((attr & PAGE_TILE_HEIGHT_MASK) >> PAGE_TILE_HEIGHT_SHIFT); |
| 165 | 165 | UINT32 w = 8 << ((attr & PAGE_TILE_WIDTH_MASK) >> PAGE_TILE_WIDTH_SHIFT); |
| r8806 | r8807 | |
| 191 | 191 | bits <<= nc; |
| 192 | 192 | if(nbits < nc) |
| 193 | 193 | { |
| 194 | UINT16 b = | |
| 194 | UINT16 b = space->r | |
| 195 | 195 | b = (b << 8) | (b >> 8); |
| 196 | 196 | bits |= b << (nc - nbits); |
| 197 | 197 | nbits += 16; |
| r8806 | r8807 | |
| 235 | 235 | UINT32 tilemap = regs[4]; |
| 236 | 236 | UINT32 palette_map = regs[5]; |
| 237 | 237 | UINT32 h, w, hn, wn; |
| 238 | | |
| 238 | | |
| 239 | 239 | |
| 240 | 240 | if(!(ctrl & PAGE_ENABLE_MASK)) |
| 241 | 241 | { |
| r8806 | r8807 | |
| 257 | 257 | { |
| 258 | 258 | for(x0 = 0; x0 < wn; x0++) |
| 259 | 259 | { |
| 260 | UINT16 tile = | |
| 260 | UINT16 tile = space->r | |
| 261 | 261 | UINT16 palette = 0; |
| 262 | 262 | UINT32 xx, yy; |
| 263 | 263 | |
| r8806 | r8807 | |
| 266 | 266 | continue; |
| 267 | 267 | } |
| 268 | 268 | |
| 269 | palette = | |
| 269 | palette = space->r | |
| 270 | 270 | if(x0 & 1) |
| 271 | 271 | { |
| 272 | 272 | palette >>= 8; |
| r8806 | r8807 | |
| 297 | 297 | static void vii_blit_sprite(running_machine *machine, bitmap_t *bitmap, const rectangle *cliprect, int depth, UINT32 base_addr) |
| 298 | 298 | { |
| 299 | 299 | vii_state *state = machine->driver_data<vii_state>(); |
| 300 | | |
| 300 | | |
| 301 | 301 | UINT16 tile, attr; |
| 302 | 302 | INT16 x, y; |
| 303 | 303 | UINT32 h, w; |
| 304 | 304 | UINT32 bitmap_addr = 0x40 * state->video_regs[0x22]; |
| 305 | 305 | |
| 306 | tile = memory_read_word_16le(space, (base_addr + 0) << 1); | |
| 307 | x = memory_read_word_16le(space, (base_addr + 1) << 1); | |
| 308 | y = memory_read_word_16le(space, (base_addr + 2) << 1); | |
| 309 | attr = memory_read_word_16le(space, (base_addr + 3) << 1); | |
| 306 | tile = space->read_word((base_addr + 0) << 1); | |
| 307 | x = space->read_word((base_addr + 1) << 1); | |
| 308 | y = space->read_word((base_addr + 2) << 1); | |
| 309 | attr = space->read_word((base_addr + 3) << 1); | |
| 310 | 310 | |
| 311 | 311 | if(!tile) |
| 312 | 312 | { |
| r8806 | r8807 | |
| 348 | 348 | |
| 349 | 349 | for(n = 0; n < 256; n++) |
| 350 | 350 | { |
| 351 | //if( | |
| 351 | //if(space->r | |
| 352 | 352 | { |
| 353 | 353 | vii_blit_sprite(machine, bitmap, cliprect, depth, 0x2c00 + 4*n); |
| 354 | 354 | } |
| r8806 | r8807 | |
| 389 | 389 | static void vii_do_dma(running_machine *machine, UINT32 len) |
| 390 | 390 | { |
| 391 | 391 | vii_state *state = machine->driver_data<vii_state>(); |
| 392 | | |
| 392 | | |
| 393 | 393 | UINT32 src = state->video_regs[0x70]; |
| 394 | 394 | UINT32 dst = state->video_regs[0x71] + 0x2c00; |
| 395 | 395 | UINT32 j; |
| 396 | 396 | |
| 397 | 397 | for(j = 0; j < len; j++) |
| 398 | 398 | { |
| 399 | | |
| 399 | space-> | |
| 400 | 400 | } |
| 401 | 401 | |
| 402 | 402 | state->video_regs[0x72] = 0; |
| r8806 | r8807 | |
| 554 | 554 | static void spg_do_dma(running_machine *machine, UINT32 len) |
| 555 | 555 | { |
| 556 | 556 | vii_state *state = machine->driver_data<vii_state>(); |
| 557 | | |
| 557 | | |
| 558 | 558 | |
| 559 | 559 | UINT32 src = ((state->io_regs[0x101] & 0x3f) << 16) | state->io_regs[0x100]; |
| 560 | 560 | UINT32 dst = state->io_regs[0x103] & 0x3fff; |
| r8806 | r8807 | |
| 562 | 562 | |
| 563 | 563 | for(j = 0; j < len; j++) |
| 564 | 564 | { |
| 565 | | |
| 565 | space-> | |
| 566 | 566 | } |
| 567 | 567 | |
| 568 | 568 | state->io_regs[0x102] = 0; |
| r8806 | r8807 | |
|---|---|---|
| 1589 | 1589 | NULL /* update address callback */ |
| 1590 | 1590 | }; |
| 1591 | 1591 | |
| 1592 | static UINT8 memory_read_byte(address_space *space, offs_t address) { return space->read_byte(address); } | |
| 1593 | static void memory_write_byte(address_space *space, offs_t address, UINT8 data) { space->write_byte(address, data); } | |
| 1594 | ||
| 1592 | 1595 | static Z80DMA_INTERFACE( x1_dma ) |
| 1593 | 1596 | { |
| 1594 | 1597 | DEVCB_CPU_INPUT_LINE("maincpu", INPUT_LINE_HALT), |
| r8806 | r8807 | |
| 1608 | 1611 | |
| 1609 | 1612 | static INPUT_CHANGED( ipl_reset ) |
| 1610 | 1613 | { |
| 1611 | | |
| 1614 | | |
| 1612 | 1615 | UINT8 *ROM = memory_region(space->machine, "maincpu"); |
| 1613 | 1616 | |
| 1614 | 1617 | cputag_set_input_line(field->port->machine, "maincpu", INPUT_LINE_RESET, newval ? CLEAR_LINE : ASSERT_LINE); |
| r8806 | r8807 | |
| 2029 | 2032 | |
| 2030 | 2033 | static TIMER_CALLBACK(keyboard_callback) |
| 2031 | 2034 | { |
| 2032 | | |
| 2035 | | |
| 2033 | 2036 | UINT32 key1 = input_port_read(machine,"key1"); |
| 2034 | 2037 | UINT32 key2 = input_port_read(machine,"key2"); |
| 2035 | 2038 | UINT32 key3 = input_port_read(machine,"key3"); |
| r8806 | r8807 | |
|---|---|---|
| 42 | 42 | static void xor100_bankswitch(running_machine *machine) |
| 43 | 43 | { |
| 44 | 44 | xor100_state *state = machine->driver_data<xor100_state>(); |
| 45 | | |
| 45 | | |
| 46 | 46 | running_device *messram = machine->device("messram"); |
| 47 | 47 | int banks = messram_get_size(messram) / 0x10000; |
| 48 | 48 |
| r8806 | r8807 | |
|---|---|---|
| 91 | 91 | |
| 92 | 92 | static MACHINE_START( palm ) |
| 93 | 93 | { |
| 94 | | |
| 94 | | |
| 95 | 95 | memory_install_read_bank (space, 0x000000, messram_get_size(machine->device("messram")) - 1, messram_get_size(machine->device("messram")) - 1, 0, "bank1"); |
| 96 | 96 | memory_install_write_bank(space, 0x000000, messram_get_size(machine->device("messram")) - 1, messram_get_size(machine->device("messram")) - 1, 0, "bank1"); |
| 97 | 97 | memory_set_bankptr(machine, "bank1", messram_get_ptr(machine->device("messram"))); |
| r8806 | r8807 | |
|---|---|---|
| 270 | 270 | static MACHINE_START( tmc600 ) |
| 271 | 271 | { |
| 272 | 272 | tmc600_state *state = machine->driver_data<tmc600_state>(); |
| 273 | | |
| 273 | | |
| 274 | 274 | |
| 275 | 275 | /* find devices */ |
| 276 | 276 | state->cassette = machine->device(CASSETTE_TAG); |
| r8806 | r8807 | |
|---|---|---|
| 456 | 456 | |
| 457 | 457 | static int vic20_dma_read_color( running_machine *machine, int offset ) |
| 458 | 458 | { |
| 459 | | |
| 459 | | |
| 460 | 460 | |
| 461 | return | |
| 461 | return pr | |
| 462 | 462 | } |
| 463 | 463 | |
| 464 | 464 | static int vic20_dma_read( running_machine *machine, int offset ) |
| 465 | 465 | { |
| 466 | | |
| 466 | | |
| 467 | 467 | |
| 468 | return | |
| 468 | return pr | |
| 469 | 469 | } |
| 470 | 470 | |
| 471 | 471 | static UINT8 vic20_lightx_cb( running_machine *machine ) |
| r8806 | r8807 | |
| 517 | 517 | static MACHINE_START( vic20 ) |
| 518 | 518 | { |
| 519 | 519 | vic20_state *state = machine->driver_data<vic20_state>(); |
| 520 | | |
| 520 | | |
| 521 | 521 | |
| 522 | 522 | /* find devices */ |
| 523 | 523 | state->via0 = machine->device(M6522_0_TAG); |
| r8806 | r8807 | |
| 556 | 556 | |
| 557 | 557 | static DEVICE_IMAGE_LOAD( vic20_cart ) |
| 558 | 558 | { |
| 559 | | |
| 559 | | |
| 560 | 560 | const char *filetype = image.filetype(); |
| 561 | 561 | UINT32 address = 0; |
| 562 | 562 | UINT32 size; |
| r8806 | r8807 | |
|---|---|---|
| 187 | 187 | { |
| 188 | 188 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 189 | 189 | UINT8 *messram = messram_get_ptr(machine->device("messram")); |
| 190 | | |
| 190 | | |
| 191 | 191 | |
| 192 | 192 | state->screen_location = messram + ((state->port_7ffd_data & 8) ? (7<<14) : (5<<14)); |
| 193 | 193 | |
| r8806 | r8807 | |
| 216 | 216 | |
| 217 | 217 | } |
| 218 | 218 | |
| 219 | ||
| 219 | ||
| 220 | 220 | { |
| 221 | spectrum_state *state = space->machine->driver_data<spectrum_state>(); | |
| 222 | running_device *beta = space->machine->device(BETA_DISK_TAG); | |
| 223 | UINT16 pc = cpu_get_reg(space->machine->device("maincpu"), STATE_GENPCBASE); | |
| 224 | ||
| 221 | spectrum_state *state = machine->driver_data<spectrum_state>(); | |
| 222 | running_device *beta = machine->device(BETA_DISK_TAG); | |
| 223 | UINT16 pc = cpu_get_reg(machine->device("maincpu"), STATE_GENPCBASE); | |
| 224 | address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); | |
| 225 | ||
| 225 | 226 | if (betadisk_is_active(beta)) |
| 226 | 227 | { |
| 227 | 228 | if (pc >= 0x4000) |
| r8806 | r8807 | |
| 229 | 230 | state->ROMSelection = ((state->port_7ffd_data>>4) & 0x01) ? 1 : 0; |
| 230 | 231 | betadisk_disable(beta); |
| 231 | 232 | memory_unmap_write(space, 0x0000, 0x3fff, 0, 0); |
| 232 | memory_set_bankptr( | |
| 233 | memory_set_bankptr( | |
| 233 | 234 | } |
| 234 | 235 | } |
| 235 | 236 | else if (((pc & 0xff00) == 0x3d00) && (state->ROMSelection==1)) |
| r8806 | r8807 | |
| 240 | 241 | if((address>=0x0000) && (address<=0x3fff)) |
| 241 | 242 | { |
| 242 | 243 | memory_unmap_write(space, 0x0000, 0x3fff, 0, 0); |
| 243 | direct->raw = direct->decrypted = memory_region(space->machine, "maincpu") + 0x010000 + (state->ROMSelection<<14); | |
| 244 | memory_set_bankptr(space->machine, "bank1", direct->raw); | |
| 244 | direct.explicit_configure(0x0000, 0x3fff, 0x3fff, memory_region(space->machine, "maincpu") + 0x010000 + (state->ROMSelection<<14)); | |
| 245 | memory_set_bankptr(machine, "bank1", memory_region(space->machine, "maincpu") + 0x010000 + (state->ROMSelection<<14)); | |
| 245 | 246 | return ~0; |
| 246 | 247 | } |
| 247 | 248 | return address; |
| r8806 | r8807 | |
| 306 | 307 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 307 | 308 | UINT8 *messram = messram_get_ptr(machine->device("messram")); |
| 308 | 309 | running_device *beta = machine->device(BETA_DISK_TAG); |
| 309 | | |
| 310 | | |
| 310 | 311 | |
| 311 | 312 | memory_install_read_bank (space, 0x0000, 0x3fff, 0, 0, "bank1"); |
| 312 | 313 | |
| 313 | 314 | betadisk_disable(beta); |
| 314 | 315 | betadisk_clear_status(beta); |
| 315 | 316 | |
| 316 | | |
| 317 | space-> | |
| 317 | 318 | |
| 318 | 319 | memset(messram,0,256*1024); |
| 319 | 320 |
| r8806 | r8807 | |
|---|---|---|
| 322 | 322 | state->port_fe_data = data; |
| 323 | 323 | } |
| 324 | 324 | |
| 325 | ||
| 325 | ||
| 326 | 326 | { |
| 327 | 327 | /* Hack for correct handling 0xffff interrupt vector */ |
| 328 | 328 | if (address == 0x0001) |
| 329 | if (cpu_get_reg( | |
| 329 | if (cpu_get_reg( | |
| 330 | 330 | { |
| 331 | cpu_set_reg( | |
| 331 | cpu_set_reg( | |
| 332 | 332 | return 0xfff4; |
| 333 | 333 | } |
| 334 | 334 | return address; |
| r8806 | r8807 | |
| 622 | 622 | |
| 623 | 623 | DRIVER_INIT( spectrum ) |
| 624 | 624 | { |
| 625 | | |
| 625 | | |
| 626 | 626 | |
| 627 | 627 | switch (messram_get_size(machine->device("messram"))) |
| 628 | 628 | { |
| r8806 | r8807 | |
| 636 | 636 | MACHINE_RESET( spectrum ) |
| 637 | 637 | { |
| 638 | 638 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 639 | | |
| 639 | | |
| 640 | 640 | |
| 641 | memory_set_direct_update_handler(space, spectrum_direct); | |
| 641 | space->set_direct_update_handler(direct_update_delegate_create_static(spectrum_direct, *machine)); | |
| 642 | ||
| 642 | 643 | state->port_7ffd_data = -1; |
| 643 | 644 | state->port_1ffd_data = -1; |
| 644 | 645 | } |
| r8806 | r8807 | |
|---|---|---|
| 493 | 493 | |
| 494 | 494 | /* System Drivers */ |
| 495 | 495 | |
| 496 | ||
| 496 | ||
| 497 | 497 | { |
| 498 | mpf1_state *state = | |
| 498 | mpf1_state *state = | |
| 499 | 499 | |
| 500 | 500 | if (!state->_break) |
| 501 | 501 | { |
| r8806 | r8807 | |
| 503 | 503 | |
| 504 | 504 | if (state->m1 == 5) |
| 505 | 505 | { |
| 506 | cputag_set_input_line( | |
| 506 | cputag_set_input_line( | |
| 507 | 507 | } |
| 508 | 508 | } |
| 509 | 509 | |
| r8806 | r8807 | |
| 512 | 512 | |
| 513 | 513 | static DRIVER_INIT( mpf1 ) |
| 514 | 514 | { |
| 515 | | |
| 515 | | |
| 516 | 516 | } |
| 517 | 517 | |
| 518 | 518 | COMP( 1979, mpf1, 0, 0, mpf1, mpf1, mpf1, "Multitech", "Micro Professor 1", 0) |
| r8806 | r8807 | |
|---|---|---|
| 41 | 41 | |
| 42 | 42 | static void atarist_fdc_dma_transfer(running_machine *machine) |
| 43 | 43 | { |
| 44 | | |
| 44 | | |
| 45 | 45 | atarist_state *state = machine->driver_data<atarist_state>(); |
| 46 | 46 | |
| 47 | 47 | if ((state->fdc_mode & ATARIST_FLOPPY_MODE_DMA_DISABLE) == 0) |
| r8806 | r8807 | |
| 50 | 50 | { |
| 51 | 51 | if (state->fdc_mode & ATARIST_FLOPPY_MODE_WRITE) |
| 52 | 52 | { |
| 53 | UINT8 data = | |
| 53 | UINT8 data = pr | |
| 54 | 54 | |
| 55 | 55 | wd17xx_data_w(state->wd1772, 0, data); |
| 56 | 56 | } |
| r8806 | r8807 | |
| 58 | 58 | { |
| 59 | 59 | UINT8 data = wd17xx_data_r(state->wd1772, 0); |
| 60 | 60 | |
| 61 | | |
| 61 | pr | |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | 64 | state->fdc_dmabase++; |
| r8806 | r8807 | |
| 1459 | 1459 | |
| 1460 | 1460 | static void atarist_configure_memory(running_machine *machine) |
| 1461 | 1461 | { |
| 1462 | | |
| 1462 | | |
| 1463 | 1463 | UINT8 *RAM = memory_region(machine, M68000_TAG); |
| 1464 | 1464 | |
| 1465 | 1465 | switch (messram_get_size(machine->device("messram"))) |
| r8806 | r8807 | |
| 1658 | 1658 | |
| 1659 | 1659 | static void stbook_configure_memory(running_machine *machine) |
| 1660 | 1660 | { |
| 1661 | | |
| 1661 | | |
| 1662 | 1662 | UINT8 *RAM = memory_region(machine, M68000_TAG); |
| 1663 | 1663 | |
| 1664 | 1664 | switch (messram_get_size(machine->device("messram"))) |
| r8806 | r8807 | |
|---|---|---|
| 798 | 798 | |
| 799 | 799 | static void sg1000_map_cartridge_memory(running_machine *machine, UINT8 *ptr, int size) |
| 800 | 800 | { |
| 801 | | |
| 801 | | |
| 802 | 802 | |
| 803 | 803 | switch (size) |
| 804 | 804 | { |
| r8806 | r8807 | |
| 838 | 838 | |
| 839 | 839 | static DEVICE_IMAGE_LOAD( sg1000_cart ) |
| 840 | 840 | { |
| 841 | | |
| 841 | | |
| 842 | 842 | UINT32 size; |
| 843 | 843 | UINT8 *ptr = memory_region(image.device().machine, Z80_TAG); |
| 844 | 844 | |
| r8806 | r8807 | |
| 896 | 896 | |
| 897 | 897 | static void sc3000_map_cartridge_memory(running_machine *machine, UINT8 *ptr, int size) |
| 898 | 898 | { |
| 899 | | |
| 899 | | |
| 900 | 900 | |
| 901 | 901 | /* include SG-1000 mapping */ |
| 902 | 902 | sg1000_map_cartridge_memory(machine, ptr, size); |
| r8806 | r8807 | |
|---|---|---|
| 1208 | 1208 | mips3drc_set_options(machine->device("maincpu"), MIPS3DRC_COMPATIBLE_OPTIONS | MIPS3DRC_CHECK_OVERFLOWS); |
| 1209 | 1209 | } |
| 1210 | 1210 | |
| 1211 | static void dump_chain( | |
| 1211 | static void dump_chain( | |
| 1212 | 1212 | { |
| 1213 | 1213 | |
| 1214 | printf("node: %08x %08x %08x (len = %x)\n", | |
| 1214 | printf("node: %08x %08x %08x (len = %x)\n", space->r | |
| 1215 | 1215 | |
| 1216 | if (( | |
| 1216 | if ((space->r | |
| 1217 | 1217 | { |
| 1218 | dump_chain(space, | |
| 1218 | dump_chain(space, space->r | |
| 1219 | 1219 | } |
| 1220 | 1220 | } |
| 1221 | 1221 | |
| r8806 | r8807 | |
| 1229 | 1229 | |
| 1230 | 1230 | static void scsi_irq(running_machine *machine, int state) |
| 1231 | 1231 | { |
| 1232 | | |
| 1232 | | |
| 1233 | 1233 | |
| 1234 | 1234 | if (state) |
| 1235 | 1235 | { |
| r8806 | r8807 | |
| 1250 | 1250 | words = wd33c93_get_dma_count(); |
| 1251 | 1251 | words /= 4; |
| 1252 | 1252 | |
| 1253 | wptr = | |
| 1253 | wptr = space->r | |
| 1254 | 1254 | nHPC_SCSI0Descriptor += words*4; |
| 1255 | 1255 | dptr = 0; |
| 1256 | 1256 | |
| r8806 | r8807 | |
| 1265 | 1265 | |
| 1266 | 1266 | while (words) |
| 1267 | 1267 | { |
| 1268 | tmpword = | |
| 1268 | tmpword = space->r | |
| 1269 | 1269 | |
| 1270 | 1270 | if (nHPC_SCSI0DMACtrl & HPC3_DMACTRL_ENDIAN) |
| 1271 | 1271 | { |
| r8806 | r8807 | |
| 1301 | 1301 | |
| 1302 | 1302 | while (twords) |
| 1303 | 1303 | { |
| 1304 | tmpword = | |
| 1304 | tmpword = space->r | |
| 1305 | 1305 | |
| 1306 | 1306 | if (nHPC_SCSI0DMACtrl & HPC3_DMACTRL_ENDIAN) |
| 1307 | 1307 | { |
| r8806 | r8807 | |
| 1333 | 1333 | wd33c93_clear_dma(); |
| 1334 | 1334 | #if 0 |
| 1335 | 1335 | UINT32 dptr, tmpword; |
| 1336 | UINT32 bc = memory_read_dword(space, nHPC_SCSI0Descriptor + 4); | |
| 1337 | UINT32 rptr = memory_read_dword(space, nHPC_SCSI0Descriptor); | |
| 1336 | UINT32 bc = space->read_dword(nHPC_SCSI0Descriptor + 4); | |
| 1337 | UINT32 rptr = space->read_dword(nHPC_SCSI0Descriptor); | |
| 1338 | 1338 | int length = bc & 0x3fff; |
| 1339 | 1339 | int xie = (bc & 0x20000000) ? 1 : 0; |
| 1340 | 1340 | int eox = (bc & 0x80000000) ? 1 : 0; |
| r8806 | r8807 | |
| 1349 | 1349 | dptr = 0; |
| 1350 | 1350 | while (length > 0) |
| 1351 | 1351 | { |
| 1352 | tmpword = | |
| 1352 | tmpword = space->r | |
| 1353 | 1353 | if (nHPC_SCSI0DMACtrl & HPC3_DMACTRL_ENDIAN) |
| 1354 | 1354 | { |
| 1355 | 1355 | dma_buffer[dptr+3] = (tmpword>>24)&0xff; |
| r8806 | r8807 | |
| 1370 | 1370 | length -= 4; |
| 1371 | 1371 | } |
| 1372 | 1372 | |
| 1373 | length = | |
| 1373 | length = space->r | |
| 1374 | 1374 | wd33c93_write_data(length, dma_buffer); |
| 1375 | 1375 | |
| 1376 | 1376 | // clear DMA on the controller too |
| r8806 | r8807 | |
| 1392 | 1392 | words = wd33c93_get_dma_count(); |
| 1393 | 1393 | words /= 4; |
| 1394 | 1394 | |
| 1395 | wptr = | |
| 1395 | wptr = space->r | |
| 1396 | 1396 | sptr = 0; |
| 1397 | 1397 | |
| 1398 | 1398 | // mame_printf_info("DMA from device: %d words @ %x\n", words, wptr); |
| r8806 | r8807 | |
| 1415 | 1415 | tmpword = dma_buffer[sptr]<<24 | dma_buffer[sptr+1]<<16 | dma_buffer[sptr+2]<<8 | dma_buffer[sptr+3]; |
| 1416 | 1416 | } |
| 1417 | 1417 | |
| 1418 | | |
| 1418 | space-> | |
| 1419 | 1419 | wptr += 4; |
| 1420 | 1420 | sptr += 4; |
| 1421 | 1421 | words--; |
| r8806 | r8807 | |
| 1439 | 1439 | { |
| 1440 | 1440 | tmpword = dma_buffer[sptr]<<24 | dma_buffer[sptr+1]<<16 | dma_buffer[sptr+2]<<8 | dma_buffer[sptr+3]; |
| 1441 | 1441 | } |
| 1442 | | |
| 1442 | space-> | |
| 1443 | 1443 | |
| 1444 | 1444 | wptr += 4; |
| 1445 | 1445 | sptr += 4; |
| r8806 | r8807 | |
|---|---|---|
| 86 | 86 | static void bankswitch(running_machine *machine) |
| 87 | 87 | { |
| 88 | 88 | px8_state *state = machine->driver_data<px8_state>(); |
| 89 | | |
| 89 | | |
| 90 | 90 | UINT8 *ram = messram_get_ptr(machine->device("messram")); |
| 91 | 91 | UINT8 *ipl_rom = memory_region(machine, UPD70008_TAG); |
| 92 | 92 |
| r8806 | r8807 | |
|---|---|---|
| 70 | 70 | static WRITE8_HANDLER( ls259_w ) |
| 71 | 71 | { |
| 72 | 72 | mm1_state *state = space->machine->driver_data<mm1_state>(); |
| 73 | | |
| 73 | | |
| 74 | 74 | int d = BIT(data, 0); |
| 75 | 75 | |
| 76 | 76 | switch (offset) |
| r8806 | r8807 | |
| 448 | 448 | } |
| 449 | 449 | } |
| 450 | 450 | |
| 451 | static UINT8 memory_read_byte(address_space *space, offs_t address) { return space->read_byte(address); } | |
| 452 | static void memory_write_byte(address_space *space, offs_t address, UINT8 data) { space->write_byte(address, data); } | |
| 453 | ||
| 451 | 454 | static I8237_INTERFACE( mm1_dma8237_intf ) |
| 452 | 455 | { |
| 453 | 456 | DEVCB_LINE(dma_hrq_changed), |
| r8806 | r8807 | |
| 685 | 688 | static MACHINE_START( mm1 ) |
| 686 | 689 | { |
| 687 | 690 | mm1_state *state = machine->driver_data<mm1_state>(); |
| 688 | | |
| 691 | | |
| 689 | 692 | |
| 690 | 693 | /* look up devices */ |
| 691 | 694 | state->i8212 = machine->device(I8212_TAG); |
| r8806 | r8807 | |
| 721 | 724 | static MACHINE_RESET( mm1 ) |
| 722 | 725 | { |
| 723 | 726 | mm1_state *state = machine->driver_data<mm1_state>(); |
| 724 | | |
| 727 | | |
| 725 | 728 | int i; |
| 726 | 729 | |
| 727 | 730 | /* reset LS259 */ |
| r8806 | r8807 | |
|---|---|---|
| 923 | 923 | offs_t page_offset = (((offs_t) dma_offset[0][dma_channel]) << 16) |
| 924 | 924 | & 0xFF0000; |
| 925 | 925 | |
| 926 | return | |
| 926 | return space->r | |
| 927 | 927 | } |
| 928 | 928 | |
| 929 | 929 | |
| r8806 | r8807 | |
| 932 | 932 | offs_t page_offset = (((offs_t) dma_offset[0][dma_channel]) << 16) |
| 933 | 933 | & 0xFF0000; |
| 934 | 934 | |
| 935 | | |
| 935 | space-> | |
| 936 | 936 | } |
| 937 | 937 | |
| 938 | 938 | static void set_dma_channel(running_device *device, int channel, int state) |
| r8806 | r8807 | |
|---|---|---|
| 748 | 748 | static WRITE8_HANDLER(modeJVP_switch_w) { modeJVP_switch(space->machine, offset, data); riot_ram[ 0x20 + offset ] = data; } |
| 749 | 749 | |
| 750 | 750 | |
| 751 | ||
| 751 | ||
| 752 | 752 | { |
| 753 | 753 | if ( ( address & 0x1FFF ) >= 0x1FF6 && ( address & 0x1FFF ) <= 0x1FF9 ) |
| 754 | 754 | { |
| 755 | modeF6_switch_w( space, ( address & 0x1FFF ) - 0x1FF6, 0 ); | |
| 755 | modeF6_switch_w( cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), ( address & 0x1FFF ) - 0x1FF6, 0 ); | |
| 756 | 756 | } |
| 757 | 757 | return address; |
| 758 | 758 | } |
| 759 | 759 | |
| 760 | ||
| 760 | ||
| 761 | 761 | { |
| 762 | 762 | if ( address & 0x1000 ) |
| 763 | 763 | { |
| 764 | direct->bytemask = 0x7ff; | |
| 765 | direct->bytestart = ( address & 0xf800 ); | |
| 766 | direct->byteend = ( address & 0xf800 ) | 0x7ff; | |
| 767 | 764 | if ( address & 0x800 ) |
| 768 | 765 | { |
| 769 | direct->decrypted = bank_base[2]; | |
| 770 | direct->raw = bank_base[2]; | |
| 766 | direct.explicit_configure(( address & 0xf800 ), ( address & 0xf800 ) | 0x7ff, 0x7ff, bank_base[2]); | |
| 771 | 767 | } |
| 772 | 768 | else |
| 773 | 769 | { |
| 774 | direct->decrypted = bank_base[1]; | |
| 775 | direct->raw = bank_base[1]; | |
| 770 | direct.explicit_configure(( address & 0xf800 ), ( address & 0xf800 ) | 0x7ff, 0x7ff, bank_base[1]); | |
| 776 | 771 | } |
| 777 | 772 | return ~0; |
| 778 | 773 | } |
| r8806 | r8807 | |
| 945 | 940 | } |
| 946 | 941 | } |
| 947 | 942 | |
| 948 | ||
| 943 | ||
| 949 | 944 | { |
| 950 | 945 | UINT8 new_bit; |
| 951 | 946 | new_bit = ( dpc.shift_reg & 0x80 ) ^ ( ( dpc.shift_reg & 0x20 ) << 2 ); |
| r8806 | r8807 | |
| 1091 | 1086 | |
| 1092 | 1087 | */ |
| 1093 | 1088 | |
| 1094 | ||
| 1089 | ||
| 1095 | 1090 | static int FETimer; |
| 1096 | 1091 | |
| 1097 | ||
| 1092 | ||
| 1098 | 1093 | { |
| 1099 | 1094 | if ( ! FETimer ) |
| 1100 | 1095 | { |
| 1101 | 1096 | /* Still cheating a bit here by looking bit 13 of the address..., but the high byte of the |
| 1102 | 1097 | cpu should be the last byte that was on the data bus and so should determine the bank |
| 1103 | 1098 | we should switch in. */ |
| 1104 | bank_base[1] = memory_region(space->machine, "user1") + 0x1000 * ( ( address & 0x2000 ) ? 0 : 1 ); | |
| 1105 | memory_set_bankptr(space->machine, "bank1", bank_base[1] ); | |
| 1099 | bank_base[1] = memory_region(machine, "user1") + 0x1000 * ( ( address & 0x2000 ) ? 0 : 1 ); | |
| 1100 | memory_set_bankptr(machine, "bank1", bank_base[1] ); | |
| 1106 | 1101 | /* and restore old opbase handler */ |
| 1107 | mem | |
| 1102 | cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM)->set_direct_update_handler( | |
| 1108 | 1103 | } |
| 1109 | 1104 | else |
| 1110 | 1105 | { |
| r8806 | r8807 | |
| 1116 | 1111 | |
| 1117 | 1112 | static void modeFE_switch(running_machine *machine,UINT16 offset, UINT8 data) |
| 1118 | 1113 | { |
| 1119 | | |
| 1114 | | |
| 1120 | 1115 | /* Retrieve last byte read by the cpu (for this mapping scheme this |
| 1121 | 1116 | should be the last byte that was on the data bus |
| 1122 | 1117 | */ |
| 1123 | 1118 | FETimer = 1; |
| 1124 | FE_old_opbase_handler = | |
| 1119 | FE_old_opbase_handler = space-> | |
| 1125 | 1120 | } |
| 1126 | 1121 | |
| 1127 | 1122 | static READ8_HANDLER(modeFE_switch_r) |
| 1128 | 1123 | { |
| 1129 | 1124 | modeFE_switch(space->machine,offset, 0 ); |
| 1130 | return | |
| 1125 | return space->r | |
| 1131 | 1126 | } |
| 1132 | 1127 | |
| 1133 | 1128 | static WRITE8_HANDLER(modeFE_switch_w) |
| 1134 | 1129 | { |
| 1135 | | |
| 1130 | space-> | |
| 1136 | 1131 | modeFE_switch(space->machine,offset, 0 ); |
| 1137 | 1132 | } |
| 1138 | 1133 | |
| r8806 | r8807 | |
| 1479 | 1474 | { |
| 1480 | 1475 | return offset; |
| 1481 | 1476 | } |
| 1482 | last_byte = | |
| 1477 | last_byte = space->r | |
| 1483 | 1478 | if ( last_byte < 0x80 || last_byte == 0xFF ) |
| 1484 | 1479 | { |
| 1485 | 1480 | return last_byte; |
| r8806 | r8807 | |
| 1489 | 1484 | { |
| 1490 | 1485 | return last_byte; |
| 1491 | 1486 | } |
| 1492 | prev_byte = | |
| 1487 | prev_byte = space->r | |
| 1493 | 1488 | if ( prev_byte == 0xB1 ) |
| 1494 | 1489 | { /* LDA (XX),Y */ |
| 1495 | return | |
| 1490 | return space->r | |
| 1496 | 1491 | } |
| 1497 | 1492 | return last_byte; |
| 1498 | 1493 | } |
| r8806 | r8807 | |
| 1619 | 1614 | |
| 1620 | 1615 | static MACHINE_RESET( a2600 ) |
| 1621 | 1616 | { |
| 1622 | | |
| 1617 | | |
| 1623 | 1618 | int chip = 0xFF; |
| 1624 | 1619 | unsigned long controltemp; |
| 1625 | 1620 | static const unsigned char snowwhite[] = { 0x10, 0xd0, 0xff, 0xff }; // Snow White Proto |
| r8806 | r8807 | |
| 1817 | 1812 | case modeF6: |
| 1818 | 1813 | memory_install_write8_handler(space, 0x1ff6, 0x1ff9, 0, 0, modeF6_switch_w); |
| 1819 | 1814 | memory_install_read8_handler(space, 0x1ff6, 0x1ff9, 0, 0, modeF6_switch_r); |
| 1820 | | |
| 1815 | space-> | |
| 1821 | 1816 | break; |
| 1822 | 1817 | |
| 1823 | 1818 | case modeF4: |
| r8806 | r8807 | |
| 1871 | 1866 | memory_set_bankptr(machine, "bank1", bank_base[1] ); |
| 1872 | 1867 | memory_set_bankptr(machine, "bank2", bank_base[2] ); |
| 1873 | 1868 | modeSS_write_enabled = 0; |
| 1874 | modeSS_byte_started = 0; | |
| 1875 | memory_set_direct_update_handler(space, modeSS_opbase ); | |
| 1869 | modeSS_byte_started = 0; | |
| 1870 | space->set_direct_update_handler(direct_update_delegate_create_static(modeSS_opbase, *machine)); | |
| 1876 | 1871 | /* The Supercharger has no motor control so just enable it */ |
| 1877 | 1872 | cassette_change_state( machine->device("cassette"), CASSETTE_MOTOR_ENABLED, CASSETTE_MOTOR_DISABLED ); |
| 1878 | 1873 | break; |
| r8806 | r8807 | |
| 1886 | 1881 | memory_install_read8_handler(space, 0x1000, 0x103f, 0, 0, modeDPC_r); |
| 1887 | 1882 | memory_install_write8_handler(space, 0x1040, 0x107f, 0, 0, modeDPC_w); |
| 1888 | 1883 | memory_install_write8_handler(space, 0x1ff8, 0x1ff9, 0, 0, modeF8_switch_w); |
| 1889 | memory_install_read8_handler(space, 0x1ff8, 0x1ff9, 0, 0, modeF8_switch_r); | |
| 1890 | memory_set_direct_update_handler(space, modeDPC_opbase_handler ); | |
| 1884 | memory_install_read8_handler(space, 0x1ff8, 0x1ff9, 0, 0, modeF8_switch_r); | |
| 1885 | space->set_direct_update_handler(direct_update_delegate_create_static(modeDPC_opbase_handler, *machine)); | |
| 1891 | 1886 | { |
| 1892 | 1887 | int data_fetcher; |
| 1893 | 1888 | for( data_fetcher = 0; data_fetcher < 8; data_fetcher++ ) |
| r8806 | r8807 | |
|---|---|---|
| 237 | 237 | |
| 238 | 238 | static void pcw_update_read_memory_block(running_machine *machine, int block, int bank) |
| 239 | 239 | { |
| 240 | | |
| 240 | | |
| 241 | 241 | char block_name[10]; |
| 242 | 242 | |
| 243 | 243 | sprintf(block_name,"bank%d",block+1); |
| r8806 | r8807 | |
|---|---|---|
| 667 | 667 | { |
| 668 | 668 | osi_state *state = machine->driver_data<osi_state>(); |
| 669 | 669 | |
| 670 | | |
| 670 | | |
| 671 | 671 | |
| 672 | 672 | /* find devices */ |
| 673 | 673 | state->cassette = machine->device(CASSETTE_TAG); |
| r8806 | r8807 | |
| 697 | 697 | { |
| 698 | 698 | osi_state *state = machine->driver_data<osi_state>(); |
| 699 | 699 | |
| 700 | | |
| 700 | | |
| 701 | 701 | |
| 702 | 702 | /* find devices */ |
| 703 | 703 | state->cassette = machine->device(CASSETTE_TAG); |
| r8806 | r8807 | |
|---|---|---|
| 148 | 148 | static void v1050_bankswitch(running_machine *machine) |
| 149 | 149 | { |
| 150 | 150 | v1050_state *state = machine->driver_data<v1050_state>(); |
| 151 | | |
| 151 | | |
| 152 | 152 | |
| 153 | 153 | int bank = (state->bank >> 1) & 0x03; |
| 154 | 154 | |
| r8806 | r8807 | |
| 1101 | 1101 | static MACHINE_START( v1050 ) |
| 1102 | 1102 | { |
| 1103 | 1103 | v1050_state *state = machine->driver_data<v1050_state>(); |
| 1104 | | |
| 1104 | | |
| 1105 | 1105 | |
| 1106 | 1106 | /* find devices */ |
| 1107 | 1107 | state->i8214 = machine->device(UPB8214_TAG); |
| r8806 | r8807 | |
|---|---|---|
| 530 | 530 | { |
| 531 | 531 | ql_state *state = machine->driver_data<ql_state>(); |
| 532 | 532 | |
| 533 | | |
| 533 | | |
| 534 | 534 | |
| 535 | 535 | /* configure ROM cartridge */ |
| 536 | 536 |
| r8806 | r8807 | |
|---|---|---|
| 210 | 210 | static void abc800_bankswitch(running_machine *machine) |
| 211 | 211 | { |
| 212 | 212 | abc800_state *state = machine->driver_data<abc800_state>(); |
| 213 | | |
| 213 | | |
| 214 | 214 | |
| 215 | 215 | if (state->fetch_charram) |
| 216 | 216 | { |
| r8806 | r8807 | |
| 227 | 227 | static void abc802_bankswitch(running_machine *machine) |
| 228 | 228 | { |
| 229 | 229 | abc802_state *state = machine->driver_data<abc802_state>(); |
| 230 | | |
| 230 | | |
| 231 | 231 | |
| 232 | 232 | if (state->lrs) |
| 233 | 233 | { |
| r8806 | r8807 | |
| 247 | 247 | static void abc806_bankswitch(running_machine *machine) |
| 248 | 248 | { |
| 249 | 249 | abc806_state *state = machine->driver_data<abc806_state>(); |
| 250 | | |
| 250 | | |
| 251 | 251 | UINT32 videoram_mask = messram_get_size(machine->device("messram")) - (32 * 1024) - 1; |
| 252 | 252 | int bank; |
| 253 | 253 | char bank_name[10]; |
| r8806 | r8807 | |
| 1357 | 1357 | |
| 1358 | 1358 | /* Driver Initialization */ |
| 1359 | 1359 | |
| 1360 | ||
| 1360 | ||
| 1361 | 1361 | { |
| 1362 | abc800_state *state = | |
| 1362 | abc800_state *state = | |
| 1363 | 1363 | |
| 1364 | 1364 | if (address >= 0x7800 && address < 0x8000) |
| 1365 | 1365 | { |
| 1366 | direct | |
| 1366 | direct. | |
| 1367 | 1367 | |
| 1368 | 1368 | if (!state->fetch_charram) |
| 1369 | 1369 | { |
| 1370 | 1370 | state->fetch_charram = 1; |
| 1371 | abc800_bankswitch( | |
| 1371 | abc800_bankswitch( | |
| 1372 | 1372 | } |
| 1373 | 1373 | |
| 1374 | 1374 | return ~0; |
| r8806 | r8807 | |
| 1377 | 1377 | if (state->fetch_charram) |
| 1378 | 1378 | { |
| 1379 | 1379 | state->fetch_charram = 0; |
| 1380 | abc800_bankswitch( | |
| 1380 | abc800_bankswitch( | |
| 1381 | 1381 | } |
| 1382 | 1382 | |
| 1383 | 1383 | return address; |
| 1384 | 1384 | } |
| 1385 | 1385 | |
| 1386 | ||
| 1386 | ||
| 1387 | 1387 | { |
| 1388 | abc802_state *state = | |
| 1388 | abc802_state *state = | |
| 1389 | 1389 | |
| 1390 | 1390 | if (state->lrs) |
| 1391 | 1391 | { |
| 1392 | 1392 | if (address >= 0x7800 && address < 0x8000) |
| 1393 | 1393 | { |
| 1394 | direct | |
| 1394 | direct. | |
| 1395 | 1395 | return ~0; |
| 1396 | 1396 | } |
| 1397 | 1397 | } |
| 1398 | 1398 | else |
| 1399 | 1399 | { |
| 1400 | direct | |
| 1400 | direct. | |
| 1401 | 1401 | return ~0; |
| 1402 | 1402 | } |
| 1403 | 1403 | |
| 1404 | 1404 | return address; |
| 1405 | 1405 | } |
| 1406 | 1406 | |
| 1407 | ||
| 1407 | ||
| 1408 | 1408 | { |
| 1409 | abc806_state *state = | |
| 1409 | abc806_state *state = | |
| 1410 | 1410 | |
| 1411 | 1411 | if (address >= 0x7800 && address < 0x8000) |
| 1412 | 1412 | { |
| 1413 | direct | |
| 1413 | direct. | |
| 1414 | 1414 | |
| 1415 | 1415 | if (!state->fetch_charram) |
| 1416 | 1416 | { |
| 1417 | 1417 | state->fetch_charram = 1; |
| 1418 | abc806_bankswitch( | |
| 1418 | abc806_bankswitch( | |
| 1419 | 1419 | } |
| 1420 | 1420 | |
| 1421 | 1421 | return ~0; |
| r8806 | r8807 | |
| 1424 | 1424 | if (state->fetch_charram) |
| 1425 | 1425 | { |
| 1426 | 1426 | state->fetch_charram = 0; |
| 1427 | abc806_bankswitch( | |
| 1427 | abc806_bankswitch( | |
| 1428 | 1428 | } |
| 1429 | 1429 | |
| 1430 | 1430 | return address; |
| r8806 | r8807 | |
| 1432 | 1432 | |
| 1433 | 1433 | static DRIVER_INIT( abc800 ) |
| 1434 | 1434 | { |
| 1435 | | |
| 1435 | | |
| 1436 | 1436 | } |
| 1437 | 1437 | |
| 1438 | 1438 | static DRIVER_INIT( abc802 ) |
| 1439 | 1439 | { |
| 1440 | | |
| 1440 | | |
| 1441 | 1441 | } |
| 1442 | 1442 | |
| 1443 | 1443 | static DRIVER_INIT( abc806 ) |
| 1444 | 1444 | { |
| 1445 | | |
| 1445 | | |
| 1446 | 1446 | } |
| 1447 | 1447 | |
| 1448 | 1448 | /* System Drivers */ |
| r8806 | r8807 | |
|---|---|---|
| 590 | 590 | timer_adjust_oneshot(flyback_timer, machine->primary_screen->time_until_pos(vidc20_vert_reg[VDER]),0); |
| 591 | 591 | } |
| 592 | 592 | |
| 593 | static void viddma_transfer_start( | |
| 593 | static void viddma_transfer_start( | |
| 594 | 594 | { |
| 595 | 595 | UINT32 src = viddma_addr_start; |
| 596 | 596 | UINT32 dst = 0; |
| r8806 | r8807 | |
| 601 | 601 | /* TODO: this should actually be a qword transfer */ |
| 602 | 602 | for(dma_index = 0;dma_index < size;dma_index++) |
| 603 | 603 | { |
| 604 | vram[dst] = | |
| 604 | vram[dst] = space->r | |
| 605 | 605 | |
| 606 | 606 | src++; |
| 607 | 607 | dst++; |
| r8806 | r8807 | |
|---|---|---|
| 219 | 219 | Channel 2: GDC |
| 220 | 220 | Channel 3: Option slots |
| 221 | 221 | */ |
| 222 | static UINT8 memory_read_byte(address_space *space, offs_t address) { return space->read_byte(address); } | |
| 223 | static void memory_write_byte(address_space *space, offs_t address, UINT8 data) { space->write_byte(address, data); } | |
| 224 | ||
| 222 | 225 | static I8237_INTERFACE( qx10_dma8237_1_interface ) |
| 223 | 226 | { |
| 224 | 227 | DEVCB_LINE(dma_hrq_changed), |
| r8806 | r8807 | |
|---|---|---|
| 17 | 17 | |
| 18 | 18 | static void tvc_set_mem_page(running_machine *machine, UINT8 data) |
| 19 | 19 | { |
| 20 | | |
| 20 | | |
| 21 | 21 | switch(data & 0x18) { |
| 22 | 22 | case 0x00 : // system ROM selected |
| 23 | 23 | memory_install_read_bank(space, 0x0000, 0x3fff, 0, 0, "bank1"); |
| r8806 | r8807 | |
|---|---|---|
| 930 | 930 | UINT8 *temp_copy; |
| 931 | 931 | running_machine *machine = image.device().machine; |
| 932 | 932 | UINT8 *mem = memory_region(machine, M6502_TAG); |
| 933 | | |
| 933 | | |
| 934 | 934 | |
| 935 | 935 | if (image.software_entry() == NULL) |
| 936 | 936 | { |
| r8806 | r8807 | |
|---|---|---|
| 996 | 996 | state->towns_cmos[offset] = data; |
| 997 | 997 | } |
| 998 | 998 | |
| 999 | void towns_update_video_banks( | |
| 999 | void towns_update_video_banks( | |
| 1000 | 1000 | { |
| 1001 | 1001 | towns_state* state = space->machine->driver_data<towns_state>(); |
| 1002 | 1002 | UINT8* ROM; |
| r8806 | r8807 | |
|---|---|---|
| 86 | 86 | { |
| 87 | 87 | newbrain_state *state = machine->driver_data<newbrain_state>(); |
| 88 | 88 | |
| 89 | | |
| 89 | | |
| 90 | 90 | int bank; |
| 91 | 91 | |
| 92 | 92 | for (bank = 1; bank < 9; bank++) |
| r8806 | r8807 | |
| 126 | 126 | { |
| 127 | 127 | newbrain_state *state = machine->driver_data<newbrain_state>(); |
| 128 | 128 | |
| 129 | | |
| 129 | | |
| 130 | 130 | int bank; |
| 131 | 131 | |
| 132 | 132 | if (state->paging) |
| r8806 | r8807 | |
|---|---|---|
| 255 | 255 | |
| 256 | 256 | static READ8_HANDLER( fk1_bank_ram_r ) |
| 257 | 257 | { |
| 258 | | |
| 258 | | |
| 259 | 259 | memory_install_write_bank(space_mem, 0x0000, 0x3fff, 0, 0, "bank1"); |
| 260 | 260 | memory_set_bankptr(space->machine, "bank1", messram_get_ptr(space->machine->device("messram"))); |
| 261 | 261 | memory_set_bankptr(space->machine, "bank2", messram_get_ptr(space->machine->device("messram")) + 0x4000); |
| r8806 | r8807 | |
| 264 | 264 | |
| 265 | 265 | static READ8_HANDLER( fk1_bank_rom_r ) |
| 266 | 266 | { |
| 267 | | |
| 267 | | |
| 268 | 268 | memory_unmap_write(space_mem, 0x0000, 0x3fff, 0, 0); |
| 269 | 269 | memory_set_bankptr(space->machine, "bank1", memory_region(space->machine, "maincpu")); |
| 270 | 270 | memory_set_bankptr(space->machine, "bank2", messram_get_ptr(space->machine->device("messram")) + 0x10000); |
| r8806 | r8807 | |
| 380 | 380 | |
| 381 | 381 | static MACHINE_RESET(fk1) |
| 382 | 382 | { |
| 383 | | |
| 383 | | |
| 384 | 384 | memory_unmap_write(space, 0x0000, 0x3fff, 0, 0); |
| 385 | 385 | memory_set_bankptr(machine, "bank1", memory_region(machine, "maincpu")); // ROM |
| 386 | 386 | memory_set_bankptr(machine, "bank2", messram_get_ptr(machine->device("messram")) + 0x10000); // VRAM |
| r8806 | r8807 | |
|---|---|---|
| 470 | 470 | ---- x--- memory bank status |
| 471 | 471 | ---- -xxx page screen graphics in B/W mode |
| 472 | 472 | */ |
| 473 | // | |
| 473 | // | |
| 474 | 474 | |
| 475 | 475 | // printf("Port B w = %02x %04x\n",data,cpu_get_pc(space->cpu)); |
| 476 | 476 |
| r8806 | r8807 | |
|---|---|---|
| 193 | 193 | static SNAPSHOT_LOAD( vtech1 ) |
| 194 | 194 | { |
| 195 | 195 | vtech1_state *vtech1 = image.device().machine->driver_data<vtech1_state>(); |
| 196 | | |
| 196 | | |
| 197 | 197 | UINT8 i, header[24]; |
| 198 | 198 | UINT16 start, end, size; |
| 199 | 199 | char pgmname[18]; |
| r8806 | r8807 | |
| 225 | 225 | switch (header[21]) |
| 226 | 226 | { |
| 227 | 227 | case VZ_BASIC: /* 0xF0 */ |
| 228 | memory_write_byte(space, 0x78a4, start % 256); /* start of basic program */ | |
| 229 | memory_write_byte(space, 0x78a5, start / 256); | |
| 230 | memory_write_byte(space, 0x78f9, end % 256); /* end of basic program */ | |
| 231 | memory_write_byte(space, 0x78fa, end / 256); | |
| 232 | memory_write_byte(space, 0x78fb, end % 256); /* start variable table */ | |
| 233 | memory_write_byte(space, 0x78fc, end / 256); | |
| 234 | memory_write_byte(space, 0x78fd, end % 256); /* start free mem, end variable table */ | |
| 235 | memory_write_byte(space, 0x78fe, end / 256); | |
| 228 | space->write_byte(0x78a4, start % 256); /* start of basic program */ | |
| 229 | space->write_byte(0x78a5, start / 256); | |
| 230 | space->write_byte(0x78f9, end % 256); /* end of basic program */ | |
| 231 | space->write_byte(0x78fa, end / 256); | |
| 232 | space->write_byte(0x78fb, end % 256); /* start variable table */ | |
| 233 | space->write_byte(0x78fc, end / 256); | |
| 234 | space->write_byte(0x78fd, end % 256); /* start free mem, end variable table */ | |
| 235 | space->write_byte(0x78fe, end / 256); | |
| 236 | 236 | image.message(" %s (B)\nsize=%04X : start=%04X : end=%04X",pgmname,size,start,end); |
| 237 | 237 | break; |
| 238 | 238 | |
| 239 | 239 | case VZ_MCODE: /* 0xF1 */ |
| 240 | memory_write_byte(space, 0x788e, start % 256); /* usr subroutine address */ | |
| 241 | memory_write_byte(space, 0x788f, start / 256); | |
| 240 | space->write_byte(0x788e, start % 256); /* usr subroutine address */ | |
| 241 | space->write_byte(0x788f, start / 256); | |
| 242 | 242 | image.message(" %s (M)\nsize=%04X : start=%04X : end=%04X",pgmname,size,start,end); |
| 243 | 243 | cpu_set_reg(image.device().machine->device("maincpu"), STATE_GENPC, start); /* start program */ |
| 244 | 244 | break; |
| r8806 | r8807 | |
| 255 | 255 | static Z80BIN_EXECUTE( vtech1 ) |
| 256 | 256 | { |
| 257 | 257 | running_device *cpu = machine->device("maincpu"); |
| 258 | | |
| 258 | | |
| 259 | 259 | |
| 260 | 260 | /* A Microsoft Basic program needs some manipulation before it can be run. |
| 261 | 261 | 1. A start address of 7ae9 indicates a basic program which needs its pointers fixed up. |
| r8806 | r8807 | |
| 264 | 264 | 7ae9 = start (load) address of a conventional basic program |
| 265 | 265 | 791e = custom routine to fix basic pointers */ |
| 266 | 266 | |
| 267 | memory_write_word_16le(space, 0x791c, end_address + 1); | |
| 268 | memory_write_word_16le(space, 0x781e, execute_address); | |
| 267 | space->write_word(0x791c, end_address + 1); | |
| 268 | space->write_word(0x781e, execute_address); | |
| 269 | 269 | |
| 270 | 270 | if (start_address == 0x7ae9) |
| 271 | 271 | { |
| r8806 | r8807 | |
| 281 | 281 | }; |
| 282 | 282 | |
| 283 | 283 | for (i = 0; i < ARRAY_LENGTH(data); i++) |
| 284 | | |
| 284 | space-> | |
| 285 | 285 | |
| 286 | 286 | if (!autorun) |
| 287 | | |
| 287 | space-> | |
| 288 | 288 | |
| 289 | 289 | cpu_set_reg(cpu, STATE_GENPC, 0x791e); |
| 290 | 290 | } |
| r8806 | r8807 | |
| 685 | 685 | static DRIVER_INIT( vtech1 ) |
| 686 | 686 | { |
| 687 | 687 | vtech1_state *vtech1 = machine->driver_data<vtech1_state>(); |
| 688 | | |
| 688 | | |
| 689 | 689 | int id; |
| 690 | 690 | |
| 691 | 691 | /* find devices */ |
| r8806 | r8807 | |
| 744 | 744 | |
| 745 | 745 | static DRIVER_INIT( vtech1h ) |
| 746 | 746 | { |
| 747 | | |
| 747 | | |
| 748 | 748 | |
| 749 | 749 | DRIVER_INIT_CALL(vtech1); |
| 750 | 750 |
| r8806 | r8807 | |
|---|---|---|
| 113 | 113 | static WRITE8_HANDLER( lynx128k_bank_w ) |
| 114 | 114 | { |
| 115 | 115 | /* get address space */ |
| 116 | | |
| 116 | | |
| 117 | 117 | |
| 118 | 118 | /* Set read banks */ |
| 119 | 119 | UINT8 bank = data & 0x0f; |
| r8806 | r8807 | |
| 312 | 312 | |
| 313 | 313 | static MACHINE_RESET( lynx128k ) |
| 314 | 314 | { |
| 315 | | |
| 315 | | |
| 316 | 316 | memory_install_read_bank (mem, 0x0000, 0x1fff, 0, 0, "bank1"); |
| 317 | 317 | memory_install_read_bank (mem, 0x2000, 0x3fff, 0, 0, "bank2"); |
| 318 | 318 | memory_install_read_bank (mem, 0x4000, 0x5fff, 0, 0, "bank3"); |
| r8806 | r8807 | |
|---|---|---|
| 115 | 115 | } |
| 116 | 116 | |
| 117 | 117 | |
| 118 | void neogeo_set_display_counter_msb( | |
| 118 | void neogeo_set_display_counter_msb( | |
| 119 | 119 | { |
| 120 | 120 | neogeo_state *state = space->machine->driver_data<neogeo_state>(); |
| 121 | 121 | |
| r8806 | r8807 | |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | 127 | |
| 128 | void neogeo_set_display_counter_lsb( | |
| 128 | void neogeo_set_display_counter_lsb( | |
| 129 | 129 | { |
| 130 | 130 | neogeo_state *state = space->machine->driver_data<neogeo_state>(); |
| 131 | 131 | |
| r8806 | r8807 | |
| 371 | 371 | else |
| 372 | 372 | { |
| 373 | 373 | state->recurse = 1; |
| 374 | ret = | |
| 374 | ret = space->r | |
| 375 | 375 | state->recurse = 0; |
| 376 | 376 | } |
| 377 | 377 | |
| r8806 | r8807 | |
| 622 | 622 | } |
| 623 | 623 | |
| 624 | 624 | |
| 625 | void neogeo_set_main_cpu_bank_address( | |
| 625 | void neogeo_set_main_cpu_bank_address( | |
| 626 | 626 | { |
| 627 | 627 | neogeo_state *state = space->machine->driver_data<neogeo_state>(); |
| 628 | 628 | |
| r8806 | r8807 | |
| 658 | 658 | |
| 659 | 659 | static void main_cpu_banking_init( running_machine *machine ) |
| 660 | 660 | { |
| 661 | | |
| 661 | | |
| 662 | 662 | |
| 663 | 663 | /* create vector banks */ |
| 664 | 664 | memory_configure_bank(machine, NEOGEO_BANK_VECTORS, 0, 1, memory_region(machine, "mainbios"), 0); |
| r8806 | r8807 | |
| 689 | 689 | } |
| 690 | 690 | |
| 691 | 691 | |
| 692 | static void audio_cpu_bank_select( | |
| 692 | static void audio_cpu_bank_select( | |
| 693 | 693 | { |
| 694 | 694 | neogeo_state *state = space->machine->driver_data<neogeo_state>(); |
| 695 | 695 | |
| r8806 | r8807 | |
| 733 | 733 | } |
| 734 | 734 | |
| 735 | 735 | |
| 736 | static void _set_audio_cpu_rom_source( | |
| 736 | static void _set_audio_cpu_rom_source( | |
| 737 | 737 | { |
| 738 | 738 | neogeo_state *state = space->machine->driver_data<neogeo_state>(); |
| 739 | 739 | |
| r8806 | r8807 | |
| 754 | 754 | } |
| 755 | 755 | |
| 756 | 756 | |
| 757 | static void set_audio_cpu_rom_source( | |
| 757 | static void set_audio_cpu_rom_source( | |
| 758 | 758 | { |
| 759 | 759 | neogeo_state *state = space->machine->driver_data<neogeo_state>(); |
| 760 | 760 | state->audio_cpu_rom_source = data; |
| r8806 | r8807 | |
| 883 | 883 | * |
| 884 | 884 | */ |
| 885 | 885 | |
| 886 | static void neocd_do_dma( | |
| 886 | static void neocd_do_dma( | |
| 887 | 887 | { |
| 888 | 888 | // TODO: Proper DMA timing and control |
| 889 | 889 | int count; |
| r8806 | r8807 | |
| 894 | 894 | case 0xffdd: |
| 895 | 895 | for(count=0;count<neocd_ctrl.word_count;count++) |
| 896 | 896 | { |
| 897 | //word = memory_read_word(space,neocd_ctrl.addr_source); | |
| 898 | memory_write_word(space,neocd_ctrl.addr_source+(count*2),neocd_ctrl.fill_word); | |
| 897 | //word = space->read_word(neocd_ctrl.addr_source); | |
| 898 | space->write_word(neocd_ctrl.addr_source+(count*2),neocd_ctrl.fill_word); | |
| 899 | 899 | } |
| 900 | 900 | logerror("CTRL: DMA word-fill transfer of %i bytes\n",count*2); |
| 901 | 901 | break; |
| 902 | 902 | case 0xfef5: |
| 903 | 903 | for(count=0;count<neocd_ctrl.word_count;count++) |
| 904 | 904 | { |
| 905 | //word = memory_read_word(space,neocd_ctrl.addr_source); | |
| 906 | memory_write_word(space,neocd_ctrl.addr_source+(count*4),(neocd_ctrl.addr_source+(count*4)) >> 16); | |
| 907 | memory_write_word(space,neocd_ctrl.addr_source+(count*4)+2,(neocd_ctrl.addr_source+(count*4)) & 0xffff); | |
| 905 | //word = space->read_word(neocd_ctrl.addr_source); | |
| 906 | space->write_word(neocd_ctrl.addr_source+(count*4),(neocd_ctrl.addr_source+(count*4)) >> 16); | |
| 907 | space->write_word(neocd_ctrl.addr_source+(count*4)+2,(neocd_ctrl.addr_source+(count*4)) & 0xffff); | |
| 908 | 908 | } |
| 909 | 909 | logerror("CTRL: DMA mode 2 transfer of %i bytes\n",count*4); |
| 910 | 910 | break; |
| 911 | 911 | case 0xcffd: |
| 912 | 912 | for(count=0;count<neocd_ctrl.word_count;count++) |
| 913 | 913 | { |
| 914 | //word = memory_read_word(space,neocd_ctrl.addr_source); | |
| 915 | memory_write_word(space,neocd_ctrl.addr_source+(count*8),((neocd_ctrl.addr_source+(count*8)) >> 24) | 0xff00); | |
| 916 | memory_write_word(space,neocd_ctrl.addr_source+(count*8)+2,((neocd_ctrl.addr_source+(count*8)) >> 16) | 0xff00); | |
| 917 | memory_write_word(space,neocd_ctrl.addr_source+(count*8)+4,((neocd_ctrl.addr_source+(count*8)) >> 8) | 0xff00); | |
| 918 | memory_write_word(space,neocd_ctrl.addr_source+(count*8)+6,(neocd_ctrl.addr_source+(count*8)) | 0xff00); | |
| 914 | //word = space->read_word(neocd_ctrl.addr_source); | |
| 915 | space->write_word(neocd_ctrl.addr_source+(count*8),((neocd_ctrl.addr_source+(count*8)) >> 24) | 0xff00); | |
| 916 | space->write_word(neocd_ctrl.addr_source+(count*8)+2,((neocd_ctrl.addr_source+(count*8)) >> 16) | 0xff00); | |
| 917 | space->write_word(neocd_ctrl.addr_source+(count*8)+4,((neocd_ctrl.addr_source+(count*8)) >> 8) | 0xff00); | |
| 918 | space->write_word(neocd_ctrl.addr_source+(count*8)+6,(neocd_ctrl.addr_source+(count*8)) | 0xff00); | |
| 919 | 919 | } |
| 920 | 920 | logerror("CTRL: DMA mode 3 transfer of %i bytes\n",count*8); |
| 921 | 921 | break; |
| r8806 | r8807 | |
| 1306 | 1306 | { |
| 1307 | 1307 | neogeo_state *state = machine->driver_data<neogeo_state>(); |
| 1308 | 1308 | offs_t offs; |
| 1309 | | |
| 1309 | | |
| 1310 | 1310 | |
| 1311 | 1311 | /* reset system control registers */ |
| 1312 | 1312 | for (offs = 0; offs < 8; offs++) |
| r8806 | r8807 | |
|---|---|---|
| 113 | 113 | { |
| 114 | 114 | kc85_state *state = machine->driver_data<kc85_state>(); |
| 115 | 115 | |
| 116 | | |
| 116 | | |
| 117 | 117 | |
| 118 | 118 | int rom_bank = data & 0x03; |
| 119 | 119 | int ram_bank = (data >> 2) & 0x03; |
| r8806 | r8807 | |
| 409 | 409 | { |
| 410 | 410 | tandy200_state *state = space->machine->driver_data<tandy200_state>(); |
| 411 | 411 | |
| 412 | | |
| 412 | | |
| 413 | 413 | |
| 414 | 414 | int rom_bank = data & 0x03; |
| 415 | 415 | int ram_bank = (data >> 2) & 0x03; |
| r8806 | r8807 | |
| 1131 | 1131 | { |
| 1132 | 1132 | kc85_state *state = machine->driver_data<kc85_state>(); |
| 1133 | 1133 | |
| 1134 | | |
| 1134 | | |
| 1135 | 1135 | |
| 1136 | 1136 | /* find devices */ |
| 1137 | 1137 | state->upd1990a = machine->device(UPD1990A_TAG); |
| r8806 | r8807 | |
| 1212 | 1212 | { |
| 1213 | 1213 | kc85_state *state = machine->driver_data<kc85_state>(); |
| 1214 | 1214 | |
| 1215 | | |
| 1215 | | |
| 1216 | 1216 | |
| 1217 | 1217 | /* find devices */ |
| 1218 | 1218 | state->upd1990a = machine->device(UPD1990A_TAG); |
| r8806 | r8807 | |
|---|---|---|
| 384 | 384 | return n_return; |
| 385 | 385 | } |
| 386 | 386 | |
| 387 | ||
| 387 | ||
| 388 | 388 | { |
| 389 | 389 | if( address == 0x80030000 ) |
| 390 | 390 | { |
| 391 | running_device *cpu = | |
| 391 | running_device *cpu = | |
| 392 | 392 | |
| 393 | mem | |
| 393 | //cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM)->set_direct_update_handler( | |
| 394 | 394 | |
| 395 | 395 | if( load_psxexe( cpu, exe_buffer, exe_size ) || |
| 396 | 396 | load_cpe( cpu, exe_buffer, exe_size ) || |
| r8806 | r8807 | |
| 413 | 413 | |
| 414 | 414 | static QUICKLOAD_LOAD( psx_exe_load ) |
| 415 | 415 | { |
| 416 | | |
| 416 | | |
| 417 | 417 | |
| 418 | 418 | exe_size = 0; |
| 419 | 419 | exe_buffer = (UINT8*)malloc( quickload_size ); |
| r8806 | r8807 | |
| 428 | 428 | return IMAGE_INIT_FAIL; |
| 429 | 429 | } |
| 430 | 430 | exe_size = quickload_size; |
| 431 | memory_set_direct_update_handler( space, psx_setopbase ); | |
| 431 | space->set_direct_update_handler(direct_update_delegate_create_static(psx_setopbase, *image.device().machine)); | |
| 432 | ||
| 432 | 433 | return IMAGE_INIT_PASS; |
| 433 | 434 | } |
| 434 | 435 |
| r8806 | r8807 | |
|---|---|---|
| 162 | 162 | |
| 163 | 163 | static WRITE8_HANDLER( samcoupe_lmpr_w ) |
| 164 | 164 | { |
| 165 | | |
| 165 | | |
| 166 | 166 | coupe_asic *asic = space->machine->driver_data<coupe_asic>(); |
| 167 | 167 | |
| 168 | 168 | asic->lmpr = data; |
| r8806 | r8807 | |
| 177 | 177 | |
| 178 | 178 | static WRITE8_HANDLER( samcoupe_hmpr_w ) |
| 179 | 179 | { |
| 180 | | |
| 180 | | |
| 181 | 181 | coupe_asic *asic = space->machine->driver_data<coupe_asic>(); |
| 182 | 182 | |
| 183 | 183 | asic->hmpr = data; |
| r8806 | r8807 | |
| 192 | 192 | |
| 193 | 193 | static WRITE8_HANDLER( samcoupe_vmpr_w ) |
| 194 | 194 | { |
| 195 | | |
| 195 | | |
| 196 | 196 | coupe_asic *asic = space->machine->driver_data<coupe_asic>(); |
| 197 | 197 | |
| 198 | 198 | asic->vmpr = data; |
| r8806 | r8807 | |
|---|---|---|
| 64 | 64 | static void tiki100_bankswitch(running_machine *machine) |
| 65 | 65 | { |
| 66 | 66 | tiki100_state *state = machine->driver_data<tiki100_state>(); |
| 67 | | |
| 67 | | |
| 68 | 68 | |
| 69 | 69 | if (state->vire) |
| 70 | 70 | { |
| r8806 | r8807 | |
|---|---|---|
| 9 | 9 | #include "machine/beta.h" |
| 10 | 10 | #include "devices/messram.h" |
| 11 | 11 | |
| 12 | ||
| 12 | ||
| 13 | 13 | { |
| 14 | spectrum_state *state = space->machine->driver_data<spectrum_state>(); | |
| 15 | running_device *beta = space->machine->device(BETA_DISK_TAG); | |
| 16 | UINT16 pc = cpu_get_reg(space->machine->device("maincpu"), STATE_GENPCBASE); | |
| 17 | ||
| 14 | spectrum_state *state = machine->driver_data<spectrum_state>(); | |
| 15 | running_device *beta = machine->device(BETA_DISK_TAG); | |
| 16 | UINT16 pc = cpu_get_reg(machine->device("maincpu"), STATE_GENPCBASE); | |
| 17 | address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); | |
| 18 | ||
| 18 | 19 | if (beta->started() && betadisk_is_active(beta)) |
| 19 | 20 | { |
| 20 | 21 | if (pc >= 0x4000) |
| r8806 | r8807 | |
| 22 | 23 | state->ROMSelection = ((state->port_7ffd_data>>4) & 0x01) ? 1 : 0; |
| 23 | 24 | betadisk_disable(beta); |
| 24 | 25 | memory_unmap_write(space, 0x0000, 0x3fff, 0, 0); |
| 25 | memory_set_bankptr( | |
| 26 | memory_set_bankptr( | |
| 26 | 27 | } |
| 27 | 28 | } |
| 28 | 29 | else if (((pc & 0xff00) == 0x3d00) && (state->ROMSelection==1)) |
| r8806 | r8807 | |
| 36 | 37 | { |
| 37 | 38 | memory_unmap_write(space, 0x0000, 0x3fff, 0, 0); |
| 38 | 39 | if (state->ROMSelection == 3) { |
| 39 | direct->raw = direct->decrypted = memory_region(space->machine, "maincpu") + 0x018000 ; | |
| 40 | direct.explicit_configure(0x0000, 0x3fff, 0x3fff, memory_region(machine, "maincpu") + 0x018000); | |
| 41 | memory_set_bankptr(machine, "bank1", memory_region(machine, "maincpu") + 0x018000); | |
| 40 | 42 | } else { |
| 41 | direct->raw = direct->decrypted = memory_region(space->machine, "maincpu") + 0x010000 + (state->ROMSelection<<14); | |
| 43 | direct.explicit_configure(0x0000, 0x3fff, 0x3fff, memory_region(machine, "maincpu") + 0x010000 + (state->ROMSelection<<14)); | |
| 44 | memory_set_bankptr(machine, "bank1", memory_region(machine, "maincpu") + 0x010000 + (state->ROMSelection<<14)); | |
| 42 | 45 | } |
| 43 | memory_set_bankptr(space->machine, "bank1", direct->raw); | |
| 44 | 46 | return ~0; |
| 45 | 47 | } |
| 46 | 48 | return address; |
| r8806 | r8807 | |
| 100 | 102 | { |
| 101 | 103 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 102 | 104 | UINT8 *messram = messram_get_ptr(machine->device("messram")); |
| 103 | | |
| 105 | | |
| 104 | 106 | running_device *beta = machine->device(BETA_DISK_TAG); |
| 105 | 107 | |
| 106 | 108 | memory_install_read_bank(space, 0x0000, 0x3fff, 0, 0, "bank1"); |
| r8806 | r8807 | |
| 111 | 113 | betadisk_clear_status(beta); |
| 112 | 114 | } |
| 113 | 115 | |
| 114 | memory_set_direct_update_handler( space, atm_direct ); | |
| 115 | ||
| 116 | space->set_direct_update_handler(direct_update_delegate_create_static(atm_direct, *machine)); | |
| 117 | ||
| 116 | 118 | memset(messram,0,128*1024); |
| 117 | 119 | |
| 118 | 120 | /* Bank 5 is always in 0x4000 - 0x7fff */ |
| r8806 | r8807 | |
|---|---|---|
| 240 | 240 | |
| 241 | 241 | /* Driver Initialization */ |
| 242 | 242 | |
| 243 | ||
| 243 | ||
| 244 | 244 | { |
| 245 | vcs80_state *state = | |
| 245 | vcs80_state *state = | |
| 246 | 246 | |
| 247 | 247 | /* _A0 is connected to PIO PB7 */ |
| 248 | 248 | z80pio_pb_w(state->z80pio, 0, (!BIT(address, 0)) << 7); |
| r8806 | r8807 | |
| 252 | 252 | |
| 253 | 253 | static DRIVER_INIT( vcs80 ) |
| 254 | 254 | { |
| 255 | memory_set_direct_update_handler(cputag_get_address_space(machine, Z80_TAG, ADDRESS_SPACE_PROGRAM), vcs80_direct_update_handler); | |
| 256 | memory_set_direct_update_handler(cputag_get_address_space(machine, Z80_TAG, ADDRESS_SPACE_IO), vcs80_direct_update_handler); | |
| 255 | cputag_get_address_space(machine, Z80_TAG, ADDRESS_SPACE_PROGRAM)->set_direct_update_handler(direct_update_delegate_create_static(vcs80_direct_update_handler, *machine)); | |
| 256 | cputag_get_address_space(machine, Z80_TAG, ADDRESS_SPACE_IO)->set_direct_update_handler(direct_update_delegate_create_static(vcs80_direct_update_handler, *machine)); | |
| 257 | 257 | } |
| 258 | 258 | |
| 259 | 259 | /* System Drivers */ |
| r8806 | r8807 | |
|---|---|---|
| 474 | 474 | static CRT9007_DRAW_SCANLINE( tandy2k_crt9007_display_pixels ) |
| 475 | 475 | { |
| 476 | 476 | tandy2k_state *state = device->machine->driver_data<tandy2k_state>(); |
| 477 | | |
| 477 | | |
| 478 | 478 | |
| 479 | 479 | for (int sx = 0; sx < x_count; sx++) |
| 480 | 480 | { |
| 481 | 481 | UINT32 videoram_addr = (state->vram_base | (va << 1)) + sx; |
| 482 | UINT8 videoram_data = | |
| 482 | UINT8 videoram_data = pr | |
| 483 | 483 | UINT16 charram_addr = (videoram_data << 4) | sl; |
| 484 | 484 | UINT8 charram_data = state->char_ram[charram_addr] & 0xff; |
| 485 | 485 | |
| r8806 | r8807 | |
| 773 | 773 | state->centronics = machine->device(CENTRONICS_TAG); |
| 774 | 774 | |
| 775 | 775 | /* memory banking */ |
| 776 | | |
| 776 | | |
| 777 | 777 | UINT8 *ram = messram_get_ptr(machine->device("messram")); |
| 778 | 778 | int ram_size = messram_get_size(machine->device("messram")); |
| 779 | 779 |
| r8806 | r8807 | |
|---|---|---|
| 404 | 404 | |
| 405 | 405 | static MACHINE_RESET(nanos) |
| 406 | 406 | { |
| 407 | | |
| 407 | | |
| 408 | 408 | |
| 409 | 409 | memory_install_write_bank(space, 0x0000, 0x0fff, 0, 0, "bank3"); |
| 410 | 410 | memory_install_write_bank(space, 0x1000, 0xffff, 0, 0, "bank2"); |
| r8806 | r8807 | |
|---|---|---|
| 79 | 79 | static UINT8 speaker_active; |
| 80 | 80 | static UINT16 fm7_kanji_address; |
| 81 | 81 | |
| 82 | static void fm7_mmr_refresh( | |
| 82 | static void fm7_mmr_refresh( | |
| 83 | 83 | |
| 84 | 84 | |
| 85 | 85 | static struct key_encoder |
| r8806 | r8807 | |
| 864 | 864 | */ |
| 865 | 865 | static void fm7_update_psg(running_machine* machine) |
| 866 | 866 | { |
| 867 | | |
| 867 | | |
| 868 | 868 | |
| 869 | 869 | if(fm7_type == SYS_FM7) |
| 870 | 870 | { |
| r8806 | r8807 | |
| 1025 | 1025 | return 0xff; |
| 1026 | 1026 | } |
| 1027 | 1027 | |
| 1028 | static void fm7_update_bank( | |
| 1028 | static void fm7_update_bank( | |
| 1029 | 1029 | { |
| 1030 | 1030 | UINT8* RAM = memory_region(space->machine,"maincpu"); |
| 1031 | 1031 | UINT16 size = 0xfff; |
| r8806 | r8807 | |
| 1116 | 1116 | memory_set_bankptr(space->machine,bank_name,RAM+(physical<<12)); |
| 1117 | 1117 | } |
| 1118 | 1118 | |
| 1119 | static void fm7_mmr_refresh( | |
| 1119 | static void fm7_mmr_refresh( | |
| 1120 | 1120 | { |
| 1121 | 1121 | int x; |
| 1122 | 1122 | UINT16 window_addr; |
| r8806 | r8807 | |
|---|---|---|
| 177 | 177 | static MACHINE_START( exp85 ) |
| 178 | 178 | { |
| 179 | 179 | exp85_state *state = machine->driver_data<exp85_state>(); |
| 180 | | |
| 180 | | |
| 181 | 181 | |
| 182 | 182 | /* setup memory banking */ |
| 183 | 183 | memory_install_read_bank(program, 0x0000, 0x07ff, 0, 0, "bank1"); |
| r8806 | r8807 | |
|---|---|---|
| 159 | 159 | { |
| 160 | 160 | trs80m2_state *state = machine->driver_data<trs80m2_state>(); |
| 161 | 161 | |
| 162 | | |
| 162 | | |
| 163 | 163 | running_device *messram = machine->device("messram"); |
| 164 | 164 | UINT8 *rom = memory_region(machine, Z80_TAG); |
| 165 | 165 | UINT8 *ram = messram_get_ptr(messram); |
| r8806 | r8807 | |
| 754 | 754 | |
| 755 | 755 | /* Z80-DMA Interface */ |
| 756 | 756 | |
| 757 | static UINT8 memory_read_byte(address_space *space, offs_t address) { return space->read_byte(address); } | |
| 758 | static void memory_write_byte(address_space *space, offs_t address, UINT8 data) { space->write_byte(address, data); } | |
| 759 | ||
| 757 | 760 | static Z80DMA_INTERFACE( dma_intf ) |
| 758 | 761 | { |
| 759 | 762 | DEVCB_CPU_INPUT_LINE(Z80_TAG, INPUT_LINE_HALT), |
| r8806 | r8807 | |
|---|---|---|
| 339 | 339 | |
| 340 | 340 | static void nc_refresh_memory_bank_config(running_machine *machine, int bank) |
| 341 | 341 | { |
| 342 | | |
| 342 | | |
| 343 | 343 | int mem_type; |
| 344 | 344 | int mem_bank; |
| 345 | 345 | char bank1[10]; |
| r8806 | r8807 | |
|---|---|---|
| 184 | 184 | p8k_daisy_interrupt(device, state); |
| 185 | 185 | } |
| 186 | 186 | |
| 187 | static UINT8 memory_read_byte(address_space *space, offs_t address) { return space->read_byte(address); } | |
| 188 | static void memory_write_byte(address_space *space, offs_t address, UINT8 data) { space->write_byte(address, data); } | |
| 189 | ||
| 187 | 190 | static Z80DMA_INTERFACE( p8k_dma_intf ) |
| 188 | 191 | { |
| 189 | 192 | DEVCB_LINE(p8k_dma_irq_w), |
| r8806 | r8807 | |
|---|---|---|
| 56 | 56 | { |
| 57 | 57 | bw12_state *state = machine->driver_data<bw12_state>(); |
| 58 | 58 | |
| 59 | | |
| 59 | | |
| 60 | 60 | |
| 61 | 61 | switch (state->bank) |
| 62 | 62 | { |
| r8806 | r8807 | |
|---|---|---|
| 9 | 9 | #include "machine/beta.h" |
| 10 | 10 | #include "devices/messram.h" |
| 11 | 11 | |
| 12 | ||
| 12 | ||
| 13 | 13 | { |
| 14 | spectrum_state *state = space->machine->driver_data<spectrum_state>(); | |
| 15 | running_device *beta = space->machine->device(BETA_DISK_TAG); | |
| 16 | UINT16 pc = cpu_get_reg(space->machine->device("maincpu"), STATE_GENPCBASE); | |
| 17 | ||
| 14 | spectrum_state *state = machine->driver_data<spectrum_state>(); | |
| 15 | running_device *beta = machine->device(BETA_DISK_TAG); | |
| 16 | UINT16 pc = cpu_get_reg(machine->device("maincpu"), STATE_GENPCBASE); | |
| 17 | address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); | |
| 18 | ||
| 18 | 19 | if (beta->started() && betadisk_is_active(beta)) |
| 19 | 20 | { |
| 20 | 21 | if (pc >= 0x4000) |
| r8806 | r8807 | |
| 22 | 23 | state->ROMSelection = ((state->port_7ffd_data>>4) & 0x01) ? 1 : 0; |
| 23 | 24 | betadisk_disable(beta); |
| 24 | 25 | memory_unmap_write(space, 0x0000, 0x3fff, 0, 0); |
| 25 | memory_set_bankptr( | |
| 26 | memory_set_bankptr( | |
| 26 | 27 | } |
| 27 | 28 | } else if (((pc & 0xff00) == 0x3d00) && (state->ROMSelection==1)) |
| 28 | 29 | { |
| r8806 | r8807 | |
| 35 | 36 | { |
| 36 | 37 | memory_unmap_write(space, 0x0000, 0x3fff, 0, 0); |
| 37 | 38 | if (state->ROMSelection == 3) { |
| 38 | if (beta->started()) | |
| 39 | direct->raw = direct->decrypted = memory_region(space->machine, "beta:beta"); | |
| 39 | if (beta->started()) { | |
| 40 | direct.explicit_configure(0x0000, 0x3fff, 0x3fff, memory_region(machine, "beta:beta")); | |
| 41 | memory_set_bankptr(machine, "bank1", memory_region(machine, "beta:beta")); | |
| 42 | } | |
| 40 | 43 | } else { |
| 41 | direct->raw = direct->decrypted = memory_region(space->machine, "maincpu") + 0x010000 + (state->ROMSelection<<14); | |
| 42 | } | |
| 43 | memory_set_bankptr(space->machine, "bank1", direct->raw); | |
| 44 | direct.explicit_configure(0x0000, 0x3fff, 0x3fff, memory_region(machine, "maincpu") + 0x010000 + (state->ROMSelection<<14)); | |
| 45 | memory_set_bankptr(machine, "bank1", memory_region(machine, "maincpu") + 0x010000 + (state->ROMSelection<<14)); | |
| 46 | } | |
| 44 | 47 | return ~0; |
| 45 | 48 | } |
| 46 | 49 | return address; |
| r8806 | r8807 | |
| 105 | 108 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 106 | 109 | UINT8 *messram = messram_get_ptr(machine->device("messram")); |
| 107 | 110 | running_device *beta = machine->device(BETA_DISK_TAG); |
| 108 | | |
| 111 | | |
| 109 | 112 | |
| 110 | 113 | memory_install_read_bank(space, 0x0000, 0x3fff, 0, 0, "bank1"); |
| 111 | 114 | memory_unmap_write(space, 0x0000, 0x3fff, 0, 0); |
| r8806 | r8807 | |
| 115 | 118 | betadisk_clear_status(beta); |
| 116 | 119 | } |
| 117 | 120 | |
| 118 | | |
| 121 | space-> | |
| 119 | 122 | |
| 120 | 123 | memset(messram,0,128*1024); |
| 121 | 124 |
| r8806 | r8807 | |
|---|---|---|
| 88 | 88 | |
| 89 | 89 | static WRITE8_HANDLER( bankswitch_w ) |
| 90 | 90 | { |
| 91 | | |
| 91 | | |
| 92 | 92 | |
| 93 | 93 | switch (offset) |
| 94 | 94 | { |
| r8806 | r8807 | |
| 182 | 182 | |
| 183 | 183 | static VIDEO_UPDATE( prestige ) |
| 184 | 184 | { |
| 185 | | |
| 185 | | |
| 186 | 186 | UINT16 addr = 0xe000; |
| 187 | 187 | |
| 188 | 188 | for (int y = 0; y < 100; y++) |
| 189 | 189 | { |
| 190 | 190 | for (int sx = 0; sx < 30; sx++) |
| 191 | 191 | { |
| 192 | UINT8 data = | |
| 192 | UINT8 data = pr | |
| 193 | 193 | |
| 194 | 194 | for (int x = 0; x < 8; x++) |
| 195 | 195 | { |
| r8806 | r8807 | |
|---|---|---|
| 92 | 92 | |
| 93 | 93 | static WRITE8_HANDLER( ram_bank_w ) |
| 94 | 94 | { |
| 95 | | |
| 95 | | |
| 96 | 96 | UINT8 bank = BIT(data,2); |
| 97 | 97 | memory_install_write_bank(space_prg, 0x0000, 0x3fff, 0, 0, "bank1"); |
| 98 | 98 | |
| r8806 | r8807 | |
| 187 | 187 | |
| 188 | 188 | static MACHINE_RESET(pce220) |
| 189 | 189 | { |
| 190 | | |
| 190 | | |
| 191 | 191 | memory_unmap_write(space, 0x0000, 0x3fff, 0, 0); |
| 192 | 192 | memory_set_bankptr(machine, "bank1", memory_region(machine, "user1") + 0x0000); |
| 193 | 193 | } |
| r8806 | r8807 | |
|---|---|---|
| 370 | 370 | |
| 371 | 371 | static void pcw16_set_bank_handlers(running_machine *machine, int bank, PCW16_RAM_TYPE type) |
| 372 | 372 | { |
| 373 | | |
| 373 | | |
| 374 | 374 | |
| 375 | 375 | switch (type) { |
| 376 | 376 | case PCW16_MEM_ROM: |
| r8806 | r8807 | |
|---|---|---|
| 152 | 152 | static void prof80_bankswitch(running_machine *machine) |
| 153 | 153 | { |
| 154 | 154 | prof80_state *state = machine->driver_data<prof80_state>(); |
| 155 | | |
| 155 | | |
| 156 | 156 | UINT8 *ram = messram_get_ptr(machine->device("messram")); |
| 157 | 157 | UINT8 *rom = memory_region(machine, Z80_TAG); |
| 158 | 158 | int bank; |
| r8806 | r8807 | |
|---|---|---|
| 17 | 17 | #include "sound/ay8910.h" |
| 18 | 18 | #include "sound/dac.h" |
| 19 | 19 | |
| 20 | UINT8 *gce_vectorram; | |
| 21 | size_t gce_vectorram_size; | |
| 22 | ||
| 20 | 23 | static ADDRESS_MAP_START(vectrex_map, ADDRESS_SPACE_PROGRAM, 8) |
| 21 | 24 | AM_RANGE(0x0000, 0x7fff) AM_ROM |
| 22 | AM_RANGE(0xc800, 0xcbff) AM_RAM AM_MIRROR(0x0400) AM_BASE(&vectorram) AM_SIZE(&vectorram_size) | |
| 25 | AM_RANGE(0xc800, 0xcbff) AM_RAM AM_MIRROR(0x0400) AM_BASE(&gce_vectorram) AM_SIZE(&gce_vectorram_size) | |
| 23 | 26 | AM_RANGE(0xd000, 0xd7ff) AM_READWRITE(vectrex_via_r, vectrex_via_w) |
| 24 | 27 | AM_RANGE(0xe000, 0xffff) AM_ROM |
| 25 | 28 | ADDRESS_MAP_END |
| r8806 | r8807 | |
| 177 | 180 | AM_RANGE(0x0000, 0x7fff) AM_ROM |
| 178 | 181 | AM_RANGE(0x8000, 0x87ff) AM_RAM AM_BASE_SIZE_GENERIC(nvram) |
| 179 | 182 | AM_RANGE(0xa000, 0xa000) AM_WRITE(raaspec_led_w) |
| 180 | AM_RANGE(0xc800, 0xcbff) AM_RAM AM_MIRROR(0x0400) AM_BASE(&vectorram) AM_SIZE(&vectorram_size) | |
| 183 | AM_RANGE(0xc800, 0xcbff) AM_RAM AM_MIRROR(0x0400) AM_BASE(&gce_vectorram) AM_SIZE(&gce_vectorram_size) | |
| 181 | 184 | AM_RANGE(0xd000, 0xd7ff) AM_READWRITE (vectrex_via_r, vectrex_via_w) |
| 182 | 185 | AM_RANGE(0xe000, 0xffff) AM_ROM |
| 183 | 186 | ADDRESS_MAP_END |
| r8806 | r8807 | |
|---|---|---|
| 140 | 140 | static QUICKLOAD_LOAD( lynx ) |
| 141 | 141 | { |
| 142 | 142 | running_device *cpu = image.device().machine->device("maincpu"); |
| 143 | | |
| 143 | | |
| 144 | 144 | UINT8 *data = NULL; |
| 145 | 145 | UINT8 *rom = memory_region(image.device().machine, "maincpu"); |
| 146 | 146 | UINT8 header[10]; // 80 08 dw Start dw Len B S 9 3 |
| r8806 | r8807 | |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | 169 | for (i = 0; i < length; i++) |
| 170 | | |
| 170 | space-> | |
| 171 | 171 | |
| 172 | 172 | free(data); |
| 173 | 173 | |
| 174 | 174 | rom[0x1fc] = start & 0xff; |
| 175 | 175 | rom[0x1fd] = start >> 8; |
| 176 | memory_write_byte(space, 0x1fc, start & 0xff); | |
| 177 | memory_write_byte(space, 0x1fd, start >> 8); | |
| 176 | space->write_byte(0x1fc, start & 0xff); | |
| 177 | space->write_byte(0x1fd, start >> 8); | |
| 178 | 178 | |
| 179 | 179 | lynx_crc_keyword((device_image_interface&)*image.device().machine->device("quickload")); |
| 180 | 180 |
| r8806 | r8807 | |
|---|---|---|
| 217 | 217 | /* install expansion memory if available */ |
| 218 | 218 | if (messram_get_size(machine->device("messram")) > 0x1000) |
| 219 | 219 | { |
| 220 | | |
| 220 | | |
| 221 | 221 | |
| 222 | 222 | memory_install_readwrite_bank(space, 0x4000, 0x4000 + messram_get_size(machine->device("messram")) - 0x1000 - 1, 0, 0, "bank1"); |
| 223 | 223 | memory_set_bankptr(machine, "bank1", messram_get_ptr(machine->device("messram"))); |
| r8806 | r8807 | |
|---|---|---|
| 36 | 36 | #define keyb_press(_val_,_charset_) \ |
| 37 | 37 | if(input_code_pressed(machine, _val_)) \ |
| 38 | 38 | { \ |
| 39 | memory_write_byte(ram_space,0xfda4,0x01); \ | |
| 40 | memory_write_byte(ram_space,0xfce1,_charset_); \ | |
| 39 | ram_space->write_byte(0xfda4,0x01); \ | |
| 40 | ram_space->write_byte(0xfce1,_charset_); \ | |
| 41 | 41 | } \ |
| 42 | 42 | |
| 43 | 43 | #define keyb_shift_press(_val_,_charset_) \ |
| 44 | 44 | if(input_code_pressed(machine, _val_) && input_code_pressed(machine, KEYCODE_LSHIFT)) \ |
| 45 | 45 | { \ |
| 46 | memory_write_byte(ram_space,0xfda4,0x01); \ | |
| 47 | memory_write_byte(ram_space,0xfce1,_charset_); \ | |
| 46 | ram_space->write_byte(0xfda4,0x01); \ | |
| 47 | ram_space->write_byte(0xfce1,_charset_); \ | |
| 48 | 48 | } \ |
| 49 | 49 | |
| 50 | 50 | /* cheap kludge to use the keyboard without going nuts with the debugger ... */ |
| 51 | 51 | static void fake_keyboard_data(running_machine *machine) |
| 52 | 52 | { |
| 53 | | |
| 53 | | |
| 54 | 54 | |
| 55 | | |
| 55 | | |
| 56 | 56 | |
| 57 | 57 | keyb_press(KEYCODE_Z, 'z'); |
| 58 | 58 | keyb_press(KEYCODE_X, 'x'); |
| r8806 | r8807 | |
| 378 | 378 | |
| 379 | 379 | if(mio_sel) |
| 380 | 380 | { |
| 381 | | |
| 381 | | |
| 382 | 382 | mio_sel = 0; |
| 383 | 383 | //printf("%08x\n",offset); |
| 384 | 384 | //return 0x0d; // hack: this is used for reading the keyboard data, we can fake it a little ... (modify fda4) |
| 385 | return me | |
| 385 | return ram_space->r | |
| 386 | 386 | } |
| 387 | 387 | |
| 388 | 388 | io_port = offset & 0xff; //trim down to 8-bit bus |
| r8806 | r8807 | |
| 411 | 411 | |
| 412 | 412 | if(mio_sel) |
| 413 | 413 | { |
| 414 | | |
| 414 | | |
| 415 | 415 | mio_sel = 0; |
| 416 | | |
| 416 | | |
| 417 | 417 | return; |
| 418 | 418 | } |
| 419 | 419 |
| r8806 | r8807 | |
|---|---|---|
| 211 | 211 | void spectrum_plus3_update_memory(running_machine *machine) |
| 212 | 212 | { |
| 213 | 213 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 214 | | |
| 214 | | |
| 215 | 215 | UINT8 *messram = messram_get_ptr(machine->device("messram")); |
| 216 | 216 | |
| 217 | 217 | if (state->port_7ffd_data & 8) |
| r8806 | r8807 | |
|---|---|---|
| 394 | 394 | static INTERRUPT_GEN( apexc_interrupt ) |
| 395 | 395 | { |
| 396 | 396 | apexc_state *state = device->machine->driver_data<apexc_state>(); |
| 397 | | |
| 397 | | |
| 398 | 398 | UINT32 edit_keys; |
| 399 | 399 | int control_keys; |
| 400 | 400 | |
| r8806 | r8807 | |
| 475 | 475 | |
| 476 | 476 | if (control_keys & panel_write) { |
| 477 | 477 | /* write memory */ |
| 478 | | |
| 478 | space-> | |
| 479 | 479 | } |
| 480 | 480 | else { |
| 481 | 481 | /* read memory */ |
| 482 | state->panel_data_reg = | |
| 482 | state->panel_data_reg = space->r | |
| 483 | 483 | } |
| 484 | 484 | } |
| 485 | 485 |
| r8806 | r8807 | |
|---|---|---|
| 2481 | 2481 | |
| 2482 | 2482 | static MACHINE_START( x68000 ) |
| 2483 | 2483 | { |
| 2484 | | |
| 2484 | | |
| 2485 | 2485 | /* Install RAM handlers */ |
| 2486 | 2486 | x68k_spriteram = (UINT16*)memory_region(machine, "user1"); |
| 2487 | 2487 | memory_install_read16_handler(space,0x000000,0xbffffb,0xffffffff,0,(read16_space_func)x68k_emptyram_r); |
| r8806 | r8807 | |
| 2511 | 2511 | |
| 2512 | 2512 | static MACHINE_START( x68030 ) |
| 2513 | 2513 | { |
| 2514 | | |
| 2514 | | |
| 2515 | 2515 | /* Install RAM handlers */ |
| 2516 | 2516 | x68k_spriteram = (UINT16*)memory_region(machine, "user1"); |
| 2517 | 2517 | memory_install_read32_handler(space,0x000000,0xbffffb,0xffffffff,0,(read32_space_func)x68k_rom0_r); |
| r8806 | r8807 | |
|---|---|---|
| 89 | 89 | static MC6845_UPDATE_ROW( victor9k_update_row ) |
| 90 | 90 | { |
| 91 | 91 | victor9k_state *state = device->machine->driver_data<victor9k_state>(); |
| 92 | | |
| 92 | | |
| 93 | 93 | |
| 94 | 94 | if (BIT(ma, 13)) |
| 95 | 95 | { |
| r8806 | r8807 | |
| 103 | 103 | { |
| 104 | 104 | UINT16 code = (state->video_ram[video_ram_addr + 1] << 8) | state->video_ram[video_ram_addr]; |
| 105 | 105 | UINT32 char_ram_addr = (BIT(ma, 12) << 16) | ((code & 0xff) << 5) | (ra << 1); |
| 106 | UINT16 data = | |
| 106 | UINT16 data = pr | |
| 107 | 107 | |
| 108 | 108 | for (int x = 0; x <= 10; x++) |
| 109 | 109 | { |
| r8806 | r8807 | |
| 987 | 987 | state->floppy[1].image = machine->device(FLOPPY_1); |
| 988 | 988 | |
| 989 | 989 | /* memory banking */ |
| 990 | | |
| 990 | | |
| 991 | 991 | UINT8 *ram = messram_get_ptr(machine->device("messram")); |
| 992 | 992 | int ram_size = messram_get_size(machine->device("messram")); |
| 993 | 993 |
| r8806 | r8807 | |
|---|---|---|
| 406 | 406 | i8257_hlda_w(device, state); |
| 407 | 407 | } |
| 408 | 408 | |
| 409 | static UINT8 memory_read_byte(address_space *space, offs_t address) { return space->read_byte(address); } | |
| 410 | static void memory_write_byte(address_space *space, offs_t address, UINT8 data) { space->write_byte(address, data); } | |
| 411 | ||
| 409 | 412 | static I8257_INTERFACE( pc8001_8257_intf ) |
| 410 | 413 | { |
| 411 | 414 | DEVCB_LINE(hrq_w), |
| r8806 | r8807 | |
| 431 | 434 | static MACHINE_START( pc8001 ) |
| 432 | 435 | { |
| 433 | 436 | pc8001_state *state = machine->driver_data<pc8001_state>(); |
| 434 | | |
| 437 | | |
| 435 | 438 | running_device *messram = machine->device("messram"); |
| 436 | 439 | |
| 437 | 440 | /* look up devices */ |
| r8806 | r8807 | |
|---|---|---|
| 471 | 471 | } |
| 472 | 472 | |
| 473 | 473 | /* helper function to map rom capsules */ |
| 474 | static void install_rom_capsule( | |
| 474 | static void install_rom_capsule( | |
| 475 | 475 | { |
| 476 | 476 | px4_state *px4 = space->machine->driver_data<px4_state>(); |
| 477 | 477 | |
| r8806 | r8807 | |
| 501 | 501 | static WRITE8_HANDLER( px4_bankr_w ) |
| 502 | 502 | { |
| 503 | 503 | px4_state *px4 = space->machine->driver_data<px4_state>(); |
| 504 | | |
| 504 | | |
| 505 | 505 | |
| 506 | 506 | if (VERBOSE) |
| 507 | 507 | logerror("%s: px4_bankr_w (0x%02x)\n", cpuexec_describe_context(space->machine), data); |
| r8806 | r8807 | |
|---|---|---|
| 228 | 228 | { |
| 229 | 229 | spectrum_state *state = machine->driver_data<spectrum_state>(); |
| 230 | 230 | UINT8 *messram = messram_get_ptr(machine->device("messram")); |
| 231 | | |
| 231 | | |
| 232 | 232 | unsigned char *ChosenROM, *ExROM, *DOCK; |
| 233 | 233 | |
| 234 | 234 | DOCK = timex_cart_data; |
| r8806 | r8807 | |
|---|---|---|
| 44 | 44 | MEMORY / I/O |
| 45 | 45 | ***************************************************************************/ |
| 46 | 46 | |
| 47 | static void enterprise_update_memory_page( | |
| 47 | static void enterprise_update_memory_page( | |
| 48 | 48 | { |
| 49 | 49 | int start = (page - 1) * 0x4000; |
| 50 | 50 | int end = (page - 1) * 0x4000 + 0x3fff; |
| r8806 | r8807 | |
|---|---|---|
| 153 | 153 | static DRIVER_INIT( mc10 ) |
| 154 | 154 | { |
| 155 | 155 | mc10_state *mc10 = machine->driver_data<mc10_state>(); |
| 156 | | |
| 156 | | |
| 157 | 157 | |
| 158 | 158 | /* initialize keyboard strobe */ |
| 159 | 159 | mc10->keyboard_strobe = 0x00; |
| r8806 | r8807 | |
|---|---|---|
| 137 | 137 | static void bankswitch(running_machine *machine) |
| 138 | 138 | { |
| 139 | 139 | atom_state *state = machine->driver_data<atom_state>(); |
| 140 | | |
| 140 | | |
| 141 | 141 | |
| 142 | 142 | UINT8 *eprom = memory_region(machine, "a000") + (state->eprom << 12); |
| 143 | 143 |
| r8806 | r8807 | |
|---|---|---|
| 239 | 239 | { |
| 240 | 240 | apricot_state *apricot = machine->driver_data<apricot_state>(); |
| 241 | 241 | running_device *maincpu = machine->device("maincpu"); |
| 242 | | |
| 242 | | |
| 243 | 243 | |
| 244 | 244 | UINT8 *ram = messram_get_ptr(machine->device("messram")); |
| 245 | 245 | UINT32 ram_size = messram_get_size(machine->device("messram")); |
| r8806 | r8807 | |
|---|---|---|
| 290 | 290 | static MACHINE_START( lc80 ) |
| 291 | 291 | { |
| 292 | 292 | lc80_state *state = machine->driver_data<lc80_state>(); |
| 293 | | |
| 293 | | |
| 294 | 294 | |
| 295 | 295 | /* find devices */ |
| 296 | 296 | state->z80pio2 = machine->device(Z80PIO2_TAG); |
| r8806 | r8807 | |
|---|---|---|
| 486 | 486 | static DRIVER_INIT( rx78 ) |
| 487 | 487 | { |
| 488 | 488 | UINT32 ram_size = messram_get_size(machine->device("messram")); |
| 489 | | |
| 489 | | |
| 490 | 490 | |
| 491 | 491 | if(ram_size == 0x4000) |
| 492 | 492 | memory_unmap_readwrite(prg, 0x6000, 0xafff, 0, 0); |
| r8806 | r8807 | |
|---|---|---|
| 722 | 722 | { |
| 723 | 723 | UINT32 *regs = &s3c240x_dma_regs[dma<<3]; |
| 724 | 724 | UINT32 curr_tc, curr_src, curr_dst; |
| 725 | | |
| 725 | | |
| 726 | 726 | int dsz, inc_src, inc_dst, servmode; |
| 727 | 727 | const UINT32 ch_int[] = { INT_DMA0, INT_DMA1, INT_DMA2, INT_DMA3}; |
| 728 | 728 | verboselog( machine, 5, "DMA %d trigger\n", dma); |
| r8806 | r8807 | |
| 739 | 739 | curr_tc--; |
| 740 | 740 | switch (dsz) |
| 741 | 741 | { |
| 742 | case 0 : memory_write_byte( space, curr_dst, memory_read_byte( space, curr_src)); break; | |
| 743 | case 1 : memory_write_word( space, curr_dst, memory_read_word( space, curr_src)); break; | |
| 744 | case 2 : memory_write_dword( space, curr_dst, memory_read_dword( space, curr_src)); break; | |
| 742 | case 0 : space->write_byte( curr_dst, space->read_byte( curr_src)); break; | |
| 743 | case 1 : space->write_word( curr_dst, space->read_word( curr_src)); break; | |
| 744 | case 2 : space->write_dword( curr_dst, space->read_dword( curr_src)); break; | |
| 745 | 745 | } |
| 746 | 746 | if (inc_src == 0) curr_src += (1 << dsz); |
| 747 | 747 | if (inc_dst == 0) curr_dst += (1 << dsz); |
| r8806 | r8807 | |
|---|---|---|
| 245 | 245 | UINT8 abus; |
| 246 | 246 | }stv_irq; |
| 247 | 247 | |
| 248 | static void dma_direct_lv0(const address_space *space); /*DMA level 0 direct transfer function*/ | |
| 249 | static void dma_direct_lv1(const address_space *space); /*DMA level 1 direct transfer function*/ | |
| 250 | static void dma_direct_lv2(const address_space *space); /*DMA level 2 direct transfer function*/ | |
| 251 | static void dma_indirect_lv0(const address_space *space); /*DMA level 0 indirect transfer function*/ | |
| 252 | static void dma_indirect_lv1(const address_space *space); /*DMA level 1 indirect transfer function*/ | |
| 253 | static void dma_indirect_lv2(const address_space *space); /*DMA level 2 indirect transfer function*/ | |
| 248 | static void dma_direct_lv0(address_space *space); /*DMA level 0 direct transfer function*/ | |
| 249 | static void dma_direct_lv1(address_space *space); /*DMA level 1 direct transfer function*/ | |
| 250 | static void dma_direct_lv2(address_space *space); /*DMA level 2 direct transfer function*/ | |
| 251 | static void dma_indirect_lv0(address_space *space); /*DMA level 0 indirect transfer function*/ | |
| 252 | static void dma_indirect_lv1(address_space *space); /*DMA level 1 indirect transfer function*/ | |
| 253 | static void dma_indirect_lv2(address_space *space); /*DMA level 2 indirect transfer function*/ | |
| 254 | 254 | |
| 255 | 255 | |
| 256 | 256 | int minit_boost,sinit_boost; |
| r8806 | r8807 | |
| 488 | 488 | intback_stage++; |
| 489 | 489 | } |
| 490 | 490 | |
| 491 | static UINT8 stv_SMPC_r8( | |
| 491 | static UINT8 stv_SMPC_r8( | |
| 492 | 492 | { |
| 493 | 493 | int return_data; |
| 494 | 494 | |
| r8806 | r8807 | |
| 545 | 545 | return return_data; |
| 546 | 546 | } |
| 547 | 547 | |
| 548 | static void stv_SMPC_w8( | |
| 548 | static void stv_SMPC_w8( | |
| 549 | 549 | { |
| 550 | 550 | system_time systime; |
| 551 | 551 | UINT8 last; |
| r8806 | r8807 | |
| 1293 | 1293 | D2MV_0; |
| 1294 | 1294 | } |
| 1295 | 1295 | |
| 1296 | static void dma_direct_lv0( | |
| 1296 | static void dma_direct_lv0( | |
| 1297 | 1297 | { |
| 1298 | 1298 | static UINT32 tmp_src,tmp_dst,tmp_size; |
| 1299 | 1299 | if(LOG_SCU) logerror("DMA lv 0 transfer START\n" |
| r8806 | r8807 | |
| 1367 | 1367 | for (; scu_size_0 > 0; scu_size_0-=scu_dst_add_0) |
| 1368 | 1368 | { |
| 1369 | 1369 | if(scu_dst_add_0 == 2) |
| 1370 | | |
| 1370 | space-> | |
| 1371 | 1371 | else if(scu_dst_add_0 == 8) |
| 1372 | 1372 | { |
| 1373 | memory_write_word(space,scu_dst_0,memory_read_word(space,scu_src_0)); | |
| 1374 | memory_write_word(space,scu_dst_0+2,memory_read_word(space,scu_src_0)); | |
| 1375 | memory_write_word(space,scu_dst_0+4,memory_read_word(space,scu_src_0+2)); | |
| 1376 | memory_write_word(space,scu_dst_0+6,memory_read_word(space,scu_src_0+2)); | |
| 1373 | space->write_word(scu_dst_0,space->read_word(scu_src_0)); | |
| 1374 | space->write_word(scu_dst_0+2,space->read_word(scu_src_0)); | |
| 1375 | space->write_word(scu_dst_0+4,space->read_word(scu_src_0+2)); | |
| 1376 | space->write_word(scu_dst_0+6,space->read_word(scu_src_0+2)); | |
| 1377 | 1377 | } |
| 1378 | 1378 | else |
| 1379 | 1379 | { |
| 1380 | memory_write_word(space,scu_dst_0,memory_read_word(space,scu_src_0)); | |
| 1381 | memory_write_word(space,scu_dst_0+2,memory_read_word(space,scu_src_0+2)); | |
| 1380 | space->write_word(scu_dst_0,space->read_word(scu_src_0)); | |
| 1381 | space->write_word(scu_dst_0+2,space->read_word(scu_src_0+2)); | |
| 1382 | 1382 | } |
| 1383 | 1383 | |
| 1384 | 1384 | scu_dst_0+=scu_dst_add_0; |
| r8806 | r8807 | |
| 1402 | 1402 | } |
| 1403 | 1403 | } |
| 1404 | 1404 | |
| 1405 | static void dma_direct_lv1( | |
| 1405 | static void dma_direct_lv1( | |
| 1406 | 1406 | { |
| 1407 | 1407 | static UINT32 tmp_src,tmp_dst,tmp_size; |
| 1408 | 1408 | if(LOG_SCU) logerror("DMA lv 1 transfer START\n" |
| r8806 | r8807 | |
| 1476 | 1476 | for (; scu_size_1 > 0; scu_size_1-=scu_dst_add_1) |
| 1477 | 1477 | { |
| 1478 | 1478 | if(scu_dst_add_1 == 2) |
| 1479 | | |
| 1479 | space-> | |
| 1480 | 1480 | else |
| 1481 | 1481 | { |
| 1482 | memory_write_word(space,scu_dst_1,memory_read_word(space,scu_src_1)); | |
| 1483 | memory_write_word(space,scu_dst_1+2,memory_read_word(space,scu_src_1+2)); | |
| 1482 | space->write_word(scu_dst_1,space->read_word(scu_src_1)); | |
| 1483 | space->write_word(scu_dst_1+2,space->read_word(scu_src_1+2)); | |
| 1484 | 1484 | } |
| 1485 | 1485 | |
| 1486 | 1486 | scu_dst_1+=scu_dst_add_1; |
| r8806 | r8807 | |
| 1503 | 1503 | } |
| 1504 | 1504 | } |
| 1505 | 1505 | |
| 1506 | static void dma_direct_lv2( | |
| 1506 | static void dma_direct_lv2( | |
| 1507 | 1507 | { |
| 1508 | 1508 | static UINT32 tmp_src,tmp_dst,tmp_size; |
| 1509 | 1509 | if(LOG_SCU) logerror("DMA lv 2 transfer START\n" |
| r8806 | r8807 | |
| 1577 | 1577 | for (; scu_size_2 > 0; scu_size_2-=scu_dst_add_2) |
| 1578 | 1578 | { |
| 1579 | 1579 | if(scu_dst_add_2 == 2) |
| 1580 | | |
| 1580 | space-> | |
| 1581 | 1581 | else |
| 1582 | 1582 | { |
| 1583 | memory_write_word(space,scu_dst_2,memory_read_word(space,scu_src_2)); | |
| 1584 | memory_write_word(space,scu_dst_2+2,memory_read_word(space,scu_src_2+2)); | |
| 1583 | space->write_word(scu_dst_2,space->read_word(scu_src_2)); | |
| 1584 | space->write_word(scu_dst_2+2,space->read_word(scu_src_2+2)); | |
| 1585 | 1585 | } |
| 1586 | 1586 | |
| 1587 | 1587 | scu_dst_2+=scu_dst_add_2; |
| r8806 | r8807 | |
| 1604 | 1604 | } |
| 1605 | 1605 | } |
| 1606 | 1606 | |
| 1607 | static void dma_indirect_lv0( | |
| 1607 | static void dma_indirect_lv0( | |
| 1608 | 1608 | { |
| 1609 | 1609 | /*Helper to get out of the cycle*/ |
| 1610 | 1610 | UINT8 job_done = 0; |
| r8806 | r8807 | |
| 1621 | 1621 | tmp_src = scu_index_0; |
| 1622 | 1622 | |
| 1623 | 1623 | /*Thanks for Runik of Saturnin for pointing this out...*/ |
| 1624 | scu_size_0 = memory_read_dword(space,scu_index_0); | |
| 1625 | scu_src_0 = memory_read_dword(space,scu_index_0+8); | |
| 1626 | scu_dst_0 = memory_read_dword(space,scu_index_0+4); | |
| 1624 | scu_size_0 = space->read_dword(scu_index_0); | |
| 1625 | scu_src_0 = space->read_dword(scu_index_0+8); | |
| 1626 | scu_dst_0 = space->read_dword(scu_index_0+4); | |
| 1627 | 1627 | |
| 1628 | 1628 | /*Indirect Mode end factor*/ |
| 1629 | 1629 | if(scu_src_0 & 0x80000000) |
| r8806 | r8807 | |
| 1647 | 1647 | for (; scu_size_0 > 0; scu_size_0-=scu_dst_add_0) |
| 1648 | 1648 | { |
| 1649 | 1649 | if(scu_dst_add_0 == 2) |
| 1650 | | |
| 1650 | space-> | |
| 1651 | 1651 | else |
| 1652 | 1652 | { |
| 1653 | 1653 | /* some games, eg columns97 are a bit weird, I'm not sure this is correct |
| r8806 | r8807 | |
| 1655 | 1655 | can't access 2 byte boundaries, and the end of the sprite list never gets marked, |
| 1656 | 1656 | the length of the transfer is also set to a 2 byte boundary, maybe the add values |
| 1657 | 1657 | should be different, I don't know */ |
| 1658 | memory_write_word(space,scu_dst_0,memory_read_word(space,scu_src_0)); | |
| 1659 | memory_write_word(space,scu_dst_0+2,memory_read_word(space,scu_src_0+2)); | |
| 1658 | space->write_word(scu_dst_0,space->read_word(scu_src_0)); | |
| 1659 | space->write_word(scu_dst_0+2,space->read_word(scu_src_0+2)); | |
| 1660 | 1660 | } |
| 1661 | 1661 | scu_dst_0+=scu_dst_add_0; |
| 1662 | 1662 | scu_src_0+=scu_src_add_0; |
| 1663 | 1663 | } |
| 1664 | 1664 | |
| 1665 | //if(DRUP(0)) memory_write_dword(space,tmp_src+8,scu_src_0|job_done ? 0x80000000 : 0); | |
| 1666 | //if(DWUP(0)) memory_write_dword(space,tmp_src+4,scu_dst_0); | |
| 1665 | //if(DRUP(0)) space->write_dword(tmp_src+8,scu_src_0|job_done ? 0x80000000 : 0); | |
| 1666 | //if(DWUP(0)) space->write_dword(tmp_src+4,scu_dst_0); | |
| 1667 | 1667 | |
| 1668 | 1668 | scu_index_0 = tmp_src+0xc; |
| 1669 | 1669 | |
| r8806 | r8807 | |
| 1672 | 1672 | timer_set(space->machine, ATTOTIME_IN_USEC(300), NULL, 0, dma_lv0_ended); |
| 1673 | 1673 | } |
| 1674 | 1674 | |
| 1675 | static void dma_indirect_lv1( | |
| 1675 | static void dma_indirect_lv1( | |
| 1676 | 1676 | { |
| 1677 | 1677 | /*Helper to get out of the cycle*/ |
| 1678 | 1678 | UINT8 job_done = 0; |
| r8806 | r8807 | |
| 1688 | 1688 | do{ |
| 1689 | 1689 | tmp_src = scu_index_1; |
| 1690 | 1690 | |
| 1691 | scu_size_1 = memory_read_dword(space,scu_index_1); | |
| 1692 | scu_src_1 = memory_read_dword(space,scu_index_1+8); | |
| 1693 | scu_dst_1 = memory_read_dword(space,scu_index_1+4); | |
| 1691 | scu_size_1 = space->read_dword(scu_index_1); | |
| 1692 | scu_src_1 = space->read_dword(scu_index_1+8); | |
| 1693 | scu_dst_1 = space->read_dword(scu_index_1+4); | |
| 1694 | 1694 | |
| 1695 | 1695 | /*Indirect Mode end factor*/ |
| 1696 | 1696 | if(scu_src_1 & 0x80000000) |
| r8806 | r8807 | |
| 1716 | 1716 | { |
| 1717 | 1717 | |
| 1718 | 1718 | if(scu_dst_add_1 == 2) |
| 1719 | | |
| 1719 | space-> | |
| 1720 | 1720 | else |
| 1721 | 1721 | { |
| 1722 | 1722 | /* some games, eg columns97 are a bit weird, I'm not sure this is correct |
| r8806 | r8807 | |
| 1724 | 1724 | can't access 2 byte boundaries, and the end of the sprite list never gets marked, |
| 1725 | 1725 | the length of the transfer is also set to a 2 byte boundary, maybe the add values |
| 1726 | 1726 | should be different, I don't know */ |
| 1727 | memory_write_word(space,scu_dst_1,memory_read_word(space,scu_src_1)); | |
| 1728 | memory_write_word(space,scu_dst_1+2,memory_read_word(space,scu_src_1+2)); | |
| 1727 | space->write_word(scu_dst_1,space->read_word(scu_src_1)); | |
| 1728 | space->write_word(scu_dst_1+2,space->read_word(scu_src_1+2)); | |
| 1729 | 1729 | } |
| 1730 | 1730 | scu_dst_1+=scu_dst_add_1; |
| 1731 | 1731 | scu_src_1+=scu_src_add_1; |
| 1732 | 1732 | } |
| 1733 | 1733 | |
| 1734 | //if(DRUP(1)) memory_write_dword(space,tmp_src+8,scu_src_1|job_done ? 0x80000000 : 0); | |
| 1735 | //if(DWUP(1)) memory_write_dword(space,tmp_src+4,scu_dst_1); | |
| 1734 | //if(DRUP(1)) space->write_dword(tmp_src+8,scu_src_1|job_done ? 0x80000000 : 0); | |
| 1735 | //if(DWUP(1)) space->write_dword(tmp_src+4,scu_dst_1); | |
| 1736 | 1736 | |
| 1737 | 1737 | scu_index_1 = tmp_src+0xc; |
| 1738 | 1738 | |
| r8806 | r8807 | |
| 1741 | 1741 | timer_set(space->machine, ATTOTIME_IN_USEC(300), NULL, 0, dma_lv1_ended); |
| 1742 | 1742 | } |
| 1743 | 1743 | |
| 1744 | static void dma_indirect_lv2( | |
| 1744 | static void dma_indirect_lv2( | |
| 1745 | 1745 | { |
| 1746 | 1746 | /*Helper to get out of the cycle*/ |
| 1747 | 1747 | UINT8 job_done = 0; |
| r8806 | r8807 | |
| 1757 | 1757 | do{ |
| 1758 | 1758 | tmp_src = scu_index_2; |
| 1759 | 1759 | |
| 1760 | scu_size_2 = memory_read_dword(space,scu_index_2); | |
| 1761 | scu_src_2 = memory_read_dword(space,scu_index_2+8); | |
| 1762 | scu_dst_2 = memory_read_dword(space,scu_index_2+4); | |
| 1760 | scu_size_2 = space->read_dword(scu_index_2); | |
| 1761 | scu_src_2 = space->read_dword(scu_index_2+8); | |
| 1762 | scu_dst_2 = space->read_dword(scu_index_2+4); | |
| 1763 | 1763 | |
| 1764 | 1764 | /*Indirect Mode end factor*/ |
| 1765 | 1765 | if(scu_src_2 & 0x80000000) |
| r8806 | r8807 | |
| 1783 | 1783 | for (; scu_size_2 > 0; scu_size_2-=scu_dst_add_2) |
| 1784 | 1784 | { |
| 1785 | 1785 | if(scu_dst_add_2 == 2) |
| 1786 | | |
| 1786 | space-> | |
| 1787 | 1787 | else |
| 1788 | 1788 | { |
| 1789 | 1789 | /* some games, eg columns97 are a bit weird, I'm not sure this is correct |
| r8806 | r8807 | |
| 1791 | 1791 | can't access 2 byte boundaries, and the end of the sprite list never gets marked, |
| 1792 | 1792 | the length of the transfer is also set to a 2 byte boundary, maybe the add values |
| 1793 | 1793 | should be different, I don't know */ |
| 1794 | memory_write_word(space,scu_dst_2,memory_read_word(space,scu_src_2)); | |
| 1795 | memory_write_word(space,scu_dst_2+2,memory_read_word(space,scu_src_2+2)); | |
| 1794 | space->write_word(scu_dst_2,space->read_word(scu_src_2)); | |
| 1795 | space->write_word(scu_dst_2+2,space->read_word(scu_src_2+2)); | |
| 1796 | 1796 | } |
| 1797 | 1797 | |
| 1798 | 1798 | scu_dst_2+=scu_dst_add_2; |
| 1799 | 1799 | scu_src_2+=scu_src_add_2; |
| 1800 | 1800 | } |
| 1801 | 1801 | |
| 1802 | //if(DRUP(2)) memory_write_dword(space,tmp_src+8,scu_src_2|job_done ? 0x80000000 : 0); | |
| 1803 | //if(DWUP(2)) memory_write_dword(space,tmp_src+4,scu_dst_2); | |
| 1802 | //if(DRUP(2)) space->write_dword(tmp_src+8,scu_src_2|job_done ? 0x80000000 : 0); | |
| 1803 | //if(DWUP(2)) space->write_dword(tmp_src+4,scu_dst_2); | |
| 1804 | 1804 | |
| 1805 | 1805 | scu_index_2 = tmp_src+0xc; |
| 1806 | 1806 |
| r8806 | r8807 | |
|---|---|---|
| 1153 | 1153 | { |
| 1154 | 1154 | if(data & 0x1000) |
| 1155 | 1155 | { |
| 1156 | | |
| 1156 | space-> | |
| 1157 | 1157 | acan_dma_regs->dest[ch]+=2; |
| 1158 | 1158 | acan_dma_regs->source[ch]+=2; |
| 1159 | 1159 | if(data & 0x0100) |
| r8806 | r8807 | |
| 1162 | 1162 | } |
| 1163 | 1163 | else |
| 1164 | 1164 | { |
| 1165 | | |
| 1165 | space-> | |
| 1166 | 1166 | acan_dma_regs->dest[ch]++; |
| 1167 | 1167 | acan_dma_regs->source[ch]++; |
| 1168 | 1168 | } |
| r8806 | r8807 | |
| 1219 | 1219 | |
| 1220 | 1220 | case 0x410: // Sound IRQ enable |
| 1221 | 1221 | data = state->sound_irq_enable_reg; |
| 1222 | if(!space->debugger_access) verboselog(state->hack_68k_to_6502_access ? "maincpu" : "soundcpu", space->machine, 0, "supracan_soundreg_r: IRQ enable: %04x\n", data); | |
| 1223 | if(!space->debugger_access) | |
| 1222 | if(!space->debugger_access()) verboselog(state->hack_68k_to_6502_access ? "maincpu" : "soundcpu", space->machine, 0, "supracan_soundreg_r: IRQ enable: %04x\n", data); | |
| 1223 | if(!space->debugger_access()) | |
| 1224 | 1224 | { |
| 1225 | 1225 | if(state->sound_irq_enable_reg & state->sound_irq_source_reg) |
| 1226 | 1226 | { |
| r8806 | r8807 | |
| 1235 | 1235 | case 0x411: // Sound IRQ source |
| 1236 | 1236 | data = state->sound_irq_source_reg; |
| 1237 | 1237 | state->sound_irq_source_reg = 0; |
| 1238 | if(!space->debugger_access) verboselog(state->hack_68k_to_6502_access ? "maincpu" : "soundcpu", space->machine, 3, "supracan_soundreg_r: IRQ source: %04x\n", data); | |
| 1239 | if(!space->debugger_access) | |
| 1238 | if(!space->debugger_access()) verboselog(state->hack_68k_to_6502_access ? "maincpu" : "soundcpu", space->machine, 3, "supracan_soundreg_r: IRQ source: %04x\n", data); | |
| 1239 | if(!space->debugger_access()) | |
| 1240 | 1240 | { |
| 1241 | 1241 | cpu_set_input_line(space->machine->device("soundcpu"), 0, CLEAR_LINE); |
| 1242 | 1242 | } |
| 1243 | 1243 | break; |
| 1244 | 1244 | case 0x420: |
| 1245 | if(!space->debugger_access) verboselog(state->hack_68k_to_6502_access ? "maincpu" : "soundcpu", space->machine, 3, "supracan_soundreg_r: Sound hardware status? (not yet implemented): %02x\n", 0); | |
| 1245 | if(!space->debugger_access()) verboselog(state->hack_68k_to_6502_access ? "maincpu" : "soundcpu", space->machine, 3, "supracan_soundreg_r: Sound hardware status? (not yet implemented): %02x\n", 0); | |
| 1246 | 1246 | break; |
| 1247 | 1247 | case 0x422: |
| 1248 | if(!space->debugger_access) verboselog(state->hack_68k_to_6502_access ? "maincpu" : "soundcpu", space->machine, 3, "supracan_soundreg_r: Sound hardware data? (not yet implemented): %02x\n", 0); | |
| 1248 | if(!space->debugger_access()) verboselog(state->hack_68k_to_6502_access ? "maincpu" : "soundcpu", space->machine, 3, "supracan_soundreg_r: Sound hardware data? (not yet implemented): %02x\n", 0); | |
| 1249 | 1249 | break; |
| 1250 | 1250 | case 0x404: |
| 1251 | 1251 | case 0x405: |
| r8806 | r8807 | |
| 1256 | 1256 | default: |
| 1257 | 1257 | if(offset >= 0x300 && offset < 0x500) |
| 1258 | 1258 | { |
| 1259 | if(!space->debugger_access) verboselog(state->hack_68k_to_6502_access ? "maincpu" : "soundcpu", space->machine, 0, "supracan_soundreg_r: Unknown register %04x\n", offset); | |
| 1259 | if(!space->debugger_access()) verboselog(state->hack_68k_to_6502_access ? "maincpu" : "soundcpu", space->machine, 0, "supracan_soundreg_r: Unknown register %04x\n", offset); | |
| 1260 | 1260 | } |
| 1261 | 1261 | break; |
| 1262 | 1262 | } |
| r8806 | r8807 | |
| 1549 | 1549 | switch(offset) |
| 1550 | 1550 | { |
| 1551 | 1551 | case 0x00/2: // Video IRQ flags |
| 1552 | if(!space->debugger_access) | |
| 1552 | if(!space->debugger_access()) | |
| 1553 | 1553 | { |
| 1554 | 1554 | //verboselog("maincpu", space->machine, 0, "read video IRQ flags (%04x)\n", data); |
| 1555 | 1555 | cpu_set_input_line(space->machine->device("maincpu"), 7, CLEAR_LINE); |
| r8806 | r8807 | |
| 1561 | 1561 | data = 0; |
| 1562 | 1562 | break; |
| 1563 | 1563 | case 0x100/2: |
| 1564 | if(!space->debugger_access) verboselog("maincpu", space->machine, 0, "read tilemap_flags[0] (%04x)\n", data); | |
| 1564 | if(!space->debugger_access()) verboselog("maincpu", space->machine, 0, "read tilemap_flags[0] (%04x)\n", data); | |
| 1565 | 1565 | break; |
| 1566 | 1566 | case 0x106/2: |
| 1567 | if(!space->debugger_access) verboselog("maincpu", space->machine, 0, "read tilemap_scrolly[0] (%04x)\n", data); | |
| 1567 | if(!space->debugger_access()) verboselog("maincpu", space->machine, 0, "read tilemap_scrolly[0] (%04x)\n", data); | |
| 1568 | 1568 | break; |
| 1569 | 1569 | case 0x120/2: |
| 1570 | if(!space->debugger_access) verboselog("maincpu", space->machine, 0, "read tilemap_flags[1] (%04x)\n", data); | |
| 1570 | if(!space->debugger_access()) verboselog("maincpu", space->machine, 0, "read tilemap_flags[1] (%04x)\n", data); | |
| 1571 | 1571 | break; |
| 1572 | 1572 | default: |
| 1573 | if(!space->debugger_access) verboselog("maincpu", space->machine, 0, "supracan_video_r: Unknown register: %08x (%04x & %04x)\n", 0xf00000 + (offset << 1), data, mem_mask); | |
| 1573 | if(!space->debugger_access()) verboselog("maincpu", space->machine, 0, "supracan_video_r: Unknown register: %08x (%04x & %04x)\n", 0xf00000 + (offset << 1), data, mem_mask); | |
| 1574 | 1574 | break; |
| 1575 | 1575 | } |
| 1576 | 1576 | |
| r8806 | r8807 | |
| 1757 | 1757 | { |
| 1758 | 1758 | if(data & 0x0100) //dma 0x00 fill (or fixed value?) |
| 1759 | 1759 | { |
| 1760 | | |
| 1760 | space-> | |
| 1761 | 1761 | acan_sprdma_regs->dst+=2 * acan_sprdma_regs->dst_inc; |
| 1762 | 1762 | //memset(supracan_vram,0x00,0x020000); |
| 1763 | 1763 | } |
| 1764 | 1764 | else |
| 1765 | 1765 | { |
| 1766 | | |
| 1766 | space-> | |
| 1767 | 1767 | acan_sprdma_regs->dst+=2 * acan_sprdma_regs->dst_inc; |
| 1768 | 1768 | acan_sprdma_regs->src+=2 * acan_sprdma_regs->src_inc; |
| 1769 | 1769 | } |
| r8806 | r8807 | |
|---|---|---|
| 363 | 363 | |
| 364 | 364 | |
| 365 | 365 | /* install expansion memory*/ |
| 366 | | |
| 366 | | |
| 367 | 367 | UINT8 *ram = messram_get_ptr(machine->device("messram")); |
| 368 | 368 | UINT16 ram_size = messram_get_size(machine->device("messram")); |
| 369 | 369 |
| r8806 | r8807 | |
|---|---|---|
| 37 | 37 | * (note that in CP/J mode address 66 is used for FCB) |
| 38 | 38 | * |
| 39 | 39 | *************************************/ |
| 40 | ||
| 40 | ||
| 41 | 41 | { |
| 42 | spectrum_state *state = | |
| 42 | spectrum_state *state = | |
| 43 | 43 | if (state->ram_at_0000 && address == 0x66) |
| 44 | 44 | { |
| 45 | direct->raw = direct->decrypted = &state->df_on_databus; | |
| 46 | direct->bytemask = 0; | |
| 45 | direct.explicit_configure(0x66, 0x66, 0, &state->df_on_databus); | |
| 47 | 46 | return ~0; |
| 48 | 47 | } |
| 49 | 48 | return address; |
| r8806 | r8807 | |
| 505 | 504 | // this is a reset of ls175 in mmu |
| 506 | 505 | elwro800jr_mmu_w(machine, 0); |
| 507 | 506 | |
| 508 | | |
| 507 | | |
| 509 | 508 | } |
| 510 | 509 | |
| 511 | 510 | static const cassette_config elwro800jr_cassette_config = |
| r8806 | r8807 | |
|---|---|---|
| 96 | 96 | |
| 97 | 97 | static void avigo_setbank(running_machine *machine, int bank, void *address, read8_space_func rh, write8_space_func wh) |
| 98 | 98 | { |
| 99 | | |
| 99 | | |
| 100 | 100 | char bank_1[10]; |
| 101 | 101 | char bank_5[10]; |
| 102 | 102 | |
| r8806 | r8807 | |
| 302 | 302 | static void avigo_refresh_memory(running_machine *machine) |
| 303 | 303 | { |
| 304 | 304 | unsigned char *addr; |
| 305 | | |
| 305 | | |
| 306 | 306 | |
| 307 | 307 | switch (avigo_rom_bank_h) |
| 308 | 308 | { |
| r8806 | r8807 | |
| 396 | 396 | }; |
| 397 | 397 | |
| 398 | 398 | /* this is needed because this driver uses handlers in memory that gets executed */ |
| 399 | ||
| 399 | ||
| 400 | 400 | { |
| 401 | 401 | void *opbase_ptr; |
| 402 | 402 | |
| 403 | 403 | opbase_ptr = avigo_banked_opbase[address / 0x4000]; |
| 404 | 404 | if (opbase_ptr != NULL) |
| 405 | 405 | { |
| 406 | direct | |
| 406 | direct. | |
| 407 | 407 | address = ~0; |
| 408 | 408 | } |
| 409 | 409 | return address; |
| r8806 | r8807 | |
| 440 | 440 | /* clear */ |
| 441 | 441 | memset(messram_get_ptr(machine->device("messram")), 0, 128*1024); |
| 442 | 442 | |
| 443 | | |
| 443 | | |
| 444 | 444 | |
| 445 | 445 | addr = (unsigned char *)intelflash_getmemptr(0); |
| 446 | 446 | avigo_setbank(machine, 0, addr, avigo_flash_0x0000_read_handler, avigo_flash_0x0000_write_handler); |
| r8806 | r8807 | |
|---|---|---|
| 554 | 554 | { |
| 555 | 555 | /* preliminary implementation, doesn't use the contrast value */ |
| 556 | 556 | t68k_state *state = screen->machine->driver_data<t68k_state>(); |
| 557 | | |
| 557 | | |
| 558 | 558 | UINT8 width = screen->width(); |
| 559 | 559 | UINT8 height = screen->height(); |
| 560 | 560 | UINT8 x, y, b; |
| r8806 | r8807 | |
| 565 | 565 | for (y = 0; y < height; y++) |
| 566 | 566 | for (x = 0; x < width / 8; x++) |
| 567 | 567 | { |
| 568 | UINT8 s_byte= | |
| 568 | UINT8 s_byte= space->r | |
| 569 | 569 | for (b = 0; b<8; b++) |
| 570 | 570 | *BITMAP_ADDR16(bitmap, y, x * 8 + (7 - b)) = (BIT(s_byte, b) > 0) ? 0 : 1; |
| 571 | 571 | } |
| r8806 | r8807 | |
| 577 | 577 | MACHINE_START( ti68k ) |
| 578 | 578 | { |
| 579 | 579 | t68k_state *state = machine->driver_data<t68k_state>(); |
| 580 | | |
| 580 | | |
| 581 | 581 | UINT16 *rom = (UINT16 *)memory_region(space->machine, "maincpu"); |
| 582 | 582 | int i; |
| 583 | 583 |
| r8806 | r8807 | |
|---|---|---|
| 139 | 139 | static void xerox820_bankswitch(running_machine *machine, int bank) |
| 140 | 140 | { |
| 141 | 141 | xerox820_state *state = machine->driver_data<xerox820_state>(); |
| 142 | | |
| 142 | | |
| 143 | 143 | UINT8 *ram = messram_get_ptr(machine->device("messram")); |
| 144 | 144 | |
| 145 | 145 | if (bank) |
| r8806 | r8807 | |
| 160 | 160 | static void xerox820ii_bankswitch(running_machine *machine, int bank) |
| 161 | 161 | { |
| 162 | 162 | xerox820_state *state = machine->driver_data<xerox820_state>(); |
| 163 | | |
| 163 | | |
| 164 | 164 | UINT8 *ram = messram_get_ptr(machine->device("messram")); |
| 165 | 165 | |
| 166 | 166 | if (bank) |
| r8806 | r8807 | |
|---|---|---|
| 194 | 194 | static DEVICE_IMAGE_LOAD( vc4000_cart ) |
| 195 | 195 | { |
| 196 | 196 | running_machine *machine = image.device().machine; |
| 197 | | |
| 197 | | |
| 198 | 198 | UINT32 size; |
| 199 | 199 | |
| 200 | 200 | if (image.software_entry() == NULL) |
| r8806 | r8807 | |
| 375 | 375 | |
| 376 | 376 | QUICKLOAD_LOAD(vc4000) |
| 377 | 377 | { |
| 378 | | |
| 378 | | |
| 379 | 379 | int i; |
| 380 | 380 | int quick_addr = 0x08c0; |
| 381 | 381 | int quick_length; |
| r8806 | r8807 | |
| 399 | 399 | //if ((quick_addr + quick_length - 5) > 0x1000) |
| 400 | 400 | // return IMAGE_INIT_FAIL; |
| 401 | 401 | |
| 402 | memory_write_byte(space, 0x08be, quick_data[3]); | |
| 403 | memory_write_byte(space, 0x08bf, quick_data[4]); | |
| 402 | space->write_byte(0x08be, quick_data[3]); | |
| 403 | space->write_byte(0x08bf, quick_data[4]); | |
| 404 | 404 | |
| 405 | 405 | for (i = 0; i < quick_length - 5; i++) |
| 406 | 406 | { if ((quick_addr + i) < 0x1000) |
| 407 | | |
| 407 | space-> | |
| 408 | 408 | } |
| 409 | 409 | |
| 410 | 410 | logerror("quick loading at %.4x size:%.4x\n", quick_addr, (quick_length-5)); |
| r8806 | r8807 | |
|---|---|---|
| 265 | 265 | static void set_ram_mode(running_machine *machine) |
| 266 | 266 | { |
| 267 | 267 | cosmicos_state *state = machine->driver_data<cosmicos_state>(); |
| 268 | | |
| 268 | | |
| 269 | 269 | |
| 270 | 270 | if (state->ram_disable) |
| 271 | 271 | { |
| r8806 | r8807 | |
| 515 | 515 | static MACHINE_START( cosmicos ) |
| 516 | 516 | { |
| 517 | 517 | cosmicos_state *state = machine->driver_data<cosmicos_state>(); |
| 518 | | |
| 518 | | |
| 519 | 519 | |
| 520 | 520 | /* find devices */ |
| 521 | 521 | state->dm9368 = machine->device(DM9368_TAG); |
| r8806 | r8807 | |
| 652 | 652 | |
| 653 | 653 | /* System Drivers */ |
| 654 | 654 | |
| 655 | ||
| 655 | ||
| 656 | 656 | { |
| 657 | cosmicos_state *state = | |
| 657 | cosmicos_state *state = | |
| 658 | 658 | |
| 659 | 659 | if (state->boot) |
| 660 | 660 | { |
| r8806 | r8807 | |
| 667 | 667 | |
| 668 | 668 | static DRIVER_INIT( cosmicos ) |
| 669 | 669 | { |
| 670 | | |
| 670 | | |
| 671 | 671 | |
| 672 | | |
| 672 | pr | |
| 673 | 673 | } |
| 674 | 674 | |
| 675 | 675 | /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */ |
| r8806 | r8807 | |
|---|---|---|
| 421 | 421 | } |
| 422 | 422 | |
| 423 | 423 | /* Read/Write common */ |
| 424 | void io_rw( | |
| 424 | void io_rw( | |
| 425 | 425 | { |
| 426 | if (space->debugger_access) | |
| 426 | if (space->debugger_access()) | |
| 427 | 427 | return; |
| 428 | 428 | |
| 429 | 429 | switch (offset & 0xffc0) |
| r8806 | r8807 | |
|---|---|---|
| 141 | 141 | int ctrl; |
| 142 | 142 | int srcadd, dstadd; |
| 143 | 143 | UINT32 src, dst; |
| 144 | | |
| 144 | | |
| 145 | 145 | gba_state *state = machine->driver_data<gba_state>(); |
| 146 | 146 | |
| 147 | 147 | src = state->dma_src[ch]; |
| r8806 | r8807 | |
| 194 | 194 | dst &= 0xfffffffc; |
| 195 | 195 | |
| 196 | 196 | // 32-bit |
| 197 | | |
| 197 | space-> | |
| 198 | 198 | switch (dstadd) |
| 199 | 199 | { |
| 200 | 200 | case 0: // increment |
| r8806 | r8807 | |
| 231 | 231 | dst &= 0xfffffffe; |
| 232 | 232 | |
| 233 | 233 | // 16-bit |
| 234 | | |
| 234 | space-> | |
| 235 | 235 | switch (dstadd) |
| 236 | 236 | { |
| 237 | 237 | case 0: // increment |
| r8806 | r8807 | |
| 2457 | 2457 | |
| 2458 | 2458 | /* this emulates the GBA's hardware protection: the BIOS returns only zeros when the PC is not in it, |
| 2459 | 2459 | and some games verify that as a protection check (notably Metroid Fusion) */ |
| 2460 | ||
| 2460 | ||
| 2461 | 2461 | { |
| 2462 | 2462 | if (address > 0x4000) |
| 2463 | 2463 | { |
| 2464 | memory_set_bankptr( | |
| 2464 | memory_set_bankptr( | |
| 2465 | 2465 | } |
| 2466 | 2466 | else |
| 2467 | 2467 | { |
| 2468 | memory_set_bankptr( | |
| 2468 | memory_set_bankptr( | |
| 2469 | 2469 | } |
| 2470 | 2470 | |
| 2471 | 2471 | return address; |
| r8806 | r8807 | |
| 2473 | 2473 | |
| 2474 | 2474 | static DRIVER_INIT(gbadv) |
| 2475 | 2475 | { |
| 2476 | | |
| 2476 | | |
| 2477 | 2477 | } |
| 2478 | 2478 | |
| 2479 | 2479 | /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */ |
| Previous | 15994 Revisions | Next |