summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
diff options
context:
space:
mode:
authorGravatarGravatar Aaron Giles <aaron@aarongiles.com>2007-12-17 15:19:59 +0000
committerGravatarGravatar Aaron Giles <aaron@aarongiles.com>2007-12-17 15:19:59 +0000
commit7b77f1218624ea26dbb2efd85a19f795f5d4e02e (patch)
tree19209304095572b4fd61c2a2d6a5aa75c4e471ad /src/emu
parent3da7f476068b3ffef713218ba2fc1bd5030f2c38 (diff)
Initial checkin of MAME 0.121.mame0121
Diffstat (limited to 'src/emu')
-rw-r--r--src/emu/attotime.c312
-rw-r--r--src/emu/attotime.h212
-rw-r--r--src/emu/audio/generic.c162
-rw-r--r--src/emu/audio/generic.h61
-rw-r--r--src/emu/audit.c505
-rw-r--r--src/emu/audit.h90
-rw-r--r--src/emu/cheat.c11890
-rw-r--r--src/emu/cheat.h25
-rw-r--r--src/emu/clifront.c977
-rw-r--r--src/emu/clifront.h56
-rw-r--r--src/emu/config.c363
-rw-r--r--src/emu/config.h58
-rw-r--r--src/emu/cpu/adsp2100/2100dasm.c550
-rw-r--r--src/emu/cpu/adsp2100/2100ops.c2310
-rw-r--r--src/emu/cpu/adsp2100/adsp2100.c2612
-rw-r--r--src/emu/cpu/adsp2100/adsp2100.h164
-rw-r--r--src/emu/cpu/alph8201/8201dasm.c261
-rw-r--r--src/emu/cpu/alph8201/alph8201.c1013
-rw-r--r--src/emu/cpu/alph8201/alph8201.h72
-rw-r--r--src/emu/cpu/apexc/apexc.c922
-rw-r--r--src/emu/cpu/apexc/apexc.h38
-rw-r--r--src/emu/cpu/apexc/apexcdsm.c171
-rw-r--r--src/emu/cpu/arm/arm.c1599
-rw-r--r--src/emu/cpu/arm/arm.h32
-rw-r--r--src/emu/cpu/arm/armdasm.c393
-rw-r--r--src/emu/cpu/arm7/arm7.c464
-rw-r--r--src/emu/cpu/arm7/arm7.h41
-rw-r--r--src/emu/cpu/arm7/arm7core.c1681
-rw-r--r--src/emu/cpu/arm7/arm7core.h412
-rw-r--r--src/emu/cpu/arm7/arm7dasm.c1233
-rw-r--r--src/emu/cpu/arm7/arm7exec.c1334
-rw-r--r--src/emu/cpu/asap/asap.c1858
-rw-r--r--src/emu/cpu/asap/asap.h42
-rw-r--r--src/emu/cpu/asap/asapdasm.c148
-rw-r--r--src/emu/cpu/ccpu/ccpu.c809
-rw-r--r--src/emu/cpu/ccpu/ccpu.h57
-rw-r--r--src/emu/cpu/ccpu/ccpudasm.c327
-rw-r--r--src/emu/cpu/cdp1802/1802dasm.c173
-rw-r--r--src/emu/cpu/cdp1802/cdp1802.c1049
-rw-r--r--src/emu/cpu/cdp1802/cdp1802.h100
-rw-r--r--src/emu/cpu/cop400/410ops.c450
-rw-r--r--src/emu/cpu/cop400/420ops.c93
-rw-r--r--src/emu/cpu/cop400/cop400.h46
-rw-r--r--src/emu/cpu/cop400/cop410.c392
-rw-r--r--src/emu/cpu/cop400/cop410ds.c336
-rw-r--r--src/emu/cpu/cop400/cop420.c407
-rw-r--r--src/emu/cpu/cop400/cop420ds.c384
-rw-r--r--src/emu/cpu/cp1610/1610dasm.c1488
-rw-r--r--src/emu/cpu/cp1610/cp1610.c3525
-rw-r--r--src/emu/cpu/cp1610/cp1610.h49
-rw-r--r--src/emu/cpu/cpu.mak1689
-rw-r--r--src/emu/cpu/drcfe.c520
-rw-r--r--src/emu/cpu/drcfe.h188
-rw-r--r--src/emu/cpu/dsp32/dsp32.c952
-rw-r--r--src/emu/cpu/dsp32/dsp32.h84
-rw-r--r--src/emu/cpu/dsp32/dsp32dis.c693
-rw-r--r--src/emu/cpu/dsp32/dsp32ops.c2898
-rw-r--r--src/emu/cpu/dsp56k/dsp56dsm.c2210
-rw-r--r--src/emu/cpu/dsp56k/dsp56k.c1336
-rw-r--r--src/emu/cpu/dsp56k/dsp56k.h82
-rw-r--r--src/emu/cpu/dsp56k/dsp56ops.c2599
-rw-r--r--src/emu/cpu/e132xs/32xsdasm.c2135
-rw-r--r--src/emu/cpu/e132xs/e132xs.c5606
-rw-r--r--src/emu/cpu/e132xs/e132xs.h173
-rw-r--r--src/emu/cpu/f8/f3853.c152
-rw-r--r--src/emu/cpu/f8/f3853.h24
-rw-r--r--src/emu/cpu/f8/f8.c2223
-rw-r--r--src/emu/cpu/f8/f8.h55
-rw-r--r--src/emu/cpu/f8/f8dasm.c510
-rw-r--r--src/emu/cpu/g65816/g65816.c484
-rw-r--r--src/emu/cpu/g65816/g65816.h106
-rw-r--r--src/emu/cpu/g65816/g65816cm.h310
-rw-r--r--src/emu/cpu/g65816/g65816ds.c350
-rw-r--r--src/emu/cpu/g65816/g65816ds.h23
-rw-r--r--src/emu/cpu/g65816/g65816o0.c3
-rw-r--r--src/emu/cpu/g65816/g65816o1.c3
-rw-r--r--src/emu/cpu/g65816/g65816o2.c3
-rw-r--r--src/emu/cpu/g65816/g65816o3.c3
-rw-r--r--src/emu/cpu/g65816/g65816o4.c3
-rw-r--r--src/emu/cpu/g65816/g65816op.h2452
-rw-r--r--src/emu/cpu/h6280/6280dasm.c250
-rw-r--r--src/emu/cpu/h6280/h6280.c562
-rw-r--r--src/emu/cpu/h6280/h6280.h54
-rw-r--r--src/emu/cpu/h6280/h6280ops.h1379
-rw-r--r--src/emu/cpu/h6280/tblh6280.c344
-rw-r--r--src/emu/cpu/h83002/h83002.c3863
-rw-r--r--src/emu/cpu/h83002/h83002.h78
-rw-r--r--src/emu/cpu/h83002/h8disasm.c1230
-rw-r--r--src/emu/cpu/h83002/h8periph.c506
-rw-r--r--src/emu/cpu/h83002/h8priv.h44
-rw-r--r--src/emu/cpu/hd6309/6309dasm.c940
-rw-r--r--src/emu/cpu/hd6309/6309ops.c5599
-rw-r--r--src/emu/cpu/hd6309/6309tbl.c814
-rw-r--r--src/emu/cpu/hd6309/hd6309.c1340
-rw-r--r--src/emu/cpu/hd6309/hd6309.h52
-rw-r--r--src/emu/cpu/i386/cycles.h666
-rw-r--r--src/emu/cpu/i386/i386.c1421
-rw-r--r--src/emu/cpu/i386/i386.h898
-rw-r--r--src/emu/cpu/i386/i386dasm.c2125
-rw-r--r--src/emu/cpu/i386/i386intf.h11
-rw-r--r--src/emu/cpu/i386/i386op16.c3156
-rw-r--r--src/emu/cpu/i386/i386op32.c2974
-rw-r--r--src/emu/cpu/i386/i386ops.c2306
-rw-r--r--src/emu/cpu/i386/i386ops.h369
-rw-r--r--src/emu/cpu/i386/i486ops.c368
-rw-r--r--src/emu/cpu/i386/pentops.c53
-rw-r--r--src/emu/cpu/i386/x87ops.c352
-rw-r--r--src/emu/cpu/i8039/8039dasm.c302
-rw-r--r--src/emu/cpu/i8039/i8039.c949
-rw-r--r--src/emu/cpu/i8039/i8039.h175
-rw-r--r--src/emu/cpu/i8051/8051dasm.c1034
-rw-r--r--src/emu/cpu/i8051/i8051.c2583
-rw-r--r--src/emu/cpu/i8051/i8051.h157
-rw-r--r--src/emu/cpu/i8051/i8051ops.c960
-rw-r--r--src/emu/cpu/i8085/8085dasm.c581
-rw-r--r--src/emu/cpu/i8085/i8085.c1759
-rw-r--r--src/emu/cpu/i8085/i8085.h57
-rw-r--r--src/emu/cpu/i8085/i8085cpu.h181
-rw-r--r--src/emu/cpu/i8085/i8085daa.h2050
-rw-r--r--src/emu/cpu/i86/ea.h58
-rw-r--r--src/emu/cpu/i86/host.h12
-rw-r--r--src/emu/cpu/i86/i186intf.h10
-rw-r--r--src/emu/cpu/i86/i188intf.h9
-rw-r--r--src/emu/cpu/i86/i286.c510
-rw-r--r--src/emu/cpu/i86/i286.h36
-rw-r--r--src/emu/cpu/i86/i286intf.h46
-rw-r--r--src/emu/cpu/i86/i86.c561
-rw-r--r--src/emu/cpu/i86/i86.h127
-rw-r--r--src/emu/cpu/i86/i86.txt111
-rw-r--r--src/emu/cpu/i86/i86intf.h30
-rw-r--r--src/emu/cpu/i86/i86mem.c110
-rw-r--r--src/emu/cpu/i86/i86mem.h14
-rw-r--r--src/emu/cpu/i86/i86time.c312
-rw-r--r--src/emu/cpu/i86/i88intf.h9
-rw-r--r--src/emu/cpu/i86/instr186.c165
-rw-r--r--src/emu/cpu/i86/instr186.h27
-rw-r--r--src/emu/cpu/i86/instr286.c308
-rw-r--r--src/emu/cpu/i86/instr286.h13
-rw-r--r--src/emu/cpu/i86/instr86.c3137
-rw-r--r--src/emu/cpu/i86/instr86.h237
-rw-r--r--src/emu/cpu/i86/instrv30.c1311
-rw-r--r--src/emu/cpu/i86/instrv30.h7
-rw-r--r--src/emu/cpu/i86/modrm.h118
-rw-r--r--src/emu/cpu/i86/table186.h525
-rw-r--r--src/emu/cpu/i86/table286.h531
-rw-r--r--src/emu/cpu/i86/table86.h525
-rw-r--r--src/emu/cpu/i86/tablev30.h528
-rw-r--r--src/emu/cpu/i86/v20intf.h11
-rw-r--r--src/emu/cpu/i86/v30.h23
-rw-r--r--src/emu/cpu/i86/v30intf.h9
-rw-r--r--src/emu/cpu/i86/v33intf.h10
-rw-r--r--src/emu/cpu/i8x41/8x41dasm.c523
-rw-r--r--src/emu/cpu/i8x41/i8x41.c2316
-rw-r--r--src/emu/cpu/i8x41/i8x41.h88
-rw-r--r--src/emu/cpu/i960/i960.c2225
-rw-r--r--src/emu/cpu/i960/i960.h64
-rw-r--r--src/emu/cpu/i960/i960dis.c291
-rw-r--r--src/emu/cpu/i960/i960dis.h15
-rw-r--r--src/emu/cpu/jaguar/jagdasm.c182
-rw-r--r--src/emu/cpu/jaguar/jaguar.c1761
-rw-r--r--src/emu/cpu/jaguar/jaguar.h107
-rw-r--r--src/emu/cpu/konami/knmidasm.c1874
-rw-r--r--src/emu/cpu/konami/konami.c651
-rw-r--r--src/emu/cpu/konami/konami.h58
-rw-r--r--src/emu/cpu/konami/konamops.c4361
-rw-r--r--src/emu/cpu/konami/konamtbl.c491
-rw-r--r--src/emu/cpu/lh5801/5801dasm.c729
-rw-r--r--src/emu/cpu/lh5801/5801tbl.c691
-rw-r--r--src/emu/cpu/lh5801/lh5801.c281
-rw-r--r--src/emu/cpu/lh5801/lh5801.h76
-rw-r--r--src/emu/cpu/m37710/m37710.c1284
-rw-r--r--src/emu/cpu/m37710/m37710.h123
-rw-r--r--src/emu/cpu/m37710/m37710cm.h318
-rw-r--r--src/emu/cpu/m37710/m37710o0.c3
-rw-r--r--src/emu/cpu/m37710/m37710o1.c3
-rw-r--r--src/emu/cpu/m37710/m37710o2.c3
-rw-r--r--src/emu/cpu/m37710/m37710o3.c3
-rw-r--r--src/emu/cpu/m37710/m37710op.h2959
-rw-r--r--src/emu/cpu/m37710/m7700ds.c614
-rw-r--r--src/emu/cpu/m37710/m7700ds.h19
-rw-r--r--src/emu/cpu/m6502/6502dasm.c788
-rw-r--r--src/emu/cpu/m6502/ill02.h278
-rw-r--r--src/emu/cpu/m6502/m4510.c540
-rw-r--r--src/emu/cpu/m6502/m4510.h48
-rw-r--r--src/emu/cpu/m6502/m6502.c1017
-rw-r--r--src/emu/cpu/m6502/m6502.h259
-rw-r--r--src/emu/cpu/m6502/m6502.txt163
-rw-r--r--src/emu/cpu/m6502/m6509.c413
-rw-r--r--src/emu/cpu/m6502/m6509.h43
-rw-r--r--src/emu/cpu/m6502/m65ce02.c389
-rw-r--r--src/emu/cpu/m6502/m65ce02.h57
-rw-r--r--src/emu/cpu/m6502/minc4510.h72
-rw-r--r--src/emu/cpu/m6502/mincce02.h71
-rw-r--r--src/emu/cpu/m6502/ops02.h803
-rw-r--r--src/emu/cpu/m6502/ops09.h217
-rw-r--r--src/emu/cpu/m6502/ops4510.h77
-rw-r--r--src/emu/cpu/m6502/opsc02.h353
-rw-r--r--src/emu/cpu/m6502/opsce02.h988
-rw-r--r--src/emu/cpu/m6502/opsn2a03.h40
-rw-r--r--src/emu/cpu/m6502/t6502.c360
-rw-r--r--src/emu/cpu/m6502/t6509.c352
-rw-r--r--src/emu/cpu/m6502/t6510.c27
-rw-r--r--src/emu/cpu/m6502/t65c02.c410
-rw-r--r--src/emu/cpu/m6502/t65ce02.c399
-rw-r--r--src/emu/cpu/m6502/t65sc02.c80
-rw-r--r--src/emu/cpu/m6502/tdeco16.c429
-rw-r--r--src/emu/cpu/m6502/tn2a03.c97
-rw-r--r--src/emu/cpu/m6800/6800dasm.c274
-rw-r--r--src/emu/cpu/m6800/6800ops.c2140
-rw-r--r--src/emu/cpu/m6800/6800tbl.c398
-rw-r--r--src/emu/cpu/m6800/m6800.c2850
-rw-r--r--src/emu/cpu/m6800/m6800.h223
-rw-r--r--src/emu/cpu/m68000/m68000.h162
-rw-r--r--src/emu/cpu/m68000/m68k.h379
-rw-r--r--src/emu/cpu/m68000/m68k_in.c10685
-rw-r--r--src/emu/cpu/m68000/m68kconf.h201
-rw-r--r--src/emu/cpu/m68000/m68kcpu.c1025
-rw-r--r--src/emu/cpu/m68000/m68kcpu.h2037
-rw-r--r--src/emu/cpu/m68000/m68kdasm.c3742
-rw-r--r--src/emu/cpu/m68000/m68kfpu.c828
-rw-r--r--src/emu/cpu/m68000/m68kmake.c1433
-rw-r--r--src/emu/cpu/m68000/m68kmame.c1291
-rw-r--r--src/emu/cpu/m68000/m68kmame.h182
-rw-r--r--src/emu/cpu/m6805/6805dasm.c211
-rw-r--r--src/emu/cpu/m6805/6805ops.c1822
-rw-r--r--src/emu/cpu/m6805/m6805.c1062
-rw-r--r--src/emu/cpu/m6805/m6805.h95
-rw-r--r--src/emu/cpu/m6809/6809dasm.c612
-rw-r--r--src/emu/cpu/m6809/6809ops.c2997
-rw-r--r--src/emu/cpu/m6809/6809tbl.c316
-rw-r--r--src/emu/cpu/m6809/m6809.c1232
-rw-r--r--src/emu/cpu/m6809/m6809.h50
-rw-r--r--src/emu/cpu/mb86233/mb86233.c1690
-rw-r--r--src/emu/cpu/mb86233/mb86233.h52
-rw-r--r--src/emu/cpu/mb86233/mb86233d.c774
-rw-r--r--src/emu/cpu/mb88xx/mb88dasm.c221
-rw-r--r--src/emu/cpu/mb88xx/mb88xx.c955
-rw-r--r--src/emu/cpu/mb88xx/mb88xx.h78
-rw-r--r--src/emu/cpu/mc68hc11/hc11dasm.c1297
-rw-r--r--src/emu/cpu/mc68hc11/hc11ops.c2201
-rw-r--r--src/emu/cpu/mc68hc11/hc11ops.h189
-rw-r--r--src/emu/cpu/mc68hc11/mc68hc11.c494
-rw-r--r--src/emu/cpu/mc68hc11/mc68hc11.h32
-rw-r--r--src/emu/cpu/minx/minx.c325
-rw-r--r--src/emu/cpu/minx/minx.h18
-rw-r--r--src/emu/cpu/minx/minxd.c465
-rw-r--r--src/emu/cpu/minx/minxfunc.h272
-rw-r--r--src/emu/cpu/minx/minxopce.h331
-rw-r--r--src/emu/cpu/minx/minxopcf.h330
-rw-r--r--src/emu/cpu/minx/minxops.h330
-rw-r--r--src/emu/cpu/mips/dismips.c326
-rw-r--r--src/emu/cpu/mips/dismips.mak2
-rw-r--r--src/emu/cpu/mips/mdrc64.c5731
-rw-r--r--src/emu/cpu/mips/mdrcold.c4883
-rw-r--r--src/emu/cpu/mips/mips3.c2478
-rw-r--r--src/emu/cpu/mips/mips3.h199
-rw-r--r--src/emu/cpu/mips/mips3com.c979
-rw-r--r--src/emu/cpu/mips/mips3com.h257
-rw-r--r--src/emu/cpu/mips/mips3drc.c1297
-rw-r--r--src/emu/cpu/mips/mips3dsm.c511
-rw-r--r--src/emu/cpu/mips/mips3fe.c721
-rw-r--r--src/emu/cpu/mips/mips3fe.h50
-rw-r--r--src/emu/cpu/mips/mipsdasm.c620
-rw-r--r--src/emu/cpu/mips/psx.c3645
-rw-r--r--src/emu/cpu/mips/psx.h206
-rw-r--r--src/emu/cpu/mips/r3000.c1379
-rw-r--r--src/emu/cpu/mips/r3000.h65
-rw-r--r--src/emu/cpu/mips/r3kdasm.c295
-rw-r--r--src/emu/cpu/nec/nec.c1533
-rw-r--r--src/emu/cpu/nec/nec.h370
-rw-r--r--src/emu/cpu/nec/necdasm.c1522
-rw-r--r--src/emu/cpu/nec/necea.h60
-rw-r--r--src/emu/cpu/nec/nechost.h12
-rw-r--r--src/emu/cpu/nec/necinstr.h507
-rw-r--r--src/emu/cpu/nec/necintrf.h18
-rw-r--r--src/emu/cpu/nec/necmodrm.h104
-rw-r--r--src/emu/cpu/pdp1/pdp1.c1893
-rw-r--r--src/emu/cpu/pdp1/pdp1.h81
-rw-r--r--src/emu/cpu/pdp1/pdp1dasm.c293
-rw-r--r--src/emu/cpu/pdp1/tx0.c1318
-rw-r--r--src/emu/cpu/pdp1/tx0.h50
-rw-r--r--src/emu/cpu/pdp1/tx0dasm.c122
-rw-r--r--src/emu/cpu/pic16c5x/16c5xdsm.c267
-rw-r--r--src/emu/cpu/pic16c5x/dis16c5x.c134
-rw-r--r--src/emu/cpu/pic16c5x/pic16c5x.c1334
-rw-r--r--src/emu/cpu/pic16c5x/pic16c5x.h137
-rw-r--r--src/emu/cpu/powerpc/drc_ops.c3802
-rw-r--r--src/emu/cpu/powerpc/drc_ops.h143
-rw-r--r--src/emu/cpu/powerpc/ppc.c1938
-rw-r--r--src/emu/cpu/powerpc/ppc.h367
-rw-r--r--src/emu/cpu/powerpc/ppc403.c964
-rw-r--r--src/emu/cpu/powerpc/ppc602.c293
-rw-r--r--src/emu/cpu/powerpc/ppc603.c300
-rw-r--r--src/emu/cpu/powerpc/ppc_dasm.c1166
-rw-r--r--src/emu/cpu/powerpc/ppc_mem.c436
-rw-r--r--src/emu/cpu/powerpc/ppc_ops.c2848
-rw-r--r--src/emu/cpu/powerpc/ppc_ops.h143
-rw-r--r--src/emu/cpu/powerpc/ppcdrc.c2302
-rw-r--r--src/emu/cpu/rsp/rsp.c3008
-rw-r--r--src/emu/cpu/rsp/rsp.h65
-rw-r--r--src/emu/cpu/rsp/rsp_dasm.c345
-rw-r--r--src/emu/cpu/s2650/2650dasm.c852
-rw-r--r--src/emu/cpu/s2650/s2650.c1619
-rw-r--r--src/emu/cpu/s2650/s2650.h30
-rw-r--r--src/emu/cpu/s2650/s2650cpu.h35
-rw-r--r--src/emu/cpu/saturn/sat.h22
-rw-r--r--src/emu/cpu/saturn/satops.c1209
-rw-r--r--src/emu/cpu/saturn/sattable.c921
-rw-r--r--src/emu/cpu/saturn/saturn.c422
-rw-r--r--src/emu/cpu/saturn/saturn.h68
-rw-r--r--src/emu/cpu/saturn/saturnds.c1454
-rw-r--r--src/emu/cpu/sc61860/readpc.c195
-rw-r--r--src/emu/cpu/sc61860/sc.h34
-rw-r--r--src/emu/cpu/sc61860/sc61860.c255
-rw-r--r--src/emu/cpu/sc61860/sc61860.h58
-rw-r--r--src/emu/cpu/sc61860/scdasm.c220
-rw-r--r--src/emu/cpu/sc61860/scops.c734
-rw-r--r--src/emu/cpu/sc61860/sctable.c144
-rw-r--r--src/emu/cpu/se3208/se3208.c1952
-rw-r--r--src/emu/cpu/se3208/se3208.h14
-rw-r--r--src/emu/cpu/se3208/se3208dis.c1413
-rw-r--r--src/emu/cpu/sh2/sh2.c3181
-rw-r--r--src/emu/cpu/sh2/sh2.h83
-rw-r--r--src/emu/cpu/sh2/sh2dasm.c602
-rw-r--r--src/emu/cpu/sh4/sh4.c4637
-rw-r--r--src/emu/cpu/sh4/sh4.h93
-rw-r--r--src/emu/cpu/sh4/sh4dasm.c792
-rw-r--r--src/emu/cpu/sh4/sh4regs.h157
-rw-r--r--src/emu/cpu/sharc/compute.c1338
-rw-r--r--src/emu/cpu/sharc/sharc.c1229
-rw-r--r--src/emu/cpu/sharc/sharc.h35
-rw-r--r--src/emu/cpu/sharc/sharcdma.c204
-rw-r--r--src/emu/cpu/sharc/sharcdsm.c1183
-rw-r--r--src/emu/cpu/sharc/sharcdsm.h77
-rw-r--r--src/emu/cpu/sharc/sharcmem.c202
-rw-r--r--src/emu/cpu/sharc/sharcops.c2758
-rw-r--r--src/emu/cpu/sharc/sharcops.h138
-rw-r--r--src/emu/cpu/sm8500/sm8500.c533
-rw-r--r--src/emu/cpu/sm8500/sm8500.h59
-rw-r--r--src/emu/cpu/sm8500/sm8500d.c581
-rw-r--r--src/emu/cpu/sm8500/sm85ops.h1686
-rw-r--r--src/emu/cpu/spc700/spc700.c1828
-rw-r--r--src/emu/cpu/spc700/spc700.h154
-rw-r--r--src/emu/cpu/spc700/spc700ds.c437
-rw-r--r--src/emu/cpu/spc700/spc700ds.h27
-rw-r--r--src/emu/cpu/ssp1610/ssp1610.c869
-rw-r--r--src/emu/cpu/ssp1610/ssp1610.h16
-rw-r--r--src/emu/cpu/ssp1610/ssp1610d.c532
-rw-r--r--src/emu/cpu/t11/t11.c540
-rw-r--r--src/emu/cpu/t11/t11.h50
-rw-r--r--src/emu/cpu/t11/t11dasm.c517
-rw-r--r--src/emu/cpu/t11/t11ops.c1400
-rw-r--r--src/emu/cpu/t11/t11table.c2409
-rw-r--r--src/emu/cpu/tlcs90/tlcs90.c2875
-rw-r--r--src/emu/cpu/tlcs90/tlcs90.h26
-rw-r--r--src/emu/cpu/tms32010/32010dsm.c349
-rw-r--r--src/emu/cpu/tms32010/dis32010.c136
-rw-r--r--src/emu/cpu/tms32010/tms32010.c982
-rw-r--r--src/emu/cpu/tms32010/tms32010.h140
-rw-r--r--src/emu/cpu/tms32025/32025dsm.c522
-rw-r--r--src/emu/cpu/tms32025/dis32025.c135
-rw-r--r--src/emu/cpu/tms32025/tms32025.c2477
-rw-r--r--src/emu/cpu/tms32025/tms32025.h78
-rw-r--r--src/emu/cpu/tms32031/32031ops.c6627
-rw-r--r--src/emu/cpu/tms32031/dis32031.c733
-rw-r--r--src/emu/cpu/tms32031/tms32031.c829
-rw-r--r--src/emu/cpu/tms32031/tms32031.h71
-rw-r--r--src/emu/cpu/tms32051/32051ops.c1961
-rw-r--r--src/emu/cpu/tms32051/32051ops.h251
-rw-r--r--src/emu/cpu/tms32051/dis32051.c643
-rw-r--r--src/emu/cpu/tms32051/tms32051.c723
-rw-r--r--src/emu/cpu/tms32051/tms32051.h12
-rw-r--r--src/emu/cpu/tms34010/34010dsm.c1760
-rw-r--r--src/emu/cpu/tms34010/34010fld.c683
-rw-r--r--src/emu/cpu/tms34010/34010gfx.c2032
-rw-r--r--src/emu/cpu/tms34010/34010ops.c2467
-rw-r--r--src/emu/cpu/tms34010/34010ops.h279
-rw-r--r--src/emu/cpu/tms34010/34010tbl.c1167
-rw-r--r--src/emu/cpu/tms34010/dis34010.c113
-rw-r--r--src/emu/cpu/tms34010/makefile6
-rw-r--r--src/emu/cpu/tms34010/tms34010.c1917
-rw-r--r--src/emu/cpu/tms34010/tms34010.h135
-rw-r--r--src/emu/cpu/tms7000/7000dasm.c445
-rw-r--r--src/emu/cpu/tms7000/tms7000.c744
-rw-r--r--src/emu/cpu/tms7000/tms7000.h55
-rw-r--r--src/emu/cpu/tms7000/tms70op.c3958
-rw-r--r--src/emu/cpu/tms7000/tms70tb.c124
-rw-r--r--src/emu/cpu/tms9900/9900dasm.c801
-rw-r--r--src/emu/cpu/tms9900/99xxcore.h4868
-rw-r--r--src/emu/cpu/tms9900/99xxstat.h483
-rw-r--r--src/emu/cpu/tms9900/ti990_10.c9
-rw-r--r--src/emu/cpu/tms9900/tms9900.c9
-rw-r--r--src/emu/cpu/tms9900/tms9900.h223
-rw-r--r--src/emu/cpu/tms9900/tms9980a.c9
-rw-r--r--src/emu/cpu/tms9900/tms9995.c9
-rw-r--r--src/emu/cpu/upd7810/7810dasm.c4059
-rw-r--r--src/emu/cpu/upd7810/7810ops.c9341
-rw-r--r--src/emu/cpu/upd7810/7810tbl.c3513
-rw-r--r--src/emu/cpu/upd7810/upd7810.c2019
-rw-r--r--src/emu/cpu/upd7810/upd7810.h157
-rw-r--r--src/emu/cpu/v30mz/necea.h60
-rw-r--r--src/emu/cpu/v30mz/nechost.h12
-rw-r--r--src/emu/cpu/v30mz/necinstr.h507
-rw-r--r--src/emu/cpu/v30mz/necintrf.h16
-rw-r--r--src/emu/cpu/v30mz/necmodrm.h104
-rw-r--r--src/emu/cpu/v30mz/v30mz.c1158
-rw-r--r--src/emu/cpu/v30mz/v30mz.h359
-rw-r--r--src/emu/cpu/v60/am.c102
-rw-r--r--src/emu/cpu/v60/am1.c1391
-rw-r--r--src/emu/cpu/v60/am2.c1256
-rw-r--r--src/emu/cpu/v60/am3.c887
-rw-r--r--src/emu/cpu/v60/op12.c2399
-rw-r--r--src/emu/cpu/v60/op2.c359
-rw-r--r--src/emu/cpu/v60/op3.c645
-rw-r--r--src/emu/cpu/v60/op4.c354
-rw-r--r--src/emu/cpu/v60/op5.c96
-rw-r--r--src/emu/cpu/v60/op6.c254
-rw-r--r--src/emu/cpu/v60/op7a.c1230
-rw-r--r--src/emu/cpu/v60/optable.c259
-rw-r--r--src/emu/cpu/v60/v60.c743
-rw-r--r--src/emu/cpu/v60/v60.h90
-rw-r--r--src/emu/cpu/v60/v60d.c1477
-rw-r--r--src/emu/cpu/v60/v60mem.c388
-rw-r--r--src/emu/cpu/v810/v810.c1240
-rw-r--r--src/emu/cpu/v810/v810.h128
-rw-r--r--src/emu/cpu/v810/v810dasm.c168
-rw-r--r--src/emu/cpu/x64drc.c629
-rw-r--r--src/emu/cpu/x64drc.h223
-rw-r--r--src/emu/cpu/x86drc.c767
-rw-r--r--src/emu/cpu/x86drc.h194
-rw-r--r--src/emu/cpu/x86emit.h2888
-rw-r--r--src/emu/cpu/x86log.c316
-rw-r--r--src/emu/cpu/x86log.h53
-rw-r--r--src/emu/cpu/z180/z180.c2643
-rw-r--r--src/emu/cpu/z180/z180.h135
-rw-r--r--src/emu/cpu/z180/z180cb.c293
-rw-r--r--src/emu/cpu/z180/z180daa.h2051
-rw-r--r--src/emu/cpu/z180/z180dasm.c555
-rw-r--r--src/emu/cpu/z180/z180dd.c296
-rw-r--r--src/emu/cpu/z180/z180ed.c297
-rw-r--r--src/emu/cpu/z180/z180fd.c291
-rw-r--r--src/emu/cpu/z180/z180op.c520
-rw-r--r--src/emu/cpu/z180/z180ops.h1197
-rw-r--r--src/emu/cpu/z180/z180tbl.h362
-rw-r--r--src/emu/cpu/z180/z180xy.c292
-rw-r--r--src/emu/cpu/z80/z80.c3818
-rw-r--r--src/emu/cpu/z80/z80.h38
-rw-r--r--src/emu/cpu/z80/z80daisy.c75
-rw-r--r--src/emu/cpu/z80/z80daisy.h36
-rw-r--r--src/emu/cpu/z80/z80dasm.c543
-rw-r--r--src/emu/cpu/z8000/8000dasm.c318
-rw-r--r--src/emu/cpu/z8000/makedab.c87
-rw-r--r--src/emu/cpu/z8000/z8000.c756
-rw-r--r--src/emu/cpu/z8000/z8000.h29
-rw-r--r--src/emu/cpu/z8000/z8000cpu.h196
-rw-r--r--src/emu/cpu/z8000/z8000dab.h275
-rw-r--r--src/emu/cpu/z8000/z8000ops.c6503
-rw-r--r--src/emu/cpu/z8000/z8000tbl.c596
-rw-r--r--src/emu/cpu/z80gb/opc_cb.h1440
-rw-r--r--src/emu/cpu/z80gb/opc_main.h1552
-rw-r--r--src/emu/cpu/z80gb/z80gb.c485
-rw-r--r--src/emu/cpu/z80gb/z80gb.h34
-rw-r--r--src/emu/cpu/z80gb/z80gbd.c288
-rw-r--r--src/emu/cpuexec.c1511
-rw-r--r--src/emu/cpuexec.h434
-rw-r--r--src/emu/cpuint.c390
-rw-r--r--src/emu/cpuint.h56
-rw-r--r--src/emu/cpuintrf.c1653
-rw-r--r--src/emu/cpuintrf.h516
-rw-r--r--src/emu/debug/debugcmd.c2200
-rw-r--r--src/emu/debug/debugcmd.h26
-rw-r--r--src/emu/debug/debugcmt.c570
-rw-r--r--src/emu/debug/debugcmt.h40
-rw-r--r--src/emu/debug/debugcon.c533
-rw-r--r--src/emu/debug/debugcon.h97
-rw-r--r--src/emu/debug/debugcpu.c2195
-rw-r--r--src/emu/debug/debugcpu.h231
-rw-r--r--src/emu/debug/debughlp.c1075
-rw-r--r--src/emu/debug/debughlp.h23
-rw-r--r--src/emu/debug/debugvw.c3187
-rw-r--r--src/emu/debug/debugvw.h228
-rw-r--r--src/emu/debug/express.c1953
-rw-r--r--src/emu/debug/express.h160
-rw-r--r--src/emu/debug/textbuf.c326
-rw-r--r--src/emu/debug/textbuf.h58
-rw-r--r--src/emu/debugger.h71
-rw-r--r--src/emu/drawgfx.c5859
-rw-r--r--src/emu/drawgfx.h331
-rw-r--r--src/emu/driver.c520
-rw-r--r--src/emu/driver.h587
-rw-r--r--src/emu/drivers/empty.c81
-rw-r--r--src/emu/eigccppc.h434
-rw-r--r--src/emu/eigccx86.h610
-rw-r--r--src/emu/eminline.h433
-rw-r--r--src/emu/emu.mak237
-rw-r--r--src/emu/emuopts.c226
-rw-r--r--src/emu/emuopts.h158
-rw-r--r--src/emu/emupal.c796
-rw-r--r--src/emu/emupal.h250
-rw-r--r--src/emu/fileio.c839
-rw-r--r--src/emu/fileio.h170
-rw-r--r--src/emu/hash.c713
-rw-r--r--src/emu/hash.h79
-rw-r--r--src/emu/info.c1009
-rw-r--r--src/emu/info.h22
-rw-r--r--src/emu/inptport.c3610
-rw-r--r--src/emu/inptport.h903
-rw-r--r--src/emu/input.c1603
-rw-r--r--src/emu/input.h555
-rw-r--r--src/emu/inputseq.c630
-rw-r--r--src/emu/inputseq.h177
-rw-r--r--src/emu/layout/dualhovu.lay72
-rw-r--r--src/emu/layout/dualhsxs.lay72
-rw-r--r--src/emu/layout/dualhuov.lay72
-rw-r--r--src/emu/layout/ho20ffff.lay18
-rw-r--r--src/emu/layout/ho2eff2e.lay18
-rw-r--r--src/emu/layout/ho4f893d.lay21
-rw-r--r--src/emu/layout/ho88ffff.lay18
-rw-r--r--src/emu/layout/hoa0a0ff.lay18
-rw-r--r--src/emu/layout/hoffe457.lay18
-rw-r--r--src/emu/layout/hoffff20.lay18
-rw-r--r--src/emu/layout/horizont.lay24
-rw-r--r--src/emu/layout/snap.lay50
-rw-r--r--src/emu/layout/triphsxs.lay62
-rw-r--r--src/emu/layout/vertical.lay24
-rw-r--r--src/emu/layout/voffff20.lay18
-rw-r--r--src/emu/machine/53c810.c896
-rw-r--r--src/emu/machine/53c810.h26
-rw-r--r--src/emu/machine/6522via.c1153
-rw-r--r--src/emu/machine/6522via.h195
-rw-r--r--src/emu/machine/6526cia.c782
-rw-r--r--src/emu/machine/6526cia.h58
-rw-r--r--src/emu/machine/6532riot.c373
-rw-r--r--src/emu/machine/6532riot.h87
-rw-r--r--src/emu/machine/6821pia.c1353
-rw-r--r--src/emu/machine/6821pia.h359
-rw-r--r--src/emu/machine/6840ptm.c703
-rw-r--r--src/emu/machine/6840ptm.h75
-rw-r--r--src/emu/machine/6850acia.c691
-rw-r--r--src/emu/machine/6850acia.h90
-rw-r--r--src/emu/machine/74123.c190
-rw-r--r--src/emu/machine/74123.h80
-rw-r--r--src/emu/machine/74148.c193
-rw-r--r--src/emu/machine/74148.h63
-rw-r--r--src/emu/machine/74153.c151
-rw-r--r--src/emu/machine/74153.h58
-rw-r--r--src/emu/machine/74181.c165
-rw-r--r--src/emu/machine/74181.h40
-rw-r--r--src/emu/machine/7474.c173
-rw-r--r--src/emu/machine/7474.h63
-rw-r--r--src/emu/machine/8042kbdc.c622
-rw-r--r--src/emu/machine/8042kbdc.h40
-rw-r--r--src/emu/machine/8237dma.c450
-rw-r--r--src/emu/machine/8237dma.h61
-rw-r--r--src/emu/machine/8255ppi.c589
-rw-r--r--src/emu/machine/8255ppi.h89
-rw-r--r--src/emu/machine/adc083x.c465
-rw-r--r--src/emu/machine/adc083x.h38
-rw-r--r--src/emu/machine/adc1213x.c251
-rw-r--r--src/emu/machine/adc1213x.h18
-rw-r--r--src/emu/machine/am53cf96.c279
-rw-r--r--src/emu/machine/am53cf96.h24
-rw-r--r--src/emu/machine/at28c16.c253
-rw-r--r--src/emu/machine/at28c16.h53
-rw-r--r--src/emu/machine/cr589.c152
-rw-r--r--src/emu/machine/cr589.h3
-rw-r--r--src/emu/machine/ds1302.c140
-rw-r--r--src/emu/machine/ds1302.h5
-rw-r--r--src/emu/machine/ds2401.c272
-rw-r--r--src/emu/machine/ds2401.h18
-rw-r--r--src/emu/machine/ds2404.c320
-rw-r--r--src/emu/machine/ds2404.h18
-rw-r--r--src/emu/machine/eeprom.c378
-rw-r--r--src/emu/machine/eeprom.h40
-rw-r--r--src/emu/machine/generic.c820
-rw-r--r--src/emu/machine/generic.h292
-rw-r--r--src/emu/machine/i2cmem.c438
-rw-r--r--src/emu/machine/i2cmem.h27
-rw-r--r--src/emu/machine/idectrl.c1793
-rw-r--r--src/emu/machine/idectrl.h37
-rw-r--r--src/emu/machine/intelfsh.c493
-rw-r--r--src/emu/machine/intelfsh.h23
-rw-r--r--src/emu/machine/laserdsc.c3361
-rw-r--r--src/emu/machine/laserdsc.h86
-rw-r--r--src/emu/machine/mb3773.c39
-rw-r--r--src/emu/machine/mb3773.h12
-rw-r--r--src/emu/machine/mb87078.c169
-rw-r--r--src/emu/machine/mb87078.h103
-rw-r--r--src/emu/machine/mc146818.c392
-rw-r--r--src/emu/machine/mc146818.h55
-rw-r--r--src/emu/machine/msm6242.c139
-rw-r--r--src/emu/machine/msm6242.h10
-rw-r--r--src/emu/machine/pc16552d.c433
-rw-r--r--src/emu/machine/pc16552d.h12
-rw-r--r--src/emu/machine/pci.c197
-rw-r--r--src/emu/machine/pci.h30
-rw-r--r--src/emu/machine/pd4990a.c352
-rw-r--r--src/emu/machine/pd4990a.h26
-rw-r--r--src/emu/machine/pic8259.c397
-rw-r--r--src/emu/machine/pic8259.h34
-rw-r--r--src/emu/machine/pit8253.c1216
-rw-r--r--src/emu/machine/pit8253.h62
-rw-r--r--src/emu/machine/roc10937.c407
-rw-r--r--src/emu/machine/roc10937.h34
-rw-r--r--src/emu/machine/rp5h01.c207
-rw-r--r--src/emu/machine/rp5h01.h29
-rw-r--r--src/emu/machine/rtc65271.c654
-rw-r--r--src/emu/machine/rtc65271.h9
-rw-r--r--src/emu/machine/scsi.c119
-rw-r--r--src/emu/machine/scsi.h104
-rw-r--r--src/emu/machine/scsicd.c768
-rw-r--r--src/emu/machine/scsicd.h17
-rw-r--r--src/emu/machine/scsidev.c155
-rw-r--r--src/emu/machine/scsidev.h15
-rw-r--r--src/emu/machine/scsihd.c311
-rw-r--r--src/emu/machine/scsihd.h16
-rw-r--r--src/emu/machine/smc91c9x.c564
-rw-r--r--src/emu/machine/smc91c9x.h22
-rw-r--r--src/emu/machine/timekpr.c483
-rw-r--r--src/emu/machine/timekpr.h35
-rw-r--r--src/emu/machine/tmp68301.c179
-rw-r--r--src/emu/machine/tmp68301.h16
-rw-r--r--src/emu/machine/upd4701.c307
-rw-r--r--src/emu/machine/upd4701.h27
-rw-r--r--src/emu/machine/wd33c93.c872
-rw-r--r--src/emu/machine/wd33c93.h26
-rw-r--r--src/emu/machine/x76f041.c623
-rw-r--r--src/emu/machine/x76f041.h22
-rw-r--r--src/emu/machine/x76f100.c497
-rw-r--r--src/emu/machine/x76f100.h22
-rw-r--r--src/emu/machine/z80ctc.c483
-rw-r--r--src/emu/machine/z80ctc.h91
-rw-r--r--src/emu/machine/z80pio.c537
-rw-r--r--src/emu/machine/z80pio.h92
-rw-r--r--src/emu/machine/z80sio.c805
-rw-r--r--src/emu/machine/z80sio.h81
-rw-r--r--src/emu/mame.c1889
-rw-r--r--src/emu/mame.h400
-rw-r--r--src/emu/mamecore.c17
-rw-r--r--src/emu/mamecore.h350
-rw-r--r--src/emu/memconv.h1020
-rw-r--r--src/emu/memory.c3422
-rw-r--r--src/emu/memory.h1166
-rw-r--r--src/emu/output.c406
-rw-r--r--src/emu/output.h97
-rw-r--r--src/emu/profiler.c205
-rw-r--r--src/emu/profiler.h86
-rw-r--r--src/emu/render.c2948
-rw-r--r--src/emu/render.h478
-rw-r--r--src/emu/rendersw.c1942
-rw-r--r--src/emu/rendfont.c853
-rw-r--r--src/emu/rendfont.h33
-rw-r--r--src/emu/rendlay.c2126
-rw-r--r--src/emu/rendlay.h218
-rw-r--r--src/emu/rendutil.c772
-rw-r--r--src/emu/rendutil.h204
-rw-r--r--src/emu/restrack.c368
-rw-r--r--src/emu/restrack.h90
-rw-r--r--src/emu/romload.c1169
-rw-r--r--src/emu/romload.h300
-rw-r--r--src/emu/sndintrf.c967
-rw-r--r--src/emu/sndintrf.h285
-rw-r--r--src/emu/sound.c955
-rw-r--r--src/emu/sound.h89
-rw-r--r--src/emu/sound/2151intf.c236
-rw-r--r--src/emu/sound/2151intf.h37
-rw-r--r--src/emu/sound/2203intf.c348
-rw-r--r--src/emu/sound/2203intf.h67
-rw-r--r--src/emu/sound/2413intf.c186
-rw-r--r--src/emu/sound/2413intf.h26
-rw-r--r--src/emu/sound/2608intf.c314
-rw-r--r--src/emu/sound/2608intf.h38
-rw-r--r--src/emu/sound/2610intf.c520
-rw-r--r--src/emu/sound/2610intf.h50
-rw-r--r--src/emu/sound/2612intf.c415
-rw-r--r--src/emu/sound/2612intf.h64
-rw-r--r--src/emu/sound/262intf.c189
-rw-r--r--src/emu/sound/262intf.h27
-rw-r--r--src/emu/sound/3812intf.c565
-rw-r--r--src/emu/sound/3812intf.h56
-rw-r--r--src/emu/sound/5110intf.c243
-rw-r--r--src/emu/sound/5110intf.h23
-rw-r--r--src/emu/sound/5220intf.c262
-rw-r--r--src/emu/sound/5220intf.h31
-rw-r--r--src/emu/sound/astrocde.c355
-rw-r--r--src/emu/sound/astrocde.h8
-rw-r--r--src/emu/sound/ay8910.c899
-rw-r--r--src/emu/sound/ay8910.h90
-rw-r--r--src/emu/sound/beep.c197
-rw-r--r--src/emu/sound/beep.h16
-rw-r--r--src/emu/sound/bsmt2000.c529
-rw-r--r--src/emu/sound/bsmt2000.h23
-rw-r--r--src/emu/sound/c140.c520
-rw-r--r--src/emu/sound/c140.h24
-rw-r--r--src/emu/sound/c352.c643
-rw-r--r--src/emu/sound/c352.h13
-rw-r--r--src/emu/sound/c6280.c370
-rw-r--r--src/emu/sound/c6280.h8
-rw-r--r--src/emu/sound/cdda.c332
-rw-r--r--src/emu/sound/cdda.h17
-rw-r--r--src/emu/sound/cdp1869.c201
-rw-r--r--src/emu/sound/cdp1869.h41
-rw-r--r--src/emu/sound/cem3394.c593
-rw-r--r--src/emu/sound/cem3394.h45
-rw-r--r--src/emu/sound/custom.c90
-rw-r--r--src/emu/sound/custom.h15
-rw-r--r--src/emu/sound/dac.c187
-rw-r--r--src/emu/sound/dac.h16
-rw-r--r--src/emu/sound/disc_dev.c1372
-rw-r--r--src/emu/sound/disc_flt.c1220
-rw-r--r--src/emu/sound/disc_inp.c261
-rw-r--r--src/emu/sound/disc_mth.c1968
-rw-r--r--src/emu/sound/disc_wav.c1707
-rw-r--r--src/emu/sound/discrete.c751
-rw-r--r--src/emu/sound/discrete.h3930
-rw-r--r--src/emu/sound/dmadac.c272
-rw-r--r--src/emu/sound/dmadac.h16
-rw-r--r--src/emu/sound/es5503.c551
-rw-r--r--src/emu/sound/es5503.h15
-rw-r--r--src/emu/sound/es5506.c2205
-rw-r--r--src/emu/sound/es5506.h53
-rw-r--r--src/emu/sound/es8712.c479
-rw-r--r--src/emu/sound/es8712.h30
-rw-r--r--src/emu/sound/filter.c233
-rw-r--r--src/emu/sound/filter.h112
-rw-r--r--src/emu/sound/flt_rc.c147
-rw-r--r--src/emu/sound/flt_rc.h59
-rw-r--r--src/emu/sound/flt_vol.c80
-rw-r--r--src/emu/sound/flt_vol.h6
-rw-r--r--src/emu/sound/fm.c4744
-rw-r--r--src/emu/sound/fm.h211
-rw-r--r--src/emu/sound/fmopl.c2625
-rw-r--r--src/emu/sound/fmopl.h111
-rw-r--r--src/emu/sound/gaelco.c377
-rw-r--r--src/emu/sound/gaelco.h13
-rw-r--r--src/emu/sound/hc55516.c246
-rw-r--r--src/emu/sound/hc55516.h31
-rw-r--r--src/emu/sound/ics2115.c578
-rw-r--r--src/emu/sound/ics2115.h12
-rw-r--r--src/emu/sound/iremga20.c304
-rw-r--r--src/emu/sound/iremga20.h16
-rw-r--r--src/emu/sound/k005289.c285
-rw-r--r--src/emu/sound/k005289.h16
-rw-r--r--src/emu/sound/k007232.c509
-rw-r--r--src/emu/sound/k007232.h32
-rw-r--r--src/emu/sound/k051649.c255
-rw-r--r--src/emu/sound/k051649.h11
-rw-r--r--src/emu/sound/k053260.c487
-rw-r--r--src/emu/sound/k053260.h24
-rw-r--r--src/emu/sound/k054539.c741
-rw-r--r--src/emu/sound/k054539.h43
-rw-r--r--src/emu/sound/msm5205.c330
-rw-r--r--src/emu/sound/msm5205.h36
-rw-r--r--src/emu/sound/msm5232.c803
-rw-r--r--src/emu/sound/msm5232.h12
-rw-r--r--src/emu/sound/multipcm.c551
-rw-r--r--src/emu/sound/multipcm.h17
-rw-r--r--src/emu/sound/n63701x.c193
-rw-r--r--src/emu/sound/n63701x.h12
-rw-r--r--src/emu/sound/namco.c927
-rw-r--r--src/emu/sound/namco.h32
-rw-r--r--src/emu/sound/namco52.c228
-rw-r--r--src/emu/sound/namco52.h32
-rw-r--r--src/emu/sound/namcona.c1329
-rw-r--r--src/emu/sound/namcona.h10
-rw-r--r--src/emu/sound/nes_apu.c789
-rw-r--r--src/emu/sound/nes_apu.h46
-rw-r--r--src/emu/sound/nes_defs.h205
-rw-r--r--src/emu/sound/okim6295.c676
-rw-r--r--src/emu/sound/okim6295.h65
-rw-r--r--src/emu/sound/pokey.c1599
-rw-r--r--src/emu/sound/pokey.h105
-rw-r--r--src/emu/sound/pokey.txt319
-rw-r--r--src/emu/sound/psx.c695
-rw-r--r--src/emu/sound/psx.h27
-rw-r--r--src/emu/sound/qsound.c411
-rw-r--r--src/emu/sound/qsound.h21
-rw-r--r--src/emu/sound/rf5c400.c581
-rw-r--r--src/emu/sound/rf5c400.h13
-rw-r--r--src/emu/sound/rf5c68.c260
-rw-r--r--src/emu/sound/rf5c68.h15
-rw-r--r--src/emu/sound/s14001a.c548
-rw-r--r--src/emu/sound/s14001a.h16
-rw-r--r--src/emu/sound/saa1099.c519
-rw-r--r--src/emu/sound/saa1099.h18
-rw-r--r--src/emu/sound/samples.c612
-rw-r--r--src/emu/sound/samples.h50
-rw-r--r--src/emu/sound/scsp.c1567
-rw-r--r--src/emu/sound/scsp.h28
-rw-r--r--src/emu/sound/scspdsp.c319
-rw-r--r--src/emu/sound/scspdsp.h37
-rw-r--r--src/emu/sound/scsplfo.c157
-rw-r--r--src/emu/sound/segapcm.c160
-rw-r--r--src/emu/sound/segapcm.h24
-rw-r--r--src/emu/sound/sid.c364
-rw-r--r--src/emu/sound/sid.h74
-rw-r--r--src/emu/sound/sid6581.c144
-rw-r--r--src/emu/sound/sid6581.h32
-rw-r--r--src/emu/sound/side6581.h124
-rw-r--r--src/emu/sound/sidenvel.c590
-rw-r--r--src/emu/sound/sidenvel.h32
-rw-r--r--src/emu/sound/sidvoice.c819
-rw-r--r--src/emu/sound/sidvoice.h117
-rw-r--r--src/emu/sound/sidw6581.h1051
-rw-r--r--src/emu/sound/sidw8580.h1395
-rw-r--r--src/emu/sound/sn76477.c2512
-rw-r--r--src/emu/sound/sn76477.h124
-rw-r--r--src/emu/sound/sn76496.c456
-rw-r--r--src/emu/sound/sn76496.h10
-rw-r--r--src/emu/sound/sound.mak717
-rw-r--r--src/emu/sound/sp0250.c257
-rw-r--r--src/emu/sound/sp0250.h10
-rw-r--r--src/emu/sound/sp0256.c1383
-rw-r--r--src/emu/sound/sp0256.h37
-rw-r--r--src/emu/sound/speaker.c104
-rw-r--r--src/emu/sound/speaker.h29
-rw-r--r--src/emu/sound/st0016.c180
-rw-r--r--src/emu/sound/st0016.h14
-rw-r--r--src/emu/sound/tiaintf.c85
-rw-r--r--src/emu/sound/tiaintf.h8
-rw-r--r--src/emu/sound/tiasound.c596
-rw-r--r--src/emu/sound/tiasound.h44
-rw-r--r--src/emu/sound/tms3615.c125
-rw-r--r--src/emu/sound/tms3615.h9
-rw-r--r--src/emu/sound/tms36xx.c565
-rw-r--r--src/emu/sound/tms36xx.h25
-rw-r--r--src/emu/sound/tms5110.c731
-rw-r--r--src/emu/sound/tms5110.h32
-rw-r--r--src/emu/sound/tms5110r.c136
-rw-r--r--src/emu/sound/tms5220.c1140
-rw-r--r--src/emu/sound/tms5220.h32
-rw-r--r--src/emu/sound/tms5220.txt86
-rw-r--r--src/emu/sound/tms5220r.c107
-rw-r--r--src/emu/sound/upd7759.c801
-rw-r--r--src/emu/sound/upd7759.h31
-rw-r--r--src/emu/sound/vlm5030.c721
-rw-r--r--src/emu/sound/vlm5030.h25
-rw-r--r--src/emu/sound/votrax.c190
-rw-r--r--src/emu/sound/vrender0.c274
-rw-r--r--src/emu/sound/vrender0.h9
-rw-r--r--src/emu/sound/wave.c100
-rw-r--r--src/emu/sound/wave.h14
-rw-r--r--src/emu/sound/wavwrite.c207
-rw-r--r--src/emu/sound/wavwrite.h14
-rw-r--r--src/emu/sound/x1_010.c330
-rw-r--r--src/emu/sound/x1_010.h13
-rw-r--r--src/emu/sound/ym2151.c2505
-rw-r--r--src/emu/sound/ym2151.h86
-rw-r--r--src/emu/sound/ym2151.txt162
-rw-r--r--src/emu/sound/ym2413.c2122
-rw-r--r--src/emu/sound/ym2413.h42
-rw-r--r--src/emu/sound/ymdeltat.c652
-rw-r--r--src/emu/sound/ymdeltat.h82
-rw-r--r--src/emu/sound/ymf262.c2719
-rw-r--r--src/emu/sound/ymf262.h46
-rw-r--r--src/emu/sound/ymf271.c1833
-rw-r--r--src/emu/sound/ymf271.h17
-rw-r--r--src/emu/sound/ymf278b.c835
-rw-r--r--src/emu/sound/ymf278b.h29
-rw-r--r--src/emu/sound/ymz280b.c1125
-rw-r--r--src/emu/sound/ymz280b.h43
-rw-r--r--src/emu/state.c966
-rw-r--r--src/emu/state.h119
-rw-r--r--src/emu/streams.c881
-rw-r--r--src/emu/streams.h50
-rw-r--r--src/emu/tilemap.c2402
-rw-r--r--src/emu/tilemap.h635
-rw-r--r--src/emu/timer.c810
-rw-r--r--src/emu/timer.h185
-rw-r--r--src/emu/ui.c1961
-rw-r--r--src/emu/ui.h141
-rw-r--r--src/emu/uigfx.c1085
-rw-r--r--src/emu/uigfx.h31
-rw-r--r--src/emu/uimenu.c2612
-rw-r--r--src/emu/uimenu.h84
-rw-r--r--src/emu/uismall.pngbin0 -> 1488 bytes
-rw-r--r--src/emu/uitext.c356
-rw-r--r--src/emu/uitext.h233
-rw-r--r--src/emu/validity.c1449
-rw-r--r--src/emu/video.c2211
-rw-r--r--src/emu/video.h169
-rw-r--r--src/emu/video/cdp1869.c569
-rw-r--r--src/emu/video/cdp1869.h128
-rw-r--r--src/emu/video/crtc6845.c444
-rw-r--r--src/emu/video/crtc6845.h62
-rw-r--r--src/emu/video/generic.c1102
-rw-r--r--src/emu/video/generic.h229
-rw-r--r--src/emu/video/poly.c1410
-rw-r--r--src/emu/video/poly.h158
-rw-r--r--src/emu/video/resnet.c738
-rw-r--r--src/emu/video/resnet.h201
-rw-r--r--src/emu/video/rgbgen.h396
-rw-r--r--src/emu/video/rgbsse.h485
-rw-r--r--src/emu/video/rgbutil.h25
-rw-r--r--src/emu/video/rgbvmx.h545
-rw-r--r--src/emu/video/s2636.c300
-rw-r--r--src/emu/video/s2636.h18
-rw-r--r--src/emu/video/tlc34076.c262
-rw-r--r--src/emu/video/tlc34076.h19
-rw-r--r--src/emu/video/tms34061.c541
-rw-r--r--src/emu/video/tms34061.h70
-rw-r--r--src/emu/video/tms9928a.c809
-rw-r--r--src/emu/video/tms9928a.h88
-rw-r--r--src/emu/video/v9938.c2428
-rw-r--r--src/emu/video/v9938.h32
-rw-r--r--src/emu/video/v9938mod.c736
-rw-r--r--src/emu/video/vector.c315
-rw-r--r--src/emu/video/vector.h30
-rw-r--r--src/emu/video/vooddefs.h3632
-rw-r--r--src/emu/video/voodoo.c5742
-rw-r--r--src/emu/video/voodoo.h50
911 files changed, 609749 insertions, 0 deletions
diff --git a/src/emu/attotime.c b/src/emu/attotime.c
new file mode 100644
index 00000000000..41bde38fd47
--- /dev/null
+++ b/src/emu/attotime.c
@@ -0,0 +1,312 @@
+/***************************************************************************
+
+ attotime.c
+
+ Support functions for working with attotime data.
+
+ Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "mamecore.h"
+#include "attotime.h"
+#include "eminline.h"
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+const attotime attotime_zero = STATIC_ATTOTIME_IN_SEC(0);
+const attotime attotime_never = STATIC_ATTOTIME_IN_SEC(ATTOTIME_MAX_SECONDS);
+
+
+
+/***************************************************************************
+ CONVERSION HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ attotime_to_attoseconds - convert a attotime
+ to attoseconds, clamping to maximum positive/
+ negative values
+-------------------------------------------------*/
+
+attoseconds_t attotime_to_attoseconds(attotime _time)
+{
+ /* positive values between 0 and 1 second */
+ if (_time.seconds == 0)
+ return _time.attoseconds;
+
+ /* negative values between -1 and 0 seconds */
+ else if (_time.seconds == -1)
+ return _time.attoseconds - ATTOSECONDS_PER_SECOND;
+
+ /* out-of-range positive values */
+ else if (_time.seconds > 0)
+ return ATTOSECONDS_PER_SECOND;
+
+ /* out-of-range negative values */
+ else
+ return -ATTOSECONDS_PER_SECOND;
+}
+
+
+
+/***************************************************************************
+ CORE MATH FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ attotime_add - add two attotimes
+-------------------------------------------------*/
+
+attotime attotime_add(attotime _time1, attotime _time2)
+{
+ attotime result;
+
+ /* if one of the items is attotime_never, return attotime_never */
+ if (_time1.seconds >= ATTOTIME_MAX_SECONDS || _time2.seconds >= ATTOTIME_MAX_SECONDS)
+ return attotime_never;
+
+ /* add the seconds and attoseconds */
+ result.attoseconds = _time1.attoseconds + _time2.attoseconds;
+ result.seconds = _time1.seconds + _time2.seconds;
+
+ /* normalize and return */
+ if (result.attoseconds >= ATTOSECONDS_PER_SECOND)
+ {
+ result.attoseconds -= ATTOSECONDS_PER_SECOND;
+ result.seconds++;
+ }
+
+ /* overflow */
+ if (result.seconds >= ATTOTIME_MAX_SECONDS)
+ return attotime_never;
+ return result;
+}
+
+
+/*-------------------------------------------------
+ attotime_add_attoseconds - add attoseconds
+ to a attotime
+-------------------------------------------------*/
+
+attotime attotime_add_attoseconds(attotime _time1, attoseconds_t _attoseconds)
+{
+ attotime result;
+
+ /* if one of the items is attotime_never, return attotime_never */
+ if (_time1.seconds >= ATTOTIME_MAX_SECONDS)
+ return attotime_never;
+
+ /* add the seconds and attoseconds */
+ result.attoseconds = _time1.attoseconds + _attoseconds;
+ result.seconds = _time1.seconds;
+
+ /* normalize and return */
+ if (result.attoseconds >= ATTOSECONDS_PER_SECOND)
+ {
+ result.attoseconds -= ATTOSECONDS_PER_SECOND;
+ result.seconds++;
+ }
+
+ /* overflow */
+ if (result.seconds >= ATTOTIME_MAX_SECONDS)
+ return attotime_never;
+ return result;
+}
+
+
+/*-------------------------------------------------
+ attotime_sub - subtract two attotimes
+-------------------------------------------------*/
+
+attotime attotime_sub(attotime _time1, attotime _time2)
+{
+ attotime result;
+
+ /* if time1 is attotime_never, return attotime_never */
+ if (_time1.seconds >= ATTOTIME_MAX_SECONDS)
+ return attotime_never;
+
+ /* add the seconds and attoseconds */
+ result.attoseconds = _time1.attoseconds - _time2.attoseconds;
+ result.seconds = _time1.seconds - _time2.seconds;
+
+ /* normalize and return */
+ if (result.attoseconds < 0)
+ {
+ result.attoseconds += ATTOSECONDS_PER_SECOND;
+ result.seconds--;
+ }
+ return result;
+}
+
+
+/*-------------------------------------------------
+ attotime_sub_attoseconds - subtract
+ attoseconds from a attotime
+-------------------------------------------------*/
+
+attotime attotime_sub_attoseconds(attotime _time1, attoseconds_t _attoseconds)
+{
+ attotime result;
+
+ /* if time1 is attotime_never, return attotime_never */
+ if (_time1.seconds >= ATTOTIME_MAX_SECONDS)
+ return attotime_never;
+
+ /* add the seconds and attoseconds */
+ result.attoseconds = _time1.attoseconds - _attoseconds;
+ result.seconds = _time1.seconds;
+
+ /* normalize and return */
+ if (result.attoseconds < 0)
+ {
+ result.attoseconds += ATTOSECONDS_PER_SECOND;
+ result.seconds--;
+ }
+ return result;
+}
+
+
+/*-------------------------------------------------
+ attotime_mul - multiply an attotime by
+ a constant
+-------------------------------------------------*/
+
+attotime attotime_mul(attotime _time1, UINT32 factor)
+{
+ INT32 attolo, attohi, reslo, reshi;
+ INT64 temp;
+
+ /* if one of the items is attotime_never, return attotime_never */
+ if (_time1.seconds >= ATTOTIME_MAX_SECONDS)
+ return attotime_never;
+
+ /* 0 times anything is zero */
+ if (factor == 0)
+ return attotime_zero;
+
+ /* split attoseconds into upper and lower halves which fit into 32 bits */
+ attohi = div_64x32_rem(_time1.attoseconds, ATTOSECONDS_PER_SECOND_SQRT, &attolo);
+
+ /* scale the lower half, then split into high/low parts */
+ temp = mul_32x32(attolo, factor);
+ temp = div_64x32_rem(temp, ATTOSECONDS_PER_SECOND_SQRT, &reslo);
+
+ /* scale the upper half, then split into high/low parts */
+ temp += mul_32x32(attohi, factor);
+ temp = div_64x32_rem(temp, ATTOSECONDS_PER_SECOND_SQRT, &reshi);
+
+ /* scale the seconds */
+ temp += mul_32x32(_time1.seconds, factor);
+ if (temp >= ATTOTIME_MAX_SECONDS)
+ return attotime_never;
+
+ /* build the result */
+ return attotime_make(temp, (attoseconds_t)reslo + mul_32x32(reshi, ATTOSECONDS_PER_SECOND_SQRT));
+}
+
+
+/*-------------------------------------------------
+ attotime_div - divide an attotime by
+ a constant
+-------------------------------------------------*/
+
+attotime attotime_div(attotime _time1, UINT32 factor)
+{
+ INT32 attolo, attohi, reshi, reslo, remainder;
+ attotime result;
+ INT64 temp;
+
+ /* if one of the items is attotime_never, return attotime_never */
+ if (_time1.seconds >= ATTOTIME_MAX_SECONDS)
+ return attotime_never;
+
+ /* ignore divide by zero */
+ if (factor == 0)
+ return _time1;
+
+ /* split attoseconds into upper and lower halves which fit into 32 bits */
+ attohi = div_64x32_rem(_time1.attoseconds, ATTOSECONDS_PER_SECOND_SQRT, &attolo);
+
+ /* divide the seconds and get the remainder */
+ result.seconds = div_64x32_rem(_time1.seconds, factor, &remainder);
+
+ /* combine the upper half of attoseconds with the remainder and divide that */
+ temp = (INT64)attohi + mul_32x32(remainder, ATTOSECONDS_PER_SECOND_SQRT);
+ reshi = div_64x32_rem(temp, factor, &remainder);
+
+ /* combine the lower half of attoseconds with the remainder and divide that */
+ temp = attolo + mul_32x32(remainder, ATTOSECONDS_PER_SECOND_SQRT);
+ reslo = div_64x32_rem(temp, factor, &remainder);
+
+ /* round based on the remainder */
+ result.attoseconds = (attoseconds_t)reslo + mul_32x32(reshi, ATTOSECONDS_PER_SECOND_SQRT);
+ if (remainder >= factor / 2)
+ if (++result.attoseconds >= ATTOSECONDS_PER_SECOND)
+ {
+ result.attoseconds = 0;
+ result.seconds++;
+ }
+ return result;
+}
+
+
+/*-------------------------------------------------
+ attotime_compare - compare two attotimes
+-------------------------------------------------*/
+
+int attotime_compare(attotime _time1, attotime _time2)
+{
+ if (_time1.seconds > _time2.seconds)
+ return 1;
+ if (_time1.seconds < _time2.seconds)
+ return -1;
+ if (_time1.attoseconds > _time2.attoseconds)
+ return 1;
+ if (_time1.attoseconds < _time2.attoseconds)
+ return -1;
+ return 0;
+}
+
+
+
+/***************************************************************************
+ MISC UTILITIES
+***************************************************************************/
+
+/*-------------------------------------------------
+ attotime_compare - return a temporary
+ printable string describing an attotime
+-------------------------------------------------*/
+
+const char *attotime_string(attotime _time, int precision)
+{
+ static char buffers[8][30];
+ static int nextbuf;
+ char *buffer = &buffers[nextbuf++ % 8][0];
+
+ /* case 1: we want no precision; seconds only */
+ if (precision == 0)
+ sprintf(buffer, "%d", _time.seconds);
+
+ /* case 2: we want 9 or fewer digits of precision */
+ else if (precision <= 9)
+ {
+ INT32 upper = _time.attoseconds / ATTOSECONDS_PER_SECOND_SQRT;
+ sprintf(buffer, "%d.%0*d", _time.seconds, precision, upper);
+ }
+
+ /* case 3: more than 9 digits of precision */
+ else
+ {
+ INT32 lower;
+ INT32 upper = div_64x32_rem(_time.attoseconds, ATTOSECONDS_PER_SECOND_SQRT, &lower);
+ sprintf(buffer, "%d.%09d%0*d", _time.seconds, upper, precision - 9, lower);
+ }
+ return buffer;
+}
diff --git a/src/emu/attotime.h b/src/emu/attotime.h
new file mode 100644
index 00000000000..8d7395b9d42
--- /dev/null
+++ b/src/emu/attotime.h
@@ -0,0 +1,212 @@
+/***************************************************************************
+
+ attotime.h
+
+ Support functions for working with attotime data.
+
+ Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+
+ Attotime is an attosecond-accurate timing system implemented as
+ 96-bit integers.
+
+ 1 second = 1e0 seconds
+ 1 millisecond = 1e-3 seconds
+ 1 microsecond = 1e-6 seconds
+ 1 nanosecond = 1e-9 seconds
+ 1 picosecond = 1e-12 seconds
+ 1 femtosecond = 1e-15 seconds
+ 1 attosecond = 1e-18 seconds
+
+ This may seem insanely accurate, but it has its uses when multiple
+ clocks in the system are run by independent crystals. It is also
+ useful to compute the attotime for something small, say 1 clock tick,
+ and still have it be accurate and useful for scaling.
+
+ Attotime consists of a 32-bit seconds count and a 64-bit attoseconds
+ count. Because the lower bits are kept as attoseconds and not as a
+ full 64-bit value, there is headroom to make some operations simpler.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __ATTOTIME_H__
+#define __ATTOTIME_H__
+
+#include "mamecore.h"
+#include <math.h>
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define ATTOSECONDS_PER_SECOND_SQRT ((attoseconds_t)1000000000)
+#define ATTOSECONDS_PER_SECOND (ATTOSECONDS_PER_SECOND_SQRT * ATTOSECONDS_PER_SECOND_SQRT)
+#define ATTOSECONDS_PER_MILLISECOND (ATTOSECONDS_PER_SECOND / 1000)
+#define ATTOSECONDS_PER_MICROSECOND (ATTOSECONDS_PER_SECOND / 1000000)
+#define ATTOSECONDS_PER_NANOSECOND (ATTOSECONDS_PER_SECOND / 1000000000)
+
+#define ATTOTIME_MAX_SECONDS ((seconds_t)1000000000)
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+/* convert between a double and attoseconds */
+#define ATTOSECONDS_TO_DOUBLE(x) ((double)(x) * 1e-18)
+#define DOUBLE_TO_ATTOSECONDS(x) ((attoseconds_t)((x) * 1e18))
+
+/* convert between hertz (as a double) and attoseconds */
+#define ATTOSECONDS_TO_HZ(x) ((double)ATTOSECONDS_PER_SECOND / (double)(x))
+#define HZ_TO_ATTOSECONDS(x) ((attoseconds_t)(ATTOSECONDS_PER_SECOND / (x)))
+
+/* macros for converting other seconds types to attoseconds */
+#define ATTOSECONDS_IN_SEC(x) ((x) * ATTOSECONDS_PER_SECOND)
+#define ATTOSECONDS_IN_MSEC(x) ((x) * ATTOSECONDS_PER_MILLISECOND)
+#define ATTOSECONDS_IN_USEC(x) ((x) * ATTOSECONDS_PER_MICROSECOND)
+#define ATTOSECONDS_IN_NSEC(x) ((x) * ATTOSECONDS_PER_NANOSECOND)
+
+/* macros for building attotimes from other types at runtime */
+#define ATTOTIME_IN_HZ(hz) attotime_make(0, HZ_TO_ATTOSECONDS(hz))
+#define ATTOTIME_IN_SEC(s) attotime_make((s) / 1, (s) % 1 /* mod here errors on doubles, which is intended */)
+#define ATTOTIME_IN_MSEC(ms) attotime_make((ms) / 1000, ATTOSECONDS_IN_MSEC((ms) % 1000))
+#define ATTOTIME_IN_USEC(us) attotime_make((us) / 1000000, ATTOSECONDS_IN_USEC((us) % 1000000))
+#define ATTOTIME_IN_NSEC(ns) attotime_make((ns) / 1000000000, ATTOSECONDS_IN_NSEC((ns) % 1000000000))
+
+/* macros for building attotimes from other types at compile time */
+#define STATIC_ATTOTIME_IN_HZ(hz) { 0, HZ_TO_ATTOSECONDS(hz) }
+#define STATIC_ATTOTIME_IN_SEC(s) { (s) / 1, (s) % 1 /* mod here errors on doubles, which is intended */ }
+#define STATIC_ATTOTIME_IN_MSEC(ms) { (ms) / 1000, ATTOSECONDS_IN_MSEC((ms) % 1000) }
+#define STATIC_ATTOTIME_IN_USEC(us) { (us) / 1000000, ATTOSECONDS_IN_USEC((us) % 1000000) }
+#define STATIC_ATTOTIME_IN_NSEC(ns) { (ns) / 1000000000, ATTOSECONDS_IN_NSEC((ns) % 1000000000) }
+
+
+#define USEC_TO_ATTOSECONDS(us) ((attoseconds_t)((us) * ATTOSECONDS_PER_MICROSECOND))
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* core components of the attotime structure */
+typedef INT64 attoseconds_t;
+typedef INT32 seconds_t;
+
+
+/* the attotime structure itself */
+typedef struct _attotime attotime;
+struct _attotime
+{
+ seconds_t seconds;
+ attoseconds_t attoseconds;
+};
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+/* constant times for zero and never */
+extern const attotime attotime_zero;
+extern const attotime attotime_never;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* ----- conversion helpers ----- */
+
+/* convert an attotime to attoseconds, clamping to maximum positive/negative values */
+attoseconds_t attotime_to_attoseconds(attotime _time);
+
+
+/* ----- core math functions ----- */
+
+/* add two attotimes */
+attotime attotime_add(attotime _time1, attotime _time2);
+
+/* add attoseconds to an attotime */
+attotime attotime_add_attoseconds(attotime _time1, attoseconds_t _attoseconds);
+
+/* subtract two attotimes */
+attotime attotime_sub(attotime _time1, attotime _time2);
+
+/* subtract attoseconds from an attotime */
+attotime attotime_sub_attoseconds(attotime _time1, attoseconds_t _attoseconds);
+
+/* multiply an attotime by a constant */
+attotime attotime_mul(attotime _time1, UINT32 factor);
+
+/* divide an attotime by a constant */
+attotime attotime_div(attotime _time1, UINT32 factor);
+
+/* compare two attotimes */
+int attotime_compare(attotime _time1, attotime _time2);
+
+
+/* ----- misc utilities ----- */
+
+/* return a temporary printable string describing an attotime */
+const char *attotime_string(attotime _time, int precision);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ attotime_make - assemble an attotime from
+ seconds and attoseconds components
+-------------------------------------------------*/
+
+INLINE attotime attotime_make(seconds_t _secs, attoseconds_t _subsecs)
+{
+ attotime result;
+ result.seconds = _secs;
+ result.attoseconds = _subsecs;
+ return result;
+}
+
+
+/*-------------------------------------------------
+ attotime_to_double - convert from attotime
+ to double
+-------------------------------------------------*/
+
+INLINE double attotime_to_double(attotime _time)
+{
+ return (double)_time.seconds + ATTOSECONDS_TO_DOUBLE(_time.attoseconds);
+}
+
+
+/*-------------------------------------------------
+ double_to_attotime - convert from double to
+ attotime
+-------------------------------------------------*/
+
+INLINE attotime double_to_attotime(double _time)
+{
+ attotime result;
+
+ /* set seconds to the integral part */
+ result.seconds = floor(_time);
+
+ /* set attoseconds to the fractional part */
+ _time -= (double)result.seconds;
+ result.attoseconds = DOUBLE_TO_ATTOSECONDS(_time);
+ return result;
+}
+
+
+#endif /* __ATTOTIME_H__ */
diff --git a/src/emu/audio/generic.c b/src/emu/audio/generic.c
new file mode 100644
index 00000000000..18c17e70e2c
--- /dev/null
+++ b/src/emu/audio/generic.c
@@ -0,0 +1,162 @@
+/***************************************************************************
+
+ generic.c
+
+ Generic simple sound functions.
+
+ Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "driver.h"
+#include "generic.h"
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+static UINT16 latch_clear_value = 0x00;
+static UINT16 latched_value[4];
+static UINT8 latch_read[4];
+
+
+
+/***************************************************************************
+ INITIALIZATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ generic_sound_init - initialize globals and
+ register for save states
+-------------------------------------------------*/
+
+int generic_sound_init(void)
+{
+ /* reset latches */
+ latch_clear_value = 0;
+ memset(latched_value, 0, sizeof(latched_value));
+ memset(latch_read, 0, sizeof(latch_read));
+
+ /* register globals with the save state system */
+ state_save_register_global_array(latched_value);
+ state_save_register_global_array(latch_read);
+
+ return 0;
+}
+
+
+
+/***************************************************************************
+
+ Many games use a master-slave CPU setup. Typically, the main CPU writes
+ a command to some register, and then writes to another register to trigger
+ an interrupt on the slave CPU (the interrupt might also be triggered by
+ the first write). The slave CPU, notified by the interrupt, goes and reads
+ the command.
+
+***************************************************************************/
+
+/*-------------------------------------------------
+ latch_callback - time-delayed callback to
+ set a latch value
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( latch_callback )
+{
+ UINT16 value = param >> 8;
+ int which = param & 0xff;
+
+ /* if the latch hasn't been read and the value is changed, log a warning */
+ if (!latch_read[which] && latched_value[which] != value)
+ logerror("Warning: sound latch %d written before being read. Previous: %02x, new: %02x\n", which, latched_value[which], value);
+
+ /* store the new value and mark it not read */
+ latched_value[which] = value;
+ latch_read[which] = 0;
+}
+
+
+/*-------------------------------------------------
+ latch_w - handle a write to a given latch
+-------------------------------------------------*/
+
+INLINE void latch_w(int which, UINT16 value)
+{
+ timer_call_after_resynch(which | (value << 8), latch_callback);
+}
+
+
+/*-------------------------------------------------
+ latch_r - handle a read from a given latch
+-------------------------------------------------*/
+
+INLINE UINT16 latch_r(int which)
+{
+ latch_read[which] = 1;
+ return latched_value[which];
+}
+
+
+/*-------------------------------------------------
+ latch_clear - clear a given latch
+-------------------------------------------------*/
+
+INLINE void latch_clear(int which)
+{
+ latched_value[which] = latch_clear_value;
+}
+
+
+/*-------------------------------------------------
+ soundlatch_w - global write handlers for
+ writing to sound latches
+-------------------------------------------------*/
+
+WRITE8_HANDLER( soundlatch_w ) { latch_w(0, data); }
+WRITE16_HANDLER( soundlatch_word_w ) { latch_w(0, data); }
+WRITE8_HANDLER( soundlatch2_w ) { latch_w(1, data); }
+WRITE16_HANDLER( soundlatch2_word_w ) { latch_w(1, data); }
+WRITE8_HANDLER( soundlatch3_w ) { latch_w(2, data); }
+WRITE16_HANDLER( soundlatch3_word_w ) { latch_w(2, data); }
+WRITE8_HANDLER( soundlatch4_w ) { latch_w(3, data); }
+WRITE16_HANDLER( soundlatch4_word_w ) { latch_w(3, data); }
+
+
+/*-------------------------------------------------
+ soundlatch_r - global read handlers for
+ reading from sound latches
+-------------------------------------------------*/
+
+READ8_HANDLER( soundlatch_r ) { return latch_r(0); }
+READ16_HANDLER( soundlatch_word_r ) { return latch_r(0); }
+READ8_HANDLER( soundlatch2_r ) { return latch_r(1); }
+READ16_HANDLER( soundlatch2_word_r ) { return latch_r(1); }
+READ8_HANDLER( soundlatch3_r ) { return latch_r(2); }
+READ16_HANDLER( soundlatch3_word_r ) { return latch_r(2); }
+READ8_HANDLER( soundlatch4_r ) { return latch_r(3); }
+READ16_HANDLER( soundlatch4_word_r ) { return latch_r(3); }
+
+
+/*-------------------------------------------------
+ soundlatch_clear_w - global write handlers
+ for clearing sound latches
+-------------------------------------------------*/
+
+WRITE8_HANDLER( soundlatch_clear_w ) { latch_clear(0); }
+WRITE8_HANDLER( soundlatch2_clear_w ) { latch_clear(1); }
+WRITE8_HANDLER( soundlatch3_clear_w ) { latch_clear(2); }
+WRITE8_HANDLER( soundlatch4_clear_w ) { latch_clear(3); }
+
+
+/*-------------------------------------------------
+ soundlatch_setclearedvalue - set the "clear"
+ value for all sound latches
+-------------------------------------------------*/
+
+void soundlatch_setclearedvalue(int value)
+{
+ latch_clear_value = value;
+}
diff --git a/src/emu/audio/generic.h b/src/emu/audio/generic.h
new file mode 100644
index 00000000000..398b4bf06cd
--- /dev/null
+++ b/src/emu/audio/generic.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+
+ generic.h
+
+ Generic simple sound functions.
+
+ Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __SOUND_GENERIC_H__
+#define __SOUND_GENERIC_H__
+
+#include "memory.h"
+
+
+
+/***************************************************************************
+
+ Function prototypes
+
+***************************************************************************/
+
+int generic_sound_init(void);
+
+/* latch readers */
+READ8_HANDLER( soundlatch_r );
+READ8_HANDLER( soundlatch2_r );
+READ8_HANDLER( soundlatch3_r );
+READ8_HANDLER( soundlatch4_r );
+READ16_HANDLER( soundlatch_word_r );
+READ16_HANDLER( soundlatch2_word_r );
+READ16_HANDLER( soundlatch3_word_r );
+READ16_HANDLER( soundlatch4_word_r );
+
+/* latch writers */
+WRITE8_HANDLER( soundlatch_w );
+WRITE8_HANDLER( soundlatch2_w );
+WRITE8_HANDLER( soundlatch3_w );
+WRITE8_HANDLER( soundlatch4_w );
+WRITE16_HANDLER( soundlatch_word_w );
+WRITE16_HANDLER( soundlatch2_word_w );
+WRITE16_HANDLER( soundlatch3_word_w );
+WRITE16_HANDLER( soundlatch4_word_w );
+
+/* latch clearers */
+WRITE8_HANDLER( soundlatch_clear_w );
+WRITE8_HANDLER( soundlatch2_clear_w );
+WRITE8_HANDLER( soundlatch3_clear_w );
+WRITE8_HANDLER( soundlatch4_clear_w );
+
+/* If you're going to use soundlatchX_clear_w, and the cleared value is
+ something other than 0x00, use this function from machine_init. Note
+ that this one call effects all 4 latches */
+void soundlatch_setclearedvalue(int value);
+
+
+#endif /* __SOUND_GENERIC_H__ */
diff --git a/src/emu/audit.c b/src/emu/audit.c
new file mode 100644
index 00000000000..e72cf7604b5
--- /dev/null
+++ b/src/emu/audit.c
@@ -0,0 +1,505 @@
+/***************************************************************************
+
+ audit.c
+
+ ROM set auditing functions.
+
+ Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include <stdarg.h>
+#include "driver.h"
+#include "hash.h"
+#include "audit.h"
+#include "harddisk.h"
+#include "sound/samples.h"
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static int audit_one_rom(core_options *options, const rom_entry *rom, const game_driver *gamedrv, UINT32 validation, audit_record *record);
+static int audit_one_disk(core_options *options, const rom_entry *rom, const game_driver *gamedrv, UINT32 validation, audit_record *record);
+static int rom_used_by_parent(const game_driver *gamedrv, const rom_entry *romentry, const game_driver **parent);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ set_status - shortcut for setting status and
+ substatus values
+-------------------------------------------------*/
+
+INLINE void set_status(audit_record *record, UINT8 status, UINT8 substatus)
+{
+ record->status = status;
+ record->substatus = substatus;
+}
+
+
+
+/***************************************************************************
+ CORE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ audit_images - validate the ROM and disk
+ images for a game
+-------------------------------------------------*/
+
+int audit_images(core_options *options, const game_driver *gamedrv, UINT32 validation, audit_record **audit)
+{
+ const rom_entry *region, *rom;
+ audit_record *record;
+ int foundany = FALSE;
+ int allshared = TRUE;
+ int records;
+
+ /* determine the number of records we will generate */
+ records = 0;
+ for (region = rom_first_region(gamedrv); region != NULL; region = rom_next_region(region))
+ for (rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom))
+ if (ROMREGION_ISROMDATA(region) || ROMREGION_ISDISKDATA(region))
+ {
+ if (allshared && !rom_used_by_parent(gamedrv, rom, NULL))
+ allshared = FALSE;
+ records++;
+ }
+
+ if (records > 0)
+ {
+ /* allocate memory for the records */
+ *audit = malloc_or_die(sizeof(**audit) * records);
+ memset(*audit, 0, sizeof(**audit) * records);
+ record = *audit;
+
+ /* iterate over regions and ROMs */
+ for (region = rom_first_region(gamedrv); region; region = rom_next_region(region))
+ for (rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ {
+ int shared = rom_used_by_parent(gamedrv, rom, NULL);
+
+ /* audit a file */
+ if (ROMREGION_ISROMDATA(region))
+ {
+ if (audit_one_rom(options, rom, gamedrv, validation, record++) && (!shared || allshared))
+ foundany = TRUE;
+ }
+
+ /* audit a disk */
+ else if (ROMREGION_ISDISKDATA(region))
+ {
+ if (audit_one_disk(options, rom, gamedrv, validation, record++) && (!shared || allshared))
+ foundany = TRUE;
+ }
+ }
+
+ /* if we found nothing, we don't have the set at all */
+ if (!foundany)
+ {
+ free(*audit);
+ *audit = NULL;
+ records = 0;
+ }
+ }
+ return records;
+}
+
+
+/*-------------------------------------------------
+ audit_samples - validate the samples for a
+ game
+-------------------------------------------------*/
+
+int audit_samples(core_options *options, const game_driver *gamedrv, audit_record **audit)
+{
+ machine_config config;
+ audit_record *record;
+ int sndnum, sampnum;
+ int records = 0;
+
+ /* count the number of sample records attached to this driver */
+ expand_machine_driver(gamedrv->drv, &config);
+#if HAS_SAMPLES
+ for (sndnum = 0; sndnum < ARRAY_LENGTH(config.sound); sndnum++)
+ if (config.sound[sndnum].type == SOUND_SAMPLES)
+ {
+ struct Samplesinterface *intf = (struct Samplesinterface *)config.sound[sndnum].config;
+
+ if (intf->samplenames != NULL)
+ {
+ /* iterate over samples in this entry */
+ for (sampnum = 0; intf->samplenames[sampnum] != NULL; sampnum++)
+ if (intf->samplenames[sampnum][0] != '*')
+ records++;
+ }
+ }
+#endif
+
+ /* if no records, just quit now */
+ if (records == 0)
+ return records;
+
+ /* allocate memory for the records */
+ *audit = malloc_or_die(sizeof(**audit) * records);
+ memset(*audit, 0, sizeof(**audit) * records);
+ record = *audit;
+
+ /* now iterate over sample entries */
+ for (sndnum = 0; sndnum < ARRAY_LENGTH(config.sound); sndnum++)
+ if (config.sound[sndnum].type == SOUND_SAMPLES)
+ {
+ struct Samplesinterface *intf = (struct Samplesinterface *)config.sound[sndnum].config;
+ const char *sharedname = NULL;
+
+ if (intf->samplenames != NULL)
+ {
+ /* iterate over samples in this entry */
+ for (sampnum = 0; intf->samplenames[sampnum] != NULL; sampnum++)
+ if (intf->samplenames[sampnum][0] == '*')
+ sharedname = &intf->samplenames[sampnum][1];
+ else
+ {
+ file_error filerr;
+ mame_file *file;
+ astring *fname;
+
+ /* attempt to access the file from the game driver name */
+ fname = astring_assemble_3(astring_alloc(), gamedrv->name, PATH_SEPARATOR, intf->samplenames[sampnum]);
+ filerr = mame_fopen_options(options, SEARCHPATH_SAMPLE, astring_c(fname), OPEN_FLAG_READ, &file);
+
+ /* attempt to access the file from the shared driver name */
+ if (filerr != FILERR_NONE && sharedname != NULL)
+ {
+ astring_assemble_3(fname, sharedname, PATH_SEPARATOR, intf->samplenames[sampnum]);
+ filerr = mame_fopen_options(options, SEARCHPATH_SAMPLE, astring_c(fname), OPEN_FLAG_READ, &file);
+ }
+ astring_free(fname);
+
+ /* fill in the record */
+ record->type = AUDIT_FILE_SAMPLE;
+ record->name = intf->samplenames[sampnum];
+ if (filerr == FILERR_NONE)
+ {
+ set_status(record++, AUDIT_STATUS_GOOD, SUBSTATUS_GOOD);
+ mame_fclose(file);
+ }
+ else
+ set_status(record++, AUDIT_STATUS_NOT_FOUND, SUBSTATUS_NOT_FOUND);
+ }
+ }
+ }
+
+ return records;
+}
+
+
+/*-------------------------------------------------
+ audit_summary - output a summary given a
+ list of audit records
+-------------------------------------------------*/
+
+int audit_summary(const game_driver *gamedrv, int count, const audit_record *records, int output)
+{
+ int overall_status = CORRECT;
+ int notfound = 0;
+ int recnum;
+
+ /* no count or records means not found */
+ if (count == 0 || records == NULL)
+ return NOTFOUND;
+
+ /* loop over records */
+ for (recnum = 0; recnum < count; recnum++)
+ {
+ const audit_record *record = &records[recnum];
+ int best_new_status = INCORRECT;
+
+ /* skip anything that's fine */
+ if (record->substatus == SUBSTATUS_GOOD)
+ continue;
+
+ /* count the number of missing items */
+ if (record->status == AUDIT_STATUS_NOT_FOUND)
+ notfound++;
+
+ /* output the game name, file name, and length (if applicable) */
+ if (output)
+ {
+ mame_printf_info("%-8s: %s", gamedrv->name, record->name);
+ if (record->explength > 0)
+ mame_printf_info(" (%d bytes)", record->explength);
+ mame_printf_info(" - ");
+ }
+
+ /* use the substatus for finer details */
+ switch (record->substatus)
+ {
+ case SUBSTATUS_GOOD_NEEDS_REDUMP:
+ if (output) mame_printf_info("NEEDS REDUMP\n");
+ best_new_status = BEST_AVAILABLE;
+ break;
+
+ case SUBSTATUS_FOUND_NODUMP:
+ if (output) mame_printf_info("NO GOOD DUMP KNOWN\n");
+ best_new_status = BEST_AVAILABLE;
+ break;
+
+ case SUBSTATUS_FOUND_BAD_CHECKSUM:
+ if (output)
+ {
+ char hashbuf[512];
+
+ mame_printf_info("INCORRECT CHECKSUM:\n");
+ hash_data_print(record->exphash, 0, hashbuf);
+ mame_printf_info("EXPECTED: %s\n", hashbuf);
+ hash_data_print(record->hash, 0, hashbuf);
+ mame_printf_info(" FOUND: %s\n", hashbuf);
+ }
+ break;
+
+ case SUBSTATUS_FOUND_WRONG_LENGTH:
+ if (output) mame_printf_info("INCORRECT LENGTH: %d bytes\n", record->length);
+ break;
+
+ case SUBSTATUS_NOT_FOUND:
+ if (output) mame_printf_info("NOT FOUND\n");
+ break;
+
+ case SUBSTATUS_NOT_FOUND_NODUMP:
+ if (output) mame_printf_info("NOT FOUND - NO GOOD DUMP KNOWN\n");
+ best_new_status = BEST_AVAILABLE;
+ break;
+
+ case SUBSTATUS_NOT_FOUND_OPTIONAL:
+ if (output) mame_printf_info("NOT FOUND BUT OPTIONAL\n");
+ best_new_status = BEST_AVAILABLE;
+ break;
+
+ case SUBSTATUS_NOT_FOUND_PARENT:
+ if (output) mame_printf_info("NOT FOUND (shared with parent)\n");
+ break;
+
+ case SUBSTATUS_NOT_FOUND_BIOS:
+ if (output) mame_printf_info("NOT FOUND (BIOS)\n");
+ break;
+ }
+
+ /* downgrade the overall status if necessary */
+ overall_status = MAX(overall_status, best_new_status);
+ }
+
+ return (notfound == count) ? NOTFOUND : overall_status;
+}
+
+
+
+/***************************************************************************
+ UTILITIES
+***************************************************************************/
+
+/*-------------------------------------------------
+ audit_one_rom - validate a single ROM entry
+-------------------------------------------------*/
+
+static int audit_one_rom(core_options *options, const rom_entry *rom, const game_driver *gamedrv, UINT32 validation, audit_record *record)
+{
+ const game_driver *drv;
+ const rom_entry *chunk;
+ UINT32 crc = 0;
+ UINT8 crcs[4];
+ int has_crc;
+
+ /* fill in the record basics */
+ record->type = AUDIT_FILE_ROM;
+ record->name = ROM_GETNAME(rom);
+ record->exphash = ROM_GETHASHDATA(rom);
+
+ /* compute the expected length by summing the chunks */
+ for (chunk = rom_first_chunk(rom); chunk; chunk = rom_next_chunk(chunk))
+ record->explength += ROM_GETLENGTH(chunk);
+
+ /* see if we have a CRC and extract it if so */
+ has_crc = hash_data_extract_binary_checksum(record->exphash, HASH_CRC, crcs);
+ if (has_crc)
+ crc = (crcs[0] << 24) | (crcs[1] << 16) | (crcs[2] << 8) | crcs[3];
+
+ /* find the file and checksum it, getting the file length along the way */
+ for (drv = gamedrv; drv != NULL; drv = driver_get_clone(drv))
+ {
+ file_error filerr;
+ mame_file *file;
+ astring *fname;
+
+ /* open the file if we can */
+ fname = astring_assemble_3(astring_alloc(), drv->name, PATH_SEPARATOR, ROM_GETNAME(rom));
+ if (has_crc)
+ filerr = mame_fopen_crc_options(options, SEARCHPATH_ROM, astring_c(fname), crc, OPEN_FLAG_READ, &file);
+ else
+ filerr = mame_fopen_options(options, SEARCHPATH_ROM, astring_c(fname), OPEN_FLAG_READ, &file);
+ astring_free(fname);
+
+ /* if we got it, extract the hash and length */
+ if (filerr == FILERR_NONE)
+ {
+ hash_data_copy(record->hash, mame_fhash(file, validation));
+ record->length = (UINT32)mame_fsize(file);
+ mame_fclose(file);
+ break;
+ }
+ }
+
+ /* if we failed to find the file, set the appropriate status */
+ if (drv == NULL)
+ {
+ const game_driver *parent;
+
+ /* no good dump */
+ if (hash_data_has_info(record->exphash, HASH_INFO_NO_DUMP))
+ set_status(record, AUDIT_STATUS_NOT_FOUND, SUBSTATUS_NOT_FOUND_NODUMP);
+
+ /* optional ROM */
+ else if (ROM_ISOPTIONAL(rom))
+ set_status(record, AUDIT_STATUS_NOT_FOUND, SUBSTATUS_NOT_FOUND_OPTIONAL);
+
+ /* not found and used by parent */
+ else if (rom_used_by_parent(gamedrv, rom, &parent))
+ set_status(record, AUDIT_STATUS_NOT_FOUND, (parent->flags & GAME_IS_BIOS_ROOT) ? SUBSTATUS_NOT_FOUND_BIOS : SUBSTATUS_NOT_FOUND_PARENT);
+
+ /* just plain old not found */
+ else
+ set_status(record, AUDIT_STATUS_NOT_FOUND, SUBSTATUS_NOT_FOUND);
+ }
+
+ /* if we did find the file, do additional verification */
+ else
+ {
+ /* length mismatch */
+ if (record->explength != record->length)
+ set_status(record, AUDIT_STATUS_FOUND_INVALID, SUBSTATUS_FOUND_WRONG_LENGTH);
+
+ /* found but needs a dump */
+ else if (hash_data_has_info(record->exphash, HASH_INFO_NO_DUMP))
+ set_status(record, AUDIT_STATUS_GOOD, SUBSTATUS_FOUND_NODUMP);
+
+ /* incorrect hash */
+ else if (!hash_data_is_equal(record->exphash, record->hash, 0))
+ set_status(record, AUDIT_STATUS_FOUND_INVALID, SUBSTATUS_FOUND_BAD_CHECKSUM);
+
+ /* correct hash but needs a redump */
+ else if (hash_data_has_info(record->exphash, HASH_INFO_BAD_DUMP))
+ set_status(record, AUDIT_STATUS_GOOD, SUBSTATUS_GOOD_NEEDS_REDUMP);
+
+ /* just plain old good */
+ else
+ set_status(record, AUDIT_STATUS_GOOD, SUBSTATUS_GOOD);
+ }
+
+ /* return TRUE if we found anything at all */
+ return (drv != NULL);
+}
+
+
+/*-------------------------------------------------
+ audit_one_disk - validate a single disk entry
+-------------------------------------------------*/
+
+static int audit_one_disk(core_options *options, const rom_entry *rom, const game_driver *gamedrv, UINT32 validation, audit_record *record)
+{
+ mame_file *source_file;
+ chd_file *source;
+ chd_error err;
+
+ /* fill in the record basics */
+ record->type = AUDIT_FILE_DISK;
+ record->name = ROM_GETNAME(rom);
+ record->exphash = ROM_GETHASHDATA(rom);
+
+ /* open the disk */
+ err = open_disk_image_options(options, gamedrv, rom, &source_file, &source);
+
+ /* if we failed, report the error */
+ if (err != CHDERR_NONE)
+ {
+ /* out of memory */
+ if (err == CHDERR_OUT_OF_MEMORY)
+ set_status(record, AUDIT_STATUS_ERROR, SUBSTATUS_ERROR);
+
+ /* not found but it's not good anyway */
+ else if (hash_data_has_info(record->exphash, HASH_INFO_NO_DUMP))
+ set_status(record, AUDIT_STATUS_NOT_FOUND, SUBSTATUS_NOT_FOUND_NODUMP);
+
+ /* not found at all */
+ else
+ set_status(record, AUDIT_STATUS_NOT_FOUND, SUBSTATUS_NOT_FOUND);
+ }
+
+ /* if we succeeded, validate it */
+ else
+ {
+ static const UINT8 nullhash[HASH_BUF_SIZE] = { 0 };
+ chd_header header = *chd_get_header(source);
+
+ /* if there's an MD5 or SHA1 hash, add them to the output hash */
+ if (memcmp(nullhash, header.md5, sizeof(header.md5)) != 0)
+ hash_data_insert_binary_checksum(record->hash, HASH_MD5, header.md5);
+ if (memcmp(nullhash, header.sha1, sizeof(header.sha1)) != 0)
+ hash_data_insert_binary_checksum(record->hash, HASH_SHA1, header.sha1);
+
+ /* found but needs a dump */
+ if (hash_data_has_info(record->exphash, HASH_INFO_NO_DUMP))
+ set_status(record, AUDIT_STATUS_GOOD, SUBSTATUS_GOOD_NEEDS_REDUMP);
+
+ /* incorrect hash */
+ else if (!hash_data_is_equal(record->exphash, record->hash, 0))
+ set_status(record, AUDIT_STATUS_FOUND_INVALID, SUBSTATUS_FOUND_BAD_CHECKSUM);
+
+ /* just plain good */
+ else
+ set_status(record, AUDIT_STATUS_GOOD, SUBSTATUS_GOOD);
+
+ chd_close(source);
+ mame_fclose(source_file);
+ }
+
+ /* return TRUE if we found anything at all */
+ return (source != NULL);
+}
+
+
+/*-------------------------------------------------
+ rom_used_by_parent - determine if a given
+ ROM is also used by the parent
+-------------------------------------------------*/
+
+static int rom_used_by_parent(const game_driver *gamedrv, const rom_entry *romentry, const game_driver **parent)
+{
+ const char *hash = ROM_GETHASHDATA(romentry);
+ const game_driver *drv;
+
+ /* iterate up the parent chain */
+ for (drv = driver_get_clone(gamedrv); drv != NULL; drv = driver_get_clone(drv))
+ {
+ const rom_entry *region;
+ const rom_entry *rom;
+
+ /* see if the parent has the same ROM or not */
+ for (region = rom_first_region(drv); region; region = rom_next_region(region))
+ for (rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ if (hash_data_is_equal(ROM_GETHASHDATA(rom), hash, 0))
+ {
+ if (parent != NULL)
+ *parent = drv;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
diff --git a/src/emu/audit.h b/src/emu/audit.h
new file mode 100644
index 00000000000..b17ddecca68
--- /dev/null
+++ b/src/emu/audit.h
@@ -0,0 +1,90 @@
+/***************************************************************************
+
+ audit.h
+
+ ROM, disk, and sample auditing functions.
+
+ Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __AUDIT_H__
+#define __AUDIT_H__
+
+#include "mamecore.h"
+#include "hash.h"
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* hashes to use for validation */
+#define AUDIT_VALIDATE_FAST (HASH_CRC)
+#define AUDIT_VALIDATE_FULL (HASH_CRC | HASH_SHA)
+
+/* return values from audit_verify_roms and audit_verify_samples */
+#define CORRECT 0
+#define BEST_AVAILABLE 1
+#define INCORRECT 2
+#define NOTFOUND 3
+
+/* image types for audit_record.type */
+#define AUDIT_FILE_ROM 0
+#define AUDIT_FILE_DISK 1
+#define AUDIT_FILE_SAMPLE 2
+
+/* status values for audit_record.status */
+#define AUDIT_STATUS_GOOD 0
+#define AUDIT_STATUS_FOUND_INVALID 1
+#define AUDIT_STATUS_NOT_FOUND 2
+#define AUDIT_STATUS_ERROR 3
+
+/* substatus values for audit_record.substatus */
+#define SUBSTATUS_GOOD 0
+#define SUBSTATUS_GOOD_NEEDS_REDUMP 1
+#define SUBSTATUS_FOUND_NODUMP 2
+#define SUBSTATUS_FOUND_BAD_CHECKSUM 3
+#define SUBSTATUS_FOUND_WRONG_LENGTH 4
+#define SUBSTATUS_NOT_FOUND 5
+#define SUBSTATUS_NOT_FOUND_NODUMP 6
+#define SUBSTATUS_NOT_FOUND_OPTIONAL 7
+#define SUBSTATUS_NOT_FOUND_PARENT 8
+#define SUBSTATUS_NOT_FOUND_BIOS 9
+#define SUBSTATUS_ERROR 100
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _audit_record audit_record;
+struct _audit_record
+{
+ UINT8 type; /* type of item that was audited */
+ UINT8 status; /* status of audit on this item */
+ UINT8 substatus; /* finer-detail status */
+ const char * name; /* name of item */
+ UINT32 explength; /* expected length of item */
+ UINT32 length; /* actual length of item */
+ const char * exphash; /* expected hash data */
+ char hash[HASH_BUF_SIZE]; /* actual hash information */
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+int audit_images(core_options *options, const game_driver *gamedrv, UINT32 validation, audit_record **audit);
+int audit_samples(core_options *options, const game_driver *gamedrv, audit_record **audit);
+int audit_summary(const game_driver *gamedrv, int count, const audit_record *records, int output);
+
+
+#endif /* __AUDIT_H__ */
diff --git a/src/emu/cheat.c b/src/emu/cheat.c
new file mode 100644
index 00000000000..9a423bbf480
--- /dev/null
+++ b/src/emu/cheat.c
@@ -0,0 +1,11890 @@
+/*********************************************************************
+
+ cheat.c
+
+ MAME cheat system.
+
+ Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#include "driver.h"
+#include "ui.h"
+#include "uimenu.h"
+#include "uitext.h"
+#include "machine/eeprom.h"
+#include "cheat.h"
+#include <ctype.h>
+#include <math.h>
+
+#ifdef MESS
+#include "cheatms.h"
+#endif
+
+#define OSD_READKEY_KLUDGE 1
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+/* easy bitfield extraction and setting, uses *_Shift, *_ShiftedMask, and *_Mask enums */
+#define EXTRACT_FIELD(data, name) (((data) >> k##name##_Shift) & k##name##_ShiftedMask)
+#define SET_FIELD(data, name, in) (data = (data & ~(k##name##_ShiftedMask << k##name##_Shift)) | (((in) & k##name##_ShiftedMask) << k##name##_Shift))
+#define TEST_FIELD(data, name) ((data) & k##name##_Mask)
+#define SET_MASK_FIELD(data, name) ((data) |= k##name##_Mask)
+#define CLEAR_MASK_FIELD(data, name) ((data) &= ~(k##name##_Mask))
+#define TOGGLE_MASK_FIELD(data, name) ((data) ^= k##name##_Mask)
+
+#define DEFINE_BITFIELD_ENUM(name, end, start) k##name##_Shift = (int)(end), \
+ k##name##_ShiftedMask = (int)(0xFFFFFFFF >> (32 - (start - end + 1))), \
+ k##name##_Mask = (int)(k##name##_ShiftedMask << k##name##_Shift)
+
+#define kRegionListLength (REGION_MAX - REGION_INVALID)
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define CHEAT_FILENAME_MAX_LEN 255
+
+/********** BIT FIELD **********/
+
+enum
+{
+ /* cheat code */
+ DEFINE_BITFIELD_ENUM(OneShot, 0, 0),
+ DEFINE_BITFIELD_ENUM(Type, 1, 2),
+ DEFINE_BITFIELD_ENUM(Operation, 3, 4),
+ DEFINE_BITFIELD_ENUM(TypeParameter, 5, 7),
+ DEFINE_BITFIELD_ENUM(UserSelectEnable, 8, 8),
+ DEFINE_BITFIELD_ENUM(UserSelectMinimumDisplay, 9, 9),
+ DEFINE_BITFIELD_ENUM(UserSelectMinimum, 10, 10),
+ DEFINE_BITFIELD_ENUM(UserSelectBCD, 11, 11),
+ DEFINE_BITFIELD_ENUM(Prefill, 12, 13),
+ DEFINE_BITFIELD_ENUM(RemoveFromList, 14, 14),
+ DEFINE_BITFIELD_ENUM(LinkExtension, 15, 15),
+ DEFINE_BITFIELD_ENUM(LinkEnable, 16, 16),
+ DEFINE_BITFIELD_ENUM(LinkCopyPreviousValue, 17, 17),
+ DEFINE_BITFIELD_ENUM(OperationParameter, 18, 18),
+ DEFINE_BITFIELD_ENUM(OperationExtend, 19, 19),
+ DEFINE_BITFIELD_ENUM(BytesUsed, 20, 21),
+ DEFINE_BITFIELD_ENUM(Endianness, 22, 22),
+ DEFINE_BITFIELD_ENUM(RestorePreviousValue, 23, 23),
+ DEFINE_BITFIELD_ENUM(LocationParameter, 24, 28),
+ DEFINE_BITFIELD_ENUM(LocationType, 29, 31),
+
+ /* watch (unused ?) */
+// DEFINE_BITFIELD_ENUM(Watch_AddValue, 0, 15),
+// DEFINE_BITFIELD_ENUM(Watch_Label, 16, 17),
+// DEFINE_BITFIELD_ENUM(Watch_DisplayType, 18, 19),
+
+ /* command */
+ DEFINE_BITFIELD_ENUM(AutoSaveEnabled, 0, 0),
+ DEFINE_BITFIELD_ENUM(SearchBox, 1, 2), // 0 = Minimum, 1 = Classic, 2 = Advanced
+ DEFINE_BITFIELD_ENUM(DontPrintNewLabels, 3, 3), // in options menu, it is reverted.
+ DEFINE_BITFIELD_ENUM(ActivationKeyMessage, 4, 4),
+ DEFINE_BITFIELD_ENUM(LoadOldFormat, 5, 5),
+ DEFINE_BITFIELD_ENUM(Debug, 6, 6)
+};
+
+/********** OPERATION **********/
+
+enum // types
+{
+ kType_NormalOrDelay = 0,
+ kType_WaitForModification,
+ kType_IgnoreIfDecrementing,
+ kType_Watch
+};
+
+enum // operations
+{
+ kOperation_WriteMask = 0,
+ kOperation_AddSubtract,
+ kOperation_ForceRange,
+ kOperation_SetOrClearBits,
+ kOperation_WriteMatch,
+ // kOperation_Unused5,
+ // kOperation_Unused6,
+ kOperation_None = 7
+};
+
+//enum // prefills (unused?)
+//{
+// kPrefill_Disable = 0,
+// kPrefill_UseFF,
+// kPrefill_Use00,
+// kPrefill_Use01
+//};
+
+enum // location types
+{
+ kLocation_Standard = 0,
+ kLocation_MemoryRegion,
+ kLocation_HandlerMemory,
+ kLocation_Custom,
+ kLocation_IndirectIndexed,
+ kLocation_ProgramSpace
+};
+
+enum // location parameters
+{
+ kCustomLocation_Comment = 0,
+ kCustomLocation_EEPROM,
+ kCustomLocation_Select,
+ kCustomLocation_AssignActivationKey,
+ kCustomLocation_Enable,
+ kCustomLocation_Overclock,
+ kCustomLocation_RefreshRate
+};
+
+enum // flags for action
+{
+ /* set for wait for modification or ignore if decrementing cheats when
+ the targeted value has changed
+ cleared after the operation is performed */
+ kActionFlag_WasModified = 1 << 0,
+
+ /* set for one shot cheats after the operation is performed */
+ kActionFlag_OperationDone = 1 << 1,
+
+ /* set if the extendData field is being used by something other than a mask value */
+ kActionFlag_IgnoreMask = 1 << 2,
+
+ /* set if the lastValue field contains valid data and can be restored if needed */
+ kActionFlag_LastValueGood = 1 << 3,
+
+ /* set after value changes from prefill value */
+ kActionFlag_PrefillDone = 1 << 4,
+
+ /* set after prefill value written */
+ kActionFlag_PrefillWritten = 1 << 5,
+
+ /* masks */
+ kActionFlag_StateMask = kActionFlag_OperationDone |
+ kActionFlag_LastValueGood |
+ kActionFlag_PrefillDone |
+ kActionFlag_PrefillWritten,
+ kActionFlag_InfoMask = kActionFlag_WasModified |
+ kActionFlag_IgnoreMask,
+ kActionFlag_PersistentMask = kActionFlag_LastValueGood
+};
+
+enum // flags for entry
+{
+ /* true when the cheat is active */
+ kCheatFlag_Active = 1 << 0,
+
+ /* true if the cheat is entirely one shot */
+ kCheatFlag_OneShot = 1 << 1,
+
+ /* true if the cheat will work with one shot in special case */
+ kCheatFlag_DoOneShot = 1 << 2,
+
+ /* true if the cheat is entirely null (ex. a comment) */
+ kCheatFlag_Null = 1 << 3,
+
+ /* true if the cheat contains a user-select element */
+ kCheatFlag_UserSelect = 1 << 4,
+
+ /* true if the cheat is a select cheat */
+ kCheatFlag_Select = 1 << 5,
+
+ /* true if the cheat has been assigned an 1st activation key */
+ kCheatFlag_HasActivationKey1 = 1 << 6,
+
+ /* true if the cheat has been assigned an 2nd activation key */
+ kCheatFlag_HasActivationKey2 = 1 << 7,
+
+ /* true if the activation key is being pressed */
+ kCheatFlag_ActivationKeyPressed = 1 << 8,
+
+ /* true if the cheat has been edited or is a new cheat */
+ kCheatFlag_Dirty = 1 << 9,
+
+ /* masks */
+ kCheatFlag_StateMask = kCheatFlag_Active |
+ kCheatFlag_DoOneShot,
+ kCheatFlag_InfoMask = kCheatFlag_OneShot |
+ kCheatFlag_DoOneShot |
+ kCheatFlag_Null |
+ kCheatFlag_UserSelect |
+ kCheatFlag_Select |
+ kCheatFlag_HasActivationKey1 |
+ kCheatFlag_HasActivationKey2 |
+ kCheatFlag_ActivationKeyPressed,
+ kCheatFlag_PersistentMask = kCheatFlag_Active |
+ kCheatFlag_DoOneShot |
+ kCheatFlag_HasActivationKey1 |
+ kCheatFlag_HasActivationKey2 |
+ kCheatFlag_ActivationKeyPressed |
+ kCheatFlag_Dirty
+};
+
+/********** WATCH **********/
+
+enum // types
+{
+ kWatchLabel_None = 0,
+ kWatchLabel_Address,
+ kWatchLabel_String,
+
+ kWatchLabel_MaxPlusOne
+};
+
+enum // display types
+{
+ kWatchDisplayType_Hex = 0,
+ kWatchDisplayType_Decimal,
+ kWatchDisplayType_Binary,
+ kWatchDisplayType_ASCII,
+
+ kWatchDisplayType_MaxPlusOne
+};
+
+/********** REGION **********/
+
+enum // flags
+{
+ /* true if enabled for search */
+ kRegionFlag_Enabled = 1 << 0
+
+ /* true if the memory region has no mapped memory and uses a memory handler (unused?) */
+// kRegionFlag_UsesHandler = 1 << 1
+};
+
+enum // types
+{
+ kRegionType_CPU = 0,
+ kRegionType_Memory
+};
+
+enum // default search regions
+{
+ kSearchSpeed_Fast = 0, // RAM + some banks
+ kSearchSpeed_Medium, // RAM + BANKx
+ kSearchSpeed_Slow, // all memory areas except ROM, NOP, and custom handlers
+ kSearchSpeed_VerySlow, // all memory areas except ROM and NOP
+ kSearchSpeed_AllMemory, // entire CPU address space
+
+ kSearchSpeed_Max = kSearchSpeed_AllMemory
+};
+
+/********** SEARCH **********/
+
+enum // operands
+{
+ kSearchOperand_Current = 0,
+ kSearchOperand_Previous,
+ kSearchOperand_First,
+ kSearchOperand_Value,
+
+ kSearchOperand_Max = kSearchOperand_Value
+};
+
+enum // bits
+{
+ kSearchSize_8Bit = 0,
+ kSearchSize_16Bit,
+ kSearchSize_24Bit,
+ kSearchSize_32Bit,
+ kSearchSize_1Bit,
+
+ kSearchSize_Max = kSearchSize_1Bit
+};
+
+enum // comparisons
+{
+ kSearchComparison_LessThan = 0,
+ kSearchComparison_GreaterThan,
+ kSearchComparison_EqualTo,
+ kSearchComparison_LessThanOrEqualTo,
+ kSearchComparison_GreaterThanOrEqualTo,
+ kSearchComparison_NotEqual,
+ kSearchComparison_IncreasedBy,
+ kSearchComparison_NearTo,
+
+ kSearchComparison_Max = kSearchComparison_NearTo
+};
+
+/********** OTHERS **********/
+
+enum
+{
+ kVerticalKeyRepeatRate = 8,
+ kHorizontalFastKeyRepeatRate = 5,
+ kHorizontalSlowKeyRepeatRate = 8
+};
+
+enum
+{
+ kSearchBox_Minimum = 0,
+ kSearchBox_Classic,
+ kSearchBox_Advanced
+};
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/********** ACTION **********/
+
+struct CheatAction
+{
+ UINT32 type;
+ UINT32 address;
+ UINT32 data;
+ UINT32 extendData;
+ UINT32 originalDataField;
+
+ INT32 frameTimer;
+ UINT32 lastValue;
+
+ UINT32 flags;
+
+ UINT8 ** cachedPointer;
+ UINT32 cachedOffset;
+
+ char * optionalName;
+};
+
+typedef struct CheatAction CheatAction;
+
+/********** ENTRY **********/
+
+struct CheatEntry
+{
+ char * name;
+ char * comment;
+
+ INT32 actionListLength;
+ CheatAction * actionList;
+
+ int activationKey1;
+ int activationKey2;
+
+ UINT32 flags;
+ int selection;
+};
+
+typedef struct CheatEntry CheatEntry;
+
+/********** WATCH **********/
+
+struct WatchInfo
+{
+ UINT32 address;
+ UINT8 cpu;
+ UINT8 numElements;
+ UINT8 elementBytes;
+ UINT8 labelType;
+ UINT8 displayType;
+ UINT8 skip;
+ UINT8 elementsPerLine;
+ INT8 addValue;
+ INT8 addressShift;
+ INT8 dataShift;
+ UINT32 xor;
+
+ UINT8 locationType;
+
+ float x, y;
+
+ CheatEntry * linkedCheat;
+
+ char label[256];
+};
+
+typedef struct WatchInfo WatchInfo;
+
+/********** REGION **********/
+
+struct SearchRegion
+{
+ UINT32 address;
+ UINT32 length;
+
+ UINT8 targetType;
+ UINT8 targetIdx;
+
+ UINT8 flags;
+
+ UINT8 * cachedPointer;
+ const address_map
+ * writeHandler;
+
+ UINT8 * first;
+ UINT8 * last;
+
+ UINT8 * status;
+
+ UINT8 * backupLast;
+ UINT8 * backupStatus;
+
+ char name[32]; // 12345678 - 12345678 BANK31
+
+ UINT32 numResults;
+ UINT32 oldNumResults;
+};
+
+typedef struct SearchRegion SearchRegion;
+
+/********** SEARCH **********/
+
+struct OldSearchOptions
+{
+ UINT8 status;
+ UINT8 energy;
+ UINT8 operand;
+ UINT32 value;
+ UINT32 delta;
+};
+
+typedef struct OldSearchOptions OldSearchOptions;
+
+struct SearchInfo
+{
+ INT32 regionListLength;
+ SearchRegion * regionList;
+
+ char * name;
+
+ INT8 bytes; // 0 = 1, 1 = 2, 2 = 3, 3 = 4, 4 = bit
+ UINT8 swap;
+ UINT8 sign;
+ INT8 lhs;
+ INT8 rhs;
+ INT8 comparison;
+
+ UINT8 targetType; // cpu/region
+ UINT8 targetIdx; // cpu or region index
+
+ UINT32 value;
+
+ UINT8 searchSpeed;
+
+ UINT32 numResults;
+ UINT32 oldNumResults;
+
+ INT32 currentRegionIdx;
+ INT32 currentResultsPage;
+
+ UINT8 backupValid;
+
+ OldSearchOptions oldOptions;
+};
+
+typedef struct SearchInfo SearchInfo;
+
+/********** CPU **********/
+
+struct CPUInfo
+{
+ UINT8 type;
+ UINT8 dataBits;
+ UINT8 addressBits;
+ UINT8 addressCharsNeeded;
+ UINT32 addressMask;
+ UINT8 endianness;
+ UINT8 addressShift;
+};
+
+typedef struct CPUInfo CPUInfo;
+
+/********** MENU **********/
+
+struct MenuStringList
+{
+ const char ** mainList; // editable menu item lists
+ const char ** subList;
+ char * flagList;
+
+ char ** mainStrings; // lists of useable strings
+ char ** subStrings;
+
+ char * buf; // string storage
+
+ UINT32 length; // number of menu items supported
+ UINT32 numStrings; // number of strings supported
+ UINT32 mainStringLength; // max length of main string
+ UINT32 subStringLength; // max length of sub string
+};
+
+typedef struct MenuStringList MenuStringList;
+
+struct MenuItemInfoStruct
+{
+ UINT32 subcheat;
+ UINT32 fieldType;
+ UINT32 extraData;
+};
+
+typedef struct MenuItemInfoStruct MenuItemInfoStruct;
+
+/***************************************************************************
+ EXPORTED VARIABLES
+***************************************************************************/
+
+static const char * cheatfile = NULL;
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+static emu_timer * periodic_timer;
+
+static CheatEntry * cheatList = NULL;
+static INT32 cheatListLength = 0;
+
+static WatchInfo * watchList = NULL;
+static INT32 watchListLength = 0;
+
+static SearchInfo * searchList = NULL;
+static INT32 searchListLength = 0;
+static INT32 currentSearchIdx = 0;
+
+static CPUInfo cpuInfoList[MAX_CPU];
+static CPUInfo regionInfoList[kRegionListLength];
+
+//static int cheatEngineWasActive = 0;
+static int foundCheatDatabase = 0;
+static int cheatsDisabled = 0;
+static int watchesDisabled = 0;
+
+static int fullMenuPageHeight = 0;
+
+static char mainDatabaseName[CHEAT_FILENAME_MAX_LEN + 1];
+
+static MenuStringList menuStrings;
+
+static MenuItemInfoStruct * menuItemInfo;
+static INT32 menuItemInfoLength = 0;
+
+static UINT32 cheatOptions = 2;
+
+static const char * kCheatNameTemplates[] =
+{
+ "Infinite Credits",
+ "Infinite Time",
+ "Infinite Lives",
+ "Infinite Energy",
+ "Invincibility",
+ "Infinite Time PL1",
+ "Infinite Lives PL1",
+ "Infinite Energy PL1",
+ "Drain all Energy Now! PL1",
+ "Invincibility PL1",
+ "Infinite Time PL2",
+ "Infinite Lives PL2",
+ "Infinite Energy PL2",
+ "Drain all Energy Now! PL2",
+ "Invincibility PL2",
+ "Infinite Ammo",
+ "Infinite Bombs",
+ "Select starting level",
+ "Rapid Fire",
+ "Infinite Ammo PL1",
+ "Infinite Bombs PL1",
+ "Select Score PL1",
+ "Rapid Fire PL1",
+ "Infinite Ammo PL2",
+ "Infinite Bombs PL2",
+ "Select Score PL2",
+ "Rapid Fire PL2",
+ "Display the Correct Answer",
+ "Infinite ",
+ "Always have ",
+ "Get ",
+ "Lose ",
+ "Finish this ",
+ "---> <ENTER> To Edit <---",
+ "\0"
+};
+
+static CPUInfo rawCPUInfo =
+{
+ 0, // type
+ 8, // dataBits
+ 8, // addressBits
+ 1, // addressCharsNeeded
+ CPU_IS_BE // endianness
+};
+
+static const int kSearchByteIncrementTable[] =
+{
+ 1,
+ 2,
+ 3,
+ 4,
+ 1
+};
+
+static const int kSearchByteStep[] =
+{
+ 1,
+ 2,
+ 1,
+ 4,
+ 1
+};
+
+static const int kSearchByteDigitsTable[] =
+{
+ 2,
+ 4,
+ 6,
+ 8,
+ 1
+};
+
+static const int kSearchByteDecDigitsTable[] =
+{
+ 3,
+ 5,
+ 8,
+ 10,
+ 1
+};
+
+static const UINT32 kSearchByteMaskTable[] =
+{
+ 0x000000FF,
+ 0x0000FFFF,
+ 0x00FFFFFF,
+ 0xFFFFFFFF,
+ 0x00000001
+};
+
+static const UINT32 kSearchByteSignBitTable[] =
+{
+ 0x00000080,
+ 0x00008000,
+ 0x00800000,
+ 0x80000000,
+ 0x00000000
+};
+
+static const UINT32 kSearchByteUnsignedMaskTable[] =
+{
+ 0x0000007F,
+ 0x00007FFF,
+ 0x007FFFFF,
+ 0x7FFFFFFF,
+ 0x00000001
+};
+
+static const UINT32 kCheatSizeMaskTable[] =
+{
+ 0x000000FF,
+ 0x0000FFFF,
+ 0x00FFFFFF,
+ 0xFFFFFFFF
+};
+
+static const UINT32 kCheatSizeDigitsTable[] =
+{
+ 2,
+ 4,
+ 6,
+ 8
+};
+
+static const int kByteConversionTable[] =
+{
+ kSearchSize_8Bit,
+ kSearchSize_16Bit,
+ kSearchSize_24Bit,
+ kSearchSize_32Bit,
+ kSearchSize_32Bit
+};
+
+static const int kWatchSizeConversionTable[] =
+{
+ kSearchSize_8Bit,
+ kSearchSize_16Bit,
+ kSearchSize_24Bit,
+ kSearchSize_32Bit,
+ kSearchSize_8Bit
+};
+
+static const int kSearchOperandNeedsInit[] =
+{
+ 0,
+ 1,
+ 1,
+ 0
+};
+
+static const UINT32 kPrefillValueTable[] =
+{
+ 0x00,
+ 0xFF,
+ 0x00,
+ 0x01
+};
+
+static const char * kWatchLabelStringList[] =
+{
+ "None",
+ "Address",
+ "String"
+};
+
+static const char * kWatchDisplayTypeStringList[] =
+{
+ "Hex",
+ "Decimal",
+ "Binary",
+ "ASCII"
+};
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/********** MAIN **********/
+static TIMER_CALLBACK( cheat_periodic );
+static void cheat_exit(running_machine *machine);
+
+/********** SPECIAL KEY HANDLING **********/
+static int ShiftKeyPressed(void);
+static int ControlKeyPressed(void);
+static int AltKeyPressed(void);
+
+static int UIPressedRepeatThrottle(int code, int baseSpeed);
+
+/********** DIRECT KEY INPUT **********/
+static int ReadHexInput(void);
+
+static char * DoDynamicEditTextField(char * buf);
+static void DoStaticEditTextField(char * buf, int size);
+static UINT32 DoEditHexField(UINT32 data);
+static UINT32 DoEditHexFieldSigned(UINT32 data, UINT32 mask);
+static INT32 DoEditDecField(INT32 data, INT32 min, INT32 max);
+
+/********** VALUE SHIFT OR CONVERTION **********/
+static UINT32 DoShift(UINT32 input, INT8 shift);
+
+static UINT32 BCDToDecimal(UINT32 value);
+static UINT32 DecimalToBCD(UINT32 value);
+
+/********** STRINGS **********/
+static void RebuildStringTables(void);
+static void RequestStrings(UINT32 length, UINT32 numStrings, UINT32 mainStringLength, UINT32 subStringLength);
+static void InitStringTable(void);
+static void FreeStringTable(void);
+
+static char * CreateStringCopy(char * buf);
+
+/********** ADDITIONAL MENU FOR CHEAT **********/
+static INT32 UserSelectValueMenu(int selection, CheatEntry * entry);
+
+/********** CHEAT MENU **********/
+static int EnableDisableCheatMenu(int selection, int firstTime);
+static int AddEditCheatMenu(int selection);
+static int EditCheatMenu(CheatEntry * entry, int index, int selection);
+
+static int DoSearchMenuMinimum(int selection); // minimum mode
+static int DoSearchMenuClassic(int selection); // classic mode
+static int DoSearchMenu(int selection); // advanced mode
+static int SelectSearchRegions(int selection, SearchInfo * search);
+static int ViewSearchResults(int selection, int firstTime);
+
+static int ChooseWatch(int selection);
+static int EditWatch(WatchInfo * entry, int selection);
+
+static int SelectOptions(int selection);
+static int SelectSearch(int selection);
+
+/********** ENTRY LIST **********/
+static void ResizeCheatList(UINT32 newLength);
+static void ResizeCheatListNoDispose(UINT32 newLength);
+
+static void AddCheatBefore(UINT32 idx);
+static void DeleteCheatAt(UINT32 idx);
+
+static void DisposeCheat(CheatEntry * entry);
+static CheatEntry * GetNewCheat(void);
+
+/********** ACTION LIST **********/
+static void ResizeCheatActionList(CheatEntry * entry, UINT32 newLength);
+static void ResizeCheatActionListNoDispose(CheatEntry * entry, UINT32 newLength);
+
+static void AddActionBefore(CheatEntry * entry, UINT32 idx);
+static void DeleteActionAt(CheatEntry * entry, UINT32 idx);
+static void DisposeAction(CheatAction * action);
+
+/********** WATCH LIST **********/
+static void InitWatch(WatchInfo * info, UINT32 idx);
+static void ResizeWatchList(UINT32 newLength);
+static void ResizeWatchListNoDispose(UINT32 newLength);
+
+static void AddWatchBefore(UINT32 idx);
+static void DeleteWatchAt(UINT32 idx);
+static void DisposeWatch(WatchInfo * watch);
+static WatchInfo * GetUnusedWatch(void);
+
+static void AddCheatFromWatch(WatchInfo * watch);
+static void SetupCheatFromWatchAsWatch(CheatEntry * entry, WatchInfo * watch);
+
+/********** SEARCH LIST **********/
+static void ResizeSearchList(UINT32 newLength);
+static void ResizeSearchListNoDispose(UINT32 newLength);
+
+static void AddSearchBefore(UINT32 idx);
+static void DeleteSearchAt(UINT32 idx);
+
+static void InitSearch(SearchInfo * info);
+
+static void DisposeSearchRegions(SearchInfo * info);
+static void DisposeSearch(UINT32 idx);
+static SearchInfo * GetCurrentSearch(void);
+
+static void FillBufferFromRegion(SearchRegion * region, UINT8 * buf);
+static UINT32 ReadRegionData(SearchRegion * region, UINT32 offset, UINT8 size, UINT8 swap);
+
+static void BackupSearch(SearchInfo * info);
+static void RestoreSearchBackup(SearchInfo * info);
+static void BackupRegion(SearchRegion * region);
+static void RestoreRegionBackup(SearchRegion * region);
+static void SetSearchRegionDefaultName(SearchRegion * region);
+static void AllocateSearchRegions(SearchInfo * info);
+static void BuildSearchRegions(SearchInfo * info);
+
+/********** CODE LOADER **********/
+static int ConvertOldCode(int code, int cpu, int * data, int * extendData);
+static void HandleLocalCommandCheat(UINT32 type, UINT32 address, UINT32 data, UINT32 extendData, char * name, char * description);
+
+static void LoadCheatFile(char * fileName);
+static void LoadCheatDatabase(void);
+
+static void DisposeCheatDatabase(void);
+static void ReloadCheatDatabase(void);
+
+static void SaveCheat(CheatEntry * entry, int selection, int saveCode);
+static void DoAutoSaveCheats(void);
+
+/********** CODE ADDITION **********/
+static void AddCheatFromResult(SearchInfo * search, SearchRegion * region, UINT32 address);
+static void AddCheatFromFirstResult(SearchInfo * search);
+static void AddWatchFromResult(SearchInfo * search, SearchRegion * region, UINT32 address);
+
+/********** SEARCH **********/
+static UINT32 SearchSignExtend(SearchInfo * search, UINT32 value);
+static UINT32 ReadSearchOperand(UINT8 type, SearchInfo * search, SearchRegion * region, UINT32 address);
+static UINT32 ReadSearchOperandBit(UINT8 type, SearchInfo * search, SearchRegion * region, UINT32 address);
+static UINT8 DoSearchComparison(SearchInfo * search, UINT32 lhs, UINT32 rhs);
+static UINT32 DoSearchComparisonBit(SearchInfo * search, UINT32 lhs, UINT32 rhs);
+//static UINT8 IsRegionOffsetValid(SearchInfo * search, SearchRegion * region, UINT32 offset);
+
+#define IsRegionOffsetValid IsRegionOffsetValidBit
+
+static UINT8 IsRegionOffsetValidBit(SearchInfo * search, SearchRegion * region, UINT32 offset);
+static void InvalidateRegionOffset(SearchInfo * search, SearchRegion * region, UINT32 offset);
+static void InvalidateRegionOffsetBit(SearchInfo * search, SearchRegion * region, UINT32 offset, UINT32 invalidate);
+static void InvalidateEntireRegion(SearchInfo * search, SearchRegion * region);
+
+static void InitializeNewSearch(SearchInfo * search);
+static void UpdateSearch(SearchInfo * search);
+
+static void DoSearch(SearchInfo * search);
+
+/********** MEMORY ACCESSORS **********/
+static UINT8 ** LookupHandlerMemory(UINT8 cpu, UINT32 address, UINT32 * outRelativeAddress);
+
+static UINT32 DoCPURead(UINT8 cpu, UINT32 address, UINT8 bytes, UINT8 swap);
+static UINT32 DoMemoryRead(UINT8 * buf, UINT32 address, UINT8 bytes, UINT8 swap, CPUInfo * info);
+static void DoCPUWrite(UINT32 data, UINT8 cpu, UINT32 address, UINT8 bytes, UINT8 swap);
+static void DoMemoryWrite(UINT32 data, UINT8 * buf, UINT32 address, UINT8 bytes, UINT8 swap, CPUInfo * info);
+
+/********** CPU **********/
+static UINT8 CPUNeedsSwap(UINT8 cpu);
+static UINT8 RegionNeedsSwap(UINT8 region);
+
+static CPUInfo * GetCPUInfo(UINT8 cpu);
+static CPUInfo * GetRegionCPUInfo(UINT8 region);
+
+static UINT32 SwapAddress(UINT32 address, UINT8 dataSize, CPUInfo * info);
+
+static UINT32 ReadData(CheatAction * action);
+static void WriteData(CheatAction * action, UINT32 data);
+
+/********** WATCH **********/
+static void WatchCheatEntry(CheatEntry * entry, UINT8 associate);
+static void AddActionWatch(CheatAction * action, CheatEntry * entry);
+static void RemoveAssociatedWatches(CheatEntry * entry);
+
+static void ResetAction(CheatAction * action);
+static void ActivateCheat(CheatEntry * entry);
+static void DeactivateCheat(CheatEntry * entry);
+static void TempDeactivateCheat(CheatEntry * entry);
+
+static void cheat_periodicOperation(CheatAction * action);
+static void cheat_periodicAction(CheatAction * action);
+static void cheat_periodicEntry(CheatEntry * entry);
+
+static void UpdateAllCheatInfo(void);
+static void UpdateCheatInfo(CheatEntry * entry, UINT8 isLoadTime);
+
+static int IsAddressInRange(CheatAction * action, UINT32 length);
+
+static void BuildCPUInfoList(void);
+
+/*--------------------------------------------------------------
+ special key handler - check pressing shift, ctrl or alt key
+--------------------------------------------------------------*/
+
+static int ShiftKeyPressed(void)
+{
+ return (input_code_pressed(KEYCODE_LSHIFT) || input_code_pressed(KEYCODE_RSHIFT));
+}
+
+static int ControlKeyPressed(void)
+{
+ return (input_code_pressed(KEYCODE_LCONTROL) || input_code_pressed(KEYCODE_RCONTROL));
+}
+
+static int AltKeyPressed(void)
+{
+ return (input_code_pressed(KEYCODE_LALT) || input_code_pressed(KEYCODE_RALT));
+}
+
+/*---------------------------------------------------------------------------------------------------------------------
+ ReadKeyAsync - dirty hack until osd_readkey_unicode is supported in MAMEW re-implementation of osd_readkey_unicode
+---------------------------------------------------------------------------------------------------------------------*/
+
+#if 1
+
+#if OSD_READKEY_KLUDGE
+
+static int ReadKeyAsync(int flush)
+{
+ int code;
+
+ if(flush) // check key input
+ {
+ while(input_code_poll_switches(TRUE) != INPUT_CODE_INVALID) ;
+
+ return 0;
+ }
+
+ while(1) // check pressed key
+ {
+ code = input_code_poll_switches(FALSE);
+
+ if(code == INPUT_CODE_INVALID)
+ {
+ return 0;
+ }
+ else if((code >= KEYCODE_A) && (code <= KEYCODE_Z))
+ {
+ if(ShiftKeyPressed())
+ {
+ return 'A' + (code - KEYCODE_A);
+ }
+ else
+ {
+ return 'a' + (code - KEYCODE_A);
+ }
+ }
+ else if((code >= KEYCODE_0) && (code <= KEYCODE_9))
+ {
+ if(ShiftKeyPressed())
+ {
+ return ")!@#$%^&*("[code - KEYCODE_0];
+ }
+ else
+ {
+ return '0' + (code - KEYCODE_0);
+ }
+ }
+ else if((code >= KEYCODE_0_PAD) && (code <= KEYCODE_9_PAD))
+ {
+ return '0' + (code - KEYCODE_0_PAD);
+ }
+ else if(code == KEYCODE_TILDE)
+ {
+ if(ShiftKeyPressed())
+ {
+ return '~';
+ }
+ else
+ {
+ return '`';
+ }
+ }
+ else if(code == KEYCODE_MINUS)
+ {
+ if(ShiftKeyPressed())
+ {
+ return '_';
+ }
+ else
+ {
+ return '-';
+ }
+ }
+ else if(code == KEYCODE_EQUALS)
+ {
+ if(ShiftKeyPressed())
+ {
+ return '+';
+ }
+ else
+ {
+ return '=';
+ }
+ }
+ else if(code == KEYCODE_BACKSPACE)
+ {
+ return 0x08;
+ }
+ else if(code == KEYCODE_OPENBRACE)
+ {
+ if(ShiftKeyPressed())
+ {
+ return '{';
+ }
+ else
+ {
+ return '[';
+ }
+ }
+ else if(code == KEYCODE_CLOSEBRACE)
+ {
+ if(ShiftKeyPressed())
+ {
+ return '}';
+ }
+ else
+ {
+ return ']';
+ }
+ }
+ else if(code == KEYCODE_COLON)
+ {
+ if(ShiftKeyPressed())
+ {
+ return ':';
+ }
+ else
+ {
+ return ';';
+ }
+ }
+ else if(code == KEYCODE_QUOTE)
+ {
+ if(ShiftKeyPressed())
+ {
+ return '\"';
+ }
+ else
+ {
+ return '\'';
+ }
+ }
+ else if(code == KEYCODE_BACKSLASH)
+ {
+ if(ShiftKeyPressed())
+ {
+ return '|';
+ }
+ else
+ {
+ return '\\';
+ }
+ }
+ else if(code == KEYCODE_COMMA)
+ {
+ if(ShiftKeyPressed())
+ {
+ return '<';
+ }
+ else
+ {
+ return ',';
+ }
+ }
+ else if(code == KEYCODE_STOP)
+ {
+ if(ShiftKeyPressed())
+ {
+ return '>';
+ }
+ else
+ {
+ return '.';
+ }
+ }
+ else if(code == KEYCODE_SLASH)
+ {
+ if(ShiftKeyPressed())
+ {
+ return '?';
+ }
+ else
+ {
+ return '/';
+ }
+ }
+ else if(code == KEYCODE_SLASH_PAD)
+ {
+ return '/';
+ }
+ else if(code == KEYCODE_ASTERISK)
+ {
+ return '*';
+ }
+ else if(code == KEYCODE_MINUS_PAD)
+ {
+ return '-';
+ }
+ else if(code == KEYCODE_PLUS_PAD)
+ {
+ return '+';
+ }
+ else if(code == KEYCODE_SPACE)
+ {
+ return ' ';
+ }
+ }
+}
+
+#define osd_readkey_unicode ReadKeyAsync
+
+#endif
+
+#endif
+
+/*-------------------------------------
+ old_style_menu - export menu items
+-------------------------------------*/
+
+static void old_style_menu(const char **items, const char **subitems, char *flag, int selected, int arrowize_subitem)
+{
+ static ui_menu_item item_list[1000];
+ int menu_items;
+
+ for (menu_items = 0; items[menu_items]; menu_items++)
+ {
+ item_list[menu_items].text = items[menu_items];
+ item_list[menu_items].subtext = subitems ? subitems[menu_items] : NULL;
+ item_list[menu_items].flags = 0;
+ if (flag && flag[menu_items])
+ item_list[menu_items].flags |= MENU_FLAG_INVERT;
+ if (menu_items == selected)
+ {
+ if (arrowize_subitem & 1)
+ item_list[menu_items].flags |= MENU_FLAG_LEFT_ARROW;
+ if (arrowize_subitem & 2)
+ item_list[menu_items].flags |= MENU_FLAG_RIGHT_ARROW;
+ }
+ }
+ ui_menu_draw(item_list, menu_items, selected, NULL);
+}
+
+/*-------------------------------------------------
+ UIPressedRepoeatThrottle - key repeat handling
+-------------------------------------------------*/
+
+static int UIPressedRepeatThrottle(int code, int baseSpeed)
+{
+ static int lastCode = -1;
+ static int lastSpeed = -1;
+ static int incrementTimer = 0;
+ int pressed = 0;
+
+ const int kDelayRampTimer = 10;
+
+ if(input_port_type_pressed(code, 0))
+ {
+ if(lastCode != code) // different key pressed
+ {
+ lastCode = code;
+ lastSpeed = baseSpeed;
+ incrementTimer = kDelayRampTimer * lastSpeed;
+ }
+ else // same key pressed
+ {
+ incrementTimer--;
+
+ if(incrementTimer <= 0)
+ {
+ incrementTimer = kDelayRampTimer * lastSpeed;
+
+ lastSpeed /= 2;
+
+ if(lastSpeed < 1)
+ lastSpeed = 1;
+
+ pressed = 1;
+ }
+ }
+ }
+ else
+ {
+ if(lastCode == code)
+ lastCode = -1;
+ }
+
+ return input_ui_pressed_repeat(code, lastSpeed);
+}
+
+/*---------------------------------
+ ReadHexInput - check hex input
+---------------------------------*/
+
+static int ReadHexInput(void)
+{
+ int i;
+
+ for(i = 0; i < 10; i++)
+ {
+ if(input_code_pressed_once(KEYCODE_0 + i))
+ return i;
+ }
+
+ for(i = 0; i < 10; i++)
+ {
+ if(input_code_pressed_once(KEYCODE_0_PAD + i))
+ return i;
+ }
+
+ for(i = 0; i < 6; i++)
+ {
+ if(input_code_pressed_once(KEYCODE_A + i))
+ return i + 10;
+ }
+
+ return -1;
+}
+
+/*-----------------------------------------------------------------
+ DoDynamicEditTextField - edit text field with direct key input
+-----------------------------------------------------------------*/
+
+static char * DoDynamicEditTextField(char * buf)
+{
+ char code = osd_readkey_unicode(0) & 0xFF;
+
+ if(code == 0x08)
+ {
+ /* ----- backspace ----- */
+ if(buf)
+ {
+ size_t length = strlen(buf);
+
+ if(length > 0)
+ {
+ buf[length - 1] = 0;
+
+ if(length > 1)
+ buf = realloc(buf, length);
+ else
+ {
+ free(buf);
+
+ buf = NULL;
+ }
+ }
+ }
+ }
+ else
+ {
+ if(isprint(code))
+ {
+ if(buf)
+ {
+ size_t length = strlen(buf);
+
+ buf = realloc(buf, length + 2);
+
+ buf[length] = code;
+ buf[length + 1] = 0;
+ }
+ else
+ {
+ buf = malloc(2);
+
+ buf[0] = code;
+ buf[1] = 0;
+ }
+ }
+ }
+
+ return buf;
+}
+
+/*------------------------
+ DoStaticEditTextField
+------------------------*/
+
+static void DoStaticEditTextField(char * buf, int size)
+{
+ char code = osd_readkey_unicode(0) & 0xFF;
+ size_t length;
+
+ if(!buf)
+ return;
+
+ length = strlen(buf);
+
+ if(code == 0x08)
+ {
+ if(length > 0)
+ {
+ buf[length - 1] = 0;
+ }
+ }
+ else if(isprint(code))
+ {
+ if(length + 1 < size)
+ {
+ buf[length] = code;
+ buf[length + 1] = 0;
+ }
+ }
+}
+
+/*------------------------------------------------------------------
+ DoEditHexField - edit hex field with direct key input (unsigned)
+------------------------------------------------------------------*/
+
+static UINT32 DoEditHexField(UINT32 data)
+{
+ INT8 key;
+
+ if(input_code_pressed_once(KEYCODE_BACKSPACE))
+ {
+ /* ----- backspace ----- */
+ data >>= 4;
+
+ return data;
+ }
+ else
+ {
+ if(input_ui_pressed(IPT_UI_CLEAR))
+ {
+ data = 0;
+
+ return data;
+ }
+ }
+
+ key = ReadHexInput();
+
+ if(key != -1)
+ {
+ data <<= 4;
+ data |= key;
+ }
+
+ return data;
+}
+
+/*-----------------------------------------------------------------------
+ DoEditHexFieldSigned - edit hex field with direct key input (signed)
+-----------------------------------------------------------------------*/
+
+static UINT32 DoEditHexFieldSigned(UINT32 data, UINT32 mask)
+{
+ INT8 key;
+ UINT32 isNegative = data & mask;
+
+ if(isNegative)
+ data |= mask;
+
+ key = ReadHexInput();
+
+ if(key != -1)
+ {
+ if(isNegative)
+ data = (~data) + 1;
+
+ data <<= 4;
+ data |= key;
+
+ if(isNegative)
+ data = (~data) + 1;
+ }
+ else
+ {
+ if(input_code_pressed_once(KEYCODE_MINUS))
+ data = (~data) + 1;
+ }
+
+ return data;
+}
+
+/*--------------------------------------------------------
+ DoEditDecField - edit dec field with direct key input
+--------------------------------------------------------*/
+
+static INT32 DoEditDecField(INT32 data, INT32 min, INT32 max)
+{
+ char code = osd_readkey_unicode(0) & 0xFF;
+
+ if((code >= '0') && (code <= '9'))
+ {
+ data *= 10;
+ data += (code - '0');
+ }
+ else
+ {
+ if(code == '-')
+ data = -data;
+ else
+ {
+ /* ----- backspace ----- */
+ if(code == 0x08)
+ data /= 10;
+ }
+ }
+
+ /* ----- adjust value ----- */
+ if(data < min)
+ data = min;
+ if(data > max)
+ data = max;
+
+ return data;
+}
+
+/***************************************************************************
+ INITIALIZATION
+***************************************************************************/
+
+/*---------------------------------------
+ cheat_init - initialize cheat system
+---------------------------------------*/
+
+void cheat_init(running_machine *machine)
+{
+ /* ----- initialize lists ----- */
+ cheatList = NULL;
+ cheatListLength = 0;
+
+ watchList = NULL;
+ watchListLength = 0;
+
+ searchList = NULL;
+ searchListLength = 0;
+
+#ifdef MESS
+ InitMessCheats();
+#endif
+
+ /* ----- initialize flags ----- */
+ currentSearchIdx = 0;
+ foundCheatDatabase = 0;
+ cheatsDisabled = 0;
+ watchesDisabled = 0;
+ cheatOptions = 2;
+
+ fullMenuPageHeight = floor(1.0f / ui_get_line_height()) - 1;
+
+ /* ----- initialize CPU info for cheat system ----- */
+ BuildCPUInfoList();
+
+ /* ----- load cheat database ----- */
+ LoadCheatDatabase();
+
+ ResizeSearchList(1);
+ ResizeWatchList(20);
+
+ /* ----- initialize search regions ----- */
+ BuildSearchRegions(GetCurrentSearch());
+ AllocateSearchRegions(GetCurrentSearch());
+
+ /* ----- initialize string table ----- */
+ InitStringTable();
+
+ periodic_timer = timer_alloc(cheat_periodic);
+ timer_adjust(periodic_timer, attotime_make(0, Machine->screen[0].refresh), 0, attotime_make(0, Machine->screen[0].refresh));
+
+ add_exit_callback(machine, cheat_exit);
+}
+
+/*---------------------------------
+ cheat_exit - free cheat system
+---------------------------------*/
+
+static void cheat_exit(running_machine *machine)
+{
+ int i;
+
+ /* ----- save all cheats automatically if needed ----- */
+ if(TEST_FIELD(cheatOptions, AutoSaveEnabled))
+ DoAutoSaveCheats();
+
+ /* ----- free database ----- */
+ DisposeCheatDatabase();
+
+ /* ----- free watch lists ----- */
+ if(watchList)
+ {
+ for(i = 0; i < watchListLength; i++)
+ DisposeWatch(&watchList[i]);
+
+ free(watchList);
+
+ watchList = NULL;
+ }
+
+ /* ----- free search lists ----- */
+ if(searchList)
+ {
+ for(i = 0; i < searchListLength; i++)
+ DisposeSearch(i);
+
+ free(searchList);
+
+ searchList = NULL;
+ }
+
+ /* ----- free string table ----- */
+ FreeStringTable();
+
+ free(menuItemInfo);
+ menuItemInfo = NULL;
+
+#ifdef MESS
+ StopMessCheats();
+#endif
+
+ /* ----- free flags ----- */
+ cheatListLength = 0;
+ watchListLength = 0;
+ searchListLength = 0;
+ currentSearchIdx = 0;
+// cheatEngineWasActive = 0;
+ foundCheatDatabase = 0;
+ cheatsDisabled = 0;
+ watchesDisabled = 0;
+ mainDatabaseName[0] = 0;
+ menuItemInfoLength = 0;
+ cheatOptions = 0;
+}
+
+/*-----------------------------------------------------
+ cheat_menu - management for the cheat general menu
+-----------------------------------------------------*/
+
+int cheat_menu(int selection)
+{
+ enum
+ {
+ kMenu_EnableDisable = 0,
+ kMenu_AddEdit,
+ kMenu_Search,
+ kMenu_ChooseWatch,
+ kMenu_ReloadDatabase,
+ kMenu_Options,
+ kMenu_Return,
+
+ kMenu_Max
+ };
+
+ ui_menu_item menu_item[kMenu_Max];
+
+ INT32 sel;
+ UINT8 total = 0;
+
+ static INT32 submenu_choice = 0;
+ static int firstEntry = 0;
+ static int lastPstn = 0;
+
+ /* ----- allocate memory for item list ----- */
+ memset(menu_item, 0, sizeof(menu_item));
+
+// cheatEngineWasActive = 1;
+
+ sel = lastPstn;
+
+ /********** SUB MENU **********/
+ if(submenu_choice)
+ {
+ switch(sel)
+ {
+ case kMenu_EnableDisable:
+ submenu_choice = EnableDisableCheatMenu(submenu_choice, firstEntry);
+ break;
+
+ case kMenu_AddEdit:
+ submenu_choice = AddEditCheatMenu(submenu_choice);
+ break;
+
+ case kMenu_Search:
+ switch(EXTRACT_FIELD(cheatOptions, SearchBox))
+ {
+ case kSearchBox_Minimum:
+ submenu_choice = DoSearchMenuMinimum(submenu_choice);
+ break;
+
+ case kSearchBox_Classic:
+ submenu_choice = DoSearchMenuClassic(submenu_choice);
+ break;
+
+ case kSearchBox_Advanced:
+ submenu_choice = DoSearchMenu(submenu_choice);
+ break;
+ }
+ break;
+
+ case kMenu_ChooseWatch:
+ submenu_choice = ChooseWatch(submenu_choice);
+ break;
+
+ case kMenu_Options:
+ submenu_choice = SelectOptions(submenu_choice);
+ break;
+ }
+
+ firstEntry = 0;
+
+ /* ----- quick menu switching ------ */
+ if(submenu_choice < 0)
+ {
+ switch(submenu_choice)
+ {
+ case -1:
+ lastPstn = kMenu_EnableDisable;
+ break;
+
+ case -2:
+ lastPstn = kMenu_AddEdit;
+ break;
+
+ case -3:
+ lastPstn = kMenu_Search;
+ break;
+
+ case -4:
+ lastPstn = kMenu_ChooseWatch;
+ break;
+
+ default:
+ ui_popup_time(1, "undefined menu switching : %x", submenu_choice);
+ }
+
+ submenu_choice = 1;
+ }
+
+ return sel + 1;
+ }
+
+ /********** MENU CONSTRUCION **********/
+ menu_item[total++].text = ui_getstring(UI_enablecheat); // Enable/Disable a Cheat
+
+ menu_item[total++].text = ui_getstring(UI_addeditcheat); // Add/Edit a Cheat
+
+ switch(EXTRACT_FIELD(cheatOptions, SearchBox)) // Search a Cheat
+ {
+ case kSearchBox_Minimum:
+ menu_item[total++].text = "Search a Cheat (Minimum Mode)";
+ break;
+
+ case kSearchBox_Classic:
+ menu_item[total++].text = "Search a Cheat (Classic Mode)";
+ break;
+
+ case kSearchBox_Advanced:
+ menu_item[total++].text = "Search a Cheat (Advanced Mode)";
+ break;
+ }
+
+ menu_item[total++].text = ui_getstring(UI_memorywatch); // Configure Watchpoints
+
+ menu_item[total++].text = ui_getstring(UI_reloaddatabase); // Reload Cheat Database
+
+ menu_item[total++].text = ui_getstring(UI_options); // Options
+
+ menu_item[total++].text = ui_getstring(UI_returntomain); // return to the MAME general menu
+
+ menu_item[total].text = NULL; // terminate array
+
+ /* ----- adjust cursor postion ----- */
+ if(sel < 0)
+ sel = 0;
+ if(sel > (total - 1))
+ sel = total - 1;
+
+ /* ----- print it ----- */
+ ui_menu_draw(menu_item, total, sel, NULL);
+
+ /********** KEY HANDLING **********/
+ if(UIPressedRepeatThrottle(IPT_UI_DOWN, kVerticalKeyRepeatRate))
+ {
+ if(sel < (total - 1))
+ sel++;
+ else
+ sel = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_UP, kVerticalKeyRepeatRate))
+ {
+ if(sel > 0)
+ sel--;
+ else
+ sel = total - 1;
+ }
+
+ if(input_ui_pressed(IPT_UI_SELECT))
+ {
+ switch(sel)
+ {
+ case kMenu_Return:
+ submenu_choice = 0;
+ sel = -1;
+ lastPstn = 0; // if cursor is now on the return item, adjust cursor keeper
+ break;
+
+ case kMenu_ReloadDatabase:
+ ReloadCheatDatabase();
+ break;
+
+ default:
+ firstEntry = 1;
+ submenu_choice = 1;
+ break;
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_RELOAD_CHEAT))
+ ReloadCheatDatabase();
+
+ if(input_ui_pressed(IPT_UI_CANCEL))
+ {
+ if(sel == kMenu_Return)
+ lastPstn = 0; // if cursor is now on the return item, adjust cursor keeper
+
+ sel = -1;
+ }
+
+ /* ----- keep current cursor position ----- */
+ if(sel >= 0)
+ lastPstn = sel;
+
+ return sel + 1;
+}
+
+/*----------
+ DoShift
+----------*/
+
+static UINT32 DoShift(UINT32 input, INT8 shift)
+{
+ if(shift > 0)
+ return input >> shift;
+ else
+ return input << -shift;
+}
+
+/*----------------------------------------
+ BCDToDecimal - convert a value to hex
+----------------------------------------*/
+
+static UINT32 BCDToDecimal(UINT32 value)
+{
+ UINT32 accumulator = 0;
+ UINT32 multiplier = 1;
+ int i;
+
+ for(i = 0; i < 8; i++)
+ {
+ accumulator += (value & 0xF) * multiplier;
+
+ multiplier *= 10;
+ value >>= 4;
+ }
+
+ return accumulator;
+}
+
+/*----------------------------------------
+ DecimalToBCD - convert a value to dec
+----------------------------------------*/
+
+static UINT32 DecimalToBCD(UINT32 value)
+{
+ UINT32 accumulator = 0;
+ UINT32 divisor = 10;
+ int i;
+
+ for(i = 0; i < 8; i++)
+ {
+ UINT32 temp;
+
+ temp = value % divisor;
+ value -= temp;
+ temp /= divisor / 10;
+
+ accumulator += temp << (i * 4);
+
+ divisor *= 10;
+ }
+
+ return accumulator;
+}
+
+/*----------------------
+ RebuildStringTables
+----------------------*/
+
+static void RebuildStringTables(void)
+{
+ UINT32 storageNeeded, i;
+ char * traverse;
+
+ storageNeeded = (menuStrings.mainStringLength + menuStrings.subStringLength) * menuStrings.numStrings;
+
+ menuStrings.mainList = (const char **) realloc((char *) menuStrings.mainList, sizeof(char *) * menuStrings.length);
+ menuStrings.subList = (const char **) realloc((char *) menuStrings.subList, sizeof(char *) * menuStrings.length);
+ menuStrings.flagList = realloc( menuStrings.flagList, sizeof(char) * menuStrings.length);
+ menuStrings.mainStrings = realloc( menuStrings.mainStrings, sizeof(char *) * menuStrings.numStrings);
+ menuStrings.subStrings = realloc( menuStrings.subStrings, sizeof(char *) * menuStrings.numStrings);
+ menuStrings.buf = realloc( menuStrings.buf, sizeof(char) * storageNeeded);
+
+ if( (!menuStrings.mainList && menuStrings.length) ||
+ (!menuStrings.subList && menuStrings.length) ||
+ (!menuStrings.flagList && menuStrings.length) ||
+ (!menuStrings.mainStrings && menuStrings.numStrings) ||
+ (!menuStrings.subStrings && menuStrings.numStrings) ||
+ (!menuStrings.buf && storageNeeded))
+ {
+ fatalerror( "cheat: memory allocation error\n"
+ " length = %.8X\n"
+ " numStrings = %.8X\n"
+ " mainStringLength = %.8X\n"
+ " subStringLength = %.8X\n"
+ "%p %p %p %p %p %p\n",
+ menuStrings.length,
+ menuStrings.numStrings,
+ menuStrings.mainStringLength,
+ menuStrings.subStringLength,
+
+ menuStrings.mainList,
+ menuStrings.subList,
+ menuStrings.flagList,
+ menuStrings.mainStrings,
+ menuStrings.subStrings,
+ menuStrings.buf);
+ }
+
+ traverse = menuStrings.buf;
+
+ for(i = 0; i < menuStrings.numStrings; i++)
+ {
+ menuStrings.mainStrings[i] = traverse;
+ traverse += menuStrings.mainStringLength;
+
+ menuStrings.subStrings[i] = traverse;
+ traverse += menuStrings.subStringLength;
+ }
+}
+
+/*-----------------------------------------------------------
+ RequestStrings - check list length and rebuild if needed
+-----------------------------------------------------------*/
+
+static void RequestStrings(UINT32 length, UINT32 numStrings, UINT32 mainStringLength, UINT32 subStringLength)
+{
+ UINT8 changed = 0;
+
+ if(menuStrings.length < length)
+ {
+ menuStrings.length = length;
+
+ changed = 1;
+ }
+
+ if(menuStrings.numStrings < numStrings)
+ {
+ menuStrings.numStrings = numStrings;
+
+ changed = 1;
+ }
+
+ if(menuStrings.mainStringLength < mainStringLength)
+ {
+ menuStrings.mainStringLength = mainStringLength;
+
+ changed = 1;
+ }
+
+ if(menuStrings.subStringLength < subStringLength)
+ {
+ menuStrings.subStringLength = subStringLength;
+
+ changed = 1;
+ }
+
+ if(changed)
+ RebuildStringTables();
+}
+
+/*------------------
+ InitStringTable
+------------------*/
+
+static void InitStringTable(void)
+{
+ memset(&menuStrings, 0, sizeof(MenuStringList));
+}
+
+/*------------------
+ FreeStringTable
+------------------*/
+
+static void FreeStringTable(void)
+{
+ free((char *)menuStrings.mainList);
+ free((char *)menuStrings.subList);
+ free(menuStrings.flagList);
+ free(menuStrings.mainStrings);
+ free(menuStrings.subStrings);
+ free(menuStrings.buf);
+
+ memset(&menuStrings, 0, sizeof(MenuStringList));
+}
+
+/*---------------------------------------------------------------------------
+ CreateStringCopy - copy stirng. It is only called on LoadCheatFile() now
+---------------------------------------------------------------------------*/
+
+static char * CreateStringCopy(char * buf)
+{
+ char * temp = NULL;
+
+ if(buf)
+ {
+ size_t length = strlen(buf) + 1;
+
+ temp = malloc(length);
+
+ if(temp)
+ memcpy(temp, buf, length);
+ }
+
+ return temp;
+}
+
+/*------------------------------------------------------------
+ UserSelectValueMenu - management for value-selection menu
+------------------------------------------------------------*/
+
+static INT32 UserSelectValueMenu(int selection, CheatEntry * entry)
+{
+ char buf[2048];
+ int sel;
+ CheatAction * action;
+ static INT32 value = -1;
+ static int firstTime = 1;
+ int delta = 0;
+ int displayValue;
+ int keyValue;
+ int forceUpdate = 0;
+
+ sel = selection - 1;
+
+ action = &entry->actionList[0];
+
+ /* ----- if we're just entering, save the value ----- */
+ if(firstTime)
+ {
+ UINT32 min = EXTRACT_FIELD(action->type, UserSelectMinimum);
+ UINT32 max = action->originalDataField + min;
+
+ value = ReadData(action);
+
+ /* ----- and check for valid BCD values ----- */
+ if(TEST_FIELD(action->type, UserSelectBCD))
+ {
+ value = BCDToDecimal(value);
+ value = DecimalToBCD(value);
+ }
+
+ if(value < min)
+ value = max;
+ if(value > max)
+ value = min;
+
+ action->data = value;
+ firstTime = 0;
+ }
+
+ displayValue = value;
+
+ /* ----- if the minimum display value is one, add one to the display value ----- */
+ if(TEST_FIELD(action->type, UserSelectMinimumDisplay))
+ {
+ if(TEST_FIELD(action->type, UserSelectBCD))
+ displayValue = BCDToDecimal(displayValue); // bcd -> dec
+
+ displayValue++;
+
+ if(TEST_FIELD(action->type, UserSelectBCD))
+ displayValue = DecimalToBCD(displayValue); // dec -> bcd
+ }
+
+ /* ----- print it ----- */
+ if(TEST_FIELD(action->type, UserSelectBCD))
+ sprintf(buf, "\t%s\n\t%.2X\n", ui_getstring(UI_search_select_value), displayValue);
+ else
+ sprintf(buf, "\t%s\n\t%.2X (%d)\n", ui_getstring(UI_search_select_value), displayValue, displayValue);
+
+ /* ----- create fake menu strings ----- */
+ strcat(buf, "\t");
+ strcat(buf, ui_getstring(UI_lefthilight));
+ strcat(buf, " ");
+ strcat(buf, ui_getstring(UI_OK));
+ strcat(buf, " ");
+ strcat(buf, ui_getstring(UI_righthilight));
+
+ /* ----- print it ----- */
+ ui_draw_message_window(buf);
+
+ /********** KEY HANDLING **********/
+ if(UIPressedRepeatThrottle(IPT_UI_LEFT, kHorizontalFastKeyRepeatRate))
+ delta = -1;
+
+ if(UIPressedRepeatThrottle(IPT_UI_RIGHT, kHorizontalFastKeyRepeatRate))
+ delta = 1;
+
+ if(input_ui_pressed(IPT_UI_SELECT))
+ {
+ /* ### redundant?? probably can be removed ### */
+ if(!firstTime)
+ {
+ int i;
+
+ /* ----- copy data field if copy previous value ----- */
+ for(i = 0; i < entry->actionListLength; i++)
+ {
+ CheatAction * traverse = &entry->actionList[i];
+
+ INT32 copyValue = value;
+
+ if(TEST_FIELD(traverse->type, LinkEnable) && TEST_FIELD(traverse->type, LinkCopyPreviousValue))
+ {
+ INT32 newData = traverse->originalDataField;
+
+ if(TEST_FIELD(traverse->type, UserSelectBCD))
+ {
+ copyValue = BCDToDecimal(value);
+ copyValue = DecimalToBCD(value);
+
+ newData = BCDToDecimal(newData);
+ newData = DecimalToBCD(newData);
+ }
+
+ copyValue += newData;
+
+ if(TEST_FIELD(traverse->type, UserSelectBCD))
+ {
+ copyValue = BCDToDecimal(copyValue);
+ copyValue = DecimalToBCD(copyValue);
+ }
+ }
+
+ if(!i || TEST_FIELD(traverse->type, LinkCopyPreviousValue))
+ traverse->data = copyValue;
+ }
+
+ ActivateCheat(entry);
+ }
+
+ firstTime = 1;
+ sel = -1;
+ }
+
+ if(input_ui_pressed(IPT_UI_CANCEL))
+ {
+ firstTime = 1;
+ sel = -1;
+ }
+
+ /* ----- get other key inputs ----- */
+ keyValue = ReadHexInput();
+
+ /* ----- BCD check for input key ----- */
+ if((keyValue != -1) && TEST_FIELD(action->type, UserSelectBCD) && ((keyValue < 0 ) || (keyValue > 9)))
+ keyValue = -1;
+
+ /* ----- if we got a key ----- */
+ if(keyValue != -1)
+ {
+ /* ----- add it ----- */
+ value <<= 4;
+
+ switch(EXTRACT_FIELD(action->type, BytesUsed))
+ {
+ case 0: // 8 bit
+ value &= 0xF0;
+ break;
+ case 1: // 16 bit
+ value &= 0xFFF0;
+ break;
+ case 2: // 24 bit
+ value &= 0xFFFFF0;
+ break;
+ case 3: // 32 bit
+ value &= 0xFFFFFFF0;
+ break;
+ }
+
+ value |= keyValue & 0x0F;
+
+ delta = 0;
+ forceUpdate = 1;
+ }
+
+ /* ----- wrap-around with BCD stuff. ### this is a really bad way to do this ----- */
+ if(delta || forceUpdate)
+ {
+ INT32 min = EXTRACT_FIELD(action->type, UserSelectMinimum);
+ INT32 max = action->originalDataField + min;
+
+ if(TEST_FIELD(action->type, UserSelectBCD))
+ value = BCDToDecimal(value);
+
+ value += delta;
+
+ if(TEST_FIELD(action->type, UserSelectBCD))
+ value = DecimalToBCD(value);
+
+ if(value < min)
+ value = max;
+ if(value > max)
+ value = min;
+ }
+
+ return sel + 1;
+}
+
+/*-------------------------------------------------
+ CommentMenu - management comment for code menu
+-------------------------------------------------*/
+
+static INT32 CommentMenu(int selection, CheatEntry * entry)
+{
+ char buf[2048];
+ int sel;
+ const char * comment;
+
+ if(!entry)
+ return 0;
+
+ sel = selection - 1;
+
+ /********** MENU CONSTRUCTION **********/
+ if(entry->comment && entry->comment[0])
+ comment = entry->comment;
+ else
+ comment = "(none)";
+
+ sprintf(buf, "%s\n\t%s %s %s", comment, ui_getstring(UI_lefthilight), ui_getstring(UI_OK), ui_getstring(UI_righthilight));
+
+ /* ----- print it ----- */
+ ui_draw_message_window(buf);
+
+ /********** KEY HANDLING **********/
+ if(input_ui_pressed(IPT_UI_SELECT) || input_ui_pressed(IPT_UI_CANCEL))
+ sel = -1;
+
+ return sel + 1;
+}
+
+/*--------------------------------------------------------------
+ EnableDisableCheatMenu - management for Enable/Disable menu
+--------------------------------------------------------------*/
+
+static int EnableDisableCheatMenu(int selection, int firstTime)
+{
+ INT32 sel;
+ static INT32 submenu_choice = 0;
+ static INT32 submenu_id = 0; // 0 = none, 1 = comment, 2 = value-selection, 3 = editCheat
+ const char ** menu_item;
+ const char ** menu_subitem;
+ char * flagBuf;
+ INT32 i;
+ INT32 total = 0;
+
+ CheatEntry * entry;
+
+ RequestStrings(cheatListLength + 5, 0, 0, 0);
+
+ menu_item = menuStrings.mainList;
+ menu_subitem = menuStrings.subList;
+ flagBuf = menuStrings.flagList;
+
+ sel = selection - 1;
+
+ /********** SUB MENU **********/
+ if(submenu_choice)
+ {
+ switch(submenu_id)
+ {
+ case 1:
+ submenu_choice = CommentMenu(submenu_choice, &cheatList[sel]);
+ break;
+
+ case 2:
+ submenu_choice = UserSelectValueMenu(submenu_choice, &cheatList[sel]);
+ break;
+
+ case 3:
+ submenu_choice = EditCheatMenu(&cheatList[sel], sel, submenu_choice);
+ break;
+
+ default:
+ submenu_choice = 0;
+ }
+
+ /* ----- meaningless ? because no longer return with sel = -1 (pressed UI_CONFIG in submenu) ----- */
+// if(submenu_choice == -1)
+// {
+// submenu_choice = 0;
+// sel = -2;
+// }
+
+ return sel + 1;
+ }
+
+ /********** MENU CONSTRUCTION **********/
+ for(i = 0; i < cheatListLength; i++)
+ {
+ CheatEntry * traverse = &cheatList[i];
+
+ /* ----- get code title ----- */
+ if(traverse->name)
+ menu_item[total] = traverse->name;
+ else
+ menu_item[total] = "null name";
+
+ menu_subitem[total] = NULL;
+
+ /* ----- get subitem ----- */
+ if(traverse->flags & kCheatFlag_Select) // label-selection gets sub-lebel name or "OFF"
+ {
+ /* ----- no "OFF" item if one shot ----- */
+ if((traverse->flags & kCheatFlag_OneShot) && !traverse->selection)
+ traverse->selection = 1; // adjust to 1st linked-code
+
+ /* ----- set sub-label name or "OFF" to subitem ----- */
+ if(traverse->selection && (traverse->selection < traverse->actionListLength))
+ menu_subitem[total] = traverse->actionList[traverse->selection].optionalName;
+ else
+ menu_subitem[total] = ui_getstring(UI_off);
+ }
+ else // others get "ON" or "OFF"
+ {
+ /* ----- add subitems for all cheats that are not comments ----- */
+ if(!(traverse->flags & kCheatFlag_Null))
+ {
+ if(traverse->flags & kCheatFlag_OneShot)
+ menu_subitem[total] = ui_getstring(UI_set);
+ else
+ {
+ if(traverse->flags & kCheatFlag_Active)
+ menu_subitem[total] = ui_getstring(UI_on);
+ else
+ menu_subitem[total] = ui_getstring(UI_off);
+ }
+ }
+ }
+
+ /* ----- get comment flag ----- */
+ if(traverse->comment && traverse->comment[0])
+ flagBuf[total++] = 1;
+ else
+ flagBuf[total++] = 0;
+ }
+
+ /* ----- if no code, set special message ----- */
+ if(cheatListLength == 0)
+ {
+ if(foundCheatDatabase) // the database found but no code
+ {
+ menu_item[total] = "there are no cheats for this game";
+ menu_subitem[total] = NULL;
+ flagBuf[total++] = 0;
+ }
+ else // the database itself not found
+ {
+ menu_item[total] = "cheat database not found";
+ menu_subitem[total] = NULL;
+ flagBuf[total++] = 0;
+
+ menu_item[total] = "unzip it and place it in the MAME directory";
+ menu_subitem[total] = NULL;
+ flagBuf[total++] = 0;
+ }
+ }
+
+ /* ----- set return item ----- */
+ menu_item[total] = ui_getstring(UI_returntoprior);
+ menu_subitem[total] = NULL;
+ flagBuf[total++] = 0;
+
+ menu_item[total] = 0; // terminate array
+ menu_subitem[total] = 0;
+ flagBuf[total] = 0;
+
+ /* ----- adjust cursor position ----- */
+ if(sel < 0)
+ sel = 0;
+ if(sel > (total - 1))
+ sel = total - 1;
+
+ /* ----- if cursor is on comment code, skip it ----- */
+ if(cheatListLength && firstTime)
+ {
+ while((sel < total - 1) && (cheatList[sel].flags & kCheatFlag_Null))
+ sel++;
+ }
+
+ /* ----- draw it ----- */
+ old_style_menu(menu_item, menu_subitem, flagBuf, sel, 0);
+
+ /********** KEY HANDLING **********/
+ if(UIPressedRepeatThrottle(IPT_UI_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel++;
+
+ if(sel >= total)
+ sel = 0;
+
+ if(cheatListLength)
+ {
+ /* ----- if cursor is on comment code, skip it ----- */
+ for(i = 0; (i < fullMenuPageHeight / 2) && (sel < total - 1) && (cheatList[sel].flags & kCheatFlag_Null); i++)
+ sel++;
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_UP, kVerticalKeyRepeatRate))
+ {
+ sel--;
+
+ if(sel < 0)
+ sel = total - 1;
+ else
+ {
+ if(cheatListLength)
+ {
+ /* ----- if cursor is on comment code, skip it ----- */
+ for(i = 0; (i < fullMenuPageHeight / 2) && (sel != total - 1) && (cheatList[sel].flags & kCheatFlag_Null); i++)
+ {
+ sel--;
+
+ if(sel < 0)
+ sel = total - 1;
+ }
+ }
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_UP, kVerticalKeyRepeatRate))
+ {
+ sel -= fullMenuPageHeight;
+
+ if(sel < 0)
+ sel = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel += fullMenuPageHeight;
+
+ if(sel >= total)
+ sel = total - 1;
+ }
+
+ if((sel >= 0) && (sel < cheatListLength))
+ entry = &cheatList[sel];
+ else
+ entry = NULL;
+
+ if(UIPressedRepeatThrottle(IPT_UI_LEFT, kHorizontalSlowKeyRepeatRate))
+ {
+ if((sel < (total - 1)) && entry)
+ {
+ if(entry->flags & kCheatFlag_Select) // label-selection
+ {
+ /* ----- move selection to unLinkExtension code or last linked-code ----- */
+ do{
+ entry->selection--;
+
+ if(entry->flags & kCheatFlag_OneShot)
+ {
+ if(entry->selection <= 0)
+ entry->selection = entry->actionListLength - 1; // first -> last
+
+ /* ----- no action when press arrow key ----- */
+ entry->flags &= ~kCheatFlag_DoOneShot;
+ }
+ else
+ {
+ if(entry->selection < 0)
+ entry->selection = entry->actionListLength - 1; // OFF -> last
+
+ if(entry->selection == 0)
+ DeactivateCheat(entry); // OFF
+ else
+ {
+ if(!TEST_FIELD(entry->actionList[entry->selection].type, LinkExtension))
+ ActivateCheat(entry); // ON
+ }
+ }
+ }while(entry->selection && TEST_FIELD(entry->actionList[entry->selection].type, LinkExtension));
+ }
+ else // others
+ {
+ if(!(entry->flags & kCheatFlag_Null) && !(entry->flags & kCheatFlag_OneShot))
+ {
+ int active = entry->flags & kCheatFlag_Active;
+
+ active ^= 0x01;
+
+ /* ----- get the user's selected value if needed ----- */
+ if((entry->flags & kCheatFlag_UserSelect) && active)
+ {
+ submenu_id = 2;
+ submenu_choice = 1;
+ }
+ else
+ {
+ if(active)
+ ActivateCheat(entry); // ON
+ else
+ DeactivateCheat(entry); // OFF
+ }
+ }
+ }
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_RIGHT, kHorizontalSlowKeyRepeatRate))
+ {
+ if((sel < (total - 1)) && entry)
+ {
+ if(entry->flags & kCheatFlag_Select) // label-selection
+ {
+ /* ----- move selection to unLinkExtension code or 1st code ----- */
+ do{
+ entry->selection++;
+
+ if(entry->flags & kCheatFlag_OneShot)
+ {
+ if(entry->selection >= entry->actionListLength)
+ {
+ entry->selection = 1; // last -> first
+
+ if(entry->selection >= entry->actionListLength)
+ entry->selection = 0;
+ }
+ /* ----- no action when press arrow key ----- */
+ entry->flags &= ~kCheatFlag_DoOneShot;
+ }
+ else // others
+ {
+ if(entry->selection >= entry->actionListLength)
+ {
+ entry->selection = 0; // last -> OFF
+
+ DeactivateCheat(entry); // OFF
+ }
+ else
+ {
+ if(!TEST_FIELD(entry->actionList[entry->selection].type, LinkExtension))
+ ActivateCheat(entry); // ON
+ }
+ }
+ }while(entry->selection && TEST_FIELD(entry->actionList[entry->selection].type, LinkExtension));
+ }
+ else
+ {
+ if(!(entry->flags & kCheatFlag_Null) && !(entry->flags & kCheatFlag_OneShot))
+ {
+ int active = entry->flags & kCheatFlag_Active;
+
+ active ^= 0x01; // toggle On and OFF
+
+ /* ----- get the user's selected value if needed ----- */
+ if((entry->flags & kCheatFlag_UserSelect) && active)
+ {
+ submenu_id = 2;
+ submenu_choice = 1;
+ }
+ else
+ {
+ if(active)
+ ActivateCheat(entry); // ON
+ else
+ DeactivateCheat(entry); // OFF
+ }
+ }
+ }
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_SELECT))
+ {
+ if(sel == (total - 1))
+ {
+ /* ----- return to prior menu ----- */
+ submenu_choice = 0;
+ sel = -1;
+ }
+ else
+ {
+ if((sel < (total - 1)) && entry)
+ {
+ if(ShiftKeyPressed())
+ {
+ if(entry->comment && entry->comment[0])
+ {
+ /* ----- display comment ------ */
+ submenu_id = 1;
+ submenu_choice = 1;
+ }
+ else
+ goto doActivate;
+ }
+ else
+ {
+ doActivate:
+
+ if(entry->flags & kCheatFlag_UserSelect)
+ {
+ /* ----- value-selection menu ----- */
+ submenu_id = 2;
+ submenu_choice = 1;
+ }
+ else
+ {
+ ActivateCheat(entry); // ON
+
+ /* ----- set do one shot flag if label-selection ----- */
+ if((entry->flags & kCheatFlag_Select) && (entry->flags & kCheatFlag_OneShot))
+ entry->flags |= kCheatFlag_DoOneShot;
+
+ /* ----- display one shot message if one shot ----- */
+ if(entry->flags & kCheatFlag_OneShot)
+ ui_popup_time(1, "%s activated", entry->name);
+ }
+ }
+ }
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_WATCH_VALUE))
+ WatchCheatEntry(entry, 0);
+
+ if(ShiftKeyPressed())
+ {
+ if(input_ui_pressed(IPT_UI_SAVE_CHEAT)) // shift + save = save all codes
+ {
+ for(i = 0; i < cheatListLength; i++)
+ SaveCheat(&cheatList[i], 0, 0);
+
+ ui_popup_time(1, "%d cheats saved", cheatListLength);
+ }
+
+ if(input_ui_pressed(IPT_UI_ADD_CHEAT)) // shift + add = add new emypty code
+ AddCheatBefore(sel);
+
+ if(input_ui_pressed(IPT_UI_DELETE_CHEAT)) // shift + delete = delete selected code
+ DeleteCheatAt(sel);
+ }
+ else
+ {
+ if(ControlKeyPressed())
+ {
+ if(input_ui_pressed(IPT_UI_SAVE_CHEAT)) // ctrl + save = save activation key
+ {
+ if((entry->flags & kCheatFlag_HasActivationKey1) || (entry->flags & kCheatFlag_HasActivationKey2))
+ {
+ SaveCheat(entry, sel, 1);
+
+ ui_popup_time(1, "activation key saved");
+ }
+ else
+ ui_popup_time(1, "no activation key");
+ }
+ }
+ else
+ {
+ if(input_ui_pressed(IPT_UI_SAVE_CHEAT))
+ SaveCheat(entry, 0, 0); // save current entry
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_EDIT_CHEAT) && entry) // edit selected code
+ {
+ submenu_id = 3;
+ submenu_choice = 1;
+ }
+
+ if(input_ui_pressed(IPT_UI_RELOAD_CHEAT))
+ ReloadCheatDatabase();
+
+ if(UIPressedRepeatThrottle(IPT_UI_ZOOM_IN, kVerticalKeyRepeatRate))
+ /* ----- quick menu switch : enable/disable -> add/edit ----- */
+ sel = -3;
+
+ if(UIPressedRepeatThrottle(IPT_UI_ZOOM_OUT, kVerticalKeyRepeatRate))
+ /* ----- quick menu switch : enable/disable -> watchpoint list ----- */
+ sel = -5;
+
+ if(input_ui_pressed(IPT_UI_CANCEL))
+ sel = -1;
+
+ return sel + 1;
+}
+
+/*--------------------------------------------------------
+ AddEditCheatMenu - management for Add/Edit cheat menu
+--------------------------------------------------------*/
+
+static int AddEditCheatMenu(int selection)
+{
+ INT32 sel;
+ static INT32 submenuChoice = 0;
+ static INT32 submenuCheat = 0;
+ const char ** menu_item;
+ INT32 i;
+ INT32 total = 0;
+ CheatEntry * entry;
+
+ sel = selection - 1;
+
+ RequestStrings(cheatListLength + 2, 0, 0, 0);
+
+ menu_item = menuStrings.mainList;
+
+ /********** SUB MENU **********/
+ if(submenuChoice)
+ {
+ submenuChoice = EditCheatMenu(&cheatList[submenuCheat], submenuCheat, submenuChoice);
+
+ /* ----- meaningless ? because no longer return with sel = -1 (pressed UI_CONFIG in submenu) ----- */
+// if(submenuChoice == -1)
+// {
+// submenuChoice = 0;
+// sel = -2;
+// }
+
+ return sel + 1;
+ }
+
+ /********** MENU CONSTRUCTION **********/
+ for(i = 0; i < cheatListLength; i++)
+ {
+ CheatEntry * traverse = &cheatList[i];
+
+ if(traverse->name)
+ menu_item[total++] = traverse->name; // code title
+ else
+ menu_item[total++] = "(none)";
+ }
+
+ menu_item[total++] = ui_getstring(UI_returntoprior); // return
+
+ menu_item[total] = NULL; // terminate array
+
+ /* ----- adjust current cursor position ----- */
+ if(sel < 0)
+ sel = 0;
+ if(sel >= total)
+ sel = total - 1;
+
+ /* ----- draw it ----- */
+ old_style_menu(menu_item, NULL, NULL, sel, 0);
+
+ /********** KEY HANDLING **********/
+ if(UIPressedRepeatThrottle(IPT_UI_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel++;
+
+ if(sel >= total)
+ sel = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_UP, kVerticalKeyRepeatRate))
+ {
+ sel--;
+
+ if(sel < 0)
+ sel = total - 1;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_UP, kVerticalKeyRepeatRate))
+ {
+ sel -= fullMenuPageHeight;
+
+ if(sel < 0)
+ sel = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel += fullMenuPageHeight;
+
+ if(sel >= total)
+ sel = total - 1;
+ }
+
+ if(sel < (total - 1))
+ entry = &cheatList[sel];
+ else
+ entry = NULL;
+
+ if(input_ui_pressed(IPT_UI_SAVE_CHEAT))
+ {
+ if(ShiftKeyPressed())
+ {
+ for(i = 0; i < cheatListLength; i++) // shift + save = save all codes
+ SaveCheat(&cheatList[i], 0, 0);
+
+ ui_popup_time(1, "%d cheats saved", cheatListLength);
+ }
+ else
+ {
+ if(ControlKeyPressed())
+ {
+ if((entry->flags & kCheatFlag_HasActivationKey1) || (entry->flags & kCheatFlag_HasActivationKey2))
+ {
+ SaveCheat(entry, sel, 1); // ctrl + save = save activation key
+
+ ui_popup_time(1, "activation key saved");
+ }
+ else
+ ui_popup_time(1, "no activation key");
+ }
+ else
+ SaveCheat(entry, 0, 0); // save current entry
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_ADD_CHEAT))
+ AddCheatBefore(sel); // insert empty code
+
+ if(input_ui_pressed(IPT_UI_DELETE_CHEAT))
+ DeleteCheatAt(sel); // delete selected code
+
+ if(input_ui_pressed(IPT_UI_WATCH_VALUE))
+ WatchCheatEntry(entry, 0); // watch selected code
+
+ if(input_ui_pressed(IPT_UI_EDIT_CHEAT)) // edit selected code
+ {
+ /* ----- if selected item is not return, go to edit menu ----- */
+ if(sel < (total - 1))
+ {
+ submenuCheat = sel;
+ submenuChoice = 1;
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_SELECT))
+ {
+ /* ----- if selected item is return, return previous menu ----- */
+ if(sel >= (total - 1))
+ {
+ submenuChoice = 0;
+ sel = -1;
+ }
+ /* ----- otherwise, go to edit menu (same as pressing edit key) ----- */
+ else
+ {
+ submenuCheat = sel;
+ submenuChoice = 1;
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_RELOAD_CHEAT))
+ ReloadCheatDatabase();
+
+ if(UIPressedRepeatThrottle(IPT_UI_ZOOM_IN, kVerticalKeyRepeatRate))
+ /* ----- quick menu switch : add/edit -> search ----- */
+ sel = -4;
+
+ if(UIPressedRepeatThrottle(IPT_UI_ZOOM_OUT, kVerticalKeyRepeatRate))
+ /* ----- quick menu switch : add/edit -> enable/disable ----- */
+ sel = -2;
+
+ if(input_ui_pressed(IPT_UI_CANCEL))
+ sel = -1;
+
+ return sel + 1;
+}
+
+/*------------------------------------------------
+ EditCheatMenu - management for edit code menu
+------------------------------------------------*/
+
+static int EditCheatMenu(CheatEntry * entry, int index, int selection)
+{
+ static const char * kTypeNames[] =
+ {
+ "Normal/Delay",
+ "Wait",
+ "Ignore Decrement",
+ "Watch",
+ "Comment",
+ "Select"
+ };
+
+ static const char * kNumbersTable[] =
+ {
+ "0", "1", "2", "3", "4", "5", "6", "7",
+ "8", "9", "10", "11", "12", "13", "14", "15",
+ "16", "17", "18", "19", "20", "21", "22", "23",
+ "24", "25", "26", "27", "28", "29", "30", "31"
+ };
+
+ static const char * kOperationNames[] =
+ {
+ "Write",
+ "Add/Subtract",
+ "Force Range",
+ "Set/Clear Bits",
+ "Write If Match",
+ "Unused (5)",
+ "Unused (6)",
+ "Null"
+ };
+
+ static const char * kAddSubtractNames[] =
+ {
+ "Add",
+ "Subtract"
+ };
+
+ static const char * kSetClearNames[] =
+ {
+ "Set",
+ "Clear"
+ };
+
+ static const char * kPrefillNames[] =
+ {
+ "None",
+ "FF",
+ "00",
+ "01"
+ };
+
+ static const char * kEndiannessNames[] =
+ {
+ "Normal",
+ "Swap"
+ };
+
+ static const char * kRegionNames[] =
+ {
+ "CPU1", "CPU2", "CPU3", "CPU4", "CPU5", "CPU6", "CPU7", "CPU8",
+ "GFX1", "GFX2", "GFX3", "GFX4", "GFX5", "GFX6", "GFX7", "GFX8",
+ "PROMS",
+ "SOUND1", "SOUND2", "SOUND3", "SOUND4", "SOUND5", "SOUND6", "SOUND7", "SOUND8",
+ "USER1", "USER2", "USER3", "USER4", "USER5", "USER6", "USER7", "USER8"
+ };
+
+ static const char * kLocationNames[] =
+ {
+ "Normal",
+ "Region",
+ "Mapped Memory",
+ "Custom",
+ "Relative Address",
+ "Program Space",
+ "Unused (6)",
+ "Unused (7)"
+ };
+
+ static const char * kCustomLocationNames[] =
+ {
+ "Comment",
+ "EEPROM",
+ "Select",
+ "Unused (3)", "Unused (4)", "Unused (5)", "Unused (6)", "Unused (7)",
+ "Unused (8)", "Unused (9)", "Unused (10)", "Unused (11)", "Unused (12)",
+ "Unused (13)", "Unused (14)", "Unused (15)", "Unused (16)", "Unused (17)",
+ "Unused (18)", "Unused (19)", "Unused (20)", "Unused (21)", "Unused (22)",
+ "Unused (23)", "Unused (24)", "Unused (25)", "Unused (26)", "Unused (27)",
+ "Unused (28)", "Unused (29)", "Unused (30)", "Unused (31)"
+ };
+
+ static const char * kSizeNames[] =
+ {
+ "8 Bit",
+ "16 Bit",
+ "24 Bit",
+ "32 Bit"
+ };
+
+ enum
+ {
+ kType_Name = 0, // text name
+ // NOTE: read from base cheat (for idx == 0)
+ kType_ExtendName, // text extraName
+ // NOTE: read from subcheat for (idx > 0) && (cheat[0].type == Select)
+ kType_Comment, // text comment
+ // NOTE: read from base cheat (for idx == 0)
+ kType_ActivationKey1, // key 1st activationKey
+ // NOTE: read from base cheat (for idx == 0)
+ kType_ActivationKey2, // key 2nd activationKey
+ // NOTE: read from base cheat (for idx == 0)
+ // if(idx > 0 && (cheat[0].type == Select))
+ kType_LinkExtension, // select LinkExtension Off - On
+ kType_Type, // select Type Normal/Delay - Wait - Ignore Decrement - Watch -
+ // Comment - Select
+ // NOTE: also uses location type field for comment and select
+ // if((Type != Comment) && (Type != Select))
+ // if(Type != Watch)
+ kType_OneShot, // select OneShot Off - On
+ kType_RestorePreviousValue,
+ // select RestorePreviousValue
+ // Off - On
+ // if((Type == Normal/Delay) || (Type == Wait))
+ kType_Delay, // value TypeParameter 0 - 7
+ // if(Type == Ignore Decrement)
+ kType_IgnoreDecrementBy,// value TypeParameter 0 - 7
+ // if(Type == Watch)
+ kType_WatchSize, // value Data 0x01 - 0xFF (stored as 0x00 - 0xFE)
+ // NOTE: value is packed in to 0x000000FF
+ kType_WatchSkip, // value Data 0x00 - 0xFF
+ // NOTE: value is packed in to 0x0000FF00
+ kType_WatchPerLine, // value Data 0x00 - 0xFF
+ // NOTE: value is packed in to 0x00FF0000
+ kType_WatchAddValue, // value Data -0x80 - 0x7F
+ // NOTE: value is packed in to 0xFF000000
+ kType_WatchFormat, // select TypeParameter Hex - Decimal - Binary - ASCII
+ // NOTE: value is packed in to 0x03
+ kType_WatchLabel, // select TypeParameter Off - On
+ // NOTE: value is packed in to 0x04
+ // and set operation to null
+ // else
+ kType_Operation, // select Operation Write - Add/Subtract - Force Range - Set/Clear Bits - Match to Write -
+ // Null
+ // if((Operation == Write) && (LocationType != Relative Address))
+ kType_WriteMask, // value extendData 0x00000000 - 0xFFFFFFFF
+ // if(Operation == Add/Subtract)
+ kType_AddSubtract, // select OperationParameter Add - Subtract
+ // if(LocationType != Relative Address)
+ // if(OperationParameter == Add)
+ kType_AddMaximum,
+ // value extendData 0x00000000 - 0xFFFFFFFF
+ // else
+ kType_SubtractMinimum,
+ // value extendData 0x00000000 - 0xFFFFFFFF
+ // if((Operation == Force Range) && (LocationType != Relative Address))
+ kType_RangeMinimum, // value extendData 0x00 - 0xFF / 0xFFFF
+ // NOTE: value is packed in to upper byte of extendData (as a word)
+ kType_RangeMaximum, // value extendData 0x00 - 0xFF / 0xFFFF
+ // NOTE: value is packed in to lower byte of extendData (as a word)
+ // if(Operation == Set/Clear)
+ kType_SetClear, // select OperationParameter Set - Clear
+ // if(Operation == Match to Write)
+ kType_WriteMatch, // value extendData 0x00000000 - 0xFFFFFFFF
+ // if((Operation != Null) || (Type == Watch))
+ // if(Type != Watch)
+ kType_Data,
+ kType_UserSelect, // select UserSelectEnable Off - On
+ // if(UserSelect == On)
+ kType_UserSelectMinimumDisp,
+ // value UserSelectMinimumDisplay
+ // 0 - 1
+ kType_UserSelectMinimum,
+ // value UserSelectMinimum 0 - 1
+ kType_UserSelectBCD,// select UserSelectBCD Off - On
+ kType_Prefill, // select UserSelectPrefill None - FF - 00 - 01
+ // if(idx > 0)
+ kType_CopyPrevious, // select LinkCopyPreviousValue
+ // Off - On
+ kType_ByteLength, // value BytesUsed 1 - 4
+ // if(bytesUsed > 0)
+ kType_Endianness, // select Endianness Normal - Swap
+ kType_LocationType, // select LocationType Normal - Region - Mapped Memory - EEPROM -
+ // Relative Address - Program Space
+ // NOTE: also uses LocationParameter for EEPROM type
+ // if((LocationType == Normal) || (LocationType == HandlerMemory) || (LocationType == ProgramSpace)
+ kType_CPU, // value LocationParameter 0 - 31
+ // if(LocationType == Region)
+ kType_Region, // select LocationParameter CPU1 - CPU2 - CPU3 - CPU4 - CPU5 - CPU6 - CPU7 -
+ // CPU8 - GFX1 - GFX2 - GFX3 - GFX4 - GFX5 - GFX6 -
+ // GFX7 - GFX8 - PROMS - SOUND1 - SOUND2 - SOUND3 -
+ // SOUND4 - SOUND5 - SOUND6 - SOUND7 - SOUND8 -
+ // USER1 - USER2 - USER3 - USER4 - USER5 - USER6 -
+ // USER7
+ // if(LocationType == RelativeAddress)
+ kType_PackedCPU, // value LocationParameter 0 - 7
+ // NOTE: packed in to upper three bits of LocationParameter
+ kType_PackedSize, // value LocationParameter 1 - 4
+ // NOTE: packed in to lower two bits of LocationParameter
+ kType_AddressIndex, // value extendData -0x80000000 - 0x7FFFFFFF
+ kType_Address,
+
+ kType_Return,
+ kType_Divider,
+
+ kType_Max
+ };
+
+ INT32 sel;
+ const char ** menuItem;
+ const char ** menuSubItem;
+ char * flagBuf;
+ char ** extendDataBuf; // FFFFFFFF (-80000000)
+ char ** addressBuf; // FFFFFFFF
+ char ** dataBuf; // 80000000 (-2147483648)
+ char ** watchSizeBuf; // FF
+ char ** watchSkipBuf; // FF
+ char ** watchPerLineBuf; // FF
+ char ** watchAddValueBuf; // FF
+ INT32 i;
+ INT32 total = 0;
+ MenuItemInfoStruct * info = NULL;
+ CheatAction * action = NULL;
+ UINT8 isSelect = 0;
+ static UINT8 editActive = 0;
+ UINT32 increment = 1;
+ UINT8 dirty = 0;
+ static INT32 currentNameTemplate = 0;
+
+ astring * temp_string_1 = astring_alloc();
+ astring * temp_string_2 = astring_alloc();
+
+ if(!entry)
+ return 0;
+
+ /********** MENU CONSTRUCTION **********/
+ if(menuItemInfoLength < (kType_Max * entry->actionListLength) + 2)
+ {
+ menuItemInfoLength = (kType_Max * entry->actionListLength) + 2;
+
+ menuItemInfo = realloc(menuItemInfo, menuItemInfoLength * sizeof(MenuItemInfoStruct));
+ }
+
+ RequestStrings((kType_Max * entry->actionListLength) + 2, 7 * entry->actionListLength, 24, 0);
+
+ menuItem = menuStrings.mainList;
+ menuSubItem = menuStrings.subList;
+ flagBuf = menuStrings.flagList;
+ extendDataBuf = &menuStrings.mainStrings[entry->actionListLength * 0];
+ addressBuf = &menuStrings.mainStrings[entry->actionListLength * 1];
+ dataBuf = &menuStrings.mainStrings[entry->actionListLength * 2];
+ watchSizeBuf = &menuStrings.mainStrings[entry->actionListLength * 3]; // these fields are wasteful
+ watchSkipBuf = &menuStrings.mainStrings[entry->actionListLength * 4]; // but the alternative is even more ugly
+ watchPerLineBuf = &menuStrings.mainStrings[entry->actionListLength * 5];
+ watchAddValueBuf = &menuStrings.mainStrings[entry->actionListLength * 6];
+
+ sel = selection - 1;
+
+ memset(flagBuf, 0, (kType_Max * entry->actionListLength) + 2);
+
+ /* ----- create menu items ----- */
+ for(i = 0; i < entry->actionListLength; i++)
+ {
+ CheatAction * traverse = &entry->actionList[i];
+
+ UINT32 type = EXTRACT_FIELD(traverse->type, Type);
+ UINT32 typeParameter = EXTRACT_FIELD(traverse->type, TypeParameter);
+ UINT32 operation = EXTRACT_FIELD(traverse->type, Operation) |
+ EXTRACT_FIELD(traverse->type, OperationExtend) << 2;
+ UINT32 operationParameter = EXTRACT_FIELD(traverse->type, OperationParameter);
+ UINT32 locationType = EXTRACT_FIELD(traverse->type, LocationType);
+ UINT32 locationParameter = EXTRACT_FIELD(traverse->type, LocationParameter);
+
+ UINT8 wasCommentOrSelect = 0;
+
+ if(isSelect)
+ {
+ /* ----- do extend name field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_ExtendName;
+ menuItem[total] = "Name";
+
+ if(traverse->optionalName)
+ menuSubItem[total++] = traverse->optionalName;
+ else
+ menuSubItem[total++] = "(none)";
+ }
+
+ /* ----- create items if 1st code ----- */
+ if(i == 0)
+ {
+ {
+ /* ----- do name field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_Name;
+ menuItem[total] = "Name";
+
+ if(entry->name)
+ menuSubItem[total++] = entry->name;
+ else
+ menuSubItem[total++] = "(none)";
+ }
+
+ {
+ /* ----- do comment field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_Comment;
+ menuItem[total] = "Comment";
+
+ if(entry->comment)
+ menuSubItem[total++] = entry->comment;
+ else
+ menuSubItem[total++] = "(none)";
+ }
+
+ {
+ /* ----- do 1st activation key field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_ActivationKey1;
+ menuItem[total] = "Activation Key (1st)";
+
+ if((entry->flags & kCheatFlag_HasActivationKey1))
+ menuSubItem[total++] = astring_c(input_code_name(temp_string_1, entry->activationKey1));
+ else
+ menuSubItem[total++] = "(none)";
+ }
+
+ {
+ /* ----- do 2nd activation key field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_ActivationKey2;
+ menuItem[total] = "Activation Key (2nd)";
+
+ if((entry->flags & kCheatFlag_HasActivationKey2))
+ menuSubItem[total++] = astring_c(input_code_name(temp_string_2, entry->activationKey2));
+ else
+ menuSubItem[total++] = "(none)";
+ }
+
+ /* ----- is this label-selection cheat ? ----- */
+ if((locationType == kLocation_Custom) && (locationParameter == kCustomLocation_Select))
+ isSelect = 1;
+ }
+
+ /* ----- create item if linked code on label-selection ----- */
+ if(i && isSelect)
+ {
+ /* ----- do link extension field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_LinkExtension;
+ menuItem[total] = "Link Extension";
+ menuSubItem[total++] = ui_getstring(TEST_FIELD(traverse->type, LinkExtension) ? UI_on : UI_off);
+ }
+
+ {
+ /* ----- do type field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_Type;
+ menuItem[total] = "Type";
+
+ if(locationType == kLocation_Custom)
+ {
+ if(locationParameter == kCustomLocation_Comment)
+ {
+ /* ----- comment ----- */
+ wasCommentOrSelect = 1;
+
+ menuSubItem[total++] = kTypeNames[4];
+ }
+ else
+ {
+ if(locationParameter == kCustomLocation_Select)
+ {
+ /* ----- label-selection ----- */
+ wasCommentOrSelect = 1;
+
+ menuSubItem[total++] = kTypeNames[5];
+ }
+ else
+ menuSubItem[total++] = kTypeNames[type & 3];
+ }
+ }
+ else
+ menuSubItem[total++] = kTypeNames[type & 3];
+ }
+
+ /* ----- create items if not comment or label-selection ----- */
+ if(!wasCommentOrSelect)
+ {
+ if(type != kType_Watch)
+ {
+ {
+ /* ----- do one shot field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_OneShot;
+ menuItem[total] = "One Shot";
+ menuSubItem[total++] = ui_getstring(TEST_FIELD(traverse->type, OneShot) ? UI_on : UI_off);
+ }
+
+ {
+ /* ----- do restore previous value field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_RestorePreviousValue;
+ menuItem[total] = "Restore Previous Value";
+ menuSubItem[total++] = ui_getstring(TEST_FIELD(traverse->type, RestorePreviousValue) ? UI_on : UI_off);
+ }
+ }
+
+ if((type == kType_NormalOrDelay) || (type == kType_WaitForModification))
+ {
+ /* ----- do delay field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_Delay;
+
+ if( TEST_FIELD(traverse->type, OneShot) && TEST_FIELD(traverse->type, RestorePreviousValue) &&
+ EXTRACT_FIELD(traverse->type, TypeParameter))
+ menuItem[total] = "Keep";
+ else
+ menuItem[total] = "Delay";
+
+ menuSubItem[total++] = kNumbersTable[typeParameter];
+ }
+
+ if(type == kType_IgnoreIfDecrementing)
+ {
+ /* ----- do ignore decrement by field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_IgnoreDecrementBy;
+ menuItem[total] = "Ignore Decrement By";
+ menuSubItem[total++] = kNumbersTable[typeParameter];
+ }
+
+ if(type == kType_Watch)
+ {
+ {
+ /* ----- do watch size field ----- */
+ sprintf(watchSizeBuf[i], "%d", (traverse->originalDataField & 0xFF) + 1);
+
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_WatchSize;
+ menuItem[total] = "Watch Size";
+ menuSubItem[total++] = watchSizeBuf[i];
+ }
+
+ {
+ /* ----- do watch skip field ----- */
+ sprintf(watchSkipBuf[i], "%d", (traverse->data >> 8) & 0xFF);
+
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_WatchSkip;
+ menuItem[total] = "Watch Skip";
+ menuSubItem[total++] = watchSkipBuf[i];
+ }
+
+ {
+ /* ----- do watch per line field ----- */
+ sprintf(watchPerLineBuf[i], "%d", (traverse->data >> 16) & 0xFF);
+
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_WatchPerLine;
+ menuItem[total] = "Watch Per Line";
+ menuSubItem[total++] = watchPerLineBuf[i];
+ }
+
+ {
+ /* ----- do watch add value field ----- */
+ {
+ INT8 temp = (traverse->data >> 24) & 0xFF;
+
+ if(temp < 0)
+ sprintf(watchAddValueBuf[i], "-%.2X", -temp);
+ else
+ sprintf(watchAddValueBuf[i], "%.2X", temp);
+ }
+
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_WatchAddValue;
+ menuItem[total] = "Watch Add Value";
+ menuSubItem[total++] = watchAddValueBuf[i];
+ }
+
+ {
+ /* ----- do watch format field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_WatchFormat;
+ menuItem[total] = "Watch Format";
+ menuSubItem[total++] = kWatchDisplayTypeStringList[(typeParameter >> 0) & 0x03];
+ }
+
+ {
+ /* ----- do watch label field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_WatchLabel;
+ menuItem[total] = "Watch Label";
+ menuSubItem[total++] = ui_getstring(((typeParameter >> 2) & 0x01) ? UI_on : UI_off);
+ }
+ }
+ else
+ {
+ /* ----- do operation field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_Operation;
+ menuItem[total] = "Operation";
+
+ if((locationType != kLocation_IndirectIndexed) && (operation == kOperation_SetOrClearBits))
+ {
+ /* ----- ignore Set/Clear Bit item if not relative address ----- */
+ operation = kOperation_WriteMask;
+
+ CLEAR_MASK_FIELD(traverse->type, OperationExtend);
+ SET_FIELD(traverse->type, Operation, operation);
+ }
+
+ menuSubItem[total++] = kOperationNames[operation];
+ }
+
+ if((operation == kOperation_WriteMask) && (locationType != kLocation_IndirectIndexed))
+ {
+ /* ----- do mask field ----- */
+ int numChars;
+
+ if(traverse->flags & kActionFlag_IgnoreMask)
+ {
+ menuItemInfo[total].extraData = 0xFFFFFFFF;
+ numChars = 8;
+ }
+ else
+ {
+ menuItemInfo[total].extraData = kCheatSizeMaskTable[EXTRACT_FIELD(traverse->type, BytesUsed)];
+ numChars = kCheatSizeDigitsTable[EXTRACT_FIELD(traverse->type, BytesUsed)];
+ }
+
+ sprintf(extendDataBuf[i], "%.*X", numChars, traverse->extendData);
+
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_WriteMask;
+ menuItem[total] = "Mask";
+ menuSubItem[total++] = extendDataBuf[i];
+ }
+
+ if(operation == kOperation_AddSubtract)
+ {
+ {
+ /* ----- do add/subtract field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_AddSubtract;
+ menuItem[total] = "Add/Subtract";
+ menuSubItem[total++] = kAddSubtractNames[operationParameter];
+ }
+
+ if(locationType != kLocation_IndirectIndexed)
+ {
+ if(operationParameter)
+ {
+ /* ----- do subtract minimum field ----- */
+ sprintf(extendDataBuf[i], "%.8X", traverse->extendData);
+
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_SubtractMinimum;
+ menuItem[total] = "Minimum Boundary";
+ menuSubItem[total++] = extendDataBuf[i];
+ }
+ else
+ {
+ /* ----- do add maximum field ----- */
+ sprintf(extendDataBuf[i], "%.8X", traverse->extendData);
+
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_AddMaximum;
+ menuItem[total] = "Maximum Boundary";
+ menuSubItem[total++] = extendDataBuf[i];
+ }
+ }
+ }
+
+ if((operation == kOperation_ForceRange) && (locationType != kLocation_IndirectIndexed))
+ {
+ /* ----- do range minimum field ----- */
+ if(!EXTRACT_FIELD(traverse->type, BytesUsed))
+ sprintf(extendDataBuf[i], "%.2X", (traverse->extendData >> 8) & 0xFF);
+ else
+ sprintf(extendDataBuf[i], "%.4X", (traverse->extendData >> 16) & 0xFFFF);
+
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_RangeMinimum;
+ menuItem[total] = "Range Minimum";
+ menuSubItem[total++] = extendDataBuf[i];
+
+ /* ----- do range maximum field ----- */
+ if(!EXTRACT_FIELD(traverse->type, BytesUsed))
+ {
+ sprintf(extendDataBuf[i] + 3, "%.2X", (traverse->extendData >> 0) & 0xFF);
+ menuSubItem[total] = extendDataBuf[i] + 3;
+ }
+ else
+ {
+ sprintf(extendDataBuf[i] + 7, "%.4X", (traverse->extendData >> 0) & 0xFFFF);
+ menuSubItem[total] = extendDataBuf[i] + 7;
+ }
+
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_RangeMaximum;
+ menuItem[total++] = "Range Maximum";
+ }
+
+ if(operation == kOperation_SetOrClearBits)
+ {
+ /* ----- do set/clear field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_SetClear;
+ menuItem[total] = "Set/Clear";
+ menuSubItem[total++] = kSetClearNames[operationParameter];
+ }
+
+ if(operation == kOperation_WriteMatch)
+ {
+ /* ----- do match value field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_WriteMatch;
+ menuItem[total] = "Match to Write";
+
+ {
+ int numChars;
+
+ if(traverse->flags & kActionFlag_IgnoreMask)
+ {
+ menuItemInfo[total].extraData = 0xFFFFFFFF;
+ numChars = 8;
+ }
+ else
+ {
+ menuItemInfo[total].extraData = kCheatSizeMaskTable[EXTRACT_FIELD(traverse->type, BytesUsed)];
+ numChars = kCheatSizeDigitsTable[EXTRACT_FIELD(traverse->type, BytesUsed)];
+ }
+
+ sprintf(extendDataBuf[i], "%.*X", numChars, traverse->extendData);
+ }
+
+ menuSubItem[total++] = extendDataBuf[i];
+ }
+
+ if((operation != kOperation_None) || (type == kType_Watch))
+ {
+ UINT32 userSelect = TEST_FIELD(entry->actionList[0].type, UserSelectEnable);
+ UINT32 bytesUsed = EXTRACT_FIELD(traverse->type, BytesUsed);
+
+ if(type != kType_Watch)
+ {
+ {
+ /* ----- do data field ----- */
+
+ sprintf(dataBuf[i], "%.*X (%d)", (int)kCheatSizeDigitsTable[bytesUsed], traverse->originalDataField, traverse->originalDataField);
+
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_Data;
+ menuItemInfo[total].extraData = kCheatSizeMaskTable[bytesUsed];
+ menuItem[total] = "Data";
+ menuSubItem[total++] = dataBuf[i];
+ }
+
+ if(!i)
+ {
+ /* ----- do user select field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_UserSelect;
+ menuItem[total] = "User Select";
+ menuSubItem[total++] = ui_getstring(userSelect ? UI_on : UI_off);
+ }
+
+ if(!i && userSelect)
+ {
+ {
+ /* ----- do user select minimum displayed value field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_UserSelectMinimumDisp;
+ menuItem[total] = "Minimum Displayed Value";
+ menuSubItem[total++] = kNumbersTable[EXTRACT_FIELD(traverse->type, UserSelectMinimumDisplay)];
+ }
+
+ {
+ /* ----- do user select minimum value field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_UserSelectMinimum;
+ menuItem[total] = "Minimum Value";
+ menuSubItem[total++] = kNumbersTable[EXTRACT_FIELD(traverse->type, UserSelectMinimum)];
+ }
+ }
+
+ if(userSelect)
+ {
+ /* ----- do user select BCD field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_UserSelectBCD;
+ menuItem[total] = "BCD";
+ menuSubItem[total++] = ui_getstring(TEST_FIELD(traverse->type, UserSelectBCD) ? UI_on : UI_off);
+ }
+
+ if(userSelect || isSelect)
+ {
+ /* ----- do prefill field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_Prefill;
+ menuItem[total] = "Prefill";
+ menuSubItem[total++] = kPrefillNames[EXTRACT_FIELD(traverse->type, Prefill)];
+ }
+
+ if(i && userSelect)
+ {
+ /* ----- do copy previous value field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_CopyPrevious;
+ menuItem[total] = "Copy Previous Value";
+ menuSubItem[total++] = ui_getstring(TEST_FIELD(traverse->type, LinkCopyPreviousValue) ? UI_on : UI_off);
+ }
+ }
+
+ {
+ /* ----- do byte length field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_ByteLength;
+ menuItem[total] = "Byte Length";
+ menuSubItem[total++] = kSizeNames[bytesUsed];
+ }
+
+ if(bytesUsed > 0)
+ {
+ /* ----- do endianness field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_Endianness;
+ menuItem[total] = "Endianness";
+ menuSubItem[total++] = kEndiannessNames[EXTRACT_FIELD(traverse->type, Endianness)];
+ }
+
+ {
+ /* ----- do location type field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_LocationType;
+ menuItem[total] = "Location";
+
+ if(locationType == kLocation_Custom)
+ menuSubItem[total++] = kCustomLocationNames[locationParameter];
+ else
+ menuSubItem[total++] = kLocationNames[locationType];
+ }
+
+ if( (locationType == kLocation_Standard) || (locationType == kLocation_HandlerMemory) ||
+ (locationType == kLocation_ProgramSpace))
+ {
+ /* ----- do cpu field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_CPU;
+ menuItem[total] = "CPU";
+ menuSubItem[total++] = kNumbersTable[locationParameter];
+ }
+
+ if(locationType == kLocation_MemoryRegion)
+ {
+ /* ----- do region field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_Region;
+ menuItem[total] = "Region";
+ menuSubItem[total++] = kRegionNames[locationParameter];
+ }
+
+ if(locationType == kLocation_IndirectIndexed)
+ {
+ {
+ /* ----- do packed CPU field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_PackedCPU;
+ menuItem[total] = "CPU";
+ menuSubItem[total++] = kNumbersTable[(locationParameter >> 2) & 7];
+ }
+
+ {
+ /* ----- do packed size field ----- */
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_PackedSize;
+ menuItem[total] = "Address Size";
+ menuSubItem[total++] = kNumbersTable[(locationParameter & 3) + 1];
+ }
+
+ {
+ /* ----- do address index field ----- */
+
+ /* ---- swap if negative ----- */
+ if(traverse->extendData & 0x80000000)
+ {
+ int temp = traverse->extendData;
+
+ temp = -temp;
+
+ sprintf(extendDataBuf[i], "-%.8X", temp);
+ }
+ else
+ sprintf(extendDataBuf[i], "%.8X", traverse->extendData);
+
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_AddressIndex;
+ menuItem[total] = "Address Index";
+ menuSubItem[total++] = extendDataBuf[i];
+ }
+ }
+
+ {
+ /* ----- do address field ----- */
+ int charsToPrint = 8;
+
+ switch(EXTRACT_FIELD(traverse->type, LocationType))
+ {
+ case kLocation_Standard:
+ case kLocation_HandlerMemory:
+ case kLocation_ProgramSpace:
+ {
+ CPUInfo * cpuInfo = &cpuInfoList[EXTRACT_FIELD(traverse->type, LocationParameter)];
+
+ charsToPrint = cpuInfo->addressCharsNeeded;
+ menuItemInfo[total].extraData = cpuInfo->addressMask;
+ }
+ break;
+
+ case kLocation_IndirectIndexed:
+ {
+ CPUInfo * cpuInfo = &cpuInfoList[(EXTRACT_FIELD(traverse->type, LocationParameter) >> 2) & 7];
+
+ charsToPrint = cpuInfo->addressCharsNeeded;
+ menuItemInfo[total].extraData = cpuInfo->addressMask;
+ }
+ break;
+
+ default:
+ menuItemInfo[total].extraData = 0xFFFFFFFF;
+ }
+
+ sprintf(addressBuf[i], "%.*X", charsToPrint, traverse->address);
+
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_Address;
+ menuItem[total] = "Address";
+ menuSubItem[total++] = addressBuf[i];
+ }
+ }
+ }
+
+ if(i < (entry->actionListLength - 1))
+ {
+ menuItemInfo[total].subcheat = i;
+ menuItemInfo[total].fieldType = kType_Divider;
+ menuItem[total] = "==========";
+ menuSubItem[total++] = NULL;
+ }
+ }
+
+ menuItemInfo[total].subcheat = 0; // return
+ menuItemInfo[total].fieldType = kType_Return;
+ menuItem[total] = ui_getstring(UI_returntoprior);
+ menuSubItem[total++] = NULL;
+
+ menuItemInfo[total].subcheat = 0; // terminate arrey
+ menuItemInfo[total].fieldType = kType_Return;
+ menuItem[total] = NULL;
+ menuSubItem[total] = NULL;
+
+ /* ----- adjuste cursor position ----- */
+ if(sel < 0)
+ sel = 0;
+ if(sel >= total)
+ sel = total - 1;
+
+ info = &menuItemInfo[sel];
+ action = &entry->actionList[info->subcheat];
+
+ /* ----- higlighted sub-item if edit mode ----- */
+ if(editActive)
+ flagBuf[sel] = 1;
+
+ /* ---- draw it ----- */
+ old_style_menu(menuItem, menuSubItem, flagBuf, sel, 0);
+
+ /********** KEY HANDLING **********/
+ if(AltKeyPressed())
+ increment <<= 4;
+ if(ControlKeyPressed())
+ increment <<= 8;
+ if(ShiftKeyPressed())
+ increment <<= 16;
+
+ if(UIPressedRepeatThrottle(IPT_UI_LEFT, kHorizontalSlowKeyRepeatRate))
+ {
+ editActive = 0;
+ dirty = 1;
+
+ switch(info->fieldType)
+ {
+ case kType_Name:
+ currentNameTemplate--;
+
+ if(currentNameTemplate < 0)
+ {
+ currentNameTemplate = 0;
+
+ while(kCheatNameTemplates[currentNameTemplate + 1][0])
+ {
+ currentNameTemplate++;
+ }
+ }
+
+ entry->name = realloc(entry->name, strlen(kCheatNameTemplates[currentNameTemplate]) + 1);
+ strcpy(entry->name, kCheatNameTemplates[currentNameTemplate]);
+ break;
+/*
+ case kType_ActivationKey1:
+ case kType_ActivationKey2:
+ if(info->fieldType == kType_ActivationKey1)
+ {
+ entry->activationKey1--;
+
+ if(entry->activationKey1 < 0)
+ entry->activationKey1 = __code_max - 1;
+ if(entry->activationKey1 >= __code_max)
+ entry->activationKey1 = 0;
+
+ entry->flags |= kCheatFlag_HasActivationKey1;
+ }
+ else
+ {
+ entry->activationKey2--;
+
+ if(entry->activationKey2 < 0)
+ entry->activationKey2 = __code_max - 1;
+ if(entry->activationKey2 >= __code_max)
+ entry->activationKey2 = 0;
+
+ entry->flags |= kCheatFlag_HasActivationKey2;
+ }
+ break;
+*/
+ case kType_LinkExtension:
+ TOGGLE_MASK_FIELD(action->type, LinkExtension);
+ break;
+
+ case kType_Type:
+ {
+ UINT8 handled = 0;
+
+ CLEAR_MASK_FIELD(action->type, OperationExtend);
+
+ if(EXTRACT_FIELD(action->type, LocationType) == kLocation_Custom)
+ {
+ UINT32 locationParameter = EXTRACT_FIELD(action->type, LocationParameter);
+
+ if(locationParameter == kCustomLocation_Comment)
+ {
+ SET_FIELD(action->type, LocationParameter, 0);
+ SET_FIELD(action->type, LocationType, kLocation_Standard);
+ SET_FIELD(action->type, Type, kType_Watch);
+ SET_FIELD(action->type, Operation, kOperation_None);
+ SET_MASK_FIELD(action->type, OperationExtend);
+
+ handled = 1;
+ }
+ else if(locationParameter == kCustomLocation_Select)
+ {
+ SET_FIELD(action->type, LocationParameter, kCustomLocation_Comment);
+ SET_FIELD(action->type, LocationType, kLocation_Custom);
+ SET_FIELD(action->type, Type, 0);
+
+ handled = 1;
+ }
+ }
+
+ if(!handled)
+ {
+ UINT32 type = EXTRACT_FIELD(action->type, Type);
+
+ if(type == kType_NormalOrDelay)
+ {
+ SET_FIELD(action->type, LocationParameter, kCustomLocation_Select);
+ SET_FIELD(action->type, LocationType, kLocation_Custom);
+ SET_FIELD(action->type, Type, 0);
+ }
+ else
+ {
+ SET_FIELD(action->type, Type, type - 1);
+ }
+ }
+ }
+ break;
+
+ case kType_OneShot:
+ TOGGLE_MASK_FIELD(action->type, OneShot);
+ break;
+
+ case kType_RestorePreviousValue:
+ TOGGLE_MASK_FIELD(action->type, RestorePreviousValue);
+ break;
+
+ case kType_Delay:
+ case kType_IgnoreDecrementBy:
+ {
+ UINT32 delay = (EXTRACT_FIELD(action->type, TypeParameter) - 1) & 7;
+
+ SET_FIELD(action->type, TypeParameter, delay);
+ }
+ break;
+
+ case kType_WatchSize:
+ action->originalDataField = (action->originalDataField & 0xFFFFFF00) | ((action->originalDataField - 0x00000001) & 0x000000FF);
+ action->data = action->originalDataField;
+ break;
+
+ case kType_WatchSkip:
+ action->originalDataField = (action->originalDataField & 0xFFFF00FF) | ((action->originalDataField - 0x00000100) & 0x0000FF00);
+ action->data = action->originalDataField;
+ break;
+
+ case kType_WatchPerLine:
+ action->originalDataField = (action->originalDataField & 0xFF00FFFF) | ((action->originalDataField - 0x00010000) & 0x00FF0000);
+ action->data = action->originalDataField;
+ break;
+
+ case kType_WatchAddValue:
+ action->originalDataField = (action->originalDataField & 0x00FFFFFF) | ((action->originalDataField - 0x01000000) & 0xFF000000);
+ action->data = action->originalDataField;
+ break;
+
+ case kType_WatchFormat:
+ {
+ UINT32 typeParameter = EXTRACT_FIELD(action->type, TypeParameter);
+
+ typeParameter = (typeParameter & 0xFFFFFFFC) | ((typeParameter - 0x00000001) & 0x0000003);
+ SET_FIELD(action->type, TypeParameter, typeParameter);
+ }
+ break;
+
+ case kType_WatchLabel:
+ SET_FIELD(action->type, TypeParameter, EXTRACT_FIELD(action->type, TypeParameter) ^ 0x00000004);
+ break;
+
+ case kType_Operation:
+ {
+ UINT32 operation = ((EXTRACT_FIELD(action->type, Operation) | EXTRACT_FIELD(action->type, OperationExtend) << 2) - 1) & 7;
+
+ if(operation == kOperation_None)
+ operation = kOperation_WriteMatch;
+
+ if( (operation == kOperation_SetOrClearBits) &&
+ !(EXTRACT_FIELD(action->type, LocationType) == kLocation_IndirectIndexed))
+ operation = (operation - 1) & 7;
+
+ if(operation >> 2)
+ SET_MASK_FIELD(action->type, OperationExtend);
+ else
+ CLEAR_MASK_FIELD(action->type, OperationExtend);
+
+ SET_FIELD(action->type, Operation, operation);
+ }
+ break;
+
+ case kType_WriteMask:
+ case kType_WriteMatch:
+ action->extendData -= increment;
+ action->extendData &= info->extraData;
+ break;
+
+ case kType_RangeMinimum:
+ if(!EXTRACT_FIELD(action->type, BytesUsed))
+ action->extendData = (action->extendData & 0xFFFF00FF) | ((action->extendData - 0x00000100) & 0x0000FF00);
+ else
+ action->extendData = (action->extendData & 0x0000FFFF) | ((action->extendData - 0x00010000) & 0xFFFF0000);
+ break;
+
+ case kType_RangeMaximum:
+ if(!EXTRACT_FIELD(action->type, BytesUsed))
+ action->extendData = (action->extendData & 0xFFFFFF00) | ((action->extendData - 0x00000001) & 0x000000FF);
+ else
+ action->extendData = (action->extendData & 0xFFFF0000) | ((action->extendData - 0x00000001) & 0x0000FFFF);
+ break;
+
+ case kType_AddressIndex:
+ case kType_SubtractMinimum:
+ case kType_AddMaximum:
+ action->extendData -= increment;
+ break;
+
+ case kType_AddSubtract:
+ case kType_SetClear:
+ TOGGLE_MASK_FIELD(action->type, OperationParameter);
+ break;
+
+ case kType_Data:
+ action->originalDataField -= increment;
+ action->originalDataField &= info->extraData;
+ action->data = action->originalDataField;
+ break;
+
+ case kType_UserSelect:
+ TOGGLE_MASK_FIELD(action->type, UserSelectEnable);
+ break;
+
+ case kType_UserSelectMinimumDisp:
+ TOGGLE_MASK_FIELD(action->type, UserSelectMinimumDisplay);
+ break;
+
+ case kType_UserSelectMinimum:
+ TOGGLE_MASK_FIELD(action->type, UserSelectMinimum);
+ break;
+
+ case kType_UserSelectBCD:
+ TOGGLE_MASK_FIELD(action->type, UserSelectBCD);
+ break;
+
+ case kType_Prefill:
+ {
+ UINT32 prefill = (EXTRACT_FIELD(action->type, Prefill) - 1) & 3;
+
+ SET_FIELD(action->type, Prefill, prefill);
+ }
+ break;
+
+ case kType_CopyPrevious:
+ TOGGLE_MASK_FIELD(action->type, LinkCopyPreviousValue);
+ break;
+
+ case kType_ByteLength:
+ {
+ UINT32 length = (EXTRACT_FIELD(action->type, BytesUsed) - 1) & 3;
+
+ SET_FIELD(action->type, BytesUsed, length);
+ }
+ break;
+
+ case kType_Endianness:
+ TOGGLE_MASK_FIELD(action->type, Endianness);
+ break;
+
+ case kType_LocationType:
+ {
+ UINT32 locationType = EXTRACT_FIELD(action->type, LocationType);
+ UINT32 locationParameter = EXTRACT_FIELD(action->type, LocationParameter);
+
+ if(locationType == kLocation_Standard)
+ {
+ SET_FIELD(action->type, LocationType, kLocation_ProgramSpace);
+ SET_FIELD(action->type, LocationParameter, (locationParameter << 2) & 0x1C);
+ }
+ else if(locationType == kLocation_Custom)
+ {
+ SET_FIELD(action->type, LocationType, kLocation_HandlerMemory);
+ SET_FIELD(action->type, LocationParameter, 0);
+ }
+ else if(locationType == kLocation_IndirectIndexed)
+ {
+ SET_FIELD(action->type, LocationType, kLocation_Custom);
+ SET_FIELD(action->type, LocationParameter, kCustomLocation_EEPROM);
+ }
+ else
+ {
+ locationType--;
+
+ SET_FIELD(action->type, LocationType, locationType);
+ }
+ }
+ break;
+
+ case kType_CPU:
+ case kType_Region:
+ {
+ UINT32 locationParameter = EXTRACT_FIELD(action->type, LocationParameter);
+
+ locationParameter = (locationParameter - 1) & 31;
+
+ SET_FIELD(action->type, LocationParameter, locationParameter);
+ }
+ break;
+
+ case kType_PackedCPU:
+ {
+ UINT32 locationParameter = EXTRACT_FIELD(action->type, LocationParameter);
+
+ locationParameter = ((locationParameter - 0x04) & 0x1C) | (locationParameter & 0x03);
+
+ SET_FIELD(action->type, LocationParameter, locationParameter);
+ }
+ break;
+
+ case kType_PackedSize:
+ {
+ UINT32 locationParameter = EXTRACT_FIELD(action->type, LocationParameter);
+
+ locationParameter = ((locationParameter - 0x01) & 0x03) | (locationParameter & 0x1C);
+
+ SET_FIELD(action->type, LocationParameter, locationParameter);
+ }
+ break;
+
+ case kType_Address:
+ action->address -= increment;
+ action->address &= info->extraData;
+ break;
+
+ case kType_Return:
+ case kType_Divider:
+ break;
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_RIGHT, kHorizontalSlowKeyRepeatRate))
+ {
+ editActive = 0;
+ dirty = 1;
+
+ switch(info->fieldType)
+ {
+ case kType_Name:
+ currentNameTemplate++;
+
+ if((currentNameTemplate < 0) || !kCheatNameTemplates[currentNameTemplate][0])
+ {
+ currentNameTemplate = 0;
+ }
+
+ entry->name = realloc(entry->name, strlen(kCheatNameTemplates[currentNameTemplate]) + 1);
+ strcpy(entry->name, kCheatNameTemplates[currentNameTemplate]);
+ break;
+/*
+ case kType_ActivationKey1:
+ case kType_ActivationKey2:
+ if(info->fieldType == kType_ActivationKey1)
+ {
+ entry->activationKey1++;
+
+ if(entry->activationKey1 < 0)
+ entry->activationKey1 = __code_max - 1;
+ if(entry->activationKey1 >= __code_max)
+ entry->activationKey1 = 0;
+
+ entry->flags |= kCheatFlag_HasActivationKey1;
+ }
+ else
+ {
+ entry->activationKey2++;
+
+ if(entry->activationKey2 < 0)
+ entry->activationKey2 = __code_max - 1;
+ if(entry->activationKey2 >= __code_max)
+ entry->activationKey2 = 0;
+
+ entry->flags |= kCheatFlag_HasActivationKey2;
+ }
+ break;
+*/
+ case kType_LinkExtension:
+ TOGGLE_MASK_FIELD(action->type, LinkExtension);
+ break;
+
+ case kType_Type:
+ {
+ UINT8 handled = 0;
+
+ CLEAR_MASK_FIELD(action->type, OperationExtend);
+
+ if(EXTRACT_FIELD(action->type, LocationType) == kLocation_Custom)
+ {
+ UINT32 locationParameter = EXTRACT_FIELD(action->type, LocationParameter);
+
+ if(locationParameter == kCustomLocation_Comment)
+ {
+ SET_FIELD(action->type, LocationParameter, kCustomLocation_Select);
+ SET_FIELD(action->type, LocationType, kLocation_Custom);
+ SET_FIELD(action->type, Type, 0);
+
+ handled = 1;
+ }
+ else if(locationParameter == kCustomLocation_Select)
+ {
+ SET_FIELD(action->type, LocationParameter, 0);
+ SET_FIELD(action->type, LocationType, kLocation_Standard);
+ SET_FIELD(action->type, Type, 0);
+
+ handled = 1;
+ }
+ }
+
+ if(!handled)
+ {
+ UINT32 type = EXTRACT_FIELD(action->type, Type);
+
+ if(type == kType_Watch)
+ {
+ SET_FIELD(action->type, LocationParameter, kCustomLocation_Comment);
+ SET_FIELD(action->type, LocationType, kLocation_Custom);
+ SET_FIELD(action->type, Type, 0);
+ }
+ else
+ {
+ SET_FIELD(action->type, Type, type + 1);
+
+ if((type + 1) == kType_Watch)
+ {
+ SET_FIELD(action->type, Operation, kOperation_None);
+ SET_MASK_FIELD(action->type, OperationExtend);
+ }
+ }
+ }
+ }
+ break;
+
+ case kType_OneShot:
+ TOGGLE_MASK_FIELD(action->type, OneShot);
+ break;
+
+ case kType_RestorePreviousValue:
+ TOGGLE_MASK_FIELD(action->type, RestorePreviousValue);
+ break;
+
+ case kType_Delay:
+ case kType_IgnoreDecrementBy:
+ {
+ UINT32 delay = (EXTRACT_FIELD(action->type, TypeParameter) + 1) & 7;
+
+ SET_FIELD(action->type, TypeParameter, delay);
+ }
+ break;
+
+ case kType_WatchSize:
+ action->originalDataField = (action->originalDataField & 0xFFFFFF00) | ((action->originalDataField + 0x00000001) & 0x000000FF);
+ action->data = action->originalDataField;
+ break;
+
+ case kType_WatchSkip:
+ action->originalDataField = (action->originalDataField & 0xFFFF00FF) | ((action->originalDataField + 0x00000100) & 0x0000FF00);
+ action->data = action->originalDataField;
+ break;
+
+ case kType_WatchPerLine:
+ action->originalDataField = (action->originalDataField & 0xFF00FFFF) | ((action->originalDataField + 0x00010000) & 0x00FF0000);
+ action->data = action->originalDataField;
+ break;
+
+ case kType_WatchAddValue:
+ action->originalDataField = (action->originalDataField & 0x00FFFFFF) | ((action->originalDataField + 0x01000000) & 0xFF000000);
+ action->data = action->originalDataField;
+ break;
+
+ case kType_WatchFormat:
+ {
+ UINT32 typeParameter = EXTRACT_FIELD(action->type, TypeParameter);
+
+ typeParameter = (typeParameter & 0xFFFFFFFC) | ((typeParameter + 0x00000001) & 0x0000003);
+ SET_FIELD(action->type, TypeParameter, typeParameter);
+ }
+ break;
+
+ case kType_WatchLabel:
+ SET_FIELD(action->type, TypeParameter, EXTRACT_FIELD(action->type, TypeParameter) ^ 0x00000004);
+ break;
+
+ case kType_Operation:
+ {
+ UINT32 operation = ((EXTRACT_FIELD(action->type, Operation) | EXTRACT_FIELD(action->type, OperationExtend) << 2) + 1) & 7;
+
+ if(operation > kOperation_WriteMatch)
+ operation = kOperation_WriteMask;
+
+ if( (operation == kOperation_SetOrClearBits) &&
+ !(EXTRACT_FIELD(action->type, LocationType) == kLocation_IndirectIndexed))
+ operation = (operation + 1) & 7;
+
+ if(operation >> 2)
+ SET_MASK_FIELD(action->type, OperationExtend);
+ else
+ CLEAR_MASK_FIELD(action->type, OperationExtend);
+
+ SET_FIELD(action->type, Operation, operation);
+ }
+ break;
+
+ case kType_WriteMask:
+ case kType_WriteMatch:
+ action->extendData += increment;
+ action->extendData &= info->extraData;
+ break;
+
+ case kType_RangeMinimum:
+ if(!EXTRACT_FIELD(action->type, BytesUsed))
+ action->extendData = (action->extendData & 0xFFFF00FF) | ((action->extendData + 0x00000100) & 0x0000FF00);
+ else
+ action->extendData = (action->extendData & 0x0000FFFF) | ((action->extendData + 0x00010000) & 0xFFFF0000);
+ break;
+
+ case kType_RangeMaximum:
+ if(!EXTRACT_FIELD(action->type, BytesUsed))
+ action->extendData = (action->extendData & 0xFFFFFF00) | ((action->extendData + 0x00000001) & 0x000000FF);
+ else
+ action->extendData = (action->extendData & 0xFFFF0000) | ((action->extendData + 0x00000001) & 0x0000FFFF);
+ break;
+
+ case kType_AddressIndex:
+ case kType_SubtractMinimum:
+ case kType_AddMaximum:
+ action->extendData += increment;
+ break;
+
+ case kType_AddSubtract:
+ case kType_SetClear:
+ TOGGLE_MASK_FIELD(action->type, OperationParameter);
+ break;
+
+ case kType_Data:
+ action->originalDataField += increment;
+ action->originalDataField &= info->extraData;
+ action->data = action->originalDataField;
+ break;
+
+ case kType_UserSelect:
+ TOGGLE_MASK_FIELD(action->type, UserSelectEnable);
+ break;
+
+ case kType_UserSelectMinimumDisp:
+ TOGGLE_MASK_FIELD(action->type, UserSelectMinimumDisplay);
+ break;
+
+ case kType_UserSelectMinimum:
+ TOGGLE_MASK_FIELD(action->type, UserSelectMinimum);
+ break;
+
+ case kType_UserSelectBCD:
+ TOGGLE_MASK_FIELD(action->type, UserSelectBCD);
+ break;
+
+ case kType_Prefill:
+ {
+ UINT32 prefill = (EXTRACT_FIELD(action->type, Prefill) + 1) & 3;
+
+ SET_FIELD(action->type, Prefill, prefill);
+ }
+ break;
+
+ case kType_CopyPrevious:
+ TOGGLE_MASK_FIELD(action->type, LinkCopyPreviousValue);
+ break;
+
+ case kType_ByteLength:
+ {
+ UINT32 length = (EXTRACT_FIELD(action->type, BytesUsed) + 1) & 3;
+
+ SET_FIELD(action->type, BytesUsed, length);
+ }
+ break;
+
+ case kType_Endianness:
+ TOGGLE_MASK_FIELD(action->type, Endianness);
+ break;
+
+ case kType_LocationType:
+ {
+ UINT32 locationType = EXTRACT_FIELD(action->type, LocationType);
+ UINT32 locationParameter = EXTRACT_FIELD(action->type, LocationParameter);
+
+ if(locationType == kLocation_ProgramSpace)
+ {
+ SET_FIELD(action->type, LocationType, kLocation_Standard);
+ SET_FIELD(action->type, LocationParameter, (locationParameter >> 2) & 7);
+ }
+ else if(locationType == kLocation_Custom)
+ {
+ SET_FIELD(action->type, LocationType, kLocation_IndirectIndexed);
+ SET_FIELD(action->type, LocationParameter, 0);
+ }
+ else if(locationType == kLocation_HandlerMemory)
+ {
+ SET_FIELD(action->type, LocationType, kLocation_Custom);
+ SET_FIELD(action->type, LocationParameter, kCustomLocation_EEPROM);
+ }
+ else
+ {
+ locationType++;
+
+ SET_FIELD(action->type, LocationType, locationType);
+ }
+ }
+ break;
+
+ case kType_CPU:
+ case kType_Region:
+ {
+ UINT32 locationParameter = EXTRACT_FIELD(action->type, LocationParameter);
+
+ locationParameter = (locationParameter + 1) & 31;
+
+ SET_FIELD(action->type, LocationParameter, locationParameter);
+ }
+ break;
+
+ case kType_PackedCPU:
+ {
+ UINT32 locationParameter = EXTRACT_FIELD(action->type, LocationParameter);
+
+ locationParameter = ((locationParameter + 0x04) & 0x1C) | (locationParameter & 0x03);
+
+ SET_FIELD(action->type, LocationParameter, locationParameter);
+ }
+ break;
+
+ case kType_PackedSize:
+ {
+ UINT32 locationParameter = EXTRACT_FIELD(action->type, LocationParameter);
+
+ locationParameter = ((locationParameter + 0x01) & 0x03) | (locationParameter & 0x1C);
+
+ SET_FIELD(action->type, LocationParameter, locationParameter);
+ }
+ break;
+
+ case kType_Address:
+ action->address += increment;
+ action->address &= info->extraData;
+ break;
+
+ case kType_Return:
+ case kType_Divider:
+ break;
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel++;
+
+ if(sel >= total)
+ sel = 0;
+
+ editActive = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_UP, kVerticalKeyRepeatRate))
+ {
+ sel--;
+
+ if(sel < 0)
+ sel = total - 1;
+
+ editActive = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_UP, kVerticalKeyRepeatRate))
+ {
+ sel -= fullMenuPageHeight;
+
+ if(sel < 0)
+ sel = 0;
+
+ editActive = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel += fullMenuPageHeight;
+
+ if(sel >= total)
+ sel = total - 1;
+
+ editActive = 0;
+ }
+
+ if(input_ui_pressed(IPT_UI_SELECT))
+ {
+ if(editActive)
+ {
+ editActive = 0;
+ }
+ else
+ {
+ switch(info->fieldType)
+ {
+ case kType_Name:
+ case kType_ExtendName:
+ case kType_Comment:
+ case kType_ActivationKey1:
+ case kType_ActivationKey2:
+ case kType_WatchSize:
+ case kType_WatchSkip:
+ case kType_WatchPerLine:
+ case kType_WatchAddValue:
+ case kType_WriteMask:
+ case kType_AddMaximum:
+ case kType_SubtractMinimum:
+ case kType_RangeMinimum:
+ case kType_RangeMaximum:
+ case kType_WriteMatch:
+ case kType_Data:
+ case kType_Address:
+ osd_readkey_unicode(1);
+ dirty = 1;
+ editActive = 1;
+ break;
+
+ case kType_Return:
+ sel = -1;
+ break;
+ }
+ }
+ }
+
+ /********** EDIT MODE **********/
+ if(editActive)
+ {
+ /* ----- do edit text ----- */
+ dirty = 1;
+
+ switch(info->fieldType)
+ {
+ case kType_Name:
+ entry->name = DoDynamicEditTextField(entry->name);
+ break;
+
+ case kType_ExtendName:
+ action->optionalName = DoDynamicEditTextField(action->optionalName);
+ break;
+
+ case kType_Comment:
+ entry->comment = DoDynamicEditTextField(entry->comment);
+ break;
+
+ case kType_ActivationKey1:
+ case kType_ActivationKey2:
+ {
+ if(input_ui_pressed(IPT_UI_CANCEL))
+ {
+ if(info->fieldType == kType_ActivationKey1)
+ {
+ entry->activationKey1 = 0;
+ entry->flags &= ~kCheatFlag_HasActivationKey1;
+ }
+ else
+ {
+ entry->activationKey2 = 0;
+ entry->flags &= ~kCheatFlag_HasActivationKey2;
+ }
+
+ editActive = 0;
+ }
+ else
+ {
+ int code = input_code_poll_switches(FALSE);
+
+ if(code == KEYCODE_ESC)
+ {
+ if(info->fieldType == kType_ActivationKey1)
+ {
+ entry->activationKey1 = 0;
+ entry->flags &= ~kCheatFlag_HasActivationKey1;
+ }
+ else
+ {
+ entry->activationKey2 = 0;
+ entry->flags &= ~kCheatFlag_HasActivationKey2;
+ }
+
+ editActive = 0;
+ }
+ else
+ {
+ if((code != INPUT_CODE_INVALID) && !input_ui_pressed(IPT_UI_SELECT))
+ {
+ if(info->fieldType == kType_ActivationKey1)
+ {
+ entry->activationKey1 = code;
+ entry->flags |= kCheatFlag_HasActivationKey1;
+ }
+ else
+ {
+ entry->activationKey2 = code;
+ entry->flags |= kCheatFlag_HasActivationKey2;
+ }
+
+ editActive = 0;
+ }
+ }
+ }
+ }
+ break;
+
+ case kType_WatchSize:
+ {
+ UINT32 temp = (action->originalDataField >> 0) & 0xFF;
+
+ temp++;
+ temp = DoEditHexField(temp) & 0xFF;
+ temp--;
+
+ action->originalDataField = (action->originalDataField & 0xFFFFFF00) | ((temp << 0) & 0x000000FF);
+ action->data = action->originalDataField;
+ }
+ break;
+
+ case kType_WatchSkip:
+ {
+ UINT32 temp = (action->originalDataField >> 8) & 0xFF;
+
+ temp = DoEditHexField(temp) & 0xFF;
+
+ action->originalDataField = (action->originalDataField & 0xFFFF00FF) | ((temp << 8) & 0x0000FF00);
+ action->data = action->originalDataField;
+ }
+ break;
+
+ case kType_WatchPerLine:
+ {
+ UINT32 temp = (action->originalDataField >> 16) & 0xFF;
+
+ temp = DoEditHexField(temp) & 0xFF;
+
+ action->originalDataField = (action->originalDataField & 0xFF00FFFF) | ((temp << 16) & 0x00FF0000);
+ action->data = action->originalDataField;
+ }
+ break;
+
+ case kType_WatchAddValue:
+ {
+ UINT32 temp = (action->originalDataField >> 24) & 0xFF;
+
+ temp = DoEditHexFieldSigned(temp, 0xFFFFFF80) & 0xFF;
+
+ action->originalDataField = (action->originalDataField & 0x00FFFFFF) | ((temp << 24) & 0xFF000000);
+ action->data = action->originalDataField;
+ }
+ break;
+
+ case kType_WriteMask:
+ action->extendData = DoEditHexField(action->extendData);
+ action->extendData &= info->extraData;
+ break;
+
+ case kType_AddMaximum:
+ case kType_SubtractMinimum:
+ case kType_WriteMatch:
+ action->extendData = DoEditHexField(action->extendData);
+ break;
+
+ case kType_RangeMinimum:
+ {
+ UINT32 temp;
+
+ if(!TEST_FIELD(action->type, BytesUsed))
+ {
+ temp = (action->extendData >> 8) & 0xFF;
+ temp = DoEditHexField(temp) & 0xFF;
+
+ action->extendData = (action->extendData & 0xFF) | ((temp << 8) & 0xFF00);
+ }
+ else
+ {
+ temp = (action->extendData >> 16) & 0xFFFF;
+ temp = DoEditHexField(temp) & 0xFFFF;
+
+ action->extendData = (action->extendData & 0x0000FFFF) | ((temp << 16) & 0xFFFF0000);
+ }
+ }
+ break;
+
+ case kType_RangeMaximum:
+ {
+ UINT32 temp;
+
+ if(!TEST_FIELD(action->type, BytesUsed))
+ {
+ temp = action->extendData & 0xFF;
+ temp = DoEditHexField(temp) & 0xFF;
+
+ action->extendData = (action->extendData & 0xFF00) | (temp & 0x00FF);
+ }
+ else
+ {
+ temp = action->extendData & 0xFFFF;
+ temp = DoEditHexField(temp) & 0xFFFF;
+
+ action->extendData = (action->extendData & 0xFFFF0000) | (temp & 0x0000FFFF);
+ }
+ }
+ break;
+
+ case kType_Data:
+ action->originalDataField = DoEditHexField(action->originalDataField);
+ action->originalDataField &= info->extraData;
+ action->data = action->originalDataField;
+ break;
+
+ case kType_Address:
+ action->address = DoEditHexField(action->address);
+ action->address &= info->extraData;
+ break;
+ }
+
+ if(input_ui_pressed(IPT_UI_CANCEL))
+ editActive = 0;
+ }
+ else
+ {
+ if(input_ui_pressed(IPT_UI_SAVE_CHEAT))
+ {
+ if(ControlKeyPressed())
+ if((entry->flags & kCheatFlag_HasActivationKey1) || (entry->flags & kCheatFlag_HasActivationKey2))
+ {
+ SaveCheat(entry, index, 1); // save activation key
+
+ ui_popup_time(1, "activation key saved");
+ }
+ else
+ ui_popup_time(1, "no activation key");
+ else
+ SaveCheat(entry, 0, 0); // save current entry
+ }
+
+ if(input_ui_pressed(IPT_UI_WATCH_VALUE))
+ WatchCheatEntry(entry, 0);
+
+ if(input_ui_pressed(IPT_UI_ADD_CHEAT))
+ AddActionBefore(entry, info->subcheat);
+
+ if(input_ui_pressed(IPT_UI_DELETE_CHEAT))
+ {
+ if(!info->subcheat)
+ {
+ /* ----- if selected entry is master, delete current entry then return to previous menu ----- */
+ DeleteCheatAt(index);
+
+ return 0;
+ }
+ else
+ DeleteActionAt(entry, info->subcheat);
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_CANCEL))
+ {
+ sel = -1;
+ editActive = 0;
+ }
+
+ if(sel == -1)
+ {
+ editActive = 0;
+ dirty = 1;
+ }
+
+ if(dirty)
+ {
+ UpdateCheatInfo(entry, 0);
+
+ entry->flags |= kCheatFlag_Dirty;
+ }
+
+ astring_free(temp_string_1);
+ astring_free(temp_string_2);
+
+ return sel + 1;
+}
+
+/*-----------------------------------------------------------
+ DoSearchMenuMinimum - management for minimum search menu
+-----------------------------------------------------------*/
+
+static int DoSearchMenuMinimum(int selection)
+{
+ /* main */
+ enum
+ {
+ kMenu_CPU = 0,
+ kMenu_SearchItem,
+
+ kMenu_Divider,
+
+ kMenu_Memory,
+ kMenu_ViewResult,
+ kMenu_RestoreSearch,
+
+ kMenu_Return,
+ };
+
+ /* search item */
+ enum
+ {
+ kItem_Value,
+ kItem_Timer,
+ kItem_Equal,
+ kItem_NotEqual,
+ kItem_Less,
+ kItem_Greater,
+
+ kItem_Max = kItem_Greater,
+ };
+
+ const char * menuItem[kMenu_Return + 2] = { 0 };
+ const char * menuSubItem[kMenu_Return + 2] = { 0 };
+
+ char valueBuffer[60];
+ char valueSignedBuffer[60];
+ char cpuBuffer[20];
+ char flagBuf[kMenu_Return + 2] = { 0 };
+
+ SearchInfo * search = GetCurrentSearch();
+
+ INT32 sel = selection - 1;
+ INT32 total = 0;
+ UINT8 doSearch = 0;
+
+ static INT8 searchItem = 0;
+ static INT8 submenuChoice = 0;
+ static UINT8 doneSaveMemory = 0;
+ static UINT8 firstEntry = 0;
+ static UINT8 editActive = 0;
+ static UINT8 posnKeep = kMenu_SearchItem;
+ static UINT32 increment = 1;
+
+ /********** SUB MENU **********/
+ if(submenuChoice)
+ {
+ switch(sel)
+ {
+ case kMenu_CPU:
+ submenuChoice = SelectSearchRegions(submenuChoice, GetCurrentSearch());
+ break;
+
+ case kMenu_ViewResult:
+ submenuChoice = ViewSearchResults(submenuChoice, firstEntry);
+ break;
+ }
+
+ firstEntry = 0;
+
+ posnKeep = sel;
+
+ /* ----- meaningless ? because no longer return with sel = -1 (pressed UI_CONFIG in submenu) ----- */
+// if(submenuChoice == -1)
+// submenuChoice = 0;
+
+ return sel + 1;
+ }
+
+ sel = posnKeep;
+
+ /* ----- unselectable comparison search item if no save ----- */
+ if(!doneSaveMemory)
+ searchItem = kItem_Value;
+
+ /********** MENU CONSTRUCTION **********/
+ sprintf(cpuBuffer, "%d", search->targetIdx); // CPU
+ menuItem[total] = ui_getstring(UI_cpu);
+ menuSubItem[total++] = cpuBuffer;
+
+ if(search->sign && (search->oldOptions.value & kSearchByteSignBitTable[search->bytes]))
+ {
+ UINT32 tempValue;
+
+ tempValue = ~search->oldOptions.value + 1;
+ tempValue &= kSearchByteUnsignedMaskTable[search->bytes];
+
+ sprintf(valueBuffer, "-%.*X (-%d)", kSearchByteDigitsTable[search->bytes], tempValue, tempValue);
+ }
+ else
+ sprintf(valueBuffer, "%.*X (%d)", kSearchByteDigitsTable[search->bytes],
+ search->oldOptions.value & kSearchByteMaskTable[search->bytes],
+ search->oldOptions.value & kSearchByteMaskTable[search->bytes]);
+
+ switch(searchItem)
+ {
+ case kItem_Value: // value
+ menuItem[total] = "Value";
+ menuSubItem[total++] = valueBuffer;
+ break;
+
+ case kItem_Timer:
+ menuItem[total] = "Timer (+ or -)"; // timer
+
+ /* ----- if memory has been saved, set sub-item for timer ----- */
+ if(doneSaveMemory)
+ {
+ if(search->oldOptions.delta & kSearchByteSignBitTable[search->bytes])
+ {
+ UINT32 tempValue;
+
+ tempValue = ~search->oldOptions.delta + 1;
+ tempValue &= kSearchByteUnsignedMaskTable[search->bytes];
+
+ sprintf(valueSignedBuffer, "-%.*X (-%d)", kSearchByteDigitsTable[search->bytes], tempValue, tempValue);
+ }
+ else
+ sprintf(valueSignedBuffer, "%.*X (%d)", kSearchByteDigitsTable[search->bytes],
+ search->oldOptions.delta & kSearchByteMaskTable[search->bytes],
+ search->oldOptions.delta & kSearchByteMaskTable[search->bytes]);
+
+ menuSubItem[total++] = valueSignedBuffer;
+ }
+ break;
+
+ case kItem_Equal:
+ menuItem[total] = "Comparison"; // equal
+ menuSubItem[total++] = "Equal";
+ break;
+
+ case kItem_NotEqual:
+ menuItem[total] = "Comparison"; // not equal
+ menuSubItem[total++] = "Not Equal";
+ break;
+
+ case kItem_Less:
+ menuItem[total] = "Comparison"; // less
+ menuSubItem[total++] = "Less";
+ break;
+
+ case kItem_Greater:
+ menuItem[total] = "Comparison"; // greater
+ menuSubItem[total++] = "Greater";
+ break;
+ }
+
+ menuItem[total] = "--------------------"; // divider
+ menuSubItem[total++] = NULL;
+
+ if(doneSaveMemory) // memory
+ menuItem[total] = "Initialize Memory";
+ else
+ menuItem[total] = "Save Memory";
+ menuSubItem[total++] = NULL;
+
+ menuItem[total] = ui_getstring(UI_viewresults); // view result
+ menuSubItem[total++] = NULL;
+
+ menuItem[total] = ui_getstring(UI_restoreresults); // restore result
+ menuSubItem[total++] = NULL;
+
+ menuItem[total] = ui_getstring(UI_returntoprior); // return
+ menuSubItem[total++] = NULL;
+
+ menuItem[total] = NULL; // terminate array
+ menuSubItem[total] = NULL;
+
+ /* ----- adjust current cursor position ----- */
+ if((sel < 0) || (sel >= total))
+ sel = kMenu_SearchItem;
+
+ /* ----- higlighted sub-item if edit mode ----- */
+ if(editActive)
+ flagBuf[sel] = 1;
+
+ /* ----- draw it ----- */
+ old_style_menu(menuItem, menuSubItem, flagBuf, sel, 0);
+
+ /********** KEY HANDLING **********/
+ if(UIPressedRepeatThrottle(IPT_UI_UP, kVerticalKeyRepeatRate))
+ {
+ if(editActive)
+ {
+ increment <<= 4;
+
+ switch(searchItem)
+ {
+ case kItem_Value:
+ search->oldOptions.value += increment;
+ search->oldOptions.value &= kSearchByteMaskTable[search->bytes];
+ break;
+
+ case kItem_Timer:
+ search->oldOptions.delta += increment;
+ search->oldOptions.delta &= kSearchByteMaskTable[search->bytes];
+ break;
+ }
+
+ increment >>= 4;
+ }
+ else
+ {
+ sel--;
+
+ /* ----- if divider, skip it ----- */
+ if(sel == kMenu_Divider)
+ sel--;
+
+ if(sel < 0)
+ sel = total - 1;
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_DOWN, kVerticalKeyRepeatRate))
+ {
+ if(editActive)
+ {
+ increment <<= 4;
+
+ switch(searchItem)
+ {
+ case kItem_Value:
+ search->oldOptions.value -= increment;
+ search->oldOptions.value &= kSearchByteMaskTable[search->bytes];
+ break;
+
+ case kItem_Timer:
+ search->oldOptions.delta -= increment;
+ search->oldOptions.delta &= kSearchByteMaskTable[search->bytes];
+ break;
+ }
+
+ increment >>= 4;
+ }
+ else
+ {
+ sel++;
+
+ /* ----- if divider, skip it ----- */
+ if(sel == kMenu_Divider)
+ sel++;
+
+ if(sel >= total)
+ sel = 0;
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_UP, kVerticalKeyRepeatRate))
+ {
+ sel -= fullMenuPageHeight;
+
+ if(sel < 0)
+ sel = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel += fullMenuPageHeight;
+
+ if(sel >= total)
+ sel = total - 1;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_LEFT, kHorizontalFastKeyRepeatRate))
+ {
+ if(editActive)
+ {
+ switch(searchItem)
+ {
+ case kItem_Value:
+ search->oldOptions.value -= increment;
+ search->oldOptions.value &= kSearchByteMaskTable[search->bytes];
+ break;
+
+ case kItem_Timer:
+ search->oldOptions.delta -= increment;
+ search->oldOptions.delta &= kSearchByteMaskTable[search->bytes];
+ break;
+ }
+ }
+ else
+ {
+ switch(sel)
+ {
+ case kMenu_CPU:
+ if(search->targetIdx > 0)
+ {
+ search->targetIdx--;
+
+ BuildSearchRegions(search);
+ AllocateSearchRegions(search);
+
+ doneSaveMemory = 0;
+ }
+ break;
+
+ case kMenu_SearchItem:
+ if(doneSaveMemory)
+ searchItem--;
+
+ if(searchItem < 0)
+ searchItem = kItem_Max;
+ break;
+ }
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_RIGHT, kHorizontalFastKeyRepeatRate))
+ {
+ if(editActive)
+ {
+ switch(searchItem)
+ {
+ case kItem_Value:
+ search->oldOptions.value += increment;
+ search->oldOptions.value &= kSearchByteMaskTable[search->bytes];
+ break;
+
+ case kItem_Timer:
+ search->oldOptions.delta += increment;
+ search->oldOptions.delta &= kSearchByteMaskTable[search->bytes];
+ break;
+ }
+ }
+ else
+ {
+ switch(sel)
+ {
+ case kMenu_CPU:
+ if(search->targetIdx < cpu_gettotalcpu() - 1)
+ {
+ search->targetIdx++;
+
+ BuildSearchRegions(search);
+ AllocateSearchRegions(search);
+
+ doneSaveMemory = 0;
+ }
+ break;
+
+ case kMenu_SearchItem:
+ if(doneSaveMemory)
+ searchItem++;
+
+ if(searchItem > kItem_Max)
+ searchItem = kItem_Value;
+
+ break;
+ }
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_SELECT))
+ {
+ if(editActive)
+ {
+ switch(searchItem)
+ {
+ case kItem_Value:
+ search->bytes = kSearchSize_8Bit;
+ search->lhs = kSearchOperand_Current;
+ search->rhs = kSearchOperand_Value;
+ search->comparison = kSearchComparison_EqualTo;
+ search->value = search->oldOptions.value;
+
+ doSearch = 1;
+ break;
+
+ case kItem_Timer:
+ search->bytes = kSearchSize_8Bit;
+ search->lhs = kSearchOperand_Current;
+ search->rhs = kSearchOperand_Previous;
+ search->comparison = kSearchComparison_IncreasedBy;
+ search->value = search->oldOptions.delta;
+
+ doSearch = 1;
+ break;
+ }
+
+ /* ----- finish edit mode then do search ----- */
+ editActive = 0;
+ }
+ else
+ {
+ switch(sel)
+ {
+ case kMenu_CPU:
+ submenuChoice = 1; // go to region selection menu
+ break;
+
+ case kMenu_SearchItem:
+ {
+
+ switch(searchItem)
+ {
+ case kItem_Value:
+ case kItem_Timer:
+ editActive = 1;
+ break;
+
+ case kItem_Equal:
+ search->bytes = kSearchSize_8Bit;
+ search->lhs = kSearchOperand_Current;
+ search->rhs = kSearchOperand_Previous;
+ search->comparison = kSearchComparison_EqualTo;
+
+ doSearch = 1;
+ break;
+
+ case kItem_NotEqual:
+ search->bytes = kSearchSize_8Bit;
+ search->lhs = kSearchOperand_Current;
+ search->rhs = kSearchOperand_Previous;
+ search->comparison = kSearchComparison_NotEqual;
+
+ doSearch = 1;
+ break;
+
+ case kItem_Less:
+ search->bytes = kSearchSize_8Bit;
+ search->lhs = kSearchOperand_Current;
+ search->rhs = kSearchOperand_Previous;
+ search->comparison = kSearchComparison_LessThan;
+
+ doSearch = 1;
+ break;
+
+ case kItem_Greater:
+ search->bytes = kSearchSize_8Bit;
+ search->lhs = kSearchOperand_Current;
+ search->rhs = kSearchOperand_Previous;
+ search->comparison = kSearchComparison_GreaterThan;
+
+ doSearch = 1;
+ break;
+ }
+ }
+ break;
+
+ case kMenu_Memory: // save memory to search newly
+ doneSaveMemory = 0;
+
+ doSearch = 1;
+ break;
+
+ case kMenu_ViewResult:
+ if(search->regionListLength)
+ {
+ /* ----- go to result viewer ----- */
+ firstEntry = 1;
+ submenuChoice = 1;
+ }
+ else
+ /* ----- if no search region (eg, sms.c in HazeMD), don't open result viewer to avoid the crash ----- */
+ ui_popup_time(1, "no search regions");
+ break;
+
+ case kMenu_RestoreSearch:
+ RestoreSearchBackup(search);
+ break;
+
+ case kMenu_Return:
+ posnKeep = kMenu_SearchItem;
+ sel = -1;
+ break;
+ }
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_ZOOM_IN, kVerticalKeyRepeatRate))
+ /* ----- quick menu switch : search -> watchpoint list ----- */
+ sel = -5;
+
+ if(UIPressedRepeatThrottle(IPT_UI_ZOOM_OUT, kVerticalKeyRepeatRate))
+ /* ----- quick menu switch : search -> add/edit ----- */
+ sel = -3;
+
+ /* ----- edit mode ON/OFF ----- */
+ if(input_ui_pressed(IPT_UI_EDIT_CHEAT))
+ {
+ if(editActive)
+ editActive = 0;
+ else
+ {
+ if((searchItem == kItem_Value) || (kItem_Timer))
+ editActive = 1;
+ }
+ }
+
+ /* ----- memory save ----- */
+ if(input_ui_pressed(IPT_UI_CLEAR))
+ {
+ doneSaveMemory = 0;
+
+ doSearch = 1;
+ }
+
+ if(input_ui_pressed(IPT_UI_CANCEL))
+ {
+ if(editActive)
+ editActive = 0;
+ else
+ {
+ posnKeep = kMenu_Memory;
+ sel = -1;
+ }
+ }
+
+ /********** SEARCH **********/
+ if(doSearch)
+ {
+ if(!doneSaveMemory)
+ /* ----- initialize search ----- */
+ InitializeNewSearch(search);
+
+ if(((sel == kMenu_SearchItem) && (searchItem == kItem_Value)) || doneSaveMemory)
+ {
+ /* ----- do search ----- */
+ BackupSearch(search);
+
+ DoSearch(search);
+ }
+
+ UpdateSearch(search);
+
+ /* ----- display message ----- */
+ if(((sel == kMenu_SearchItem) && (searchItem == kItem_Value)) || doneSaveMemory)
+ popmessage("%d results found", search->numResults);
+ else
+ popmessage("saved all memory regions");
+
+ doneSaveMemory = 1;
+
+ if(search->numResults == 1)
+ {
+ AddCheatFromFirstResult(search);
+
+ popmessage("1 result found, added to list");
+ }
+ }
+
+ /********** EDIT **********/
+ if((sel == kMenu_SearchItem) && editActive)
+ {
+ if(searchItem == kItem_Value)
+ {
+ search->oldOptions.value = DoEditHexField(search->oldOptions.value);
+
+ search->oldOptions.value &= kSearchByteMaskTable[search->bytes];
+ }
+ else
+ {
+ if(searchItem == kItem_Timer)
+ {
+ search->oldOptions.delta = DoEditHexField(search->oldOptions.delta);
+
+ search->oldOptions.delta &= kSearchByteMaskTable[search->bytes];
+ }
+ }
+ }
+
+ if(sel >= 0)
+ posnKeep = sel;
+
+ return sel + 1;
+}
+
+/*-----------------------------------------------------------
+ DoSearchMenuClassic - management for classic search menu
+-----------------------------------------------------------*/
+
+static int DoSearchMenuClassic(int selection)
+{
+ static const char * energyStrings[] =
+ {
+ "Less",
+ "Greater",
+ "Less or Equal",
+ "Greater or Equal",
+ };
+
+ static const char * equalOrNotStrings[] =
+ {
+ "Equal",
+ "Not Equal",
+ };
+
+ static const char * operandStrings[] =
+ {
+ "Previous Data",
+ "First Data",
+ };
+
+ /* conversion table */
+ static const int kEnergyComparisonConversionTable[] =
+ {
+ kSearchComparison_LessThan,
+ kSearchComparison_GreaterThan,
+ kSearchComparison_LessThanOrEqualTo,
+ kSearchComparison_GreaterThanOrEqualTo
+ };
+
+ static const int kEqualOrNotConversionTable[] =
+ {
+ kSearchComparison_EqualTo,
+ kSearchComparison_NotEqual
+ };
+
+ static const int kOperandConversionTable[] =
+ {
+ kSearchOperand_Previous,
+ kSearchOperand_First
+ };
+
+ enum
+ {
+ kMenu_DoMemorySave = 0,
+
+ kMenu_Divider,
+
+ kMenu_CPU,
+ kMenu_ValueEqual,
+ kMenu_ValueNearTo,
+ kMenu_Time,
+ kMenu_Energy,
+ kMenu_Status,
+ kMenu_Operand,
+
+ kMenu_Divider2,
+
+ kMenu_ViewResult,
+ kMenu_RestoreSearch,
+
+ kMenu_Return,
+ };
+
+ enum
+ {
+ kEnergy_Less = 0,
+ kEnergy_Greater,
+ kEnergy_LessOrEqual,
+ kEnergy_GreaterOrEqual,
+ };
+
+ const char * menuItem[kMenu_Return + 2] = { 0 };
+ const char * menuSubItem[kMenu_Return + 2] = { 0 };
+
+ char valueBuffer[60];
+ char valueSignedBuffer[60];
+ char cpuBuffer[20];
+
+ SearchInfo * search = GetCurrentSearch();
+
+ INT32 sel = selection - 1;
+ INT32 total = 0;
+ UINT32 increment = 1;
+ UINT8 doSearch = 0;
+
+ static INT8 submenuChoice = 0;
+ static UINT8 doneSaveMemory = 0;
+ static UINT8 firstEntry = 0;
+ static int lastPos = 0;
+
+ sel = lastPos;
+
+ /********** SUB MENU **********/
+ if(submenuChoice)
+ {
+ switch(sel)
+ {
+ case kMenu_CPU:
+ submenuChoice = SelectSearchRegions(submenuChoice, GetCurrentSearch());
+ break;
+
+ case kMenu_ViewResult:
+ submenuChoice = ViewSearchResults(submenuChoice, firstEntry);
+ break;
+ }
+
+ firstEntry = 0;
+
+ /* ----- meaningless ? because no longer return with sel = -1 (pressed UI_CONFIG in submenu) ----- */
+// if(submenuChoice == -1)
+// submenuChoice = 0;
+
+ return sel + 1;
+ }
+
+ /********** MENU CONSTRUCTION **********/
+ if(!doneSaveMemory)
+ menuItem[total] = "Save Memory";
+ else
+ menuItem[total] = "Initialize Memory";
+
+ menuSubItem[total++] = NULL;
+
+ menuItem[total] = "--------------------";
+ menuSubItem[total++] = NULL;
+
+ sprintf(cpuBuffer, "%d", search->targetIdx);
+ menuItem[total] = ui_getstring(UI_cpu);
+ menuSubItem[total++] = cpuBuffer;
+
+ if(search->sign && (search->oldOptions.value & kSearchByteSignBitTable[search->bytes]))
+ {
+ UINT32 tempValue;
+
+ tempValue = ~search->oldOptions.value + 1;
+ tempValue &= kSearchByteUnsignedMaskTable[search->bytes];
+
+ sprintf(valueBuffer, "-%.*X (-%d)", kSearchByteDigitsTable[search->bytes], tempValue, tempValue);
+ }
+ else
+ sprintf(valueBuffer, "%.*X (%d)", kSearchByteDigitsTable[search->bytes], search->oldOptions.value & kSearchByteMaskTable[search->bytes], search->oldOptions.value & kSearchByteMaskTable[search->bytes]);
+
+ menuItem[total] = "Value (Equal)";
+
+ if(sel >= kMenu_ValueNearTo)
+ menuSubItem[total++] = " ";
+ else
+ menuSubItem[total++] = valueBuffer;
+
+ menuItem[total] = "Value (NearTo)";
+
+ if(sel >= kMenu_ValueNearTo)
+ menuSubItem[total++] = valueBuffer;
+ else
+ menuSubItem[total++] = " ";
+
+ menuItem[total] = "Timer (+ or -)";
+ menuSubItem[total++] = " ";
+
+ menuItem[total] = "Energy (Less or Greater)";
+ menuSubItem[total++] = " ";
+
+ menuItem[total] = "Status (Same or Different)";
+ menuSubItem[total++] = " ";
+
+ menuItem[total] = "Comparison Option";
+ menuSubItem[total++] = " ";
+
+ menuItem[total] = "--------------------";
+ menuSubItem[total++] = NULL;
+
+ menuItem[total] = ui_getstring(UI_viewresults); // view result
+ menuSubItem[total++] = NULL;
+
+ menuItem[total] = ui_getstring(UI_restoreresults); // restore result
+ menuSubItem[total++] = NULL;
+
+ menuItem[total] = ui_getstring(UI_returntoprior); // return
+ menuSubItem[total++] = NULL;
+
+ menuItem[total] = NULL; // terminate array
+ menuSubItem[total] = NULL;
+
+ /* ----- if memory has been saved, set sub-menu items ----- */
+ if(doneSaveMemory)
+ {
+ if(search->oldOptions.delta & kSearchByteSignBitTable[search->bytes])
+ {
+ UINT32 tempValue;
+
+ tempValue = ~search->oldOptions.delta + 1;
+ tempValue &= kSearchByteUnsignedMaskTable[search->bytes];
+
+ sprintf(valueSignedBuffer, "-%.*X (-%d)", kSearchByteDigitsTable[search->bytes], tempValue, tempValue);
+ }
+ else
+ sprintf(valueSignedBuffer, "%.*X (%d)", kSearchByteDigitsTable[search->bytes], search->oldOptions.delta & kSearchByteMaskTable[search->bytes], search->oldOptions.delta & kSearchByteMaskTable[search->bytes]);
+
+ menuSubItem[kMenu_Time] = valueSignedBuffer;
+ menuSubItem[kMenu_Energy] = energyStrings[search->oldOptions.energy];
+ menuSubItem[kMenu_Status] = equalOrNotStrings[search->oldOptions.status];
+ menuSubItem[kMenu_Operand] = operandStrings[search->oldOptions.operand];
+ }
+
+ /* ----- adjust current cursor position ----- */
+ if(sel < 0)
+ sel = 0;
+ if(sel >= total)
+ sel = total - 1;
+
+ /* ----- draw it ----- */
+ old_style_menu(menuItem, menuSubItem, 0, sel, 0);
+
+ /********** KEY HANDLING **********/
+ if(AltKeyPressed())
+ increment <<= 4;
+
+ if(UIPressedRepeatThrottle(IPT_UI_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel++;
+
+ /* ----- if divider, skip it ----- */
+ if((sel == kMenu_Divider) || (sel == kMenu_Divider2))
+ sel++;
+
+ if(sel >= total)
+ sel = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_UP, kVerticalKeyRepeatRate))
+ {
+ sel--;
+
+ /* ----- if divider, skip it ----- */
+ if((sel == kMenu_Divider) || (sel == kMenu_Divider2))
+ sel--;
+
+ if(sel < 0)
+ sel = total - 1;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_UP, kVerticalKeyRepeatRate))
+ {
+ sel -= fullMenuPageHeight;
+
+ if(sel < 0)
+ sel = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel += fullMenuPageHeight;
+
+ if(sel >= total)
+ sel = total - 1;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_LEFT, kHorizontalFastKeyRepeatRate))
+ {
+ switch(sel)
+ {
+ case kMenu_CPU:
+ if(search->targetIdx > 0)
+ {
+ search->targetIdx--;
+
+ BuildSearchRegions(search);
+ AllocateSearchRegions(search);
+
+ doneSaveMemory = 0;
+ }
+ break;
+
+ case kMenu_ValueEqual:
+ case kMenu_ValueNearTo:
+ search->oldOptions.value -= increment;
+
+ search->oldOptions.value &= kSearchByteMaskTable[search->bytes];
+ break;
+
+ case kMenu_Time:
+ if(doneSaveMemory)
+ {
+ search->oldOptions.delta -= increment;
+
+ search->oldOptions.delta &= kSearchByteMaskTable[search->bytes];
+ }
+ break;
+
+ case kMenu_Energy:
+ if(doneSaveMemory)
+ {
+ if(search->oldOptions.energy < kEnergy_GreaterOrEqual)
+ search->oldOptions.energy++;
+ else
+ search->oldOptions.energy = kEnergy_Less;
+ }
+ break;
+
+ case kMenu_Status:
+ if(doneSaveMemory)
+ search->oldOptions.status ^= 1;
+ break;
+
+ case kMenu_Operand:
+ if(doneSaveMemory)
+ search->oldOptions.operand ^= 1;
+ break;
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_RIGHT, kHorizontalFastKeyRepeatRate))
+ {
+ switch(sel)
+ {
+ case kMenu_CPU:
+ if(search->targetIdx < cpu_gettotalcpu() - 1)
+ {
+ search->targetIdx++;
+
+ BuildSearchRegions(search);
+ AllocateSearchRegions(search);
+
+ doneSaveMemory = 0;
+ }
+ break;
+
+ case kMenu_ValueEqual:
+ case kMenu_ValueNearTo:
+ search->oldOptions.value += increment;
+
+ search->oldOptions.value &= kSearchByteMaskTable[search->bytes];
+ break;
+
+ case kMenu_Time:
+ if(doneSaveMemory)
+ {
+ search->oldOptions.delta += increment;
+
+ search->oldOptions.delta &= kSearchByteMaskTable[search->bytes];
+ }
+ break;
+
+ case kMenu_Energy:
+ if(doneSaveMemory)
+ {
+ if(search->oldOptions.energy > kEnergy_Less)
+ search->oldOptions.energy--;
+ else
+ search->oldOptions.energy = kEnergy_GreaterOrEqual;
+ }
+ break;
+
+ case kMenu_Status:
+ if(doneSaveMemory)
+ search->oldOptions.status ^= 1;
+ break;
+
+ case kMenu_Operand:
+ if(doneSaveMemory)
+ search->oldOptions.operand ^= 1;
+ break;
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_SELECT))
+ {
+ switch(sel)
+ {
+ case kMenu_DoMemorySave: // save memory to search newly
+ doneSaveMemory = 0;
+
+ doSearch = 1;
+ break;
+
+ case kMenu_CPU:
+ submenuChoice = 1; // go to region selection menu
+ break;
+
+ case kMenu_ValueEqual:
+ case kMenu_ValueNearTo:
+ search->bytes = kSearchSize_8Bit;
+ search->lhs = kSearchOperand_Current;
+ search->rhs = kSearchOperand_Value;
+
+ if(sel == kMenu_ValueEqual)
+ search->comparison = kSearchComparison_EqualTo; // search requested value
+ else
+ search->comparison = kSearchComparison_NearTo; // search requested and requested -1 value
+
+ search->value = search->oldOptions.value;
+
+ doSearch = 1;
+ break;
+
+ case kMenu_Time:
+ search->bytes = kSearchSize_8Bit;
+ search->lhs = kSearchOperand_Current;
+ search->rhs = kOperandConversionTable[search->oldOptions.operand];
+ search->comparison = kSearchComparison_IncreasedBy;
+ search->value = search->oldOptions.delta;
+
+ doSearch = 1;
+ break;
+
+ case kMenu_Energy:
+ search->bytes = kSearchSize_8Bit;
+ search->lhs = kSearchOperand_Current;
+ search->rhs = kOperandConversionTable[search->oldOptions.operand];
+ search->comparison = kEnergyComparisonConversionTable[search->oldOptions.energy];
+
+ doSearch = 1;
+ break;
+
+ case kMenu_Status:
+ search->bytes = kSearchSize_8Bit;
+ search->lhs = kSearchOperand_Current;
+ search->rhs = kOperandConversionTable[search->oldOptions.operand];
+ search->comparison = kEqualOrNotConversionTable[search->oldOptions.status];
+
+ doSearch = 1;
+ break;
+
+ case kMenu_ViewResult:
+ if(search->regionListLength)
+ {
+ /* ----- go to result viewer ----- */
+ firstEntry = 1;
+ submenuChoice = 1;
+ }
+ else
+ /* ----- if no search region (eg, sms.c in HazeMD), don't open result viewer to avoid the crash ----- */
+ ui_popup_time(1, "no search regions");
+ break;
+
+ case kMenu_RestoreSearch:
+ /* ----- restore previous results ----- */
+ RestoreSearchBackup(search);
+ break;
+
+ case kMenu_Return:
+ sel = -1;
+ lastPos = 0;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_ZOOM_IN, kVerticalKeyRepeatRate))
+ /* ----- quick menu switch : search -> watchpoint list ----- */
+ sel = -5;
+
+ if(UIPressedRepeatThrottle(IPT_UI_ZOOM_OUT, kVerticalKeyRepeatRate))
+ /* ----- quick menu switch : search -> add/edit ----- */
+ sel = -3;
+
+
+ if(input_ui_pressed(IPT_UI_CANCEL))
+ {
+ /* ----- if cursor is now on the return item, adjust cursor keeper ----- */
+ if(sel == kMenu_Return)
+ lastPos = 0;
+
+ sel = -1;
+ }
+
+ if(doSearch)
+ {
+ if(!doneSaveMemory)
+ /* ----- initialize search ----- */
+ InitializeNewSearch(search);
+
+ if( (sel == kMenu_ValueEqual) || (sel == kMenu_ValueNearTo) || doneSaveMemory)
+ {
+ /* ----- do search ----- */
+ BackupSearch(search);
+
+ DoSearch(search);
+ }
+
+ UpdateSearch(search);
+
+ if( (sel == kMenu_ValueEqual) || (sel == kMenu_ValueNearTo) || doneSaveMemory)
+ popmessage("%d results found", search->numResults);
+ else
+ popmessage("saved all memory regions");
+
+ doneSaveMemory = 1;
+
+ if(search->numResults == 1)
+ {
+ AddCheatFromFirstResult(search);
+
+ popmessage("1 result found, added to list");
+ }
+ }
+
+ /* ----- edit a value if direct key input ----- */
+ if((sel == kMenu_ValueEqual) || (sel == kMenu_ValueNearTo))
+ {
+ search->oldOptions.value = DoEditHexField(search->oldOptions.value);
+
+ search->oldOptions.value &= kSearchByteMaskTable[search->bytes];
+ }
+ else
+ {
+ if(sel == kMenu_Time)
+ {
+ search->oldOptions.delta = DoEditHexField(search->oldOptions.delta);
+
+ search->oldOptions.delta &= kSearchByteMaskTable[search->bytes];
+ }
+ }
+
+ /* ----- keep current cursor position ----- */
+ if(sel >= 0)
+ lastPos = sel;
+
+ return sel + 1;
+}
+
+/*-----------------------------------------------------
+ DoSearchMenu - management for advanced search menu
+-----------------------------------------------------*/
+
+static int DoSearchMenu(int selection)
+{
+ /* menu stirngs */
+ static const char * kOperandNameTable[] =
+ {
+ "Current Data",
+ "Previous Data",
+ "First Data",
+ "Value"
+ };
+
+ static const char * kComparisonNameTable[] =
+ {
+ "Less",
+ "Greater",
+ "Equal",
+ "Less Or Equal",
+ "Greater Or Equal",
+ "Not Equal",
+ "Increased By Value",
+ "Near To"
+ };
+
+ static const char * kSearchByteNameTable[] =
+ {
+ "1",
+ "2",
+ "3",
+ "4",
+ "Bit"
+ };
+
+ enum
+ {
+ kMenu_LHS,
+ kMenu_Comparison,
+ kMenu_RHS,
+ kMenu_Value,
+
+ kMenu_Divider,
+
+ kMenu_Size,
+ kMenu_Swap,
+ kMenu_Sign,
+ kMenu_CPU,
+ kMenu_Name,
+
+ kMenu_Divider2,
+
+ kMenu_DoSearch,
+ kMenu_SaveMemory,
+
+ kMenu_Divider3,
+
+ kMenu_ViewResult,
+ kMenu_RestoreSearch,
+
+ kMenu_Return,
+
+ kMenu_Max
+ };
+
+ const char * menu_item[kMenu_Max + 2] = { 0 };
+ const char * menu_subitem[kMenu_Max + 2] = { 0 };
+
+ char valueBuffer[20];
+ char cpuBuffer[20];
+ char flagBuf[kMenu_Max + 2] = { 0 };
+
+ SearchInfo * search = GetCurrentSearch();
+
+ INT32 sel = selection - 1;
+ INT32 total = 0;
+ UINT32 increment = 1;
+
+ static INT8 submenuChoice = 0;
+ static UINT8 doneMemorySave = 0;
+ static UINT8 editActive = 0;
+ static UINT8 firstEntry = 0;
+ static int lastSel = 0;
+
+ sel = lastSel;
+
+ /********** SUB MENU **********/
+ if(submenuChoice)
+ {
+ switch(sel)
+ {
+ case kMenu_CPU:
+ submenuChoice = SelectSearchRegions(submenuChoice, GetCurrentSearch());
+ break;
+
+ case kMenu_ViewResult:
+ submenuChoice = ViewSearchResults(submenuChoice, firstEntry);
+ break;
+ }
+
+ firstEntry = 0;
+
+ /* ----- meaningless ? because no longer return with sel = -1 (pressed UI_CONFIG in submenu) ----- */
+// if(submenuChoice == -1)
+// submenuChoice = 0;
+
+ return sel + 1;
+ }
+
+ /********** MENU CONSTRUCION **********/
+ if((search->sign || search->comparison == kSearchComparison_IncreasedBy) && (search->value & kSearchByteSignBitTable[search->bytes]))
+ {
+ UINT32 tempValue;
+
+ tempValue = ~search->value + 1;
+ tempValue &= kSearchByteUnsignedMaskTable[search->bytes];
+
+ sprintf(valueBuffer, "-%.*X", kSearchByteDigitsTable[search->bytes], tempValue);
+ }
+ else
+ sprintf(valueBuffer, "%.*X", kSearchByteDigitsTable[search->bytes], search->value & kSearchByteMaskTable[search->bytes]);
+
+ if(TEST_FIELD(cheatOptions, DontPrintNewLabels))
+ {
+ menu_item[total] = kOperandNameTable[search->lhs];
+ menu_subitem[total++] = NULL;
+
+ menu_item[total] = kComparisonNameTable[search->comparison];
+ menu_subitem[total++] = NULL;
+
+ menu_item[total] = kOperandNameTable[search->rhs];
+ menu_subitem[total++] = NULL;
+
+ menu_item[total] = valueBuffer;
+ menu_subitem[total++] = NULL;
+ }
+ else
+ {
+ menu_item[total] = "LHS";
+ menu_subitem[total++] = kOperandNameTable[search->lhs];
+
+ menu_item[total] = "Comparison";
+ menu_subitem[total++] = kComparisonNameTable[search->comparison];
+
+ menu_item[total] = "RHS";
+ menu_subitem[total++] = kOperandNameTable[search->rhs];
+
+ menu_item[total] = "Value";
+ menu_subitem[total++] = valueBuffer;
+ }
+
+ menu_item[total] = "---";
+ menu_subitem[total++] = NULL;
+
+ menu_item[total] = "Size";
+ menu_subitem[total++] = kSearchByteNameTable[search->bytes];
+
+ menu_item[total] = "Swap";
+ menu_subitem[total++] = ui_getstring(search->swap ? UI_on : UI_off);
+
+ menu_item[total] = "Signed";
+ menu_subitem[total++] = ui_getstring(search->sign ? UI_on : UI_off);
+
+ sprintf(cpuBuffer, "%d", search->targetIdx);
+ menu_item[total] = "CPU";
+ menu_subitem[total++] = cpuBuffer;
+
+ menu_item[total] = "Name";
+ if(search->name)
+ menu_subitem[total++] = search->name;
+ else
+ menu_subitem[total++] = "(none)";
+
+ menu_item[total] = "---";
+ menu_subitem[total++] = NULL;
+
+ menu_item[total] = "Do Search";
+ menu_subitem[total++] = NULL;
+
+ menu_item[total] = "Save Memory";
+ menu_subitem[total++] = NULL;
+
+ menu_item[total] = "---";
+ menu_subitem[total++] = NULL;
+
+ menu_item[total] = ui_getstring(UI_viewresults); // view result
+ menu_subitem[total++] = NULL;
+
+ menu_item[total] = ui_getstring(UI_restoreresults); // restore result
+ menu_subitem[total++] = NULL;
+
+ menu_item[total] = ui_getstring(UI_returntoprior); // return
+ menu_subitem[total++] = NULL;
+
+ menu_item[total] = NULL; // terminate array
+ menu_subitem[total] = NULL;
+
+ /* ----- adjust current cursor position ----- */
+ if(sel < 0)
+ sel = 0;
+ if(sel >= total)
+ sel = total - 1;
+
+ /* ----- higlighted sub-item if edit mode ----- */
+ if(editActive)
+ flagBuf[sel] = 1;
+
+ /* ----- draw it ----- */
+ old_style_menu(menu_item, menu_subitem, flagBuf, sel, 0);
+
+ /********** KEY HANDLING **********/
+ if(AltKeyPressed())
+ increment <<= 4;
+ if(ControlKeyPressed())
+ increment <<= 8;
+ if(ShiftKeyPressed())
+ increment <<= 16;
+
+ if(UIPressedRepeatThrottle(IPT_UI_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel++;
+
+ /* ----- if divider, skip it ----- */
+ if((sel == kMenu_Divider) || (sel == kMenu_Divider2) || (sel == kMenu_Divider3))
+ sel++;
+
+ if(sel >= total)
+ sel = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_UP, kVerticalKeyRepeatRate))
+ {
+ sel--;
+
+ /* ----- if divider, skip it ----- */
+ if((sel == kMenu_Divider) || (sel == kMenu_Divider2) || (sel == kMenu_Divider3))
+ sel--;
+
+ if(sel < 0)
+ sel = total - 1;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_UP, kVerticalKeyRepeatRate))
+ {
+ sel -= fullMenuPageHeight;
+
+ if(sel < 0)
+ sel = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel += fullMenuPageHeight;
+
+ if(sel >= total)
+ sel = total - 1;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_LEFT, kHorizontalFastKeyRepeatRate))
+ {
+ switch(sel)
+ {
+ case kMenu_Value:
+ search->value -= increment;
+
+ search->value &= kSearchByteMaskTable[search->bytes];
+ break;
+
+ case kMenu_LHS:
+ search->lhs--;
+
+ if(search->lhs < kSearchOperand_Current)
+ search->lhs = kSearchOperand_Max;
+ break;
+
+ case kMenu_RHS:
+ search->rhs--;
+
+ if(search->rhs < kSearchOperand_Current)
+ search->rhs = kSearchOperand_Max;
+ break;
+
+ case kMenu_Comparison:
+ search->comparison--;
+
+ if(search->comparison < kSearchComparison_LessThan)
+ search->comparison = kSearchComparison_Max;
+ break;
+
+ case kMenu_Size:
+ search->bytes--;
+
+ if(search->bytes < kSearchSize_8Bit)
+ search->bytes = kSearchSize_Max;
+ break;
+
+ case kMenu_Swap:
+ search->swap ^= 1;
+ break;
+
+ case kMenu_Sign:
+ search->sign ^= 1;
+ break;
+
+ case kMenu_CPU:
+ if(search->targetIdx > 0)
+ {
+ search->targetIdx--;
+
+ BuildSearchRegions(search);
+ AllocateSearchRegions(search);
+
+ doneMemorySave = 0;
+ }
+ break;
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_RIGHT, kHorizontalFastKeyRepeatRate))
+ {
+ switch(sel)
+ {
+ case kMenu_Value:
+ search->value += increment;
+
+ search->value &= kSearchByteMaskTable[search->bytes];
+ break;
+
+ case kMenu_Size:
+ search->bytes++;
+
+ if(search->bytes > kSearchSize_Max)
+ search->bytes = kSearchSize_8Bit;
+ break;
+
+ case kMenu_LHS:
+ search->lhs++;
+
+ if(search->lhs > kSearchOperand_Max)
+ search->lhs = kSearchOperand_Current;
+ break;
+
+ case kMenu_RHS:
+ search->rhs++;
+
+ if(search->rhs > kSearchOperand_Max)
+ search->rhs = kSearchOperand_Current;
+ break;
+
+ case kMenu_Comparison:
+ search->comparison++;
+
+ if(search->comparison > kSearchComparison_Max)
+ search->comparison = kSearchComparison_LessThan;
+ break;
+
+ case kMenu_Swap:
+ search->swap ^= 1;
+ break;
+
+ case kMenu_Sign:
+ search->sign ^= 1;
+ break;
+
+ case kMenu_CPU:
+ if(search->targetIdx < cpu_gettotalcpu() - 1)
+ {
+ search->targetIdx++;
+
+ BuildSearchRegions(search);
+ AllocateSearchRegions(search);
+
+ doneMemorySave = 0;
+ }
+ break;
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_SELECT))
+ {
+ if(editActive)
+ editActive = 0;
+ else
+ {
+ switch(sel)
+ {
+ case kMenu_Value: // edit selected field
+ case kMenu_Name:
+ editActive = 1;
+ break;
+
+ case kMenu_CPU: // go to region selection menu
+ submenuChoice = 1;
+ break;
+
+ case kMenu_DoSearch:
+ if(!doneMemorySave)
+ /* ----- initialize search ----- */
+ InitializeNewSearch(search);
+
+ if((!kSearchOperandNeedsInit[search->lhs] && !kSearchOperandNeedsInit[search->rhs]) || doneMemorySave)
+ {
+ BackupSearch(search);
+
+ DoSearch(search);
+ }
+
+ UpdateSearch(search);
+
+ if((!kSearchOperandNeedsInit[search->lhs] && !kSearchOperandNeedsInit[search->rhs]) || doneMemorySave)
+ popmessage("%d results found", search->numResults);
+ else
+ popmessage("saved all memory regions");
+
+ doneMemorySave = 1;
+
+ if(search->numResults == 1)
+ {
+ AddCheatFromFirstResult(search);
+
+ popmessage("1 result found, added to list");
+ }
+ break;
+
+ case kMenu_SaveMemory:
+ InitializeNewSearch(search);
+
+ UpdateSearch(search);
+
+ popmessage("saved all memory regions");
+
+ doneMemorySave = 1;
+ break;
+
+ case kMenu_ViewResult:
+ if(search->regionListLength)
+ {
+ /* ----- go to result viewer ----- */
+ firstEntry = 1;
+ submenuChoice = 1;
+ }
+ else
+ /* ----- if no search region (eg, sms.c in HazeMD), don't open result viewer to avoid the crash ----- */
+ ui_popup_time(1, "no search regions");
+ break;
+
+ case kMenu_RestoreSearch:
+ /* ----- restore previous results ----- */
+ RestoreSearchBackup(search);
+ break;
+
+ case kMenu_Return:
+ submenuChoice = 0;
+ sel = -1;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ /* ----- edit selected field ----- */
+ if(editActive)
+ {
+ switch(sel)
+ {
+ case kMenu_Value:
+ search->value = DoEditHexField(search->value);
+
+ search->value &= kSearchByteMaskTable[search->bytes];
+ break;
+
+ case kMenu_Name:
+ search->name = DoDynamicEditTextField(search->name);
+ break;
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_CANCEL))
+ sel = -1;
+
+ /* ----- keep current cursor position ----- */
+ if(!(sel == -1))
+ lastSel = sel;
+
+ return sel + 1;
+}
+
+/*---------------------------------------------------------------------
+ SelectSearchRegions - management for search regions selection menu
+---------------------------------------------------------------------*/
+
+static int SelectSearchRegions(int selection, SearchInfo * search)
+{
+ static const char * kSearchSpeedList[] =
+ {
+ "Fast",
+ "Medium",
+ "Slow",
+ "Very Slow",
+ "All Memory"
+ };
+
+ INT32 sel;
+ const char ** menuItem;
+ const char ** menuSubItem;
+ INT32 i;
+ INT32 total = 0;
+ SearchRegion * region;
+
+ if(!search)
+ return 0;
+
+ sel = selection - 1;
+
+ RequestStrings(search->regionListLength + 3, 0, 0, 0);
+
+ /********** MENU CONSTRUCTION **********/
+ menuItem = menuStrings.mainList;
+ menuSubItem = menuStrings.subList;
+
+ for(i = 0; i < search->regionListLength; i++)
+ {
+ SearchRegion * traverse = &search->regionList[i];
+
+ menuItem[total] = traverse->name;
+ menuSubItem[total++] = ui_getstring((traverse->flags & kRegionFlag_Enabled) ? UI_on : UI_off);
+ }
+
+ menuItem[total] = "Search Speed";
+ menuSubItem[total++] = kSearchSpeedList[search->searchSpeed];
+
+ menuItem[total] = ui_getstring(UI_returntoprior); // return item
+ menuSubItem[total++] = NULL;
+
+ menuItem[total] = NULL; // terminate array
+ menuSubItem[total] = NULL;
+
+ /* ----- adjust current cursor positon ----- */
+ if(sel < 0)
+ sel = 0;
+ if(sel > (total - 1))
+ sel = total - 1;
+
+ if(sel < search->regionListLength)
+ region = &search->regionList[sel];
+ else
+ region = NULL;
+
+ /* ----- draw it ----- */
+ old_style_menu(menuItem, menuSubItem, NULL, sel, 0);
+
+ /********** KEY HANDLING **********/
+ if(UIPressedRepeatThrottle(IPT_UI_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel++;
+
+ if(sel >= total)
+ sel = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_UP, kVerticalKeyRepeatRate))
+ {
+ sel--;
+
+ if(sel < 0)
+ sel = total - 1;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_UP, kVerticalKeyRepeatRate))
+ {
+ sel -= fullMenuPageHeight;
+
+ if(sel < 0)
+ sel = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel += fullMenuPageHeight;
+
+ if(sel >= total)
+ sel = total - 1;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_LEFT, kHorizontalSlowKeyRepeatRate))
+ {
+ if(sel < search->regionListLength)
+ {
+ search->regionList[sel].flags ^= kRegionFlag_Enabled;
+
+ AllocateSearchRegions(search);
+ }
+
+ if(sel == search->regionListLength) // set search speed
+ {
+ if(search->searchSpeed > kSearchSpeed_Fast)
+ search->searchSpeed--;
+ else
+ search->searchSpeed = kSearchSpeed_Max;
+
+ BuildSearchRegions(search);
+ AllocateSearchRegions(search);
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_RIGHT, kHorizontalSlowKeyRepeatRate))
+ {
+ if(sel < search->regionListLength)
+ {
+ search->regionList[sel].flags ^= kRegionFlag_Enabled;
+
+ AllocateSearchRegions(search);
+ }
+
+ if(sel == search->regionListLength) // set search speed
+ {
+ if(search->searchSpeed < kSearchSpeed_Max)
+ search->searchSpeed++;
+ else
+ search->searchSpeed = kSearchSpeed_Fast;
+
+ BuildSearchRegions(search);
+ AllocateSearchRegions(search);
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_DELETE_CHEAT))
+ {
+ if(ShiftKeyPressed()) // shift + delete = invalid region
+ {
+ if(region && search)
+ {
+ InvalidateEntireRegion(search, region);
+
+ ui_popup_time(1, "region invalidated - %d results remain", search->numResults);
+ }
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_SELECT))
+ {
+ if(sel >= total - 1)
+ sel = -1;
+ }
+
+ if(input_ui_pressed(IPT_UI_CANCEL))
+ sel = -1;
+
+ return sel + 1;
+}
+
+/*--------------------------------------------------------
+ ViewSearchResults - management for search result menu
+--------------------------------------------------------*/
+
+static int ViewSearchResults(int selection, int firstTime)
+{
+ enum
+ {
+ kMenu_Header = 0,
+ kMenu_FirstResult,
+
+ kMaxResultsPerPage = 100
+ };
+
+ const char ** menu_item;
+ char ** buf;
+ char * header;
+
+ SearchInfo * search = GetCurrentSearch();
+ SearchRegion * region;
+
+ INT32 sel;
+ INT32 total = 0;
+ INT32 numPages;
+ INT32 resultsPerPage;
+ INT32 i;
+ UINT32 traverse;
+ UINT8 hadResults = 0;
+ INT32 numToSkip;
+ UINT32 resultsFound = 0;
+ UINT32 selectedAddress = 0;
+ UINT32 selectedOffset = 0;
+ UINT8 selectedAddressGood = 0;
+ int goToNextPage = 0;
+ int goToPrevPage = 0;
+
+ RequestStrings(kMaxResultsPerPage + 3, kMaxResultsPerPage + 3, 80, 0);
+
+ menu_item = menuStrings.mainList;
+ buf = &menuStrings.mainStrings[1];
+ header = menuStrings.mainStrings[0];
+
+ sel = selection - 1;
+
+ /********** FIRST SETTING **********/
+ if(firstTime)
+ {
+ search->currentRegionIdx = 0;
+ search->currentResultsPage = 0;
+
+ /* ----- set current REGION for first display ----- */
+ for(traverse = 0; traverse < search->regionListLength; traverse++)
+ {
+ region = &search->regionList[traverse];
+
+ if(region->numResults)
+ {
+ search->currentRegionIdx = traverse;
+ break;
+ }
+ }
+ }
+
+ /* ----- adjust current REGION ----- */
+ if(search->currentRegionIdx >= search->regionListLength)
+ search->currentRegionIdx = search->regionListLength - 1;
+ if(search->currentRegionIdx < 0)
+ search->currentRegionIdx = 0;
+
+ region = &search->regionList[search->currentRegionIdx];
+
+ /* ----- set and adjust maximum displayable result in the PAGE ----- */
+ resultsPerPage = fullMenuPageHeight - 3;
+
+ if(resultsPerPage <= 0)
+ resultsPerPage = 1;
+ else if(resultsPerPage > kMaxResultsPerPage)
+ resultsPerPage = kMaxResultsPerPage;
+
+ /* ----- get the number of total page ----- */
+ if(region->flags & kRegionFlag_Enabled)
+ numPages = (region->numResults / kSearchByteStep[search->bytes] + resultsPerPage - 1) / resultsPerPage;
+ else
+ numPages = 0;
+
+ /* ----- adjust current PAGE ----- */
+ if(search->currentResultsPage >= numPages)
+ search->currentResultsPage = numPages - 1;
+ if(search->currentResultsPage < 0)
+ search->currentResultsPage = 0;
+
+ /* ----- set the number of undisplay result ----- */
+ numToSkip = resultsPerPage * search->currentResultsPage;
+
+ /********** MENU CONSTRUCTION **********/
+ /* ----- construct header item ----- */
+ sprintf(header, "%s %d/%d", region->name, search->currentResultsPage + 1, numPages);
+
+ menu_item[total++] = header;
+
+ traverse = 0;
+
+ if((region->length < kSearchByteIncrementTable[search->bytes]) || !(region->flags & kRegionFlag_Enabled))
+ ; // no results...
+ else
+ {
+ /* ----- construct result item ----- */
+ for(i = 0; (i < resultsPerPage) && (traverse < region->length) && (resultsFound < region->numResults);)
+ {
+ while(!IsRegionOffsetValid(search, region, traverse) && (traverse < region->length))
+ traverse += kSearchByteStep[search->bytes];
+
+ if(traverse < region->length)
+ {
+ if(numToSkip > 0)
+ numToSkip--;
+ else
+ {
+ if(total == sel)
+ {
+ selectedAddress = region->address + traverse;
+ selectedOffset = traverse;
+ selectedAddressGood = 1;
+ }
+
+ sprintf( buf[total],
+ "%.8X (%.*X %.*X %.*X)",
+ region->address + traverse,
+ kSearchByteDigitsTable[search->bytes],
+ ReadSearchOperand(kSearchOperand_First, search, region, region->address + traverse),
+ kSearchByteDigitsTable[search->bytes],
+ ReadSearchOperand(kSearchOperand_Previous, search, region, region->address + traverse),
+ kSearchByteDigitsTable[search->bytes],
+ ReadSearchOperand(kSearchOperand_Current, search, region, region->address + traverse));
+
+ menu_item[total] = buf[total];
+ total++;
+
+ i++;
+ }
+
+ traverse += kSearchByteStep[search->bytes];
+ resultsFound++;
+ hadResults = 1;
+ }
+ }
+ }
+
+ /* ----- set special message if empty REGION ----- */
+ if(!hadResults)
+ {
+ if(search->numResults)
+ menu_item[total++] = "no results for this region";
+ else
+ menu_item[total++] = "no results found";
+ }
+
+ menu_item[total++] = ui_getstring(UI_returntoprior); // return
+
+ menu_item[total] = NULL; // terminate array
+
+ /* ----- adjust current cursor position ----- */
+ if(sel <= kMenu_Header)
+ sel = kMenu_FirstResult;
+ if(sel > (total - 1) || !hadResults)
+ sel = total - 1;
+
+ /* ----- draw it ----- */
+ old_style_menu(menu_item, NULL, NULL, sel, 0);
+
+ /********** KEY HANDLING **********/
+ if(UIPressedRepeatThrottle(IPT_UI_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel++;
+
+ if(sel >= total)
+ sel = kMenu_FirstResult;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_UP, kVerticalKeyRepeatRate))
+ {
+ sel--;
+
+ if(sel < 1)
+ sel = total - 1;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_RIGHT, kHorizontalFastKeyRepeatRate))
+ {
+ if(ShiftKeyPressed())
+ search->currentResultsPage = numPages - 1; // shift + right = go to last PAGE
+ else
+ {
+ if(ControlKeyPressed())
+ {
+ search->currentRegionIdx++; // ctrl + right = go to next REGION
+
+ if(search->currentRegionIdx >= search->regionListLength)
+ search->currentRegionIdx = 0;
+ }
+ else
+ goToNextPage = 1; // right = go to next PAGE
+ }
+
+ sel = kMenu_FirstResult;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_LEFT, kHorizontalFastKeyRepeatRate))
+ {
+ if(ShiftKeyPressed())
+ search->currentResultsPage = 0; // shift + left = go to first PAGE
+ else
+ {
+ if(ControlKeyPressed())
+ {
+ search->currentRegionIdx--; // ctrl + left = go to previous REGION
+
+ if(search->currentRegionIdx < 0)
+ search->currentRegionIdx = search->regionListLength - 1;
+ }
+ else
+ goToPrevPage = 1; // left = go to previous PAGE
+ }
+
+ sel = kMenu_FirstResult;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_UP, kHorizontalFastKeyRepeatRate))
+ {
+ sel -=fullMenuPageHeight;
+
+ if(sel <= kMenu_Header)
+ sel = kMenu_FirstResult;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_DOWN, kHorizontalFastKeyRepeatRate))
+ {
+ sel +=fullMenuPageHeight;
+
+ if(sel >= total)
+ sel = total - 1;
+ }
+
+ if(input_code_pressed_once(KEYCODE_END))
+ search->currentResultsPage = numPages - 1; // go to last PAGE
+
+ if(input_code_pressed_once(KEYCODE_HOME))
+ search->currentResultsPage = 0; // go to first PAGE
+
+ if(UIPressedRepeatThrottle(IPT_UI_PREV_GROUP, kVerticalKeyRepeatRate))
+ {
+ search->currentRegionIdx--; // go to previous REGION
+
+ if(search->currentRegionIdx < 0)
+ search->currentRegionIdx = search->regionListLength - 1;
+
+ sel = kMenu_FirstResult;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_NEXT_GROUP, kVerticalKeyRepeatRate))
+ {
+ search->currentRegionIdx++; // go to next REGION
+
+ if(search->currentRegionIdx >= search->regionListLength)
+ search->currentRegionIdx = 0;
+
+ sel = kMenu_FirstResult;
+ }
+
+ if(goToNextPage)
+ {
+ search->currentResultsPage++;
+
+ /* ----- if current PAGE is the last, go to first PAGE in next REGION ----- */
+ if(search->currentResultsPage >= numPages)
+ {
+ search->currentResultsPage = 0;
+ search->currentRegionIdx++;
+
+ /* ----- if current REGION is the last, go to first REGION ----- */
+ if(search->currentRegionIdx >= search->regionListLength)
+ search->currentRegionIdx = 0;
+
+ /* ----- if next REGION is empty, search next "non-empty" REGION.
+ but incomplete because last REGION is displayed even if empty ----- */
+ for(traverse = search->currentRegionIdx; traverse < search->regionListLength; traverse++)
+ {
+ search->currentRegionIdx = traverse;
+
+ if(search->regionList[traverse].numResults)
+ break;
+ }
+ }
+
+ sel = kMenu_FirstResult;
+ }
+
+ if(goToPrevPage)
+ {
+ search->currentResultsPage--;
+
+ /* ----- if current PAGE is first, go to previous REGION ----- */
+ if(search->currentResultsPage < 0)
+ {
+ search->currentResultsPage = 0;
+ search->currentRegionIdx--;
+
+ /* ----- if current REGION is first, go to last REGION ----- */
+ if(search->currentRegionIdx < 0)
+ search->currentRegionIdx = search->regionListLength - 1;
+
+ /* ----- if previous REGION is empty, search previous "non-empty" REGION.
+ but incomplete because first REGION is displayed even if empty ----- */
+ for(i = search->currentRegionIdx; i >= 0; i--)
+ {
+ search->currentRegionIdx = i;
+
+ if(search->regionList[i].numResults)
+ break;
+ }
+
+ /* ----- go to last PAGE in previous REGION ----- */
+ {
+ /* ----- get the number of total page for previous REGION ----- */
+ SearchRegion * newRegion = &search->regionList[search->currentRegionIdx];
+ UINT32 nextNumPages = (newRegion->numResults / kSearchByteStep[search->bytes] + resultsPerPage - 1) / resultsPerPage;
+
+ if(nextNumPages <= 0)
+ nextNumPages = 1;
+
+ search->currentResultsPage = nextNumPages - 1;
+ }
+ }
+
+ sel = kMenu_FirstResult;
+ }
+
+ if(selectedAddressGood)
+ {
+ if(input_ui_pressed(IPT_UI_WATCH_VALUE))
+ AddWatchFromResult(search, region, selectedAddress); // watch selected result
+
+ if(input_ui_pressed(IPT_UI_ADD_CHEAT))
+ AddCheatFromResult(search, region, selectedAddress); // add selected result as new code to cheat list
+
+ if(input_ui_pressed(IPT_UI_DELETE_CHEAT))
+ {
+ InvalidateRegionOffset(search, region, selectedOffset); // delete selected result
+ search->numResults--;
+ region->numResults--;
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_DELETE_CHEAT))
+ {
+ if(ShiftKeyPressed())
+ {
+ if(region && search)
+ {
+ InvalidateEntireRegion(search, region); // invalidate all results in current REGION
+
+ ui_popup_time(1, "region invalidated - %d results remain", search->numResults);
+ }
+ }
+ }
+
+ if((input_ui_pressed(IPT_UI_SELECT) && (sel == total - 1)) || input_ui_pressed(IPT_UI_CANCEL))
+ sel = -1;
+
+ return sel + 1;
+}
+
+/*----------------------------------------------------
+ ChooseWatch - management for watchpoint list menu
+----------------------------------------------------*/
+
+static int ChooseWatch(int selection)
+{
+ const char ** menuItem;
+ char ** buf;
+
+ WatchInfo * watch;
+
+ static INT32 submenuChoice = 0;
+ static INT32 submenuWatch = 0;
+ INT32 sel;
+ INT32 total = 0;
+ int i;
+
+ RequestStrings(watchListLength + 2, watchListLength, 30, 0);
+
+ menuItem = menuStrings.mainList;
+ buf = menuStrings.mainStrings;
+
+ sel = selection - 1;
+
+ /********** SUB MENU **********/
+ if(submenuChoice)
+ {
+ submenuChoice = EditWatch(&watchList[submenuWatch], submenuChoice);
+
+ /* ----- meaningless ? because no longer return with sel = -1 (pressed UI_CONFIG in submenu) ----- */
+// if(submenuChoice == -1)
+// {
+// submenuChoice = 0;
+// sel = -2;
+// }
+
+ return sel + 1;
+ }
+
+ /********** MENU CONSTRUCTION **********/
+ for(i = 0; i < watchListLength; i++)
+ {
+ WatchInfo * traverse = &watchList[i];
+
+ sprintf(buf[i], "%d:%.*X (%d)", traverse->cpu, cpuInfoList[traverse->cpu].addressCharsNeeded, traverse->address, traverse->numElements);
+
+ menuItem[total] = buf[i];
+ total++;
+ }
+
+ menuItem[total++] = ui_getstring(UI_returntoprior); // return
+
+ menuItem[total] = NULL; // terminate array
+
+ /* ----- adjust current cursor position ----- */
+ if(sel < 0)
+ sel = 0;
+ if(sel >= total)
+ sel = total - 1;
+
+ /* ----- draw it ----- */
+ old_style_menu(menuItem, NULL, NULL, sel, 0);
+
+ if(sel < watchListLength)
+ watch = &watchList[sel];
+ else
+ watch = NULL;
+
+ /********** KEY HANDLING **********/
+ if(UIPressedRepeatThrottle(IPT_UI_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel++;
+
+ if(sel >= total)
+ sel = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_UP, kVerticalKeyRepeatRate))
+ {
+ sel--;
+
+ if(sel < 0)
+ sel = total - 1;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_UP, kVerticalKeyRepeatRate))
+ {
+ sel -= fullMenuPageHeight;
+
+ if(sel < 0)
+ sel = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel += fullMenuPageHeight;
+
+ if(sel >= total)
+ sel = total - 1;
+ }
+
+ if(ShiftKeyPressed())
+ {
+ if(input_ui_pressed(IPT_UI_ADD_CHEAT)) // shift + add = add new watchpoint
+ AddWatchBefore(sel);
+
+ if(input_ui_pressed(IPT_UI_DELETE_CHEAT)) // shift + delete = delete selected watchpoint
+ DeleteWatchAt(sel);
+ }
+ else
+ {
+ if(input_ui_pressed(IPT_UI_SAVE_CHEAT)) // save = save selected watchpoint as watchpoint code
+ {
+ if(watch)
+ {
+ CheatEntry entry;
+
+ memset(&entry, 0, sizeof(CheatEntry));
+
+ SetupCheatFromWatchAsWatch(&entry, watch);
+ SaveCheat(&entry, 0, 0);
+ DisposeCheat(&entry);
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_ADD_CHEAT))
+ {
+ if(watch)
+ {
+ if(ControlKeyPressed()) // ctrl + add = add selected watchpoing as watchpoint code to cheat list
+ {
+ CheatEntry * entry = GetNewCheat();
+
+ DisposeCheat(entry);
+ SetupCheatFromWatchAsWatch(entry, watch);
+ }
+ else
+ AddCheatFromWatch(watch); // add = add selected watchpoint as cheat code to cheat list
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_DELETE_CHEAT))
+ {
+ if(ControlKeyPressed())
+ {
+ for(i = 0; i < watchListLength; i++) // ctrl + delete = disable all watchpoints
+ watchList[i].numElements = 0;
+ }
+ else
+ {
+ if(watch) // delete = disable selected watchpoint
+ watch->numElements = 0;
+ }
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_EDIT_CHEAT)) // edit = edit selected watchpoint
+ {
+ if(sel < (total - 1))
+ {
+ submenuWatch = sel;
+ submenuChoice = 1;
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_SELECT))
+ {
+ if(sel == (total - 1)) // return previous menu
+ {
+ submenuChoice = 0;
+ sel = -1;
+ }
+ else
+ {
+ if(sel < (total - 1)) // edit selected watchpoint (same as edit key)
+ {
+ submenuWatch = sel;
+ submenuChoice = 1;
+ }
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_CLEAR))
+ {
+ /* ----- reset all watchpoints ----- */
+ for(i = 0; i < watchListLength; i++)
+ {
+ if(watch)
+ {
+ watchList[i].address = 0;
+ watchList[i].cpu = 0;
+ watchList[i].numElements = 0;
+ watchList[i].elementBytes = kWatchSizeConversionTable[0];
+ watchList[i].labelType = kWatchLabel_None;
+ watchList[i].displayType = kWatchDisplayType_Hex;
+ watchList[i].skip = 0;
+ watchList[i].elementsPerLine = 0;
+ watchList[i].addValue = 0;
+
+ watchList[i].linkedCheat = NULL;
+
+ watchList[i].label[0] = 0;
+ }
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_ZOOM_IN, kVerticalKeyRepeatRate))
+ /* ----- quick menu switch : watchpoint list -> enable/disable ----- */
+ sel = -2;
+
+ if(UIPressedRepeatThrottle(IPT_UI_ZOOM_OUT, kVerticalKeyRepeatRate))
+ /* ----- quick menu switch : watchpoint list -> search ----- */
+ sel = -4;
+
+ if(input_ui_pressed(IPT_UI_CANCEL))
+ sel = -1;
+
+ return sel + 1;
+}
+
+/*--------------------------------------------------
+ EditWatch - management for watchpoint edit menu
+--------------------------------------------------*/
+
+static int EditWatch(WatchInfo * entry, int selection)
+{
+ enum
+ {
+ kMenu_Address = 0,
+ kMenu_CPU,
+ kMenu_NumElements,
+ kMenu_ElementSize,
+ kMenu_LabelType,
+ kMenu_TextLabel,
+ kMenu_DisplayType,
+ kMenu_XPosition,
+ kMenu_YPosition,
+ kMenu_Skip,
+ kMenu_ElementsPerLine,
+ kMenu_AddValue,
+ kMenu_AddressShift,
+ kMenu_DataShift,
+ kMenu_XOR,
+
+ kMenu_Return
+ };
+
+ static const char * kWatchSizeStringList[] =
+ {
+ "8 Bit",
+ "16 Bit",
+ "24 Bit",
+ "32 Bit"
+ };
+
+ const char ** menuItem;
+ const char ** menuSubItem;
+ char ** buf;
+ char * flagBuf;
+
+ INT32 sel;
+ INT32 total = 0;
+ UINT32 increment = 1;
+ static UINT8 editActive = 0;
+
+ /* ----- if no watch entry, direct return ----- */
+ if(!entry)
+ return 0;
+
+ RequestStrings(kMenu_Return + 2, kMenu_Return, 0, 20);
+
+ menuItem = menuStrings.mainList;
+ menuSubItem = menuStrings.subList;
+ buf = menuStrings.subStrings;
+ flagBuf = menuStrings.flagList;
+
+ memset(flagBuf, 0, kMenu_Return + 2);
+
+ sel = selection - 1;
+
+ /********** MENU CONSTRUCTION **********/
+ sprintf(buf[total], "%.*X", cpuInfoList[entry->cpu].addressCharsNeeded, entry->address >> entry->addressShift);
+ menuItem[total] = "Address";
+ menuSubItem[total] = buf[total];
+ total++;
+
+ sprintf(buf[total], "%d", entry->cpu);
+ menuItem[total] = "CPU";
+ menuSubItem[total] = buf[total];
+ total++;
+
+ sprintf(buf[total], "%d", entry->numElements);
+ menuItem[total] = "Length";
+ menuSubItem[total] = buf[total];
+ total++;
+
+ menuItem[total] = "Element Size";
+ menuSubItem[total++] = kWatchSizeStringList[entry->elementBytes];
+
+ menuItem[total] = "Label Type";
+ menuSubItem[total++] = kWatchLabelStringList[entry->labelType];
+
+ menuItem[total] = "Text Label";
+ if(entry->label[0])
+ menuSubItem[total++] = entry->label;
+ else
+ menuSubItem[total++] = "(none)";
+
+ menuItem[total] = "Display Type";
+ menuSubItem[total++] = kWatchDisplayTypeStringList[entry->displayType];
+
+ sprintf(buf[total], "%f", entry->x);
+ menuItem[total] = "X";
+ menuSubItem[total] = buf[total];
+ total++;
+
+ sprintf(buf[total], "%f", entry->y);
+ menuItem[total] = "Y";
+ menuSubItem[total] = buf[total];
+ total++;
+
+ sprintf(buf[total], "%d", entry->skip);
+ menuItem[total] = "Skip Bytes";
+ menuSubItem[total] = buf[total];
+ total++;
+
+ sprintf(buf[total], "%d", entry->elementsPerLine);
+ menuItem[total] = "Elements Per Line";
+ menuSubItem[total] = buf[total];
+ total++;
+
+ if(entry->addValue < 0)
+ sprintf(buf[total], "-%.2X", -entry->addValue);
+ else
+ sprintf(buf[total], "%.2X", entry->addValue);
+
+ menuItem[total] = "Add Value";
+ menuSubItem[total] = buf[total];
+ total++;
+
+ sprintf(buf[total], "%d", entry->addressShift);
+ menuItem[total] = "Address Shift";
+ menuSubItem[total] = buf[total];
+ total++;
+
+ sprintf(buf[total], "%d", entry->dataShift);
+ menuItem[total] = "Data Shift";
+ menuSubItem[total] = buf[total];
+ total++;
+
+ sprintf(buf[total], "%.*X", kSearchByteDigitsTable[kWatchSizeConversionTable[entry->elementBytes]], entry->xor);
+ menuItem[total] = "XOR";
+ menuSubItem[total] = buf[total];
+ total++;
+
+ menuItem[total] = ui_getstring(UI_returntoprior); // return
+ menuSubItem[total++] = NULL;
+
+ menuItem[total] = NULL; // terminate array
+ menuSubItem[total] = NULL;
+
+ /* ----- adjust current cursor position ----- */
+ if(sel < 0)
+ sel = 0;
+ if(sel >= total)
+ sel = total - 1;
+
+ /* ----- higlighted sub-item if edit mode ----- */
+ if(editActive)
+ flagBuf[sel] = 1;
+
+ /* ----- draw it ----- */
+ old_style_menu(menuItem, menuSubItem, flagBuf, sel, 0);
+
+ /********** KEY HANDLING **********/
+ if(AltKeyPressed())
+ increment <<= 4;
+ if(ControlKeyPressed())
+ increment <<= 8;
+ if(ShiftKeyPressed())
+ increment <<= 16;
+
+ if(UIPressedRepeatThrottle(IPT_UI_LEFT, kHorizontalSlowKeyRepeatRate))
+ {
+ editActive = 0;
+
+ switch(sel)
+ {
+ case kMenu_Address:
+ entry->address = DoShift(entry->address, entry->addressShift);
+ entry->address -= increment;
+ entry->address = DoShift(entry->address, -entry->addressShift);
+
+ if(entry->locationType != kLocation_MemoryRegion)
+ entry->address &= cpuInfoList[entry->cpu].addressMask;
+
+ break;
+
+ case kMenu_CPU:
+ entry->cpu--;
+
+ if(entry->cpu >= cpu_gettotalcpu())
+ entry->cpu = cpu_gettotalcpu() - 1;
+
+ entry->address &= cpuInfoList[entry->cpu].addressMask;
+ break;
+
+ case kMenu_NumElements:
+ if(entry->numElements > 0)
+ entry->numElements--;
+ else
+ entry->numElements = 0;
+ break;
+
+ case kMenu_ElementSize:
+ if(entry->elementBytes > 0)
+ entry->elementBytes--;
+ else
+ entry->elementBytes = 0;
+
+ entry->xor &= kSearchByteMaskTable[kWatchSizeConversionTable[entry->elementBytes]];
+ break;
+
+ case kMenu_LabelType:
+ if(entry->labelType > 0)
+ entry->labelType--;
+ else
+ entry->labelType = 0;
+ break;
+
+ case kMenu_TextLabel:
+ break;
+
+ case kMenu_DisplayType:
+ if(entry->displayType > 0)
+ entry->displayType--;
+ else
+ entry->displayType = 0;
+ break;
+
+ case kMenu_XPosition:
+ entry->x -= 0.01;
+ break;
+
+ case kMenu_YPosition:
+ entry->y -= 0.01;
+ break;
+
+ case kMenu_Skip:
+ if(entry->skip > 0)
+ entry->skip--;
+ break;
+
+ case kMenu_ElementsPerLine:
+ if(entry->elementsPerLine > 0)
+ entry->elementsPerLine--;
+ break;
+
+ case kMenu_AddValue:
+ entry->addValue = (entry->addValue - 1) & 0xFF;
+ break;
+
+ case kMenu_AddressShift:
+ if(entry->addressShift > -31)
+ entry->addressShift--;
+ else
+ entry->addressShift = 31;
+ break;
+
+ case kMenu_DataShift:
+ if(entry->dataShift > -31)
+ entry->dataShift--;
+ else
+ entry->dataShift = 31;
+ break;
+
+ case kMenu_XOR:
+ entry->xor -= increment;
+ entry->xor &= kSearchByteMaskTable[kWatchSizeConversionTable[entry->elementBytes]];
+ break;
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_RIGHT, kHorizontalSlowKeyRepeatRate))
+ {
+ editActive = 0;
+
+ switch(sel)
+ {
+ case kMenu_Address:
+ entry->address = DoShift(entry->address, entry->addressShift);
+ entry->address += increment;
+ entry->address = DoShift(entry->address, -entry->addressShift);
+ entry->address &= cpuInfoList[entry->cpu].addressMask;
+ break;
+
+ case kMenu_CPU:
+ entry->cpu++;
+
+ if(entry->cpu >= cpu_gettotalcpu())
+ entry->cpu = 0;
+
+ entry->address &= cpuInfoList[entry->cpu].addressMask;
+ break;
+
+ case kMenu_NumElements:
+ entry->numElements++;
+ break;
+
+ case kMenu_ElementSize:
+ if(entry->elementBytes < kSearchSize_32Bit)
+ entry->elementBytes++;
+ else
+ entry->elementBytes = kSearchSize_32Bit;
+
+ entry->xor &= kSearchByteMaskTable[kWatchSizeConversionTable[entry->elementBytes]];
+ break;
+
+ case kMenu_LabelType:
+ if(entry->labelType < kWatchLabel_MaxPlusOne - 1)
+ entry->labelType++;
+ else
+ entry->labelType = kWatchLabel_MaxPlusOne - 1;
+ break;
+
+ case kMenu_TextLabel:
+ break;
+
+ case kMenu_DisplayType:
+ if(entry->displayType < kWatchDisplayType_MaxPlusOne - 1)
+ entry->displayType++;
+ else
+ entry->displayType = kWatchDisplayType_MaxPlusOne - 1;
+ break;
+
+ case kMenu_XPosition:
+ entry->x += 0.01;
+ break;
+
+ case kMenu_YPosition:
+ entry->y += 0.01;
+ break;
+
+ case kMenu_Skip:
+ entry->skip++;
+ break;
+
+ case kMenu_ElementsPerLine:
+ entry->elementsPerLine++;
+ break;
+
+ case kMenu_AddValue:
+ entry->addValue = (entry->addValue + 1) & 0xFF;
+ break;
+
+ case kMenu_AddressShift:
+ if(entry->addressShift < 31)
+ entry->addressShift++;
+ else
+ entry->addressShift = -31;
+ break;
+
+ case kMenu_DataShift:
+ if(entry->dataShift < 31)
+ entry->dataShift++;
+ else
+ entry->dataShift = -31;
+ break;
+
+ case kMenu_XOR:
+ entry->xor += increment;
+ entry->xor &= kSearchByteMaskTable[kWatchSizeConversionTable[entry->elementBytes]];
+ break;
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel++;
+
+ if(sel >= total)
+ sel = 0;
+
+ editActive = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_UP, kVerticalKeyRepeatRate))
+ {
+ sel--;
+
+ if(sel < 0)
+ sel = total - 1;
+
+ editActive = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_UP, kVerticalKeyRepeatRate))
+ {
+ sel -= fullMenuPageHeight;
+
+ if(sel < 0)
+ sel = 0;
+
+ editActive = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel += fullMenuPageHeight;
+
+ if(sel >= total)
+ sel = total - 1;
+
+ editActive = 0;
+ }
+
+ if(input_ui_pressed(IPT_UI_SELECT))
+ {
+ if(editActive)
+ editActive = 0;
+ else
+ {
+ switch(sel)
+ {
+ case kMenu_Return:
+ sel = -1;
+ break;
+
+ case kMenu_Address:
+ case kMenu_CPU:
+ case kMenu_NumElements:
+ case kMenu_TextLabel:
+ case kMenu_XPosition:
+ case kMenu_YPosition:
+ case kMenu_AddValue:
+ case kMenu_AddressShift:
+ case kMenu_DataShift:
+ case kMenu_XOR:
+ osd_readkey_unicode(1);
+ editActive = 1;
+ }
+ }
+ }
+
+ if(editActive)
+ {
+ switch(sel)
+ {
+ case kMenu_Address:
+ entry->address = DoShift(entry->address, entry->addressShift);
+ entry->address = DoEditHexField(entry->address);
+ entry->address = DoShift(entry->address, -entry->addressShift);
+ entry->address &= cpuInfoList[entry->cpu].addressMask;
+ break;
+
+ case kMenu_CPU:
+ entry->cpu = DoEditDecField(entry->cpu, 0, cpu_gettotalcpu() - 1);
+ entry->address &= cpuInfoList[entry->cpu].addressMask;
+ break;
+
+ case kMenu_NumElements:
+ entry->numElements = DoEditDecField(entry->numElements, 0, 99);
+ break;
+
+ case kMenu_TextLabel:
+ DoStaticEditTextField(entry->label, 255);
+ break;
+
+ case kMenu_XPosition:
+ entry->x = DoEditDecField(entry->x, -1000, 1000);
+ break;
+
+ case kMenu_YPosition:
+ entry->y = DoEditDecField(entry->y, -1000, 1000);
+ break;
+
+ case kMenu_AddValue:
+ entry->addValue = DoEditHexFieldSigned(entry->addValue, 0xFFFFFF80) & 0xFF;
+ break;
+
+ case kMenu_AddressShift:
+ entry->addressShift = DoEditDecField(entry->addressShift, -31, 31);
+ break;
+
+ case kMenu_DataShift:
+ entry->dataShift = DoEditDecField(entry->dataShift, -31, 31);
+ break;
+
+ case kMenu_XOR:
+ entry->xor = DoEditHexField(entry->xor);
+ entry->xor &= kSearchByteMaskTable[kWatchSizeConversionTable[entry->elementBytes]];
+ break;
+ }
+
+ if(input_ui_pressed(IPT_UI_CANCEL))
+ editActive = 0;
+ }
+ else
+ {
+ if(input_ui_pressed(IPT_UI_ADD_CHEAT))
+ AddCheatFromWatch(entry);
+
+ if(input_ui_pressed(IPT_UI_DELETE_CHEAT))
+ entry->numElements = 0;
+
+ if(input_ui_pressed(IPT_UI_SAVE_CHEAT))
+ {
+ CheatEntry tempEntry;
+
+ memset(&tempEntry, 0, sizeof(CheatEntry));
+
+ SetupCheatFromWatchAsWatch(&tempEntry, entry);
+ SaveCheat(&tempEntry, 0, 0);
+ DisposeCheat(&tempEntry);
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_CANCEL))
+ sel = -1;
+
+ return sel + 1;
+}
+
+/*----------------------------------------------
+ SelectOptions - management for options menu
+----------------------------------------------*/
+
+static int SelectOptions(int selection)
+{
+ enum
+ {
+ kMenu_SelectSearch = 0,
+ kMenu_SearchDialogStyle,
+ kMenu_ShowSearchLabels,
+ kMenu_AutoSaveCheats,
+ kMenu_ShowActivationKeyMessage,
+ kMenu_LoadOldFormat,
+ kMenu_Debug,
+ kMenu_Return,
+
+ kMenu_Max
+ };
+
+ INT32 sel;
+ static INT32 submenuChoice = 0;
+ const char * menuItem[kMenu_Max + 1];
+ const char * menuSubItem[kMenu_Max + 1];
+ int total = 0;
+
+ sel = selection - 1;
+
+ /********** SUB MENU **********/
+ if(submenuChoice)
+ {
+ switch(sel)
+ {
+ case kMenu_SelectSearch:
+ submenuChoice = SelectSearch(submenuChoice);
+ break;
+
+ default:
+ submenuChoice = 0;
+ sel = -1;
+ break;
+ }
+
+ if(submenuChoice == -1)
+ submenuChoice = 0;
+
+ return sel + 1;
+ }
+
+ /********** MENU CONSTRUCTION **********/
+ menuItem[total] = "Select Search";
+ menuSubItem[total++] = NULL;
+
+ menuItem[total] = "Search Dialog Style";
+ switch(EXTRACT_FIELD(cheatOptions, SearchBox))
+ {
+ case kSearchBox_Minimum:
+ menuSubItem[total++] = "Minimum";
+ break;
+
+ case kSearchBox_Classic:
+ menuSubItem[total++] = "Classic";
+ break;
+
+ case kSearchBox_Advanced:
+ menuSubItem[total++] = "Advanced";
+ break;
+ }
+
+ menuItem[total] = "Show Search Labels";
+ menuSubItem[total++] = ui_getstring(TEST_FIELD(cheatOptions, DontPrintNewLabels) ? UI_off : UI_on);
+
+ menuItem[total] = "Auto Save Cheats";
+ menuSubItem[total++] = ui_getstring(TEST_FIELD(cheatOptions, AutoSaveEnabled) ? UI_on : UI_off);
+
+ menuItem[total] = "Show Activation Key Message";
+ menuSubItem[total++] = ui_getstring(TEST_FIELD(cheatOptions, ActivationKeyMessage) ? UI_on : UI_off);
+
+ menuItem[total] = "Load Old Format Code";
+ menuSubItem[total++] = ui_getstring(TEST_FIELD(cheatOptions, LoadOldFormat) ? UI_on : UI_off);
+
+ menuItem[total] = "Debug";
+ menuSubItem[total++] = ui_getstring(TEST_FIELD(cheatOptions, Debug) ? UI_on : UI_off);
+
+ menuItem[total] = ui_getstring(UI_returntoprior); // return
+ menuSubItem[total++] = NULL;
+
+ menuItem[total] = NULL; // terminate array
+ menuSubItem[total] = NULL;
+
+ /* ----- draw it ----- */
+ old_style_menu(menuItem, menuSubItem, NULL, sel, 0);
+
+ /********** KEY HANDLING **********/
+ if(UIPressedRepeatThrottle(IPT_UI_RIGHT, kHorizontalSlowKeyRepeatRate))
+ {
+ switch(sel)
+ {
+ case kMenu_SearchDialogStyle:
+ {
+ UINT8 length = (EXTRACT_FIELD(cheatOptions, SearchBox) + 1) & 3;
+
+ if(length > kSearchBox_Advanced)
+ length = kSearchBox_Minimum;
+
+ SET_FIELD(cheatOptions, SearchBox, length);
+ }
+ break;
+
+ case kMenu_ShowSearchLabels:
+ TOGGLE_MASK_FIELD(cheatOptions, DontPrintNewLabels);
+ break;
+
+ case kMenu_AutoSaveCheats:
+ TOGGLE_MASK_FIELD(cheatOptions, AutoSaveEnabled);
+ break;
+
+ case kMenu_ShowActivationKeyMessage:
+ TOGGLE_MASK_FIELD(cheatOptions, ActivationKeyMessage);
+ break;
+
+ case kMenu_LoadOldFormat:
+ TOGGLE_MASK_FIELD(cheatOptions, LoadOldFormat);
+ break;
+
+ case kMenu_Debug:
+ TOGGLE_MASK_FIELD(cheatOptions, Debug);
+ break;
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_LEFT, kHorizontalSlowKeyRepeatRate))
+ {
+ switch(sel)
+ {
+ case kMenu_SearchDialogStyle:
+ {
+ UINT8 length = (EXTRACT_FIELD(cheatOptions, SearchBox) - 1) & 3;
+
+ if(length > kSearchBox_Advanced)
+ length = kSearchBox_Advanced;
+
+ SET_FIELD(cheatOptions, SearchBox, length);
+ }
+ break;
+
+ case kMenu_ShowSearchLabels:
+ TOGGLE_MASK_FIELD(cheatOptions, DontPrintNewLabels);
+ break;
+
+ case kMenu_AutoSaveCheats:
+ TOGGLE_MASK_FIELD(cheatOptions, AutoSaveEnabled);
+ break;
+
+ case kMenu_ShowActivationKeyMessage:
+ TOGGLE_MASK_FIELD(cheatOptions, ActivationKeyMessage);
+ break;
+
+ case kMenu_LoadOldFormat:
+ TOGGLE_MASK_FIELD(cheatOptions, LoadOldFormat);
+ break;
+
+ case kMenu_Debug:
+ TOGGLE_MASK_FIELD(cheatOptions, Debug);
+ break;
+ }
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_DOWN, kVerticalKeyRepeatRate))
+ {
+ if(sel < (kMenu_Max - 1))
+ sel++;
+ else
+ sel = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_UP, kVerticalKeyRepeatRate))
+ {
+ if(sel > 0)
+ sel--;
+ else
+ sel = kMenu_Max - 1;
+ }
+
+ if(input_ui_pressed(IPT_UI_SELECT))
+ {
+ switch(sel)
+ {
+ case kMenu_Return:
+ submenuChoice = 0;
+ sel = -1;
+ break;
+
+ case kMenu_SelectSearch:
+ submenuChoice = 1;
+ break;
+ }
+ }
+
+ if(input_ui_pressed(IPT_UI_SAVE_CHEAT))
+ {
+ SaveCheat(NULL, 0, 2);
+
+ ui_popup_time(1, "command code saved");
+ }
+
+ if(input_ui_pressed(IPT_UI_RELOAD_CHEAT))
+ ReloadCheatDatabase();
+
+ if(input_ui_pressed(IPT_UI_CANCEL))
+ sel = -1;
+
+ return sel + 1;
+}
+
+/*------------------------------------------------------
+ SelectSearch - management for search selection menu
+------------------------------------------------------*/
+
+static int SelectSearch(int selection)
+{
+ INT32 sel;
+ const char ** menuItem;
+ char ** buf;
+ INT32 i;
+ INT32 total = 0;
+
+ sel = selection - 1;
+
+ RequestStrings(searchListLength + 2, searchListLength, 300, 0);
+
+ menuItem = menuStrings.mainList;
+ buf = menuStrings.mainStrings;
+
+ /********** MENU CONSTRUCTION **********/
+ for(i = 0; i < searchListLength; i++)
+ {
+ SearchInfo * info = &searchList[i];
+
+ if(i == currentSearchIdx)
+ {
+ if(info->name)
+ sprintf(buf[total], "[#%d: %s]", i, info->name);
+ else
+ sprintf(buf[total], "[#%d]", i);
+ }
+ else
+ {
+ if(info->name)
+ sprintf(buf[total], "#%d: %s", i, info->name);
+ else
+ sprintf(buf[total], "#%d", i);
+ }
+
+ menuItem[total] = buf[total];
+ total++;
+ }
+
+ menuItem[total++] = ui_getstring(UI_returntoprior); // return
+
+ menuItem[total] = NULL; // terminate array
+
+ /* ----- adjust current cursor position ----- */
+ if(sel < 0)
+ sel = 0;
+ if(sel > (total - 1))
+ sel = total - 1;
+
+ /* ----- draw it ----- */
+ old_style_menu(menuItem, NULL, NULL, sel, 0);
+
+ /********** KEY HANDLING **********/
+ if(UIPressedRepeatThrottle(IPT_UI_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel++;
+
+ if(sel >= total)
+ sel = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_UP, kVerticalKeyRepeatRate))
+ {
+ sel--;
+
+ if(sel < 0)
+ sel = total - 1;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_UP, kVerticalKeyRepeatRate))
+ {
+ sel -= fullMenuPageHeight;
+
+ if(sel < 0)
+ sel = 0;
+ }
+
+ if(UIPressedRepeatThrottle(IPT_UI_PAGE_DOWN, kVerticalKeyRepeatRate))
+ {
+ sel += fullMenuPageHeight;
+
+ if(sel >= total)
+ sel = total - 1;
+ }
+
+ if(input_ui_pressed(IPT_UI_ADD_CHEAT))
+ {
+ AddSearchBefore(sel);
+
+ BuildSearchRegions(&searchList[sel]);
+ AllocateSearchRegions(&searchList[sel]);
+ }
+
+ if(input_ui_pressed(IPT_UI_DELETE_CHEAT))
+ {
+ if(searchListLength > 1)
+ DeleteSearchAt(sel);
+ }
+
+ if(input_ui_pressed(IPT_UI_EDIT_CHEAT))
+ {
+ if(sel < total - 1)
+ currentSearchIdx = sel;
+ }
+
+ if(input_ui_pressed(IPT_UI_SELECT))
+ {
+ if(sel >= total - 1)
+ sel = -1;
+ else
+ currentSearchIdx = sel;
+ }
+
+ if(input_ui_pressed(IPT_UI_CANCEL))
+ sel = -1;
+
+ return sel + 1;
+}
+
+/*------------------
+ cheate_periodic
+------------------*/
+
+static TIMER_CALLBACK( cheat_periodic )
+{
+ int i;
+
+ if(input_ui_pressed(IPT_UI_TOGGLE_CHEAT))
+ {
+ if(ShiftKeyPressed())
+ {
+ /* ------ toggle watchpoint display if shift + toggle cheat ----- */
+ watchesDisabled ^= 1;
+
+ ui_popup_time(1, "%s %s", ui_getstring(UI_watchpoints), watchesDisabled ? ui_getstring (UI_off) : ui_getstring (UI_on));
+ }
+ else
+ {
+ /* ------ toggle cheat ----- */
+ cheatsDisabled ^= 1;
+
+ ui_popup_time(1, "%s %s", ui_getstring(UI_cheats), cheatsDisabled ? ui_getstring (UI_off) : ui_getstring (UI_on));
+
+ if(cheatsDisabled)
+ {
+ for(i = 0; i < cheatListLength; i++)
+ TempDeactivateCheat(&cheatList[i]);
+ }
+ }
+ }
+
+ if(cheatsDisabled)
+ return;
+
+ for(i = 0; i < cheatListLength; i++)
+ cheat_periodicEntry(&cheatList[i]);
+}
+
+/*--------------
+ PrintBinary
+--------------*/
+
+static UINT32 PrintBinary(char * buf, UINT32 data, UINT32 mask)
+{
+ UINT32 traverse = 0x80000000;
+ UINT32 written = 0;
+
+ while(traverse)
+ {
+ if(mask & traverse)
+ {
+ *buf++ = (data & traverse) ? '1' : '0';
+ written++;
+ }
+
+ traverse >>= 1;
+ }
+
+ *buf++ = 0;
+
+ return written;
+}
+
+/*-------------
+ PrintASCII
+-------------*/
+
+static UINT32 PrintASCII(char * buf, UINT32 data, UINT8 size)
+{
+ switch(size)
+ {
+ case kSearchSize_8Bit:
+ case kSearchSize_1Bit:
+ default:
+ buf[0] = (data >> 0) & 0xFF;
+ buf[1] = 0;
+
+ return 1;
+
+ case kSearchSize_16Bit:
+ buf[0] = (data >> 8) & 0xFF;
+ buf[1] = (data >> 0) & 0xFF;
+ buf[2] = 0;
+
+ return 2;
+
+ case kSearchSize_24Bit:
+ buf[0] = (data >> 16)& 0xFF;
+ buf[1] = (data >> 8) & 0xFF;
+ buf[2] = (data >> 0) & 0xFF;
+ buf[3] = 0;
+
+ return 3;
+
+ case kSearchSize_32Bit:
+ buf[0] = (data >> 24) & 0xFF;
+ buf[1] = (data >> 16) & 0xFF;
+ buf[2] = (data >> 8) & 0xFF;
+ buf[3] = (data >> 0) & 0xFF;
+ buf[4] = 0;
+
+ return 4;
+ }
+
+ buf[0] = 0;
+ return 0;
+}
+
+/*---------------------------------------------
+ cheat_display_watches - display watchpoint
+---------------------------------------------*/
+
+void cheat_display_watches(void)
+{
+ int i;
+
+ if(watchesDisabled)
+ return;
+
+ for(i = 0; i < watchListLength; i++)
+ {
+ int j;
+ WatchInfo * info = &watchList[i];
+ char buf[1024];
+ UINT32 address = info->address;
+ int xOffset = 0, yOffset = 0;
+ int numChars;
+ int lineElements = 0;
+
+ /* ----- if the length of the watchpoint is not 0, display it ----- */
+ if(info->numElements)
+ {
+ /* ----- label display ----- */
+ switch(info->labelType)
+ {
+ case kWatchLabel_Address:
+ numChars = sprintf(buf, "%.8X: ", info->address);
+
+ ui_draw_text(buf, xOffset * ui_get_char_width('0') + info->x, yOffset * ui_get_line_height() + info->y);
+ xOffset += numChars;
+ break;
+
+ case kWatchLabel_String:
+ numChars = sprintf(buf, "%s: ", info->label);
+
+ ui_draw_text(buf, xOffset * ui_get_char_width('0') + info->x, yOffset * ui_get_line_height() + info->y);
+ xOffset += numChars;
+ break;
+ }
+
+ /* ----- value display ----- */
+ for(j = 0; j < info->numElements; j++)
+ {
+ UINT32 data = 0;
+
+ switch(info->locationType)
+ {
+ case kLocation_Standard:
+ data = (DoCPURead(info->cpu, address, kSearchByteIncrementTable[info->elementBytes], CPUNeedsSwap(info->cpu)) + info->addValue) &
+ kSearchByteMaskTable[info->elementBytes];
+ break;
+
+ case kLocation_MemoryRegion:
+ {
+ int region = REGION_CPU1 + info->cpu;
+ UINT8 * buf = memory_region(region);
+
+ data = DoMemoryRead(buf, address, kSearchByteIncrementTable[info->elementBytes], RegionNeedsSwap(region) + info->addValue, GetRegionCPUInfo(region)) &
+ kSearchByteMaskTable[info->elementBytes];
+ }
+ break;
+
+ case kLocation_IndirectIndexed:
+ return; // under construction...
+
+ case kLocation_ProgramSpace:
+ {
+ UINT8 * buf;
+
+ memory_set_opbase(address);
+
+ buf = memory_get_op_ptr(info->cpu, address, 0);
+
+ buf -= address;
+
+ if(buf)
+ data = DoMemoryRead(buf, address, kSearchByteIncrementTable[info->elementBytes], CPUNeedsSwap(info->cpu) + info->addValue, GetCPUInfo(info->cpu)) &
+ kSearchByteMaskTable[info->elementBytes];
+ }
+ break;
+
+ default:
+ logerror("invalid location type : %x\n", info->locationType);
+ return;
+
+ }
+
+ data = DoShift(data, info->dataShift);
+ data ^= info->xor;
+
+ if( (lineElements >= info->elementsPerLine) && info->elementsPerLine)
+ {
+ lineElements = 0;
+
+ xOffset = 0;
+ yOffset++;
+ }
+
+ switch(info->displayType)
+ {
+ case kWatchDisplayType_Hex:
+ numChars = sprintf(buf, "%.*X", kSearchByteDigitsTable[info->elementBytes], data);
+
+ ui_draw_text(buf, xOffset * ui_get_char_width('0') + info->x, yOffset * ui_get_line_height() + info->y);
+ xOffset += numChars;
+ xOffset++;
+ break;
+
+ case kWatchDisplayType_Decimal:
+ numChars = sprintf(buf, "%.*d", kSearchByteDecDigitsTable[info->elementBytes], data);
+
+ ui_draw_text(buf, xOffset * ui_get_char_width('0') + info->x, yOffset * ui_get_line_height() + info->y);
+ xOffset += numChars;
+ xOffset++;
+ break;
+
+ case kWatchDisplayType_Binary:
+ numChars = PrintBinary(buf, data, kSearchByteMaskTable[info->elementBytes]);
+
+ ui_draw_text(buf, xOffset * ui_get_char_width('0') + info->x, yOffset * ui_get_line_height() + info->y);
+ xOffset += numChars;
+ xOffset++;
+ break;
+
+ case kWatchDisplayType_ASCII:
+ numChars = PrintASCII(buf, data, info->elementBytes);
+
+ ui_draw_text(buf, xOffset * ui_get_char_width('0') + info->x, yOffset * ui_get_line_height() + info->y);
+ xOffset += numChars;
+ break;
+ }
+
+ address += kSearchByteIncrementTable[info->elementBytes] + info->skip;
+ lineElements++;
+ }
+ }
+ }
+}
+
+/*------------------
+ ResizeCheatList
+------------------*/
+
+static void ResizeCheatList(UINT32 newLength)
+{
+ if(newLength != cheatListLength)
+ {
+ if(newLength < cheatListLength)
+ {
+ int i;
+
+ for(i = newLength; i < cheatListLength; i++)
+ DisposeCheat(&cheatList[i]);
+ }
+
+ cheatList = realloc(cheatList, newLength * sizeof(CheatEntry));
+
+ if(!cheatList && (newLength != 0))
+ {
+ logerror("ResizeCheatList: out of memory resizing cheat list\n");
+ ui_popup_time(2, "out of memory while loading cheat database");
+
+ cheatListLength = 0;
+
+ return;
+ }
+
+ if(newLength > cheatListLength)
+ {
+ int i;
+
+ memset(&cheatList[cheatListLength], 0, (newLength - cheatListLength) * sizeof(CheatEntry));
+
+ for(i = cheatListLength; i < newLength; i++)
+ cheatList[i].flags |= kCheatFlag_Dirty;
+ }
+
+ cheatListLength = newLength;
+ }
+}
+
+/*---------------------------
+ ResizeCheatListNoDispose
+---------------------------*/
+
+static void ResizeCheatListNoDispose(UINT32 newLength)
+{
+ if(newLength != cheatListLength)
+ {
+ cheatList = realloc(cheatList, newLength * sizeof(CheatEntry));
+
+ if(!cheatList && (newLength != 0))
+ {
+ logerror("ResizeCheatListNoDispose: out of memory resizing cheat list\n");
+ ui_popup_time(2, "out of memory while loading cheat database");
+
+ cheatListLength = 0;
+
+ return;
+ }
+
+ if(newLength > cheatListLength)
+ {
+ int i;
+
+ memset(&cheatList[cheatListLength], 0, (newLength - cheatListLength) * sizeof(CheatEntry));
+
+ for(i = cheatListLength; i < newLength; i++)
+ cheatList[i].flags |= kCheatFlag_Dirty;
+ }
+
+ cheatListLength = newLength;
+ }
+}
+
+/*---------------------------------------------------------------
+ AddCheatBefore - insert new cheat entry before selected code
+---------------------------------------------------------------*/
+
+static void AddCheatBefore(UINT32 idx)
+{
+ /* ----- memory reallocation ----- */
+ ResizeCheatList(cheatListLength + 1);
+
+ if(idx < (cheatListLength - 1))
+ memmove(&cheatList[idx + 1], &cheatList[idx], sizeof(CheatEntry) * (cheatListLength - 1 - idx));
+
+ if(idx >= cheatListLength)
+ idx = cheatListLength - 1;
+
+ /* ----- insert new entry ----- */
+ memset(&cheatList[idx], 0, sizeof(CheatEntry));
+
+ cheatList[idx].flags |= kCheatFlag_Dirty;
+
+ ResizeCheatActionList(&cheatList[idx], 1);
+}
+
+/*----------------
+ DeleteCheatAt
+----------------*/
+
+static void DeleteCheatAt(UINT32 idx)
+{
+ if(idx >= cheatListLength)
+ return;
+
+ DisposeCheat(&cheatList[idx]);
+
+ if(idx < (cheatListLength - 1))
+ {
+ memmove(&cheatList[idx], &cheatList[idx + 1], sizeof(CheatEntry) * (cheatListLength - 1 - idx));
+ }
+
+ ResizeCheatListNoDispose(cheatListLength - 1);
+}
+
+/*------------------------------------------------
+ DisposeCheat - free memory for selected entry
+------------------------------------------------*/
+
+static void DisposeCheat(CheatEntry * entry)
+{
+ if(entry)
+ {
+ int i;
+
+ free(entry->name);
+ free(entry->comment);
+
+ for(i = 0; i < entry->actionListLength; i++)
+ {
+ CheatAction * action = &entry->actionList[i];
+
+ DisposeAction(action);
+ }
+
+ free(entry->actionList);
+
+ memset(entry, 0, sizeof(CheatEntry));
+ }
+}
+
+/*------------------------------------
+ GetNewCheat - get new cheat entry
+------------------------------------*/
+
+static CheatEntry * GetNewCheat(void)
+{
+ /* ----- insert new cheat entry ----- */
+ AddCheatBefore(cheatListLength);
+
+ /* ----- return inserted entry ----- */
+ return &cheatList[cheatListLength - 1];
+}
+
+/*------------------------
+ ResizeCheatActionList
+------------------------*/
+
+static void ResizeCheatActionList(CheatEntry * entry, UINT32 newLength)
+{
+ if(newLength != entry->actionListLength)
+ {
+ if(newLength < entry->actionListLength)
+ {
+ int i;
+
+ for(i = newLength; i < entry->actionListLength; i++)
+ DisposeAction(&entry->actionList[i]);
+ }
+
+ entry->actionList = realloc(entry->actionList, newLength * sizeof(CheatAction));
+ if(!entry->actionList && (newLength != 0))
+ {
+ logerror("ResizeCheatActionList: out of memory resizing cheat action list\n");
+ ui_popup_time(2, "out of memory while loading cheat database");
+
+ entry->actionListLength = 0;
+
+ return;
+ }
+
+ if(newLength > entry->actionListLength)
+ {
+ memset(&entry->actionList[entry->actionListLength], 0, (newLength - entry->actionListLength) * sizeof(CheatAction));
+ }
+
+ entry->actionListLength = newLength;
+ }
+}
+
+/*---------------------------------
+ ResizeCheatActionListNoDispose
+---------------------------------*/
+
+static void ResizeCheatActionListNoDispose(CheatEntry * entry, UINT32 newLength)
+{
+ if(newLength != entry->actionListLength)
+ {
+ entry->actionList = realloc(entry->actionList, newLength * sizeof(CheatAction));
+ if(!entry->actionList && (newLength != 0))
+ {
+ logerror("ResizeCheatActionList: out of memory resizing cheat action list\n");
+ ui_popup_time(2, "out of memory while loading cheat database");
+
+ entry->actionListLength = 0;
+
+ return;
+ }
+
+ if(newLength > entry->actionListLength)
+ {
+ memset(&entry->actionList[entry->actionListLength], 0, (newLength - entry->actionListLength) * sizeof(CheatAction));
+ }
+
+ entry->actionListLength = newLength;
+ }
+}
+
+/*------------------
+ AddActionBefore
+------------------*/
+
+static void AddActionBefore(CheatEntry * entry, UINT32 idx)
+{
+ ResizeCheatActionList(entry, entry->actionListLength + 1);
+
+ if(idx < (entry->actionListLength - 1))
+ memmove(&entry->actionList[idx + 1], &entry->actionList[idx], sizeof(CheatAction) * (entry->actionListLength - 1 - idx));
+
+ if(idx >= entry->actionListLength)
+ idx = entry->actionListLength - 1;
+
+ memset(&entry->actionList[idx], 0, sizeof(CheatAction));
+}
+
+/*-----------------
+ DeleteActionAt
+-----------------*/
+
+static void DeleteActionAt(CheatEntry * entry, UINT32 idx)
+{
+ if(idx >= entry->actionListLength)
+ return;
+
+ DisposeAction(&entry->actionList[idx]);
+
+ if(idx < (entry->actionListLength - 1))
+ memmove(&entry->actionList[idx], &entry->actionList[idx + 1], sizeof(CheatAction) * (entry->actionListLength - 1 - idx));
+
+ ResizeCheatActionListNoDispose(entry, entry->actionListLength - 1);
+}
+
+/*----------------
+ DisposeAction
+----------------*/
+
+static void DisposeAction(CheatAction * action)
+{
+ if(action)
+ {
+ free(action->optionalName);
+
+ memset(action, 0, sizeof(CheatAction));
+ }
+}
+
+/*----------------------------------------------------
+ InitWatch - initialize y-position for watchpoints
+----------------------------------------------------*/
+
+static void InitWatch(WatchInfo * info, UINT32 idx)
+{
+ if(idx > 0)
+ /* ----- set 2nd or later y-position ----- */
+ info->y = watchList[idx - 1].y + ui_get_line_height();
+ else
+ /* ----- set 1st y-position (always Y=0) ----- */
+ info->y = 0;
+}
+
+/*------------------
+ ResizeWatchList
+------------------*/
+
+static void ResizeWatchList(UINT32 newLength)
+{
+ if(newLength != watchListLength)
+ {
+ if(newLength < watchListLength)
+ {
+ int i;
+
+ for(i = newLength; i < watchListLength; i++)
+ DisposeWatch(&watchList[i]);
+ }
+
+ watchList = realloc(watchList, newLength * sizeof(WatchInfo));
+ if(!watchList && (newLength != 0))
+ {
+ logerror("ResizeWatchList: out of memory resizing watch list\n");
+ ui_popup_time(2, "out of memory while adding watch");
+
+ watchListLength = 0;
+
+ return;
+ }
+
+ if(newLength > watchListLength)
+ {
+ int i;
+
+ memset(&watchList[watchListLength], 0, (newLength - watchListLength) * sizeof(WatchInfo));
+
+ for(i = watchListLength; i < newLength; i++)
+ InitWatch(&watchList[i], i);
+ }
+
+ watchListLength = newLength;
+ }
+}
+
+/*---------------------------
+ ResizeWatchListNoDispose
+---------------------------*/
+
+static void ResizeWatchListNoDispose(UINT32 newLength)
+{
+ if(newLength != watchListLength)
+ {
+ watchList = realloc(watchList, newLength * sizeof(WatchInfo));
+ if(!watchList && (newLength != 0))
+ {
+ logerror("ResizeWatchList: out of memory resizing watch list\n");
+ ui_popup_time(2, "out of memory while adding watch");
+
+ watchListLength = 0;
+
+ return;
+ }
+
+ if(newLength > watchListLength)
+ {
+ int i;
+
+ memset(&watchList[watchListLength], 0, (newLength - watchListLength) * sizeof(WatchInfo));
+
+ for(i = watchListLength; i < newLength; i++)
+ InitWatch(&watchList[i], i);
+ }
+
+ watchListLength = newLength;
+ }
+}
+
+/*-----------------
+ AddWatchBefore
+-----------------*/
+
+static void AddWatchBefore(UINT32 idx)
+{
+ ResizeWatchList(watchListLength + 1);
+
+ if(idx < (watchListLength - 1))
+ memmove(&watchList[idx + 1], &watchList[idx], sizeof(WatchInfo) * (watchListLength - 1 - idx));
+
+ if(idx >= watchListLength)
+ idx = watchListLength - 1;
+
+ memset(&watchList[idx], 0, sizeof(WatchInfo));
+
+ InitWatch(&watchList[idx], idx);
+}
+
+/*----------------
+ DeleteWatchAt
+----------------*/
+
+static void DeleteWatchAt(UINT32 idx)
+{
+ if(idx >= watchListLength)
+ return;
+
+ DisposeWatch(&watchList[idx]);
+
+ if(idx < (watchListLength - 1))
+ memmove(&watchList[idx], &watchList[idx + 1], sizeof(WatchInfo) * (watchListLength - 1 - idx));
+
+ ResizeWatchListNoDispose(watchListLength - 1);
+}
+
+/*---------------
+ DisposeWatch
+---------------*/
+
+static void DisposeWatch(WatchInfo * watch)
+{
+ if(watch)
+ memset(watch, 0, sizeof(WatchInfo));
+}
+
+/*----------------------------------------------------------
+ GetUnusedWatch - search unused watchpoint and return it
+----------------------------------------------------------*/
+
+static WatchInfo * GetUnusedWatch(void)
+{
+ int i;
+ WatchInfo * info;
+ WatchInfo * theWatch = NULL;
+
+ /* ----- search unused watchpoint ----- */
+ for(i = 0; i < watchListLength; i++)
+ {
+ info = &watchList[i];
+
+ if(info->numElements == 0)
+ {
+ theWatch = info;
+ break;
+ }
+ }
+
+ /* ----- if unused watchpoint is not found, insert new watchpoint as unused ----- */
+ if(!theWatch)
+ {
+ AddWatchBefore(watchListLength);
+
+ theWatch = &watchList[watchListLength - 1];
+ }
+
+ /* ----- return unused watchpoint ----- */
+ return theWatch;
+}
+
+/*----------------------------------------------------------------------------
+ AddCheatFromWatch - add new cheat code from watchpoint list to cheat list
+----------------------------------------------------------------------------*/
+
+static void AddCheatFromWatch(WatchInfo * watch)
+{
+ if(watch)
+ {
+ CheatEntry * entry = GetNewCheat();
+ CheatAction * action = &entry->actionList[0];
+ char tempString[1024];
+ int tempStringLength;
+ UINT32 data = DoCPURead(watch->cpu, watch->address, kSearchByteIncrementTable[watch->elementBytes], 0);
+
+ tempStringLength = sprintf(tempString, "%.8X (%d) = %.*X", watch->address, watch->cpu, kSearchByteDigitsTable[watch->elementBytes], data);
+
+ entry->name = realloc(entry->name, tempStringLength + 1);
+ memcpy(entry->name, tempString, tempStringLength + 1);
+
+ SET_FIELD(action->type, LocationParameter, watch->cpu);
+ SET_FIELD(action->type, BytesUsed, kSearchByteIncrementTable[watch->elementBytes] - 1);
+ action->address = watch->address;
+ action->data = data;
+ action->extendData = 0xFFFFFFFF;
+ action->originalDataField = data;
+
+ UpdateCheatInfo(entry, 0);
+ }
+}
+
+/*-------------------------------------------------------------------------------------
+ SetupCheatFromWatchAsWatch - add new watch code from watchpoint list to cheat list
+-------------------------------------------------------------------------------------*/
+
+static void SetupCheatFromWatchAsWatch(CheatEntry * entry, WatchInfo * watch)
+{
+ if(watch && entry && watch->numElements)
+ {
+ CheatAction * action;
+ char tempString[1024];
+ size_t tempStringLength;
+
+ DisposeCheat(entry);
+ ResizeCheatActionList(entry, 1);
+
+ action = &entry->actionList[0];
+
+ tempStringLength = sprintf(tempString, "Watch %.8X (%d)", watch->address, watch->cpu);
+
+ entry->name = realloc(entry->name, tempStringLength + 1);
+ memcpy(entry->name, tempString, tempStringLength + 1);
+
+ action->type = 0;
+ SET_FIELD(action->type, LocationParameter, watch->cpu);
+ SET_FIELD(action->type, Type, kType_Watch);
+ SET_FIELD(action->type, BytesUsed, kSearchByteIncrementTable[watch->elementBytes] - 1);
+ SET_FIELD(action->type, TypeParameter, watch->displayType | ((watch->labelType == kWatchLabel_String) ? 0x04 : 0));
+
+ action->address = watch->address;
+ action->data = ((watch->numElements - 1) & 0xFF) |
+ ((watch->skip & 0xFF) << 8) |
+ ((watch->elementsPerLine & 0xFF) << 16) |
+ ((watch->addValue & 0xFF) << 24);
+ action->originalDataField = action->data;
+ action->extendData = 0xFFFFFFFF;
+
+ tempStringLength = strlen(watch->label);
+ entry->comment = realloc(entry->comment, tempStringLength + 1);
+ memcpy(entry->comment, watch->label, tempStringLength + 1);
+
+ UpdateCheatInfo(entry, 0);
+ }
+}
+
+/*-------------------
+ ResizeSearchList
+-------------------*/
+
+static void ResizeSearchList(UINT32 newLength)
+{
+ if(newLength != searchListLength)
+ {
+ if(newLength < searchListLength)
+ {
+ int i;
+
+ for(i = newLength; i < searchListLength; i++)
+ DisposeSearch(i);
+ }
+
+ searchList = realloc(searchList, newLength * sizeof(SearchInfo));
+ if(!searchList && (newLength != 0))
+ {
+ logerror("ResizeSearchList: out of memory resizing search list\n");
+ ui_popup_time(2, "out of memory while adding search");
+
+ searchListLength = 0;
+
+ return;
+ }
+
+ if(newLength > searchListLength)
+ {
+ int i;
+
+ memset(&searchList[searchListLength], 0, (newLength - searchListLength) * sizeof(SearchInfo));
+
+ for(i = searchListLength; i < newLength; i++)
+ {
+ InitSearch(&searchList[i]);
+ }
+ }
+
+ searchListLength = newLength;
+ }
+}
+
+/*----------------------------
+ ResizeSearchListNoDispose
+----------------------------*/
+
+static void ResizeSearchListNoDispose(UINT32 newLength)
+{
+ if(newLength != searchListLength)
+ {
+ searchList = realloc(searchList, newLength * sizeof(SearchInfo));
+ if(!searchList && (newLength != 0))
+ {
+ logerror("ResizeSearchList: out of memory resizing search list\n");
+ ui_popup_time(2, "out of memory while adding search");
+
+ searchListLength = 0;
+
+ return;
+ }
+
+ if(newLength > searchListLength)
+ {
+ memset(&searchList[searchListLength], 0, (newLength - searchListLength) * sizeof(SearchInfo));
+ }
+
+ searchListLength = newLength;
+ }
+}
+
+/*------------------
+ AddSearchBefore
+------------------*/
+
+static void AddSearchBefore(UINT32 idx)
+{
+ ResizeSearchListNoDispose(searchListLength + 1);
+
+ if(idx < (searchListLength - 1))
+ memmove(&searchList[idx + 1], &searchList[idx], sizeof(SearchInfo) * (searchListLength - 1 - idx));
+
+ if(idx >= searchListLength)
+ idx = searchListLength - 1;
+
+ memset(&searchList[idx], 0, sizeof(SearchInfo));
+ InitSearch(&searchList[idx]);
+}
+
+/*-----------------
+ DeleteSearchAt
+-----------------*/
+
+static void DeleteSearchAt(UINT32 idx)
+{
+ if(idx >= searchListLength)
+ return;
+
+ DisposeSearch(idx);
+
+ if(idx < (searchListLength - 1))
+ {
+ memmove(&searchList[idx], &searchList[idx + 1], sizeof(SearchInfo) * (searchListLength - 1 - idx));
+ }
+
+ ResizeSearchListNoDispose(searchListLength - 1);
+}
+
+/*--------------------------------------
+ InitSearch - initialize search info
+--------------------------------------*/
+
+static void InitSearch(SearchInfo * info)
+{
+ if(info)
+ {
+ info->searchSpeed = kSearchSpeed_Medium;
+ }
+}
+
+/*-----------------------
+ DisposeSearchRegions
+-----------------------*/
+
+static void DisposeSearchRegions(SearchInfo * info)
+{
+ if(info->regionList)
+ {
+ int i;
+
+ for(i = 0; i < info->regionListLength; i++)
+ {
+ SearchRegion * region = &info->regionList[i];
+
+ free(region->first);
+ free(region->last);
+ free(region->status);
+ free(region->backupLast);
+ free(region->backupStatus);
+ }
+
+ free(info->regionList);
+
+ info->regionList = NULL;
+ }
+
+ info->regionListLength = 0;
+}
+
+/*------------------
+ DisposeSearch
+ ----------------*/
+
+static void DisposeSearch(UINT32 idx)
+{
+ SearchInfo * info;
+
+ if(idx >= searchListLength)
+ return;
+
+ info = &searchList[idx];
+
+ DisposeSearchRegions(info);
+
+ free(info->name);
+ info->name = NULL;
+}
+
+/*----------------------------------------
+ GetCurrentSearch - return search info
+----------------------------------------*/
+
+static SearchInfo * GetCurrentSearch(void)
+{
+ if(currentSearchIdx >= searchListLength)
+ currentSearchIdx = searchListLength - 1;
+ if(currentSearchIdx < 0)
+ currentSearchIdx = 0;
+
+ return &searchList[currentSearchIdx];
+}
+
+/*-------------------------------------------------------
+ FillBufferFromRegion - set a data into search region
+-------------------------------------------------------*/
+
+static void FillBufferFromRegion(SearchRegion * region, UINT8 * buf)
+{
+ UINT32 offset;
+
+ /* ### optimize if needed ### */
+ for(offset = 0; offset < region->length; offset++)
+ buf[offset] = ReadRegionData(region, offset, 1, 0);
+}
+
+/*-------------------------------------------------------
+ ReadRegionData - read a data from region when search
+-------------------------------------------------------*/
+
+static UINT32 ReadRegionData(SearchRegion * region, UINT32 offset, UINT8 size, UINT8 swap)
+{
+ UINT32 address = region->address + offset;
+
+ switch(region->targetType)
+ {
+ case kRegionType_CPU:
+ return DoCPURead(region->targetIdx, address, size, CPUNeedsSwap(region->targetIdx) ^ swap);
+
+ case kRegionType_Memory:
+ if(region->cachedPointer)
+ return DoMemoryRead(region->cachedPointer, address, size, swap, &rawCPUInfo);
+ else
+ return 0;
+ }
+
+ return 0;
+}
+/*-----------------------------------------------
+ BackupSearch - back up current search region
+-----------------------------------------------*/
+
+static void BackupSearch(SearchInfo * info)
+{
+ int i;
+
+ for(i = 0; i < info->regionListLength; i++)
+ BackupRegion(&info->regionList[i]);
+
+ info->oldNumResults = info->numResults;
+ info->backupValid = 1;
+}
+
+/*-------------------------------------------------------
+ RestoreSearchBackup - restore previous search region
+-------------------------------------------------------*/
+
+static void RestoreSearchBackup(SearchInfo * info)
+{
+ int i;
+
+ if(info && info->backupValid)
+ {
+ for(i = 0; i < info->regionListLength; i++)
+ RestoreRegionBackup(&info->regionList[i]);
+
+ info->numResults = info->oldNumResults;
+ info->backupValid = 0;
+
+ ui_popup_time(1, "values restored");
+ }
+ else
+ ui_popup_time(1, "there are no old values");
+}
+
+/*------------------------------------------------
+ BackupRegion - back up current search results
+------------------------------------------------*/
+
+static void BackupRegion(SearchRegion * region)
+{
+ if(region->flags & kRegionFlag_Enabled)
+ {
+ memcpy(region->backupLast, region->last, region->length);
+ memcpy(region->backupStatus, region->status, region->length);
+ region->oldNumResults = region->numResults;
+ }
+}
+
+/*--------------------------------------------------------
+ RestoreSearchBackup - restore previous search results
+--------------------------------------------------------*/
+
+static void RestoreRegionBackup(SearchRegion * region)
+{
+ if(region->flags & kRegionFlag_Enabled)
+ {
+ memcpy(region->last, region->backupLast, region->length);
+ memcpy(region->status, region->backupStatus, region->length);
+ region->numResults = region->oldNumResults;
+ }
+}
+
+/*-----------------------------------------------------------
+ DefaultEnableRegion - get default regions you can search
+-----------------------------------------------------------*/
+
+static UINT8 DefaultEnableRegion(SearchRegion * region, SearchInfo * info)
+{
+ write8_handler handler = region->writeHandler->write.handler8;
+ FPTR handlerAddress = (FPTR)handler;
+
+ switch(info->searchSpeed)
+ {
+ case kSearchSpeed_Fast:
+
+#if HAS_SH2
+ if(Machine->drv->cpu[0].type == CPU_SH2)
+ {
+ if( (info->targetType == kRegionType_CPU) && (info->targetIdx == 0) && (region->address == 0x06000000))
+ return 1;
+
+ return 0;
+ }
+#endif
+
+ if( (handler == MWA8_RAM) && (!region->writeHandler->base))
+ return 1;
+
+#ifndef MESS
+
+ {
+ /* ----- for neogeo, search bank one ----- */
+ if( (!strcmp(Machine->gamedrv->parent, "neogeo")) && (info->targetType == kRegionType_CPU) &&
+ (info->targetIdx == 0) && (handler == MWA8_BANK1))
+ return 1;
+ }
+
+#endif
+
+#if HAS_TMS34010
+
+ /* ----- for exterminator, search bank one ----- */
+ if( (Machine->drv->cpu[1].type == CPU_TMS34010) && (info->targetType == kRegionType_CPU) &&
+ (info->targetIdx == 1) && (handler == MWA8_BANK1))
+ return 1;
+
+ /* ----- for smashtv, search bank two ----- */
+ if( (Machine->drv->cpu[0].type == CPU_TMS34010) && (info->targetType == kRegionType_CPU) &&
+ (info->targetIdx == 0) && (handler == MWA8_BANK2))
+ return 1;
+
+#endif
+ return 0;
+
+ case kSearchSpeed_Medium:
+ if( (handlerAddress >= ((FPTR)MWA8_BANK1)) && (handlerAddress <= ((FPTR)MWA8_BANK24)))
+ return 1;
+
+ if(handler == MWA8_RAM)
+ return 1;
+
+ return 0;
+
+ case kSearchSpeed_Slow:
+ if( (handler == MWA8_NOP) || (handler == MWA8_ROM))
+ return 0;
+
+ if( (handlerAddress > STATIC_COUNT) && (!region->writeHandler->base))
+ return 0;
+
+ return 1;
+
+ case kSearchSpeed_VerySlow:
+ if( (handler == MWA8_NOP) || (handler == MWA8_ROM))
+ return 0;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/*-----------------------------
+ SetSearchRegionDefaultName
+-----------------------------*/
+
+static void SetSearchRegionDefaultName(SearchRegion * region)
+{
+ switch(region->targetType)
+ {
+ case kRegionType_CPU:
+ {
+ char desc[16];
+
+ if(region->writeHandler)
+ {
+ genf * handler = region->writeHandler->write.handler;
+ FPTR handlerAddress = (FPTR)handler;
+
+ if( (handlerAddress >= ((FPTR)MWA8_BANK1)) && (handlerAddress <= ((FPTR)MWA8_BANK24)))
+ sprintf(desc, "BANK%.2d", (int)(handlerAddress - (FPTR)MWA8_BANK1) + 1);
+ else
+ {
+ switch(handlerAddress)
+ {
+ case (FPTR)MWA8_NOP: strcpy(desc, "NOP "); break;
+ case (FPTR)MWA8_RAM: strcpy(desc, "RAM "); break;
+ case (FPTR)MWA8_ROM: strcpy(desc, "ROM "); break;
+ default: strcpy(desc, "CUSTOM"); break;
+ }
+ }
+ }
+ else
+ sprintf(desc, "CPU%.2d ", region->targetIdx);
+
+ sprintf(region->name, "%.*X-%.*X %s",
+ cpuInfoList[region->targetIdx].addressCharsNeeded,
+ region->address,
+ cpuInfoList[region->targetIdx].addressCharsNeeded,
+ region->address + region->length - 1,
+ desc);
+ }
+ break;
+
+ case kRegionType_Memory:
+ sprintf(region->name, "%.8X-%.8X MEMORY", region->address, region->address + region->length - 1);
+ break;
+
+ default:
+ sprintf(region->name, "UNKNOWN");
+ break;
+ }
+}
+
+/*-----------------------------------------------------------------------------------
+ AllocateSearchRegions - free memory for search region then realloc if searchable
+-----------------------------------------------------------------------------------*/
+
+static void AllocateSearchRegions(SearchInfo * info)
+{
+ int i;
+
+ info->backupValid = 0;
+ info->numResults = 0;
+
+ for(i = 0; i < info->regionListLength; i++)
+ {
+ SearchRegion * region;
+
+ region = &info->regionList[i];
+
+ region->numResults = 0;
+
+ free(region->first);
+ free(region->last);
+ free(region->status);
+ free(region->backupLast);
+ free(region->backupStatus);
+
+ if(region->flags & kRegionFlag_Enabled)
+ {
+ region->first = malloc(region->length);
+ region->last = malloc(region->length);
+ region->status = malloc(region->length);
+ region->backupLast = malloc(region->length);
+ region->backupStatus = malloc(region->length);
+
+ if(!region->first || !region->last || !region->status || !region->backupLast || !region->backupStatus)
+ {
+ free(region->first);
+ free(region->last);
+ free(region->status);
+ free(region->backupLast);
+ free(region->backupStatus);
+
+ region->first = NULL;
+ region->last = NULL;
+ region->status = NULL;
+ region->backupLast = NULL;
+ region->backupStatus = NULL;
+
+ region->flags &= ~kRegionFlag_Enabled;
+ }
+ }
+ else
+ {
+ region->first = NULL;
+ region->last = NULL;
+ region->status = NULL;
+ region->backupLast = NULL;
+ region->backupStatus = NULL;
+ }
+ }
+}
+
+/*---------------------
+ BuildSearchRegions
+---------------------*/
+
+static void BuildSearchRegions(SearchInfo * info)
+{
+ info->comparison = kSearchComparison_EqualTo;
+
+ DisposeSearchRegions(info);
+
+ switch(info->targetType)
+ {
+ case kRegionType_CPU:
+ {
+ if(info->searchSpeed == kSearchSpeed_AllMemory)
+ {
+ UINT32 length = cpuInfoList[info->targetIdx].addressMask + 1;
+ SearchRegion * region;
+
+ info->regionList = calloc(sizeof(SearchRegion), 1);
+ info->regionListLength = 1;
+ region = info->regionList;
+
+ region->address = 0;
+ region->length = length;
+
+ region->targetIdx = info->targetIdx;
+ region->targetType = info->targetType;
+ region->writeHandler = NULL;
+
+ region->first = NULL;
+ region->last = NULL;
+ region->status = NULL;
+
+ region->backupLast = NULL;
+ region->backupStatus = NULL;
+
+ region->flags = kRegionFlag_Enabled;
+
+ SetSearchRegionDefaultName(region);
+ }
+ else
+ {
+ if(info->targetIdx < cpu_gettotalcpu())
+ {
+ const address_map * map = NULL;
+ SearchRegion * traverse;
+ int count = 0;
+
+ map = memory_get_map(info->targetIdx, ADDRESS_SPACE_PROGRAM);
+
+ while(!IS_AMENTRY_END(map))
+ {
+ if(!IS_AMENTRY_EXTENDED(map) && map->write.handler)
+ count++;
+
+ map++;
+ }
+
+ info->regionList = calloc(sizeof(SearchRegion), count);
+ info->regionListLength = count;
+ traverse = info->regionList;
+
+ map = memory_get_map(info->targetIdx, ADDRESS_SPACE_PROGRAM);
+
+ while(!IS_AMENTRY_END(map))
+ {
+ if(!IS_AMENTRY_EXTENDED(map) && map->write.handler)
+ {
+ UINT32 length = (map->end - map->start) + 1;
+
+ traverse->address = map->start;
+ traverse->length = length;
+
+ traverse->targetIdx = info->targetIdx;
+ traverse->targetType = info->targetType;
+ traverse->writeHandler = map;
+
+ traverse->first = NULL;
+ traverse->last = NULL;
+ traverse->status = NULL;
+
+ traverse->backupLast = NULL;
+ traverse->backupStatus = NULL;
+
+ traverse->flags = DefaultEnableRegion(traverse, info) ? kRegionFlag_Enabled : 0;
+
+ SetSearchRegionDefaultName(traverse);
+
+ traverse++;
+ }
+
+ map++;
+ }
+ }
+ }
+ }
+ break;
+
+ case kRegionType_Memory:
+ break;
+ }
+}
+
+/*---------------------------------------------------------------------
+ ConvertOldCode - convert old format code to new when load database
+---------------------------------------------------------------------*/
+
+static int ConvertOldCode(int code, int cpu, int * data, int * extendData)
+{
+ enum
+ {
+ kCustomField_None = 0,
+ kCustomField_DontApplyCPUField = 1 << 0,
+ kCustomField_SetBit = 1 << 1,
+ kCustomField_ClearBit = 1 << 2,
+ kCustomField_SubtractOne = 1 << 3,
+
+ kCustomField_BitMask = kCustomField_SetBit |
+ kCustomField_ClearBit,
+ kCustomField_End = 0xFF
+ };
+
+ struct ConversionTable
+ {
+ int oldCode;
+ UINT32 newCode;
+ UINT8 customField;
+ };
+
+ static struct ConversionTable kConversionTable[] =
+ {
+ { 0, 0x00000000, kCustomField_None },
+ { 1, 0x00000001, kCustomField_None },
+ { 2, 0x00000020, kCustomField_None },
+ { 3, 0x00000040, kCustomField_None },
+ { 4, 0x000000A0, kCustomField_None },
+ { 5, 0x00000022, kCustomField_None },
+ { 6, 0x00000042, kCustomField_None },
+ { 7, 0x000000A2, kCustomField_None },
+ { 8, 0x00000024, kCustomField_None },
+ { 9, 0x00000044, kCustomField_None },
+ { 10, 0x00000064, kCustomField_None },
+ { 11, 0x00000084, kCustomField_None },
+ { 15, 0x00000023, kCustomField_None },
+ { 16, 0x00000043, kCustomField_None },
+ { 17, 0x000000A3, kCustomField_None },
+ { 20, 0x00000000, kCustomField_SetBit },
+ { 21, 0x00000001, kCustomField_SetBit },
+ { 22, 0x00000020, kCustomField_SetBit },
+ { 23, 0x00000040, kCustomField_SetBit },
+ { 24, 0x000000A0, kCustomField_SetBit },
+ { 40, 0x00000000, kCustomField_ClearBit },
+ { 41, 0x00000001, kCustomField_ClearBit },
+ { 42, 0x00000020, kCustomField_ClearBit },
+ { 43, 0x00000040, kCustomField_ClearBit },
+ { 44, 0x000000A0, kCustomField_ClearBit },
+ { 60, 0x00000103, kCustomField_None },
+ { 61, 0x00000303, kCustomField_None },
+ { 62, 0x00000503, kCustomField_SubtractOne },
+ { 63, 0x00000903, kCustomField_None },
+ { 64, 0x00000B03, kCustomField_None },
+ { 65, 0x00000D03, kCustomField_SubtractOne },
+ { 70, 0x00000101, kCustomField_None },
+ { 71, 0x00000301, kCustomField_None },
+ { 72, 0x00000501, kCustomField_SubtractOne },
+ { 73, 0x00000901, kCustomField_None },
+ { 74, 0x00000B01, kCustomField_None },
+ { 75, 0x00000D01, kCustomField_SubtractOne },
+ { 80, 0x00000102, kCustomField_None },
+ { 81, 0x00000302, kCustomField_None },
+ { 82, 0x00000502, kCustomField_SubtractOne },
+ { 83, 0x00000902, kCustomField_None },
+ { 84, 0x00000B02, kCustomField_None },
+ { 85, 0x00000D02, kCustomField_SubtractOne },
+ { 90, 0x00000100, kCustomField_None },
+ { 91, 0x00000300, kCustomField_None },
+ { 92, 0x00000500, kCustomField_SubtractOne },
+ { 93, 0x00000900, kCustomField_None },
+ { 94, 0x00000B00, kCustomField_None },
+ { 95, 0x00000D00, kCustomField_SubtractOne },
+ { 100, 0x20800000, kCustomField_None },
+ { 101, 0x20000001, kCustomField_None },
+ { 102, 0x20800000, kCustomField_None },
+ { 103, 0x20000001, kCustomField_None },
+ { 110, 0x40800000, kCustomField_None },
+ { 111, 0x40000001, kCustomField_None },
+ { 112, 0x40800000, kCustomField_None },
+ { 113, 0x40000001, kCustomField_None },
+ { 120, 0x63000001, kCustomField_None },
+ { 121, 0x63000001, kCustomField_DontApplyCPUField | kCustomField_SetBit },
+ { 122, 0x63000001, kCustomField_DontApplyCPUField | kCustomField_ClearBit },
+ { 998, 0x00000006, kCustomField_None },
+ { 999, 0x60000000, kCustomField_DontApplyCPUField },
+ { -1, 0x00000000, kCustomField_End }
+ };
+
+ struct ConversionTable * traverse = kConversionTable;
+ UINT32 newCode;
+ UINT8 linkCheat = 0;
+
+ /* ----- convert link cheats ----- */
+ if((code >= 500) && (code <= 699))
+ {
+ linkCheat = 1;
+ code -= 500;
+ }
+
+ /* ----- look up code ----- */
+ while(traverse->oldCode >= 0)
+ {
+ if(code == traverse->oldCode)
+ goto foundCode;
+ traverse++;
+ }
+
+ logerror("ConvertOldCode: %d not found\n", code);
+
+ /* ----- not found ----- */
+ *extendData = 0;
+ return 0;
+
+ /* ----- found ----- */
+ foundCode:
+
+ newCode = traverse->newCode;
+
+ /* ----- add in the CPU field ----- */
+ if(!(traverse->customField & kCustomField_DontApplyCPUField))
+ newCode = (newCode & ~0x1F000000) | ((cpu << 24) & 0x1F000000);
+
+ /* ----- hack-ish, subtract one from data field for x5 user select ----- */
+ if(traverse->customField & kCustomField_SubtractOne)
+ (*data)--; // yaay for C operator precedence
+
+ /* ----- set up the extend data ----- */
+ if(traverse->customField & kCustomField_BitMask)
+ *extendData = *data;
+ else
+ *extendData = 0xFFFFFFFF;
+
+ if(traverse->customField & kCustomField_ClearBit)
+ *data = 0;
+
+ if(linkCheat)
+ SET_MASK_FIELD(newCode, LinkEnable);
+
+ return newCode;
+}
+
+/*--------------------------------------------------------------------------------
+ HandleLocalCommandCheat - get special code which is not added into cheat list
+--------------------------------------------------------------------------------*/
+
+static void HandleLocalCommandCheat(UINT32 type, UINT32 address, UINT32 data, UINT32 extendData, char * name, char * description)
+{
+ switch(EXTRACT_FIELD(type, LocationType))
+ {
+ case kLocation_Custom:
+ switch(EXTRACT_FIELD(type, LocationParameter))
+ {
+ /* ----- activation key ----- */
+ case kCustomLocation_AssignActivationKey:
+ {
+ if(address < cheatListLength)
+ {
+ CheatEntry * entry = &cheatList[address];
+
+ if(!TEST_FIELD(type, OneShot))
+ {
+ /* ----- 1st activation key ----- */
+ entry->activationKey1 = data;
+ entry->flags |= kCheatFlag_HasActivationKey1;
+ }
+ else
+ {
+ /* ----- 2nd activation key ----- */
+ entry->activationKey2 = data;
+ entry->flags |= kCheatFlag_HasActivationKey2;
+ }
+ }
+ }
+ break;
+
+ /* ----- pre-enable ----- */
+ case kCustomLocation_Enable:
+ {
+ if(address < cheatListLength)
+ {
+ CheatEntry * entry = &cheatList[address];
+
+ ActivateCheat(entry);
+ }
+ }
+ break;
+
+ /* ----- over-clock ----- */
+ case kCustomLocation_Overclock:
+ {
+ if(address < cpu_gettotalcpu())
+ {
+ double overclock = data;
+
+ overclock /= 65536.0;
+
+ cpunum_set_clockscale(address, overclock);
+ }
+ }
+ break;
+
+ /* ----- refresh rate ----- */
+ case kCustomLocation_RefreshRate:
+ {
+ screen_state *state = &Machine->screen[0];
+ double refresh = data;
+
+ refresh /= 65536.0;
+
+ video_screen_configure(0, state->width, state->height, &state->visarea, HZ_TO_ATTOSECONDS(refresh));
+ }
+ break;
+ }
+ break;
+ }
+}
+
+/*------------------------------------------------
+ LoadCheatFile - load cheat code from database
+------------------------------------------------*/
+
+static void LoadCheatFile(char * fileName)
+{
+ mame_file * theFile;
+ file_error filerr;
+ char formatString[256];
+ char oldFormatString[256];
+ char buf[2048];
+ int recordNames = 0;
+
+ /* ----- open the database ----- */
+ filerr = mame_fopen(SEARCHPATH_CHEAT, fileName, OPEN_FLAG_READ, &theFile);
+
+ if(filerr != FILERR_NONE)
+ return;
+
+ foundCheatDatabase = 1;
+
+ /* ----- make the format strings ----- */
+#ifdef MESS
+ sprintf(formatString, ":%s:%s", Machine->gamedrv->name, "%x:%x:%x:%x:%x:%[^:\n\r]:%[^:\n\r]");
+ sprintf(oldFormatString, "%s:%s", Machine->gamedrv->name, "%x:%d:%x:%x:%d:%[^:\n\r]:%[^:\n\r]");
+#else
+ sprintf(formatString, ":%s:%s", Machine->gamedrv->name, "%x:%x:%x:%x:%[^:\n\r]:%[^:\n\r]");
+ sprintf(oldFormatString, "%s:%s", Machine->gamedrv->name, "%d:%x:%x:%d:%[^:\n\r]:%[^:\n\r]");
+#endif
+
+ /* ----- get a line from database ----- */
+ while(mame_fgets(buf, 2048, theFile))
+ {
+ int type;
+ int address;
+ int data;
+ int extendData;
+ char name[256];
+ char description[256];
+#ifdef MESS
+ int crc;
+#endif
+
+ int argumentsMatched;
+ UINT32 command;
+
+ CheatEntry * entry;
+ CheatAction * action;
+
+ /* ----- get command line ----- */
+ argumentsMatched = sscanf(buf, ":_command:%8X", &command);
+
+ if(argumentsMatched == 1)
+ {
+ /* ----- set cheatOptions from command line ----- */
+ cheatOptions = command;
+
+ continue;
+ }
+
+ /* ----- get cheat code ----- */
+ name[0] = 0;
+ description[0] = 0;
+
+#ifdef MESS
+ argumentsMatched = sscanf(buf, formatString, &crc, &type, &address, &data, &extendData, name, description);
+#else
+ argumentsMatched = sscanf(buf, formatString, &type, &address, &data, &extendData, name, description);
+#endif
+
+#ifdef MESS
+ if(argumentsMatched < 5)
+#else
+ if(argumentsMatched < 4)
+#endif
+ {
+ int oldCPU;
+ int oldCode;
+
+#ifdef MESS
+ argumentsMatched = sscanf(buf, oldFormatString, &crc, &oldCPU, &address, &data, &oldCode, name, description);
+
+ if(argumentsMatched < 5)
+#else
+ argumentsMatched = sscanf(buf, oldFormatString, &oldCPU, &address, &data, &oldCode, name, description);
+
+ if(argumentsMatched < 4)
+#endif
+ /* ----- if it is not a cheat code, continue ----- */
+ continue;
+ else
+ {
+#ifdef MESS
+ if(!MatchesCRCTable(crc))
+ continue;
+#endif
+ /* ----- convert the old code to the new format ----- */
+ if(TEST_FIELD(cheatOptions, LoadOldFormat))
+ type = ConvertOldCode(oldCode, oldCPU, &data, &extendData);
+// continue;
+ }
+ }
+ else
+ {
+#ifdef MESS
+ if(!MatchesCRCTable(crc))
+ continue;
+#endif
+ }
+
+ //logerror("cheat: processing %s\n", buf);
+
+ if(TEST_FIELD(type, RemoveFromList))
+ {
+ //logerror("cheat: cheat line removed\n", buf);
+
+ HandleLocalCommandCheat(type, address, data, extendData, name, description);
+ }
+ else
+ {
+ if(TEST_FIELD(type, LinkEnable))
+ {
+ /* ----- if 1st code is the link code, it is invalid ----- */
+ if(cheatListLength == 0)
+ {
+ logerror("LoadCheatFile: first cheat found was link cheat; bailing\n");
+
+ goto bail;
+ }
+
+ //logerror("cheat: doing link cheat\n");
+
+ entry = &cheatList[cheatListLength - 1];
+ }
+ else
+ {
+ /* ----- go to the next cheat entry ----- */
+ ResizeCheatList(cheatListLength + 1);
+
+ //logerror("cheat: doing normal cheat\n");
+
+ if(cheatListLength == 0)
+ {
+ logerror("LoadCheatFile: cheat list resize failed; bailing\n");
+
+ goto bail;
+ }
+
+ entry = &cheatList[cheatListLength - 1];
+
+ /* ----- copy the code name ----- */
+ entry->name = CreateStringCopy(name);
+
+ /* ----- copy the description if we got it ----- */
+ if(argumentsMatched == 6)
+ entry->comment = CreateStringCopy(description);
+
+ recordNames = 0;
+
+ /* ----- try to copy the label if label-selection ------ */
+ if( (EXTRACT_FIELD(type, LocationType) == kLocation_Custom) &&
+ (EXTRACT_FIELD(type, LocationParameter) == kCustomLocation_Select))
+ recordNames = 1;
+ }
+
+ ResizeCheatActionList(&cheatList[cheatListLength - 1], entry->actionListLength + 1);
+
+ if(entry->actionListLength == 0)
+ {
+ logerror("LoadCheatFile: action list resize failed; bailing\n");
+
+ goto bail;
+ }
+
+ action = &entry->actionList[entry->actionListLength - 1];
+
+ action->type = type;
+ action->address = address;
+ action->data = data;
+ action->originalDataField = data;
+ action->extendData = extendData;
+
+ /* ----- copy the label if label-selection ------ */
+ if(recordNames)
+ action->optionalName = CreateStringCopy(name);
+ }
+ }
+
+ bail:
+
+ /* ----- close the database ----- */
+ mame_fclose(theFile);
+}
+
+/*---------------------------------------------------------
+ LoadCheatDatabase - get the database name then load it
+---------------------------------------------------------*/
+
+static void LoadCheatDatabase(void)
+{
+ char buf[4096];
+ const char * inTraverse;
+ char * outTraverse;
+ char * mainTraverse;
+ int first = 1;
+ char data;
+
+ cheatfile = options_get_string(mame_options(), OPTION_CHEAT_FILE);
+
+ /* ----- set default database name as "cheat.dat" ----- */
+ if (cheatfile[0] == 0)
+ cheatfile = "cheat.dat";
+
+ inTraverse = cheatfile;
+ outTraverse = buf;
+ mainTraverse = mainDatabaseName;
+
+ buf[0] = 0;
+
+ /* ----- get database name ----- */
+ do
+ {
+ data = *inTraverse;
+
+ /* ----- check separator or line end ----- */
+ if((data == ';') || (data == 0))
+ {
+ *outTraverse++ = 0;
+
+ if(first)
+ *mainTraverse++ = 0;
+
+ if(buf[0])
+ {
+ /* ----- load database based on the name we gotten ----- */
+ LoadCheatFile(buf);
+
+ outTraverse =buf;
+ buf[0] = 0;
+ first = 0;
+ }
+ }
+ else
+ {
+ *outTraverse++ = data;
+
+ if(first)
+ *mainTraverse++ = data;
+ }
+
+ inTraverse++;
+ }
+ while(data);
+
+ UpdateAllCheatInfo();
+}
+
+/*-----------------------------------------------------------------------------------------
+ DisposeCheatDatabase - deactivate all cheats when reload database or exit cheat system
+-----------------------------------------------------------------------------------------*/
+
+static void DisposeCheatDatabase(void)
+{
+ int i;
+
+ /* ----- first, turn all cheats "OFF" ----- */
+ for(i = 0; i < cheatListLength; i++)
+ TempDeactivateCheat(&cheatList[i]);
+
+ /* ----- next, free memory for all cheat entries ----- */
+ if(cheatList)
+ {
+ for(i = 0; i < cheatListLength; i++)
+ DisposeCheat(&cheatList[i]);
+
+ free(cheatList);
+
+ cheatList = NULL;
+ cheatListLength = 0;
+ }
+}
+
+/*-------------------------------------------------------------------------
+ ReloadCheatDatabase - reload cheat database directly on the cheat menu
+-------------------------------------------------------------------------*/
+
+static void ReloadCheatDatabase(void)
+{
+ DisposeCheatDatabase();
+ LoadCheatDatabase();
+
+ ui_popup_time(1, "Cheat Database reloaded");
+}
+
+/*---------------------------------------------------------------
+ SaveCheat - save a code (normal code, activation key, option)
+---------------------------------------------------------------*/
+
+static void SaveCheat(CheatEntry * entry, int selection, int saveCode)
+{
+ enum{
+ normalCode = 0,
+ activationKey,
+ command,
+ };
+
+ mame_file * theFile;
+ file_error filerr;
+ UINT32 i;
+ char buf[4096];
+
+ /* ----- check selected entry ----- */
+ if((saveCode == normalCode) || (saveCode == activationKey))
+ {
+ if(!entry || !entry->actionList)
+ return;
+
+ if((saveCode == activationKey) && (entry->flags & kCheatFlag_Select) && !entry->actionListLength)
+ return;
+ }
+
+ /* ----- open the database ----- */
+ filerr = mame_fopen(SEARCHPATH_CHEAT, mainDatabaseName, OPEN_FLAG_WRITE, &theFile);
+
+ /* ----- if fails to create, no save ----- */
+ if(!theFile)
+ return;
+ if (filerr != FILERR_NONE)
+ {
+ filerr = mame_fopen(SEARCHPATH_CHEAT, mainDatabaseName, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, &theFile);
+
+ /* ----- if fails to create, no save ----- */
+ if(filerr != FILERR_NONE)
+ return;
+ }
+
+ mame_fseek(theFile, 0, SEEK_END);
+
+ switch(saveCode)
+ {
+ case normalCode:
+ for(i = 0; i < entry->actionListLength; i++)
+ {
+ CheatAction * action = &entry->actionList[i];
+ char * name = entry->name;
+ UINT32 type = action->type;
+ char * bufTraverse = buf;
+ int addressLength = 8;
+
+ /* ----- set link enable and label if label-selection ----- */
+ if(i)
+ {
+ SET_MASK_FIELD(type, LinkEnable);
+
+ if(entry->flags & kCheatFlag_Select)
+ name = action->optionalName;
+ }
+
+ /* ----- get address length for current CPU ----- */
+ switch(EXTRACT_FIELD(type, LocationType))
+ {
+ case kLocation_Standard:
+ case kLocation_HandlerMemory:
+ case kLocation_ProgramSpace:
+ addressLength = cpuInfoList[EXTRACT_FIELD(type, LocationParameter)].addressCharsNeeded;
+ break;
+
+ case kLocation_IndirectIndexed:
+ addressLength = cpuInfoList[(EXTRACT_FIELD(type, LocationParameter) >> 2) & 0x7].addressCharsNeeded;
+ break;
+
+ case kLocation_MemoryRegion:
+ {
+ int idx = EXTRACT_FIELD(type, LocationParameter) + REGION_CPU1 - REGION_INVALID;
+
+ if(idx < kRegionListLength)
+ addressLength = regionInfoList[idx].addressCharsNeeded;
+ }
+ break;
+ }
+#ifdef MESS
+ bufTraverse += sprintf(bufTraverse, ":%s:%.8X:%.8X:%.*X:%.8X:%.8X", Machine->gamedrv->name, thisGameCRC, type, addressLength, action->address, action->originalDataField, action->extendData);
+#else
+ bufTraverse += sprintf(bufTraverse, ":%s:%.8X:%.*X:%.8X:%.8X", Machine->gamedrv->name, type, addressLength, action->address, action->originalDataField, action->extendData);
+#endif
+ /* ----- set description and comment ----- */
+ if(name)
+ {
+ bufTraverse += sprintf(bufTraverse, ":%s", name);
+
+ if(!i && (entry->comment))
+ bufTraverse += sprintf(bufTraverse, ":%s", entry->comment);
+ }
+ else
+ {
+ if(!i && (entry->comment))
+ bufTraverse += sprintf(bufTraverse, ":(none):%s", entry->comment);
+ }
+
+ bufTraverse += sprintf(bufTraverse, "\n");
+
+ /* ----- write the normal cheat code ----- */
+ mame_fwrite(theFile, buf, (UINT32)strlen(buf));
+ }
+ break;
+
+ case activationKey:
+ for(i = 0; i < 2; i++)
+ {
+ char * bufTraverse = buf;
+ int addressLength;
+
+ /* ----- if not find 1st activation key at saving 1st key, try to save 2nd key ----- */
+ if(!i && !(entry->flags & kCheatFlag_HasActivationKey1))
+ continue;
+
+ /* ----- if not find 2nd key after 1st key saved, finish ------ */
+ if(i && !(entry->flags & kCheatFlag_HasActivationKey2))
+ break;
+
+ /* ----- get address length for current CPU ----- */
+ if(!(entry->flags & kCheatFlag_Select))
+ addressLength = cpuInfoList[EXTRACT_FIELD(entry->actionList[0].type, LocationParameter)].addressCharsNeeded;
+ else
+ addressLength = cpuInfoList[EXTRACT_FIELD(entry->actionList[1].type, LocationParameter)].addressCharsNeeded;
+#ifdef MESS
+ if(!i)
+ bufTraverse += sprintf(bufTraverse, ":%s:%.8X:63004000:%.*X:%.8X:00000000", Machine->gamedrv->name, thisGameCRC, addressLength, selection, entry->activationKey1);
+ else
+ bufTraverse += sprintf(bufTraverse, ":%s:%.8X:63004001:%.*X:%.8X:00000000", Machine->gamedrv->name, thisGameCRC, addressLength, selection, entry->activationKey2);
+#else
+ if(!i)
+ bufTraverse += sprintf(bufTraverse, ":%s:63004000:%.*X:%.8X:00000000", Machine->gamedrv->name, addressLength, selection, entry->activationKey1);
+ else
+ bufTraverse += sprintf(bufTraverse, ":%s:63004001:%.*X:%.8X:00000000", Machine->gamedrv->name, addressLength, selection, entry->activationKey2);
+#endif
+ /* ----- set description and button index ----- */
+ if(!i)
+ {
+ /* ----- 1st key ----- */
+ astring *name = input_code_name(astring_alloc(), entry->activationKey1);
+ if (entry->name)
+ bufTraverse += sprintf(bufTraverse, ":1st Activation Key for %s (%s)\n", entry->name, astring_c(name));
+ else
+ bufTraverse += sprintf(bufTraverse, ":1st Activation Key (%s)\n", astring_c(name));
+ astring_free(name);
+ }
+ else
+ {
+ /* ----- 2nd key ----- */
+ astring *name = input_code_name(astring_alloc(), entry->activationKey2);
+ if (entry->name)
+ bufTraverse += sprintf(bufTraverse, ":2nd Activation Key for %s (%s)\n", entry->name, astring_c(name));
+ else
+ bufTraverse += sprintf(bufTraverse, ":2nd Activation Key (%s)\n", astring_c(name));
+ astring_free(name);
+ }
+
+ /* ----- write the activation key code ----- */
+ mame_fwrite(theFile, buf, (UINT32)strlen(buf));
+ }
+ break;
+
+ case command:
+ sprintf(buf, ":_command:%.8X\n", cheatOptions);
+
+ /* ----- write the command code ----- */
+ mame_fwrite(theFile, buf, (UINT32)strlen(buf));
+ break;
+
+ default:
+ break;
+ }
+
+ /* ----- close the database ----- */
+ mame_fclose(theFile);
+
+ /* ----- clear dirty flag ----- */
+ if((saveCode == normalCode) || (saveCode == activationKey))
+ entry->flags &= ~kCheatFlag_Dirty;
+}
+
+/*--------------------------------------------------------------------------
+ DoAutoSaveCheat - save normal code automatically when exit cheat system
+--------------------------------------------------------------------------*/
+
+static void DoAutoSaveCheats(void)
+{
+ int i;
+
+ for(i = 0; i < cheatListLength; i++)
+ {
+ CheatEntry * entry = &cheatList[i];
+
+ if(entry->flags & kCheatFlag_Dirty)
+ SaveCheat(entry, 0, 0);
+ }
+}
+
+/*-------------------------------------------------------------------
+ AddCheatFromResult - add a code from result viewer to cheat list
+-------------------------------------------------------------------*/
+
+static void AddCheatFromResult(SearchInfo * search, SearchRegion * region, UINT32 address)
+{
+ if(region->targetType == kRegionType_CPU)
+ {
+ CheatEntry * entry = GetNewCheat();
+ CheatAction * action = &entry->actionList[0];
+ char tempString[1024];
+ int tempStringLength;
+ UINT32 data = ReadSearchOperand(kSearchOperand_First, search, region, address);
+
+ tempStringLength = sprintf(tempString, "%.8X (%d) = %.*X", address, region->targetIdx, kSearchByteDigitsTable[search->bytes], data);
+
+ entry->name = realloc(entry->name, tempStringLength + 1);
+ memcpy(entry->name, tempString, tempStringLength + 1);
+
+ SET_FIELD(action->type, LocationParameter, region->targetIdx);
+ SET_FIELD(action->type, BytesUsed, kSearchByteIncrementTable[search->bytes] - 1);
+ action->address = address;
+ action->data = data;
+ action->extendData = 0xFFFFFFFF;
+ action->originalDataField = data;
+
+ UpdateCheatInfo(entry, 0);
+ }
+}
+
+/*--------------------------------------------------------------------------------------------
+ AddCheatFromFirstResult - add a code from search box to cheat list if found result is one
+--------------------------------------------------------------------------------------------*/
+
+static void AddCheatFromFirstResult(SearchInfo * search)
+{
+ int i;
+
+ for(i = 0; i < search->regionListLength; i++)
+ {
+ SearchRegion * region = &search->regionList[i];
+
+ if(region->numResults)
+ {
+ UINT32 traverse;
+
+ for(traverse = 0; traverse < region->length; traverse++)
+ {
+ UINT32 address = region->address + traverse;
+
+ if(IsRegionOffsetValid(search, region, traverse))
+ {
+ AddCheatFromResult(search, region, address);
+
+ return;
+ }
+ }
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------
+ AddWatchFromResult - add a watch code from result viewer to cheat list
+-------------------------------------------------------------------------*/
+
+static void AddWatchFromResult(SearchInfo * search, SearchRegion * region, UINT32 address)
+{
+ if(region->targetType == kRegionType_CPU)
+ {
+ WatchInfo * info = GetUnusedWatch();
+
+ info->address = address;
+ info->cpu = region->targetIdx;
+ info->numElements = 1;
+ info->elementBytes = kWatchSizeConversionTable[search->bytes];
+ info->labelType = kWatchLabel_None;
+ info->displayType = kWatchDisplayType_Hex;
+ info->skip = 0;
+ info->elementsPerLine = 0;
+ info->addValue = 0;
+
+ info->linkedCheat = NULL;
+
+ info->label[0] = 0;
+ }
+}
+
+/*--------------------
+ SearchSignExtend
+--------------------*/
+
+static UINT32 SearchSignExtend(SearchInfo * search, UINT32 value)
+{
+ if(search->sign)
+ {
+ if(value & kSearchByteSignBitTable[search->bytes])
+ value |= ~kSearchByteUnsignedMaskTable[search->bytes];
+ }
+
+ return value;
+}
+
+/*-------------------------------------------------------------------
+ ReadSearchOperand - read a data from search region and return it
+-------------------------------------------------------------------*/
+
+static UINT32 ReadSearchOperand(UINT8 type, SearchInfo * search, SearchRegion * region, UINT32 address)
+{
+ UINT32 value = 0;
+
+ switch(type)
+ {
+ case kSearchOperand_Current:
+ value = ReadRegionData(region, address - region->address, kSearchByteIncrementTable[search->bytes], search->swap);
+ break;
+
+ case kSearchOperand_Previous:
+ value = DoMemoryRead(region->last, address - region->address, kSearchByteIncrementTable[search->bytes], search->swap, NULL);
+ break;
+
+ case kSearchOperand_First:
+ value = DoMemoryRead(region->first, address - region->address, kSearchByteIncrementTable[search->bytes], search->swap, NULL);
+ break;
+
+ case kSearchOperand_Value:
+ value = search->value;
+ break;
+ }
+
+ value = SearchSignExtend(search, value);
+
+ return value;
+}
+
+/*------------------------------------------------------------------------------------------
+ ReadSearchOperandBit - read a bit data from search region and return it when bit search
+------------------------------------------------------------------------------------------*/
+
+static UINT32 ReadSearchOperandBit(UINT8 type, SearchInfo * search, SearchRegion * region, UINT32 address)
+{
+ UINT32 value = 0;
+
+ switch(type)
+ {
+ case kSearchOperand_Current:
+ value = ReadRegionData(region, address - region->address, kSearchByteIncrementTable[search->bytes], search->swap);
+ break;
+
+ case kSearchOperand_Previous:
+ value = DoMemoryRead(region->last, address - region->address, kSearchByteIncrementTable[search->bytes], search->swap, NULL);
+ break;
+
+ case kSearchOperand_First:
+ value = DoMemoryRead(region->first, address - region->address, kSearchByteIncrementTable[search->bytes], search->swap, NULL);
+ break;
+
+ case kSearchOperand_Value:
+ if(search->value)
+ value = 0xFFFFFFFF;
+ else
+ value = 0x00000000;
+ break;
+ }
+
+ value = SearchSignExtend(search, value);
+
+ return value;
+}
+
+/*----------------------------------------------------------
+ DoSearchComparison - compare data and return it matched
+----------------------------------------------------------*/
+
+static UINT8 DoSearchComparison(SearchInfo * search, UINT32 lhs, UINT32 rhs)
+{
+ INT32 svalue;
+
+ if(search->sign)
+ {
+ /* ----- signed ----- */
+ INT32 slhs = lhs;
+ INT32 srhs = rhs;
+
+ switch(search->comparison)
+ {
+ case kSearchComparison_LessThan:
+ return slhs < srhs;
+
+ case kSearchComparison_GreaterThan:
+ return slhs > srhs;
+
+ case kSearchComparison_EqualTo:
+ return slhs == srhs;
+
+ case kSearchComparison_LessThanOrEqualTo:
+ return slhs <= srhs;
+
+ case kSearchComparison_GreaterThanOrEqualTo:
+ return slhs >= srhs;
+
+ case kSearchComparison_NotEqual:
+ return slhs != srhs;
+
+ case kSearchComparison_IncreasedBy:
+ svalue = search->value;
+ if(search->value & kSearchByteSignBitTable[search->bytes])
+ svalue |= ~kSearchByteUnsignedMaskTable[search->bytes];
+
+ return slhs == (srhs + svalue);
+
+ case kSearchComparison_NearTo:
+ return (slhs == srhs) || ((slhs + 1) == srhs);
+ }
+ }
+ else
+ {
+ /* ----- unsigned ----- */
+ switch(search->comparison)
+ {
+ case kSearchComparison_LessThan:
+ return lhs < rhs;
+
+ case kSearchComparison_GreaterThan:
+ return lhs > rhs;
+
+ case kSearchComparison_EqualTo:
+ return lhs == rhs;
+
+ case kSearchComparison_LessThanOrEqualTo:
+ return lhs <= rhs;
+
+ case kSearchComparison_GreaterThanOrEqualTo:
+ return lhs >= rhs;
+
+ case kSearchComparison_NotEqual:
+ return lhs != rhs;
+
+ case kSearchComparison_IncreasedBy:
+ svalue = search->value;
+ if(search->value & kSearchByteSignBitTable[search->bytes])
+ svalue |= ~kSearchByteUnsignedMaskTable[search->bytes];
+
+ return lhs == (rhs + svalue);
+
+ case kSearchComparison_NearTo:
+ return (lhs == rhs) || ((lhs + 1) == rhs);
+ }
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------
+ DoSearchComparisonBit - compare bit data and return it matched
+-----------------------------------------------------------------*/
+
+static UINT32 DoSearchComparisonBit(SearchInfo * search, UINT32 lhs, UINT32 rhs)
+{
+ switch(search->comparison)
+ {
+ case kSearchComparison_LessThan:
+ case kSearchComparison_NotEqual:
+ case kSearchComparison_GreaterThan:
+ case kSearchComparison_LessThanOrEqualTo:
+ case kSearchComparison_GreaterThanOrEqualTo:
+ case kSearchComparison_IncreasedBy:
+ return lhs ^ rhs;
+
+ case kSearchComparison_EqualTo:
+ case kSearchComparison_NearTo:
+ return ~(lhs ^ rhs);
+ }
+
+ return 0;
+}
+
+/*----------------------
+ IsRegionOffsetValid
+----------------------*/
+
+/*
+static UINT8 IsRegionOffsetValid(SearchInfo * search, SearchRegion * region, UINT32 offset)
+{
+ switch(kSearchByteIncrementTable[search->bytes])
+ {
+ case 1:
+ return *((UINT8 *)&region->status[offset]) == 0xFF;
+ break;
+
+ case 2:
+ return *((UINT16 *)&region->status[offset]) == 0xFFFF;
+ break;
+
+ case 4:
+ return *((UINT32 *)&region->status[offset]) == 0xFFFFFFFF;
+ break;
+ }
+
+ return 0;
+}
+*/
+
+/*----------------------------------------------------------
+ IsRegionOffsetValidBit - check selected offset is valid
+----------------------------------------------------------*/
+
+static UINT8 IsRegionOffsetValidBit(SearchInfo * search, SearchRegion * region, UINT32 offset)
+{
+ switch(kSearchByteStep[search->bytes])
+ {
+ case 1:
+ return *((UINT8 *)&region->status[offset]) != 0;
+ break;
+
+ case 2:
+ return *((UINT16 *)&region->status[offset]) != 0;
+ break;
+
+ case 3:
+ return ((*((UINT16 *)&region->status[offset]) != 0) | (*((UINT8 *)&region->status[offset+2]) != 0));
+ break;
+
+ case 4:
+ return *((UINT32 *)&region->status[offset]) != 0;
+ break;
+ }
+
+ return 0;
+}
+
+/*----------------------------------------------------------------
+ InvalidateRegionOffset - remove unmatched offset after search
+----------------------------------------------------------------*/
+
+static void InvalidateRegionOffset(SearchInfo * search, SearchRegion * region, UINT32 offset)
+{
+ switch(kSearchByteStep[search->bytes])
+ {
+ case 1:
+ *((UINT8 *)&region->status[offset]) = 0;
+ break;
+
+ case 2:
+ *((UINT16 *)&region->status[offset]) = 0;
+ break;
+
+ case 3:
+ *((UINT16 *)&region->status[offset]) = 0;
+ *((UINT8 *)&region->status[offset+2]) = 0;
+ break;
+
+ case 4:
+ *((UINT32 *)&region->status[offset]) = 0;
+ break;
+ }
+}
+
+/*-----------------------------------------------------------------------
+ InvalidateRegionOffsetBit - remove unmatched offset after bit search
+-----------------------------------------------------------------------*/
+
+static void InvalidateRegionOffsetBit(SearchInfo * search, SearchRegion * region, UINT32 offset, UINT32 invalidate)
+{
+ switch(kSearchByteStep[search->bytes])
+ {
+ case 1:
+ *((UINT8 *)&region->status[offset]) &= ~invalidate;
+ break;
+
+ case 2:
+ *((UINT16 *)&region->status[offset]) &= ~invalidate;
+ break;
+
+ case 3:
+ *((UINT16 *)&region->status[offset]) &= ~invalidate;
+ *((UINT8 *)&region->status[offset+2]) &= ~invalidate;
+ break;
+
+ case 4:
+ *((UINT32 *)&region->status[offset]) &= ~invalidate;
+ break;
+ }
+}
+
+/*--------------------------------------------------------------
+ InvalidateEntireRegions - invalidate selected search region
+--------------------------------------------------------------*/
+
+static void InvalidateEntireRegion(SearchInfo * search, SearchRegion * region)
+{
+ memset(region->status, 0, region->length);
+
+ search->numResults -= region->numResults;
+ region->numResults = 0;
+}
+
+/*-------------------------------------------------------------------
+ InitializeNewSearch - initialize search region to start a search
+-------------------------------------------------------------------*/
+
+static void InitializeNewSearch(SearchInfo * search)
+{
+ int i;
+
+ search->numResults = 0;
+
+ for(i = 0; i < search->regionListLength; i++)
+ {
+ SearchRegion * region = &search->regionList[i];
+
+ if(region->flags & kRegionFlag_Enabled)
+ {
+ region->numResults = 0;
+
+ memset(region->status, 0xFF, region->length);
+
+ FillBufferFromRegion(region, region->first);
+
+ memcpy(region->last, region->first, region->length);
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------
+ UpdateSearch - updata a data in search region after initialize or search
+---------------------------------------------------------------------------*/
+
+static void UpdateSearch(SearchInfo * search)
+{
+ int i;
+
+ for(i = 0; i < search->regionListLength; i++)
+ {
+ SearchRegion * region = &search->regionList[i];
+
+ if(region->flags & kRegionFlag_Enabled)
+ FillBufferFromRegion(region, region->last);
+ }
+}
+
+/*-------------------------------------
+ DoSearch - management for a search
+-------------------------------------*/
+
+static void DoSearch(SearchInfo * search)
+{
+ int i, j;
+
+ search->numResults = 0;
+
+ if(search->bytes == kSearchSize_1Bit)
+ {
+ /* ----- bit search ----- */
+ for(i = 0; i < search->regionListLength; i++)
+ {
+ SearchRegion * region = &search->regionList[i];
+ UINT32 lastAddress = region->length - kSearchByteIncrementTable[search->bytes] + 1;
+ UINT32 increment = kSearchByteStep[search->bytes];
+
+ region->numResults = 0;
+
+ if((region->length < kSearchByteIncrementTable[search->bytes]) || !region->flags & kRegionFlag_Enabled)
+ continue;
+
+ for(j = 0; j < lastAddress; j += increment)
+ {
+ UINT32 address;
+ UINT32 lhs, rhs;
+
+ address = region->address + j;
+
+ if(IsRegionOffsetValidBit(search, region, j))
+ {
+ UINT32 validBits;
+
+ lhs = ReadSearchOperandBit(search->lhs, search, region, address);
+ rhs = ReadSearchOperandBit(search->rhs, search, region, address);
+
+ /* ----- do search ----- */
+ validBits = DoSearchComparisonBit(search, lhs, rhs);
+
+ InvalidateRegionOffsetBit(search, region, j, ~validBits);
+
+ if(IsRegionOffsetValidBit(search, region, j))
+ {
+ search->numResults++;
+ region->numResults++;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /* ----- normal search ----- */
+ for(i = 0; i < search->regionListLength; i++)
+ {
+ SearchRegion * region = &search->regionList[i];
+ UINT32 lastAddress = region->length - kSearchByteIncrementTable[search->bytes] + 1;
+ UINT32 increment = kSearchByteStep[search->bytes];
+
+ region->numResults = 0;
+
+ if((region->length < kSearchByteIncrementTable[search->bytes]) || !region->flags & kRegionFlag_Enabled)
+ continue;
+
+ for(j = 0; j < lastAddress; j += increment)
+ {
+ UINT32 address;
+ UINT32 lhs, rhs;
+
+ address = region->address + j;
+
+ if(IsRegionOffsetValid(search, region, j))
+ {
+ lhs = ReadSearchOperand(search->lhs, search, region, address);
+ rhs = ReadSearchOperand(search->rhs, search, region, address);
+
+ /* ----- do search ----- */
+ if(!DoSearchComparison(search, lhs, rhs))
+ /* ----- unmatched ----- */
+ InvalidateRegionOffset(search, region, j);
+ else
+ {
+ /* ----- matched ----- */
+ search->numResults++;
+ region->numResults++;
+ }
+ }
+ }
+ }
+ }
+}
+
+/*----------------------
+ LookupHandlerMemory
+----------------------*/
+
+static UINT8 ** LookupHandlerMemory(UINT8 cpu, UINT32 address, UINT32 * outRelativeAddress)
+{
+ const address_map * map = memory_get_map(cpu, ADDRESS_SPACE_PROGRAM);
+
+ while(!IS_AMENTRY_END(map))
+ {
+ if(!IS_AMENTRY_EXTENDED(map) && map->write.handler)
+ {
+ if((address >= map->start) && (address <= map->end))
+ {
+ if(outRelativeAddress)
+ *outRelativeAddress = address - map->start;
+
+ return (UINT8 **)map->base;
+ }
+ }
+
+ map++;
+ }
+
+ return NULL;
+}
+
+/*------------------------------------------
+ DoCPURead - read a data from RAM region
+------------------------------------------*/
+
+static UINT32 DoCPURead(UINT8 cpu, UINT32 address, UINT8 bytes, UINT8 swap)
+{
+ switch(bytes)
+ {
+ case 1:
+ return (cpunum_read_byte(cpu, address + 0) << 0);
+
+ case 2:
+ if(swap)
+ return (cpunum_read_byte(cpu, address + 0) << 0) | (cpunum_read_byte(cpu, address + 1) << 8);
+ else
+ return (cpunum_read_byte(cpu, address + 0) << 8) | (cpunum_read_byte(cpu, address + 1) << 0);
+ break;
+
+ case 3:
+ if(swap)
+ return (cpunum_read_byte(cpu, address + 0) << 0) | (cpunum_read_byte(cpu, address + 1) << 8) |
+ (cpunum_read_byte(cpu, address + 2) << 16);
+ else
+ return (cpunum_read_byte(cpu, address + 0) << 16) | (cpunum_read_byte(cpu, address + 1) << 8) |
+ (cpunum_read_byte(cpu, address + 2) << 0);
+ break;
+
+ case 4:
+ if(swap)
+ return (cpunum_read_byte(cpu, address + 0) << 0) | (cpunum_read_byte(cpu, address + 1) << 8) |
+ (cpunum_read_byte(cpu, address + 2) << 16) | (cpunum_read_byte(cpu, address + 3) << 24);
+ else
+ return (cpunum_read_byte(cpu, address + 0) << 24) | (cpunum_read_byte(cpu, address + 1) << 16) |
+ (cpunum_read_byte(cpu, address + 2) << 8) | (cpunum_read_byte(cpu, address + 3) << 0);
+ break;
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------------
+ DoMemoryRead - read a data from ROM or User region
+-----------------------------------------------------*/
+
+static UINT32 DoMemoryRead(UINT8 * buf, UINT32 address, UINT8 bytes, UINT8 swap, CPUInfo * info)
+{
+ UINT32 data = 0;
+
+ if(!info)
+ {
+ switch(bytes)
+ {
+ case 1:
+ data = buf[address];
+ break;
+
+ case 2:
+ data = *((UINT16 *)&buf[address]);
+
+ if(swap)
+ data = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00);
+ break;
+
+ case 4:
+ data = *((UINT32 *)&buf[address]);
+
+ if(swap)
+ data = ((data >> 24) & 0x000000FF) | ((data >> 8) & 0x0000FF00) |
+ ((data << 8) & 0x00FF0000) | ((data << 24) & 0xFF000000);
+ break;
+
+ default:
+ info = &rawCPUInfo;
+ goto generic;
+ }
+
+ return data;
+ }
+
+generic:
+
+ if(swap)
+ {
+ UINT32 i;
+
+ for(i = 0; i < bytes; i++)
+ data |= buf[SwapAddress(address + i, bytes, info)] << (i * 8);
+ }
+ else
+ {
+ UINT32 i;
+
+ for(i = 0; i < bytes; i++)
+ data |= buf[SwapAddress(address + i, bytes, info)] << ((bytes - i - 1) * 8);
+ }
+
+ return data;
+}
+
+/*--------------------------------------------
+ DoCPUWrite - write a data into RAM region
+--------------------------------------------*/
+
+static void DoCPUWrite(UINT32 data, UINT8 cpu, UINT32 address, UINT8 bytes, UINT8 swap)
+{
+ switch(bytes)
+ {
+ case 1:
+ cpunum_write_byte(cpu, address + 0, data & 0xFF);
+ break;
+
+ case 2:
+ if(swap)
+ {
+ cpunum_write_byte(cpu, address + 0, (data >> 0) & 0xFF);
+ cpunum_write_byte(cpu, address + 1, (data >> 8) & 0xFF);
+ }
+ else
+ {
+ cpunum_write_byte(cpu, address + 0, (data >> 8) & 0xFF);
+ cpunum_write_byte(cpu, address + 1, (data >> 0) & 0xFF);
+ }
+ break;
+
+ case 3:
+ if(swap)
+ {
+ cpunum_write_byte(cpu, address + 0, (data >> 0) & 0xFF);
+ cpunum_write_byte(cpu, address + 1, (data >> 8) & 0xFF);
+ cpunum_write_byte(cpu, address + 2, (data >> 16) & 0xFF);
+ }
+ else
+ {
+ cpunum_write_byte(cpu, address + 0, (data >> 16) & 0xFF);
+ cpunum_write_byte(cpu, address + 1, (data >> 8) & 0xFF);
+ cpunum_write_byte(cpu, address + 2, (data >> 0) & 0xFF);
+ }
+ break;
+
+ case 4:
+ if(swap)
+ {
+ cpunum_write_byte(cpu, address + 0, (data >> 0) & 0xFF);
+ cpunum_write_byte(cpu, address + 1, (data >> 8) & 0xFF);
+ cpunum_write_byte(cpu, address + 2, (data >> 16) & 0xFF);
+ cpunum_write_byte(cpu, address + 3, (data >> 24) & 0xFF);
+ }
+ else
+ {
+ cpunum_write_byte(cpu, address + 0, (data >> 24) & 0xFF);
+ cpunum_write_byte(cpu, address + 1, (data >> 16) & 0xFF);
+ cpunum_write_byte(cpu, address + 2, (data >> 8) & 0xFF);
+ cpunum_write_byte(cpu, address + 3, (data >> 0) & 0xFF);
+ }
+ break;
+
+ default:
+ logerror("DoCPUWrite: bad size (%d)\n", bytes);
+ break;
+ }
+}
+
+/*-------------------------------------------------------
+ DoMemoryWrite - write a data into ROM or User region
+-------------------------------------------------------*/
+
+static void DoMemoryWrite(UINT32 data, UINT8 * buf, UINT32 address, UINT8 bytes, UINT8 swap, CPUInfo * info)
+{
+ if(!info)
+ {
+ switch(bytes)
+ {
+ case 1:
+ buf[address] = data;
+ break;
+
+ case 2:
+ if(swap)
+ data = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00);
+
+ *((UINT16 *)&buf[address]) = data;
+ break;
+
+ case 4:
+ if(swap)
+ data = ((data >> 24) & 0x000000FF) | ((data >> 8) & 0x0000FF00) |
+ ((data << 8) & 0x00FF0000) | ((data << 24) & 0xFF000000);
+
+ *((UINT32 *)&buf[address]) = data;
+ break;
+
+ default:
+ info = &rawCPUInfo;
+ goto generic;
+ }
+
+ return;
+ }
+
+generic:
+
+ if(swap)
+ {
+ UINT32 i;
+
+ for(i = 0; i < bytes; i++)
+ buf[SwapAddress(address + i, bytes, info)] = data >> (i * 8);
+ }
+ else
+ {
+ UINT32 i;
+
+ for(i = 0; i < bytes; i++)
+ buf[SwapAddress(address + i, bytes, info)] = data >> ((bytes - i - 1) * 8);
+ }
+}
+
+/*--------------------------------
+ CPUNeedsSwap - endian checker
+--------------------------------*/
+
+static UINT8 CPUNeedsSwap(UINT8 cpu)
+{
+ return cpuInfoList[cpu].endianness ^ 1;
+}
+
+/*-----------------------------------
+ RegionNeedsSwap - endian checker
+-----------------------------------*/
+
+static UINT8 RegionNeedsSwap(UINT8 region)
+{
+ CPUInfo * temp = GetRegionCPUInfo(region);
+
+ if(temp)
+ return temp->endianness ^ 1;
+
+ return 0;
+}
+
+/*----------------------------------------------------
+ GetCPUInfo - return CPU info for standard region
+----------------------------------------------------*/
+
+static CPUInfo * GetCPUInfo(UINT8 cpu)
+{
+ return &cpuInfoList[cpu];
+}
+
+/*-------------------------------------------------
+ GetRegionCPUInfo - return CPU info for regions
+-------------------------------------------------*/
+
+static CPUInfo * GetRegionCPUInfo(UINT8 region)
+{
+ if((region >= REGION_INVALID) && (region < REGION_MAX))
+ return &regionInfoList[region - REGION_INVALID];
+
+ return NULL;
+}
+
+/*--------------
+ SwapAddress
+--------------*/
+
+static UINT32 SwapAddress(UINT32 address, UINT8 dataSize, CPUInfo * info)
+{
+ switch(info->dataBits)
+ {
+ case 16:
+ if(info->endianness == CPU_IS_BE)
+ return BYTE_XOR_BE(address);
+ else
+ return BYTE_XOR_LE(address);
+
+ case 32:
+ if(info->endianness == CPU_IS_BE)
+ return BYTE4_XOR_BE(address);
+ else
+ return BYTE4_XOR_LE(address);
+ }
+
+ return address;
+}
+
+/*------------------------------------
+ ReadData - read a data per region
+------------------------------------*/
+
+static UINT32 ReadData(CheatAction * action)
+{
+ UINT8 parameter = EXTRACT_FIELD(action->type, LocationParameter);
+ UINT8 bytes = EXTRACT_FIELD(action->type, BytesUsed) + 1;
+ UINT8 swapBytes = EXTRACT_FIELD(action->type, Endianness);
+
+ switch(EXTRACT_FIELD(action->type, LocationType))
+ {
+ case kLocation_Standard:
+ return DoCPURead(parameter, action->address, bytes, CPUNeedsSwap(parameter) ^ swapBytes);
+ break;
+
+ case kLocation_MemoryRegion:
+ {
+ int region = REGION_CPU1 + parameter;
+ UINT8 * buf = memory_region(region);
+
+ if(buf)
+ {
+ if(TEST_FIELD(cheatOptions, Debug))
+ {
+ if(ControlKeyPressed())
+ ui_popup_time(1, "MR : %x : %p", region, buf);
+ }
+
+ if(IsAddressInRange(action, memory_region_length(region)))
+ return DoMemoryRead(buf, action->address, bytes, RegionNeedsSwap(region) ^ swapBytes, GetRegionCPUInfo(region));
+ }
+ }
+ break;
+
+ case kLocation_HandlerMemory:
+ {
+ UINT32 relativeAddress;
+ UINT8 ** buf;
+
+ if(!action->cachedPointer)
+ action->cachedPointer = LookupHandlerMemory(parameter, action->address, &action->cachedOffset);
+
+ buf = action->cachedPointer;
+ relativeAddress = action->cachedOffset;
+
+ if(buf && *buf)
+ return DoMemoryRead(*buf, relativeAddress, bytes, CPUNeedsSwap(parameter) ^ swapBytes, GetCPUInfo(parameter));
+ }
+ break;
+
+ case kLocation_IndirectIndexed:
+ {
+ UINT32 address;
+ INT32 offset = action->extendData;
+ UINT8 cpu = (parameter >> 2) & 0x7;
+ UINT8 addressBytes = (parameter & 0x3) + 1;
+ CPUInfo * info = GetCPUInfo(cpu);
+
+ address = DoCPURead(cpu, action->address, addressBytes, CPUNeedsSwap(cpu) ^ swapBytes);
+
+ if(info)
+ address = DoShift(address, info->addressShift);
+
+ if(address)
+ {
+ address += offset;
+
+ return DoCPURead(cpu, address, bytes, CPUNeedsSwap(cpu) ^ swapBytes);
+ }
+ }
+ break;
+
+ case kLocation_ProgramSpace:
+ {
+ UINT8 * buf;
+
+ memory_set_opbase(action->address);
+
+ buf = memory_get_op_ptr(parameter, action->address, 0);
+
+ buf -= action->address;
+
+ if(buf)
+ {
+ if(TEST_FIELD(cheatOptions, Debug))
+ {
+ if(ControlKeyPressed())
+ ui_popup_time(1,"PG : %x : %p", parameter, buf);
+ }
+
+ return DoMemoryRead(buf, action->address, bytes, CPUNeedsSwap(parameter) ^ swapBytes, GetCPUInfo(parameter));
+ }
+ }
+ break;
+
+ case kLocation_Custom:
+ {
+ switch(parameter)
+ {
+ case kCustomLocation_Comment:
+ break;
+
+ case kCustomLocation_EEPROM:
+ {
+ int length;
+ UINT8 * buf;
+
+ buf = EEPROM_get_data_pointer(&length);
+
+ if(IsAddressInRange(action, length))
+ return DoMemoryRead(buf, action->address, bytes, swapBytes, &rawCPUInfo);
+ }
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/*--------------------------------------
+ WriteData - write a data per region
+--------------------------------------*/
+
+static void WriteData(CheatAction * action, UINT32 data)
+{
+ UINT8 parameter = EXTRACT_FIELD(action->type, LocationParameter);
+ UINT8 bytes = EXTRACT_FIELD(action->type, BytesUsed) + 1;
+ UINT8 swapBytes = EXTRACT_FIELD(action->type, Endianness);
+
+ switch(EXTRACT_FIELD(action->type, LocationType))
+ {
+ case kLocation_Standard:
+ DoCPUWrite(data, parameter, action->address, bytes, CPUNeedsSwap(parameter) ^ swapBytes);
+
+ break;
+
+ case kLocation_MemoryRegion:
+ {
+ int region = REGION_CPU1 + parameter;
+ UINT8 * buf = memory_region(region);
+
+ if(buf)
+ {
+ if(IsAddressInRange(action, memory_region_length(region)))
+ DoMemoryWrite(data, buf, action->address, bytes, RegionNeedsSwap(region) ^ swapBytes, GetRegionCPUInfo(region));
+ }
+ }
+ break;
+
+ case kLocation_HandlerMemory:
+ {
+ UINT32 relativeAddress;
+ UINT8 ** buf;
+
+ if(!action->cachedPointer)
+ {
+ action->cachedPointer = LookupHandlerMemory(parameter, action->address, &action->cachedOffset);
+ }
+
+ buf = action->cachedPointer;
+ relativeAddress = action->cachedOffset;
+
+ if(buf && *buf)
+ DoMemoryWrite(data, *buf, relativeAddress, bytes, CPUNeedsSwap(parameter) ^ swapBytes, GetCPUInfo(parameter));
+ }
+ break;
+
+ case kLocation_IndirectIndexed:
+ {
+ UINT32 address;
+ INT32 offset = action->extendData;
+ UINT8 cpu = (parameter >> 2) & 0x7;
+ UINT8 addressBytes = (parameter & 0x3) + 1;
+ CPUInfo * info = GetCPUInfo(cpu);
+
+ address = DoCPURead(cpu, action->address, addressBytes, CPUNeedsSwap(cpu) ^ swapBytes);
+
+ if(info)
+ address = DoShift(address, info->addressShift);
+
+ if(address)
+ {
+ address += offset;
+
+ DoCPUWrite(data, cpu, address, bytes, CPUNeedsSwap(cpu) ^ swapBytes);
+ }
+ }
+ break;
+
+ case kLocation_ProgramSpace:
+ {
+ UINT8 * buf;
+
+ memory_set_opbase(action->address);
+
+ buf = memory_get_op_ptr(parameter, action->address, 0);
+
+ buf -= action->address;
+
+ if(buf)
+ DoMemoryWrite(data, buf, action->address, bytes, CPUNeedsSwap(parameter) ^ swapBytes, GetCPUInfo(parameter));
+ }
+ break;
+
+ case kLocation_Custom:
+ {
+ switch(parameter)
+ {
+ case kCustomLocation_Comment:
+ break;
+
+ case kCustomLocation_EEPROM:
+ {
+ int length;
+ UINT8 * buf;
+
+ buf = EEPROM_get_data_pointer(&length);
+
+ if(IsAddressInRange(action, length))
+ DoMemoryWrite(data, buf, action->address, bytes, swapBytes, &rawCPUInfo);
+ }
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*-----------------------------------------------------
+ WatchCheatEntry - set watchpoint from action entry
+-----------------------------------------------------*/
+
+static void WatchCheatEntry(CheatEntry * entry, UINT8 associate)
+{
+ UINT32 i, j;
+ CheatEntry * associateEntry = NULL;
+
+ if(associate)
+ associateEntry = entry;
+
+ if(!entry)
+ return;
+
+ for(i = 0; i < entry->actionListLength; i++)
+ {
+ if(!i)
+ /* ----- first action entry ----- */
+ AddActionWatch(&entry->actionList[i], associateEntry);
+ else
+ {
+ /* ----- 2nd or later action entry ----- */
+ UINT8 sameAddress = 0;
+
+ for(j = 0; j < i; j++)
+ {
+ /* ----- if we find the same address action entry, skip it ----- */
+ if(entry->actionList[j].address == entry->actionList[i].address)
+ sameAddress = 1;
+ }
+
+ if(!sameAddress)
+ AddActionWatch(&entry->actionList[i], associateEntry);
+ }
+ }
+}
+
+/*--------------------------------------------------
+ AddActionWatch - add watchpoint into watch list
+--------------------------------------------------*/
+
+static void AddActionWatch(CheatAction * action, CheatEntry * entry)
+{
+ if( (EXTRACT_FIELD(action->type, LocationType) == kLocation_Standard) ||
+ (EXTRACT_FIELD(action->type, LocationType) == kLocation_MemoryRegion) ||
+ (EXTRACT_FIELD(action->type, LocationType) == kLocation_IndirectIndexed) ||
+ (EXTRACT_FIELD(action->type, LocationType) == kLocation_ProgramSpace))
+
+ {
+ WatchInfo * info = GetUnusedWatch();
+
+ info->address = action->address;
+ info->cpu = EXTRACT_FIELD(action->type, LocationParameter);
+ info->displayType = kWatchDisplayType_Hex;
+ info->elementBytes = kByteConversionTable[EXTRACT_FIELD(action->type, BytesUsed)];
+ info->label[0] = 0;
+ info->labelType = kWatchLabel_None;
+ info->linkedCheat = entry;
+ info->numElements = 1;
+ info->skip = 0;
+
+ info->locationType = EXTRACT_FIELD(action->type, LocationType);
+
+ if(EXTRACT_FIELD(action->type, Type) == kType_Watch)
+ {
+ /* ----- set watchpoint from watch code ----- */
+ UINT32 typeParameter = EXTRACT_FIELD(action->type, TypeParameter);
+
+ info->numElements = (action->data & 0xFF) + 1;
+
+ info->skip = (action->data >> 8) & 0xFF;
+ info->elementsPerLine = (action->data >> 16) & 0xFF;
+ info->addValue = (action->data >> 24) & 0xFF;
+
+ if(info->addValue & 0x80)
+ info->addValue |= ~0xFF;
+
+ if(action->extendData != 0xFFFFFFFF)
+ {
+ /* ### fix me... ### */
+ info->x = (float)((action->extendData >> 16) & 0xFFFF)/100;
+ info->y = (float)((action->extendData >> 0) & 0xFFFF)/100;
+ }
+
+ /* ----- if label is needed, copy the description from comment field ----- */
+ if((typeParameter & 0x04) && (entry->comment) && (strlen(entry->comment) < 256))
+ {
+ info->labelType = kWatchLabel_String;
+ strcpy(info->label, entry->comment);
+ }
+
+ info->displayType = typeParameter & 0x03;
+ }
+ }
+}
+
+/*-----------------------------------------------------------------
+ RemoveAssociatedWatches - remove watchpoint when CODE is "OFF"
+-----------------------------------------------------------------*/
+
+static void RemoveAssociatedWatches(CheatEntry * entry)
+{
+ int i;
+
+ for(i = watchListLength - 1; i >= 0; i--)
+ {
+ WatchInfo * info = &watchList[i];
+
+ if(info->linkedCheat == entry)
+ DeleteWatchAt(i);
+ }
+}
+
+/*----------------------------------------------------------------------
+ ResetAction - back up data and set action flags when turn CODE "ON"
+----------------------------------------------------------------------*/
+
+static void ResetAction(CheatAction * action)
+{
+ action->frameTimer = 0;
+
+ /* ----- backup value ----- */
+ if(!(action->flags & kActionFlag_LastValueGood))
+ action->lastValue = ReadData(action);
+
+ action->flags &= ~kActionFlag_StateMask;
+ action->flags |= kActionFlag_LastValueGood;
+}
+
+/*-------------------------------------------------------------------------------------
+ ActivateCheat - reset action entry and set activate entry flag when turn CODE "ON"
+-------------------------------------------------------------------------------------*/
+
+static void ActivateCheat(CheatEntry * entry)
+{
+ int i;
+
+ for(i = 0; i < entry->actionListLength; i++)
+ {
+ CheatAction * action = &entry->actionList[i];
+
+ ResetAction(action);
+
+ /* ----- if watchpoint code, add watchpoint ----- */
+ if(EXTRACT_FIELD(action->type, Type) == kType_Watch)
+ AddActionWatch(action, entry);
+ }
+
+ entry->flags |= kCheatFlag_Active;
+}
+
+/*--------------------------------------------------------------------------------------
+ DeactivateCheat - restore previous value and remove watchpoint when turn CODE "OFF"
+--------------------------------------------------------------------------------------*/
+
+static void DeactivateCheat(CheatEntry * entry)
+{
+ int i;
+
+ for(i = 0; i < entry->actionListLength; i++)
+ {
+ CheatAction * action = &entry->actionList[i];
+
+ /* ----- restore previous value and clear backup flag if needed ----- */
+ if(EXTRACT_FIELD(action->type, RestorePreviousValue) && (action->flags & kActionFlag_LastValueGood))
+ {
+ WriteData(action, action->lastValue);
+
+ action->flags &= ~kActionFlag_LastValueGood;
+ }
+ }
+
+ /* ----- remove watchpoint ----- */
+ RemoveAssociatedWatches(entry);
+
+ entry->flags &= ~kCheatFlag_StateMask;
+}
+
+/*--------------------------------------------------------------------
+ TempDeactivateCheat - restore previous value when turn CHEAT "OFF"
+--------------------------------------------------------------------*/
+
+static void TempDeactivateCheat(CheatEntry * entry)
+{
+ if(entry->flags & kCheatFlag_Active)
+ {
+ int i;
+
+ for(i = 0; i < entry->actionListLength; i++)
+ {
+ CheatAction * action = &entry->actionList[i];
+
+ /* ----- restore previous value if needed ----- */
+ if(EXTRACT_FIELD(action->type, RestorePreviousValue) && (action->flags & kActionFlag_LastValueGood))
+ WriteData(action, action->lastValue);
+ }
+ }
+}
+
+/*------------------------------------------------------------
+ cheat_periodicOperation - management for cheat operations
+------------------------------------------------------------*/
+
+static void cheat_periodicOperation(CheatAction * action)
+{
+ UINT8 operation = EXTRACT_FIELD(action->type, Operation) | (EXTRACT_FIELD(action->type, OperationExtend) << 2);
+
+ switch(operation)
+ {
+ case kOperation_WriteMask:
+ {
+ UINT32 temp;
+
+ if(action->flags & kActionFlag_IgnoreMask)
+ WriteData(action, action->data);
+ else
+ {
+ temp = ReadData(action);
+
+ temp = (action->data & action->extendData) | (temp & ~action->extendData);
+
+ WriteData(action, temp);
+ }
+ }
+ break;
+
+ case kOperation_AddSubtract:
+ {
+ INT32 temp, bound;
+
+ /* ----- if extend data field is invalid, direct return ----- */
+ //if(action->flags & kActionFlag_IgnoreMask)
+ return;
+
+ temp = ReadData(action);
+
+ /* ----- OperationParameter field stores add/subtract ----- */
+ if(TEST_FIELD(action->type, OperationParameter))
+ {
+ /* ----- subtract ----- */
+ bound = action->extendData + action->data;
+
+ if(temp > bound)
+ temp -= action->data;
+ }
+ else
+ {
+ /* ----- add ----- */
+ bound = action->extendData - action->data;
+
+ if(temp < bound)
+ temp += action->data;
+ }
+
+ WriteData(action, temp);
+ }
+ break;
+
+ case kOperation_ForceRange:
+ {
+ UINT32 temp;
+
+ /* ----- if extend data field is invalid, direct return ----- */
+ if(action->flags & kActionFlag_IgnoreMask)
+ return;
+
+ temp = ReadData(action);
+
+ if(!TEST_FIELD(action->type, BytesUsed))
+ {
+ /* ----- 8 bit ----- */
+ if( (temp < ((action->extendData >> 8) & 0xFF)) || (temp > ((action->extendData >> 0) & 0xFF)))
+ {
+ temp = action->data;
+
+ WriteData(action, temp);
+ }
+ }
+ else
+ {
+ /* ----- 16 bit (or 24, 32 bit) ----- */
+ if( (temp < ((action->extendData >> 16) & 0xFFFF)) || (temp > ((action->extendData >> 0) & 0xFFFF)))
+ {
+ temp = action->data;
+
+ WriteData(action, temp);
+ }
+ }
+ }
+ break;
+
+ case kOperation_SetOrClearBits:
+ {
+ UINT32 temp;
+
+ temp = ReadData(action);
+
+ if(TEST_FIELD(action->type, OperationParameter))
+ /* ----- clear bit ----- */
+ temp &= ~action->data;
+ else
+ /* ----- set bit ----- */
+ temp |= action->data;
+
+ WriteData(action, temp);
+ }
+ break;
+
+ case kOperation_WriteMatch:
+ {
+ UINT32 temp;
+
+ /* ----- if extend data field is invalid, direct return ----- */
+ if(action->flags & kActionFlag_IgnoreMask)
+ return;
+
+ temp = ReadData(action);
+
+ /* ----- if current value matches appointed value, write ----- */
+ if(temp == action->extendData)
+ {
+ temp = action->data;
+
+ WriteData(action, temp);
+ }
+ }
+ break;
+
+ case kOperation_None:
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*------------------------------------------------------
+ cheat_periodicAction - management for cheat actions
+------------------------------------------------------*/
+
+static void cheat_periodicAction(CheatAction * action)
+{
+ UINT8 parameter = EXTRACT_FIELD(action->type, TypeParameter);
+
+ /* ----- if operation is done in case of one shot, no action ----- */
+ if(action->flags & kActionFlag_OperationDone)
+ return;
+
+ if(TEST_FIELD(action->type, Prefill) && (!(action->flags & kActionFlag_PrefillDone)))
+ {
+ /* ----- pre-fill ----- */
+ UINT32 prefillValue = kPrefillValueTable[EXTRACT_FIELD(action->type, Prefill)];
+
+ if(!(action->flags & kActionFlag_PrefillWritten))
+ {
+ /* ----- set pre-fill value ---- */
+ WriteData(action, prefillValue);
+
+ action->flags |= kActionFlag_PrefillWritten;
+
+ return;
+ }
+ else
+ {
+ /* ----- if value is changed, try to write new value ----- */
+ if(ReadData(action) == prefillValue)
+ return;
+
+ action->flags |= kActionFlag_PrefillDone;
+ }
+ }
+
+ switch(EXTRACT_FIELD(action->type, Type))
+ {
+ case kType_NormalOrDelay:
+ {
+ if(TEST_FIELD(action->type, OneShot) && TEST_FIELD(action->type, RestorePreviousValue) && parameter)
+ {
+ /* ----- keep if one shot + restore prevous value + delay !=0 ----- */
+ cheat_periodicOperation(action);
+
+ if(action->frameTimer >= (parameter * ATTOSECONDS_TO_HZ(Machine->screen[0].refresh)))
+ {
+ action->frameTimer = 0;
+
+ action->flags |= kActionFlag_OperationDone;
+ }
+ else
+ action->frameTimer++;
+ }
+ else
+ {
+ /* ----- otherwise, delay ----- */
+ if(action->frameTimer >= (parameter * ATTOSECONDS_TO_HZ(Machine->screen[0].refresh)))
+ {
+ action->frameTimer = 0;
+
+ cheat_periodicOperation(action);
+
+ if(TEST_FIELD(action->type, OneShot))
+ action->flags |= kActionFlag_OperationDone;
+ }
+ else
+ action->frameTimer++;
+ }
+ }
+ break;
+
+ case kType_WaitForModification:
+ {
+ if(action->flags & kActionFlag_WasModified)
+ {
+ if(action->frameTimer <= 0)
+ {
+ cheat_periodicOperation(action);
+
+ action->flags &= ~kActionFlag_WasModified;
+
+ if(TEST_FIELD(action->type, OneShot))
+ action->flags |= kActionFlag_OperationDone;
+ }
+ else
+ action->frameTimer--;
+
+ action->lastValue = ReadData(action);
+ }
+ else
+ {
+ UINT32 currentValue = ReadData(action);
+
+ if(currentValue != action->lastValue)
+ {
+ action->frameTimer = parameter * ATTOSECONDS_TO_HZ(Machine->screen[0].refresh);
+
+ action->flags |= kActionFlag_WasModified;
+ }
+
+ action->lastValue = currentValue;
+ }
+ }
+ break;
+
+ case kType_IgnoreIfDecrementing:
+ {
+ UINT32 currentValue = ReadData(action);
+
+ /* ### is "NotEqual" correct ? "LessOrEqual" seems to be good... ### */
+ if(currentValue != (action->lastValue - parameter))
+ {
+ cheat_periodicOperation(action);
+
+ if(TEST_FIELD(action->type, OneShot))
+ action->flags |= kActionFlag_OperationDone;
+ }
+
+ action->lastValue = currentValue;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*-----------------------------------------------------
+ cheat_periodicEntry - management for cheat entries
+-----------------------------------------------------*/
+
+static void cheat_periodicEntry(CheatEntry * entry)
+{
+ int i;
+
+ /* ----- special handling for label-selection ----- */
+ if(entry->flags & kCheatFlag_Select)
+ {
+ /* ----- special handling for activation key ----- */
+ if((entry->flags & kCheatFlag_HasActivationKey1) || (entry->flags & kCheatFlag_HasActivationKey2))
+ {
+ if(input_code_pressed(entry->activationKey1) || input_code_pressed(entry->activationKey2))
+ {
+ if(!(entry->flags & kCheatFlag_ActivationKeyPressed))
+ {
+ /* ----- move current position until find OFF or no link extension code ----- */
+ do{
+ /* ----- 1st activation key pressed ----- */
+ if(input_code_pressed(entry->activationKey1))
+ {
+ entry->selection++;
+
+ if(entry->flags & kCheatFlag_OneShot)
+ {
+ if(entry->selection >= entry->actionListLength)
+ {
+ entry->selection = 1;
+
+ if(entry->selection >= entry->actionListLength)
+ entry->selection = 0;
+ }
+
+ if(!TEST_FIELD(entry->actionList[entry->selection].type, LinkExtension))
+ {
+ ActivateCheat(entry);
+
+ entry->flags |= kCheatFlag_DoOneShot;
+ }
+ }
+ else
+ {
+ if(entry->selection >= entry->actionListLength)
+ {
+ entry->selection = 0;
+
+ DeactivateCheat(entry);
+ }
+ else
+ {
+ if(!TEST_FIELD(entry->actionList[entry->selection].type, LinkExtension))
+ ActivateCheat(entry);
+ }
+ }
+ }
+ /* ----- 2nd activation key pressed ----- */
+ else
+ {
+ entry->selection--;
+
+ if(entry->flags & kCheatFlag_OneShot)
+ {
+ if(entry->selection <= 0)
+ entry->selection = entry->actionListLength - 1;
+
+ if(!TEST_FIELD(entry->actionList[entry->selection].type, LinkExtension))
+ {
+ ActivateCheat(entry);
+
+ entry->flags |= kCheatFlag_DoOneShot;
+ }
+ }
+ else
+ {
+ if(!entry->selection)
+ DeactivateCheat(entry);
+ else
+ {
+ if(entry->selection < 0)
+ entry->selection = entry->actionListLength - 1;
+
+ if(!TEST_FIELD(entry->actionList[entry->selection].type, LinkExtension))
+ ActivateCheat(entry);
+ }
+ }
+ }
+ }while(entry->selection && TEST_FIELD(entry->actionList[entry->selection].type, LinkExtension));
+
+ /* ----- display selected label name if needed ----- */
+ if(TEST_FIELD(cheatOptions, ActivationKeyMessage))
+ {
+ if(!entry->selection)
+ ui_popup_time(1,"%s disabled", entry->name);
+ else
+ ui_popup_time(1,"%s : %s selected", entry->name, entry->actionList[entry->selection].optionalName);
+ }
+
+ entry->flags |= kCheatFlag_ActivationKeyPressed; // set flag
+ }
+ }
+ else
+ entry->flags &= ~kCheatFlag_ActivationKeyPressed; // clear flag
+ }
+
+ /* ----- if a subcheat is selected, handle it ----- */
+ if(entry->selection)
+ {
+ i = entry->selection;
+
+ do{
+ if(!(entry->flags & kCheatFlag_OneShot) || (entry->flags & kCheatFlag_DoOneShot))
+ cheat_periodicAction(&entry->actionList[i]);
+
+ i++;
+
+ /* ----- if illegal index, finish ----- */
+ if(i >= entry->actionListLength)
+ break;
+
+ /* ----- if next code has link extension, handle it too ----- */
+ }while(TEST_FIELD(entry->actionList[i].type, LinkExtension));
+ }
+ }
+ else
+ {
+ /* ----- NOTE : activatinon key for value-selection is disabled -----*/
+ if(((entry->flags & kCheatFlag_HasActivationKey1) || (entry->flags & kCheatFlag_HasActivationKey2)) &&
+ !(entry->flags & kCheatFlag_UserSelect))
+ {
+ /* ----- special handling for activation key ----- */
+ if(input_code_pressed(entry->activationKey1) || input_code_pressed(entry->activationKey2))
+ {
+ if(!(entry->flags & kCheatFlag_ActivationKeyPressed))
+ {
+ if(entry->flags & kCheatFlag_OneShot)
+ {
+ ActivateCheat(entry);
+
+ /* ----- display description for one shot if needed ----- */
+ if(TEST_FIELD(cheatOptions, ActivationKeyMessage))
+ ui_popup_time(1,"set %s", entry->name);
+ }
+ else
+ {
+ if(entry->flags & kCheatFlag_Active)
+ {
+ DeactivateCheat(entry);
+
+ /* ----- display description for OFF if needed ----- */
+ if(TEST_FIELD(cheatOptions, ActivationKeyMessage))
+ ui_popup_time(1,"%s disabled", entry->name);
+ }
+ else
+ {
+ ActivateCheat(entry);
+
+ /* ----- display description for ON if needed ----- */
+ if(TEST_FIELD(cheatOptions, ActivationKeyMessage))
+ ui_popup_time(1,"%s enabled", entry->name);
+ }
+ }
+
+ entry->flags |= kCheatFlag_ActivationKeyPressed;
+ }
+ }
+ else
+ entry->flags &= ~kCheatFlag_ActivationKeyPressed;
+ }
+
+ if(!(entry->flags & kCheatFlag_Active))
+ return;
+
+ /* ----- update all actions ----- */
+ for(i = 0; i < entry->actionListLength; i++)
+ cheat_periodicAction(&entry->actionList[i]);
+
+ /* ----- if all actions are done, deactivate the cheat if oneshot entry ----- */
+ {
+ UINT8 done = 1;
+
+ for(i = 0 ; (i < entry->actionListLength && done) ; i++)
+ if(!(entry->actionList[i].flags & kActionFlag_OperationDone))
+ done = 0;
+
+ if(done)
+ DeactivateCheat(entry);
+ }
+ }
+}
+
+/*------------------------------------------------------------------
+ UpdateAllCheatInfo - update all cheat info when database loaded
+------------------------------------------------------------------*/
+
+static void UpdateAllCheatInfo(void)
+{
+ int i;
+
+ for(i = 0; i < cheatListLength; i++)
+ UpdateCheatInfo(&cheatList[i], 1);
+}
+
+/*--------------------------------------------------
+ UpdateCheatInfo - update entry, action and flag
+--------------------------------------------------*/
+
+static void UpdateCheatInfo(CheatEntry * entry, UINT8 isLoadTime)
+{
+ int isOneShot = 1;
+ int isNull = 1;
+ int flags = 0;
+ int i;
+
+ flags = entry->flags & kCheatFlag_PersistentMask;
+
+ /* ---- is it label-selection ? ----- */
+ if( (EXTRACT_FIELD(entry->actionList[0].type, LocationType) == kLocation_Custom) &&
+ (EXTRACT_FIELD(entry->actionList[0].type, LocationParameter) == kCustomLocation_Select))
+ flags |= kCheatFlag_Select;
+
+ for(i = 0; i < entry->actionListLength; i++)
+ {
+ CheatAction * action = &entry->actionList[i];
+
+ int isActionNull = 0;
+ UINT32 size;
+ UINT32 operation;
+ UINT32 actionFlags = action->flags & kActionFlag_PersistentMask;
+
+ size = EXTRACT_FIELD(action->type, BytesUsed);
+
+ operation = EXTRACT_FIELD(action->type, Operation) | EXTRACT_FIELD(action->type, OperationExtend) << 2;
+
+ /* ---- is it comment ? ----- */
+ if( (EXTRACT_FIELD(action->type, LocationType) == kLocation_Custom) &&
+ (EXTRACT_FIELD(action->type, LocationParameter) == kCustomLocation_Comment))
+ isActionNull = 1;
+ else
+ isNull = 0;
+
+ /* ---- is it one shot ? ----- */
+ if(!TEST_FIELD(action->type, OneShot))
+ isOneShot = 0;
+
+ /* ---- is it value-selection ? ----- */
+ if(TEST_FIELD(action->type, UserSelectEnable))
+ flags |= kCheatFlag_UserSelect;
+
+ /* ---- is it relative address ? ----- */
+ if(EXTRACT_FIELD(action->type, LocationType) == kLocation_IndirectIndexed)
+ actionFlags |= kActionFlag_IgnoreMask;
+ else
+ {
+ if(isLoadTime)
+ {
+ /* ----- check for mask == 0 and fix when database loaded ----- */
+ if((operation == kOperation_WriteMask) && (action->extendData == 0))
+ action->extendData = ~0;
+ }
+ }
+
+ action->flags = actionFlags;
+ }
+
+ /* ---- set one shot flag ----- */
+ if(isOneShot)
+ flags |= kCheatFlag_OneShot;
+
+ /* ---- set null flag ----- */
+ if(isNull)
+ flags |= kCheatFlag_Null;
+
+ entry->flags = (flags & kCheatFlag_InfoMask) | (entry->flags & ~kCheatFlag_InfoMask);
+
+ if(isLoadTime)
+ entry->flags &= ~kCheatFlag_Dirty;
+}
+
+/*--------------------------------------------------------------------------------
+ IsAddressInRange - check an address is in range (1 = in range, 0 = out range)
+--------------------------------------------------------------------------------*/
+
+static int IsAddressInRange(CheatAction * action, UINT32 length)
+{
+ UINT8 bytes = EXTRACT_FIELD(action->type, BytesUsed) + 1;
+
+ return ((action->address + bytes) <= length);
+}
+
+/*---------------------------------------------------------------
+ BuildCPUInfoList - get CPU info when initialize cheat system
+---------------------------------------------------------------*/
+
+static void BuildCPUInfoList(void)
+{
+ int i;
+
+ /* ----- do regions ----- */
+ {
+ const rom_entry * traverse = rom_first_region(Machine->gamedrv);
+
+ memset(regionInfoList, 0, sizeof(CPUInfo) * kRegionListLength);
+
+ while(traverse)
+ {
+ if(ROMENTRY_ISREGION(traverse))
+ {
+ UINT8 regionType = ROMREGION_GETTYPE(traverse);
+
+ /* ----- non-cpu region ? ----- */
+ if((regionType >= REGION_GFX1) && (regionType <= REGION_USER8))
+ {
+ CPUInfo * info = &regionInfoList[regionType - REGION_INVALID];
+ UINT32 length = memory_region_length(regionType);
+ int bitState = 0;
+
+ info->type = regionType;
+ info->dataBits = ROMREGION_GETWIDTH(traverse);
+
+ info->addressBits = 0;
+ info->addressMask = length;
+
+ /* ----- build address mask ----- */
+ for(i = 0; i < 32; i++)
+ {
+ UINT32 mask = 1 << (31 - i);
+
+ if(bitState)
+ info->addressMask |= mask;
+ else
+ {
+ if(info->addressMask & mask)
+ {
+ info->addressBits = 32 - i;
+ bitState = 1;
+ }
+ }
+ }
+
+ info->addressCharsNeeded = info->addressBits >> 2;
+
+ if(info->addressBits & 3)
+ info->addressCharsNeeded++;
+
+ info->endianness = ROMREGION_ISBIGENDIAN(traverse);
+ }
+ }
+
+ traverse = rom_next_region(traverse);
+ }
+ }
+
+ /* ----- do CPUs ----- */
+ {
+ memset(cpuInfoList, 0, sizeof(CPUInfo) * MAX_CPU);
+
+ for(i = 0; i < cpu_gettotalcpu(); i++)
+ {
+ CPUInfo * info = &cpuInfoList[i];
+ CPUInfo * regionInfo = &regionInfoList[REGION_CPU1 + i - REGION_INVALID];
+
+ cpu_type type = Machine->drv->cpu[i].type;
+
+ info->type = type;
+ info->dataBits = cputype_databus_width(type, ADDRESS_SPACE_PROGRAM);
+ info->addressBits = cputype_addrbus_width(type, ADDRESS_SPACE_PROGRAM);
+ info->addressMask = 0xFFFFFFFF >> (32 - cputype_addrbus_width(type, ADDRESS_SPACE_PROGRAM));
+
+ info->addressCharsNeeded = info->addressBits >> 2;
+ if(info->addressBits & 0x3)
+ info->addressCharsNeeded++;
+
+ info->endianness = (cputype_endianness(type) == CPU_IS_BE);
+
+ switch(type)
+ {
+#if HAS_TMS34010
+ case CPU_TMS34010:
+ info->addressShift = 3;
+ break;
+#endif
+#if HAS_TMS34020
+ case CPU_TMS34020:
+ info->addressShift = 3;
+ break;
+#endif
+ default:
+ info->addressShift = 0;
+ break;
+ }
+
+ /* ----- copy to region list ----- */
+ memcpy(regionInfo, info, sizeof(CPUInfo));
+ }
+ }
+}
+
diff --git a/src/emu/cheat.h b/src/emu/cheat.h
new file mode 100644
index 00000000000..566742c69f3
--- /dev/null
+++ b/src/emu/cheat.h
@@ -0,0 +1,25 @@
+/*********************************************************************
+
+ cheat.h
+
+ Cheat system.
+
+ Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#pragma once
+
+#ifndef __CHEAT_H__
+#define __CHEAT_H__
+
+#include "mamecore.h"
+
+void cheat_init(running_machine *machine);
+
+int cheat_menu(int selection);
+
+void cheat_display_watches(void);
+
+#endif /* __CHEAT_H__ */
diff --git a/src/emu/clifront.c b/src/emu/clifront.c
new file mode 100644
index 00000000000..ad7c39a74d2
--- /dev/null
+++ b/src/emu/clifront.c
@@ -0,0 +1,977 @@
+/***************************************************************************
+
+ clifront.c
+
+ Command-line interface frontend for MAME.
+
+ Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "driver.h"
+#include "emuopts.h"
+#include "clifront.h"
+#include "hash.h"
+#include "jedparse.h"
+#include "audit.h"
+#include "info.h"
+#include "unzip.h"
+#include "romload.h"
+#include "sound/samples.h"
+
+#include <ctype.h>
+
+#ifdef MESS
+#include "climess.h"
+#endif /* MESS */
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _romident_status romident_status;
+struct _romident_status
+{
+ int total; /* total files processed */
+ int matches; /* number of matches found */
+ int nonroms; /* number of non-ROM files found */
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static int execute_simple_commands(core_options *options, const char *exename);
+static int execute_commands(core_options *options, const char *exename, const game_driver *driver);
+static void display_help(void);
+
+/* informational functions */
+static int info_verifyroms(core_options *options, const char *gamename);
+static int info_verifysamples(core_options *options, const char *gamename);
+static int info_romident(core_options *options, const char *gamename);
+
+/* utilities */
+static void romident(const char *filename, romident_status *status);
+static void identify_file(const char *name, romident_status *status);
+static void identify_data(const char *name, const UINT8 *data, int length, romident_status *status);
+static void match_roms(const char *hash, int length, int *found);
+
+
+
+/***************************************************************************
+ COMMAND-LINE OPTIONS
+***************************************************************************/
+
+const options_entry cli_options[] =
+{
+ /* core commands */
+ { NULL, NULL, OPTION_HEADER, "CORE COMMANDS" },
+ { "help;h;?", "0", OPTION_COMMAND, "show help message" },
+ { "validate;valid", "0", OPTION_COMMAND, "perform driver validation on all game drivers" },
+
+ /* configuration commands */
+ { NULL, NULL, OPTION_HEADER, "CONFIGURATION COMMANDS" },
+ { "createconfig;cc", "0", OPTION_COMMAND, "create the default configuration file" },
+ { "showconfig;sc", "0", OPTION_COMMAND, "display running parameters" },
+ { "showusage;su", "0", OPTION_COMMAND, "show this help" },
+
+ /* frontend commands */
+ { NULL, NULL, OPTION_HEADER, "FRONTEND COMMANDS" },
+ { "listxml;lx", "0", OPTION_COMMAND, "all available info on driver in XML format" },
+ { "listfull;ll", "0", OPTION_COMMAND, "short name, full name" },
+ { "listsource;ls", "0", OPTION_COMMAND, "driver sourcefile" },
+ { "listclones;lc", "0", OPTION_COMMAND, "show clones" },
+ { "listcrc", "0", OPTION_COMMAND, "CRC-32s" },
+ { "listroms", "0", OPTION_COMMAND, "list required roms for a driver" },
+ { "listsamples", "0", OPTION_COMMAND, "list optional samples for a driver" },
+ { "verifyroms", "0", OPTION_COMMAND, "report romsets that have problems" },
+ { "verifysamples", "0", OPTION_COMMAND, "report samplesets that have problems" },
+ { "romident", "0", OPTION_COMMAND, "compare files with known MAME roms" },
+#ifdef MESS
+ { "listdevices", "0", OPTION_COMMAND, "list available devices" },
+#endif
+
+ { NULL }
+};
+
+
+
+/***************************************************************************
+ CORE IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ cli_execute - execute a game via the standard
+ command line interface
+-------------------------------------------------*/
+
+int cli_execute(int argc, char **argv, const options_entry *osd_options)
+{
+ core_options *options;
+ astring *gamename = astring_alloc();
+ astring *exename = astring_alloc();
+ const game_driver *driver;
+ int result;
+
+ /* initialize the options manager and add the CLI-specific options */
+ options = mame_options_init(osd_options);
+ options_add_entries(options, cli_options);
+
+ /* parse the command line first; if we fail here, we're screwed */
+ if (options_parse_command_line(options, argc, argv, OPTION_PRIORITY_CMDLINE))
+ {
+ result = MAMERR_INVALID_CONFIG;
+ goto error;
+ }
+
+ /* parse the simple commmands before we go any further */
+ core_filename_extract_base(exename, argv[0], TRUE);
+ result = execute_simple_commands(options, astring_c(exename));
+ if (result != -1)
+ goto error;
+
+ /* find out what game we might be referring to */
+ core_filename_extract_base(gamename, options_get_string(options, OPTION_GAMENAME), TRUE);
+ driver = driver_get_name(astring_c(gamename));
+
+ /* execute any commands specified */
+ result = execute_commands(options, astring_c(exename), driver);
+ if (result != -1)
+ goto error;
+
+ /* if we don't have a valid driver selected, offer some suggestions */
+ if (astring_len(gamename) > 0 && driver == NULL)
+ {
+ const game_driver *matches[10];
+ int drvnum;
+
+ /* get the top 10 approximate matches */
+ driver_list_get_approx_matches(drivers, astring_c(gamename), ARRAY_LENGTH(matches), matches);
+
+ /* print them out */
+ fprintf(stderr, "\n\"%s\" approximately matches the following\n"
+ "supported " GAMESNOUN " (best match first):\n\n", astring_c(gamename));
+ for (drvnum = 0; drvnum < ARRAY_LENGTH(matches); drvnum++)
+ if (matches[drvnum] != NULL)
+ fprintf(stderr, "%-10s%s\n", matches[drvnum]->name, matches[drvnum]->description);
+
+ /* exit with an error */
+ result = MAMERR_NO_SUCH_GAME;
+ goto error;
+ }
+
+ /* run the game */
+ result = mame_execute(options);
+
+error:
+ /* free our options and exit */
+ options_free(options);
+ astring_free(gamename);
+ astring_free(exename);
+ return result;
+}
+
+
+/*-------------------------------------------------
+ help_output - output callback for printing
+ requested help information
+-------------------------------------------------*/
+
+static void help_output(const char *s)
+{
+ mame_printf_info("%s", s);
+}
+
+
+/*-------------------------------------------------
+ execute_simple_commands - execute basic
+ commands that don't require any context
+-------------------------------------------------*/
+
+static int execute_simple_commands(core_options *options, const char *exename)
+{
+ /* help? */
+ if (options_get_bool(options, CLIOPTION_HELP))
+ {
+ display_help();
+ return MAMERR_NONE;
+ }
+
+ /* showusage? */
+ if (options_get_bool(options, CLIOPTION_SHOWUSAGE))
+ {
+ mame_printf_info("Usage: %s [%s] [options]\n\nOptions:\n", exename, GAMENOUN);
+ options_output_help(options, help_output);
+ return MAMERR_NONE;
+ }
+
+ /* validate? */
+ if (options_get_bool(options, CLIOPTION_VALIDATE))
+ {
+ extern int mame_validitychecks(const game_driver *driver);
+ return mame_validitychecks(NULL);
+ }
+
+ return -1;
+}
+
+
+/*-------------------------------------------------
+ execute_commands - execute various frontend
+ commands
+-------------------------------------------------*/
+
+static int execute_commands(core_options *options, const char *exename, const game_driver *driver)
+{
+ static const struct
+ {
+ const char *option;
+ int (*function)(core_options *options, const char *gamename);
+ } info_commands[] =
+ {
+ { CLIOPTION_LISTXML, cli_info_listxml },
+ { CLIOPTION_LISTFULL, cli_info_listfull },
+ { CLIOPTION_LISTSOURCE, cli_info_listsource },
+ { CLIOPTION_LISTCLONES, cli_info_listclones },
+ { CLIOPTION_LISTCRC, cli_info_listcrc },
+#ifdef MESS
+ { CLIOPTION_LISTDEVICES, info_listdevices },
+#endif
+ { CLIOPTION_LISTROMS, cli_info_listroms },
+ { CLIOPTION_LISTSAMPLES, cli_info_listsamples },
+ { CLIOPTION_VERIFYROMS, info_verifyroms },
+ { CLIOPTION_VERIFYSAMPLES, info_verifysamples },
+ { CLIOPTION_ROMIDENT, info_romident }
+ };
+ int i;
+
+ /* createconfig? */
+ if (options_get_bool(options, CLIOPTION_CREATECONFIG))
+ {
+ file_error filerr;
+ mame_file *file;
+
+ /* parse any relevant INI files before proceeding */
+ mame_parse_ini_files(options, driver);
+
+ /* make the output filename */
+ filerr = mame_fopen_options(options, NULL, CONFIGNAME ".ini", OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, &file);
+
+ /* error if unable to create the file */
+ if (filerr != FILERR_NONE)
+ {
+ fprintf(stderr, "Unable to create file " CONFIGNAME ".ini\n");
+ return MAMERR_FATALERROR;
+ }
+
+ /* output the configuration and exit cleanly */
+ options_output_ini_file(options, mame_core_file(file));
+ mame_fclose(file);
+ return MAMERR_NONE;
+ }
+
+ /* showconfig? */
+ if (options_get_bool(options, CLIOPTION_SHOWCONFIG))
+ {
+ /* parse any relevant INI files before proceeding */
+ mame_parse_ini_files(options, driver);
+ options_output_ini_stdfile(options, stdout);
+ return MAMERR_NONE;
+ }
+
+ /* informational commands? */
+ for (i = 0; i < ARRAY_LENGTH(info_commands); i++)
+ if (options_get_bool(options, info_commands[i].option))
+ {
+ const char *gamename = options_get_string(options, OPTION_GAMENAME);
+
+ /* parse any relevant INI files before proceeding */
+ mame_parse_ini_files(options, driver);
+ return (*info_commands[i].function)(options, (gamename[0] == 0) ? "*" : gamename);
+ }
+
+ return -1;
+}
+
+
+/*-------------------------------------------------
+ display_help - display help to standard
+ output
+-------------------------------------------------*/
+
+static void display_help(void)
+{
+#ifndef MESS
+ mame_printf_info("M.A.M.E. v%s - Multiple Arcade Machine Emulator\n"
+ "Copyright (C) 1997-2007 by Nicola Salmoria and the MAME Team\n\n", build_version);
+ mame_printf_info("%s\n", mame_disclaimer);
+ mame_printf_info("Usage: MAME gamename [options]\n\n"
+ " MAME -showusage for a brief list of options\n"
+ " MAME -showconfig for a list of configuration optio